feat(web): 票据夹资产缓存接入与 AI 工作台附件流程完善

- ReceiptFolderView 删除票据后提示已关联附件副本保留,接入 useToast;fetchReceiptFolderAsset 加 no-store 避免预览缓存
- PersonalWorkbenchAiMode 附件区/对话气泡适配资产缓存,personal-workbench-ai-mode.css 调整布局
- usePersonalWorkbenchAiMode/useWorkbenchAiApplicationPreviewFlow/useWorkbenchAiAttachmentAssociationFlow/useWorkbenchAiStewardFlow 完善附件草稿选择与关联流程
- travelRequestDetailSmartEntryRecognition 智能识别增强,AppShellRouteView/PersonalWorkbenchView/useApplicationPreviewEditor/useTravelReimbursementSubmitComposer 等配套适配
- 新增 expense-attachment-draft-selection、receipt-folder-asset-cache、travel-request-detail-smart-entry-recognition 测试,更新 attachment-association-confirmation、expense-application-fast-preview、workbench-ai-mode-switch 测试
This commit is contained in:
caoxiaozhu
2026-06-23 09:42:13 +08:00
parent 84a8998e59
commit e725b7f19c
22 changed files with 850 additions and 70 deletions

View File

@@ -1902,6 +1902,80 @@ test('application preview editor can edit return date from inline table input',
assert.equal(message.applicationPreview.fields.days, '5\u5929')
})
test('application preview editor opens date fields with native date input values', () => {
const preview = normalizeApplicationPreview({
fields: {
applicationType: '\u5dee\u65c5\u8d39\u7528\u7533\u8bf7',
time: '2026-02-20 \u81f3 2026-02-23',
location: '\u4e0a\u6d77',
reason: '\u670d\u52a1\u9879\u76ee\u90e8\u7f72',
days: '4\u5929'
}
})
const message = {
id: 'application-preview-editor-native-date-message',
applicationPreview: preview,
text: ''
}
const editor = useApplicationPreviewEditor({
persistSessionState: () => {},
toast: () => {}
})
editor.openApplicationPreviewEditor(message, 'time', message.applicationPreview.fields.time)
assert.equal(editor.resolveApplicationPreviewEditorControl('time'), 'date')
assert.equal(editor.applicationPreviewEditor.value.draftValue, '2026-02-20')
assert.equal(editor.resolveApplicationPreviewEditorDateMax(message, 'time'), '2026-02-23')
editor.openApplicationPreviewEditor(message, 'time_return', '2026-02-23')
assert.equal(editor.resolveApplicationPreviewEditorControl('time_return'), 'date')
assert.equal(editor.applicationPreviewEditor.value.draftValue, '2026-02-23')
assert.equal(editor.resolveApplicationPreviewEditorDateMin(message, 'time_return'), '2026-02-20')
})
test('application preview editor blocks invalid date ranges', async () => {
const preview = normalizeApplicationPreview({
fields: {
applicationType: '\u5dee\u65c5\u8d39\u7528\u7533\u8bf7',
time: '2026-02-20 \u81f3 2026-02-23',
location: '\u4e0a\u6d77',
reason: '\u670d\u52a1\u9879\u76ee\u90e8\u7f72',
days: '4\u5929',
transportMode: '\u706b\u8f66',
amount: ''
}
})
const message = {
id: 'application-preview-editor-invalid-date-message',
applicationPreview: preview,
text: ''
}
const toastMessages = []
const editor = useApplicationPreviewEditor({
persistSessionState: () => {},
toast: (messageText) => {
toastMessages.push(messageText)
}
})
editor.openApplicationPreviewEditor(message, 'time_return', '2026-02-23')
editor.applicationPreviewEditor.value.draftValue = '2026-02-19'
const returnCommitted = await editor.commitApplicationPreviewEditor(message)
assert.equal(returnCommitted, false)
assert.equal(message.applicationPreview.fields.time, '2026-02-20 \u81f3 2026-02-23')
assert.equal(message.applicationPreview.fields.days, '4\u5929')
assert.equal(toastMessages.at(-1), '\u51fa\u53d1\u65f6\u95f4\u4e0d\u80fd\u665a\u4e8e\u8fd4\u56de\u65f6\u95f4\uff0c\u8bf7\u91cd\u65b0\u9009\u62e9\u3002')
editor.openApplicationPreviewEditor(message, 'time', message.applicationPreview.fields.time)
editor.applicationPreviewEditor.value.draftValue = '2026-02-24'
const startCommitted = await editor.commitApplicationPreviewEditor(message)
assert.equal(startCommitted, false)
assert.equal(message.applicationPreview.fields.time, '2026-02-20 \u81f3 2026-02-23')
assert.equal(toastMessages.at(-1), '\u51fa\u53d1\u65f6\u95f4\u4e0d\u80fd\u665a\u4e8e\u8fd4\u56de\u65f6\u95f4\uff0c\u8bf7\u91cd\u65b0\u9009\u62e9\u3002')
})
test('application preview editor estimates after shorthand return date input', async () => {
const preview = normalizeApplicationPreview({
fields: {