feat(web): AI 工作台多 task 串行推进与会话适配

- useWorkbenchAiApplicationPreviewFlow/useWorkbenchAiActionRouter/useWorkbenchAiCommandIntents 支持 task1 完成后自动推进 task2,确认按钮直接拉起申请预览,草稿/提交成功后继续推进下一 task
- workbenchAiIntentPlannerModel/workbenchAiMessageModel/workbenchAiCommandIntentModel 适配多 task 意图规划与消息结构
- aiApplicationPreviewActions/aiApplicationPrecheckModel/aiExpenseDraftModel/aiWorkbenchConversationStore 草稿与会话存储适配
- PersonalWorkbenchAiMode 与样式适配,更新 preview-actions/expense-draft/conversation-store/fast-preview/action-router/command-intent/intent-planner 测试
This commit is contained in:
caoxiaozhu
2026-06-26 22:42:23 +08:00
parent 5753899eb3
commit c4b5fcc067
22 changed files with 1171 additions and 144 deletions

View File

@@ -258,7 +258,8 @@ export function usePersonalWorkbenchAiMode(props, emit) {
resolveLatestInlineUserPrompt,
scrollInlineConversationToBottom,
sending,
toast
toast,
onApplicationActionCompleted: startModelPlannedNextTask
})
const expenseFlow = useWorkbenchAiExpenseFlow({
@@ -710,6 +711,46 @@ export function usePersonalWorkbenchAiMode(props, emit) {
return pendingMessage
}
function buildModelPlannedNextTaskAction(remainingTasks = []) {
const tasks = Array.isArray(remainingTasks) ? remainingTasks : []
const nextTask = tasks[0]
if (!nextTask || typeof nextTask !== 'object') {
return null
}
const taskType = String(nextTask.task_type || nextTask.taskType || '').trim()
const assignedAgent = String(nextTask.assigned_agent || nextTask.assignedAgent || '').trim()
const isApplication = taskType === 'expense_application' || assignedAgent === 'application_assistant'
const isReimbursement = taskType === 'reimbursement' || assignedAgent === 'reimbursement_assistant'
if (!isApplication && !isReimbursement) {
return null
}
const ontologyFields = nextTask.ontology_fields || nextTask.ontologyFields || {}
const flowId = isApplication ? 'travel_application' : 'travel_reimbursement'
const taskLabel = isApplication ? '出差申请' : '费用报销'
return {
label: `继续处理${taskLabel}`,
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(),
steward_remaining_tasks: tasks.slice(1)
}
}
}
function startModelPlannedNextTask(remainingTasks = []) {
const nextTaskAction = buildModelPlannedNextTaskAction(remainingTasks)
if (!nextTaskAction) {
return
}
actionRouter.handleInlineSuggestedAction(nextTaskAction)
}
function startModelPlannedApplicationPreview(travelApplicationRequest, plannerPendingMessage = null) {
void applicationFlow.startAiApplicationPreview(
travelApplicationRequest.expenseType,
@@ -723,7 +764,10 @@ export function usePersonalWorkbenchAiMode(props, emit) {
autoSubmit: travelApplicationRequest.autoSubmit,
autoSaveDraft: travelApplicationRequest.autoSaveDraft,
requestedSubmit: travelApplicationRequest.requestedSubmit,
submitRequiresConfirmation: travelApplicationRequest.submitRequiresConfirmation
submitRequiresConfirmation: travelApplicationRequest.submitRequiresConfirmation,
stewardRemainingTasks: travelApplicationRequest.stewardRemainingTasks,
onPreviewReadyForNextTask: startModelPlannedNextTask,
onApplicationActionCompleted: startModelPlannedNextTask
}
)
}
@@ -741,7 +785,8 @@ export function usePersonalWorkbenchAiMode(props, emit) {
autoSubmit: travelApplicationRequest.autoSubmit,
autoSaveDraft: travelApplicationRequest.autoSaveDraft,
requestedSubmit: travelApplicationRequest.requestedSubmit,
submitRequiresConfirmation: travelApplicationRequest.submitRequiresConfirmation
submitRequiresConfirmation: travelApplicationRequest.submitRequiresConfirmation,
stewardRemainingTasks: travelApplicationRequest.stewardRemainingTasks
}
}
replaceInlineMessage(plannerPendingMessage.id, createInlineMessage('assistant', confirmText, {