feat: 实现 Sense 运维中心 (#74)

This commit is contained in:
QiuSW
2026-08-28 11:02:34 +08:00
parent 4157d90e9f
commit 184f101a86
14 changed files with 1218 additions and 0 deletions
@@ -0,0 +1,17 @@
import request from '@/utils/request'
import { getOperationProblem, listOperationProblems, retryOperationProblem } from '@/api/sense/operations'
jest.mock('@/utils/request', () => jest.fn())
describe('Sense operations API', () => {
beforeEach(() => request.mockReset())
test('encodes identifiers and sends only the expected version for controlled retry', () => {
listOperationProblems({ pageIndex: 1, pageSize: 10 })
getOperationProblem('media:camera/unsafe')
retryOperationProblem('media:camera/unsafe', 7)
expect(request).toHaveBeenNthCalledWith(1, { url: '/api/v1/operations', method: 'get', params: { pageIndex: 1, pageSize: 10 }})
expect(request).toHaveBeenNthCalledWith(2, { url: '/api/v1/operations/media%3Acamera%2Funsafe', method: 'get' })
expect(request).toHaveBeenNthCalledWith(3, { url: '/api/v1/operations/media%3Acamera%2Funsafe/retry', method: 'post', data: { expectedVersion: 7 }})
})
})
@@ -0,0 +1,23 @@
import { buildOperationsQuery, canRetry, objectLabel, problemLabel, severityType, stateLabel } from '@/views/sense/operations/operationsState'
describe('Sense operations presentation state', () => {
test('uses operator-facing state labels', () => {
expect(objectLabel('local_inference')).toBe('本地推理')
expect(problemLabel('orphan_safety_gate')).toBe('孤儿安全闸')
expect(stateLabel('unavailable')).toBe('不可用(未安装)')
expect(stateLabel('active / ready')).toBe('已启用 / 就绪')
expect(severityType('high')).toBe('danger')
})
test('allows retry only when the server projection says it is safe', () => {
expect(canRetry({ retryable: true, retryInProgress: false, version: 2 })).toBe(true)
expect(canRetry({ retryable: true, retryInProgress: true, version: 2 })).toBe(false)
expect(canRetry({ retryable: false, retryInProgress: false, version: 2 })).toBe(false)
})
test('builds an allowlisted query', () => {
expect(buildOperationsQuery({ pageIndex: 2, pageSize: 20, objectType: ' device ', problemType: 'clock_drift', severity: ' medium ', keyword: ' 南门 ', ignored: 'not-sent' })).toEqual({
pageIndex: 2, pageSize: 20, objectType: 'device', problemType: 'clock_drift', severity: 'medium', keyword: '南门'
})
})
})