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
+2 -11
View File
@@ -1,6 +1,6 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { RequestFence, RetryIntent, RuntimePoller, contextParams, progressText, sameContext, shownQuantity, taskRetryAllowed, trendSegments, validateCustomRange } from './state'
import type { DailyPoint, QueryContext, Task } from './types'
import { RequestFence, RetryIntent, RuntimePoller, contextParams, progressText, sameContext, shownQuantity, taskRetryAllowed, validateCustomRange } from './state'
import type { QueryContext, Task } from './types'
const context: QueryContext = { salesRunId: '9007199254740999', inventoryRunId: null, salesScopeHash: 'sales', inventoryScopeHash: null, queryAsOf: '2026-10-12T15:00:00+08:00', queryExpiresAt: '2026-10-12T15:30:00+08:00', businessTimezone: 'Asia/Shanghai', anchorDate: '2026-10-12' }
const task: Task = { taskNo: 'COL-TEST-001', warehouseCode: 'WH-A', taskType: 'BACKFILL', dataFamily: 'OUTBOUND', taskStatus: 'FAILED', applyState: 'BLOCKED', attemptCount: 1, latestAttemptNo: 1, resultPublicationState: 'NOT_PUBLISHED', nextRetryAt: null, allowedActions: ['RETRY'], actionBlockReason: null, progress: null, queryFrom: null, queryUntil: null }
@@ -52,15 +52,6 @@ describe('self-operated query and command protection', () => {
expect(intent.create(task.taskNo, 'WH-A', '新的原因', key).requestKey).toBe('key-3')
expect(first).not.toHaveProperty('taskId')
})
it('breaks trend at unknown days and retains a single reliable zero point', () => {
const point = (businessDate: string, value: string | null, status: string): DailyPoint => ({ businessDate, outboundQuantity: value, observedQuantity: value, dataStatus: status, reasonCodes: [], quantityUnit: 'PCS' })
const segments = trendSegments([point('2026-10-10', '0', 'COMPLETE'), point('2026-10-11', null, 'UNKNOWN'), point('2026-10-12', '4', 'PARTIAL')])
expect(segments).toHaveLength(2)
expect(segments[0]?.path).not.toContain(' L')
expect(segments[1]?.partial).toBe(true)
expect(trendSegments([point('2026-10-12', '0', 'COMPLETE')])).toHaveLength(1)
expect(trendSegments([point('2026-10-12', null, 'UNKNOWN')])).toEqual([])
})
it('does not invent progress denominator or combine warehouse and account counts', () => {
const text = progressText({ progressScope: 'ACCOUNT_SHARED', countBasis: 'ATTEMPT_ONLY', attemptNo: 2, scanRound: 2, phase: 'DIRECTORY', completed: 3, total: null, totalKnown: false, unit: 'PAGE', sliceFrom: null, sliceUntil: null })
expect(text).toContain('账号共享')