# 统计分析逻辑 **本文引用的文件** - [stats_service.py](file://backend/app/services/stats_service.py) - [stats.py](file://backend/app/api/v1/stats.py) - [models.py](file://backend/app/models/models.py) - [finance.py](file://backend/app/models/finance.py) - [schemas.py](file://backend/app/schemas/schemas.py) - [finance.py](file://backend/app/api/v1/finance.py) - [stats.js](file://frontend/src/api/stats.js) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue) - [Reports.vue](file://frontend/src/views/reports/Reports.vue) - [详细设计.md](file://docs/详细设计.md) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向医院绩效系统的统计分析逻辑,围绕平衡计分卡(BSC)四个维度(财务、客户、内部流程、学习与成长)展开,系统性阐述: - 维度统计与加权平均的实现 - 科室绩效排名、趋势分析、同比/环比计算 - 多维度数据聚合、图表数据生成与前端展示 - 统计口径定义、数据准确性保障与性能优化策略 - 统计结果的展示逻辑、导出能力现状与扩展建议、自定义报表配置思路 ## 项目结构 后端采用 FastAPI + SQLAlchemy 异步 ORM,统计分析位于服务层与 API 层,前端通过 ECharts 进行可视化展示。数据库模型涵盖指标、考核、员工、科室、财务等核心实体。 ```mermaid graph TB subgraph "后端" API["API 路由
/stats/*"] SVC["统计服务
StatsService"] MODELS["数据模型
Assessment/Detail/Indicator/Department/Staff"] FINANCE_MODEL["财务模型
DepartmentFinance"] end subgraph "前端" FE_API["前端统计接口封装
stats.js"] DASHBOARD["仪表盘视图
Dashboard.vue"] REPORTS["报表视图
Reports.vue"] end FE_API --> API API --> SVC SVC --> MODELS SVC --> FINANCE_MODEL DASHBOARD --> FE_API REPORTS --> FE_API ``` **图表来源** - [stats.py](file://backend/app/api/v1/stats.py#L1-L242) - [stats_service.py](file://backend/app/services/stats_service.py#L1-L300) - [models.py](file://backend/app/models/models.py#L117-L203) - [finance.py](file://backend/app/models/finance.py#L45-L74) - [stats.js](file://frontend/src/api/stats.js#L1-L43) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L225-L819) - [Reports.vue](file://frontend/src/views/reports/Reports.vue#L183-L245) **章节来源** - [stats.py](file://backend/app/api/v1/stats.py#L1-L242) - [stats_service.py](file://backend/app/services/stats_service.py#L1-L300) - [models.py](file://backend/app/models/models.py#L117-L203) - [finance.py](file://backend/app/models/finance.py#L45-L74) - [stats.js](file://frontend/src/api/stats.js#L1-L43) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L225-L819) - [Reports.vue](file://frontend/src/views/reports/Reports.vue#L183-L245) ## 核心组件 - 统计服务层(StatsService):提供 BSC 维度统计、科室统计、趋势分析、排名、指标完成度等核心统计方法。 - API 层(/stats):暴露统计接口,负责参数解析、默认值处理、响应包装。 - 数据模型:Assessment/AssessmentDetail/Indicator/Department/Staff/Finance 相关表,支撑统计口径与聚合。 - 前端接口封装与可视化:stats.js 封装请求,Dashboard.vue 与 Reports.vue 使用 ECharts 渲染图表。 **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L16-L300) - [stats.py](file://backend/app/api/v1/stats.py#L14-L242) - [models.py](file://backend/app/models/models.py#L117-L203) - [finance.py](file://backend/app/models/finance.py#L45-L74) - [stats.js](file://frontend/src/api/stats.js#L1-L43) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L225-L819) - [Reports.vue](file://frontend/src/views/reports/Reports.vue#L183-L245) ## 架构总览 统计分析的调用链路如下: - 前端通过 stats.js 请求 /stats/* 接口 - API 层解析参数并调用 StatsService - StatsService 基于 SQLAlchemy 异步查询,按统计口径进行聚合 - 返回标准化 JSON 结果,前端渲染图表与表格 ```mermaid sequenceDiagram participant FE as "前端(stats.js)" participant API as "API 路由(stats.py)" participant SVC as "统计服务(StatsService)" participant DB as "数据库(ORM)" FE->>API : GET /stats/department?year&month API->>SVC : get_department_stats(year, month) SVC->>DB : 查询Assessment/AssessmentDetail/Staff/Department DB-->>SVC : 聚合结果 SVC-->>API : 列表(含科室均分/排名等) API-->>FE : JSON 响应 FE->>FE : ECharts 渲染图表 ``` **图表来源** - [stats.js](file://frontend/src/api/stats.js#L1-L43) - [stats.py](file://backend/app/api/v1/stats.py#L36-L49) - [stats_service.py](file://backend/app/services/stats_service.py#L75-L146) **章节来源** - [stats.js](file://frontend/src/api/stats.js#L1-L43) - [stats.py](file://backend/app/api/v1/stats.py#L36-L49) - [stats_service.py](file://backend/app/services/stats_service.py#L75-L146) ## 详细组件分析 ### BSC 四维度统计(财务、客户、内部流程、学习与成长) - 统计口径 - 维度得分 = Σ(指标得分 × 指标权重) / Σ(指标权重) - 指标得分来自 AssessmentDetail.score,权重来自 Indicator.weight - 仅统计状态为“已确认”的考核记录 - 查询条件 - 可按年、月、科室过滤 - 返回字段 - 各维度的总分、权重、指标数量、平均分(总分/权重) ```mermaid flowchart TD Start(["进入 get_bsc_dimension_stats"]) --> BuildCond["构建查询条件
状态=FINALIZED
可选: 年/月/科室"] BuildCond --> JoinTables["连接表: Indicator → AssessmentDetail → Assessment"] JoinTables --> GroupByDim["按 bs_dimension 分组"] GroupByDim --> Calc["计算: 总分=Σ(score*weight)
权重=Σ(weight)
指标数=count(*)"] Calc --> Avg["平均分=总分/权重"] Avg --> Return["返回维度统计+周期"] ``` **图表来源** - [stats_service.py](file://backend/app/services/stats_service.py#L19-L72) - [models.py](file://backend/app/models/models.py#L117-L146) **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L19-L72) - [models.py](file://backend/app/models/models.py#L117-L146) ### 科室绩效统计与排名 - 统计口径 - 按科室汇总:员工数、总分、平均分、最高分、最低分、员工列表 - 平均分 = 总分 / 员工数 - 结果按平均分降序排列 - 排名口径 - 员工维度:按加权得分降序取前 N - 科室维度:按科室平均分降序取前 N ```mermaid flowchart TD S1["查询 FINALIZED 考核记录"] --> Join["连接 Staff/Assessment/Department"] Join --> Group["按 Department 聚合"] Group --> Sum["累计: 员工数/总分/最高分/最低分"] Sum --> Avg["平均分=总分/员工数"] Avg --> Sort["按平均分降序"] Sort --> Limit["可选: 截取前N"] Limit --> Out["返回科室统计列表"] ``` **图表来源** - [stats_service.py](file://backend/app/services/stats_service.py#L75-L146) **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L75-L146) ### 趋势分析(月度) - 统计口径 - 以月为粒度,计算当月平均总分、平均加权分、记录数 - 可按年份与最近 N 个月过滤 - 跨年处理:若起始月小于 1,则跨年累加 - 返回字段 - 月份、平均得分、平均加权得分、记录数 ```mermaid flowchart TD T0["输入: 年份/月份数/科室ID"] --> T1["构造条件: FINALIZED"] T1 --> T2{"是否指定年份?"} T2 -- 是 --> T3["计算起始月=当前月-N+1"] T3 --> T4{"起始月<1?"} T4 -- 是 --> T5["拼接跨年条件"] T4 -- 否 --> T6["拼接同年内条件"] T2 -- 否 --> T7["使用当前年份"] T5 --> T8["连接 Staff/Assessment"] T6 --> T8 T7 --> T8 T8 --> T9["按月分组, 计算平均值与计数"] T9 --> T10["返回趋势数据"] ``` **图表来源** - [stats_service.py](file://backend/app/services/stats_service.py#L148-L199) **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L148-L199) ### 指标完成度统计 - 统计口径 - 计算指标平均得分、最大/最小得分、完成率 = min(平均得分/目标值×100, 100) - 可按年、月、指标过滤 - 返回字段 - 指标ID/名称/编码、目标值、最高分、平均分、完成率、样本数 **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L246-L299) ### 财务相关统计(收支趋势) - 当前实现 - /stats/finance-trend 为演示接口,返回模拟数据 - 建议实现 - 使用 DepartmentFinance 表按月统计收入/支出/结余 - 与财务模型一致的类别枚举(收入/支出类别) - 与趋势分析一致的“最近 N 月”参数 **章节来源** - [stats.py](file://backend/app/api/v1/stats.py#L156-L183) - [finance.py](file://backend/app/models/finance.py#L45-L74) ### 统计结果展示与图表生成 - Dashboard.vue - 初始化 ECharts 实例,加载趋势、饼图、科室排名、财务趋势、仪表盘等数据 - 趋势图:双轴(得分/奖金),折线+面积 - 仪表盘:床位使用率、药占比、材料占比、患者满意度(模拟数据) - Reports.vue - 科室柱状图(平均分)+折线(奖金总额) - 支持筛选与刷新 **章节来源** - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L423-L819) - [Reports.vue](file://frontend/src/views/reports/Reports.vue#L183-L245) ## 依赖关系分析 - 统计服务依赖数据模型与枚举(Assessment/AssessmentDetail/Indicator/Department/Staff/BSCDimension/AssessmentStatus) - API 层依赖统计服务与安全中间件(用户鉴权) - 前端依赖 stats.js 封装的接口,调用 /stats/* 并渲染图表 ```mermaid graph LR STATS_API["/stats/*"] --> STATS_SVC["StatsService"] STATS_SVC --> MODELS_M["Assessment/Detail/Indicator/Department/Staff"] STATS_SVC --> MODELS_F["DepartmentFinance"] FE_STATS["stats.js"] --> STATS_API DASH["Dashboard.vue"] --> FE_STATS REPORTS["Reports.vue"] --> FE_STATS ``` **图表来源** - [stats.py](file://backend/app/api/v1/stats.py#L14-L242) - [stats_service.py](file://backend/app/services/stats_service.py#L10-L13) - [models.py](file://backend/app/models/models.py#L117-L203) - [finance.py](file://backend/app/models/finance.py#L45-L74) - [stats.js](file://frontend/src/api/stats.js#L1-L43) **章节来源** - [stats.py](file://backend/app/api/v1/stats.py#L14-L242) - [stats_service.py](file://backend/app/services/stats_service.py#L10-L13) - [models.py](file://backend/app/models/models.py#L117-L203) - [finance.py](file://backend/app/models/finance.py#L45-L74) - [stats.js](file://frontend/src/api/stats.js#L1-L43) ## 性能考虑 - 查询优化 - 使用 group_by 与聚合函数一次性计算,避免多次往返 - 为常用过滤字段(状态、年、月、科室)建立索引(模型中已有索引) - 异步 I/O - 使用 SQLAlchemy AsyncSession,降低阻塞 - 缓存策略 - 对热点报表(如趋势、排名)可引入 Redis 缓存,设置合理过期时间 - 分页与限制 - 排名接口限制返回条数(默认 10),避免大数据集传输 - 前端渲染 - ECharts 按需初始化,窗口 resize 时重绘,避免重复实例化 **章节来源** - [models.py](file://backend/app/models/models.py#L174-L178) - [stats_service.py](file://backend/app/services/stats_service.py#L202-L244) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L441-L447) ## 故障排查指南 - 接口返回空数据 - 检查考核状态是否为 FINALIZED - 确认年/月/科室参数是否正确 - 确认数据是否已归档到对应周期 - 趋势数据异常 - 跨年月份计算是否正确(起始月<1 的分支) - 是否存在缺失月份导致平均值异常 - 图表不显示 - 确认 ECharts 实例已初始化且容器尺寸有效 - 检查数据结构与图表配置项是否匹配 - 财务趋势为空 - 当前 /stats/finance-trend 为演示接口,需对接 DepartmentFinance 表真实数据 **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L148-L199) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L423-L447) - [stats.py](file://backend/app/api/v1/stats.py#L156-L183) ## 结论 本系统以 BSC 四维度为核心,结合指标权重与加权平均,实现了维度得分、科室统计、趋势分析与排名等关键统计能力。通过异步查询与前端可视化,形成了从数据到洞察的完整闭环。财务趋势与关键指标仪表盘目前为演示实现,建议尽快对接 DepartmentFinance 表,以提供真实财务数据支持。 ## 附录 ### 统计口径与算法一览 - BSC 维度统计 - 维度得分 = Σ(得分×权重)/Σ(权重) - 仅统计 FINALIZED 考核 - 科室统计 - 员工数、总分、平均分、最高/最低分 - 平均分=总分/员工数 - 趋势分析 - 月度平均总分、平均加权分、记录数 - 跨年处理:起始月<1 时拼接跨年条件 - 指标完成度 - 完成率=min(平均得分/目标值×100, 100) - 排名 - 员工:按加权得分降序取前 N - 科室:按平均分降序取前 N **章节来源** - [stats_service.py](file://backend/app/services/stats_service.py#L19-L299) ### 数据模型与统计关系 ```mermaid erDiagram INDICATOR { int id PK string name string code enum bs_dimension numeric weight numeric max_score numeric target_value } ASSESSMENT { int id PK int staff_id FK int period_year int period_month numeric total_score numeric weighted_score enum status } ASSESSMENT_DETAIL { int id PK int assessment_id FK int indicator_id FK numeric actual_value numeric score } STAFF { int id PK int department_id FK string employee_id string name } DEPARTMENT { int id PK string name string code enum dept_type } INDICATOR ||--o{ ASSESSMENT_DETAIL : "包含" ASSESSMENT_DETAIL ||--|| ASSESSMENT : "属于" ASSESSMENT ||--|| STAFF : "由员工产生" STAFF ||--|| DEPARTMENT : "属于" ``` **图表来源** - [models.py](file://backend/app/models/models.py#L117-L203) ### 导出与自定义报表配置 - 导出能力现状 - 后端未提供报表导出接口 - 前端未实现 Excel/PDF 导出 - 建议 - 新增 /stats/export 接口,支持按参数导出 CSV/Excel - 前端增加导出按钮,调用后端接口并下载文件 - 自定义报表配置:允许用户保存筛选条件与图表布局,后续可扩展为“仪表盘模板” **章节来源** - [stats.py](file://backend/app/api/v1/stats.py#L1-L242) - [Dashboard.vue](file://frontend/src/views/Dashboard.vue#L225-L819) ### 与系统设计文档的对应关系 - 设计目标与原则 - 战略导向、分类分层、定量与定性结合、可操作性、持续改进 - 报表与分析中心 - 标准报表、自定义仪表盘、多维分析、趋势预测、数据导出 - 实施路线图 - 分阶段推进,逐步覆盖全院并深化应用 **章节来源** - [详细设计.md](file://docs/详细设计.md#L1-L196)