fix(web): 保存草稿/提交成功后也推进到下一个 task

之前多 task 串行推进只在 steward action 执行链(executeInlineStewardAction)
生效,但保存草稿走的是 application preview 流(executeInlineApplicationPreviewAction),
成功后只显示'查看单据',不会提示继续下一个报销 task。

- startAiApplicationPreviewFromAction 透传 steward_remaining_tasks 到 preview message
- startAiApplicationPreview 把 stewardRemainingTasks 存到 message 上
- executeInlineApplicationPreviewAction 成功后:检查 targetMessage.stewardRemainingTasks,
  有剩余 task 则追加'继续处理费用报销'按钮(复用 steward_confirm_flow 分支)
- 新增 buildApplicationPreviewNextTaskAction 辅助函数

现在保存草稿/提交申请成功后,用户会看到:[查看单据] [继续处理费用报销]
This commit is contained in:
caoxiaozhu
2026-06-26 11:21:16 +08:00
parent 3a5664c4da
commit 3e4b1e1597
2 changed files with 43 additions and 3 deletions

View File

@@ -330,6 +330,38 @@ export function useWorkbenchAiApplicationPreviewFlow({
}
}
function buildApplicationPreviewNextTaskAction(targetMessage) {
// 多 task 串行推进:申请草稿保存/提交成功后,检查是否有剩余 task(如报销),
// 有则生成"继续处理下一个任务"按钮,让用户一键推进。
const remainingTasks = Array.isArray(targetMessage?.stewardRemainingTasks)
? targetMessage.stewardRemainingTasks
: []
const nextTask = remainingTasks[0]
if (!nextTask || !nextTask.task_type) {
return null
}
const taskType = String(nextTask.task_type || '').trim()
const isApplication = taskType === 'expense_application'
const flowId = isApplication ? 'travel_application' : 'travel_reimbursement'
const taskLabel = isApplication ? '出差申请' : '费用报销'
const ontologyFields = nextTask.ontology_fields || nextTask.ontologyFields || {}
return {
label: `继续处理${taskLabel}`,
description: `接下来处理${taskLabel}${String(nextTask.summary || nextTask.title || '').slice(0, 40)}`,
icon: isApplication ? 'mdi mdi-file-plus-outline' : 'mdi mdi-receipt-text-plus-outline',
action_type: 'steward_continue_next_task',
payload: {
steward_confirm_flow: true,
flow_id: flowId,
steward_current_task: nextTask,
expense_type: String(ontologyFields.expense_type || 'travel').trim() || 'travel',
expense_type_label: String(ontologyFields.expense_type_label || '差旅费').trim() || '差旅费',
ontology_fields: ontologyFields,
original_message: String(nextTask.summary || nextTask.title || `继续处理${taskLabel}`).trim()
}
}
}
async function executeInlineApplicationPreviewAction(actionType, sourceMessage = null, options = {}) {
const targetMessage = sourceMessage?.applicationPreview ? sourceMessage : resolveLatestInlineApplicationPreviewMessage()
if (!targetMessage?.applicationPreview) {
@@ -424,6 +456,8 @@ export function useWorkbenchAiApplicationPreviewFlow({
targetMessage.draftPayload = draftPayload
}
targetMessage.suggestedActions = []
const detailActions = buildInlineApplicationDetailAction(draftPayload)
const nextTaskAction = buildApplicationPreviewNextTaskAction(targetMessage)
replaceInlineMessage(
pendingMessage.id,
createInlineMessage('assistant', buildInlineApplicationPreviewActionResultText(actionType, payload), {
@@ -432,7 +466,7 @@ export function useWorkbenchAiApplicationPreviewFlow({
streamStatus: 'completed',
thinkingEvents: completeInlineThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
},
suggestedActions: buildInlineApplicationDetailAction(draftPayload)
suggestedActions: nextTaskAction ? [...detailActions, nextTaskAction] : detailActions
})
)
persistCurrentConversation()
@@ -552,9 +586,10 @@ export function useWorkbenchAiApplicationPreviewFlow({
suggestedActions: buildInlineApplicationPreviewSuggestedActions(preview),
requestedSubmit: Boolean(options.requestedSubmit),
submitRequiresConfirmation: Boolean(options.submitRequiresConfirmation),
stewardRemainingTasks: Array.isArray(options.stewardRemainingTasks) ? options.stewardRemainingTasks : [],
stewardPlan: {
streamStatus: 'completed',
thinkingEvents: completeInlineThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
thinkingEvents: completeWorkbenchAiThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
},
text: content
})

View File

@@ -143,7 +143,12 @@ export function useWorkbenchAiExpenseFlow({
return startAiApplicationPreview(
expenseType,
expenseTypeLabel,
payload.carry_text || resolveLatestInlineUserPrompt()
payload.carry_text || resolveLatestInlineUserPrompt(),
{
stewardRemainingTasks: Array.isArray(payload.steward_remaining_tasks)
? payload.steward_remaining_tasks
: []
}
)
}