2026-05-17 14:27:13 +08:00

100 lines
1.8 KiB
Vue

<script lang="ts" setup>
import { onBeforeUnmount, onMounted, reactive } from 'vue';
import { purchaseTodayTotal } from '#/api/legacy/operate';
defineOptions({ name: 'StatisticsDatavPurchaseCount' });
const props = withDefaults(
defineProps<{
timeOutSecond?: number;
}>(),
{
timeOutSecond: 60,
},
);
const summary = reactive({
total: 0,
});
let refreshTimer: number | undefined;
function normalizeNumber(value: any) {
const amount = Number(value || 0);
return Number.isFinite(amount) ? amount : 0;
}
function formatValue(value: number) {
return value.toLocaleString('zh-CN', {
maximumFractionDigits: 2,
});
}
async function loadData() {
try {
summary.total = normalizeNumber(await purchaseTodayTotal());
} catch {
summary.total = 0;
}
}
onMounted(() => {
void loadData();
refreshTimer = window.setInterval(() => {
void loadData();
}, props.timeOutSecond * 1000);
});
onBeforeUnmount(() => {
if (refreshTimer) {
window.clearInterval(refreshTimer);
}
});
</script>
<template>
<div class="stat-grid">
<div class="stat-card">
<div class="stat-card__label">总额</div>
<div class="stat-card__value">{{ formatValue(summary.total) }}</div>
</div>
</div>
</template>
<style scoped>
.stat-grid {
display: grid;
gap: 16px;
grid-template-columns: minmax(0, 1fr);
}
.stat-card {
background: rgba(40, 49, 99, 0.62);
border: 1px solid rgba(79, 189, 255, 0.16);
border-radius: 16px;
min-height: 124px;
padding: 22px 20px;
}
.stat-card__label {
color: rgba(210, 223, 246, 0.72);
font-size: 14px;
margin-bottom: 14px;
}
.stat-card__value {
color: #f8fbff;
font-size: clamp(24px, 4vw, 38px);
font-weight: 700;
line-height: 1.15;
word-break: break-all;
}
@media (max-width: 640px) {
.stat-grid {
grid-template-columns: 1fr;
}
}
</style>