# 财务看板排行口径与部门人员占比 ## 功能一句话 在分析看板的财务看板中补齐部门人员报销占比,并让部门、个人、高额单据使用统一的排行时间筛选口径。 ## 背景与问题 当前财务看板已有部门报销排行、个人报销排行和本月高额单据,但存在三个问题: - 部门排行的时间筛选只有本周、本月、本季度,缺少本年和全部。 - 个人报销排行标题固定为“本月”,实际无法由用户切换本月、本季度、本年和全部。 - 高额单据旁缺少部门内人员报销构成,财务人员难以判断高额单据是否集中在少数人员或单一部门。 ## 目标与非目标 目标: - 新增“部门人员报销占比”饼图,放在“本月高额单据”左侧,并与排行时间筛选口径联动。 - 部门报销排行增加参与人员数量,卡片空间完整展示排行内容。 - 个人报销排行增加报销笔数和所属部门信息,卡片空间完整展示排行内容。 - 部门排行、个人排行、高额单据、部门人员占比统一支持:本月、本季度、本年、全部。 非目标: - 不新增独立页面。 - 不重做顶部 KPI、趋势图、预算指标和系统/风险/数字员工看板。 - 不引入新的图表库,继续复用现有 ECharts 封装组件。 ## 用户与场景 用户: - 高级财务人员、预算监控员、管理员。 场景: - 财务人员进入分析看板后,查看不同时间口径下的部门费用集中度。 - 财务人员切换本季度、本年或全部后,对比部门排行、个人排行、高额单据和人员占比。 - 财务人员判断某部门报销金额高,是因为多人正常报销,还是少数人集中报销。 ## 功能能力 输入: - `department_range` 查询参数,取值:`本月`、`本季度`、`本年`、`全部`。 输出: - `department_ranking`:部门报销排行,新增 `employeeCount`。 - `employee_ranking`:个人报销排行,保留金额、笔数、部门,并随筛选口径变化。 - `top_claims`:高额单据,随筛选口径变化,标题不再固定为本月。 - `department_employee_mix`:部门人员报销占比饼图数据。 状态与边界: - 没有真实数据时返回空数组或“暂无数据”占位。 - 草稿、删除等非支出口径状态不参与金额排行。 - 缺失部门或人员名称的数据不进入排行和占比图。 - `全部` 表示所有可用报销单据,不按日期裁剪。 ## 方案设计 后端: - 在 `FinanceDashboardService` 中扩展排行时间范围解析。 - 将 `department_range` 作为排行分析窗口,统一供部门排行、个人排行、高额单据和部门人员占比使用。 - 部门排行按部门聚合金额、单据数、待付款金额和人员数量。 - 部门人员占比按“部门 + 人员”聚合金额,展示排名靠前的人员构成,名称格式为 `部门 · 人员`。 接口: - `GET /api/v1/analytics/finance-dashboard` 保持原路径。 - `department_range` 支持 `本月`、`本季度`、`本年`、`全部`。 - 响应体新增 `department_employee_mix`。 前端: - `analytics.js` 增加 `departmentEmployeeMix` 归一化。 - `metrics.js` 将 `departmentRangeOptions` 改为 `本月 / 本季度 / 本年 / 全部`。 - `useOverviewView.js` 新增部门人员占比 legend,并让部门/个人排行读取新增字段。 - `OverviewView.vue` 调整财务看板底部布局: - 部门排行占更宽区域,并保留筛选器。 - 个人排行占更宽区域,并增加相同筛选器。 - 高额单据卡片左侧放部门人员报销占比饼图,右侧放高额单据列表。 - 样式继续沿用企业 SaaS 直角、低饱和、Element Plus 控件和已有 `DonutChart` / `BarChart`。 ## 算法与公式 支出金额: $$ amount_i = claim_i.amount $$ 部门金额: $$ departmentAmount_d = \sum_{i \in claims(d)} amount_i $$ 部门人员数: $$ employeeCount_d = \left| distinct(employeeName_i), i \in claims(d) \right| $$ 个人金额: $$ employeeAmount_e = \sum_{i \in claims(e)} amount_i $$ 部门人员报销占比: $$ share_{d,e} = \frac{\sum_{i \in claims(d,e)} amount_i}{\sum_{i \in rankingClaims} amount_i} $$ 其中 `rankingClaims` 为当前 `department_range` 时间口径下过滤后的有效报销单据。 ## 测试方案 - 后端单元测试: - 覆盖 `department_range=本年` 和 `department_range=全部`。 - 验证部门排行返回 `employeeCount`。 - 验证个人排行随口径变化。 - 验证 `department_employee_mix` 返回正确人员占比数据。 - 前端源码测试: - 验证筛选选项包含本月、本季度、本年、全部。 - 验证个人排行和部门排行都有筛选器。 - 验证高额单据卡片包含部门人员报销占比图。 - 验证服务层归一化新增字段。 - 构建验证: - `npm.cmd --prefix web run build`。 - 容器验证: - 后端测试在 `x-financial-main:/app` 中运行,超时不超过 60s。 - 可用时通过接口检查 `department_employee_mix`、`employeeCount` 和 `department_range=全部`。 ## 指标与验收 - 财务看板接口返回 `department_employee_mix`。 - 部门排行每项返回 `employeeCount`。 - 部门排行和个人排行都可选择本月、本季度、本年、全部。 - 个人排行标题不再固定“本月”。 - 高额单据卡片左侧显示部门人员报销占比饼图。 - 定向后端测试和前端构建通过。 ## 风险与开放问题 - 当前工作区存在大量未提交变更,提交时必须只纳入本次相关文件。 - 如果浏览器自动化不可用,前端以源码测试、构建和接口验证为主要证据。 - `全部` 口径数据量可能更大,当前实现继续沿用内存聚合;后续数据量过大时再考虑 SQL 聚合优化。