feat: 报销预审会话状态管理与工作台交互增强

- 新增差旅报销会话状态管理与对话模型重构
- 增强风险观测服务与运行时聊天上下文作用域
- 优化工作台图标资源、助理意图识别与摘要工具
- 完善报销创建视图样式与差旅详情页标准调整交互
- 补充风险观测、运行时聊天与报销端点测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-04 11:03:29 +08:00
parent 87da5df91b
commit 1cbf3fee44
60 changed files with 4156 additions and 393 deletions

View File

@@ -15,6 +15,7 @@ import { useTravelReimbursementReviewDrawer } from './useTravelReimbursementRevi
import { useTravelReimbursementSubmitComposer } from './useTravelReimbursementSubmitComposer.js'
import { useTravelReimbursementReviewActions } from './useTravelReimbursementReviewActions.js'
import { useTravelReimbursementGuidedFlow } from './useTravelReimbursementGuidedFlow.js'
import { useStewardPlanFlow } from './useStewardPlanFlow.js'
import { useApplicationPreviewEditor } from './useApplicationPreviewEditor.js'
import {
buildOperationFeedbackPayload,
@@ -24,6 +25,7 @@ import { recognizeOcrFiles } from '../../services/ocr.js'
import { fetchAgentRunDetail } from '../../services/agentAssets.js'
import { createOperationFeedback } from '../../services/operationFeedback.js'
import { deleteConversation, runOrchestrator } from '../../services/orchestrator.js'
import { fetchStewardPlan, fetchStewardPlanStream } from '../../services/steward.js'
import { renderMarkdown } from '../../utils/markdown.js'
import { clearAssistantSessionSnapshot } from '../../utils/assistantSessionSnapshot.js'
import {
@@ -182,6 +184,7 @@ import {
SESSION_TYPE_APPROVAL,
SESSION_TYPE_EXPENSE,
SESSION_TYPE_KNOWLEDGE,
SESSION_TYPE_STEWARD,
canUseBudgetAssistantSession,
aiAvatar,
buildExpenseIntentConfirmationMessage,
@@ -674,9 +677,12 @@ export default {
const isKnowledgeSession = computed(() => activeSessionType.value === SESSION_TYPE_KNOWLEDGE)
const isApplicationSession = computed(() => activeSessionType.value === SESSION_TYPE_APPLICATION)
const isStewardSession = computed(() => activeSessionType.value === SESSION_TYPE_STEWARD)
const activeAssistantMode = computed(() => resolveAssistantSessionMode(activeSessionType.value))
const assistantHeaderTitle = computed(() => '个人工作台')
const assistantHeaderDescription = computed(() => '个人工作窗,一站式费控解决枢纽')
const assistantHeaderTitle = computed(() => (isStewardSession.value ? '小财管家' : '个人工作台'))
const assistantHeaderDescription = computed(() =>
isStewardSession.value ? '统一财务任务编排入口' : '个人工作窗,一站式费控解决枢纽'
)
const {
flowRunId,
flowSteps,
@@ -747,6 +753,9 @@ export default {
showInsightPanel.value ? '隐藏详细信息' : '展开详细信息'
)
const composerPlaceholder = computed(() => {
if (isStewardSession.value) {
return '例如申请7月2日去北京出差同时报销昨天交通费和6月3日上海出差费用。'
}
if (isKnowledgeSession.value) {
return '例如:差旅住宿标准是什么?发票抬头不一致还能报销吗?'
}
@@ -1213,6 +1222,9 @@ export default {
const isReviewOverviewDrawer = computed(() => reviewDrawerMode.value === REVIEW_DRAWER_MODE_REVIEW)
const shortcuts = computed(() => {
if (isStewardSession.value) {
return []
}
const accessibleModes = filterAssistantSessionModes(ASSISTANT_SESSION_MODE_OPTIONS, currentUser.value)
const visibleModes = props.entrySource === 'budget'
? accessibleModes.filter((mode) => mode.key === SESSION_TYPE_BUDGET)
@@ -1416,6 +1428,7 @@ export default {
onBeforeUnmount(() => {
document.removeEventListener('click', handleComposerDatePickerOutside)
clearStewardThinkingTimers()
stopFlowRuntime()
stopAttachmentRuntime()
})
@@ -1518,6 +1531,27 @@ export default {
messages.value.splice(index, 1, nextMessage)
}
const { submitStewardPlan, clearStewardThinkingTimers } = useStewardPlanFlow({
activeSessionType,
attachedFiles,
composerDraft,
currentUser,
fileInputRef,
messages,
createMessage,
fetchStewardPlan,
fetchStewardPlanStream,
nextTick,
persistSessionState,
replaceMessage,
scrollToBottom,
adjustComposerTextareaHeight,
submitting,
reviewActionBusy,
sessionSwitchBusy,
toast
})
async function runShortcut(shortcut) {
if (shortcut?.action === 'switch_view' && shortcut?.targetSessionType) {
if (shortcut.targetSessionType === SESSION_TYPE_BUDGET && !canUseBudgetAssistantSession(currentUser.value)) {
@@ -1675,6 +1709,15 @@ export default {
scrollToBottom()
})
persistSessionState()
if (actionPayload.auto_submit && carryText) {
await submitComposer({
rawText: carryText,
userText: action.label || '确认继续处理',
pendingText: '正在按确认内容继续处理...',
files: carryFiles,
skipScopeGuard: true
})
}
return
}
@@ -2406,6 +2449,9 @@ export default {
// submitting.value = true
// recognizeOcrFiles(files)
// submitting.value = false
if (isStewardSession.value && await submitStewardPlan(options)) {
return null
}
if (await handleGuidedComposerSubmit(options)) {
return null
}
@@ -2651,7 +2697,7 @@ export default {
return {
emit, messageItemUi, insightPanelUi, ASSISTANT_DISPLAY_NAME, aiAvatar, userAvatar, fileInputRef, composerTextareaRef, messageListRef, composerDraft, composerDatePickerOpen, composerDateMode, composerSingleDate, composerRangeStartDate, composerRangeEndDate, composerBusinessTimeTags, composerCanApplyDateSelection,
toggleComposerDatePicker, closeComposerDatePicker, setComposerDateMode, handleComposerDateInputChange, removeComposerBusinessTimeTag, flowSteps, flowRunId, flowRefreshBusy, completedFlowStepCount, flowOverallStatusTone, flowOverallStatusText, flowTotalDurationText,
attachedFiles, composerFilesExpanded, visibleAttachedFiles, hiddenAttachedFileCount, submitting, sessionSwitchBusy, messages, currentInsight, linkedRequest, canSubmit, activeSessionType, isKnowledgeSession, hotKnowledgeQuestions,
attachedFiles, composerFilesExpanded, visibleAttachedFiles, hiddenAttachedFileCount, submitting, sessionSwitchBusy, messages, currentInsight, linkedRequest, canSubmit, activeSessionType, isKnowledgeSession, isStewardSession, hotKnowledgeQuestions,
hasInsightPanelContent, showInsightPanel, insightPanelToggleLabel, assistantHeaderTitle, assistantHeaderDescription, composerPlaceholder, currentIntentLabel, canDeleteCurrentSession, latestReviewMessage, activeReviewPayload, activeReviewPanelScope, activeReviewFilePreviews, reviewDrawerMode, isReviewOverviewDrawer, isReviewDocumentDrawer, isReviewRiskDrawer, isReviewFlowDrawer,
reviewDrawerTitle, reviewOverviewDrawerAvailable, reviewDocumentDrawerAvailable, reviewRiskDrawerAvailable, reviewFlowDrawerAvailable, reviewDocumentDrawerLabel, reviewDocumentDrawerIcon, reviewRiskDrawerLabel, reviewRiskDrawerIcon, reviewFlowDrawerLabel, reviewFlowDrawerIcon, activeReviewDocument, activeReviewDocumentIndex, activeReviewDocumentPreview, canPreviewActiveReviewDocument,
reviewIntentText, reviewFactCards, reviewCategoryOptions, reviewOtherCategoryOptions, reviewSelectedOtherCategory, reviewInlineDirty, reviewInlineForm, reviewInlineEditorKey, reviewInlineErrors, reviewOtherCategoryOpen, reviewInlinePendingFiles, DATE_INPUT_FORMAT, REVIEW_SCENE_OTHER_OPTION, REVIEW_SCENE_OPTIONS, REVIEW_OTHER_CATEGORY_OPTIONS,