const DRAFT_DELETION_ACTION_PATTERN = /删除|删掉|删了|移除|作废|撤销/ const DRAFT_DELETION_TARGET_PATTERN = ( /草稿|这个单据|这张单据|当前单据|当前申请|当前报销|刚才保存的草稿|刚才的草稿|上面的单据|最近的单据|申请单|报销单/ ) const NON_DRAFT_DELETE_TARGET_PATTERN = /附件|票据|发票|图片|文件|明细|费用行/ const DELETABLE_DRAFT_STATUS = new Set(['', 'draft', 'pending', '待提交', '草稿']) const SUBMITTED_OR_FINAL_STATUS = new Set([ 'submitted', 'approved', 'completed', 'paid', 'archived', 'deleted', 'rejected', 'returned', '审批中', '已审批', '已完成', '已付款', '已归档', '已删除', '已驳回', '已退回' ]) function normalizeCompactText(value = '') { return String(value || '').replace(/\s+/g, '').trim() } function normalizeDraftDocumentType(payload = {}, claimNo = '') { const rawType = String(payload.document_type || payload.documentType || payload.draft_type || payload.draftType || '').trim() if (/application|expense_application|申请/.test(rawType)) { return 'application' } if (/reimbursement|expense|报销/.test(rawType)) { return 'reimbursement' } return /^A/i.test(String(claimNo || '').trim()) ? 'application' : 'reimbursement' } function normalizeDraftPayload(payload = null, sourceText = '') { if (!payload || typeof payload !== 'object') { return null } const claimId = String(payload.claim_id || payload.claimId || payload.id || '').trim() const claimNo = String(payload.claim_no || payload.claimNo || payload.document_no || payload.documentNo || '').trim() if (!claimId && !claimNo) { return null } const status = String(payload.status || payload.status_label || payload.statusLabel || '').trim() if (SUBMITTED_OR_FINAL_STATUS.has(status.toLowerCase()) || SUBMITTED_OR_FINAL_STATUS.has(status)) { return null } if (!DELETABLE_DRAFT_STATUS.has(status.toLowerCase()) && !DELETABLE_DRAFT_STATUS.has(status) && !/草稿/.test(sourceText)) { return null } return { claimId, claimNo, status: status || 'draft', documentType: normalizeDraftDocumentType(payload, claimNo) } } function extractDraftPayloadFromSuggestedActions(message = {}) { const actions = Array.isArray(message?.suggestedActions) ? message.suggestedActions : [] for (const action of [...actions].reverse()) { const actionType = String(action?.action_type || action?.actionType || '').trim() if (actionType !== 'open_application_detail') { continue } const payload = normalizeDraftPayload(action.payload, String(message.content || message.text || '')) if (payload) { return payload } } return null } export function isWorkbenchDraftDeletionIntent(prompt = '') { const compact = normalizeCompactText(prompt) if (!compact || !DRAFT_DELETION_ACTION_PATTERN.test(compact)) { return false } if (NON_DRAFT_DELETE_TARGET_PATTERN.test(compact) && !/草稿|单据|申请单|报销单/.test(compact)) { return false } return DRAFT_DELETION_TARGET_PATTERN.test(compact) } export function resolveLatestWorkbenchDraftPayload(messages = []) { const safeMessages = Array.isArray(messages) ? messages : [] for (const message of [...safeMessages].reverse()) { const sourceText = String(message?.content || message?.text || '') const actionPayload = extractDraftPayloadFromSuggestedActions(message) if (actionPayload) { return actionPayload } const draftPayload = normalizeDraftPayload(message?.draftPayload, sourceText) if (draftPayload) { return draftPayload } } return null } export function buildWorkbenchDraftDeletionGuidance(draftPayload = {}) { const claimNo = String(draftPayload.claimNo || draftPayload.claim_no || '').trim() const claimId = String(draftPayload.claimId || draftPayload.claim_id || '').trim() const documentType = String(draftPayload.documentType || draftPayload.document_type || 'reimbursement').trim() const reference = claimNo || claimId || '最近这张草稿' return { content: [ '### 已识别到您想删除草稿', `我找到了最近这张草稿:**${reference}**。`, '删除草稿会影响单据和附件关联,我不会直接替您删除。请先打开详情页,在详情页点击 **删除草稿** 并完成二次确认。' ].join('\n\n'), suggestedActions: [{ label: claimNo ? `查看草稿 ${claimNo}` : '查看草稿详情', description: '打开详情页后可点击删除草稿并二次确认。', icon: 'mdi mdi-open-in-new', action_type: 'open_application_detail', payload: { claim_id: claimId, claim_no: claimNo, document_type: documentType } }] } }