Files
X-Financial/web/src/utils/workbenchSummary.js
caoxiaozhu 04cd6d0f81 feat: 新增数字员工管理页面与工作台首页重构
后端优化 agent 资产种子初始化和常量配置,前端新增数字员工
视图和调度对话框组件,重构个人工作台首页布局和洞察面板,
完善审计页面数字员工详情和运行时模型,优化侧边栏导航和图
标配置,新增工作台摘要和工作台数据模块,补充单元测试。
2026-05-28 09:30:34 +08:00

97 lines
2.9 KiB
JavaScript

function parseNumber(value) {
const nextValue = Number(value)
return Number.isFinite(nextValue) ? nextValue : 0
}
function toDate(value) {
if (!value) {
return null
}
const nextDate = new Date(value)
return Number.isNaN(nextDate.getTime()) ? null : nextDate
}
function isCurrentMonth(dateValue) {
const date = toDate(dateValue)
if (!date) {
return false
}
const now = new Date()
return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth()
}
function resolveClaimDate(request) {
return request?.submittedAt || request?.createdAt || request?.occurredAt || ''
}
export function belongsToCurrentUser(request, currentUser) {
const person = String(request?.person || request?.employeeName || '').trim()
if (!person) {
return false
}
const names = [
String(currentUser?.name || '').trim(),
String(currentUser?.username || '').trim()
].filter(Boolean)
return names.some((name) => name === person)
}
export function hasHighRiskFlag(request) {
const riskFlags = Array.isArray(request?.riskFlags) ? request.riskFlags : []
if (riskFlags.some((item) => String(item?.severity || '').trim().toLowerCase() === 'high')) {
return true
}
const summary = String(request?.riskSummary || '').trim()
return summary.includes('高')
}
function formatCurrency(value) {
return new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY',
minimumFractionDigits: 0,
maximumFractionDigits: Number.isInteger(value) ? 0 : 2
}).format(parseNumber(value))
}
export function buildWorkbenchSummary(requests, currentUser) {
const ownedRequests = Array.isArray(requests)
? requests.filter((item) => belongsToCurrentUser(item, currentUser))
: []
const monthlyClaims = ownedRequests.filter((item) => isCurrentMonth(resolveClaimDate(item)))
const monthlyCount = monthlyClaims.length
const monthlyAmount = monthlyClaims.reduce((sum, item) => sum + parseNumber(item.amount), 0)
const totalCount = ownedRequests.length
const totalAmount = ownedRequests.reduce((sum, item) => sum + parseNumber(item.amount), 0)
const inReviewCount = ownedRequests.filter((item) => item.approvalKey === 'in_progress').length
const pendingPaymentCount = ownedRequests.filter((item) => {
const status = String(item.status || item.approvalStatus || '').trim()
return status.includes('待付款') || status.includes('待支付')
}).length
const completedCount = ownedRequests.filter((item) => item.approvalKey === 'completed').length
const returnCount = ownedRequests.filter((item) => item.approvalKey === 'rejected').length
const highRiskCount = monthlyClaims.filter((item) => hasHighRiskFlag(item)).length
return {
monthlyCount,
monthlyAmount,
monthlyAmountLabel: formatCurrency(monthlyAmount),
totalCount,
totalAmount,
totalAmountLabel: formatCurrency(totalAmount),
inReviewCount,
pendingPaymentCount,
completedCount,
returnCount,
highRiskCount
}
}