- 重构报销状态注册表、审批流路由与平台风险标记 - 完善管家意图规划器与模型计划构建器全链路 - 新增 OCR Worker 脚本、数据库会话管理与通知状态 - 优化文档中心、日志视图、预算中心与员工管理交互 - 增强工作台摘要、图标资源与全局主题样式 - 补充审批路由、状态注册、OCR 服务与管家规划器测试覆盖
154 lines
5.9 KiB
JavaScript
154 lines
5.9 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
|
|
import {
|
|
buildDocumentViewedStatePatch,
|
|
buildDocumentsViewedStatePatches,
|
|
countNewDocuments,
|
|
isNewDocument,
|
|
markDocumentViewed,
|
|
markDocumentsViewed,
|
|
mergeNotificationStatesIntoViewedDocumentKeys,
|
|
readDocumentScope,
|
|
readViewedDocumentKeys,
|
|
resolveDocumentNewKey,
|
|
resolveDocumentNotificationId,
|
|
writeDocumentScope
|
|
} from '../src/utils/documentCenterNewState.js'
|
|
import { buildDocumentInboxRows } from '../src/composables/useDocumentCenterInbox.js'
|
|
|
|
function createMemoryStorage(initial = {}) {
|
|
const store = new Map(Object.entries(initial))
|
|
return {
|
|
getItem(key) {
|
|
return store.has(key) ? store.get(key) : null
|
|
},
|
|
setItem(key, value) {
|
|
store.set(key, value)
|
|
}
|
|
}
|
|
}
|
|
|
|
test('document center new state resolves source scoped document keys', () => {
|
|
assert.equal(resolveDocumentNewKey({ source: 'archive', claimId: 'claim-1' }), 'archive:claim-1')
|
|
assert.equal(resolveDocumentNewKey({ source: 'approval', documentNo: 'EXP-1' }), 'approval:EXP-1')
|
|
assert.equal(
|
|
resolveDocumentNotificationId({ source: 'owned', claimId: 'claim-1', documentKey: 'owned:claim-1' }),
|
|
'document:owned:claim-1'
|
|
)
|
|
})
|
|
|
|
test('document center merges backend notification states into viewed keys', () => {
|
|
const storage = createMemoryStorage()
|
|
const viewedKeys = mergeNotificationStatesIntoViewedDocumentKeys([
|
|
{ notification_id: 'document:owned:claim-1', read_at: '2026-06-05T09:00:00+08:00' },
|
|
{ notificationId: 'document:approval:claim-2', hiddenAt: '2026-06-05T09:01:00+08:00' },
|
|
{ notification_id: 'workbench:todo:claim-3', read_at: '2026-06-05T09:02:00+08:00' }
|
|
], readViewedDocumentKeys(storage), storage)
|
|
|
|
assert.equal(isNewDocument({ source: 'owned', claimId: 'claim-1' }, viewedKeys), false)
|
|
assert.equal(isNewDocument({ source: 'approval', claimId: 'claim-2' }, viewedKeys), false)
|
|
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1', 'approval:claim-2'])
|
|
})
|
|
|
|
test('document center builds backend viewed-state patches for unread rows', () => {
|
|
const rows = [
|
|
{ source: 'owned', claimId: 'claim-1', documentKey: 'owned:claim-1' },
|
|
{ source: 'approval', claimId: 'claim-2', documentKey: 'approval:claim-2' },
|
|
{ source: 'archive', claimId: 'claim-3', documentKey: 'archive:claim-3' }
|
|
]
|
|
const patches = buildDocumentsViewedStatePatches(rows, new Set(['owned:claim-1']))
|
|
|
|
assert.deepEqual(patches.map((patch) => patch.notification_id), ['document:approval:claim-2'])
|
|
assert.equal(patches[0].read, true)
|
|
assert.equal(patches[0].hidden, false)
|
|
assert.equal(patches[0].context_json.kind, 'document')
|
|
assert.equal(buildDocumentViewedStatePatch(rows[2]), null)
|
|
})
|
|
|
|
test('document center new state counts unseen documents and persists viewed rows', () => {
|
|
const storage = createMemoryStorage()
|
|
const rows = [
|
|
{ source: 'owned', claimId: 'claim-1' },
|
|
{ source: 'approval', claimId: 'claim-2' }
|
|
]
|
|
let viewedKeys = readViewedDocumentKeys(storage)
|
|
|
|
assert.equal(countNewDocuments(rows, viewedKeys), 2)
|
|
assert.equal(isNewDocument(rows[0], viewedKeys), true)
|
|
|
|
viewedKeys = markDocumentViewed(rows[0], viewedKeys, storage)
|
|
|
|
assert.equal(countNewDocuments(rows, viewedKeys), 1)
|
|
assert.equal(isNewDocument(rows[0], viewedKeys), false)
|
|
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1'])
|
|
})
|
|
|
|
test('document center new state can mark all unread rows as viewed at once', () => {
|
|
const storage = createMemoryStorage()
|
|
const rows = [
|
|
{ source: 'owned', claimId: 'claim-1' },
|
|
{ source: 'approval', claimId: 'claim-2' },
|
|
{ source: 'archive', claimId: 'claim-3' }
|
|
]
|
|
const viewedKeys = markDocumentsViewed(rows, readViewedDocumentKeys(storage), storage)
|
|
|
|
assert.equal(countNewDocuments(rows, viewedKeys), 0)
|
|
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1', 'approval:claim-2'])
|
|
})
|
|
|
|
test('document center archive rows are never marked as new', () => {
|
|
const viewedKeys = readViewedDocumentKeys(createMemoryStorage())
|
|
const rows = [
|
|
{ source: 'archive', claimId: 'archived-1' },
|
|
{ archived: true, source: 'owned', claimId: 'archived-2' },
|
|
{ isNewDocument: false, source: 'owned', claimId: 'archived-3' }
|
|
]
|
|
|
|
assert.equal(countNewDocuments(rows, viewedKeys), 0)
|
|
assert.equal(isNewDocument(rows[0], viewedKeys), false)
|
|
assert.equal(isNewDocument(rows[1], viewedKeys), false)
|
|
assert.equal(isNewDocument(rows[2], viewedKeys), false)
|
|
})
|
|
|
|
test('document center sidebar inbox shares source scoped document keys', () => {
|
|
const rows = buildDocumentInboxRows({
|
|
ownedClaims: [{ id: 'claim-1', claim_no: 'EXP-1' }],
|
|
approvalClaims: [{ id: 'claim-1', claim_no: 'EXP-1' }],
|
|
archivedClaims: [{ id: 'claim-2', claim_no: 'EXP-2' }]
|
|
})
|
|
|
|
assert.deepEqual(rows.map((row) => resolveDocumentNewKey(row)), ['approval:claim-1', 'archive:claim-2'])
|
|
})
|
|
|
|
test('document center inbox rows expose real notification metadata', () => {
|
|
const rows = buildDocumentInboxRows({
|
|
ownedClaims: [{
|
|
id: 'claim-1',
|
|
claim_no: 'EXP-1',
|
|
title: '差旅报销',
|
|
status: 'draft',
|
|
created_at: '2026-06-03T09:10:00+08:00'
|
|
}]
|
|
})
|
|
|
|
assert.equal(rows[0].documentNo, 'EXP-1')
|
|
assert.equal(rows[0].sourceLabel, '我的单据')
|
|
assert.equal(rows[0].title, '差旅报销')
|
|
assert.equal(rows[0].createdAt, '2026-06-03T09:10:00+08:00')
|
|
assert.equal(Number.isFinite(rows[0].sortTime), true)
|
|
})
|
|
|
|
test('document center scope state restores only allowed tabs', () => {
|
|
const storage = createMemoryStorage()
|
|
const scopes = ['全部', '申请单', '报销单', '审核单', '归档']
|
|
|
|
assert.equal(readDocumentScope('全部', scopes, storage), '全部')
|
|
|
|
writeDocumentScope('归档', scopes, storage)
|
|
assert.equal(readDocumentScope('全部', scopes, storage), '归档')
|
|
|
|
writeDocumentScope('不存在', scopes, storage)
|
|
assert.equal(readDocumentScope('全部', scopes, storage), '归档')
|
|
})
|