feat: 新增票据夹模块并优化 OCR 与员工画像服务
后端新增票据夹端点、数据模型和服务模块,优化 OCR 端点 Schema 和附件操作逻辑,完善员工行为画像服务和辅助函数, 前端新增票据夹视图和服务层,优化文档中心样式和侧边栏导 航,完善员工画像详情弹窗和权限控制,补充单元测试。
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
export const DEFAULT_APP_VIEW_ORDER = [
|
||||
'workbench',
|
||||
'documents',
|
||||
'budget',
|
||||
'workbench',
|
||||
'documents',
|
||||
'receiptFolder',
|
||||
'budget',
|
||||
'audit',
|
||||
'overview',
|
||||
'policies',
|
||||
@@ -10,7 +11,7 @@ export const DEFAULT_APP_VIEW_ORDER = [
|
||||
'settings'
|
||||
]
|
||||
|
||||
const ALWAYS_VISIBLE_VIEWS = new Set(['workbench', 'documents', 'policies'])
|
||||
const ALWAYS_VISIBLE_VIEWS = new Set(['workbench', 'documents', 'receiptFolder', 'policies'])
|
||||
const VIEW_ROLE_RULES = {
|
||||
overview: ['finance', 'executive'],
|
||||
budget: ['budget_monitor', 'executive'],
|
||||
|
||||
@@ -97,11 +97,15 @@ export function buildUserProfileMetricCards(profile, runs = [], currentUser = {}
|
||||
const index = indexProfiles(profile)
|
||||
const aiMetrics = metricsOf(index.ai_usage)
|
||||
const userRuns = filterRunsByCurrentUser(runs, currentUser)
|
||||
const durationDisplay = formatDurationMetric(sumRunDurationMs(userRuns))
|
||||
const commonAgent = resolveCommonAgent(userRuns)
|
||||
const windowedUserRuns = filterRunsByProfileWindow(userRuns, profile)
|
||||
const durationMs = hasProfileDurationMetric(aiMetrics)
|
||||
? resolveNumber(aiMetrics.ai_run_duration_ms)
|
||||
: sumRunDurationMs(windowedUserRuns)
|
||||
const durationDisplay = formatDurationMetric(durationMs)
|
||||
const commonAgent = resolveCommonAgent(windowedUserRuns)
|
||||
const tokenCount = resolveNumber(aiMetrics.exact_token_count) || resolveNumber(aiMetrics.estimated_token_count)
|
||||
const tokenDisplay = formatTokenCount(tokenCount)
|
||||
const aiRunCount = resolveNumber(aiMetrics.ai_run_count) || userRuns.length
|
||||
const aiRunCount = resolveNumber(aiMetrics.ai_run_count) || windowedUserRuns.length
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -223,11 +227,23 @@ function metricsOf(profile) {
|
||||
return profile?.metrics && typeof profile.metrics === 'object' ? profile.metrics : {}
|
||||
}
|
||||
|
||||
function hasProfileDurationMetric(metrics) {
|
||||
return Object.prototype.hasOwnProperty.call(metrics || {}, 'ai_run_duration_ms')
|
||||
}
|
||||
|
||||
function filterRunsByCurrentUser(runs, currentUser) {
|
||||
const identities = resolveCurrentUserIdentities(currentUser)
|
||||
return (Array.isArray(runs) ? runs : []).filter((run) => belongsToCurrentUser(run, identities))
|
||||
}
|
||||
|
||||
function filterRunsByProfileWindow(runs, profile) {
|
||||
const cutoff = Date.now() - resolveWindowDays(profile) * 24 * 60 * 60 * 1000
|
||||
return (Array.isArray(runs) ? runs : []).filter((run) => {
|
||||
const startedAt = Date.parse(run?.started_at || '')
|
||||
return Number.isFinite(startedAt) && startedAt >= cutoff
|
||||
})
|
||||
}
|
||||
|
||||
function belongsToCurrentUser(run, identities) {
|
||||
if (!identities.size) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user