feat(web): 工作台 AI 模式报销预审与文档查询模型拆分

- 新增 aiApplicationPrecheckModel/aiDocumentQueryModel/aiApplicationPreviewActions/aiConversationHtmlRenderer 四个独立模型与服务,按职责从主组件拆出
- PersonalWorkbenchAiMode 接入拆分后的预审、文档查询与 HTML 渲染逻辑,配合 markdown 工具增强结构化展示
- 文档中心与归档筛选、风险可见性、申请预览等工具同步适配,补充对应单元测试
- 新增 AI 文档卡片背景资源
This commit is contained in:
caoxiaozhu
2026-06-20 10:17:37 +08:00
parent 3d69f8501f
commit 304bbe1fd4
26 changed files with 3974 additions and 117 deletions

View File

@@ -756,14 +756,6 @@ export function buildApplicationPolicyEstimateRequest(preview = {}, currentUser
const transportMode = String(fields.transportMode || '').trim()
const shouldEstimate = /差旅|住宿|交通/.test(applicationType) || Boolean(transportMode)
if (/差旅|出差/.test(applicationType) && !transportMode) {
return {
canCalculate: false,
reason: '缺少出行方式',
payload: null
}
}
if (!shouldEstimate || !days || !location) {
return {
canCalculate: false,
@@ -794,12 +786,8 @@ export function buildApplicationPolicyEstimateRequest(preview = {}, currentUser
}
export function applyApplicationPolicyEstimateResult(preview = {}, result = {}, currentUser = {}) {
const resultTransportMode = String(result?.transport_mode || '').trim()
const fields = {
...(preview?.fields || {}),
...(!String(preview?.fields?.transportMode || '').trim() && resultTransportMode
? { transportMode: resultTransportMode }
: {})
...(preview?.fields || {})
}
const hotelRate = formatPolicyMoney(result?.hotel_rate)
const hotelAmount = formatPolicyMoney(result?.hotel_amount)
@@ -808,6 +796,11 @@ export function applyApplicationPolicyEstimateResult(preview = {}, result = {},
const matchedCity = String(result?.matched_city || fields.location || '').trim()
const grade = String(result?.grade || fields.grade || resolveCurrentUserGrade(currentUser)).trim()
if (isTravelApplicationType(fields.applicationType) && !String(fields.transportMode || '').trim()) {
const days = Number(result?.days) || parseApplicationDaysValue(fields.days) || 1
const baseTotalAmount = parseMoneyNumber(result?.hotel_amount) + parseMoneyNumber(result?.allowance_amount)
const baseTotalDisplay = Number.isFinite(baseTotalAmount) && baseTotalAmount > 0
? formatPolicyMoney(baseTotalAmount)
: ''
return normalizeApplicationPreview({
...preview,
fields: {
@@ -816,7 +809,10 @@ export function applyApplicationPolicyEstimateResult(preview = {}, result = {},
lodgingDailyCap: formatDailyPolicyMoney(result?.hotel_rate),
subsidyDailyCap: formatDailyPolicyMoney(result?.total_allowance_rate),
transportPolicy: APPLICATION_TRANSPORT_REIMBURSEMENT_TEXT,
policyEstimate: APPLICATION_POLICY_PENDING_TEXT,
policyEstimate: baseTotalDisplay
? `交通待补充 + 住宿 ${hotelAmount}元 + 补贴 ${allowanceAmount}元 = ${baseTotalDisplay}元(${days}天,不含交通)`
: APPLICATION_POLICY_PENDING_TEXT,
amount: baseTotalDisplay ? `${baseTotalDisplay}元(不含交通)` : fields.amount,
matchedCity,
ruleName: String(result?.rule_name || '').trim(),
ruleVersion: String(result?.rule_version || '').trim(),
@@ -827,7 +823,7 @@ export function applyApplicationPolicyEstimateResult(preview = {}, result = {},
transportQueryLatencyMs: '',
transportEstimateSource: '',
transportEstimateConfidence: '',
policyTotalAmount: ''
policyTotalAmount: baseTotalDisplay ? `${baseTotalDisplay}元(不含交通)` : ''
},
policyEstimateStatus: 'pending'
})