Files
X-Financial/web/src/components/shared/riskRuleTestDialogDisplay.js
caoxiaozhu 7989f3a159 feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL
校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计,
优化 agent 运行和编排执行链路,清理旧开发文档,前端新增
系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈
对话框和工作台日期选择器,优化报销创建和审批详情交互,
补充单元测试覆盖。
2026-05-30 15:46:51 +08:00

123 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 buildTraceItems(result, fields = []) {
const steps = Array.isArray(result?.trace?.steps) ? result.trace.steps : []
return steps.slice(0, 6).map((step, index) => {
const title = String(step?.title || step?.node_id || `判断 ${index + 1}`).trim()
const status = step?.result ? '成立' : '不成立'
const inputs = step?.inputs && typeof step.inputs === 'object'
? Object.entries(step.inputs).slice(0, 3).map(([key, value]) => `${formatFieldName(key, fields)}=${formatDebugValue(value)}`).join('')
: ''
return inputs ? `${title}${status}${inputs}` : `${title}${status}`
})
}
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 })
}