feat: 扩展风险规则体系、审批动态路由与预算中心列表化改造
- 新增 25+ 条风险规则(预算/报销/申请/通用类),完善风险规则模拟与反馈发布机制 - 引入费用审批动态路由、平台风险分级、预审与风险阶段管理 - 预算中心列表化改造,优化票据夹仪表盘与数字员工工作看板 - 新增 Hermes 风险线索收集器、Agent 链路追踪中心 - 扩展数字员工能力库(18 个领域 Skill)与交通费用自动预估 - 完善报销申请快速预览、权限控制与前端测试覆盖
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
buildModelRefinedApplicationPreview,
|
||||
shouldUseLocalApplicationPreview
|
||||
} from '../../utils/expenseApplicationPreview.js'
|
||||
import { waitForMockApplicationTransportQuote } from '../../utils/expenseApplicationEstimate.js'
|
||||
import { fetchOntologyParse } from '../../services/ontology.js'
|
||||
import { buildExpenseApplicationOntologyContext } from '../../utils/expenseApplicationOntology.js'
|
||||
import { calculateTravelReimbursement } from '../../services/reimbursements.js'
|
||||
@@ -79,6 +80,7 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
persistSessionState,
|
||||
props,
|
||||
recognizeOcrFiles,
|
||||
refreshCurrentUserFromBackend,
|
||||
refreshFlowRunDetail,
|
||||
rememberFilePreviews,
|
||||
replaceMessage,
|
||||
@@ -339,8 +341,18 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
]
|
||||
}
|
||||
|
||||
async function buildApplicationPreviewWithModelReview(rawText) {
|
||||
async function resolveApplicationPreviewUser() {
|
||||
const user = currentUser.value || {}
|
||||
if (String(user.position || '').trim() || typeof refreshCurrentUserFromBackend !== 'function') {
|
||||
return user
|
||||
}
|
||||
|
||||
await refreshCurrentUserFromBackend({ silent: true })
|
||||
return currentUser.value || user
|
||||
}
|
||||
|
||||
async function buildApplicationPreviewWithModelReview(rawText) {
|
||||
const user = await resolveApplicationPreviewUser()
|
||||
const localPreview = buildLocalApplicationPreview(rawText, user)
|
||||
|
||||
const enrichWithPolicyEstimate = async (preview) => {
|
||||
@@ -349,6 +361,12 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
return preview
|
||||
}
|
||||
try {
|
||||
const fields = preview?.fields || {}
|
||||
await waitForMockApplicationTransportQuote({
|
||||
transportMode: fields.transportMode,
|
||||
location: fields.location,
|
||||
time: fields.time
|
||||
})
|
||||
const result = await calculateTravelReimbursement(estimateRequest.payload)
|
||||
return applyApplicationPolicyEstimateResult(preview, result, user)
|
||||
} catch (error) {
|
||||
@@ -548,14 +566,14 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
startFlowStep('application-review-preview', {
|
||||
title: '申请信息核对',
|
||||
tool: 'ontology.application_review',
|
||||
detail: '正在进行申请信息模型复核...'
|
||||
detail: '正在复核申请信息,并查询交通票价...'
|
||||
})
|
||||
if (!options.skipUserMessage) {
|
||||
messages.value.push(createMessage('user', userText, fileNames))
|
||||
}
|
||||
const pendingMessage = createMessage(
|
||||
'assistant',
|
||||
'正在进行申请信息模型复核。本步骤只识别意图和抽取字段,不会创建、更新或保存草稿。',
|
||||
'正在复核申请信息,并查询交通票价,请稍候。',
|
||||
[],
|
||||
{
|
||||
meta: ['模型复核中']
|
||||
@@ -770,7 +788,7 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
isKnowledgeSession.value
|
||||
? '正在整理财务知识答案...'
|
||||
: activeSessionType.value === 'application'
|
||||
? '正在识别并整理申请核对信息...'
|
||||
? '正在识别申请信息并查询交通票价...'
|
||||
: activeSessionType.value === 'approval'
|
||||
? '正在查询审核上下文并整理风险提示...'
|
||||
: '正在识别并整理右侧核对信息...'
|
||||
@@ -1037,20 +1055,29 @@ export function useTravelReimbursementSubmitComposer(ctx) {
|
||||
nextTick(scrollToBottom)
|
||||
const resolvedDraftClaimId = String(payload?.result?.draft_payload?.claim_id || draftClaimId.value || '').trim()
|
||||
if (!isKnowledgeSession.value && resolvedDraftClaimId && files.length) {
|
||||
void syncComposerFilesToDraft(resolvedDraftClaimId, files)
|
||||
.then((syncResult) => {
|
||||
const persistComposerFilesToDraft = async () => {
|
||||
try {
|
||||
const syncResult = await syncComposerFilesToDraft(resolvedDraftClaimId, files)
|
||||
persistSessionState()
|
||||
if (detailScopedUpload && Number(syncResult?.uploadedCount || 0) > 0) {
|
||||
if (detailScopedUpload) {
|
||||
emitRequestUpdated?.({
|
||||
claimId: resolvedDraftClaimId,
|
||||
source: 'detail-smart-entry-attachment-sync'
|
||||
source: 'detail-smart-entry-attachment-sync',
|
||||
uploadedCount: Number(syncResult?.uploadedCount || 0),
|
||||
skippedCount: Number(syncResult?.skippedCount || 0)
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
} catch (error) {
|
||||
console.warn('Failed to persist composer attachments to draft claim:', error)
|
||||
toast(error?.message || '票据已归集到草稿,但附件原件保存失败,请在单据详情中重新上传。')
|
||||
})
|
||||
}
|
||||
}
|
||||
const persistTask = persistComposerFilesToDraft()
|
||||
if (detailScopedUpload) {
|
||||
await persistTask
|
||||
} else {
|
||||
void persistTask
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
clearFlowSimulationTimers()
|
||||
|
||||
Reference in New Issue
Block a user