# 共同富裕成果年度报告 — 技术方案 > 依据:同目录 `共同富裕成果年度报告功能需求.md`;数据源为《共同富裕成果技术方案》表 `biz_common_prosperity_achievement`。本模块**只读统计**,无独立业务表。 --- ## 1. 技术架构 | 项 | 说明 | | --- | --- | | **后端** | RuoYi **v3.9.2**(**springboot2** 分支):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` | | **前端** | 若依 Vue2 + **ECharts**(或项目已有图表封装);单接口驱动整页 | | **代码包** | `com.ruoyi.web.modules.commonprosperity`(与成果台账同包,建议 `achievement` 子包旁增 `report` 或合入 `AchievementReportController`) | **分层**:`Controller`(权限、`statYear` 校验、`AjaxResult`)→ `ReportService`(按年查询、缺月补 0、年度汇总)→ 复用 `BizCommonProsperityAchievementMapper`(或只读 SQL)。 **实现要点** - **不新建业务表**;按 `stat_year` 查询成果表,内存组装 **12 个月序列** + **年度总览**。 - **缺月按 0**(功能需求 §2.2、§2.4);**全年无记录**时 `hasData=false`,不返回「全 0 汇总」误导前端。 - 前端**一次请求**加载总览与全部图表(功能需求 §8 性能建议)。 --- ## 2. 数据库设计 ### 2.1 本模块表结构 **无新增表。** 年度报告数据全部来自既有表: | 表名 | 用途 | | --- | --- | | `biz_common_prosperity_achievement` | 月度成果台账;按 `stat_period`(`YYYY-MM`)取数 | 字段、DDL、索引以《共同富裕成果技术方案》**§2** 为准,此处不重复。 ### 2.2 查询与索引 | 项 | 说明 | | --- | --- | | **按年筛选** | `stat_period LIKE CONCAT(#{statYear}, '-%')` 或 `LEFT(stat_period, 4) = #{statYear}` | | **排序** | `ORDER BY stat_period ASC`(组装 1~12 月) | | **索引** | 沿用 `idx_stat_period` / `uk_stat_period`;单年最多 12 行,无额外索引要求 | | **可选年份列表** | `SELECT DISTINCT LEFT(stat_period, 4) AS stat_year FROM biz_common_prosperity_achievement ORDER BY stat_year DESC` | ### 2.3 汇总计算(服务端,与大屏共同富裕一致) | 类型 | 字段 | 算法 | | --- | --- | --- | | 总览 `summary` | 全部 12 项指标 | 取该年台账 **最大统计月** 的单月值 | | 分月 `monthly` | 同上字段 | 所选年 **1~最大月 N**;区间内缺月补 **0**;无数据返回空列表 | **`hasData` 判定**:该年存在 ≥1 条有效台账为 `true`;为 `false` 时 `summary=null`,`monthly=[]`。 --- ## 3. 接口设计 **统一响应**:`AjaxResult` → `data` 为 **3.1** 结构(驼峰 JSON)。 **权限标识(示例)**:`commonProsperity:achievementReport:query`(仅查询;与成果台账 CRUD 权限分离) **Base Path(示例)**:`/commonProsperity/achievementReport` | # | 说明 | Method | URI | 权限 | 要点 | | --- | --- | --- | --- | --- | --- | | 3.1 | 年度报告数据 | GET | `/commonProsperity/achievementReport` | `commonProsperity:achievementReport:query` | Query:`statYear`(必填,4 位年) | | 3.2 | 可选年份列表 | GET | `/commonProsperity/achievementReport/years` | 同上 | 无参;返回台账中出现过的年份,供年份选择器 | > 若希望接口更少,可将 **3.2** 的 `availableYears` 并入 **3.1** 的 `data.availableYears`。 ### 3.1.1 Query 参数(年度报告) | 参数 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `statYear` | int / string | Y | 统计年份,如 `2026`;非法年份返回 400 业务错误 | ### 3.1.2 响应 `data` 结构 ```json { "statYear": 2026, "hasData": true, "summary": { "collectiveEconomyIncome": 120.50, "employmentDrivenCount": 360, "newJobPositions": 48, "envProjectCount": 12, "newGreenArea": 85.20, "culturalHeritageCount": 24, "ethnicIntegrationProjectCount": 6, "ethnicUnityActivityCount": 18, "digitalPlatformUsageRate": 0.7250, "regionalPublicBrandCount": 9, "brandPremiumRate": 0.1500 }, "monthly": [ { "month": 1, "statPeriod": "2026-01", "collectiveEconomyIncome": 10.00, "employmentDrivenCount": 30, "newJobPositions": 4, "envProjectCount": 1, "newGreenArea": 7.10, "culturalHeritageCount": 2, "ethnicIntegrationProjectCount": 1, "ethnicUnityActivityCount": 2, "digitalPlatformUsageRate": 0.80, "regionalPublicBrandCount": 1, "brandPremiumRate": 0.12 } ] } ``` | 字段 | 说明 | | --- | --- | | `statYear` | 请求年份回显 | | `hasData` | 该年是否存在 ≥1 条成果记录 | | `summary` | 年度总览;`hasData=false` 时为 **`null`**(不推荐返回全 0) | | `monthly` | **固定长度 12**;`month` 为 1~12;`statPeriod` 有台账则为 `YYYY-MM`,缺月为 **`null`** 或省略(指标值均为 **0**) | | `monthly[].*` 指标 | 与成果台账字段一致(驼峰);缺月各项为 **0** | **图表与字段映射(前端)** | 图表区块 | 取用字段 | | --- | --- | | 集体经济收入(横向柱) | `monthly[].collectiveEconomyIncome` | | 就业带动(双折线) | `employmentDrivenCount`、`newJobPositions` | | 环境治理(柱) | `envProjectCount` | | 绿化建设(折线) | `newGreenArea` | | 文化传承(柱) | `culturalHeritageCount` | | 民族团结(堆叠柱) | `ethnicIntegrationProjectCount`、`ethnicUnityActivityCount` | ### 3.2 响应 `data`(可选年份) ```json { "years": [2026, 2025, 2024] } ``` ### 3.3 服务端逻辑(摘要) ``` 1. 校验 statYear(四位数字,合理范围如 1900–2100) 2. List rows = mapper.selectByStatYear(statYear) 3. hasData = rows.notEmpty() 4. Map byMonth = 按 stat_period 月份 1-12 映射 5. for m in 1..12: monthly[m] = byMonth.get(m) 或 全指标 0 6. if hasData: summary = 按 §2.3 对 monthly 序列做 SUM / AVG(比率,÷12) else: summary = null 7. return AjaxResult.success(data) ``` **异常**:`statYear` 缺失/非法 → `code`/`msg` 明确;Mapper 异常走统一异常处理。 --- ## 4. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | 组件路径(示例) | | --- | --- | --- | --- | | 菜单 | 共同富裕成果年度报告 | `commonProsperity:achievementReport:query` | `commonProsperity/achievementReport/index` | 前端 API 建议:`ruoyi-ui/src/api/commonProsperity/achievementReport.js` → `getAchievementAnnualReport(statYear)`。 --- ## 5. 交付清单 - [ ] `AchievementReportController` + `IAchievementReportService`(或合入现有 Service) - [ ] Mapper 方法:`selectByStatYear`、`selectDistinctYears`(只读) - [ ] 单元测试:全年无数据、仅 3 月有数据(其余月为 0)、比率年均、加总正确 - [ ] 前端:年份选择 + ECharts 六图 + `hasData` 空态;i18n 复用 `commonProsperity.achievement` - [ ] 菜单权限 SQL(`commonProsperity:achievementReport:query`) - [ ] 依赖成果表 DDL 已执行(`biz_common_prosperity_achievement`) --- ## 6. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:无新表;单接口年度报告 + 可选年份列表;缺月补 0;`hasData` 控制空态 | | 1.1 | 与大屏对齐:总览取最大月单月;`monthly` 为 1~最大月 |