feat: 新增员工行为画像算法与费用风险标签体系

后端新增员工行为画像算法模块,支持标签规则引擎和评分计算,
完善员工模型、银行信息、序列化和导入逻辑,优化报销审批流
和工作流常量,增强 Hermes 同步和知识同步能力,前端新增费
用画像详情弹窗、雷达图和风险卡片组件,完善登录页和工作台
样式,优化文档中心和归档中心交互,补充单元测试。
This commit is contained in:
caoxiaozhu
2026-05-28 12:09:49 +08:00
parent 04cd6d0f81
commit 8a4a777be7
96 changed files with 9835 additions and 704 deletions

View File

@@ -51,7 +51,8 @@ const REIMBURSEMENT_PROGRESS_LABELS = [
'AI预审',
'直属领导审批',
'财务审批',
'归档入账'
'待付款',
'已付款'
]
const APPLICATION_PROGRESS_LABELS = [
@@ -264,6 +265,14 @@ function resolveApprovalMeta(status) {
return { key: 'supplement', label: '待补充', tone: 'warning' }
}
if (normalized === 'pending_payment') {
return { key: 'pending_payment', label: '待付款', tone: 'warning' }
}
if (normalized === 'paid') {
return { key: 'completed', label: '已付款', tone: 'success' }
}
if (['approved', 'completed', 'paid'].includes(normalized)) {
return { key: 'completed', label: '已完成', tone: 'success' }
}
@@ -296,8 +305,13 @@ function resolveWorkflowNode(claim, approvalMeta, isApplicationDocument = false)
return '待提交'
}
if (approvalMeta.key === 'pending_payment') {
return '待付款'
}
if (approvalMeta.key === 'completed') {
return isApplicationDocument ? '审批完成' : '归档入账'
const normalizedStatus = String(claim?.status || '').trim().toLowerCase()
return isApplicationDocument ? '审批完成' : normalizedStatus === 'paid' ? '已付款' : '归档入账'
}
return isApplicationDocument ? '直属领导审批' : 'AI预审'
@@ -352,12 +366,22 @@ function resolveProgressCurrentIndex(approvalMeta, workflowNode) {
const normalizedNode = String(workflowNode || '').trim()
if (approvalMeta.key === 'completed') {
return 6
}
if (approvalMeta.key === 'pending_payment') {
return 5
}
if (normalizedNode.includes('归档') || normalizedNode.includes('入账')) {
if (normalizedNode.includes('已付款')) {
return 6
}
if (normalizedNode.includes('待付款')) {
return 5
}
if (normalizedNode.includes('归档') || normalizedNode.includes('入账')) {
return 6
}
if (normalizedNode.includes('财务')) {
return 4
}
@@ -529,6 +553,7 @@ function findApprovalEventForStep(claim, label) {
if (stepLabel === '财务审批') {
return (
previousStage.includes('财务')
|| nextStage.includes('待付款')
|| nextStage.includes('归档')
|| nextStage.includes('入账')
|| nextStage.includes('完成')
@@ -551,6 +576,19 @@ function findLatestReturnEvent(claim) {
)
}
function findLatestPaymentEvent(claim) {
return getLatestEvent(
getRiskFlags(claim).filter((flag) => (
flag
&& typeof flag === 'object'
&& (
normalizeText(flag.source) === 'payment'
|| normalizeText(flag.event_type || flag.eventType) === 'expense_claim_payment_completed'
)
))
)
}
function findLatestApplicationReturnEvent(claim) {
return getLatestEvent(
getRiskFlags(claim).filter((flag) => {
@@ -639,6 +677,18 @@ function buildCompletedStepMeta(claim, label) {
}
}
if (stepLabel === '待付款') {
const approvalEvent = findApprovalEventForStep(claim, '财务审批')
const pendingAt = formatDateTime(approvalEvent?.created_at || approvalEvent?.createdAt || claim?.updated_at)
return buildProgressStepMeta('待付款', pendingAt)
}
if (stepLabel === '已付款') {
const paymentEvent = findLatestPaymentEvent(claim)
const paidAt = formatDateTime(paymentEvent?.created_at || paymentEvent?.createdAt || claim?.updated_at)
return buildProgressStepMeta('已付款', paidAt)
}
if (stepLabel === '归档入账') {
const archivedAt = formatDateTime(claim?.updated_at)
return buildProgressStepMeta('归档入账', archivedAt)
@@ -675,6 +725,14 @@ function resolveCurrentStepStartedAt(claim, label) {
const leaderApprovalEvent = findApprovalEventForStep(claim, '直属领导审批')
return leaderApprovalEvent?.created_at || leaderApprovalEvent?.createdAt || claim?.updated_at || claim?.submitted_at
}
if (stepLabel === '待付款') {
const approvalEvent = findApprovalEventForStep(claim, '财务审批')
return approvalEvent?.created_at || approvalEvent?.createdAt || claim?.updated_at || claim?.submitted_at
}
if (stepLabel === '已付款') {
const paymentEvent = findLatestPaymentEvent(claim)
return paymentEvent?.created_at || paymentEvent?.createdAt || claim?.updated_at || claim?.submitted_at
}
if (stepLabel === '归档入账' || stepLabel === '审批完成') {
return claim?.updated_at || claim?.submitted_at
}
@@ -703,6 +761,8 @@ function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}
const currentTime =
approvalMeta.key === 'completed'
? '已完成'
: approvalMeta.key === 'pending_payment'
? '待付款'
: approvalMeta.key === 'supplement'
? '待补充'
: approvalMeta.key === 'rejected'