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

31 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>