# 工作日结_2026-09-16 ## 一、今天做了什么 ### 1. 环境启动 - 11:12 用 `start-dev.ps1` 启动前后端(启动前 8090/8080 均空闲)。 - 就绪标志:后端 `Tomcat started on port(s): 8090` / `Started TrafficAuditApplication`;前端 `Compiled successfully` / `App running at:`。 ### 2. 修复「用局域网 IP 打开页面后登录失败」 - **用户反馈**:用 `http://192.168.177.26:8080/` 登录提示「网络错误,登录失败」,而 `http://localhost:8080/` 正常。 - **排查路径**:curl 直发同一 URL 的 POST `/api/auth/login` 正常返回(说明后端与代理都通)→ 用应用内浏览器在 LAN 地址复现(确实提示「网络错误,登录失败」)→ 对比出差异只在 `Origin` 头 → curl 补 `Origin: http://192.168.177.26:8080` 得到 `403 Invalid CORS request`,根因落地。 - **根因**:浏览器 POST/PUT/DELETE 必带 `Origin`(GET 不带);9-14 跨域收紧后白名单只列了 `localhost:8080 / 127.0.0.1:8080`,经 dev-server 代理转发过来的 `Origin: http://192.168.177.26:8080` 命中不了,被 `CorsFilter` 403 拦掉。页面本身和 `GET /api/auth/captcha-config` 不带 `Origin` 所以正常,表现为"页面能开、一登录就网络错误"。 - **顺带发现**:打包部署(前端内嵌、用 `http://<部署机IP>:8090` 访问)时 POST 同样带 `Origin: http://:8090`,也会被 403 挡住登录——属于同类隐患,本次一并解决。 - **改动(2 文件)**:`CorsConfig.java` 由 `setAllowedOrigins` 改为 `setAllowedOriginPatterns`,默认放行 `http://localhost:*`、`http://127.0.0.1:*`、`http://192.168.*:*`、`http://10.*:*`、`http://172.*:*`;`application.yml` 的 `app.cors.allowed-origins` 同步并补注释。白名单校验机制与 `allowCredentials=false` 均未放松。 - **验证**:按 PID 精确停旧后端链(`cmd 3608 → java(maven) 23704 → java(app) 12636`)后重启;应用内浏览器在 LAN 地址实登成功进入 `#/dashboard`;白名单负向用例(`http://evil.example.com`)仍 403。详见《功能测试报告_局域网IP访问登录CORS修复_2026-09-16.md》。 ## 二、测试结果摘要 - CORS 修复 12 条用例全通过:正向(LAN 来源、同源 8090 来源、内网网段来源、带令牌业务接口、预检 OPTIONS)、负向(非法来源 403)、回归(localhost 来源、无 Origin 头)。 - 真实浏览器端到端:`http://192.168.177.26:8080/#/login` 输入 `admin/123456` → 提示「登录成功」→ 跳转工作台,顶部显示 admin。 - 今日无导入/数据库写入操作,未做入库抽查(改动只涉及跨域校验,不触碰数据链路)。 ## 三、遗留问题与待办 1. **改用域名访问时需补白名单**:`app.cors.allowed-origins` 默认只覆盖本机 + 内网网段,若将来用域名或公网 IP 访问,需把该来源(含端口)追加进去(yml 注释已写明)。 2. `Login.vue` 把所有失败都提示为「网络错误,登录失败」,403/500 这类有响应的错误也被归到"网络",排查易误导;建议后续按状态码细分提示(未做,等用户确认)。 3. 9-15 遗留继续挂账:AI 外发脱敏补齐(system prompt 企业名/解释原文未脱敏)、保密数据部署路线确认、4 张明细报表模板扩列、审核比对基准缺失保护、`sys_role` 权限落地、3D 验证码生产开启、`backend.log` 历史明文清理。 4. 仓库根目录仍有大量未跟踪临时文件(`_*.py`/`_*.sql`/`_*.ps1` 等)未被 `.gitignore` 覆盖,清理前需用户确认。 5. **公司 gitea 今日推不上去(网络问题,非凭据)**:TCP 3000 可连通(`Test-NetConnection` 返回 True),但 HTTP 无响应——`curl http://61.183.254.94:3000/r/trafficAudit.git/info/refs?service=git-upload-pack` 20 秒超时(`000`),`git fetch gitea` 与 `git push gitea` 均无限挂起(各等待 2~4 分钟后手动终止)。待网络恢复后补推;补推前先 `git fetch gitea` 与远端 `main` 比对合并(禁强推)。 ## 四、明天计划 1. 与用户确认域名/其他访问方式是否需要一并加白名单,并确认 `Login.vue` 错误提示细分方案是否实施。 2. 推进 AI 外发脱敏补齐(约 20 行改动),完成后写《功能测试报告》,沿用"假 DeepSeek 服务抓包"做报文级验证。 3. 继续推进报表模板扩列 / 审核基准保护等挂账项。 ## 五、git 记录 - 本次改动(4 文件):`CorsConfig.java`、`application.yml.example`、本报告、本日结。 - 说明:`application.yml` 被 `.gitignore` 忽略(仓库内模板是 `application.yml.example`),故模板同步修改后一并提交。 - 流程与结果: 1. 先写《功能测试报告》与本《工作日结》,再 `git fetch origin`(gitee,`master`)——无新提交,本地已包含远端全部提交; 2. 提交 `0d2a5fc`:`fix(cors): 放行内网网段来源,修复局域网 IP 访问时登录 403`; 3. 推个人仓库 `origin`:`git push origin main:master` 成功(`82100d6..0d2a5fc`); 4. 推公司 `gitea`:`git fetch gitea`、`git push gitea main:main` 均因 HTTP 无响应而挂起,未推送成功(详见遗留问题 5);本次为快进推送,不涉及强推。 --- ## 六、下午追加(两条用户需求,2026-09-16) ### 1. 把 8 月导入的「货运量周转量表」中的 21–26 年数据全部读入数据库 - **背景**:用户 8 月导入的 `定稿-湖北省各市州运输量数据(2026年1-8月).xlsx` 一个工作簿内含 5 个年度 Sheet(`2026年 / 2025年 / 2024年 / 2022年 / 2021年`,源文件无 2023 年),而老逻辑只读第 1 个 Sheet 并按「左半今年 1–N 月 / 右半去年 1–12 月」的月度模板解析,其余年度数据被丢弃。 - **改动(后端 1 文件,+153/−19)**:`DataImportService.java` 中 `importFreightTurnover` 改为分流入口;原逻辑抽为 `importFreightTurnoverByMonth`(逐行不变);新增 `detectYearSheets`(识别多年度工作簿)、`importFreightTurnoverByYear`(按年入库 + 上年同期取自上一年度 Sheet)、`parseWholeYearSheet`(整年 Sheet 的货运量块/周转量块解析)、`persistFreightTurnover`(按报表期先删后插并记批次)。 - **结果**:源文件 5 个年度全部入库,返回「共 90 条记录」,报表期为 `2021-12 / 2022-12 / 2024-12 / 2025-12 / 2026-08`,每期 18 行;与源文件逐项比对 **1080 个单元格零差异**;重复导入幂等(全表 216 行 md5 前后一致);非多年度文件自动回退原月度路径。 - 详见《功能测试报告_货运量周转量多年度导入_2026-09-16.md》。 ### 2. 报表生成-汇总大表预览:删掉「中口径」之后的表格 - **改动(前端 1 文件,单行)**:`ReportExport.vue` 第 133 行由 `v-else-if="it.summary && it.summary.length"` 改为 `v-if="it.key !== 'summaryWorkbook' && it.summary && it.summary.length"`。根因是上面的汇总表用 `v-if`、第二张表用 `v-else-if`,对 `summaryWorkbook` 也照样渲染。 - **验证(推翻上一轮的无效取证)**:早期截图没拍到弹窗、AX 树读到的是缓存,均为无效证据;本轮改用 `tab.playwright.evaluate` 直接读 DOM —— 弹窗内有且仅有 1 张表(`preview-summary wb-table`,12 行指标),表格下方只有两条同比缺失提示与「关闭」按钮,**第二张表已彻底消失**。有效截图:`_qa_out/preview_summaryWorkbook_2026-08_verified_20260916.png`(本轮复核重拍 `..._verified2_20260916.png`,均 54006 字节)。 - 详见《功能测试报告_汇总大表预览删除中口径后明细表_2026-09-16.md》。 ## 七、测试结果摘要(下午追加部分) - 多年度导入:12 条用例全通过——正向(多年度入库、1080 单元格逐项抽查零差异、报表期语义、上年同期、批次记录)、负向(单 Sheet 月度模板回退、非年度命名双 Sheet 回退、混合命名回退、非 Excel 文件报错)、幂等(重复导入全表 md5 一致)、回归(测试期清理干净、真实月份 216 行 / 12 期口径不变)。 - 预览弹窗:7 条用例全通过——DOM 实测弹窗内 `table` 数量为 1、类名与行数正确、12 行数值与同比完整、表格下方无第二张表、`git diff` 仅 1 行改动不回归。 - 测试期清理:`2099-01` ~ `2099-04` 全部用 `POST /api/import/clear?period=…` 清空(各 dataRows=18、batchRows=1),当前库 **0 条 2099 残留**、`freight_turnover_import` 216 行 / 12 个报表期。 ## 八、遗留问题与待办(更新) 1. **`2021-12` 等报表期是「整年」语义**:这些期承载该年 1–12 月全年数据,而非 12 月单月;后续报表/审核若按单月口径取数需用户确认口径,必要时再改造。 2. **源文件缺 2023 年 Sheet**:导致不生成 `2023-12`,`2024-12` 无上年同期。属源数据缺口。 3. **`2026-01` ~ `2026-07` 的 `last_*` 为空**:经比对改动前备份(`2026-04` 的 INSERT)确认这几期改动前即为空,且本次导入未触碰这些报表期(批次只覆盖 5 个期),**非本次改动引入**;如需补上年同期需重新导入对应年度数据。 4. **改动前的备份不完整**:`_backup_freight_turnover_before_multiyear_20260916.sql` 仅 59642 字节、只解析出 `2026-04` 一处 INSERT,**不能作为完整回滚依据**。 5. 弹窗内「共 0 行」与「月度覆盖:1~8月均有数据」口径不同(前者是明细行数),易误解,可考虑改文案(未做,等用户确认)。 6. 上午遗留继续挂账:域名/公网访问的白名单补充、`Login.vue` 错误提示细分、AI 外发脱敏补齐、4 张明细报表模板扩列、审核比对基准缺失保护、`sys_role` 权限落地、3D 验证码生产开启、`backend.log` 历史明文清理、仓库根目录临时文件清理。 7. **公司 gitea 仍待补推**(网络问题,非凭据),补推前先 `git fetch gitea` 与远端 `main` 对比合并,禁强推。 ## 九、明天计划 1. 与用户确认 `2021-12` / `2022-12` 等「整年报表期」的业务口径,以及是否需要把年度数据拆成逐月报表期。 2. 确认是否需要补 2023 年数据、以及 `2026-01`~`2026-07` 的上年同期是否需要补齐。 3. 视用户意见处理预览弹窗「共 0 行」文案。 4. 网络恢复后补推公司 gitea。 --- ## 十、傍晚追加(第 3 轮用户反馈 6 条,2026-09-16) 用户本轮提出 6 条反馈,逐条处理结果如下: | # | 用户反馈 | 处理结果 | |---|----------|----------| | 1 | 21–26 年货运量周转量表数据入库 | 上轮已完成(`0cfd6e0`),本轮补齐 2023 年(见 #2) | | 2 | 用户核实「23 年有 12 月的数据」 | **属实**。8 月源文件确实没有 2023 年 Sheet,但 7 月文件 `D:\05_数据分类\货运\7月\定稿-湖北省各市州运输量数据(2026年1-7月).xlsx` 里有一个名为 `2023` 的 Sheet。已另存 `_2023_import_tmp.xlsx`(`2023` + `2022年` 两个 Sheet)导入,生成 `2023-12`(18 行),**432 项逐格比对零差异** | | 3 | 要一份「所有要注意的点」的汇总文档 | 新建 `docs/问题汇总/问题与注意事项汇总_2026-09-16.md`(11 章 + 速查表,含启动/进程、日志验证、数据库、导入路径与期次约定、报表、验证码、文件编码、浏览器取证、git 双仓库、遗留问题) | | 4 | 换 WiFi 后登录页出现验证码白框 + 「验证码加载失败」 | 已修复(前端默认值 + fail-safe),本轮浏览器复测通过 | | 5 | 预览点一下弹「导出失败,请确认导入数据」 | 已修复提示逻辑(区分网络/后端原因);另外两小项(指标错位、弹窗拖动圆角)本轮浏览器实测通过 | | 6 | 公路旅客 H203-1 模板被修改 | 已适配并验证:新增 `统一社会信用代码` / `填报单位` 两列入库,新老格式双向兼容 | ### 1. 2023 年货运数据补录(用户第 2 条) - **排查过程**:先确认 8 月源文件 5 个 Sheet 全为可见、无 2023;再全盘搜索 `*运输量*`、`*23年*`、`*货运量*` 文件名;最后扫描 `D:\05_数据分类` 与 `D:\桌面` 下所有 `.xlsx` 的 **Sheet 名**,命中 7 月文件的 `2023` Sheet。 - **一致性预检**:7 月与 8 月文件的 `2021年 / 2022年 / 2024年` 三年数据逐格比对,`onlyJuly / onlyAug / differ` 全为空 → 三年**零差异**,可安全用 7 月文件补 2022(作为 2023 的上年同期来源)。 - **导入**:`POST /api/import/freightTurnover?period=2023-12`,返回「共 36 条记录」。 - **验证**:`2023-12` 18 行;货运量 + 周转量共 432 项与 Excel 逐格比对 **mismatches=0**;`last_*` 与 `2022-12` 逐值相同;全部报表期 2021-12 → 2026-08 共 13 期、每期 18 行。 - 详见《功能测试报告_货运量周转量2023年数据补录_2026-09-16.md》。 ### 2. H203-1 模板新增列适配(用户第 6 条) - **模板 diff 结论**:Sheet1 由 773×50 → 816×52;在「企业名称」后插入 `统一社会信用代码`、`填报单位` 两列,其余 48 列整体右移。 - **改动 6 处**:库 DDL、`docs/init.sql`、`docs/database.md`、`PassengerEnterpriseMonthly.java`、`DataImportService.java`、`DataViewController.java`(数据查看页列)。 - **验证**:新模板导入 814 条 0 失败,四项汇总(客运车辆 24584 / 核定载客位 711018 / 客运量 16371625 / 周转量 1023386179)与源文件全等;老格式 `.xls` 导入 767 条 0 失败且新列有值(**老文件其实也带这两列**),数值与既有 2026-08 完全一致;负向用例(选错类型)报错清晰。 - **过程中的失误**:`docs/database.md` 里 `| enterprise_name | varchar(200) | 企业名称 |` 出现 4 次,首次批量替换误改 3 张表,已 `git checkout` 回退后改为「截取章节再替换」。 - 详见《功能测试报告_H2031模板新增列适配_2026-09-16.md》。 ### 3. 登录验证码容错 + 报表预览整改(用户第 4、5 条) - **验证码**:`Login.vue` 默认 `captchaRequired=false`,改为 fail-safe(仅后端明确返回 `required===true` 才显示);换 WiFi/后端不可达时不再残留验证码白框。 - **失败提示**:`failWith(err, action)` + `errReason(raw)` 重写,区分「连不上服务器」与「后端真实原因」;预览调用带 `action='预览'`;Blob 错误先 `text()` 再解析。 - **指标错位**:预览表头由 3 列补为 4 列(分类/指标/数据/同比),实测 x 坐标 35 / 118 / 394 / 587,`16888.76` 落在「数据」列。 - **弹窗拖动 + 圆角**:新增 `dialogDrag.js` 指令(Element UI 2.15.14 无 `draggable`),`border-radius:10px`;实测拖动 `(0,40) → (120,200)`,`transform=matrix(1,0,0,1,120,160)`,关闭后复位 `none`。 - 「中口径之后不再渲染表格」上轮已修,本轮复核弹窗内**有且仅有一张表**。 - 详见《功能测试报告_登录验证码容错与报表预览整改_2026-09-16.md》。 ### 4. 注意事项汇总文档(用户第 3 条) 新建 `docs/问题汇总/问题与注意事项汇总_2026-09-16.md`,共 11 章: 速查表(10 条)、启动与进程管理、服务状态验证、数据库、数据导入(路径 + 期次约定 + 多年度工作簿识别规则)、报表生成、登录与验证码、文件写入与文本处理的坑、浏览器自动化取证的坑、Git 双仓库工作流、当前已知遗留问题。 ## 十一、测试结果摘要(傍晚追加部分) - **2023 补录**(5 条用例):正向入库、432 项逐格比对零差异、上年同期取自 2022、报表期清单无重复/无残留、2022-12 重写后逐值不变 —— 全部通过。 - **H203-1 新增列**(9 条用例):新模板 814 条 0 失败、两列 814/814 有值、首行与汇总四项与源文件全等、老格式 767 条 0 失败且数值与 2026-08 全等、Excel COM 抽查首行一致、负向选错类型报错清晰、列右移不影响旧字段 —— 全部通过。 - **登录验证码 + 预览整改**(10 条用例):无验证码白框、接口 `required=false`、表头 4 列且 x 坐标对齐、圆角 10px、拖动位移 120/160、关闭复位、弹窗内仅 1 张表、失败提示已细分、导出成功 —— 全部通过。 - **测试数据清理**:H203-1 导入验证产生的 `2099-06 / 2099-07 / 2099-09` 三个测试期(共 2395 行)及其 `import_batch` 记录已删除,`h2031_enterprise_monthly` 恢复为 2026-01 ~ 2026-08 共 8 期;`freight_turnover_import` 为 13 期 × 18 行。 ## 十二、遗留问题与待办(傍晚更新) | # | 问题 | 状态 | |---|------|------| | 1 | 8 月源文件缺 2023 年 Sheet | **已解决**(用 7 月文件补录 `2023-12`) | | 2 | `2026-01` ~ `2026-07` 的 `last_*` 为空 | 待用户确认是否补 | | 3 | `2026-01` ~ `2026-08` 的 H203-1 `unified_credit_code` / `report_unit` 为空(此前代码未读这两列) | **待用户确认是否重导历史文件回填** | | 4 | `2024-12` 的上年同期未回填(需重导 2024 年数据) | 待用户确认 | | 5 | 预览弹窗「共 0 行」与「月度覆盖:1~8月均有数据」口径文案不同 | 待用户确认改文案 | | 6 | `2021-12` 等「整年报表期」的业务口径 | 待用户确认 | | 7 | 公司 gitea 推送(网络无响应) | 待补推,**禁强推** | | 8 | 仓库根目录大量 `_*.*` 临时文件 | 经用户同意后再清理 | ## 十三、下一步计划(傍晚更新) 1. 等用户确认 3 件事:是否重导 2026 年历史 H203-1 文件回填两列、是否补 `last_*` / `2024-12` 上年同期、预览弹窗文案是否调整。 2. 网络恢复后补推公司 gitea(先 fetch 合并,禁强推)。 3. 视用户意见清理仓库根目录 `_*.*` 临时文件。 ## 十四、git 实际结果(傍晚补记) 1. `git fetch origin`(个人 gitee,`master`):远端与本地一致(`HEAD...origin/master = 0 0`),**无同事/用户新提交**,无需合并。 2. 提交 `24b4c28`:`feat(h2031): 适配模板新增「统一社会信用代码/填报单位」两列并入库;fix(import): 补录 2023 年货运量周转量;fix(login/report): 验证码容错、预览指标对齐、弹窗可拖动圆角、失败提示细分;docs: 新增问题与注意事项汇总`(10 个改动 + 4 个新增,共 14 个文件)。 3. 推个人仓库 `origin`:`git push origin main:master` 成功(`0cfd6e0..24b4c28`)。 4. 推公司 `gitea`:`git fetch gitea` 报 `Operation too slow. Less than 1000 bytes/sec transferred the last 15 seconds`;`curl --max-time 20 http://61.183.254.94:3000/` 返回 `http_code=000 time=20.01`,确认**公司内网不可达**(网络问题,非凭据),本次未推送成功,已列为遗留问题;补推前先 `git fetch gitea` 与远端 `main` 合并,**禁强推**。 ## 十五、用户 4 条确认的落实(2026-09-16 收尾) | 用户反馈 | 结论与处置 | |---|---| | 1-2「我导入的货运量周转量表里有 23 年数据」 | 已逐格复核:8 月源文件只有 `2026年 / 2025年 / 2024年 / 2022年 / 2021年` 五个 Sheet,内文无任何 2023 标识(命中项均为浮点数里的数字巧合);`2023` Sheet 出现在**7 月**文件里。已用 7 月文件的 `2023` Sheet 补录 `2023-12`,无需再导。 | | 1「让他空着吧」 | 2026-01~08 的 H203-1 `unified_credit_code` / `report_unit` 保持空,**不重导**历史文件。 | | 2「是不是把 23 年也导进去」 | 是,已导入 `2023-12`(18 行)。若要回填 `2024-12` 的上年同期值,需再重导一次 2024 年数据(待用户确认)。 | | 3「可以」 | 预览弹窗文案已按确认修改(汇总大表「指标 N 项」/其它报表「共 N 行明细」),并已在浏览器实测。 | | 4「什么时候开始连不上的」 | 公司 gitea **自 2026-09-15 起不可用**:09-15 为凭据弹窗未推成功;09-16 起变为 TCP 3000 可连但 HTTP 无响应。今日复测 `Test-NetConnection` 为 True、`curl` 25s 超时 `code=000`。 | ## 十六、git 实际结果(收尾补记) - `git fetch origin`(个人 gitee):`HEAD...origin/master = 0 0`,无新提交,无需合并。 - 提交 `e7cddc4`:`fix(report): 预览弹窗行数文案按报表类型区分`(4 个文件,+25/-1)。 - 推个人仓库 `origin`:`git push origin main:master` 成功(`b0c8b4f..e7cddc4`)。 - 推公司 `gitea`:`git fetch gitea` 仍失败,报 `fatal: unable to access ... Recv failure: Connection was reset`(`fetch_exit=128`),本次**未推送成功**,继续列为遗留问题;补推前先 `git fetch gitea` 与远端 `main` 合并,**禁强推**。 ## 十七、用户第 5 条:汇总大表与 8 月定稿逐表比对 **比对对象**:`D:\桌面\生成_道路运输量汇总表.xlsx`(用户 14:39 导出) vs `D:\05_数据分类\汇总表\8月汇总定稿\2026年8月客运量、货运量定稿.xlsx`。重新导出一次(`GET /api/report/export/summaryWorkbook?period=2026-08&mode=month`)得到的文件与桌面那份**字节数完全一致(950,186)**,排除“文件过期”。 **踩的坑(重要)**: 1. 两边**行块高度不同**(导出每市州 6 行、定稿 4 行;导出 118 行 vs 定稿 84 行),直接按单元格坐标比会得出 4.6 万个“差异”,全是错位噪声 → 改用「地区+指标+列标题」**语义键**对齐。 2. 导出端有 **39,939 个公式格**(`=C7+C9`、`=C5/V5-1`、`RANK(...)`),`openpyxl(data_only=True)` 读出来全是 None → 误判成“整表没数据”。Excel COM 打不开(用户已开着 Excel,不能乱动),最后**自己写公式求值器**(SUM/RANK/ROUND+四则+跨表引用)算出 61,972 个数值格再比。 **结论**:语义键一致 28,567 个,不一致 4,742 个。 * ` 货运` 表:导出每市州比定稿**多两行**(「规上+规下货运量」「规下货运量」),同指标数值**零差异**;定稿还有「规上+规下周转量」行而导出该行为空。 * **最大差异来源**:`city_bus_monthly / city_taxi_monthly / wyc_order_monthly / wyc_total_monthly` **只有 2026-01~08,没有 2025 年** → 公交/出租/网约车/中口径几张表的「与去年同比」被算成 `0`/`-1`、2025 年累计偏小。 * `h2031_enterprise_monthly` 缺 `2025-01`(源文件本身没有 1 月)。 * 导出端「中口径分析」多一段当月块、缺 4 行“占比”。 详见《功能测试报告/汇总大表与定稿比对_2026-09-16.md》。 ## 十八、用户第 2 条:2024 年数据重导(回填上年同期) **背景**:`last_*`(上年同期)只从**同一个工作簿的上一年 Sheet** 取,8 月文件没有 `2023` Sheet,所以 `2024-12` 的 `last_*` 一直是 NULL。 **过程**:先用 7 月文件(含 `2023` Sheet)另存只留 4 个年度 Sheet 的临时文件导入 → `2024-12` 的 `last_*` 填上了,但 **`2021-12` 的「湖北省」行 1 月值从 14945.34 变成了 0**。排查发现「湖北省」行是 `=SUM()` **公式**,openpyxl 另存会**丢掉公式的缓存值**,POI 读到空公式就写 0。 **修正**:改用**原始 7 月文件**整份重导(`POST /api/import/freightTurnover?period=2026-07`,返回「共 108 条记录」= 6 期 × 18 行)。 **复核**:7 月/8 月两个文件的 11 个年度 Sheet 与库逐格比对 **4,752 格全部 0 不一致**;上年同期链条 2022→2021、2023→2022、2024→2023、2025→2024、2026-07/08→2025 **全部 0 不一致**。 **教训**:以后不能用 openpyxl 另存 Excel 再喂给后端,公式缓存会丢;要么用原始文件,要么用 Excel COM 另存。 ## 十九、用户第 3 轮提问:货运页签「累计」为什么只有前四个对得上 + 新导入数据体检 ### 19.1 定位过程 1. 解剖导出件「 货运」页签:共 6 个累计列 —— `S`(2026 1-8月)、`AT`(2025)、`BV`(2024)、`CW`(2023)、`DZ`(2022)、`EO`(2021)。 2. 读母版 `docs/生成汇总大表/生成_道路运输量汇总表.xlsx` 的同名页:`S5/AT5/BV5/CW5` 是 **Σ公式**,`DZ5` 是 **数值常量 144979.285376043**,`EO5/EP5` **为空**。2021 年 `EC5:EN5` 十二个月都有值(合计 161309.5316),只是累计列漏了。 3. 用源文件(`D:\05_数据分类\高速\定稿-湖北省各市州运输量数据(2026年1-8月).xlsx`,另有 7 月文件含 2023 页)复算全省行: | 年度 | 列 | 汇总表 | 源文件核算 | 差异 | |---|---|---|---|---| | 2026(1-8月) | S | 130311.8927 | 130311.8927 | 0 | | 2025 | AT | 195433.2232 | 195433.2232 | 0 | | 2024 | BV | 184938.5780 | 184938.5780 | 0 | | 2023 | CW | 173045.2932 | 173045.2964 | −0.0033 | | 2022 | DZ | 144979.2854 | 144979.2825 | +0.0029 | | 2021 | EO | 空 | 161309.5316 | 整列缺失 | 周转量行同理(2023 −0.0017、2022 +0.0025、2021 空)。市州行 2026~2022 逐格一致,差异只在「全省」行和 2021 列。 ### 19.2 原因 * **2021 累计列(EO)在母版里就是空的** —— 漏填累计公式;8 月定稿同样为空,属历史遗留。 * **2022 累计列(DZ)是写死常量**,不会随导入数据刷新;其各月值也是当年手工录入的旧精度(1 月 10709.5265 vs 源文件 10709.5234)。 * **2023 累计列(CW)是公式,但输入来自母版**:母版 2023 全省行 = 规上+规下两行相加,与源文件 `2023` 页湖北省行精度不同,差 0.0033。 * 代码每次导出只回填「目标当月」一列(`SummaryWorkbookFiller.fillFreightSheet`),历史月份全部沿用母版 → 母版对不上就整体对不上。 ### 19.3 新导入数据体检(问题清单) | # | 严重度 | 问题 | |---|---|---| | 1 | 高 | `h2032_enterprise_monthly` 多出一个 **2026-09 期**,源文件名是「道路货物运输月度生产情况(2026年8月).xls」(batch 302)。与 2026-08 期逐企业比:636 条企业完全同集、90 个区划,仅 38 家企业数值不同 → 是 8 月数据的另一版本被存成 9 月 | | 2 | 高 | `h2031_enterprise_monthly` **缺 2025-01**(今天只导了 02~12),2025 年累计会少 1 个月 | | 3 | 中 | `passenger_individual_monthly` 2026-08 **缺黄冈市**(7 条变 6 条) | | 4 | 低 | PASSENGER_AUTH 11 期全 0 行,需确认是否正常 | | 5 | 提示 | 2025-04 的 H2032 此前缺失,本次已补齐(batch 382,664 行);h2032 区划数 2025=87 / 2026=90,属企业进退规正常变动 | 入库抽查:H2032 2025 全年规上 50117.0940 万吨 / 7435040.9971 万吨公里、2026 年 1-8 月规上 31399.8248 万吨,逐市州 17/17 与导出件「货运量排名」累计表一致。 详见《功能测试报告/货运累计列核对与导入数据体检_2026-09-16.md》。 ### 19.4 git 结果(本轮) - 提交 `27574bc`(功能测试报告 + 本节 + .gitignore 补 `_pylibs/`、修正 `~$*` 前导空格)→ **已推 origin(gitee master)**:`559e937..27574bc`。 - **公司 gitea 仍不可用**:`Test-NetConnection 61.183.254.94:3000` 返回 True(TCP 通),但 `GET /r/trafficAudit.git/info/refs?service=git-upload-pack` 25 秒无任何响应(HTTP 000),`git fetch gitea` 报 `Operation too slow. Less than 1000 bytes/sec`。判断为服务端未正常提供 HTTP 响应,待恢复后补推,**禁强推**。 ## 二十、用户「可以」授权项落实:货运页签累计列修复 + H2032 脏期清理 ### 20.1 关键发现:根因不是累计公式,而是「全省规下」行 上一节我判定为「2021 累计列空 + 2022 写死常量 + 2023 精度差」,本轮用 Excel COM 逐月实测后**修正了结论**。对 6 个年度块逐月比较「全省行」与「17 市州行之和」: | 年度 | 合计差 | 规上差 | 规下差 | |---|---|---|---| | 2026(1-8) | 2.8e-5 | 1.8e-12 | 2.8e-5 | | 2025 | 3.3e-11 | 9.1e-13 | 3.5e-11 | | 2024 | 1.5e-11 | 9.1e-13 | 1.3e-11 | | 2023 | **4.6e-3** | 4.5e-13 | **4.6e-3** | | 2022 | **3.1e-3** | 2.3e-13 | **3.1e-3** | | 2021 | 4.0e-5 | 4.0e-5 | 1.5e-4 | - 「规上」全省行永远是 17 市州之和(公式),**一处不差**; - 差异 100% 来自「全省规下」行 —— 它是**写死的常量**,与 17 市州规下之和不等; - 而「17 市州行之和」恰好等于源文件湖北省行(2022 = 144979.2825、2023 = 173045.2964),正是用户人工核算的那个数。 所以只要把「全省 规上/规下」两行都改成 17 市州求和公式,全省行自然等于市州之和,累计列随之自动对上。 ### 20.2 母版改动(docs/生成汇总大表/2026年8月道路运输量汇总表.xlsx 的「 货运」页) | 位置 | 改前 | 改后 | |---|---|---| | r7/r8/r9/r10(全省 规上/规下 货运量·周转量,2021-2025 各月) | 写死常量 | SUM(17 市州对应行) | | r5/r6(全省 货运量/周转量,2021-2025 各月) | 常量 | m7+m9 / m8+m10 | | DZ(2022 累计,行 5-112) | 写死常量 | SUM(DM:DX) | | EO(2021 累计,行 5-112) | 空 | SUM(EC:EN) | | EA(2022 累计同比,行 5-112) | 写死常量 | IFERROR(DZ/SUM(EC:EN)-1,"") | 共 360 + 324 个单元。2026 年块不动(当月值由导出代码回填);EP(2021 累计同比)保持为空(页内没有 2020 块,无同比基期)。改前备份 docs/生成汇总大表/_bak_202608母版修改前_20260916/。 **只改母版这一个文件**:生成_道路运输量汇总表.xlsx 是列宽参照件(代码只读列宽/隐藏标记),_版式原型.xlsx 运行时无任何代码引用;同期备份母版 resolveSummaryDonor(2026,8) 要求文件名以 _备份_ 开头且含「2026年8月」,目录下无匹配(导出日志确认「未找到同期备份母版」),不会冲掉改动。 ### 20.3 数据库清理 - DELETE FROM h2032_enterprise_monthly WHERE report_period='2026-09' → 636 行(ROW_COUNT() 实测) - DELETE FROM import_batch WHERE id=302 → 1 行 - 备份:_backup_h2032_2026-09_rows_20260916.sql(636 元组)、_backup_h2032_2026-09_batch302_20260916.sql ### 20.4 修复后实测(重导出 2026-08,Excel 重算) | 年度 | 列 | 修复前 | 修复后 | 源文件核算 | |---|---|---|---|---| | 2026(1-8月) | S | 130311.8927 | 130311.8927 | 130311.8927 | | 2025 | AT | 195433.2232 | 195433.2232 | 195433.2232 | | 2024 | BV | 184938.5780 | 184938.5780 | 184938.5780 | | 2023 | CW | 173045.2932 | **173045.2964** | 173045.2964 | | 2022 | DZ | 144979.2854 | **144979.2825** | 144979.2825 | | 2021 | EO | 空 | **161309.5316** | 161309.5316 | 全部 4 位小数一致(最大残差 4.1e-5,为浮点累加噪声)。导出件「全省行」vs「17 市州行之和」逐月 小于等于 9.3e-10。预览接口 types=summaryWorkbook 返回 ready=true、20 项指标(当月货运量 16888.76、累计 130311.89)。2026-07 导出回归通过。 ### 20.5 踩坑 1. **PowerShell 双引号里的 "$m7" 会被当成变量 m7**:公式串 "=SUM(DM$r:DX$r)" 中的 $r:DX 被当成「驱动器 r:」而吞掉,公式被写成 =SUM(DM5) —— 首次脚本已把母版改坏,靠备份还原后改用 ${m}/${r} 定界重跑。 2. **嵌套的单引号 here-string 会提前终止外层 here-string** → 改为「先 Out-File 写补丁文件,再 Get-Content -Raw 传给 codex.exe --codex-run-as-apply-patch」。 3. 母版被 Excel 重存后体积 959,706 → 1,480,392 字节,导出件 950,186 → 1,331,599(Excel 自身格式开销,不影响数据)。 4. 2026年8月道路运输量汇总表_版式原型.xlsx 的 S 列漏了 8 月(=C+E+G+I+K+M+O,缺 Q5),但它运行时不被引用,本次未改。 ### 20.6 遗留 - 2026-09 期在 h204_vehicle_quarterly(1284 行,batch 142/144 同文件)、investment_monthly(31 行,batch 107/108 同源)、audit_result(2061 行)、audit_run(3 行)中仍在,本次未动,待用户确认是否清理。 - 2026-07 期导出件「 货运」页为 118x145(比 8 月少 2 列),因 7 月母版是「1-4 月骨架」。 详见《功能测试报告/功能测试报告_货运页签累计列修复与脏期清理_2026-09-16.md》。 --- ## 二十一、2026-07 母版补齐 + 导出件「Excel 打不开」根因修复 日期:2026-09-16(第 9 轮,接二十节) ### 21.1 今天做了什么 | # | 事项 | 结果 | |---|---|---| | 1 | 清理 2026-09 残留数据(用户第 1 条) | **完成**:h204_vehicle_quarterly 1284 / investment_monthly 31 / audit_result 2061 / audit_run 3 / import_batch 5 / h2032 636,全部复核为 0 残留;已留可还原 SQL 备份 `_backup_2026-09_residual_all_20260916.sql` | | 2 | 修 2026-07 导出件「Excel 打不开」 | **完成**(P0,见 21.2) | | 3 | 补齐 2026-07 母版(用户第 3 条「可以补齐」) | **完成**(见 21.3) | | 4 | 修备份母版回填把补齐「打回原形」 | **完成**(见 21.4) | ### 21.2 根因:openpyxl 母版 + 备份回填 → 残留 非法格 - 坏件里 19 个格子形如 `67.067.00`:`t="n"` 却带 ``,模式非法,Excel 直接拒开(COM 报「不能取得类 Workbooks 的 Open 属性」,连修复模式 `CorruptLoad=1` 也打不开)。 - 7 月母版是 **openpyxl 写出**(文本存 ``),8 月母版是 **Excel 原生**(文本走 sharedStrings)→ 同代码下只有 7 月坏。 - 触发者是 `restoreSummaryMonthlyBlocks`:7 月有 `_备份_2026年7月…清理前…xlsx`,整格回填时往 inlineStr 格里写值,留下旧 ``;8 月没有 `_备份_*`,不走回填,所以一直是好的。 - 定位手法(值得记住):坏件/好件**除 worksheets/styles/sharedStrings 外全部部件逐字节相同** → zip 杂交 + Excel 逐一开档 leave-one-out → 锁定 **sheet9《公交》17 格 + sheet12《轨道、轮渡》2 格**。 ### 21.3 修复 1. `ReportExportService.exportSummaryWorkbook`:落盘前新增 `normalizeStaleInlineStrings(wb)`,清掉所有「非 inlineStr 却残留 ``」的格子(幂等 + warn 日志)。 2. `ReportExportService.restoreSummaryMonthlyBlocks`:新增 `skipFreightHistoryBlocks`,《 货运》页 **T 列及以后**(2025..2021 五个年度块 + 各年累计列)永不从备份母版回填 —— 与既有「中口径排名左块」保护同一思路,防「生成又复活」。 ### 21.4 7 月母版补齐(Excel COM,360 + 324 格) 按 `_fix_mother.ps1`(8 月母版那版)**整体左移 2 列**改写: - 年度块:2025 `T,V,X,Z,AB,AD,AF,AH,AJ,AL,AN,AP`;2024 `AV..BR` 隔列;2023 `BW..CS` 隔列;2022 `DK..DV` 连续;2021 `EA..EL` 连续;每列写 `r7/r9/r8/r10 = SUM(17 市州)`、`r5=r7+r9`、`r6=r8+r10` → **360 格**; - 累计列:`DX=SUM(DK:DV)`、`EM=SUM(EA:EL)`、`DY=IFERROR(DX/SUM(EA:EL)-1,"")`,行 5..112 → **324 格**; - `CalculateFullRebuild` 后保存。母版 921,559 → 1,440,038 字节(转 Excel 原生)。 ### 21.5 测试结果摘要 | 用例 | 结果 | |---|---| | 2026-07 导出(修复前) | FAIL(复现) | | 环境/路径排除(小件、两本母版、09-08 旧导出、改名复制) | 全部 OK,确认非环境问题 | | 修复后 2026-07 导出 | **OK sheets=19**,`DX5=144979.2825`、`DY5=-0.101235487797891`、`EM5=161309.53162`、`CU5=173045.296428512` | | 修复后 2026-08 导出 | **OK sheets=19**,`DZ5=144979.2825`、`EO5=161309.53162`、`CW5=173045.296428512` | | 跨月一致性 | 7 月与 8 月的 2022/2021/2023 累计**完全相等** | | 非法格复扫 | 0 个 | | 2026-09 残留复核 | 5 张表全 0 | > 注:8 月母版计算后 `DZ5` 由旧的写死常量 `144979.285376043` 变为 `144979.2825`,差 0.0029 —— 正是第十二节记录的「全省规下常量 ≠ 17 市州之和」那笔差额,属**修正**而非回退。 ### 21.6 踩坑 1. **Excel COM 孤儿进程会让 `Workbooks.Open` 间歇性假报同一个错**:每例测完必须强杀本次新建的 `EXCEL` 进程。排查初期就因孤儿进程误判「8 月件也打不开」,浪费了一轮。 2. `CTWorksheet` **没有** `isSetSheetData()`(sheetData 是必填),要用 `getSheetData() != null`。 3. 母版补齐的备份文件**不能**用 `_备份_` 前缀(会被 `resolveSummaryDonor` 当 donor 回填),本次用 `_bak_2026年7月道路运输量汇总表_补齐前_20260916.xlsx`。 ### 21.7 遗留 - 2026-06 / 2026-09 无母版 → 预览 `ready=False`「未找到模板文件」,需先建母版。 - 第 8 棒遗留未动:`h2031` 缺 2025-01、`passenger_individual_monthly` 2026-08 缺黄冈、`PASSENGER_AUTH` 11 期全 0。 - 仓库根 `_*.*`(含本次 `_hyb_*` / `_loo_*` / `_v2_*` / `_final_*` / `_fixed_*` / `_t7_*` / `_poijar`)未删,待用户同意。 详见《功能测试报告/功能测试报告_2026-07母版补齐与导出件打不开修复_2026-09-16.md》。