Files
admin-web/src/modules/self-operated/components/InventoryRankingDiagnostics.vue
T
2026-10-14 11:02:56 +08:00

50 lines
4.5 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 { computed } from 'vue'
import type { Dashboard } from '../types'
import { beijingTime, label, quantityText, reasonsText } from '../state'
const props = defineProps<{ data: Dashboard; warehouse: string; historical: boolean }>()
const explanations: Record<string, string> = {
PHYSICAL_INVENTORY_UNKNOWN: '实物库存缺失、异常或已过期,需核对库存采集结果。',
AVAILABLE_INVENTORY_UNKNOWN: '正品可售库存缺失、异常或已过期,暂不能计算消化天数。',
UNIT_UNKNOWN_OR_CONFLICT: '销量或库存的数量单位未确认或不一致。',
SALES_WINDOW_UNAVAILABLE: '所选区间的完整销量不可用,需核对覆盖范围、销量状态与修订核对结果。',
OBSERVATION_INSUFFICIENT: '缺少统计窗口起点及以前的本仓有效出库或库存观察依据;仅补齐窗口内销量不一定满足此条件。',
METRIC_DEPENDENCY_UNKNOWN: '计算所需资料仍有未知项,需进入库存分析核对具体SKU。',
}
const causes = computed(() => Object.entries(props.data.coverageDistribution.unknownReasons)
.filter(([, count]) => count == null || !Number.isFinite(Number(count)) || Number(count) > 0))
</script>
<template>
<div class="inventory-ranking-diagnostics">
<p><strong>{{ warehouse || '—' }}</strong> · 查询时间 {{ beijingTime(data.context.queryAsOf) }}(北京时间)</p>
<p v-if="historical" role="status">当前为历史查询结果,请整体刷新后再核对最新采集覆盖。</p>
<table class="density-table">
<tbody>
<tr><th scope="row">榜单要求的销量区间</th><td>{{ data.longCoverageSkus.windowStartDate }} 至 {{ data.longCoverageSkus.windowEndDateExclusive }}(截止日不含)</td></tr>
<tr><th scope="row">已发布销量覆盖</th><td>{{ beijingTime(data.context.salesCoveredFrom) }} 至 {{ beijingTime(data.context.salesCoveredUntil) }}(截止时刻不含)</td></tr>
<tr><th scope="row">完整日覆盖</th><td v-if="data.context.completeDayFrom && data.context.completeDayUntil">{{ data.context.completeDayFrom }} 至 {{ data.context.completeDayUntil }}(截止日不含)</td><td v-else>尚无可确认的完整日覆盖范围</td></tr>
<tr><th scope="row">销量状态</th><td>{{ label(data.context.salesStatus) }};所选时段日均:{{ label(data.kpis.averageDailyOutboundQuantity.dataStatus) }} · {{ reasonsText(data.kpis.averageDailyOutboundQuantity.reasonCodes) }}</td></tr>
<tr><th scope="row">库存采集时间</th><td>{{ beijingTime(data.context.inventoryObservedFrom) }} 至 {{ beijingTime(data.context.inventoryObservedUntil) }}</td></tr>
<tr><th scope="row">库存状态/有效期</th><td>{{ label(data.context.inventoryStatus) }};有效至 {{ beijingTime(data.context.inventoryFreshUntil) }}</td></tr>
<tr><th scope="row">本次查询提示</th><td>{{ reasonsText(data.context.reasonCodes) }}</td></tr>
<tr><th scope="row">预计消化时间最长</th><td>符合条件 {{ quantityText(data.longCoverageSkus.eligibleCount) }} SKU;待评估 {{ quantityText(data.longCoverageSkus.unassessableCount) }} SKU</td></tr>
<tr><th scope="row">所选时段无出库库存</th><td>符合条件 {{ quantityText(data.noOutboundSkus.eligibleCount) }} SKU;待评估 {{ quantityText(data.noOutboundSkus.unassessableCount) }} SKU</td></tr>
</tbody>
</table>
<h4>全仓库存分布的待核验原因</h4>
<p>以下为全仓库存分布的原因计数,不是两个榜单各自的排除明细。每个SKU仅列首个命中的原因,补齐后仍可能有其他条件待满足。</p>
<table v-if="causes.length" class="density-table">
<thead><tr><th scope="col">原因</th><th scope="col">SKU数</th><th scope="col">需要核对的数据</th></tr></thead>
<tbody><tr v-for="[reason, count] in causes" :key="reason"><td>{{ reasonsText([reason]) }}</td><td>{{ quantityText(count) }}</td><td>{{ explanations[reason] || '接口未提供更细说明,请核对库存分析中的SKU资料。' }}</td></tr></tbody>
</table>
<p v-else>本次查询未列出非零的具体原因计数,不能据此认定资料全部齐备。</p>
<p>消化榜还要求正可售库存且日均出库大于零;无出库榜要求正实物库存且完整窗口出库为零。两榜均需满足本仓观察资格;未知销量不能按零处理。</p>
</div>
</template>
<style scoped>
table { width: 100%; }
th, td { text-align: left; overflow-wrap: anywhere; }
tbody th { width: 180px; }
</style>