feat(self-operated): add charts and continuous collection status
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user