feat: add platform self-operated sales inventory and collection views

This commit is contained in:
2026-10-12 20:33:39 +08:00
parent cc4856ceac
commit 533273769d
23 changed files with 1395 additions and 4 deletions
@@ -0,0 +1,38 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { DailyResponse } from '../types'
import { label, quantityText, shownQuantity, trendSegments } from '../state'
const props = defineProps<{ data: DailyResponse }>()
const segments = computed(() => trendSegments(props.data.points))
const maximum = computed(() => Math.max(1, ...props.data.points.map(point => Number(shownQuantity(point) ?? 0))))
function x(index: number) { return props.data.points.length === 1 ? 400 : 30 + index / (props.data.points.length - 1) * 740 }
function y(value: string | number | null) { return 175 - Number(value ?? 0) / maximum.value * 145 }
</script>
<template>
<section aria-label="SKU每日出库趋势">
<h3>{{ data.summary.customerCode }} · {{ data.summary.sku }} · 每日出库趋势</h3>
<p>{{ data.summary.dataStatus === 'COMPLETE' ? '完整出库量' : '该版本已采集出库量' }}:{{ quantityText(shownQuantity(data.summary)) }} {{ data.summary.quantityUnit ?? '单位未知' }};{{ label(data.summary.dataStatus) }}。今日为已采集累计,非实时值。</p>
<p v-if="!segments.length">所选范围尚无可靠数据,未知日期不作为零销量。</p>
<svg v-else viewBox="0 0 800 220" role="img" aria-label="每日出库件数;虚线点表示未完整,缺失日期断线" class="sku-trend">
<line x1="30" y1="175" x2="770" y2="175" stroke="currentColor" />
<text x="30" y="20">{{ maximum }} PCS</text>
<path v-for="(segment, index) in segments" :key="index" :d="segment.path" fill="none" stroke="var(--el-color-primary)" stroke-width="2" :stroke-dasharray="segment.partial ? '5 4' : undefined" />
<g v-for="(point, index) in data.points" :key="point.businessDate">
<circle v-if="shownQuantity(point) != null && point.dataStatus !== 'UNKNOWN'" :cx="x(index)" :cy="y(shownQuantity(point))" r="4" :fill="point.dataStatus === 'COMPLETE' ? 'var(--el-color-primary)' : 'white'" stroke="var(--el-color-primary)">
<title>{{ point.businessDate }}:{{ quantityText(shownQuantity(point)) }} {{ point.quantityUnit ?? '单位未知' }},{{ label(point.dataStatus) }};覆盖截止 {{ point.coveredUntil ?? '未知' }}</title>
</circle>
<text v-if="data.points.length <= 15 || index === 0 || index === data.points.length - 1" :x="x(index)" y="205" text-anchor="middle">{{ point.businessDate.slice(5) }}</text>
</g>
</svg>
<details>
<summary>每日数量、完整性及覆盖证据</summary>
<table class="density-table"><thead><tr><th>北京时间日期</th><th>完整出库量</th><th>已采集量</th><th>状态</th><th>覆盖截止</th><th>缺口原因</th></tr></thead><tbody>
<tr v-for="point in data.points" :key="point.businessDate"><td>{{ point.businessDate }}</td><td>{{ quantityText(point.outboundQuantity) }}</td><td>{{ quantityText(point.observedQuantity) }}</td><td>{{ label(point.dataStatus) }}</td><td>{{ point.coveredUntil ?? '—' }}</td><td>{{ point.reasonCodes.join('、') || '—' }}</td></tr>
</tbody></table>
</details>
</section>
</template>
<style scoped>
.sku-trend { width: 100%; max-height: 280px; }
text { font-size: var(--admin-font-caption); }
</style>