49 lines
3.2 KiB
TypeScript
49 lines
3.2 KiB
TypeScript
import type { EChartsOption, LineSeriesOption } from 'echarts'
|
|
import type { DailyPoint } from './types'
|
|
import { label, quantityText, reasonsText, shownQuantity } from './state'
|
|
|
|
export function skuTrendOption(points: DailyPoint[]): EChartsOption {
|
|
const dates = points.map(point => point.businessDate)
|
|
const values = points.map(point => {
|
|
const value = shownQuantity(point)
|
|
return point.dataStatus !== 'UNKNOWN' && value != null && Number.isFinite(Number(value)) ? Number(value) : null
|
|
})
|
|
const series: LineSeriesOption[] = [{
|
|
name: '每日出库量', type: 'line', connectNulls: false, lineStyle: { opacity: 0 },
|
|
symbolSize: 8, showAllSymbol: true,
|
|
data: values.map((value, index) => ({ value, symbol: points[index]?.dataStatus === 'COMPLETE' ? 'circle' : 'emptyCircle' })),
|
|
itemStyle: { color: '#6078ea' }, emphasis: { scale: 1.5 },
|
|
}]
|
|
let segment: { partial: boolean; data: (number | null)[] } | null = null
|
|
for (let index = 1; index < points.length; index++) {
|
|
if (values[index - 1] == null || values[index] == null || Date.parse(dates[index]!) - Date.parse(dates[index - 1]!) !== 86400000) { segment = null; continue }
|
|
const partial = points[index - 1]!.dataStatus !== 'COMPLETE' || points[index]!.dataStatus !== 'COMPLETE'
|
|
if (!segment || segment.partial !== partial) {
|
|
segment = { partial, data: Array<number | null>(points.length).fill(null) }
|
|
series.push({ type: 'line', data: segment.data, symbol: 'none', silent: true, connectNulls: false,
|
|
tooltip: { show: false }, lineStyle: { color: '#6078ea', width: 3, type: partial ? 'dashed' : 'solid' },
|
|
emphasis: { disabled: true }, animation: false })
|
|
}
|
|
segment.data[index - 1] = values[index - 1]!
|
|
segment.data[index] = values[index]!
|
|
}
|
|
return {
|
|
animation: false,
|
|
grid: { left: 24, right: 32, top: 42, bottom: 80, containLabel: true },
|
|
xAxis: { type: 'category', data: dates, name: '日期(北京时间)', nameLocation: 'middle', nameGap: 30,
|
|
boundaryGap: false, axisLine: { show: true }, axisTick: { show: true },
|
|
axisLabel: { hideOverlap: true, showMinLabel: true, showMaxLabel: true, formatter: (value: string) => value.slice(5) } },
|
|
yAxis: { type: 'value', name: '出库量(件)', min: 0, axisLine: { show: true }, axisTick: { show: true }, splitLine: { show: true, lineStyle: { type: 'dashed', color: '#e5eaf3' } } },
|
|
tooltip: { trigger: 'axis', renderMode: 'richText', confine: true, axisPointer: { type: 'line' },
|
|
formatter: params => {
|
|
const entries = Array.isArray(params) ? params : [params]
|
|
const item = entries.find(entry => entry.seriesIndex === 0) ?? entries[0]
|
|
const point = item ? points[item.dataIndex] : undefined
|
|
return point ? `${point.businessDate}\n出库量:${quantityText(shownQuantity(point))} 件\n${label(point.dataStatus)}\n覆盖截止:${point.coveredUntil ?? '未知'}\n${reasonsText(point.reasonCodes)}` : ''
|
|
} },
|
|
dataZoom: [{ type: 'slider', bottom: 4, height: 20, start: 0, end: 100, filterMode: 'none' }],
|
|
aria: { enabled: true, description: 'SKU每日出库趋势。横轴为北京时间日期,纵轴为出库件数。完整日实线,未完整日虚线,缺失日期断线。详细数值可展开下方表格。' },
|
|
series,
|
|
}
|
|
}
|