feat(self-operated): add charts and continuous collection status

This commit is contained in:
2026-10-13 20:44:31 +08:00
parent 698ca34529
commit 4c4a3db1eb
33 changed files with 780 additions and 211 deletions
@@ -0,0 +1,39 @@
vi.mock('@/shared/components/AppDialog.vue', () => ({ default: { props: ['modelValue'], template: '<section v-if="modelValue"><slot /></section>' } }))
import { mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
import { defineComponent } from 'vue'
vi.mock('vue-echarts', () => ({ default: defineComponent({ name: 'VChart', props: ['option', 'autoresize', 'initOptions'], template: '<div />' }) }))
import SkuTrend from './SkuTrend.vue'
import type { DailyResponse } from '../types'
function data(status = 'COMPLETE'): DailyResponse {
return {
context: { salesRunId: null, inventoryRunId: null, salesScopeHash: null, inventoryScopeHash: null, queryAsOf: '', queryExpiresAt: '', businessTimezone: 'Asia/Shanghai', anchorDate: '2026-10-13' },
summary: { sourceAccount: 'test', customerCode: 'OWNER', warehouseCode: 'WH', sku: 'SKU', productName: null, quantityUnit: 'PCS', outboundQuantity: '30', observedQuantity: '30', dataStatus: status, reasonCodes: [], completeDayCount: 30, partialDayCount: 0, unknownDayCount: 0 },
points: Array.from({ length: 30 }, (_, index) => ({ businessDate: `2026-09-${String(index + 1).padStart(2, '0')}`, outboundQuantity: status === 'UNKNOWN' ? null : '1', observedQuantity: status === 'UNKNOWN' ? null : '1', dataStatus: status, quantityUnit: 'PCS', reasonCodes: [] })),
}
}
describe('SKU daily trend axes', () => {
it('shows both axes, intermediate dates, zero and maximum ticks for a 30-day window', () => {
const w = mount(SkuTrend, { props: { data: data() } })
const chart = w.findComponent({ name: 'VChart' })
const option = chart.props('option')
expect(option.xAxis).toMatchObject({ type: 'category', name: '日期(北京时间)' })
expect(option.xAxis.data).toHaveLength(30)
expect(option.yAxis).toMatchObject({ type: 'value', min: 0, name: '出库量(件)' })
expect(option.series[1].data).toEqual(Array(30).fill(1))
expect(option.tooltip.trigger).toBe('axis')
expect(chart.props('initOptions')).toEqual({ renderer: 'canvas' })
expect(w.find('svg').exists()).toBe(false)
w.unmount()
})
it('retains axes and date markers for an unknown window without drawing zero points', () => {
const w = mount(SkuTrend, { props: { data: data('UNKNOWN') } })
expect(w.text()).toContain('未知日期不作为零销量')
const option = w.findComponent({ name: 'VChart' }).props('option')
expect(option.series[0].data.every((point: { value: number | null }) => point.value === null)).toBe(true)
expect(option.series).toHaveLength(1)
expect(option.xAxis.data).toHaveLength(30)
w.unmount()
})
})