feat(web): AI 工作台文件预览/附件关联任务与草稿分支

- 新增 WorkbenchAiFilePreviewDialog 附件预览对话框及 useWorkbenchAiFilePreview,附件支持点击预览
- 新增 attachmentAssociationJobs/linkedReimbursementDraftJobs 前端服务与对应 composable,接入后台任务轮询与状态展示
- 新增 travelReimbursementDraftBranchModel 草稿分支模型,报销关联门控支持跳过/选择草稿
- PersonalWorkbenchAiMode 及各 composable(expense/document/steward/application-preview/attachment-association)重构适配,WorkbenchAiComposer/FileStrip 样式与交互完善
- DocumentsCenter/ReceiptFolder/TravelReimbursementCreate 等视图及 scripts 重构,风险/差旅规划/审批等工具适配
- 新增/更新前端测试:application-result-card、reimbursement-list-preview-fetch、guided-flow、composer-components 等
This commit is contained in:
caoxiaozhu
2026-06-24 10:42:50 +08:00
parent 0264a4b5b4
commit ee730aa31c
73 changed files with 2528 additions and 379 deletions

View File

@@ -195,14 +195,14 @@ test('AI mode formats saved application draft as a detail table without continui
assert.match(aiMode, /function normalizeInlineApplicationStatusLabel\(value, fallback = ''\)/)
assert.match(aiMode, /submitted:\s*'审批中'/)
assert.match(aiMode, /const statusLabel = normalizeInlineApplicationStatusLabel\(info\.statusLabel, options\.statusLabel\)/)
assert.match(aiMode, /\| 单据类型 \| 单据编号 \| 单据状态 \| 当前节点 \| 日期 \| 地点 \| 事由 \| 金额 \| 操作 \|/)
assert.match(aiMode, /\[查看\]\(\$\{href\}\)/)
assert.match(aiMode, /\| 单据类型 \| 单据编号 \| 单据状态 \| 当前节点 \| 日期 \| 地点 \| 事由 \| 金额 \|/)
assert.doesNotMatch(aiMode, /\| 单据类型 \| 单据编号 \| 单据状态 \| 当前节点 \| 日期 \| 地点 \| 事由 \| 金额 \| 操作 \|/)
assert.doesNotMatch(aiMode, /\[查看\]\(\$\{href\}\)/)
assert.match(aiMode, /dateLabel:\s*rangeText \|\| dateText \|\| resolveBodyField\(\['时间', '日期', '申请时间'\]\) \|\| '待补充'/)
assert.match(aiMode, /locationLabel:[\s\S]*resolveBodyField\(\['地点', '目的地'\]\) \|\| '待补充'/)
assert.match(aiMode, /reasonLabel:[\s\S]*resolveBodyField\(\['事由', '事件', '申请事由'\]\) \|\| '待补充'/)
assert.match(aiMode, /buildInlineApplicationActionDetailHref\(info\)/)
assert.match(aiMode, /params\.set\('claim_id', claimId\)/)
assert.match(aiMode, /params\.set\('claim_no', claimNo\)/)
assert.match(aiMode, /function buildInlineApplicationDetailAction\(draftPayload = \{\}\)/)
assert.match(aiMode, /action_type:\s*'open_application_detail'/)
const resultStart = aiMode.indexOf('function buildInlineApplicationPreviewActionResultText')
const resultEnd = aiMode.indexOf('\nfunction buildInlineApplicationDetailAction', resultStart)
@@ -227,7 +227,7 @@ test('AI mode formats saved application draft as a detail table without continui
executeBlock,
/targetMessage\.suggestedActions = isSubmit[\s\S]*buildInlineApplicationPreviewSuggestedActions\(targetMessage\.applicationPreview, draftPayload\)/
)
assert.match(executeBlock, /suggestedActions:\s*isSubmit\s*\?\s*buildInlineApplicationDetailAction\(draftPayload\)\s*:\s*\[\]/)
assert.match(executeBlock, /suggestedActions:\s*buildInlineApplicationDetailAction\(draftPayload\)/)
})
test('AI mode locks application preview actions while estimate refresh is pending', () => {