Files
admin-web/src/modules/self-operated/components/OwnerOverviewPanel.vue
T

31 lines
3.9 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import type { OwnerOverview, QuantityTotal, RiskShare } from '../types'
import { beijingTime, label, quantityText, reasonsText } from '../state'
defineProps<{ data: OwnerOverview }>()
const metrics: { key: keyof Pick<OwnerOverview, 'physicalSkuCount' | 'physicalQuantity' | 'availableQuantity' | 'frozenQuantity' | 'defectivePhysicalQuantity' | 'transitQuantity' | 'outboundQuantity30d' | 'averageDailyOutboundQuantity'>; name: string }[] = [
{ key: 'physicalSkuCount', name: '有实物库存 SKU 数' }, { key: 'physicalQuantity', name: '全品质实物件数' },
{ key: 'availableQuantity', name: '正品可售件数' }, { key: 'frozenQuantity', name: '全品质冻结件数' },
{ key: 'defectivePhysicalQuantity', name: '次品实物件数' }, { key: 'transitQuantity', name: '在途件数' },
{ key: 'outboundQuantity30d', name: '近30天出库件数' }, { key: 'averageDailyOutboundQuantity', name: '30天日均出库' },
]
const risks: { key: 'noOutbound30d' | 'coverageAboveThreshold'; name: string }[] = [{ key: 'noOutbound30d', name: '近30天无出库' }, { key: 'coverageAboveThreshold', name: '可售天数超过本次阈值' }]
function totalText(metric: QuantityTotal) { return `${quantityText(metric.overallTotal)} · ${label(metric.dataStatus)}` }
function ratioText(risk: RiskShare) { return risk.physicalQuantityRatio == null ? '—' : `${(Number(risk.physicalQuantityRatio) * 100).toFixed(2)}%` }
</script>
<template>
<section aria-label="货主经营概览">
<h3>货主 {{ data.customerCode }} {{ data.customerName ?? '' }} · 经营概览</h3>
<p>固定所选货主全量范围,不受下方 SKU、关注筛选或分页影响。SKU 候选数 {{ quantityText(data.skuCount) }}。实物件数不是空间占比,不自动评级。</p>
<p>近30完整日计算区间 {{ data.context.rangeStartDate ?? '—' }} 至 {{ data.context.rangeEndDateExclusive ?? '—' }}(结束边界不含);销量质量:{{ label(data.context.salesStatus) }};库存质量:{{ label(data.context.inventoryStatus) }}。库存观测时段:{{ beijingTime(data.context.inventoryObservedFrom) }} 至 {{ beijingTime(data.context.inventoryObservedUntil) }}。</p>
<table class="density-table">
<thead><tr><th>指标</th><th>正式总量 / 质量</th><th>已知有效小计(部分资料)</th><th>未知 SKU 数</th><th>依据</th></tr></thead>
<tbody><tr v-for="metric in metrics" :key="metric.key"><th>{{ metric.name }}</th><td>{{ totalText(data[metric.key]) }}</td><td>{{ quantityText(data[metric.key].knownSubtotal) }}</td><td>{{ quantityText(data[metric.key].unknownSkuCount) }}</td><td>{{ reasonsText(data[metric.key].reasonCodes) }}</td></tr></tbody>
</table>
<table class="density-table">
<thead><tr><th>关注</th><th>命中 SKU 数 / 实物件数</th><th>占货主实物件数比例</th><th>已确认命中小计</th><th>待判断 SKU / 已知实物件数</th><th>依据</th></tr></thead>
<tbody><tr v-for="risk in risks" :key="risk.key"><th>{{ risk.name }}</th><td>{{ quantityText(data[risk.key].matchedSkuCount) }} / {{ quantityText(data[risk.key].matchedPhysicalQuantity) }}</td><td>{{ ratioText(data[risk.key]) }}</td><td>{{ quantityText(data[risk.key].knownMatchedSkuCount) }} SKU / {{ quantityText(data[risk.key].knownMatchedPhysicalQuantity) }} PCS</td><td>{{ quantityText(data[risk.key].unassessableSkuCount) }} / {{ quantityText(data[risk.key].unassessableKnownPhysicalQuantity) }}</td><td>{{ reasonsText(data[risk.key].reasonCodes) }}</td></tr></tbody>
</table>
<p>占比的分母为本货主全品质实物正式总量 {{ quantityText(data.physicalQuantity.overallTotal) }} PCS({{ label(data.physicalQuantity.dataStatus) }})。冻结及次品均已包含在实物中,在途不计当前占仓。{{ Number(data.physicalQuantity.overallTotal) === 0 && data.physicalQuantity.overallTotal !== null ? '本货主无实物库存,占比不适用。' : '' }}</p>
</section>
</template>