HANDOFF.md
@@ -4,7 +4,330 @@
> **每天结束时**:把当天进展、踩过的坑、新需求、未完成事项更新到本文件,然后可以放心开新对话。
> **协作约定(2026-08-31)**:说「提交」= 本地 commit + 推送到远端 git(origin main,Gitblit),不再只做本地 commit。
### 10-12(12):汇总大表「缺数不留上一期旧值」(排名页按源侧留空)+ 缺数清单代码入库【待验收】
- **背景**:用户问"生成表里很多数据都是 8 月的吧";同时库里的缺数清单代码一直未提交(本机沙箱故障期间写的,沙箱恢复后补提交)。
- **口径改动(3 处,同一件事:缺数不留上一期旧值)**:
  1. `loadCumulativeMap` / `getProvinceCumulative`:③规上规下拆分表**只认目标期**(原实现允许"目标期及之前最近一期"→ 会静默拿上一期的数当本期);
  2. `copyRankValues`:源侧(独立排名表)缺数时**目标格留空**,不再沿用母版上一报表期的旧值(源侧文字标签不清);
  3. 排名块**整块缺数**(源侧一个数都没有,如 9 月缺②③时的《货运周转量排名》)→ 整块只留标题与市州名,避免母版自带 RANK/占比公式在空块上算出"排名全 1 + 占比 #DIV/0!"。
- **效果(2026-09 实测,产物 `docs\生成汇总大表\输出\生成_道路运输量汇总表_2026-09.xlsx`)**:
  - 《货运周转量排名》整块留空 —— 与用户日常核对的《生成_周转量排名》空态一致 ✓;
  - 《货运量排名》9 月块:规上=①实数(全省 **3575.1211**)、规下/合计留空(缺②);占比列沿用源侧公式(其中 72 个 #DIV/0! 是独立排名表本身就有的);
  - 无回归:公交 9 月客运量 **13476.35**、城市内 12021.00、出租客运量 5626.81 与库内 Σ17 市州逐位一致 ✓(其余页与上一版产物差异仅来自母版脏格清理与缓存刷新)。
- **同时补提交**(沙箱故障期间遗留,已按 10-12(4)报告验证过):`reportexport/calc/SummaryMissingDataCheck.java`(只读缺数清单)、`GET /api/report/summaryWorkbook/missing`、导出日志 `dbProblems` 接入(本次导出日志已可见"缺数提示=[…]")。
- **遗留/待确认**:① 城市分市州、道路运输周转量的 34 个 #DIV/0! 按 10-12(7)用户决定不动;② **排名页在缺数期整体留空是否符合预期,请验收时确认**(若要"保留上一期值"的口径,可回退第 2/3 条)。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_汇总大表缺数不留上一期旧值_2026-10-12.md`。状态:**【待验收】**。
### 10-12(11):扩列表头行二次修正 + 9 月母版被扩列写成日期的 13 格清理【待验收】
- **现象(用户报告)**:生成表里"很多数据是 8 月的"。排查发现 **9 月母版里有 13 个数据格被写成了 9 月月份日期序列 `46266`(= 2026-09-01)**:` 货运!S11/T11`、`班线包车!S9/T9`、`公交!S8/T8`、`出租!S6/T6`、`中口径明细!S5/T5`;下游缓存被带偏(`班线包车!S5`、`中口径明细!S99/S100/S104/S105` 等也是 46266)。
- **根因**:扩列器 `headerRowsOf` 首版只要求"整行 ≥2 个月份格",而出租第 6 行、班线包车第 3 行这类**数据行**里恰好有 2 个像日期序列的数值 → 被误判成表头行 → 扩列时把"月份日期"写进了数据行(`cloneHeaderCell` 对数值格写 `targetMonth` 的日期)。
- **修法**:改为**先取"月份表头格最多的那一行"作基准,把它的月份列当标准列**;只有这些列上大半是月份格的行才算表头行。轨道、轮渡一页两个块的 `[1,10]` 保持 ✓;` 货运/公交/网约车/中口径明细` 仍为单行表头 ✓。
- **母版修复(用 Excel COM,未整本重写)**:13 格按扩列规则精修(该留空的清空、公式按规则补回 `=S12+S13` / `=S11/AN11-1` / `=S10+S14+…`)+ `CalculateFull` 整本重算刷新缓存;修复前备份 `_bak_2026年9月母版_清理脏格前_20261012.xlsx`。修复后全簿只剩 3 个 `46266` 的**合法表头月份格**(城市客运 S2、公交 S3、出租 S3)。
- **验证**:重跑 2026-08→9 月扩列(日志表头行 ` 货运[2] 班线包车[1] 城市客运[1] 公交[2] 出租[2] 网约车[2] 轨道、轮渡[1,10] 中口径明细[2]`),新推件在这 13 格上全部正确;重跑 2026-09 生成,产物 `docs\生成汇总大表\输出\生成_道路运输量汇总表_2026-09.xlsx` 中 13 格恢复为真实 9 月值(`班线包车!S9=20647.5363`、`公交!S8=61618.09`、`出租!S6=32787.72`),**无 46266 残留**。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_扩列表头行基准列修正与母版脏格清理_2026-10-12.md`。状态:**【待验收】**。
### 10-12(3):修「9 月产物丢 8 月列 / 累计漏月」——扩列改为**以当期产物为底**【待验收】
- **现象(用户报告)**:生成的 9 月汇总大表里 **8 月列全空**,累计漏掉 8 月(规上货运量累计显示 31309.58,正确应为 1-7月 27734.46 + 8月 3665.36 + 9月 3575.12 = **34974.95**)。
- **根因(逐层证实)**:① 母版**不带"当期列"的值与公式**——`fillFreightSheet` 明确"只回填目标期当月,1..目标月-1 以母版为准",全省行公式由生成时按当期补;② 8 月的数据只落在**8 月产物**里、未回写母版;③ 9 月母版是**从 8 月母版扩列**来的 → 继承"8 月列空" → 生成时又只补 9 月 → 8 月永久空缺、累计 `=C+E+…+Q(空)+S` 漏月。
- **修复**:扩列器**优先以「当期产物」为底**(产物含当期列的值与公式)——取该期**最新产物**(导出落盘缓存 `_cache/summaryWorkbook_<period>_month__v*.xlsx`,多根目录定位),取不到才回退母版并打 WARN;另修体检规则误报(②全口径缺失时不再报"规下为负",改报"缺②全口径 → 规下无法计算",否则 9 月只有规上时会对每个市州刷屏)。
- **关键实现点**:产物缓存定位必须用 3 候选根目录(`summaryTemplateDir` → `user.dir/…` → `user.dir/../…`)——首版用单相对路径,因 `spring-boot:run` 的工作目录是**模块目录**而找不到,静默回退到了母版(表现为"改了但还是空")。
- **验证**:`docs/生成汇总大表/输出/_扩列_2026年9月_待确认_v3.xlsx`(日志确认 base=**产物** `summaryWorkbook_2026-08_month__v37…xlsx`):
  - 8 月列有值:货运 全口径 **16888.7615** / 规上 **3665.3638** / 规下 **13223.3977**;公交全省 **12315.37**;
  - 累计公式 **含 8 月与 9 月**:`=C5+E5+…+Q5+S5`;累计同比分母 `SUM(X5,Z5,…,AL5,AN5)`(2025-01~09);
  - 9 月列留空(无 9 月源数据);7 个标题页标题 **1-9月 / 9月** 正确。
- **口径结论(写进设计)**:**新母版一律从"当期产物"派生**(产物带当期数据与公式),不再从旧母版派生——否则每月都会丢"当期列",累计逐月漏数。
- **遗留**:① 待用户确认是否把 v3 落盘为正式 9 月母版(会先备份手工版);② 扩列产物中被重写的公式暂无缓存值(只写公式 + `fullCalcOnLoad`,Excel/WPS 打开自动算)——建议补"整本重算写缓存";③ `中口径明细` 表头行识别返回 `[2,4]`,需核查。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_扩列以当期产物为底_2026-10-12.md`。状态:**【待验收】**。
### 10-12(4):扩列公式克隆两处修正 + 9 月母版落盘 + 端到端验证通过【待验收】
- **修前问题(同一批次的三个)**:① 克隆"当月值列"时公式未相对右移(新列写成 `=Q7+Q9`,应 `=S7+S9`)→ 全省行取到上月数;② 克隆"当月同比列"时分子指向旧月份(`=Q5/AN5-1`,应 `=S5/AN5-1`)→ 算的是"上月值÷去年同月";③ POI `setCellFormula` **不接受前导 `=`** → 接口 500(`FormulaParseException`,§6.3 历史坑)。
- **修法**:新增 `shiftRefsAll`(克隆时对"本页/已扩列页"引用**无条件 +2**,相对复制)与 `cloneYoyCell`(不克隆,直接写 `本月值/表中定位的去年同月-1`,即 C3 口径);公式串去掉前导 `=`。
- **9 月母版落盘(用户已确认)**:手工版备份为 `_bak_2026年9月母版_手工版_20261012.xlsx`;新母版 = "8 月产物 → 扩列",1,083,567 B;输出目录命名理顺(最新件 `_扩列_2026年9月_待确认.xlsx`,旧版加 `_bak_` 前缀)。
- **端到端验证(用新母版生成 2026-09)**:
  - 货运 8 月列有值:全口径 **16888.7615**、规上 **3665.3638**、规下 **13223.3977**;
  - 9 月列:全口径 3575.1211(②表未导,只有①规上)、规上 3575.1211;
  - **累计:全口径 133887.0138(=1-8月 130311.89 + 9月 3575.12)、规上 34974.9459(=27734.46+3665.36+3575.12)、规下 98912.0679** ✓ 与手算一致;
  - 公交:8 月 12315.37、累计 110776.34 ✓。
- **遗留**:① 扩列产物被重写的公式无缓存值(建议补"整本重算写缓存");② `中口径明细` 表头行识别返回 `[2,4]` 待核查;③ ②表(全口径)9 月未导入前,"全口径"行显示等于规上(公式 =规上+规下、规下为空),体检已提示,导数据后自动正常。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_扩列公式克隆修正与9月验证_2026-10-12.md`。状态:**【待验收】**。
### 10-12(5):修「9 月公交/出租月报导不进去」——导入改按表头名定位列【待验收】
- **现象**:用户导入 9 月公交/出租月报反复失败;`import_batch` 无记录、`city_bus_monthly`/`city_taxi_monthly` 无 2026-09 行 → **解析阶段即抛错**(没进写库)。
- **根因(实测三份文件)**:9 月模板比 7 月**少列导致整体左移**——公交 68→**66** 列(少 `统一社会信用代码`、`填报单位`,第 3 列起左移 2);出租 41→**40** 列(少 `填报单位`,左移 1)。导入器原是**按固定列号取值 + 固定列位校验** → 校验直接抛「与文件内容不符」。必需列按名都在,是列位不匹配;且取值也按固定列号,不改会整体读错列。
- **改动(按 I4 口径兼容模板差异)**:新增 `colByName(hdr, fallback, name[, occurrence])`(按表头名取列,未命中回退原固定列号)与 `requireHeaderColsByName(...)`(只校验必需列按名存在、不校验列位);`importCityBus`/`importCityTaxi` 所有字段改为按名取值;公交重复表头「其中:城市内」(2 次)用出现序号区分(`stopCity`=1、`passengerCity`=2)。映射取自实测表头(公交 42 字段、出租 37 字段全部命中)。
- **验证**:列位差异已定位;名称映射完备(42/42、37/37);校验放宽仍保留"真缺列"的负向拦截;编译通过、后端已重启(PID 40592,13:17:38)。
- **待办**:**请用户在页面重导这两个 9 月文件**(助手不代导);导入后助手做只读抽查(行数/市州/与源文件逐列对齐,尤其"城市内/城际城乡"口径字段)。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_公交出租导入按表头名定位_2026-10-12.md`。状态:**【待验收】**。
### 10-12(6):修「城市分市州当月块标题停在 7 月」——标题写入行号差一行的 bug【待验收】
- **现象**:9 月产物(8 月产物同样)里 `城市分市州` 显示"城市客运客运量分市州**7月**情况",标题不随月份更新。
- **根因(代码行号差一行)**:母版里当月块的**标题在 `A45`、单位在 `A46`**(周转量块是 `A67`/`A68`),但程序写的是 0 基 `45`/`67` = **Excel 第 46/68 行** → ① 真标题行 `A45/A67` 从未更新(一直停在母版旧月份);② 程序的标题**覆盖了"单位:万人次/万人次公里"行**。累计块 `0/22` 正确,其余页(城市汇总 `0/11`、中口径分析 `0/9`、道路运输周转量 `0/22`、两张排名)行号均已核对无误。
- **改动**:① 代码 `smSetTitle(sh,45,…)`→`44`、`smSetTitle(sh,67,…)`→`66`;② 母版被覆盖的 `A46/A68` 用 **XML 精准改格**恢复为"单位:万人次 / 单位:万人次公里"(复用文件内既有共享字符串索引,不整本重写)。
- **验证(生成 2026-09 实测)**:`A45/A67` = `城市客运客运量/客运周转量分市州**9月**情况` ✓;`A46/A68` = `单位:万人次 / 单位:万人次公里` ✓;累计块 `A1/A2/A23/A24` 正常 ✓。
- **遗留(待用户确认后做)**:① `城市分市州` S50:S66 与 `道路运输周转量` I27:I43 各 **17 个 `#DIV/0!`**(占比分母=全省行在无数据月被写成 0)→ 建议"生成收尾统一错误值留白 + 母版占比公式加 IFERROR 兜底";② `中口径分析` 9 月**网约车行**值 0/同比 −1(9 月网约车数据未导,属缺数);③ `中口径明细` D107/D108/F107/F108 为硬编码 `0` 公式(母版既有);④ **用户提出的"格式调整"尚未给出具体位置**,待提供后同步母版。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_城市分市州当月标题行号修正_2026-10-12.md`。状态:**【待验收】**。
### 10-12(7):用户决定——以下三项**暂不处理**(记录,勿再作为待办提出)
- **明确决定(2026-10-12)**:以下三项用户决定**不改**,后续会话不要再当成待办重复提出;若用户以后主动提起再议。
  1. `城市分市州` S50:S66 与 `道路运输周转量` I27:I43 的 34 个 `#DIV/0!`(占比公式分母=全省行在无数据月被写成 0)——不做"错误值留白/IFERROR 兜底"。
  2. `中口径分析` 9 月网约车行(值 0、同比 −1,因 9 月网约车数据未导)——不额外处理,等数据到位自然恢复。
  3. 表格格式调整同步母版——用户不再提供具体改动,母版不做格式同步。
- **本日已完成并待验收的改动(汇总)**:Step 0 表头动态定位(`6d1ac61`)、货运体检 6 条规则(`91f6583`)、扩列以当期产物为底(`fb269f6`)、扩列公式克隆修正 + 9 月母版落盘(`3b3652e`)、公交/出租导入按表头名定位(`797f03b`)、城市分市州当月标题行号修正(`64f6466`)。
### 10-12(8):按用户要求收敛为「一个母版」+ 母版格式按用户调整版【待验收】
- **用户要求(2026-10-12)**:格式按用户手工调整过的《生成_道路运输量汇总表_2026-09 (3).xlsx》来;母版只要一个。
- **已完成**:
  1. **母版收敛为一本**:`docs/生成汇总大表/` 下只留 `2026年9月道路运输量汇总表.xlsx`;把 7 月母版、8 月母版、8月版式原型、9月试做件、**版式参照件《生成_道路运输量汇总表.xlsx》** 共 5 件移入 `docs/生成汇总大表/归档/`(`_备份_`/`_bak_` 按 A3 仍留原地作回归对照,不算母版)。
  2. **停用参照件**:`exportSummaryWorkbook` 不再调用 `applySummaryReferenceLayout`(`widthApplied=0`),**版式一律以当期母版为准**(日志不再出现"套用参照件列宽")。
  3. **用户样式套入母版**:用 Excel COM 精确套用(109 列宽 + 3 行高 + 1348 格字号 + 32 格单元格格式),并去掉母版 `fullCalcOnLoad` 以免 Excel 打开即重算。
  4. **验证**:生成 2026-09 → **产物与母版的列宽/行高/字号完全一致(差异 0)** ✓;与上一版产物比 **结构差异 0** ✓。
- **两处残留(均不可见,已核实)**:① 列宽 226 处 **±0.01**(Excel 按 1/256 字符存宽度)✓;② 32 个**空白格/合并区覆盖格**的填充与字体色(Excel 保存对空格格式的处理差异)✓。
- **一处需用户拍板的数值变化**:本次生成件 `中口径排名` 有 **46 格**(同比/排名,如 `D3` 0.0581→**0.0402**、`E4` 第10→第**9**)与上一版不同;**新值与《中口径分析》页逐位一致**(`B3=35028.0636`、`C3=0.04015856`)——即排名页与明细/分析页口径统一(原旧值是该页在母版里的旧缓存)。**保留新值 / 回退旧值待用户确认**。
- **归档说明**:`归档/` 内 5 件历史母版/版式件仍可随时取回(未删除);母版目录以后只放"当期一本"。
- **状态**:**【待验收】**。
### 10-12(9):扩列器加「整本重算写缓存」+ 明确保留中口径排名新值【待验收】
- **问题定位(用户问"为什么产生这 46 格差异")**:母版里**大量公式只有公式、没有缓存值**(POI 写公式不带缓存)。实证:母版经 Excel 保存前后 **约 2.47 万格**由"空"变"有值"(如 ` 货运!U5: 空→130311.8927`)。`中口径排名` 的同比/排名由程序**读母版缓存**计算(方案 A)→ 缓存空时算旧值 `0.0581`,缓存补齐后算 `0.0402`(**与《中口径分析》逐位一致**)。**新值才是数据完整时的正确结果**。
- **改动**:`SummaryLayoutExpander` 新增 `recalcAndCache(wb)`(`clearAllCachedResultValues()` + `evaluateAll()` 写回缓存,失败仅 WARN),在 `expand()` 与 `fixTitles()` 中调用。
- **验证**:扩列 2026-08 → 公式格 **39,961** 个,**空缓存仅 4 格**(全在 ` 货运`,POI 无法求解的外部引用,Excel 打开会算);修复前同类母版约 2.47 万格无缓存。
- **用户决定**:`中口径排名` 那 46 格**保留新值**(与中口径分析一致,口径统一)。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_扩列整本重算写缓存_2026-10-12.md`。状态:**【待验收】**。
### 10-12(10):9 月导入核验 + 出表抽查通过;9 月仍缺数据清单【待验收】
- **9 月导入核验(只读查库)**:城市公交 **141 行**、巡游出租 **17 行**、公路旅客 H2031 **767 行**、货运企业 H2032 **636 行** → 全部成功(**公交/出租的"按表头名定位"改动实测有效** ✓,`import_batch` 551/552 可见)。仍缺 9 月:**②《货运量周转量表》(全口径)0 行、③规上规下拆分表 0 行、网约车订单/全省 pin 0/0、个体客运 0 行**(用户 2026-10-12 说明:其他数据暂时还没有)。
- **出表抽查(产物落 `docs/生成汇总大表/输出/生成_道路运输量汇总表_2026-09.xlsx`)**:公交 9 月客运量 **13476.35**、城市内 **12021.00**、出租客运量 **5626.81**、城市内 **5139.61** —— 与库内 Σ17 市州**逐位一致** ✓;累计已含 9 月(公交累计 **124252.69** = 1-8月 110776.34 + 9月 13476.35)✓。因②未导,9 月《 货运》页"全口径"暂等于规上(3575.1211)、"规下"为 0 —— 属缺数,非算错。
- **小待办**:公交 9 月 **141 行** vs 1-8 月各期 **142 行**(少 1 行),待核是源文件少行还是导入跳过(可能是空行/汇总行)——用户说先这样,留待以后。
- **本机限制**:助手沙箱不能写 `D:\下载`,生成件只能落在仓库内(`docs/生成汇总大表/输出/`);正式下载请在页面点生成/下载。
- **状态**:**【待验收】**。
## 最新(2026-10-12,zyj 线)
### 10-12:扩列器补「标题按母版期次重写」+ 修正 8 月母版标题【待验收】
- **用户反馈**:9 月版式件与 8 月母版里,7 个页签的标题仍是 `1-7月 / 7月`(货运量排名、货运周转量排名、城市汇总、城市分市州、中口径排名、中口径分析、道路运输周转量)。
- **根因(两条)**:① 按已确认口径这 7 页是 C 类页——**标题由生成程序在出表时现写**(`ReportExportService :969 / :1011 / :2707 / :2891 / :4446 / :4498 / :4499 / :4604` 均按 period 写),母版里的文字不参与出表,所以扩列器原本没动它们;② **我的实现确实漏了"标题 +1"这一步**——《扩列配置·核对版》动作 7 写了"标题:页面标题月份+1(逐页核对)",我只做了 8 个台账页的表头克隆。
- **修复**:扩列器新增 `applyTitles(...)`——按**母版期次**重写标题(累计=`1-M月`、当月=`M月`),只处理 7 个标题页、**命中标题标记才改**(避免误伤 ` 货运!A1` 这类备注),4 位年份一并按目标年重写;新增只读接口参数 `?titlesOnly=true`(只改标题不扩列)。
- **8 月母版已修正**:7 页标题 `1-7月/7月` → **`1-8月/8月`**(修正前备份 `docs/生成汇总大表/_bak_2026年8月母版_标题修正前_20261012.xlsx`);19 页签与公式抽查无损(`中口径明细!C5`、`公交!C5` 全省行公式、` 货运!A1` 备注均正常)。
- **9 月版式重跑**:7 页标题 → **`1-9月/9月`**;产出 `docs/生成汇总大表/输出/_扩列_2026年9月_待确认_v2.xlsx`(1,037,071 B)。
- **与手工 9 月母版复比**:851 条差异 = 8 个台账页 836 条(沿用 10-10 分类:累计/分母是否扩到 9 月 548、分隔符 153、表名引号 130、浮点尾差 1)+ **标题页 15 条**(手工件标题为滞后的 `1-8月/7月`)。
- **踩坑**:重跑时目标文件被 Excel/WPS 占用(`being used by another process`)→ 先落 `_v2` 命名;用户关闭后可用原名重写。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_汇总大表扩列器标题修正_2026-10-12.md`;日结 `docs/工作日结/工作日结_2026-10-12.md`。
- **待用户验收/确认**:① 标题口径按"**标题期次=母版期次**"(8月→1-8月/8月、9月→1-9月/9月)是否正确;② `_扩列_2026年9月_待确认_v2.xlsx` 是否改名为正式名(原名那份是旧内容、被 WPS 存过,未经同意不动);③ 累计/累计同比"是否扩到 9 月"(产出=已扩、手工版未扩)。
- **状态**:**【待验收】**。
### 10-12(2):货运口径「导出前基数体检」(B4)6 条规则落地【待验收】
- **背景**:规下 = ②《货运量周转量表》全口径 − ①H203-2 规上÷10000,是**倒减**——①漏报会让规下虚高、极端还会算出负数。用户 2026-10-12 同意把这组规则加进 B4。
- **实现**:新增 `reportexport/calc/FreightReadinessCheck.java`(只读);接入 `exportSummaryWorkbook` 的缺数收集 `dbProblems`(随导出日志输出);新增只读接口 `GET /api/report/summaryWorkbook/freightCheck?period=YYYY-MM`。
- **规则**:① 某市州规下为负;② ②有全口径、①无规上记录(疑漏报→规下=全口径);③ ②全口径 < ①规上;④ Σ17 市州 ≠ ②"湖北省"行(容差 0.01);⑤ **本月与上月完全相同**(疑重复导入,两侧 ≥50 万吨/万吨公里);⑥ **同比异常**(|去年同月→本月| > 50%,两侧 ≥50);⑥' 累计勾稽(①周转量 1..M 求和 ÷10000 vs ③拆分表 CUMULATIVE)。
- **阈值修正(实测驱动,重要)**:首版用"规下环比 > 30%" → 2026-02 命中 22 条、2026-03 命中 32 条,复核确认**全是春节季节性**(各市州 2 月 −30~−40%、3 月 +30~+60%),非数据错误 → 改为"重复导入特征 + 同比>50%";并给判据加**绝对门槛 50 万吨/万吨公里**,避免神农架林区(20~46 万吨)这类小基数噪声长期报警。
- **实测**:2026-01~08 **全期 0 命中**(无误报);②表 `last_freight_m08`/`last_turnover_m08` **18/18 行有值** → 同比规则确实参与计算(非空跑)。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_货运基数体检B4六条规则_2026-10-12.md`;日结同日两条。
- **待用户验收/确认**:① 阈值(绝对门槛 50、同比 50%)是否合适;② 是否现在做 B4 剩余部分——导出前弹窗 + 生成件《数据缺失清单》页(P0-3 剩余)。
- **状态**:**【待验收】**。只读功能,未改动业务数据。
### 10-12(3):生成数据「验证方法」成文(五段链条 + 反同源盲区)
- **成文**:`docs/汇总大表生成数据验证方法_2026-10-12.md`(回答"如何验证程序生成的数据是否正确")。
- **口径**:把问题拆成 4 问(源数据 / 算法 / 版式 / 与定稿一致),每段配一个**独立于该段的参照**;链条五段 L0 源文件→库、L1 库→口径值、L2 口径值→单元格、L3 单元格→整本、L4 跨页合成页勾稽;**通过标准 L0~L4 已写死**(任一层未覆盖,结论不得写"已验证")。
- **对既有"四层验证法"(10-08/10-12 会话)的三处补强**:① 补 L0 源数据层与**反同源盲区**——"生成件 vs 定稿"在母版与定稿同源时查不出源数据问题(今日 2025-11 两处即例);② **体检通过 ≠ 数据齐全**,异常清单与缺数清单分开输出(今日 2026-08 体检 0 命中,但 9 月件 8 月列仍空);③ 必须专门做一次「库内值 vs 母版缓存」全量 diff(10-09 待办)——**出表口径不切库**与**验证必须比一次**并不矛盾。
- **佐证**:2026-08 vs 9/13 定稿(1020 条 → 11 条关注,算法层通过);库内 2025 vs 母版 2025(公交/出租/轨道轮渡 100% 一致,3 处需业务确认,报告见 `docs/功能测试报告/功能测试报告_库内2025与母版2025逐格核对_2026-10-12.md`)。
- **状态**:文档类,无需验收。
- **B4 关联(已核)**:10-12 上午的货运基数体检 B4 已由另一会话提交(`91f6583`,报告 `docs/功能测试报告/功能测试报告_货运基数体检B4六条规则_2026-10-12.md`);本次 2026-08 核对实际调用了它的 `GET /api/report/summaryWorkbook/freightCheck`(2026-01~08 全期 0 命中)。
### 10-12(4):汇总大表「缺数清单」落地(只读接口 + 接入导出日志)【待验收】
- **动因**:用户要求把「缺数」显式摆到台面上——当日两个真实问题(9 月生成件 8 月列为空、9 月周转量全 0)都属"该有的数没有",而 `freightCheck` 体检当时 **0 命中**,两者必须分开。
- **实现**:新增 `reportexport/calc/SummaryMissingDataCheck.java`(只读);接口 `GET /api/report/summaryWorkbook/missing?period=YYYY-MM`;接入 `exportSummaryWorkbook` 的 `dbProblems`(随导出日志输出)。
- **口径**:① 逐月回填页(班线包车/公交/出租/轨道轮渡)查 1..目标月 来源是否有数、17 市州是否齐全;② 货运/网约车只回填目标月,查目标月各项来源(货运①+②+③、网约车订单+全省 pin+出租平均运距);③ 这两页的历史月由母版承担——**母版与同期备份母版(donor)都没有数**才算缺口(否则会误报 7 月那种"骨架母版 + donor 还原")。
- **实测**(独立 8099 实例,未打扰 8090,测完已关;`mvn -o compile` exit=0):2026-08 **0 条**、2026-07 **0 条**、2026-09 **11 条**(班线包车/公交/轨道轮渡/出租 无源 4 条 + 货运②③ 2 条 + 网约车 3 条 + 母版 8 月列空 2 条)——命中的正是当日两个真实问题。
- **修正**:首版只比母版 → 误报 2026-07 两条;已按生成链实现补上 donor 比对,复测 0 条。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_汇总大表缺数清单_2026-10-12.md`。
- **待办**:导出前弹窗 + 生成件《数据缺失清单》页(与 B4 的 P0-3 合并)。
- **状态**:**【待验收】**(只读功能;未落盘、未改业务数据)。
## 最新(2026-10-10,zyj 线)
### 10-10:Step 1 扩列器落地 + 8→9 月版式首轮产出【待验收】
- **新增扩列器**:`traffic-audit-server/.../reportexport/layout/SummaryLayoutExpander.java`;新增只读接口 `GET /api/report/export/summaryWorkbook/expand?period=YYYY-MM`(返回字节、**不落盘**);`ReportExportService.expandSummaryWorkbook(period)` 负责取当期母版并调用。规则依据 `docs/汇总大表母版扩列配置_核对版_2026-10-09.md`(8 个可见台账页;4 个隐藏页不扩列但同步平移其跨页引用)。
- **产出(待确认件,未落盘为母版)**:`docs/生成汇总大表/输出/_扩列_2026年9月_待确认.xlsx`(1,036,939 B,2026-10-10 09:30:07)。只做版式,9 月数据列留空。
- **与手工 9 月母版逐格比对**:**` 货运` 差异 = 0**(规则正确的最强证据);其余 7 页共 836 条差异,**全部非数值分歧**,分为四类:
  1. **548 条**:产出把「累计/累计同比分母」扩到 9 月,手工版未扩——正是 09-29《扩列进度》认定的待修项 ③④("累计列只算到 8 月""去年基数只到 8 月"),即**手工 9 月母版这 7 页尚未修完**;
  2. 153 条:分母新增项分隔符写法(`SUM(a+b+…,c)` vs `SUM(a+b+…+c)`,等价同值);
  3. 130 条:表名引号写法(`轨道、轮渡!C6` vs `'轨道、轮渡'!C6`,Excel 规范化所致,同值);
  4. 1 条:浮点尾差。
- **8 月及以前列**:仅 28 条差异且全部属第 3 类引号写法(集中在 `城市客运`),未动数值/列号。
- **过程中修掉的两个实现缺陷**(重要,避免复现):
  1. POI 5.2.5 的合并区 API 是 `addMergedRegion(CellRangeRangeAddress)`、`removeMergedRegion(int)`(无 CellRangeAddress 重载)——按下标摘除、按对象添加;
  2. 引用正则最初只认 ASCII 表名,**漏掉母版里 5,574 处"未带引号的中文表名"引用**(如 `轨道、轮渡!C6`)→ 已把表名字符类扩到 CJK,修正后列号与手工真值一致。
  3. 写件用 **POI**(与生成链路同源),不用 openpyxl(本项目历史上有 openpyxl 写出导致 Excel 拒绝打开的案例)。
- **报告(本地、不入库)**:`docs/功能测试报告/功能测试报告_汇总大表扩列器8月到9月版式_2026-10-10.md`;日结 `docs/工作日结/工作日结_2026-10-10.md`。
- **待用户验收/确认**:① 累计列与累计同比分母**是否应扩到 9 月**(产出=已扩;按 09-29 待修清单,方向与当时认定一致);② 确认后是否把产出落盘为正式 9 月母版(按已确认口径:人工确认后落盘)。
- **状态**:**【待验收】**(版式类改动)。未导入任何业务数据、未改动生成主链。
- **下一步**:按确认结论微调(如需)→ 复跑 8→9 → 接入主链(`resolveSummaryMother` 找不到目标月母版时自动扩列)+ 归档目录与版式参照件按 C4 收尾。
## 最新(2026-10-09,zyj 线)
### 10-09:2025 数据现状核验(结论:已在库,无需补录)+ M0 规格补第十二节
- **核验方式**:只读查询库 `127.0.0.1:3308/traffic_audit`(MySQL 8.0.29),未导入、未修改任何数据。
- **2025-01~12 各 12 个月齐全**:`city_bus_monthly`、`city_taxi_monthly`、`wyc_order_monthly`、`wyc_total_monthly`、`h2031_enterprise_monthly`、`h2032_enterprise_monthly`、`passenger_individual_monthly`。
- **两张"不以为缺口"的表**:`freight_turnover_import` 仅 2025-12,但表带 `last_freight_m01..m12` / `last_turnover_m01..m12`,2026 各期文件自带去年同月值;`scale_split_transport` 无 2025,但表带 `above/below/total_yoy`,同比已随 2026 各期入库。
- **修正早前判断**:09-07 方案文档"2025 未入库"的说法已过期(09-16 后补录过多年度数据);`ReportExportService.java:499 / 558 / 561` 三处"待 2025 年定稿数据导入后自动出现"的提示条件已不成立。同比取数走库内去年同期(`aggOf(data, year-1, m, "湖北省")`,约 540 行)。
- **遗留的是口径问题,不是缺数据**:中口径排名/明细的 2025 列仍以母版静态定稿值为准(`readMidDetailLastYearCumulative`,`ReportExportService.java:2745` 起),注释(2686-2689 行)说明原因是"排名页原先查库现算,两者在 2025-03/04 网约车拆分上不同"。→ 需先做「库内 2025 vs 母版 2025」逐项 diff,交业务确认基准后再决定是否切换读库(切换必须过 diff=0 回归)。
- **规格更新**:`docs/汇总大表M0版式重建器规格_2026-10-06.md` 新增第十二节(三层职责 / 一表一粒度 / 调整值覆盖层 / 2025 实测核验 / 结果层可选 / 「母版不留数据」红线 / 与 M0 的依赖顺序)。
- **状态**:本节与规格第十二节均为【待验收】;未改动代码、未导入数据。
### 10-09(2):查证既有拍板——同比基准以母版缓存为准;扩列按月按需
- **同比基准(用户指出,已查证;先前判断修正)**:2026 与 2025 的同比**以母版缓存为准**,库只做校验、不直接替代。出处:`docs/要求与验收基线清单.md` F8(✅ 口径确认)、`docs/确认回执汇总与剩余疑问_汇总大表数据驱动改造_2026-09-07.md` Q1、`docs/汇总大表数据驱动改造方案_2026-09-07.md` 第九节、`docs/待确认_汇总大表数据驱动改造问题清单_2026-09-07.md` A1、`docs/问题汇总/汇总大表问题交接_2026-09-21.md` 方案 A(已实施)。切换唯一前提 = 人工核对并重导一致。
  - **修正**:本日上一条"中口径 2025 遗留口径待定"的说法作废;库内 2025 现算值不得直接替代母版静态定稿值。
- **扩列方式(既有拍板,与 M0 规格冲突)**:`docs/要求与验收基线清单.md` F10 = **按月按需扩列,不预做 12 月满版**(✅ M0 v4);改造方案 v1.1(09-08 用户拍板)同口径,正文"12 月满版列版式"建议已作废。M0 规格第九/十一节的"满版式"建议**待用户裁定**。
- **已有 09-29 扩列产物(本地未入库)**:`docs/问题汇总/_扩列规格表_2026-09-29.md/.csv`(19 页逐页规格)、`_扩列配置初稿_20260929.md/.csv`、`_扩列计划_v3..v10.json`、`_扩列进度_20260929.md`;试做件 `docs/生成汇总大表/2026年9月道路运输量汇总表_试做_20260929.xlsx`(数值未修完,勿用于出表)。
- **规格更新**:`docs/汇总大表M0版式重建器规格_2026-10-06.md` 新增第十三节(既有拍板核验,优先级最高);并修正 12.4 的处置结论。
- **状态**:【待验收】;未改动代码、未导入数据。
### 10-09(3):已确认口径全量核验 + 09-29 扩列规格转正入库 + M0 规格改写
- **口径核验范围**:`docs/要求与验收基线清单.md`、`docs/确认回执汇总与剩余疑问_汇总大表数据驱动改造_2026-09-07.md`(唯一决策基线)、`docs/待确认_汇总大表数据驱动改造问题清单_2026-09-07.md`、`docs/问题汇总/汇总大表问题交接_2026-09-21.md`、`docs/问题汇总/中口径排名同比与城市客运列错位_根因与长效方案_2026-09-18.md`、`docs/问题汇总/数据查看汇总与汇总大表口径对应关系_2026-09-23.md`。
- **关键已确认项**:F1(全精度存储+显示两位小数)、F8(母版缓存优先作同比基准,库仅校验)、F10(扩列按月按需、不预做 12 月满版、新增列为两行纵向合并标题)、A1(只覆盖 2026 动态块,2025 及以前不重算)、A3(备份还原验证通过前保留)、A4(母版只当版式模板)、D1-D5(D3 每年新开一本、2026 只到 12 月)、E1-E3、C1-C7(C5 中口径排名/分析只由中口径客运量页生成、C6 周转量系数固定、C7 城市汇总口径)、C3(累计同比分母按表头定位"去年 M 月"列)、C4(版式对齐按表头文字匹配列)、确认回执六.4/六.5(两行合并标题、母版文本数字归一)。
- **撤回三处此前误述**:① "12 月满版式"(与 F10 / 六.1 冲突);② "历史参照值入库、同比切库值"(与 F8 / Q1 冲突);③ "停用 `_备份_` donor 还原"(与 A3 冲突,须验证通过后再做)。
- **规格转正入库(2026-10-09)**:`docs/汇总大表母版扩列规格_2026-09-29.md` / `.csv`(19 页逐页规格)、`docs/汇总大表母版扩列配置初稿_2026-09-29.md`(逐页列位配置 + 硬前提)。原文件在 `docs/问题汇总/_*`(被 `.gitignore:118` 挡住、仅本机),本次按正式文件名入库,原 `_` 文件保留本地。
- **新增关键硬前提**(来自配置初稿第五节):`SM_CUR_COL0=2`(2026年1月=C)与 `SM_LAST_COL0=21`(2025年1月=V)是**写死的列位置**,插列后四张跨页合成页会读错 2025 基数 → **扩列前必须先改成按表头动态定位**。
- **M0 规格改写**:第九/十一节"满版式"表述就地作废;新增第十四节《最终执行口径》(6 条动作 + 逐格 diff 验收 + 未决项)。
- **未决**:扩列走"程序自动"(09-21 §5.3 方案 A)还是"本机 Excel 小工具"(方案 B)——09-21 交接 §11.2 未记录结论,09-29 产物为"程序生成计划 + 人工确认"混合路线,待用户确认。
- **状态**:【待验收】;未改动代码、未导入数据。
### 10-09(4):扩列口径拍板——程序扩列、范围 8 页、4 个隐藏页保留隐藏
- **用户拍板(2026-10-09)**:① 扩列方式 = **程序扩列**(扩列器);② 扩列范围 = **8 个可见台账页**(` 货运`、`班线包车`、`城市客运`、`公交`、`出租`、`网约车`、`轨道、轮渡`、`中口径明细`);③ **4 个隐藏页保留并继续隐藏、不纳入数据加工**(`公路总客运`、`2025年城市客运量`、`中口径客运量`、`中口径计算过程`),不插列、不改公式。
- **母版构成实测(openpyxl + xl/workbook.xml)**:**15 个可见页签 + 4 个隐藏页签**,隐藏状态为 `state="hidden"`(非 veryHidden,右键标签可取消隐藏)。`公路总客运` 40×274、`中口径客运量` 189×68、`中口径计算过程` 217×11、`2025年城市客运量` 16×13。
- **消解两处矛盾**:09-29《扩列规格表》把 `中口径客运量`(页签 18)标为 A 类、且 09-29 进度里已插列的 8 页没有它;《配置初稿》又把它标成"无 2026 月份对"。按本次拍板统一为**不加工**;两份文档已就地追加《口径补充(2026-10-09)》。
- **字母陷阱记档(避免再混)**:09-21 交接 §5.3「方案 A=程序自动扩列 / 方案 B=Excel 小工具」,与 09-28/09-29 工作日结「方案 A=人工做母版 / 方案 B=扩列器」**字母相反**。后续统一写"**扩列器(程序)**",不再用 A/B 字母。
- **易混淆点记档**:`中口径明细` 页的 A1 标题本身就写作"中口径客运量",与隐藏页签 `中口径客运量` 同名——文档与口头沟通务必带页签位置(第 13 位 vs 第 18 位)。
- **仍待确认(仅一项)**:扩列产物是自动落盘为下期母版,还是每次人工确认后再落盘(建议后者,与 A3/A4 一致)。
- **文档更新**:`docs/汇总大表M0版式重建器规格_2026-10-06.md` 第十四节已定项替换"未决项";规格表与配置初稿各追加口径补充。
- **状态**:【待验收】;未改动代码、未导入数据。
- **(同日已确认,非待确认项)落盘与文件管理**:扩列产物**先落 `docs/生成汇总大表/输出/`**(`_扩列_YYYY年M月_待确认.xlsx`),**人工确认后**才重命名落盘为当期母版;目录只留**当期一本**母版,历史期移入 `docs/生成汇总大表/归档/`,`2026年8月…_版式原型.xlsx` 一并归档;版式参照件 `生成_道路运输量汇总表.xlsx` 在扩列器跑通后归档(归档前做 C4 两步:列宽/隐藏一次性固化进母版 + `applySummaryReferenceLayout` 改按表头文字匹配列)。
- **实施要点(实测细节,非决策项)**:母版 vs 参照件实测 **列宽 320 处、隐藏标记 31 处**不同(` 货运` 77+8、班线包车 109、中口径明细 32+14、中口径排名 17+9 等);`copyColumnWidth`(`ReportExportService.java:1186`)**只复制宽度、不复制 hidden**,扩列器克隆月份列时须补 hidden。
### 10-09(5):Step 0 落地——四张跨页合成页取数改为**按表头动态定位**月份列【待验收】
- **改动**:`ReportExportService` 中 `SM_CUR_COL0 = 2`(2026年1月=C)/ `SM_LAST_COL0 = 21`(2025年1月=V)**废弃**,改由新增的 `smMonthCols(sheet, year)` + `smYearMonthOf(cell)` 按表头定位;`smSumMonths` 改吃「月份→列号」映射。**只换取数方式,不改版式与数值口径、不做扩列**。
- **为什么必须先做**:该写死列位是 09-29《配置初稿》第五节标明的"硬前提"——一插列,2025 块右移,四页会读错去年基数(对应已确认口径 C3/C4)。
- **表头三形式兼容**(实测 8 月母版确为三种混用):文本 `'2026年3月'`、裸日期序列号(`46082`,General,出租页几乎整行)、真日期 + `yyyy"年"m"月"`(` 货运`)。排除含「累计/同比/环比」的表头与非当月 1 号的数值;年份不匹配(2024/2023 块)不认。
- **验证(关键,重做过一次)**:旧代码实例(java PID 5716)生成 2026-08 作基线 → 新代码实例(java PID 32368,10:07:58 启动)生成 2026-08 → **逐格 diff = 0**(公式/文本 0、缓存值 0,覆盖 19 页);无"未识别到月份表头列"告警;2026-07 亦正常出表。
- **踩坑(务必记住)**:首次对比的"0 差异"是**假的**——旧后端仍占 8090,`start-dev.ps1` 因端口已监听而跳过启动,且其报出的 PID 与真实监听 PID 不一致,导致误判"已换新进程"。**判断是否换了进程,必须看 `netstat -ano` 的真实监听 PID + 日志里的启动时间/PID,不能只信启停脚本输出。**
- **其它确认**:后端日志中文为 **GBK**(`Select-String` 中文模式匹配不到,需用 PID/类名等 ASCII 锚点);两次产物 sha256 不同但 29 个 zip 条目内容全同(差异仅在 zip 容器元数据)。
- **报告**(本地、不入库):`docs/功能测试报告/功能测试报告_汇总大表列位置表头动态定位_2026-10-09.md`;日结 `docs/工作日结/工作日结_2026-10-09.md`。
- **一致性旁证(2026-10-09,作为 Step 0 验收材料)**:用 `docs/工具/汇总大表差异比对.py` 把**新代码产物**与**手工定稿** `D:\05_数据分类\汇总表\8月汇总定稿\2026年8月客运量、货运量定稿.xlsx`(9/13 版)逐格比对,明细 1020 条:
  - 实质数值差异 **10**:全在《 货运》`DZ` 列(2022 年累计同比,仙桃/潜江/天门/林区)——即 09-21~09-28 已确认"**软件正确**"的那 10 条;
  - 需处理(非数值文本) **1**:班线包车 `IM50`(仙桃 客运量同比),生成件为数值 `0.0077858…`,手工侧值是**反引号脏字符**;
  - 错误值(手工) **364**:程序侧留空、手工侧 `#REF!`/`#DIV/0!`,属已确认的"历史错误值留白"口径;
  - 用户手工改动 **1**:`城市汇总!G20` 措辞(已登记 `USER_EDITS`);
  - 其余 1009 条为已按口径忽略的结构/格式类(结构/设计、无表头草稿列、排名表当月/累计块、文本型数字 354、取整尾差、单边有值、措辞等)。
  - **结论**:与手工定稿**数字一致**,无新增需处理项;比 09-29"需处理=0"多出的部分全部源于该定稿为 **9/13 版**、尚未同步 09-28 之后的手工改动(措辞/清 0/错误值留白/按软件值同步)——属定稿滞后,非程序回归。报告(本地):`_tmp/_step0/diff_0813.md` / `.csv`。
- **状态**:**【待验收】**(取数方式属口径相关改动)。未导入任何业务数据。
- **下一步**:Step 1 扩列器本体(配置驱动,8 个可见台账页;§5.2 三条必改点;产物先落 `输出/` 待人工确认后再落盘为下期母版)。
## 最新(2026-10-06,zyj 线)
### 10-06:拉取合并 + 验收门禁分级 + 汇总大表 M0 立项
- **拉取合并**:`origin/main` 由 `8b739ce` 更新到 `54e10ae`(同事 xyc 38 个提交:节假日专项统计、观测站分日调查导入、v1.0.0 版本管理、打包与 Windows 服务自启等)。本地未推送提交 `ef85b05`(09-29 交接)保留,合并提交 `bee9e18`,无冲突;合并后相对远端的差异正好只有本地的 3 个文件。
- **验收门禁分级(用户 2026-10-06 确认,参考同事做法)**:一般功能 / 修复 / 重构沿用「测试通过即提交推送」;口径类 / 版式类 / 任何会改输出数字或表格版式的改动,照常提交推送,但必须在 HANDOFF 标注 **【待验收】**,用户验收通过后再补一条 `docs(交接): …` 提交改为「已验收(日期)」。规则已写入 `AGENTS.md` 第 5 条。
- **汇总大表 M0 立项(规格待审定)**:新增 `docs/汇总大表M0版式重建器规格_2026-10-06.md`。结论 **不重写**——计算层(`reportexport/calc` 约 900 行)、回填层(`SummaryWorkbookFiller` 899 行)、扩列原语(`moveColumnPair` / `cloneColumnPair` / `cloneCellForMonth` / `cloneMergedRegion` / `copyColumnWidth` / `fixCumulativeFormulas`,`ReportExportService.java:1039-1200`)均已在用;缺口只是把这些原语编排到 10 个需扩列长表页(已列页规格表,约 2.45 万处公式平移)。
- **工作量重估**:M0 约 **3.5–5 天**(含测试与验收),此前 09-29 记的「0.5~1 天」偏乐观,只算了原语复用。
- **卡点未变**:`resolveSummaryMother`(`ReportExportService.java:4576`)只精确匹配《{year}年{month}月道路运输量汇总表.xlsx》,目标月无母版即报错;9 月母版仍为用户 09-29 手工扩列产物(本机未入库)。
- **待确认**:① 扩列蓝本用 9 月手工版还是 8 月版;② 是否一次建成 12 月满版式(方案 v1 建议满版式)。
- **状态**:本段与 M0 规格均为【待验收】;本轮未改动任何代码。工作区未跟踪的 `docs/生成汇总大表/2026年9月道路运输量汇总表*.xlsx` 与 `docs/确认.docx` 按约定保留。
## 最新(2026-10-06)
### 10-06:折线图纵向间距加高(验收通过)
- **用户背景**:客运量图线间距较好、标签摆放合理;其他多序列折线图因线距偏近,标签仍可能压线。用户同意适当增加图高,Word 只是取图来源,不要求当前分页为最终版,但图不能过高。
- **实现**:
  - `HolidayTrendChartService`:折线纵轴留白收紧为 `lowerMargin=0.04 / upperMargin=0.07`;`LINE_CHART_HEIGHT_SCALE=1.20`,所有折线 PNG 高度放大约 20%。
  - `HolidayTrendService`:12 张折线图的 Word 内嵌图片高度同步放大约 20%,保持 PNG 与 Word 图片框比例一致;饼图、堆叠图未改。
  - `HolidayTrendChartServiceTest`:新增折线图高度缩放断言。
- **验收**:用户于 2026-10-06 查看 `C:\Users\jcxiong\Downloads\2026年十一假期全省综合运输客流量走势图(折线加高20实验).docx` 后验收通过。
- **验证结果**:
  1. 15% 加高版在铁路客运量图 `image5` 检出 OCR 标签框重叠;20% 版 12 张折线图(`image1/2/4/5/6/7/8/9/10/11/14/15`)未检出标签框重叠。
  2. PNG 宽高比与 Word `wp:extent` 宽高比最大误差约 `0.162%`,未发生明显拉伸。
  3. Word 仍为 8 页、每页 2 张图(首页 1 张),与 15% 加高实验相同。
  4. 后端全量 `mvn -q test -f traffic-audit-server\pom.xml` 通过;`HolidayTrendChartServiceTest` 聚焦测试通过。
  5. 标签亲和度检查记录到 3 处标签框更靠近邻近线(`image1` 的 `1,518.02`、`image4` 的 `1,346.17`、`image9` 的 `248.65`);白描边保证可读,用户整体验收通过并保留该排版策略。
  6. `image13` 堆叠图有 4 处 OCR 标签重叠,但该图未参与本实验且代码未改。
- **数据边界**:未导入、覆盖或重导任何业务数据;仅本地只读生成走势图做实验。
### 10-06:平均拥挤度标签恢复为 2 位小数
- **调整**:按用户要求,“普通国省道观测站平均拥挤度”不再单独使用 3 位小数,恢复为折线图默认 2 位。
- **一致性**:由于折线图现已统一按显示标签精度绘制,10-04、10-05 的拥挤度都会显示并绘制为 `0.49`,不会再出现同标签不同高度。
- **验证**:后端全量 `mvn -q test -f traffic-audit-server\pom.xml` 通过。
### 10-06:折线图统一按显示标签精度绘制
- **口径(用户 2026-10-06 确认)**:同一张折线图中,同一个显示标签必须对应同一个点位高度;分析文字不得引用比该图显示精度更细的差异。
- **实现**:`HolidayTrendChartService.lineChart` 在所有原始统计计算完成后,于最终入图边界调用 `displayValue`;普通图按该图 `valueDecimals` 做 `HALF_UP` 舍入,百分比点标签按 1 位百分比精度(即原始小数 3 位)舍入。折线坐标和点标签共用同一舍入值,纵轴格式沿用该图精度。
- **边界**:只在最终图表显示层舍入,不改数据库、不改累计、快报、同比、环比或调整口径;该规则用于静态分析报告图,不能让文字引用图上无法分辨的微小差异。
- **验证**:`HolidayTrendChartServiceTest` 聚焦测试通过;后端全量 `mvn -q test -f traffic-audit-server\pom.xml` 通过。新增测试覆盖“两个不同原值按 2 位标签舍入后生成相同几何”和百分比精度换算。测试报告:`docs/功能测试报告/功能测试报告_折线图按标签精度绘制_2026-10-06.md`(本地留存,不入库)。
### 10-06:观测站平均拥挤度走势图改为 3 位小数
- **问题**:用户导入 10-05 观测站数据后反馈,最后一张拥挤度图中 10-04、10-05 标签都显示 `0.49`,但点位高度不同。
- **根因**:平均拥挤度原值分别为 `0.490890014472` 和 `0.492414492754`,折线按未取整原值绘制,标签原为最多 2 位小数,导致标签精度与图形精度不一致,不是日汇总或点位计算错误。
- **修正**:`HolidayTrendChartService.lineChart` 新增可选 `valueDecimals`,默认仍为 2;仅“普通国省道观测站平均拥挤度”图传 3 位。10-04、10-05 现在分别显示 `0.491`、`0.492`,其余图口径不变。
- **验证**:后端全量 `mvn -q test -f traffic-audit-server\pom.xml` 通过;重启后只读生成新 DOCX,OCR 标签为 `0.504/0.476/0.467/0.491/0.492`;与用户提供的文档逐图比对,15 张图中仅拥挤度图 `image15` 变化,其他 14 张 SHA-256 完全一致。测试报告:`docs/功能测试报告/功能测试报告_拥挤度走势图精度_2026-10-06.md`(本地留存,不入库)。
- **数据边界**:未导入、覆盖或重导任何业务数据。
### 10-06:往年国省道调整列表补充调整前值
- **改动**:调整列表接口在同一年份、同一日期、普通国省道口径下,从 `holiday_vehicle_flow` 补返回 `originalValue`;没有原始记录时保持空,页面不显示占位符。表格新增“调整前国省道车流量(万辆次)”,原“调整后国省道车流”改为“调整后国省道车流量”。
- **弹窗**:新增/编辑弹窗同步增加只读“调整前国省道车流量(万辆次)”;编辑已有记录时展示 `originalValue`,无原值或新选择日期时不显示内容。切换年份或日期会清空旧原值,避免错日展示。
- **随日期刷新**:新增接口 `GET /api/holiday/adjustments/source-value`,按所选年份和日期实时读取普通国省道原值;新增/编辑弹窗选日期后自动刷新,未查到源数据时显示为空。前端用请求序号丢弃迟到的旧请求,避免快速换日期时串值。
- **边界**:`originalValue` 只是列表展示字段,标记为 `@TableField(exist = false)`,不写库、不参与调整、环比分母、累计或走势图计算。
- **验证**:`mvn -o test` 11 个测试全部通过;`npm run build` 通过;本地重启后只读核对 2025-10-03/04/05 原值分别为 `362.0035/337.9501/334.2040`,无源数据的 2025-10-09 返回空。测试报告:`docs/功能测试报告/功能测试报告_往年国省道调整原值展示_2026-10-06.md`(本地留存,不入库)。
### 10-06:方案 D 已实现(往年国省道调整表 + 环比基期只作用于前一日分母)
- **最终口径**:`HolidayStatService.loadVehicleByDate` 先用 `holiday_vehicle_adjustment` 覆盖对应历史年份的“当日值”,供走势图、同比、累计和快报使用;随后构造“前一日环比分母”,若前一日普通国省道 C 列有值,则用 C 替换该日前一日国省道值,并据此重算非营业性人员流动量、公路人员流动量和总计。所有环比行只继承这份分母。
- **关键边界**:C 只影响“下一日的环比分母”,不影响 C 所在日的当日值、累计或走势图;调整表只维护历史年份(`year < 当前年份`),2026 年调整仍由导入 Excel 的 D 列进入当日值。
- **本轮实现**:新增 `holiday_vehicle_adjustment` 表及 mapper/service/controller;前端在专项统计-节假日页的“节假日数据”和“观测站分日调查数据”之间新增“往年国省道数据调整”卡片(后续按用户提议保持该位置),支持年份筛选、新增、编辑、删除和原因留痕;部署脚本与 migration 清单已同步。
- **10-04 导入预检(只读,不写库)**:用 `C:\Users\jcxiong\Downloads\2026年十一数据 (2).xlsx` 以 `allowHistoricalOverwrite=false` 调导入接口,返回确认项:
  - `第4日 2026-10-04 普通国省道:原值 323.6551,导入值 322.7695`
  - `第3日 2026-10-03 普通国省道环比基期:原值 空,导入值 320.2418`
  因此 C5 由空变有值不会硬拒绝导入,只会要求历史变更确认;用户确认后即可随调整后的 Excel 重导写入。
- **当前库状态**:本地 `traffic_audit.holiday_vehicle_adjustment` 已执行 DDL(0 行);2026-10-04 业务值仍为旧值 `323.6551`,等待用户自行重导调整后的 Excel。助手未执行任何业务数据导入、覆盖或重导。
- **验证**:后端 `mvn -o test` 9 个测试全绿(含 C5 只改 10-04 环比分母、历史调整进入 2025 当日值)、前端 `npm run build` 通过;页面实测“往年国省道数据调整”卡片与新增弹窗正常。
- **取整口径(用户 2026-10-06 确认)**:不做“从原始值一次取整”的备选。唯一要求是与 Excel 显示值一致:先按源 Excel 单元格格式生成显示值,再按快报统一 1 位小数。10-04 总计环比原始值约 `4.5481%`,源格显示 `4.55%`,快报取 1 位得到 `4.6%`;这属于既定口径,不是需要修正的边界问题。
> 说明:本文件早前“环比基期只作备用、不参与计算”的段落已作废。该版本针对的是旧实现误把 C 放到 C 所在日本身计算的问题;自方案 D 起,C 的正确语义是**前一日环比分母的调整值**。
### 10-06(已作废,见上方方案 D):普通国省道「环比基期」改为人工备用值(不再参与计算)
- **背景**:10-04 鄂州樊家庄站中小客流量断崖下跌(35419 -> 8856),领导要求剔除。手工稿快报的做法是:先用剔站后的数值算出 10-04 环比,把 10-03 国省道值挪到「环比基期」C 列备用,再把 10-03 恢复原值以免影响累计。用户明确口径:**「环比基期」只用于数据备用,不参与任何计算**。
- **旧行为(错)**:`HolidayStatService.nationalProvincialRingRatio` 在 2026 年只要 `comparison_base` 有值就按「当日 / 环比基期 - 1」算国省道环比;导出时 E 列写 `=(D{行}-C{行})/C{行}`。按手工稿的 C 列摆法(基期放在被比日那行),这样算还会错位(10-03 环比被算成 +1.11%)。
- **新行为(本次已改)**:国省道环比固定「当日 / 前一日 - 1」,2024/2025/2026 一致;`comparison_base` 只在导入/导出/页面展示时原样保存与回写,不参与环比、折算、累计。导出 E 列改为 `=(D{行}-D{上一日行})/D{上一日行}`,C 列照常回写备用值。
- **改动**:`HolidayStatService.java`(`nationalProvincialRingRatio` 去掉 year/comparisonBase 形参)、`HolidayWorkbookService.java`(新增 `ringRatioFormula`,导出按上一行同年 D 列)、`docs/database.md`(`comparison_base` 与计算口径两处)。
- **验证**:新增 `HolidayComparisonBaseTest`:① 库内存 `comparison_base=320.2418` 时,10-04 国省道环比仍按前一日 323.7837 计算,且不等于按基期算出的值;② 导出公式 = `=(D6-D5)/D5`。`mvn -o test` 全绿(4 个测试类)。
### 10-06:待确认——10-04 国省道剔站(鄂州樊家庄)怎么进系统
- **手工口径已逐项核对,与库内 `observation_station_flow` 完全对得上**:
  - 10-04 国省道值(2026/2025/2024)= 原值 − 樊家庄当日值 -> 322.7695 / 337.5009 / 322.5277 万辆次(樊家庄 8856 / 4492 / 2328)。
  - 10-04 环比分母 = 2026-10-03 原值 − 樊家庄 10-03 值 = 323.7837 − 3.5419 = **320.2418** 万辆次 -> 环比 = 322.7695/320.2418 − 1 = **+0.79%**。
  - 10-03 显示值与累计仍用原值 323.7837,被剔的 320.2418 只落到 C 列备用。
- **趋势结论(需先跟领导对齐)**:只剔樊家庄,10-04 国省道环比只有 **+0.79%**;同日高速小客车 **+9.78%**、铁路 +9.94%、民航 +11.69%、道路 +4.99%、水路 +4.33%。**剔一站填不平约 9 个百分点的趋势差**,与「让国省道和高速趋势一致」的预期并不相符,建议同时请鄂州核实原始记录。
- **待决策的代码方案**:因 `comparison_base` 已定为纯备用,系统无法从「当日值」反推剔站基期,需要另设机制。推荐新增「异常站剔除」配置(站点编号 + 生效日期 + 年份),算环比分母时用 `observation_station_flow` 的「该日站点合计 − 剔站值」作基期;显示值与累计仍用原值。
- **决策点**:① 做成可配置的通用「异常站剔除」(推荐,可复用于其他节假日/站点),还是只按本次 10-04 一次性处理;② 剔站只影响国省道环比分母,还是也要下沉到非营业性小客车/公路/全社会的环比(手工稿实际把 4.17% / 4.55% 也一起改了)。
## 最新(2026-10-05)
### 10-05 上午:关机快照(当前状态)
- **已完成**:v1.0.0 正式发布包 `deploy/traffic-audit-deploy-20261005-v1.0.0/`(zip **77.78 MB**)已生成,去密自检、版本自检、结构核对与真实启动冒烟均通过,待上传服务器。版本管理代码与文档均已提交推送(`main` = `93b36c8`)。
- **运行状态**:关机前本机 dev 服务仍在运行(后端 8090 java PID 64112、前端 8080 node PID 46472),随关机停止,无需处理;打包冒烟用的 8095 实例已停止、端口已释放。
- **工作区**:除若干本地临时文件(`_tmp_*`)与一份专项统计 xls 外,git 工作区与远端 `main` 一致;`docs/工作日结/`、`docs/功能测试报告/` 等按约定不入库。
- **下次接手**:先读根目录 `AGENTS.md` + 本文件;待办见第七节(数值精度统一改造、态势感知图、AI 助手 RAG、经济指标试算等),首要事项是跟进正式包在服务器的部署结果。
### 10-05 上午:正式发布包按新版本管理重新生成(v1.0.0,单端口瘦包)
@@ -279,7 +602,7 @@
- **Excel 浮点精度(2026-10-02 追加)**:参考 `docs/Excel浮点数存储.txt`,新增 `HolidayNumberUtils`(`NumberToTextConverter.toText` + `BigDecimal`,`MathContext(15, HALF_UP)`);节假日模块由 `Double` 全面改 `BigDecimal`;三张表数值列改 `DECIMAL(30,15)`;库内 6 条客运系数由 2.3999999999999995 校正为 2.4。迁移脚本 `docs/sql_holiday_decimal_migration.sql`。
- **菜单顺序**:“专项统计”已移到“报表生成”之后,当前为 报表生成 -> 专项统计 -> 规则管理 -> 用户管理 -> 系统配置。
- **节假日删除复活修复(2026-10-02 追加)**:原初始化逻辑每次启动补齐缺失的第 N 日,导致 admin 删除 2026-10-08 后被重新插入;现改为仅 `holiday_calendar` 整表为空时首次初始化。重启后 2026 年十一保持 10-01 至 10-07 共 7 天。
- **普通国省道环比基期(2026-10-02 追加)**:普通国省道 C 列为可选环比基期,仅 2026 年启用;填写后只影响普通国省道车流量自身环比 `当日 / 基期 - 1`,未填写按前一日。`holiday_vehicle_flow.comparison_base` 已入库,导入导出与历史变更确认均已接入;折算人员流动量、总人员流动量和 Word 快报继续按 Excel 原公式,不受基期影响。2024/2025 不使用。
- **普通国省道环比基期(2026-10-02 追加,2026-10-06 方案 D 已修正)**:C 列语义最终确定为“下一日环比分母的调整值”;填写后只影响下一日的环比分母,不影响 C 所在日及累计、走势图。`holiday_vehicle_flow.comparison_base` 已入库,导入导出与历史变更确认均已接入。
- **快报首日口径(2026-10-02 追加)**:假期第1天没有前一日环比基数,正文不输出“环比增长/下降/持平”短语,表格当日环比列为“—”;第2天起仍按实际前一日输出环比。已用 2025-10-01/02 快报回归验证。
- **快报百分比精度(2026-10-02 追加)**:Word 快报中同比/环比百分比统一保留1位小数(如6.79%显示6.8%、11.46%显示11.5%);人次、车流等业务数值仍保留2位小数。
- **验证结果**:后端编译、前端构建、权限/CRUD/负向导入、历史变更两阶段导入、Excel 导出、Word 快报、前端 admin/非 admin 烟测均通过;菜单顺序、客运系数 2.4 展示(系统配置页 + 节假日统计页)、`decimal(30,15)` 列型、历史变更两阶段导入回归均已实测;功能测试报告与工作日结按 2026-09-27 提交规范仅本地留存(不入库):`docs/功能测试报告/功能测试报告_重要节假日专项统计_2026-10-02.md`、`docs/工作日结/工作日结_2026-10-02.md`。
@@ -314,6 +637,11 @@
  - 结果:按当前母版重新生成 2026-08 后,与手工定稿的**需处理差异 = 0**,其余全部落在"已忽略(约定差异)"。清单:`docs/问题汇总/_清单_母版最新生成件_20260928.md/.csv`(本地,不入库)。
  - 注意:桌面那份 `生成_道路运输量汇总表_2026-08.xlsx` 是旧导出(含旧错误值/旧基数),与更新后的定稿比对会显示较多差异,以"母版重新生成件"为准。
- **无表头草稿列清单(9 处,共 539 格)**:`公交/出租/网约车!U`(各 72)、`城市客运!U`(36)、`班线包车!DU`(55,表头"1-3月累计")、`中口径明细!U`(90)、`中口径客运量!AB`(180)、` 货运!V` 与 ` 货运!AX`(各 74,用户所指 U 列在手工那份右移一列)。母版/生成件**已全部清空**,手工定稿仍保留 → 对比时归入「已知设计(无表头草稿列)」。其余"无表头列"是合并表头的正常列(` 货运!C…Q` 月份值列、各年块尾部累计/累计同比列、排名页 R 列等),两边都有、非草稿。明细见 `docs/问题汇总/_已确认差异清单_2026-08_20260928.md`。
- **09-29:用户手工改母版(仅格式 + 删除草稿),并立项母版扩列器**
  - 用户说明本次母版改动仅"调格式 + 删草稿",未动业务口径;指纹变化缓存自动失效,已重新生成核对:需处理 2 条 → `城市汇总!G20` 按"以用户手工改动为准"登记为**已知差异(用户手工改动)**(工具新增 `USER_EDITS`);剩 `班线包车!EO6` = `#DIV/0!`(WPS 保存重算产生,待定留白)。
  - **母版扩列器(方案 B)**:复用 `cloneColumnPair/moveColumnPair/cloneCellForMonth/cloneMergedRegion/copyColumnWidth/fixCumulativeFormulas` 与 `SummaryWorkbookFiller.ensureMonth*`;需新写"扩列编排 + 每页规则配置 + 回归自检"。**当年内每期一键、跨年加一次性"新年块"逻辑**;首次估 0.5~1 天。等同事确认后先出《19 页扩列规格表》。
  - 运行状态:后端 8090 / 前端 8080 已由 `start-dev.ps1` 启动。
  - 用户母版改动尚未提交,待确认后与扩列器一起提交。
- **待办**:① 排名页结构(块顺序、标题措辞、市州名短名/全名、周转量排名多 7 行);② 排名页结构(块顺序、标题措辞、市州名短名/全名、周转量排名多 7 行);③ 缺 2026-09 母版、导出前基数体检(P0-3)。
## 最新(2026-09-27)