feat(web): 工作台 AI 模式报销预审与文档查询模型拆分

- 新增 aiApplicationPrecheckModel/aiDocumentQueryModel/aiApplicationPreviewActions/aiConversationHtmlRenderer 四个独立模型与服务,按职责从主组件拆出
- PersonalWorkbenchAiMode 接入拆分后的预审、文档查询与 HTML 渲染逻辑,配合 markdown 工具增强结构化展示
- 文档中心与归档筛选、风险可见性、申请预览等工具同步适配,补充对应单元测试
- 新增 AI 文档卡片背景资源
This commit is contained in:
caoxiaozhu
2026-06-20 10:17:37 +08:00
parent 3d69f8501f
commit 304bbe1fd4
26 changed files with 3974 additions and 117 deletions

View File

@@ -48,7 +48,13 @@ test('AI mode offers an inline application shortcut when no candidate applicatio
assert.match(aiMode, /!candidates\.length/)
assert.match(aiMode, /ai_application_start_inline/)
assert.match(aiMode, /buildRequiredApplicationMissingText/)
assert.match(aiMode, /function startAiApplicationDraft/)
assert.match(aiMode, /function startAiApplicationPreview/)
assert.match(aiMode, /buildLocalApplicationPreview/)
assert.match(aiMode, /buildLocalApplicationPreviewMessage/)
assert.match(aiMode, /refreshApplicationPreviewEstimate/)
assert.match(aiMode, /applicationPreview:\s*preview/)
assert.doesNotMatch(aiMode, /function startAiApplicationDraft/)
assert.doesNotMatch(aiMode, /buildAiApplicationStepPrompt/)
})
test('AI mode steward reimbursement action opens expense scene selection locally', () => {
@@ -72,9 +78,28 @@ test('AI mode attaches required application lookup result before steward plannin
assert.match(aiMode, /await attachAiRequiredApplicationGate\(planRequest, prompt\)/)
})
test('AI mode automatically continues required application gate decisions from steward plan', () => {
assert.match(aiMode, /function continueAiRequiredApplicationGateFromPlan\(normalizedPlan\)/)
assert.match(aiMode, /flow\.flowId === 'travel_application'[\s\S]*startAiApplicationDraft\('travel', '差旅费'/)
assert.match(aiMode, /flow\.flowId === 'travel_reimbursement'[\s\S]*startAiExpenseDraft\('travel', '差旅费', true/)
assert.match(aiMode, /continueAiRequiredApplicationGateFromPlan\(normalizedPlan\)/)
test('AI mode handles document query prompts locally before steward planning', () => {
assert.match(aiMode, /resolveAiDocumentQueryIntent\(prompt/)
assert.match(aiMode, /async function handleAiDocumentQueryIntent/)
assert.match(aiMode, /buildAiDocumentQueryConditionSummary/)
assert.match(aiMode, /filterAiDocumentQueryRecords\(payload, intent\)/)
assert.match(aiMode, /fetchApprovalExpenseClaims/)
assert.match(aiMode, /buildAiDocumentQueryMessage/)
assert.match(aiMode, /AI_DOCUMENT_QUERY_STEP_DELAY_MS/)
assert.match(aiMode, /async function updateAiDocumentQueryThinking/)
assert.match(aiMode, /解析自然语言筛选条件/)
assert.match(aiMode, /查询业务单据接口/)
assert.match(aiMode, /组合筛选单据/)
assert.match(aiMode, /if \(await handleAiDocumentQueryIntent\(prompt, pendingMessage\)\) \{[\s\S]*return[\s\S]*\}/)
assert.match(aiMode, /emit\('open-document', buildAiDocumentDetailRequest\(detailReference\)\)/)
})
test('AI mode continues required application gate decisions into table preview from steward plan', () => {
assert.match(aiMode, /function continueAiRequiredApplicationGateFromPlan\(normalizedPlan, prompt = ''\)/)
assert.match(aiMode, /flow\.flowId === 'travel_application'[\s\S]*void startAiApplicationPreview\('travel', '差旅费', prompt/)
assert.match(aiMode, /flow\.flowId === 'travel_reimbursement'[\s\S]*startAiExpenseDraft\('travel', '差旅费', true/)
assert.match(aiMode, /continueAiRequiredApplicationGateFromPlan\(normalizedPlan, prompt\)/)
assert.match(aiMode, /class="workbench-ai-application-preview application-preview-shell"/)
assert.match(aiMode, /resolveInlineApplicationPreviewRows\(message\)/)
assert.match(aiMode, /commitInlineApplicationPreviewEditor\(message\)/)
})