feat(dashboard): polish risk and digital employee boards
This commit is contained in:
233
web/src/utils/riskLabels.js
Normal file
233
web/src/utils/riskLabels.js
Normal file
@@ -0,0 +1,233 @@
|
||||
const RISK_SIGNAL_LABELS = {
|
||||
duplicate_invoice: '重复发票',
|
||||
split_billing: '拆分报销',
|
||||
frequent_small_claims: '高频小额报销',
|
||||
location_mismatch: '地点不一致',
|
||||
amount_outlier: '金额异常',
|
||||
preapproval_absent: '缺少事前申请',
|
||||
travel_city_consistency: '差旅城市一致性',
|
||||
travel_route_city_consistency: '差旅路线一致性',
|
||||
hotel_over_limit: '住宿超标',
|
||||
hotel_amount_missing: '住宿金额待补充',
|
||||
travel_meal_amount_missing: '餐饮金额待补充',
|
||||
travel_meal_allowance_over_limit: '餐补超标',
|
||||
transport_class_over_limit: '交通舱等超标',
|
||||
travel_type_uncertain: '差旅类型待确认',
|
||||
invoice_missing: '票据缺失',
|
||||
attachment_missing: '附件缺失',
|
||||
amount_missing: '金额待补充',
|
||||
policy_missing: '制度依据缺失',
|
||||
budget_overrun: '预算超支',
|
||||
suspicious_supplier: '供应商异常',
|
||||
abnormal_frequency: '频次异常',
|
||||
abnormal_amount: '金额异常',
|
||||
manual_review: '人工复核',
|
||||
unknown: '未知风险'
|
||||
}
|
||||
|
||||
const EXPENSE_TYPE_LABELS = {
|
||||
travel: '差旅费',
|
||||
transport: '交通费',
|
||||
hotel: '住宿费',
|
||||
meal: '餐饮费',
|
||||
office: '办公费',
|
||||
entertainment: '招待费',
|
||||
training: '培训费',
|
||||
communication: '通讯费',
|
||||
taxi_receipt: '出租车票据',
|
||||
parking_toll_receipt: '停车通行票据',
|
||||
transport_receipt: '交通票据',
|
||||
train_ticket: '火车票',
|
||||
flight_itinerary: '机票行程单',
|
||||
hotel_invoice: '住宿发票',
|
||||
meal_receipt: '餐饮票据',
|
||||
travel_ticket: '差旅票据',
|
||||
travel_allowance: '差旅补贴',
|
||||
other: '其他费用',
|
||||
unknown: '未知费用'
|
||||
}
|
||||
|
||||
const RISK_SOURCE_LABELS = {
|
||||
financial_risk_graph: '风险图谱',
|
||||
rule_center: '规则中心',
|
||||
user_feedback: '用户反馈',
|
||||
manual_review: '人工复核',
|
||||
system_scan: '系统扫描',
|
||||
onlyoffice: '文档协同',
|
||||
onlyoffice_preview: '文档预览',
|
||||
unknown: '未知来源'
|
||||
}
|
||||
|
||||
const RISK_STATUS_LABELS = {
|
||||
pending_review: '待复核',
|
||||
pending: '待处理',
|
||||
confirmed: '已确认',
|
||||
false_positive: '误报',
|
||||
resolved: '已处理',
|
||||
ignored: '已忽略',
|
||||
closed: '已关闭',
|
||||
unknown: '未知状态'
|
||||
}
|
||||
|
||||
const RISK_LEVEL_LABELS = {
|
||||
critical: '重大',
|
||||
high: '高',
|
||||
medium: '中',
|
||||
low: '低',
|
||||
none: '无',
|
||||
unknown: '未知'
|
||||
}
|
||||
|
||||
const RULE_LABELS = {
|
||||
'policy.duplicate_invoice': '重复发票规则',
|
||||
'policy.split_billing': '拆分报销规则',
|
||||
'policy.frequent_small_claims': '高频小额规则',
|
||||
'policy.location_mismatch': '地点一致性规则',
|
||||
'policy.amount_outlier': '金额异常规则',
|
||||
'policy.preapproval_absent': '事前申请规则',
|
||||
'rule.expense.travel_risk_control_standard': '差旅风险控制规则',
|
||||
'rule.expense.travel_receipt_requirements': '差旅票据要求',
|
||||
'rule.expense.company_travel_expense_reimbursement': '公司差旅费报销规则'
|
||||
}
|
||||
|
||||
const UNKNOWN_LABELS = {
|
||||
department: '未归集部门',
|
||||
expense_type: '未归集费用',
|
||||
risk_type: '未知风险类型',
|
||||
supplier: '未归集供应商',
|
||||
grade: '未归集职级',
|
||||
employee: '未归集员工',
|
||||
rule: '未关联规则',
|
||||
source: '未知来源',
|
||||
status: '未知状态'
|
||||
}
|
||||
|
||||
const LATIN_PATTERN = /[A-Za-z]/
|
||||
|
||||
function normalizeText(value) {
|
||||
return String(value || '').trim()
|
||||
}
|
||||
|
||||
function normalizeKey(value) {
|
||||
return normalizeText(value)
|
||||
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
||||
.replace(/[\s-]+/g, '_')
|
||||
.replace(/\/+/g, '.')
|
||||
.toLowerCase()
|
||||
}
|
||||
|
||||
function lastKeySegment(key) {
|
||||
const parts = String(key || '').split(/[.:]/).filter(Boolean)
|
||||
return parts[parts.length - 1] || key
|
||||
}
|
||||
|
||||
function isMissingValue(text) {
|
||||
return !text || ['unknown', '待补充', '待确认', '未归属部门', '未归属', 'N/A', 'n/a', '-'].includes(text)
|
||||
}
|
||||
|
||||
function fallbackVisibleText(text, fallback) {
|
||||
if (!text) {
|
||||
return fallback
|
||||
}
|
||||
return LATIN_PATTERN.test(text) ? fallback : text
|
||||
}
|
||||
|
||||
export function formatRiskSignalLabel(value, fallback = '未知风险') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return fallback
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
const direct = RISK_SIGNAL_LABELS[key] || RISK_SIGNAL_LABELS[lastKeySegment(key)]
|
||||
if (direct) {
|
||||
return direct
|
||||
}
|
||||
if (key.startsWith('policy.') || key.startsWith('rule.')) {
|
||||
return formatRiskRuleLabel(text)
|
||||
}
|
||||
return fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatExpenseTypeLabel(value, fallback = '未知费用') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return fallback
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
return EXPENSE_TYPE_LABELS[key] || EXPENSE_TYPE_LABELS[lastKeySegment(key)] || fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatRiskSourceLabel(value, fallback = '未知来源') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return fallback
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
return RISK_SOURCE_LABELS[key] || RISK_SOURCE_LABELS[lastKeySegment(key)] || fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatRiskStatusLabel(value, fallback = '未知状态') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return fallback
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
return RISK_STATUS_LABELS[key] || RISK_STATUS_LABELS[lastKeySegment(key)] || fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatRiskLevelLabel(value, fallback = '未知') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return fallback
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
return RISK_LEVEL_LABELS[key] || fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatRiskRuleLabel(value, fallback = '规则指标') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return '未关联规则'
|
||||
}
|
||||
const key = normalizeKey(text)
|
||||
if (RULE_LABELS[key]) {
|
||||
return RULE_LABELS[key]
|
||||
}
|
||||
const suffix = lastKeySegment(key)
|
||||
const signalLabel = RISK_SIGNAL_LABELS[suffix]
|
||||
if (signalLabel) {
|
||||
return `${signalLabel}规则`
|
||||
}
|
||||
return fallbackVisibleText(text, fallback)
|
||||
}
|
||||
|
||||
export function formatRiskDimensionLabel(value, kind = '') {
|
||||
const text = normalizeText(value)
|
||||
if (isMissingValue(text)) {
|
||||
return UNKNOWN_LABELS[kind] || '未知'
|
||||
}
|
||||
if (kind === 'risk_type') {
|
||||
return formatRiskSignalLabel(text, '未知风险类型')
|
||||
}
|
||||
if (kind === 'expense_type') {
|
||||
return formatExpenseTypeLabel(text)
|
||||
}
|
||||
if (kind === 'rule') {
|
||||
return formatRiskRuleLabel(text)
|
||||
}
|
||||
if (kind === 'source') {
|
||||
return formatRiskSourceLabel(text)
|
||||
}
|
||||
if (kind === 'status') {
|
||||
return formatRiskStatusLabel(text)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
export function formatRiskObservationTitle(item = {}) {
|
||||
const title = normalizeText(item.title)
|
||||
if (title && !LATIN_PATTERN.test(title)) {
|
||||
return title
|
||||
}
|
||||
return formatRiskSignalLabel(item.riskSignal || item.riskType || title)
|
||||
}
|
||||
Reference in New Issue
Block a user