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

40 lines
3.2 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 { DailyResponse } from '../types'
import { label, quantityText, shownQuantity, trendSegments, reasonsText } 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.sku }} · 每日出库趋势</h3>
<p>所属货主:{{ data.summary.customerCode || '—' }} · {{ data.summary.productName || '—' }}</p>
<p>{{ data.summary.dataStatus === 'COMPLETE' ? '完整出库量' : '已采集出库量' }}:{{ quantityText(shownQuantity(data.summary)) }} {{ data.summary.quantityUnit === 'PCS' ? '件' : '单位未知' }};{{ 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 }} 件</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 === 'PCS' ? '件' : '单位未知' }},{{ 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>{{ reasonsText(point.reasonCodes) }}</td></tr>
</tbody></table>
</details>
</section>
</template>
<style scoped>
.sku-trend { width: 100%; max-height: 280px; }
text { font-size: var(--admin-font-caption); }
</style>