Files
X-Financial/web/src/views/scripts/useTravelReimbursementCreateViewLifecycle.js
caoxiaozhu d5a8f84703 refactor(web): 应用外壳/差旅详情/报销创建视图适配主题与多 task
- AppShellRouteView/useAppShell 适配主题皮肤与会话入口
- TravelRequestDetailView/travelRequestDetailSetup 差旅详情适配,travel-request-detail-view.css 调整
- TravelReimbursementCreateView/useTravelReimbursementCreateViewLifecycle 创建视图适配
- 更新 app-shell-financial-assistant-entry/travel-request-detail-risk-advice 测试
2026-06-26 22:42:29 +08:00

258 lines
6.9 KiB
JavaScript

import { nextTick, onBeforeUnmount, onMounted, watch } from 'vue'
import {
buildLocalApplicationPreviewMessage,
normalizeApplicationPreview
} from '../../utils/expenseApplicationPreview.js'
import {
MAX_ATTACHMENTS,
VISIBLE_ATTACHMENT_CHIPS,
buildReviewFilePreviewsFromReviewPayload
} from './travelReimbursementAttachmentModel.js'
import {
SESSION_TYPE_EXPENSE,
createMessage,
buildWelcomeInsight
} from './travelReimbursementConversationModel.js'
export function 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,
startFlowTick,
stewardState,
stopAttachmentRuntime,
stopFlowRuntime,
submitComposer,
submitting,
sessionSwitchBusy,
toast,
workbenchVisible,
REVIEW_DRAWER_MODE_DOCUMENTS,
REVIEW_DRAWER_MODE_FLOW,
REVIEW_DRAWER_MODE_REVIEW,
REVIEW_DRAWER_MODE_RISK,
SESSION_TYPE_EXPENSE: sessionTypeExpense = SESSION_TYPE_EXPENSE
}) {
watch(
() => [activeReviewPayload.value, activeReviewPanelScope.value],
([payload]) => {
rememberFilePreviews(buildReviewFilePreviewsFromReviewPayload(payload))
const shouldKeepFlowDrawer = reviewDrawerMode.value === REVIEW_DRAWER_MODE_FLOW && activeFlowSteps.value.length > 0
resetReviewDrawerFromPayload(payload)
if (shouldKeepFlowDrawer) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_FLOW
}
},
{ immediate: true }
)
watch(
() => hasInsightPanelContent.value,
(available) => {
if (!available) {
insightPanelCollapsed.value = false
}
}
)
watch(
() => reviewDocumentDrawerAvailable.value,
(available) => {
if (!available && reviewDrawerMode.value === REVIEW_DRAWER_MODE_DOCUMENTS) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
}
}
)
watch(
() => reviewRiskDrawerAvailable.value,
(available) => {
if (!available && reviewDrawerMode.value === REVIEW_DRAWER_MODE_RISK) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
}
}
)
watch(
() => reviewFlowDrawerAvailable.value,
(available) => {
if (!available && reviewDrawerMode.value === REVIEW_DRAWER_MODE_FLOW) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
}
}
)
watch(
() => [activeSessionType.value, activeFlowSteps.value.length],
([, activeCount], [, previousActiveCount] = []) => {
if (activeCount <= 0 || previousActiveCount > 0) {
return
}
reviewDrawerMode.value = REVIEW_DRAWER_MODE_FLOW
insightPanelCollapsed.value = false
}
)
watch(
() => composerDraft.value,
() => {
nextTick(adjustComposerTextareaHeight)
}
)
watch(
() => ({
sessionType: activeSessionType.value,
conversationId: conversationId.value,
stewardState: stewardState.value,
draftClaimId: draftClaimId.value,
messages: messages.value,
currentInsight: currentInsight.value,
reviewFilePreviews: reviewFilePreviews.value,
composerDraft: composerDraft.value,
composerUploadIntent: composerUploadIntent.value,
guidedFlowState: guidedFlowState.value,
insightPanelCollapsed: insightPanelCollapsed.value
}),
() => {
persistSessionState()
},
{ deep: true }
)
watch(
() => [activeSessionType.value, resolveActiveClaimId()],
([sessionType, claimId]) => {
if (sessionType !== sessionTypeExpense || !claimId) {
return
}
void restorePersistedDraftAttachmentPreviews(claimId)
},
{ immediate: true }
)
watch(
() => props.invalidatedDraftClaimId,
(claimId) => {
clearExpenseSessionForDeletedClaim(claimId)
},
{ immediate: true }
)
watch(
() => workbenchVisible.value,
(visible) => {
if (visible) {
scrollToBottom()
} else {
maybeFinalizeDeferredClose()
}
}
)
watch(
() => [submitting.value, reviewActionBusy.value, sessionSwitchBusy.value, workbenchVisible.value],
() => {
maybeFinalizeDeferredClose()
}
)
watch(
() => props.reopenToken,
(token, previousToken) => {
if (token === previousToken) {
return
}
closeAfterBusy.value = false
workbenchVisible.value = true
nextTick(() => {
adjustComposerTextareaHeight()
scrollToBottom()
})
}
)
onMounted(() => {
document.addEventListener('click', handleComposerDatePickerOutside)
startFlowTick()
nextTick(() => {
workbenchVisible.value = true
nextTick(() => {
adjustComposerTextareaHeight()
scrollToBottom()
})
})
currentInsight.value =
currentInsight.value
|| buildWelcomeInsight(props.entrySource, linkedRequest.value, activeSessionType.value, currentUser.value)
if (props.initialApplicationPreview && typeof props.initialApplicationPreview === 'object') {
const applicationPreview = normalizeApplicationPreview(props.initialApplicationPreview)
const draftPayload = props.initialDraftPayload && typeof props.initialDraftPayload === 'object'
? props.initialDraftPayload
: null
messages.value.push(createMessage('assistant', buildLocalApplicationPreviewMessage(applicationPreview), [], {
meta: ['修改申请'],
applicationPreview,
draftPayload
}))
persistSessionState()
}
if (props.initialPrompt?.trim() || props.initialFiles.length) {
const initialMerge = mergeFilesWithLimit([], Array.from(props.initialFiles), MAX_ATTACHMENTS)
composerDraft.value = props.initialPrompt.trim()
attachedFiles.value = initialMerge.files
composerFilesExpanded.value = initialMerge.files.length > VISIBLE_ATTACHMENT_CHIPS
if (initialMerge.overflowCount > 0) {
toast(`一次最多上传 ${MAX_ATTACHMENTS} 份附件,已保留前 ${MAX_ATTACHMENTS} 份。`)
}
nextTick(() => {
adjustComposerTextareaHeight()
})
if (props.initialPromptAutoSubmit !== false) {
submitComposer()
}
}
})
onBeforeUnmount(() => {
document.removeEventListener('click', handleComposerDatePickerOutside)
clearStewardThinkingTimers()
stopFlowRuntime()
stopAttachmentRuntime()
})
}