Files
X-Financial/web/src/views/scripts/useTravelReimbursementReviewActions.js

253 lines
9.5 KiB
JavaScript

export function useTravelReimbursementReviewActions(ctx) {
const {
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
} = ctx
function saveInlineReviewChanges() {
if (
!activeReviewPayload.value
|| !reviewHasUnsavedChanges.value
|| submitting.value
|| reviewActionBusy.value
|| sessionSwitchBusy.value
) return
if (reviewInlineEditorKey.value && !commitInlineReviewEditor()) {
return
}
reviewActionBusy.value = true
try {
const fields = mergeInlineReviewFields(reviewInlineBaseFields.value, reviewInlineForm.value)
const nextReviewPayload = buildLocallySyncedReviewPayload(activeReviewPayload.value, reviewInlineForm.value)
const messageText = `${buildLocalReviewSavedMessage(
reviewInlineBaseForm.value,
reviewInlineForm.value,
reviewInlinePendingFiles.value,
reviewDocumentBaseDrafts.value,
reviewDocumentDrafts.value
)} ${buildLocalReviewCompletionMessage(nextReviewPayload)}`
reviewInlineBaseFields.value = cloneReviewEditFields(fields)
reviewInlineBaseForm.value = { ...reviewInlineForm.value }
reviewDocumentBaseDrafts.value = cloneReviewDocumentDrafts(reviewDocumentDrafts.value)
if (latestReviewMessage.value) {
latestReviewMessage.value.reviewPayload = nextReviewPayload
}
if (currentInsight.value?.agent) {
currentInsight.value = {
...currentInsight.value,
agent: {
...currentInsight.value.agent,
reviewPayload: nextReviewPayload
}
}
}
messages.value.push(createMessage('assistant', messageText, [], {
meta: ['本地修改'],
draftPayload: latestReviewMessage.value?.draftPayload || null,
reviewPayload: nextReviewPayload
}))
nextTick(scrollToBottom)
} finally {
reviewActionBusy.value = false
}
}
async function handleReviewAction(message, action) {
const actionType = String(action?.action_type || '').trim()
if (!actionType || submitting.value || reviewActionBusy.value || sessionSwitchBusy.value) return
if (!['save_draft', 'next_step', 'link_to_existing_draft', 'create_new_claim_from_documents'].includes(actionType)) {
return
}
if (reviewInlineEditorKey.value && !commitInlineReviewEditor()) {
return
}
if (['save_draft', 'link_to_existing_draft', 'create_new_claim_from_documents'].includes(actionType)) {
await handleSaveDraftDirectly(message, actionType)
return
}
reviewActionBusy.value = true
try {
const baseFields = reviewInlineBaseFields.value.length
? reviewInlineBaseFields.value
: cloneReviewEditFields(message?.reviewPayload?.edit_fields)
const fields = mergeInlineReviewFields(baseFields, reviewInlineForm.value)
const reviewChangedUserText = reviewHasUnsavedChanges.value
? buildReviewSubmitUserText(
reviewInlineBaseForm.value,
reviewInlineForm.value,
reviewInlinePendingFiles.value,
reviewDocumentBaseDrafts.value,
reviewDocumentDrafts.value
)
: ''
const documentCorrectionMessage = buildReviewDocumentCorrectionMessage(
reviewDocumentBaseDrafts.value,
reviewDocumentDrafts.value
)
const payload = await submitComposer({
rawText: [
reviewHasUnsavedChanges.value ? buildReviewCorrectionMessage(fields) : '',
reviewHasUnsavedChanges.value ? documentCorrectionMessage : '',
'我已核对右侧识别结果,请进入下一步。'
]
.filter(Boolean)
.join('\n'),
userText: reviewChangedUserText || '我确认当前识别结果,继续下一步。',
files: reviewInlinePendingFiles.value,
pendingText: '正在进入下一步...',
systemGenerated: true,
extraContext: {
review_action: actionType,
review_form_values: buildReviewFormValues(fields),
review_document_form_values: buildReviewDocumentCorrectionContext(reviewDocumentDrafts.value)
}
})
if (payload?.result?.draft_payload?.status === 'submitted') {
emit(
'draft-saved',
buildDraftSavedPayload({
draftPayload: payload.result.draft_payload,
reviewPayload: payload?.result?.review_payload || message?.reviewPayload || activeReviewPayload.value,
inlineState: reviewInlineForm.value,
linkedRequest: linkedRequest.value,
currentUser: currentUser.value,
riskItems: buildReviewRiskItems(payload?.result?.review_payload || message?.reviewPayload || activeReviewPayload.value)
})
)
}
} finally {
reviewActionBusy.value = false
}
}
async function handleSaveDraftDirectly(message, actionType = 'save_draft') {
reviewActionBusy.value = true
const actionConfig = {
save_draft: {
rawText: '请按当前已识别信息先保存草稿,缺失字段后续再补。',
pendingText: '正在保存当前草稿...',
successMeta: '草稿已保存',
successMessage: (payload) => {
const claimNo = String(payload?.result?.draft_payload?.claim_no || '').trim()
return claimNo ? `草稿已保存,单号:${claimNo}` : '草稿保存完成'
}
},
link_to_existing_draft: {
rawText: '请把当前上传的票据合并到现有报销草稿中。',
pendingText: '正在关联到现有草稿...',
successMeta: '已关联草稿',
successMessage: (payload) => {
const claimNo = String(payload?.result?.draft_payload?.claim_no || '').trim()
return claimNo ? `已关联到草稿 ${claimNo}` : '已关联到现有草稿'
}
},
create_new_claim_from_documents: {
rawText: '请基于当前上传的多张票据,单独建立一张新的报销草稿。',
pendingText: '正在建立新的报销草稿...',
successMeta: '新草稿已建立',
successMessage: (payload) => {
const claimNo = String(payload?.result?.draft_payload?.claim_no || '').trim()
return claimNo ? `已建立新草稿 ${claimNo}` : '已建立新的报销草稿'
}
}
}[actionType] || {
rawText: '请按当前已识别信息先保存草稿,缺失字段后续再补。',
pendingText: '正在保存当前草稿...',
successMeta: '草稿已保存',
successMessage: () => '草稿保存完成'
}
try {
const baseFields = reviewInlineBaseFields.value.length
? reviewInlineBaseFields.value
: cloneReviewEditFields(message?.reviewPayload?.edit_fields)
const fields = mergeInlineReviewFields(baseFields, reviewInlineForm.value)
const payload = await submitComposer({
rawText: actionConfig.rawText,
userText: '',
skipUserMessage: true,
files: reviewInlinePendingFiles.value,
pendingText: actionConfig.pendingText,
systemGenerated: true,
extraContext: {
review_action: actionType,
review_form_values: buildReviewFormValues(fields),
review_document_form_values: buildReviewDocumentCorrectionContext(reviewDocumentDrafts.value)
}
})
if (payload?.result?.draft_payload?.claim_no) {
emit(
'draft-saved',
buildDraftSavedPayload({
draftPayload: payload.result.draft_payload,
reviewPayload: payload?.result?.review_payload || message?.reviewPayload || activeReviewPayload.value,
inlineState: reviewInlineForm.value,
linkedRequest: linkedRequest.value,
currentUser: currentUser.value,
riskItems: buildReviewRiskItems(payload?.result?.review_payload || message?.reviewPayload || activeReviewPayload.value)
})
)
}
nextTick(scrollToBottom)
} catch (error) {
messages.value.push(createMessage('assistant', '保存失败,请稍后重试。', [], { meta: ['错误'] }))
nextTick(scrollToBottom)
} finally {
reviewActionBusy.value = false
}
}
return {
handleReviewActionInternal: handleReviewAction,
handleSaveDraftDirectlyInternal: handleSaveDraftDirectly,
saveInlineReviewChangesInternal: saveInlineReviewChanges
}
}