feat(web): 报销单新增关联申请单门控与草稿检测流程

- 新增 travelReimbursementAssociationGateModel,查询可关联申请单/草稿报销单并生成跳过/选择/单独新建动作,区分差旅费与业务招待费类型
- travelReimbursementApplicationLinkModel 补充 buildLinkedApplicationReferenceIndex/buildRequiredApplicationActions 等关联构建逻辑
- useTravelReimbursementSuggestedActions 接入 select_required_application/skip 系列动作,'我要报销'入口改为先走关联门控
- useWorkbenchAiActionRouter 新增 SKIP_REQUIRED_APPLICATION_LINK/SKIP_REIMBURSEMENT_DRAFT_CHECK 动作分发
- useWorkbenchAiExpenseFlow 暴露 startAiReimbursementAssociationGate,stewardPlanModel 待处理流程适配
- 新增 workbench-ai-action-router、workbench-ai-reimbursement-association-gate 测试并更新 guided-flow、steward-plan 测试
This commit is contained in:
caoxiaozhu
2026-06-22 15:55:59 +08:00
parent aa965da69d
commit ba444a514f
11 changed files with 1756 additions and 25 deletions

View File

@@ -12,6 +12,10 @@ import {
AI_ATTACHMENT_OCR_DETAIL_ACTION
} from './workbenchAiMessageModel.js'
import { SESSION_TYPE_EXPENSE } from './useWorkbenchAiExpenseFlow.js'
import {
SKIP_REQUIRED_APPLICATION_LINK_ACTION,
SKIP_REIMBURSEMENT_DRAFT_CHECK_ACTION
} from '../../views/scripts/travelReimbursementAssociationGateModel.js'
export function useWorkbenchAiActionRouter({
aiExpenseDraft,
@@ -98,6 +102,23 @@ export function useWorkbenchAiActionRouter({
return
}
if (actionType === SKIP_REIMBURSEMENT_DRAFT_CHECK_ACTION) {
void expenseFlow.startAiReimbursementAssociationGate(
actionPayload.original_message || '我要报销',
action.label || '不用草稿,关联申请单新建报销单',
{ skipDraftCheck: true }
)
return
}
if (actionType === SKIP_REQUIRED_APPLICATION_LINK_ACTION) {
expenseFlow.pushInlineExpenseSceneSelectionPrompt(
actionPayload.original_message || '我要报销',
action.label || '单独新建报销单'
)
return
}
if (actionType === 'ai_application_start_inline') {
aiExpenseDraft.value = null
void expenseFlow.startAiApplicationPreviewFromAction(action?.payload || {}, action?.label)
@@ -109,7 +130,7 @@ export function useWorkbenchAiActionRouter({
return
}
if (String(action?.payload?.session_type || '').trim() === SESSION_TYPE_EXPENSE && carryText === '我要报销') {
expenseFlow.pushInlineExpenseSceneSelectionPrompt(carryText, action.label)
void expenseFlow.startAiReimbursementAssociationGate(carryText, action.label)
return
}
startInlineConversation(carryText, {