Files
X-Financial/web/src/views/scripts/TravelReimbursementCreateView.js
caoxiaozhu ee730aa31c feat(web): AI 工作台文件预览/附件关联任务与草稿分支
- 新增 WorkbenchAiFilePreviewDialog 附件预览对话框及 useWorkbenchAiFilePreview,附件支持点击预览
- 新增 attachmentAssociationJobs/linkedReimbursementDraftJobs 前端服务与对应 composable,接入后台任务轮询与状态展示
- 新增 travelReimbursementDraftBranchModel 草稿分支模型,报销关联门控支持跳过/选择草稿
- PersonalWorkbenchAiMode 及各 composable(expense/document/steward/application-preview/attachment-association)重构适配,WorkbenchAiComposer/FileStrip 样式与交互完善
- DocumentsCenter/ReceiptFolder/TravelReimbursementCreate 等视图及 scripts 重构,风险/差旅规划/审批等工具适配
- 新增/更新前端测试:application-result-card、reimbursement-list-preview-fetch、guided-flow、composer-components 等
2026-06-24 10:42:50 +08:00

587 lines
44 KiB
JavaScript

import { computed, nextTick, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElDialog } from 'element-plus/es/components/dialog/index.mjs'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import TravelReimbursementInsightPanel from '../../components/travel/TravelReimbursementInsightPanel.vue'
import TravelReimbursementMessageItem from '../../components/travel/TravelReimbursementMessageItem.vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import { useTravelReimbursementFlow } from './useTravelReimbursementFlow.js'
import { useTravelReimbursementComposerTools } from './useTravelReimbursementComposerTools.js'
import { useTravelReimbursementAttachments } from './useTravelReimbursementAttachments.js'
import { useTravelReimbursementSessionState } from './useTravelReimbursementSessionState.js'
import { useTravelReimbursementReviewDrawer } from './useTravelReimbursementReviewDrawer.js'
import { useTravelReimbursementSubmitComposer } from './useTravelReimbursementSubmitComposer.js'
import { useTravelReimbursementReviewActions } from './useTravelReimbursementReviewActions.js'
import { useTravelReimbursementCreateViewLifecycle } from './useTravelReimbursementCreateViewLifecycle.js'
import { useTravelReimbursementCreateViewControls } from './useTravelReimbursementCreateViewControls.js'
import { useTravelReimbursementCreateViewDrawerControls } from './useTravelReimbursementCreateViewDrawerControls.js'
import { useTravelReimbursementCreateViewMessageHandlers } from './useTravelReimbursementCreateViewMessageHandlers.js'
import { useTravelReimbursementCreateViewOperationFeedback } from './useTravelReimbursementCreateViewOperationFeedback.js'
import { useTravelReimbursementCreateViewScroll } from './useTravelReimbursementCreateViewScroll.js'
import { useTravelReimbursementCreateViewSessionCleanup } from './useTravelReimbursementCreateViewSessionCleanup.js'
import { useTravelReimbursementCreateViewState } from './useTravelReimbursementCreateViewState.js'
import { useTravelReimbursementCreateViewSuggestedActionLock } from './useTravelReimbursementCreateViewSuggestedActionLock.js'
import { useTravelReimbursementCreateViewTravelCalculator } from './useTravelReimbursementCreateViewTravelCalculator.js'
import { useTravelReimbursementCreateViewUi } from './useTravelReimbursementCreateViewUi.js'
import { useTravelReimbursementGuidedFlow } from './useTravelReimbursementGuidedFlow.js'
import { useTravelReimbursementMessageActions } from './useTravelReimbursementMessageActions.js'
import { useTravelReimbursementSuggestedActions } from './useTravelReimbursementSuggestedActions.js'
import { useStewardPlanFlow } from './useStewardPlanFlow.js'
import { useTravelReimbursementApplicationSubmitConfirm } from './useTravelReimbursementApplicationSubmitConfirm.js'
import { useTravelReimbursementStewardRuntimeDecision } from './useTravelReimbursementStewardRuntimeDecision.js'
import { useTravelReimbursementApplicationPreviewDateEditor } from './useTravelReimbursementApplicationPreviewDateEditor.js'
import { buildStewardFieldItems, formatStewardMissingFieldList, formatStewardOntologyFields } from './stewardPlanModel.js'
import { useApplicationPreviewEditor } from './useApplicationPreviewEditor.js'
import { buildStewardFieldCompletionContinuation, buildStewardFieldCompletionRawText } from './stewardFieldCompletionModel.js'
import { buildOperationFeedbackPayload } from '../../composables/useOperationFeedback.js'
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 { buildLocalExtractionProgressMessages, buildLocalIntentPreview, shouldRequestExpenseIntentConfirmation, shouldRequestExpenseSceneSelection, summarizeSemanticIntentDetail } from '../../utils/reimbursementTextInference.js'
import { buildExpenseIntentConfirmationActions, buildExpenseSceneSelectionActions } from '../../utils/expenseAssistantActions.js'
import { ASSISTANT_SCOPE_ACTION_SWITCH } from '../../utils/assistantSessionScope.js'
import { mergeComposerPrefill, resolveSuggestedActionPrefill } from '../../utils/assistantSuggestedActionPrefill.js'
import { APPLICATION_TRANSPORT_MODE_OPTIONS, buildApplicationPreviewFooterMessage, buildApplicationPreviewSubmitText, buildLocalApplicationPreviewMessage, normalizeTransportModeOption } from '../../utils/expenseApplicationPreview.js'
import { TRAVEL_PLANNING_ACTION_GENERATE, TRAVEL_PLANNING_ACTION_SKIP } from '../../utils/travelApplicationPlanning.js'
import { calculateTravelReimbursement, createExpenseClaimItem, fetchExpenseClaims, fetchExpenseClaimAttachmentAsset, fetchExpenseClaimDetail, fetchExpenseClaimItemAttachmentMeta, uploadExpenseClaimItemAttachment } from '../../services/reimbursements.js'
import { EXPENSE_TYPE_LABELS, REVIEW_SLOT_CONFIG, REVIEW_CATEGORY_PRESET_OPTIONS, REVIEW_OTHER_CATEGORY_OPTIONS, REVIEW_SCENE_OTHER_OPTION, REVIEW_SCENE_OPTIONS, DATE_INPUT_FORMAT, cloneReviewDocumentDrafts, buildReviewDocumentDrafts, normalizeReviewDocumentComparableValue, buildReviewDocumentCorrectionMessage, buildReviewDocumentCorrectionContext, cloneReviewEditFields, buildReviewFormValues, resolveReviewRecognizedSlotCards, resolveReviewMissingSlotCards, resolveReviewExtraMissingLabels, formatConfidenceLabel, resolveDocumentTypeLabel, resolveExpenseTypeLabel, buildReviewRecognizedLines, buildReviewSlotMap, resolveExpenseTypeCode, isValidIsoDateString, parseAmountNumber, normalizeAmountValue, extractAmountInputValue, inferPresetSceneFromReview, summarizeReviewScene, buildInlineReviewState, resolveReviewCategoryConfidenceScore, buildReviewCategoryOptions, buildReviewPanelConfidence, buildLocallySyncedReviewPayload, buildInlineReviewChangedLines, buildLocalReviewSavedMessage, buildReviewSubmitUserText, mergeInlineReviewFields, buildClientTimeContext, formatDraftApplyTime, formatDateInputValue, buildDraftSavedPayload, buildReviewHeadline, buildReviewSubline, buildReviewStateLabel, buildReviewStateTone, buildReviewPlainFollowupCopy, buildReviewNextStepRichCopy, buildReviewRiskLevelCounts, resolveReviewFooterActions, resolveReviewSaveDraftAction, resolveReviewNextStepAction, buildReviewPrimaryButtonLabel, buildReviewIntentText, buildReviewSceneValue, buildMissingRiskLine, buildReviewRiskSummary as buildReviewRiskSummaryModel, buildLocalReviewCompletionMessage, buildReviewRecognitionNotes, buildReviewDocumentSummaries } from './travelReimbursementReviewModel.js'
import { buildBusinessTimeContextFromReviewValues, buildReviewCorrectionMessage, buildReviewFactCards, buildReviewFormContextFromPayload, buildReviewMainMessageText, buildReviewRiskConversationText, buildReviewRiskItems, canExposeReviewPanelScope, isTravelReviewPayload, normalizeReviewPanelScope, resolveReviewRiskBriefs, resolveReviewTravelTransportType } from './travelReimbursementCreateReviewModel.js'
import { buildDraftAssociationQueryPayload, buildExpenseQueryHint, buildExpenseQueryWindowLabel, getExpenseQueryActivePage, getExpenseQueryTotalPages, getExpenseQueryVisibleRecords, normalizeExpenseQueryPayload } from './travelReimbursementExpenseQueryModel.js'
import { MAX_ATTACHMENTS, MAX_OCR_DOCUMENTS, VISIBLE_ATTACHMENT_CHIPS, buildAgentInsight, buildErrorInsight, buildFileIdentity, buildFilePreviews, buildOcrDocumentsFromReviewPayload, buildOcrSummaryFromDocuments, buildReviewFilePreviewsFromReviewPayload, extractReviewAttachmentNames, isTemporaryPreviewUrl, mergeFilePreviews, mergeFilesWithLimit, mergeUploadAttachmentNames, mergeUploadOcrDocuments, resolveAttachmentPreviewKind, resolveDocumentPreview } from './travelReimbursementAttachmentModel.js'
import { ASSISTANT_SESSION_MODE_OPTIONS, ASSISTANT_DISPLAY_NAME, FLOW_STEP_FALLBACKS, HOT_KNOWLEDGE_QUESTIONS, INTENT_LABELS, SCENARIO_LABELS, SESSION_TYPE_BUDGET, SESSION_TYPE_APPLICATION, SESSION_TYPE_APPROVAL, SESSION_TYPE_EXPENSE, SESSION_TYPE_KNOWLEDGE, SESSION_TYPE_STEWARD, canUseBudgetAssistantSession, aiAvatar, buildExpenseIntentConfirmationMessage, buildExpenseSceneSelectionMessage, buildMessageMeta, buildWelcomeInsight, createMessage, filterAssistantSessionModes, hasMeaningfulSessionMessages, resolveAssistantSessionMode, resolveKnowledgeRankLabel, resolveKnowledgeRankTone, sanitizeRequest, summarizeSemanticParseDetail, userAvatar } from './travelReimbursementConversationModel.js'
const STEWARD_ASSISTANT_NAME = '小财管家'
const APPLICATION_PREVIEW_FIELD_ACTION_SET = 'set_application_preview_field'
const COMPOSER_TEXTAREA_HEIGHT = 36
const COMPOSER_MAX_ROWS = 5
const REVIEW_DRAWER_MODE_REVIEW = 'review'
const REVIEW_DRAWER_MODE_DOCUMENTS = 'documents'
const REVIEW_DRAWER_MODE_RISK = 'risk'
const REVIEW_DRAWER_MODE_FLOW = 'flow'
const REVIEW_NEXT_STEP_HREF = '#review-next-step'
const APPLICATION_SUBMIT_HREF = '#application-submit'
const REVIEW_RISK_PANEL_HREF_PREFIX = '#review-risk'
const REVIEW_QUICK_EDIT_HREF = '#review-quick-edit'
const FLOW_STEP_STATUS_PENDING = 'pending'
const FLOW_STEP_STATUS_RUNNING = 'running'
const FLOW_STEP_STATUS_COMPLETED = 'completed'
const FLOW_STEP_STATUS_FAILED = 'failed'
export default {
name: 'TravelReimbursementCreateView',
components: {
ElDialog,
ConfirmDialog,
TravelReimbursementInsightPanel,
TravelReimbursementMessageItem
},
props: {
initialPrompt: {
type: String,
default: ''
},
initialPromptAutoSubmit: {
type: Boolean,
default: true
},
initialApplicationPreview: {
type: Object,
default: null
},
initialFiles: {
type: Array,
default: () => []
},
initialConversation: {
type: Object,
default: null
},
initialBudgetContext: {
type: Object,
default: null
},
initialSessionType: {
type: String,
default: ''
},
entrySource: {
type: String,
default: 'requests'
},
requestContext: {
type: Object,
default: null
},
invalidatedDraftClaimId: {
type: String,
default: ''
},
reopenToken: {
type: Number,
default: 0
}
},
emits: ['close', 'draft-saved', 'request-updated'],
setup(props, { emit }) {
const router = useRouter()
const { currentUser, refreshCurrentUserFromBackend } = useSystemState()
const { toast } = useToast()
const fileInputRef = ref(null)
const composerTextareaRef = ref(null)
const messageListRef = ref(null)
const composerDraft = ref('')
const submitting = ref(false)
const workbenchVisible = ref(false)
const closeAfterBusy = ref(false)
const linkedRequest = computed(() => sanitizeRequest(props.requestContext))
const hotKnowledgeQuestions = HOT_KNOWLEDGE_QUESTIONS
let sessionRuntimeRefs = {}
let scrollHandlers = {}
function scrollToBottom() {
return scrollHandlers.scrollToBottom?.()
}
function handleAssistantModalAfterEnter() {
return scrollHandlers.handleAssistantModalAfterEnter?.()
}
function adjustComposerTextareaHeight() {
return scrollHandlers.adjustComposerTextareaHeight?.()
}
function handleComposerInput() {
return scrollHandlers.handleComposerInput?.()
}
function handleComposerEnter(event) {
return scrollHandlers.handleComposerEnter?.(event)
}
let sessionCleanupHandlers = {}
function resetCurrentSessionState() {
return sessionCleanupHandlers.resetCurrentSessionState?.()
}
function clearExpenseSessionForDeletedClaim(claimId) {
return sessionCleanupHandlers.clearExpenseSessionForDeletedClaim?.(claimId)
}
let suggestedActionLockHandlers = {}
function lockSuggestedActionMessage(message, action) {
return suggestedActionLockHandlers.lockSuggestedActionMessage?.(message, action) ?? false
}
function buildMessageActionRows(message) {
return suggestedActionLockHandlers.buildMessageActionRows?.(message) ?? []
}
const {
activeSessionType,
messages,
conversationId,
stewardState,
draftClaimId,
sessionSnapshots,
currentInsight,
reviewFilePreviews,
composerUploadIntent,
guidedFlowState,
insightPanelCollapsed,
sessionSwitchBusy,
buildEmptySessionState,
resolveCurrentUserId,
persistSessionState,
applySessionState,
switchSessionType
} = useTravelReimbursementSessionState({
props,
currentUser,
linkedRequest,
toast,
composerDraft,
adjustComposerTextareaHeight,
scrollToBottom,
getSessionRuntimeRefs: () => sessionRuntimeRefs
})
const deleteSessionDialogOpen = ref(false)
const applicationSubmitConfirmDialog = ref({
open: false,
message: null
})
const nextStepConfirmDialog = ref({
open: false,
message: null,
action: null
})
const reviewActionBusy = ref(false)
const deleteSessionBusy = ref(false)
const reviewDrawerMode = ref(REVIEW_DRAWER_MODE_REVIEW)
const {
applicationPreviewEditor,
resolveApplicationPreviewRows,
resolveApplicationPreviewEditorControl,
resolveApplicationPreviewEditorOptions,
isApplicationPreviewEditing,
isApplicationPreviewDateEditorOpen,
openApplicationPreviewEditor,
commitApplicationPreviewEditor,
commitApplicationPreviewDateEditor,
cancelApplicationPreviewEditor,
setApplicationPreviewDateMode,
canApplyApplicationPreviewDateSelection,
handleApplicationPreviewEditorKeydown
} = useApplicationPreviewEditor({
persistSessionState,
toast,
calculateTravelReimbursement,
currentUser
})
let applyLinkedApplicationPreviewDateSelection = () => false
let openApplicationPreviewEditorFromUi = openApplicationPreviewEditor
const {
activeReviewPanelScope,
activeReviewPayload,
assistantHeaderDescription,
assistantHeaderTitle,
canDeleteCurrentSession,
composerPlaceholder,
currentIntentLabel,
hasInsightPanelContent,
insightPanelToggleLabel,
isApplicationSession,
isKnowledgeSession,
isStewardSession,
latestReviewMessage,
shortcuts,
showInsightPanel,
showStewardInitialRecognition
} = useTravelReimbursementCreateViewState({
ASSISTANT_SESSION_MODE_OPTIONS,
SESSION_TYPE_APPLICATION,
SESSION_TYPE_APPROVAL,
SESSION_TYPE_BUDGET,
SESSION_TYPE_KNOWLEDGE,
SESSION_TYPE_STEWARD,
activeSessionType,
canExposeReviewPanelScope,
conversationId,
currentInsight,
currentUser,
filterAssistantSessionModes,
getActiveFlowSteps: () => activeFlowSteps.value,
hasMeaningfulSessionMessages,
insightPanelCollapsed,
linkedRequest,
messages,
normalizeReviewPanelScope,
props,
resolveAssistantSessionMode,
submitting,
workbenchVisible
})
const {
flowRunId,
flowSteps,
activeFlowSteps,
visibleFlowSteps,
flowRefreshBusy,
completedFlowStepCount,
flowOverallStatusTone,
flowOverallStatusText,
flowTotalDurationText,
clearFlowSimulationTimers,
resetFlowRun,
startFlowTick,
stopFlowRuntime,
startFlowStep,
completeFlowStep,
failCurrentFlowStep,
startSemanticFlowPreview,
startExpenseSceneSelectionFlowPreview,
startExpenseIntentConfirmationFlowPreview,
startExpenseSceneSelectionAfterIntentConfirmation,
startReviewActionFlowStep,
startExpenseClaimDraftFlowStep,
completeFlowResult,
refreshFlowRunDetail,
formatFlowStepDuration,
resolveFlowStepStatusLabel,
resolveFlowStepDetail
} = useTravelReimbursementFlow({
activeSessionType,
reviewDrawerMode,
insightPanelCollapsed,
isKnowledgeSession,
fetchAgentRunDetail,
buildLocalIntentPreview,
buildLocalExtractionProgressMessages,
summarizeSemanticIntentDetail,
summarizeSemanticParseDetail,
SCENARIO_LABELS,
INTENT_LABELS,
EXPENSE_TYPE_LABELS,
FLOW_STEP_FALLBACKS,
REVIEW_DRAWER_MODE_FLOW,
REVIEW_DRAWER_MODE_REVIEW,
FLOW_STEP_STATUS_PENDING,
FLOW_STEP_STATUS_RUNNING,
FLOW_STEP_STATUS_COMPLETED,
FLOW_STEP_STATUS_FAILED
})
const reviewRiskBriefResolver = (payload) => resolveReviewRiskBriefs(payload)
const buildReviewRiskSummary = (payload) => buildReviewRiskSummaryModel(payload, reviewRiskBriefResolver)
const { reviewInlineForm, reviewInlineBaseForm, reviewInlineBaseFields, reviewInlinePendingFiles, reviewInlineEditorKey, reviewInlineErrors, reviewOtherCategoryOpen, reviewDocumentDrafts, reviewDocumentBaseDrafts, activeReviewDocumentIndex, documentPreviewDialog, activeReviewFilePreviews, reviewIntentText, reviewFactCards, reviewCategoryOptions, reviewOtherCategoryOptions, reviewSelectedOtherCategory, reviewInlineDirty, reviewPanelConfidence, reviewRiskSummary, reviewRiskItems, reviewRiskEmpty, reviewOverviewDrawerAvailable, reviewDocumentDrawerAvailable, reviewRiskDrawerAvailable, reviewFlowDrawerAvailable, recognizedNarratives, reviewRecognitionNotes, reviewDocumentSummaries, reviewDocumentCount, isReviewDocumentDrawer, isReviewRiskDrawer, isReviewFlowDrawer, reviewDrawerTitle, reviewDocumentDrawerLabel, reviewDocumentDrawerIcon, reviewRiskDrawerLabel, reviewRiskDrawerIcon, reviewFlowDrawerLabel, reviewFlowDrawerIcon, activeReviewDocument, activeReviewDocumentPreview, canPreviewActiveReviewDocument, reviewDocumentDirty, reviewHasUnsavedChanges, setInlineReviewFieldError, clearInlineReviewFieldError, resetReviewDrawerFromPayload, enforceReviewDrawerAvailability, openInlineReviewEditor, closeInlineReviewEditor, commitInlineReviewEditor, selectInlineScene, selectReviewCategory, selectReviewOtherCategory, goReviewDocument, openActiveReviewDocumentPreview, closeDocumentPreview } = useTravelReimbursementReviewDrawer({
activeReviewPayload, activeReviewPanelScope, reviewFilePreviews, flowSteps: activeFlowSteps, submitting, reviewActionBusy, triggerFileUpload: (...args) => triggerFileUpload(...args), resolveDocumentPreview, buildReviewFactCards, buildReviewRiskItems, buildReviewRiskSummary, buildReviewIntentText, resolveReviewRiskBriefs, reviewDrawerMode, REVIEW_DRAWER_MODE_REVIEW, REVIEW_DRAWER_MODE_DOCUMENTS, REVIEW_DRAWER_MODE_RISK, REVIEW_DRAWER_MODE_FLOW
})
const { composerDatePickerOpen, composerDateMode, composerSingleDate, composerRangeStartDate, composerRangeEndDate, composerBusinessTimeTags, composerBusinessTimeDraftTouched, composerCanApplyDateSelection, travelCalculatorOpen, travelCalculatorBusy, travelCalculatorError, travelCalculatorResult, travelCalculatorForm, travelCalculatorCanSubmit, buildComposerBusinessTimeLabel, hasComposerBusinessTimeSelection, buildComposerBusinessTimeContext, mergeBusinessTimeIntoExtraContext, syncComposerBusinessTimeToReviewCard, resolveComposerSubmitText, resolveComposerDisplaySubmitText, toggleComposerDatePicker, closeComposerDatePicker, setComposerDateMode, handleComposerDateInputChange, removeComposerBusinessTimeTag, handleComposerDatePickerOutside, applyComposerDateSelection, resolveTravelCalculatorInitialDays, resolveTravelCalculatorInitialLocation, openTravelCalculator: openTravelCalculatorInternal, toggleTravelCalculator: toggleTravelCalculatorInternal, closeTravelCalculator, formatTravelCalculatorMoney, buildTravelCalculatorResultText, submitTravelCalculator: submitTravelCalculatorInternal } = useTravelReimbursementComposerTools({
currentUser, activeReviewPayload, reviewInlineForm, latestReviewMessage, currentInsight, messages, composerDraft, composerTextareaRef, adjustComposerTextareaHeight, scrollToBottom, toast, calculateTravelReimbursement, createMessage, buildReviewSlotMap, isValidIsoDateString, buildLocallySyncedReviewPayload, formatDateInputValue, onComposerDateSelection: (...args) => applyLinkedApplicationPreviewDateSelection(...args)
})
;({
applyLinkedApplicationPreviewDateSelection,
openApplicationPreviewEditorFromUi
} = useTravelReimbursementApplicationPreviewDateEditor({
applicationPreviewEditor,
cancelApplicationPreviewEditor,
commitApplicationPreviewDateEditor,
composerDateMode,
composerDatePickerOpen,
composerRangeEndDate,
composerRangeStartDate,
composerSingleDate,
formatDateInputValue,
isApplicationPreviewEditing,
messages,
openApplicationPreviewEditor,
travelCalculatorOpen
}))
const { fileInputMode, attachedFiles, composerFilesExpanded, visibleAttachedFiles, hiddenAttachedFileCount, rememberFilePreviews, buildComposerFilePreviews, resolveActiveClaimId, restorePersistedDraftAttachmentPreviews, syncComposerFilesToDraft, triggerFileUpload, handleFilesChange, toggleAttachedFilesExpanded, removeAttachedFile, clearAttachedFiles, stopAttachmentRuntime } = useTravelReimbursementAttachments({
isKnowledgeSession, reviewFilePreviews, linkedRequest, draftClaimId, activeReviewPayload, reviewInlinePendingFiles, reviewInlineForm, reviewInlineEditorKey, composerUploadIntent, submitting, reviewActionBusy, toast, fileInputRef, createExpenseClaimItem, fetchExpenseClaimDetail, fetchExpenseClaimItemAttachmentMeta, fetchExpenseClaimAttachmentAsset, uploadExpenseClaimItemAttachment, extractReviewAttachmentNames, mergeFilesWithLimit, mergeFilePreviews, isTemporaryPreviewUrl, resolveAttachmentPreviewKind, resolveDocumentPreview, buildFilePreviews, buildFileIdentity, MAX_ATTACHMENTS, VISIBLE_ATTACHMENT_CHIPS, clearInlineReviewFieldError
})
sessionRuntimeRefs = {
attachedFiles,
composerFilesExpanded,
guidedFlowState
}
const { emitOperationCompleted } = useTravelReimbursementCreateViewOperationFeedback({
activeSessionType,
conversationId,
currentUser,
props,
resolveCurrentUserId
})
const { confirmPendingAttachmentAssociationInternal, submitComposerInternal } = useTravelReimbursementSubmitComposer({
MAX_ATTACHMENTS, activeReviewPayload, activeSessionType, adjustComposerTextareaHeight, attachedFiles, buildAgentInsight, buildClientTimeContext, buildComposerBusinessTimeContext, buildComposerFilePreviews, buildDraftAssociationQueryPayload, buildErrorInsight, buildExpenseIntentConfirmationActions, buildExpenseIntentConfirmationMessage, buildExpenseSceneSelectionActions, buildExpenseSceneSelectionMessage, buildMessageMeta, buildOcrDocumentsFromReviewPayload, buildOcrSummaryFromDocuments, buildReviewFormContextFromPayload, clearAttachedFiles, clearFlowSimulationTimers, completeFlowResult, completeFlowStep, composerBusinessTimeDraftTouched, composerBusinessTimeTags, composerDraft, composerUploadIntent, conversationId, createMessage, currentInsight, currentUser, refreshCurrentUserFromBackend, draftClaimId, extractReviewAttachmentNames, failCurrentFlowStep, fetchExpenseClaims, fileInputRef, flowRunId, insightPanelCollapsed, isKnowledgeSession, linkedRequest, mergeBusinessTimeIntoExtraContext, mergeFilePreviews, mergeFilesWithLimit, mergeUploadAttachmentNames, mergeUploadOcrDocuments, messages, nextTick, normalizeExpenseQueryPayload, persistSessionState, props, recognizeOcrFiles, refreshFlowRunDetail, rememberFilePreviews, replaceMessage, resolveComposerDisplaySubmitText, resetFlowRun, resolveComposerSubmitText, reviewInlineForm, runOrchestrator, scrollToBottom, sessionSwitchBusy, shouldRequestExpenseIntentConfirmation, shouldRequestExpenseSceneSelection, startExpenseClaimDraftFlowStep, startExpenseIntentConfirmationFlowPreview, startExpenseSceneSelectionFlowPreview, startFlowStep, startSemanticFlowPreview, submitting, syncComposerFilesToDraft, emitOperationCompleted, emitDraftSaved: (payload) => emit('draft-saved', payload), emitRequestUpdated: (payload) => emit('request-updated', payload), toast
})
let submitComposerFromMessageHandlers = null
async function submitComposer(options = {}) {
if (submitComposerFromMessageHandlers) {
return submitComposerFromMessageHandlers(options)
}
return submitComposerInternal(options)
}
const canSubmit = computed(
() =>
!submitting.value
&& !sessionSwitchBusy.value
&& Boolean(
composerDraft.value.trim()
|| attachedFiles.value.length
|| composerBusinessTimeTags.value.length
)
)
const { handleGuidedShortcut, handleGuidedComposerSubmit, handleGuidedSuggestedAction, handleSceneSelectionApplicationGate, resetGuidedFlowState } = useTravelReimbursementGuidedFlow({
guidedFlowState, messages, composerDraft, attachedFiles, composerBusinessTimeTags, composerBusinessTimeDraftTouched, fileInputRef, submitting, reviewActionBusy, sessionSwitchBusy, createMessage, nextTick, scrollToBottom, persistSessionState, clearAttachedFiles, adjustComposerTextareaHeight, buildComposerBusinessTimeContext, openTravelCalculator, lockSuggestedActionMessage, submitExistingComposer: submitComposerInternal, currentUser, refreshCurrentUserFromBackend, toast
})
const { appendExpenseQueryRiskToConversation, appendReviewRiskBriefToConversation, buildApplicationDraftSummaryItems, buildApplicationPreviewFooterText, buildMessageBubbleClass, buildReviewNextStepRichCopyForMessage, canOpenDraftDetail, closeReviewNextStepConfirm, confirmReviewNextStepSubmit, copyAssistantMessage, isApplicationDraftPayload, isMessageFeedbackSelected, openApplicationDraftDetail, openReviewNextStepConfirm, queryDraftByClaimNo, resolveApplicationDraftStatusLabel, resolveApplicationPreviewMissingFields, resolveReimbursementDraftClaimNo, shouldShowAssistantMessageActions, shouldShowDraftSavedCard, speakAssistantMessage, submitOperationFeedbackForMessage } = useTravelReimbursementMessageActions({
activeSessionType, buildMessageActionRows, conversationId, createMessage, currentInsight, currentUser, draftClaimId, emit, getHandleReviewActionInternal: () => handleReviewActionInternal, latestReviewMessage, linkedRequest, messages, nextStepConfirmDialog, nextTick, persistSessionState, props, resolveActiveClaimId, resolveCurrentUserId, reviewActionBusy, router, scrollToBottom, submitComposer, submitting, toast
})
const { continueStewardApplicationFieldCompletion, handleSuggestedAction, isSuggestedActionSelected, runShortcut } = useTravelReimbursementSuggestedActions({
applicationPreviewEditor, attachedFiles, buildExpenseSceneSelectionActions, buildExpenseSceneSelectionMessage, commitApplicationPreviewEditor, composerDraft, composerFilesExpanded, composerTextareaRef, composerUploadIntent, createMessage, currentUser, draftClaimId, emit, fetchExpenseClaims, handleGuidedShortcut, handleGuidedSuggestedAction, handleSceneSelectionApplicationGate, lockSuggestedActionMessage, mergeFilesWithLimit, messages, nextTick, openApplicationPreviewEditor: openApplicationPreviewEditorFromUi, persistSessionState, resolveApplicationPreviewMissingFields, reviewActionBusy, router, scrollToBottom, sessionSwitchBusy, startExpenseSceneSelectionAfterIntentConfirmation, submitComposer, submitComposerInternal, submitting, switchSessionType, toast, adjustComposerTextareaHeight
})
const {
canShowTravelCalculator,
openTravelCalculator,
submitTravelCalculator,
toggleTravelCalculator
} = useTravelReimbursementCreateViewTravelCalculator({
SESSION_TYPE_EXPENSE,
activeSessionType,
closeTravelCalculator,
openTravelCalculatorInternal,
submitTravelCalculatorInternal,
toggleTravelCalculatorInternal,
travelCalculatorOpen
})
const isReviewOverviewDrawer = computed(() => reviewDrawerMode.value === REVIEW_DRAWER_MODE_REVIEW)
const {
emitCloseAfterLeave,
handleExpenseQueryRecordClick,
maybeFinalizeDeferredClose,
openDeleteSessionDialog,
openExpenseQueryRecord,
closeDeleteSessionDialog,
confirmDeleteCurrentSession,
requestCloseWorkbench,
setExpenseQueryPage,
shiftExpenseQueryPage
} = useTravelReimbursementCreateViewControls({
activeSessionType,
attachedFiles,
clearAssistantSessionSnapshot,
closeAfterBusy,
conversationId,
deleteConversation,
deleteSessionBusy,
deleteSessionDialogOpen,
draftClaimId,
emitClose: () => emit('close'),
getExpenseQueryActivePage,
getExpenseQueryTotalPages,
persistSessionState,
resetCurrentSessionState,
reviewActionBusy,
router,
resolveCurrentUserId,
sessionSwitchBusy,
submitComposer,
submitting,
toast,
workbenchVisible
})
useTravelReimbursementCreateViewLifecycle({
activeFlowSteps, activeReviewPanelScope, activeReviewPayload, activeSessionType, adjustComposerTextareaHeight, attachedFiles, clearExpenseSessionForDeletedClaim, clearStewardThinkingTimers, closeAfterBusy, composerDraft, composerFilesExpanded, composerUploadIntent, conversationId, currentInsight, currentUser, draftClaimId, guidedFlowState, handleComposerDatePickerOutside, hasInsightPanelContent, insightPanelCollapsed, linkedRequest, maybeFinalizeDeferredClose, mergeFilesWithLimit, messages, persistSessionState, props, rememberFilePreviews, resetReviewDrawerFromPayload, resolveActiveClaimId, restorePersistedDraftAttachmentPreviews, reviewActionBusy, reviewDocumentDrawerAvailable, reviewDrawerMode, reviewFilePreviews, reviewFlowDrawerAvailable, reviewRiskDrawerAvailable, scrollToBottom, sessionSwitchBusy, startFlowTick, stewardState, stopAttachmentRuntime, stopFlowRuntime, submitComposer, submitting, toast, workbenchVisible, REVIEW_DRAWER_MODE_DOCUMENTS, REVIEW_DRAWER_MODE_FLOW, REVIEW_DRAWER_MODE_REVIEW, REVIEW_DRAWER_MODE_RISK, SESSION_TYPE_EXPENSE
})
scrollHandlers = useTravelReimbursementCreateViewScroll({
COMPOSER_MAX_ROWS,
COMPOSER_TEXTAREA_HEIGHT,
composerTextareaRef,
messageListRef,
nextTick,
reviewActionBusy,
sessionSwitchBusy,
submitComposer,
submitting
})
sessionCleanupHandlers = useTravelReimbursementCreateViewSessionCleanup({
SESSION_TYPE_EXPENSE,
activeSessionType,
applySessionState,
buildEmptySessionState,
clearAssistantSessionSnapshot,
resetFlowRun,
resetGuidedFlowState,
resolveActiveClaimId,
resolveCurrentUserId,
sessionSnapshots,
toast
})
function replaceMessage(messageId, nextMessage) {
const index = messages.value.findIndex((item) => item.id === messageId)
if (index === -1) {
messages.value.push(nextMessage)
return
}
messages.value.splice(index, 1, nextMessage)
}
const { submitStewardPlan, clearStewardThinkingTimers } = useStewardPlanFlow({
activeSessionType,
attachedFiles,
composerDraft,
conversationId,
currentUser,
fileInputRef,
messages,
createMessage,
fetchStewardPlan,
fetchStewardPlanStream,
nextTick,
persistSessionState,
replaceMessage,
scrollToBottom,
adjustComposerTextareaHeight,
executeStewardSuggestedAction: (message, action) => handleSuggestedAction(message, action),
submitting,
reviewActionBusy,
sessionSwitchBusy,
stewardState,
toast
})
suggestedActionLockHandlers = useTravelReimbursementCreateViewSuggestedActionLock({
messages,
persistSessionState,
resolveApplicationPreviewRows
})
const {
switchReviewDrawerMode,
switchToReviewOverviewDrawer,
toggleInsightPanel,
toggleReviewDocumentDrawer,
toggleReviewFlowDrawer,
toggleReviewRiskDrawer
} = useTravelReimbursementCreateViewDrawerControls({
REVIEW_DRAWER_MODE_DOCUMENTS,
REVIEW_DRAWER_MODE_FLOW,
REVIEW_DRAWER_MODE_REVIEW,
REVIEW_DRAWER_MODE_RISK,
hasInsightPanelContent,
insightPanelCollapsed,
reviewDocumentDrawerAvailable,
reviewDrawerMode,
reviewFlowDrawerAvailable,
reviewOverviewDrawerAvailable,
reviewRiskDrawerAvailable
})
const { closeApplicationSubmitConfirm, confirmApplicationSubmit, openApplicationSubmitConfirm, resolveStewardMissingFieldItems } = useTravelReimbursementApplicationSubmitConfirm({
activeSessionType, applicationSubmitConfirmDialog, buildStewardFieldItems, createMessage, emitDraftSaved: (payload) => emit('draft-saved', payload), formatStewardMissingFieldList, formatStewardOntologyFields, linkedRequest, messages, nextTick, persistSessionState, reviewActionBusy, scrollToBottom, submitComposer, submitting, toast
})
const { handleApplicationSubmitConfirmationText, handleStewardRuntimeDecision } = useTravelReimbursementStewardRuntimeDecision({
APPLICATION_PREVIEW_FIELD_ACTION_SET, activeSessionType, adjustComposerTextareaHeight, applicationSubmitConfirmDialog, attachedFiles, composerDraft, confirmApplicationSubmit, continueStewardApplicationFieldCompletion, conversationId, createMessage, handleSuggestedAction, isStewardSession, messages, nextTick, persistSessionState, props, reviewActionBusy, resolveCurrentUserId, scrollToBottom, stewardState, submitComposer, submitComposerInternal, submitStewardPlan, submitting
})
const { handleReviewActionInternal, handleSaveDraftDirectlyInternal, saveInlineReviewChangesInternal } = useTravelReimbursementReviewActions({
activeReviewPayload, buildDraftSavedPayload, buildLocalReviewCompletionMessage, buildLocalReviewSavedMessage, buildReviewCorrectionMessage, buildReviewDocumentCorrectionContext, buildReviewDocumentCorrectionMessage, buildReviewFormValues, buildReviewRiskItems, buildReviewSubmitUserText, buildLocallySyncedReviewPayload, cloneReviewDocumentDrafts, cloneReviewEditFields, commitInlineReviewEditor, createMessage, currentInsight, currentUser, emit, latestReviewMessage, linkedRequest, mergeInlineReviewFields, messages, nextTick, reviewActionBusy, reviewDocumentBaseDrafts, reviewDocumentDrafts, reviewHasUnsavedChanges, reviewInlineBaseFields, reviewInlineBaseForm, reviewInlineEditorKey, reviewInlineForm, reviewInlinePendingFiles, scrollToBottom, sessionSwitchBusy, submitComposer, submitting
})
const { askHotKnowledgeQuestion, buildReviewPlainFollowupForMessage, canUseInlineSaveDraft, handleAssistantMarkdownClick, handleInlineSaveDraft, handleReviewAction, handleSaveDraftDirectly, isDraftSavedReviewMessage, saveInlineReviewChanges, submitComposer: submitComposerMessageHandler } = useTravelReimbursementCreateViewMessageHandlers({
APPLICATION_SUBMIT_HREF, REVIEW_NEXT_STEP_HREF, REVIEW_QUICK_EDIT_HREF, REVIEW_RISK_PANEL_HREF_PREFIX, REVIEW_DRAWER_MODE_REVIEW, REVIEW_DRAWER_MODE_RISK, activeReviewPayload, buildReviewPlainFollowupCopy, confirmPendingAttachmentAssociationInternal, draftClaimId, handleApplicationSubmitConfirmationText, handleGuidedComposerSubmit, handleReviewActionInternal, handleSaveDraftDirectlyInternal, handleStewardRuntimeDecision, handleInlineSaveDraftDirectly: handleSaveDraftDirectlyInternal, handleGuidedStewardPlan: (options) => isStewardSession.value && !options.skipStewardPlan && submitStewardPlan(options), isKnowledgeSession, openApplicationSubmitConfirm, openReviewNextStepConfirm, reviewActionBusy, reviewHasUnsavedChanges, reviewOverviewDrawerAvailable, reviewRiskDrawerAvailable, resolveActiveClaimId, resolveReviewSaveDraftAction, router, saveInlineReviewChangesInternal, sessionSwitchBusy, submitComposerInternal, submitting, switchReviewDrawerMode, toast
})
submitComposerFromMessageHandlers = submitComposerMessageHandler
const { insightPanelUi, messageItemUi } = useTravelReimbursementCreateViewUi({
ASSISTANT_DISPLAY_NAME, DATE_INPUT_FORMAT, REVIEW_SCENE_OPTIONS, REVIEW_SCENE_OTHER_OPTION, activeFlowSteps, activeReviewDocument, activeReviewDocumentIndex, activeReviewDocumentPreview, activeReviewPayload, activeSessionType, aiAvatar, appendExpenseQueryRiskToConversation, appendReviewRiskBriefToConversation, applicationPreviewEditor, askHotKnowledgeQuestion, buildApplicationDraftSummaryItems, buildApplicationPreviewFooterText, buildExpenseQueryHint, buildExpenseQueryWindowLabel, buildMessageBubbleClass, buildReviewMainMessageText, buildReviewNextStepRichCopyForMessage, buildReviewPlainFollowupForMessage, buildReviewPrimaryButtonLabel, canApplyApplicationPreviewDateSelection, canOpenDraftDetail, canPreviewActiveReviewDocument, canUseInlineSaveDraft, clearInlineReviewFieldError, commitApplicationPreviewDateEditor, commitApplicationPreviewEditor, commitInlineReviewEditor, copyAssistantMessage, currentInsight, currentIntentLabel, deleteSessionBusy, flowOverallStatusText, flowOverallStatusTone, flowRefreshBusy, flowRunId, flowTotalDurationText, formatFlowStepDuration, getExpenseQueryActivePage, getExpenseQueryTotalPages, getExpenseQueryVisibleRecords, goReviewDocument, handleAssistantMarkdownClick, handleExpenseQueryRecordClick, handleInlineSaveDraft, handleReviewAction, handleSuggestedAction, isApplicationDraftPayload, isApplicationPreviewDateEditorOpen, isApplicationPreviewEditing, isKnowledgeSession, isMessageFeedbackSelected, isReviewDocumentDrawer, isReviewFlowDrawer, isReviewOverviewDrawer, isReviewRiskDrawer, isSuggestedActionSelected, openActiveReviewDocumentPreview, openApplicationDraftDetail, openApplicationPreviewEditorFromUi, openInlineReviewEditor, refreshFlowRunDetail, renderMarkdown, resolveApplicationDraftStatusLabel, resolveApplicationPreviewEditorControl, resolveApplicationPreviewEditorOptions, resolveApplicationPreviewMissingFields, resolveApplicationPreviewRows, resolveFlowStepDetail, resolveFlowStepStatusLabel, resolveKnowledgeRankLabel, resolveKnowledgeRankTone, resolveReimbursementDraftClaimNo, resolveReviewFooterActions, resolveStewardMissingFieldItems, reviewActionBusy, reviewCategoryOptions, reviewDocumentCount, reviewDocumentDrawerAvailable, reviewDocumentDrawerIcon, reviewDrawerMode, reviewDrawerTitle, reviewFactCards, reviewFlowDrawerAvailable, reviewFlowDrawerIcon, reviewHasUnsavedChanges, reviewInlineEditorKey, reviewInlineErrors, reviewInlineForm, reviewInlinePendingFiles, reviewOtherCategoryOpen, reviewOtherCategoryOptions, reviewOverviewDrawerAvailable, reviewPanelConfidence, reviewRiskDrawerAvailable, reviewRiskDrawerIcon, reviewRiskEmpty, reviewRiskItems, reviewRiskSummary, reviewSelectedOtherCategory, runShortcut, saveInlineReviewChanges, selectInlineScene, selectReviewCategory, selectReviewOtherCategory, sessionSwitchBusy, setApplicationPreviewDateMode, setExpenseQueryPage, shiftExpenseQueryPage, shouldShowAssistantMessageActions, shouldShowDraftSavedCard, speakAssistantMessage, submitOperationFeedbackForMessage, submitting, switchToReviewOverviewDrawer, toggleReviewDocumentDrawer, toggleReviewFlowDrawer, toggleReviewRiskDrawer, userAvatar, visibleFlowSteps
})
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, isStewardSession, showStewardInitialRecognition, 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,
workbenchVisible, reviewPanelConfidence, reviewRiskSummary, reviewRiskItems, reviewRiskEmpty, recognizedNarratives, reviewRecognitionNotes, reviewDocumentSummaries, reviewDocumentCount, reviewDocumentDirty, reviewHasUnsavedChanges,
travelCalculatorOpen, travelCalculatorBusy, travelCalculatorError, travelCalculatorResult, travelCalculatorForm, travelCalculatorCanSubmit, canShowTravelCalculator, deleteSessionDialogOpen, applicationSubmitConfirmDialog, applicationPreviewEditor, nextStepConfirmDialog, reviewActionBusy, deleteSessionBusy, documentPreviewDialog, shortcuts,
resolveReviewMissingSlotCards, resolveReviewRiskBriefs, buildReviewHeadline, buildReviewSubline, buildReviewStateLabel, buildReviewStateTone, buildReviewPlainFollowupCopy, buildReviewPlainFollowupForMessage, buildReviewNextStepRichCopyForMessage, buildMessageBubbleClass, resolveReviewFooterActions, resolveReviewSaveDraftAction, buildReviewPrimaryButtonLabel, buildReviewMainMessageText,
renderMarkdown, buildExpenseQueryWindowLabel, buildExpenseQueryHint, getExpenseQueryActivePage, getExpenseQueryTotalPages, getExpenseQueryVisibleRecords, resolveDocumentPreview, triggerFileUpload, applyComposerDateSelection, handleFilesChange, handleComposerInput, handleComposerEnter, runShortcut, runWelcomeQuickAction: runShortcut, handleSuggestedAction, isSuggestedActionSelected, askHotKnowledgeQuestion, resolveKnowledgeRankLabel, resolveKnowledgeRankTone,
refreshFlowRunDetail, formatFlowStepDuration, resolveFlowStepStatusLabel, resolveFlowStepDetail, toggleInsightPanel, openTravelCalculator, toggleTravelCalculator, closeTravelCalculator, submitTravelCalculator, switchToReviewOverviewDrawer, toggleReviewDocumentDrawer, toggleReviewRiskDrawer, toggleReviewFlowDrawer, toggleAttachedFilesExpanded, removeAttachedFile, clearAttachedFiles,
requestCloseWorkbench, emitCloseAfterLeave, handleAssistantModalAfterEnter, openExpenseQueryRecord, handleExpenseQueryRecordClick, setExpenseQueryPage, shiftExpenseQueryPage, openDeleteSessionDialog, closeDeleteSessionDialog, confirmDeleteCurrentSession, openInlineReviewEditor, closeInlineReviewEditor, commitInlineReviewEditor, clearInlineReviewFieldError, selectInlineScene, selectReviewCategory, selectReviewOtherCategory,
queryDraftByClaimNo, appendReviewRiskBriefToConversation, appendExpenseQueryRiskToConversation, goReviewDocument, openActiveReviewDocumentPreview, closeDocumentPreview, saveInlineReviewChanges, submitComposer, handleAssistantMarkdownClick, handleReviewAction, handleSaveDraftDirectly, resolveApplicationPreviewRows, resolveApplicationPreviewEditorControl, resolveApplicationPreviewEditorOptions, isApplicationPreviewEditing, isApplicationPreviewDateEditorOpen, openApplicationPreviewEditor: openApplicationPreviewEditorFromUi, commitApplicationPreviewEditor, commitApplicationPreviewDateEditor, cancelApplicationPreviewEditor, setApplicationPreviewDateMode, canApplyApplicationPreviewDateSelection, handleApplicationPreviewEditorKeydown, buildApplicationPreviewFooterText, isApplicationDraftPayload, resolveApplicationDraftStatusLabel, buildApplicationDraftSummaryItems, shouldShowDraftSavedCard, resolveReimbursementDraftClaimNo, openApplicationDraftDetail, shouldShowAssistantMessageActions, copyAssistantMessage, speakAssistantMessage, isMessageFeedbackSelected, submitOperationFeedbackForMessage, closeApplicationSubmitConfirm, confirmApplicationSubmit, closeReviewNextStepConfirm, confirmReviewNextStepSubmit, isDraftSavedReviewMessage, canUseInlineSaveDraft, handleInlineSaveDraft
}
}
}