<template>
|
<div class="stats">
|
<div v-for="(item, i) in cards" :key="item.key" class="app-panel stat-card">
|
<div class="stat-card__icon" :class="`is-${item.tone}`">
|
<el-icon :size="18"><component :is="item.icon" /></el-icon>
|
</div>
|
<div class="stat-card__main">
|
<div class="stat-card__label">{{ item.label }}</div>
|
<div class="stat-card__value app-num">{{ formatted[i] }}<span class="stat-card__unit">{{ item.unit }}</span></div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { computed } from 'vue'
|
import {
|
Money, DocumentCopy, ShoppingCart, CreditCard, Box, Van
|
} from '@element-plus/icons-vue'
|
import { useCountUp, formatNum } from '../useCountUp'
|
|
const props = defineProps({
|
business: { type: Object, default: () => ({}) }
|
})
|
|
const cards = [
|
{ key: 'monthSaleMoney', label: '本月销售额', unit: '元', icon: Money, tone: 'primary' },
|
{ key: 'monthSaleHaveMoney', label: '未开票金额', unit: '元', icon: DocumentCopy, tone: 'warning' },
|
{ key: 'monthPurchaseMoney', label: '本月采购额', unit: '元', icon: ShoppingCart, tone: 'info' },
|
{ key: 'monthPurchaseHaveMoney', label: '待付款金额', unit: '元', icon: CreditCard, tone: 'danger' },
|
{ key: 'inventoryNum', label: '当前库存总量', unit: '件', icon: Box, tone: 'success' },
|
{ key: 'todayInventoryNum', label: '今日入库', unit: '件', icon: Van, tone: 'primary' }
|
]
|
|
const sources = cards.map((c) => computed(() => Number(props.business[c.key]) || 0))
|
const values = sources.map((s) => useCountUp(s))
|
const formatted = computed(() => values.map((v) => formatNum(v.value)))
|
</script>
|
|
<style scoped>
|
.stats {
|
display: grid;
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
gap: var(--app-gap);
|
}
|
|
.stat-card {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
padding: 16px;
|
min-width: 0;
|
transition: box-shadow var(--app-transition), transform var(--app-transition);
|
}
|
|
.stat-card:hover {
|
box-shadow: var(--app-shadow-md);
|
transform: translateY(-1px);
|
}
|
|
.stat-card__icon {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 40px;
|
height: 40px;
|
flex-shrink: 0;
|
border-radius: var(--app-radius-sm);
|
}
|
|
.stat-card__icon.is-primary { background: var(--app-primary-soft); color: var(--app-primary); }
|
.stat-card__icon.is-success { background: var(--app-success-soft); color: var(--app-success); }
|
.stat-card__icon.is-warning { background: var(--app-warning-soft); color: var(--app-warning); }
|
.stat-card__icon.is-danger { background: var(--app-danger-soft); color: var(--app-danger); }
|
.stat-card__icon.is-info { background: var(--app-info-soft); color: var(--app-info); }
|
|
.stat-card__main {
|
min-width: 0;
|
}
|
|
.stat-card__label {
|
font-size: 12px;
|
color: var(--app-text-tertiary);
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
|
.stat-card__value {
|
margin-top: 4px;
|
font-size: 20px;
|
font-weight: 600;
|
color: var(--app-text);
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
|
.stat-card__unit {
|
margin-left: 4px;
|
font-size: 12px;
|
font-weight: 400;
|
color: var(--app-text-tertiary);
|
}
|
|
@media (max-width: 1440px) {
|
.stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
}
|
|
@media (max-width: 768px) {
|
.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
}
|
</style>
|