feat: 增强风险规则生成引擎与预算中心页面
后端拆分风险规则生成为解释器、语义分析、本体对齐等子模块, 优化模板执行和流程图生成,完善员工种子数据和导入逻辑,增强 报销单权限策略和草稿持久化,前端新增预算中心视图和趋势图 组件,重构审计页面和风险规则测试对话框交互,完善文档中心 和报销创建页面细节,补充单元测试覆盖。
This commit is contained in:
110
web/src/components/shared/riskRuleTestDialogDisplay.js
Normal file
110
web/src/components/shared/riskRuleTestDialogDisplay.js
Normal file
@@ -0,0 +1,110 @@
|
||||
export function formatFieldLabel(field) {
|
||||
const key = String(field?.key || '').trim()
|
||||
const label = String(field?.display || field?.label || '').trim()
|
||||
if (!key) return label || '-'
|
||||
if (!label || label === key) return key
|
||||
return label.includes(`[${key}]`) ? label : `${label}[${key}]`
|
||||
}
|
||||
|
||||
export function buildResultFields(result, fields = []) {
|
||||
const values = result?.field_values && typeof result.field_values === 'object'
|
||||
? result.field_values
|
||||
: {}
|
||||
return Object.entries(values).slice(0, 8).map(([key, value]) => ({
|
||||
key,
|
||||
label: formatFieldLabel(fields.find((field) => field.key === key) || { key }),
|
||||
value: Array.isArray(value) ? value.join('、') : String(value ?? '-')
|
||||
}))
|
||||
}
|
||||
|
||||
export function buildRecognizedFieldRows(result, fields = []) {
|
||||
const rows = Array.isArray(result?.recognized_fields) ? result.recognized_fields : []
|
||||
return rows.slice(0, 12).map((field, index) => ({
|
||||
key: String(field?.key || `field-${index}`),
|
||||
label: formatFieldLabel(
|
||||
fields.find((item) => item.key === field?.key) || {
|
||||
key: field?.key,
|
||||
label: field?.label
|
||||
}
|
||||
),
|
||||
source: formatRecognitionSource(field?.source),
|
||||
value: formatDebugValue(field?.value)
|
||||
}))
|
||||
}
|
||||
|
||||
export function buildEvidenceItems(result, fields = []) {
|
||||
const evidence = result?.evidence && typeof result.evidence === 'object'
|
||||
? result.evidence
|
||||
: {}
|
||||
const items = []
|
||||
if (Array.isArray(evidence.failed_conditions)) {
|
||||
evidence.failed_conditions.slice(0, 3).forEach((condition) => {
|
||||
const left = Array.isArray(condition.left_values) ? condition.left_values.join('、') : '-'
|
||||
const right = Array.isArray(condition.right_values) ? condition.right_values.join('、') : '-'
|
||||
items.push(`${formatFieldName(condition.left, fields)}:${left};${formatFieldName(condition.right, fields)}:${right}`)
|
||||
})
|
||||
}
|
||||
if (Array.isArray(evidence.missing_fields)) {
|
||||
evidence.missing_fields.slice(0, 5).forEach((field) => {
|
||||
items.push(`${formatFieldName(field, fields)} 缺失`)
|
||||
})
|
||||
}
|
||||
if (Array.isArray(evidence.keyword_hits)) {
|
||||
items.push(`命中关键词:${evidence.keyword_hits.join('、')}`)
|
||||
}
|
||||
if (evidence.condition_summary) {
|
||||
items.push(String(evidence.condition_summary))
|
||||
}
|
||||
return [...new Set(items)].slice(0, 5)
|
||||
}
|
||||
|
||||
export function buildDocumentBrief(document) {
|
||||
const fields = Array.isArray(document?.document_fields) ? document.document_fields : []
|
||||
if (fields.length) {
|
||||
return fields.slice(0, 6).map((field) => `${field.label}:${field.value}`).join(';')
|
||||
}
|
||||
return String(document?.summary || document?.text || '未提取到结构化字段').slice(0, 120)
|
||||
}
|
||||
|
||||
export function formatDocumentMeta(document) {
|
||||
const labels = [
|
||||
document?.document_type_label || '',
|
||||
document?.scene_label || '',
|
||||
document?.avg_score ? `置信度 ${Math.round(Number(document.avg_score) * 100)}%` : ''
|
||||
].filter(Boolean)
|
||||
return labels.join(' · ') || '未分类'
|
||||
}
|
||||
|
||||
export function resolveFileStatusLabel(file) {
|
||||
return file.statusText || {
|
||||
pending: '待发送',
|
||||
recognizing: '识别中',
|
||||
recognized: '已识别',
|
||||
failed: '识别失败'
|
||||
}[file.status] || '待识别'
|
||||
}
|
||||
|
||||
export function trimDebugText(text, maxLength = 800) {
|
||||
const value = String(text || '').replace(/\s+/g, ' ').trim()
|
||||
if (!value) return ''
|
||||
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value
|
||||
}
|
||||
|
||||
function formatRecognitionSource(source) {
|
||||
return {
|
||||
manual: '手动输入',
|
||||
ocr: 'OCR结构字段',
|
||||
inferred: '文本推断',
|
||||
model_refined: '模型过滤'
|
||||
}[String(source || '').trim()] || '未标注来源'
|
||||
}
|
||||
|
||||
function formatDebugValue(value) {
|
||||
if (Array.isArray(value)) return value.map((item) => String(item ?? '')).filter(Boolean).join('、') || '-'
|
||||
if (value && typeof value === 'object') return JSON.stringify(value)
|
||||
return String(value ?? '-')
|
||||
}
|
||||
|
||||
function formatFieldName(key, fields) {
|
||||
return formatFieldLabel(fields.find((field) => field.key === key) || { key })
|
||||
}
|
||||
Reference in New Issue
Block a user