feat(web): 工作台 AI 模式与差旅/风险建议交互优化

- 新增 PersonalWorkbenchAiMode 组件、AI 侧边栏与 orb 机器人视觉资源
- 新增 aiApplicationDraftModel / aiExpenseDraftModel / aiWorkbenchConversationStore
  及业务准入 aiSidebarBusinessAccess,支撑 AI 模式下的申请与报销草稿
- 顶栏、侧边栏、工作台样式重构,适配 AI 模式切换与响应式布局
- 同步 steward plan/off_topic、差旅报销引导流、风险建议卡片等测试
This commit is contained in:
caoxiaozhu
2026-06-18 22:12:24 +08:00
parent a6674a1e76
commit 0cde1f8990
65 changed files with 8011 additions and 1608 deletions

View File

@@ -24,7 +24,8 @@ import {
import { useApplicationPreviewEditor } from './useApplicationPreviewEditor.js'
import {
buildStewardFieldCompletionContinuation,
buildStewardFieldCompletionRawText
buildStewardFieldCompletionRawText,
resolveStewardRuntimeFieldCompletion
} from './stewardFieldCompletionModel.js'
import {
buildOperationFeedbackPayload,
@@ -169,8 +170,6 @@ import {
buildFileIdentity,
buildFilePreviews,
buildOcrDocumentsFromReviewPayload,
buildOcrFilePreviews,
buildOcrSummary,
buildOcrSummaryFromDocuments,
buildReviewFilePreviewsFromReviewPayload,
extractReviewAttachmentNames,
@@ -179,7 +178,6 @@ import {
mergeFilesWithLimit,
mergeUploadAttachmentNames,
mergeUploadOcrDocuments,
normalizeOcrDocuments,
resolveAttachmentPreviewKind,
resolveDocumentPreview
} from './travelReimbursementAttachmentModel.js'
@@ -1121,8 +1119,6 @@ export default {
buildExpenseSceneSelectionMessage,
buildMessageMeta,
buildOcrDocumentsFromReviewPayload,
buildOcrFilePreviews,
buildOcrSummary,
buildOcrSummaryFromDocuments,
buildReviewFormContextFromPayload,
clearAttachedFiles,
@@ -1155,7 +1151,6 @@ export default {
messages,
nextTick,
normalizeExpenseQueryPayload,
normalizeOcrDocuments,
persistSessionState,
props,
recognizeOcrFiles,
@@ -1904,6 +1899,10 @@ export default {
})
return
}
if (targetSessionType === SESSION_TYPE_EXPENSE && carryText === '我要报销') {
pushExpenseSceneSelectionPrompt(carryText)
return
}
if (String(actionPayload.steward_plan_id || '').trim()) {
const confirmedByText = Boolean(action.confirmedByText)
delete action.confirmedByText
@@ -2141,6 +2140,9 @@ export default {
}
function buildMessageBubbleClass(message) {
if (message?.role === 'assistant' && message?.assistantVariant === 'compact_guidance') {
return 'message-bubble-compact-guidance'
}
if (message?.role === 'assistant' && message?.budgetReport) {
return 'message-bubble-budget-report'
}
@@ -2965,6 +2967,10 @@ export default {
: '当前申请还有信息需要先补充。请先回复系统刚刚追问的内容,我再继续生成核对结果。'
}
}
const fieldCompletionDecision = resolveStewardRuntimeFieldCompletion(normalizedText, runtimeState)
if (fieldCompletionDecision) {
return fieldCompletionDecision
}
}
return null
}
@@ -3082,6 +3088,39 @@ export default {
})
return true
}
if (nextAction === 'fill_current_application_field') {
const targetMessageId = String(decision?.target_message_id || decision?.targetMessageId || '').trim()
const targetMessage = targetMessageId
? messages.value.find((message) => String(message.id || '') === targetMessageId)
: findLatestApplicationPreviewMessage()
if (!targetMessage?.applicationPreview) {
return false
}
const fieldKey = String(decision?.field_key || decision?.fieldKey || '').trim()
const fieldLabel = String(decision?.field_label || decision?.fieldLabel || '').trim()
const fieldValue = String(decision?.field_value || decision?.fieldValue || rawText).trim()
if (!fieldKey || !fieldValue) {
return false
}
await continueStewardApplicationFieldCompletion({
targetMessage,
action: {
label: fieldValue,
suppressUserEcho: userMessageAlreadyAdded,
payload: {
steward_delegated_field_completion: true,
field_key: fieldKey,
field_label: fieldLabel,
value: fieldValue
}
},
sourcePreview: targetMessage.applicationPreview,
fieldKey,
fieldLabel,
value: fieldValue
})
return true
}
if (nextAction === 'ask_user' || nextAction === 'cancel_current_action' || nextAction === 'no_op') {
pushStewardRuntimeResponse(rawText, decision, { userMessageAlreadyAdded })
return true