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

@@ -258,6 +258,51 @@ function resolveCandidateFlowExpenseType(flow = {}) {
return rawType
}
function normalizeStewardExpenseTypeCode(value = '') {
const text = String(value || '').trim()
if (text === '差旅' || text === '差旅费' || text === 'travel') {
return 'travel'
}
return text
}
function resolveTaskExpenseType(task = null) {
const fields = task?.ontologyFields || task?.ontology_fields || {}
const explicitType = normalizeStewardExpenseTypeCode(
fields.expense_type ||
fields.expenseType ||
fields.application_type ||
fields.applicationType ||
''
)
if (explicitType) {
return explicitType
}
const taskText = [
task?.title,
task?.summary,
fields.reason,
fields.location
].map((item) => String(item || '').trim()).join(' ')
return /差旅|出差/.test(taskText) ? 'travel' : ''
}
function buildStewardApplicationPreviewRoutePayload(actionType, task = null) {
if (actionType !== 'confirm_create_application') {
return {}
}
const expenseType = resolveTaskExpenseType(task)
if (expenseType !== 'travel') {
return {}
}
return {
steward_confirm_flow: true,
flow_id: 'travel_application',
expense_type: expenseType,
expense_type_label: FLOW_EXPENSE_TYPE_LABELS[expenseType] || ''
}
}
export function buildStewardSuggestedActions(plan) {
const normalized = normalizeStewardPlan(plan)
if (isOffTopicPlan(normalized)) {
@@ -320,6 +365,7 @@ export function buildStewardSuggestedActions(plan) {
action_type: ASSISTANT_SCOPE_ACTION_SWITCH,
payload: {
session_type: targetSessionType,
...buildStewardApplicationPreviewRoutePayload(actionType, task),
carry_text: buildStewardCarryText(actionType, task, group, normalized),
carry_files: actionType !== 'confirm_create_application',
auto_submit: true,