编辑 | blame | 历史 | 原始文档

交通货运统计审核系统 — 问题与注意事项汇总

用途:把项目运行、数据导入、报表生成、仓库协作中所有「踩过的坑」集中记录,供后续开发与运维快速查阅。
维护方式:新发现问题请直接在本文件追加,并注明日期。
最后更新:2026-09-16


一、速查表(最常见的 10 条)

# 事项 正确做法
1 启动前后端 项目根目录执行 powershell -NoProfile -ExecutionPolicy Bypass -File start-dev.ps1
2 端口占用判断 看 backend.log / traffic-audit-web/frontend.log,**不要**依赖 Get-NetTCPConnection
3 后端就绪标志 日志出现 Started TrafficAuditApplication + Tomcat started on port(s): 8090
4 前端就绪标志 日志出现 Compiled successfully + App running at:
5 连数据库 mysql.exe --host=127.0.0.1 --port=3308 --user=root --default-character-set=utf8mb4 -D traffic_audit
6 停旧进程 按 PID 精确停 cmd → java(maven) → java(app) 链;**不要杀 node_repl 和用户自己的 cmd 窗口**
7 脚本报「已添加了具有相同键的项」 本机同时存在 Path 与 PATH,改用 cmd.exe /c ... > log 2>&1,**严禁用 Start-Process**
8 写中文文件 用 UTF-8;main.js 带 BOM 必须写回 BOM;改文件前先确认原文件是 CRLF 还是 LF
9 提交前 先测试 + 写《功能测试报告》+ 更新《工作日结》,再 fetch/合并/推送
10 推公司 gitea 先 git fetch gitea 与远端 main 合并,**禁止强推**

二、启动与进程管理

问题 原因 处置
Start-Process 报「已添加了具有相同键的项」 环境变量同时存在 Path 与 PATH(值相同) 统一用 cmd.exe /c ... > log 2>&1 或 ProcessStartInfo 启动
前端在沙箱内起不来(EPERM: lstat) node 访问用户目录被沙箱拦截 start-dev.ps1 整体在沙箱外执行
嵌套 powershell.exe -Command 引号被破坏 外层 shell 先解析一层引号 直接运行 .ps1 文件,不做嵌套
重启时误杀 Codex 内核 按名字杀 node.exe 会命中 node_repl 按 PID 精确停后端链 cmd → java(maven) → java(app)、前端链 cmd → node(npm) → cmd → node(vue-cli-service)
前端日志找不到 日志在子目录 traffic-audit-web/frontend.log;后端 backend.log 在仓库根目录

重启标准流程:列出 java.exe 进程 → 停 app → maven → cmd → 运行 start-dev.ps1(脚本自动跳过已在监听的端口)。


三、服务状态验证

  • 沙箱内 Get-NetTCPConnection 会因权限「拒绝访问」而**静默失败**,据此判定端口未监听是错的。
  • 判断服务状态一律以日志为准;HTTP 探活用:
  • 后端:GET http://127.0.0.1:8090/api/auth/captcha-config(返回 {"code":200,...} 即通)
  • 前端:http://localhost:8080/#/login
  • 前端日志出现 Proxy error: Could not proxy request /api/... (ECONNREFUSED) 说明**后端当时没起来**,不是前端问题。

四、数据库

  • 连接(本地开发库):
    & 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe' --host=127.0.0.1 --port=3308 --user=root --password=<见 AGENTS.md> --default-character-set=utf8mb4 -D traffic_audit
  • 必须写 --host=127.0.0.1:写成 -h127.0.0.1 会被解析成 host 127,连接失败。
  • 输出过滤 2>&1 | Select-String -NotMatch 'Warning' 可屏蔽密码警告。
  • 常用表与关键列:
表 说明 关键列
freight_turnover_import 货运量/周转量 report_period、region_name、freight_m01..m12、turnover_m01..m12、last_*
h2031_enterprise_monthly 公路旅客 H203-1 月报 report_period、enterprise_code、unified_credit_code、report_unit
import_batch 导入批次 import_type、report_period、file_name、success_rows
audit_result / audit_run 审核结果/运行 report_period
  • 排查「某期数据在不在」:SELECT report_period, COUNT(*) FROM <表> GROUP BY report_period ORDER BY report_period;
  • 排查「某期导入来自哪个文件」:查 import_batch 的 file_name。
  • 表结构变更要同步三处:实际库 DDL、docs/init.sql、docs/database.md。
  • 测试用报表期建议用 2099-xx,测完用 POST /api/import/clear?period=... 或直接 DELETE 清理,避免污染真实月份下拉项。

五、数据导入:文件路径与期次约定

5.1 货运量/周转量(/api/import/freightTurnover)

源文件 覆盖期次 备注
D:\05_数据分类\高速\定稿-湖北省各市州运输量数据(2026年1-8月).xlsx 2021-12 / 2022-12 / 2024-12 / 2025-12 / 2026-08 无 2023 年 Sheet
D:\05_数据分类\货运\7月\定稿-湖北省各市州运输量数据(2026年1-7月).xlsx 多一个 2023 Sheet 2023 年数据的来源;2021/2022/2024 与 8 月文件逐值一致
  • 多年度工作簿识别规则(detectYearSheets):
  1. 至少 2 个 Sheet(单 Sheet 文件不识别为多年度工作簿,会走老的月度模板路径);
  2. 每个 Sheet 名匹配 ^\d{4}\s*年?$(2023年、2023 都可以);
  3. 每个 Sheet 首行 A1 含「货运量」、B1 含「月」。
    任一条件不满足 → 整体回退老的月度模板解析。
  • 每个年度 Sheet 的结构:上方是「货运量(万吨)」块(约 20 行),下方是「周转量(万吨公里)」块;**同一市州名第二次出现即视为周转量块**。
  • 报表期语义:**2021-12 这类期放的是该年 1–12 月的全年数据**(m01..m12 全部有值),不是 12 月单月。该年最后有数据的月份决定期号(2026 年只有 1–8 月 → 2026-08)。
  • 上年同期:多年度文件里自动取**上一年度 Sheet**;若上一年度不存在(如 2021 无 2020 Sheet),last_* 为空。
  • 只补某一年时,可另存一个只含该年 + 上一年的临时工作簿再导入(注意「至少 2 个 Sheet」规则)。

5.2 公路旅客 H203-1(/api/import/passengerMonthly)

源文件 备注
docs\公路旅客\模板_交企统H203-1表_公路旅客运输月度生产情况.xlsx 用户修改后的模板
D:\桌面\测试数据\公路旅客\八月\公路旅客运输月度生产情况(2026)_2026-09-09 09_18_45.xls 系统导出的老格式样例
D:\需要导入的数据\公路旅客\*.xls 历史各月导出文件
  • 解析**按表头名取值**(buildHeaderMap),因此模板在中间插列/整体右移**不会**破坏其它字段。
  • 新模板在「企业名称」后新增 2 列:统一社会信用代码、填报单位;老格式文件其实也带这两列(此前代码未读取)。
  • 必需列缺失会直接报错,例如选错类型时提示「表头缺少必需列【企业名称】【客运量_总计】」。

5.3 其它

  • 导入失败必须在页面显示**行号**(用户要求),新增解析逻辑时不要吞掉行号信息。

六、报表生成

  • 「汇总大表」预览弹窗由 ReportExport.vue 渲染:
  • 弹窗内**只保留一张指标表**(分类 / 指标 / 数据 / 同比),「中口径」之后不再渲染任何表格;
  • 弹窗支持拖动(v-dialog-drag 指令,拖标题栏)+ 10px 圆角。
  • 导出依赖**母版模板文件**:docs/生成汇总大表/YYYY年M月道路运输量汇总表.xlsx。缺失时报「母版定位失败:未找到模板文件」,**不是数据问题**。
  • 接口层面自查(绕过前端,定位是前端还是后端问题):
  • 预览:GET /api/report/preview?period=2026-08&mode=month&types=summaryWorkbook
  • 导出:GET /api/report/export/summaryWorkbook?...
  • 失败提示已细分:能区分「连不上服务器」和「后端返回的具体原因」;导出接口是 responseType:'blob',报错时 data 也是 Blob,必须先 text() 再解析。

七、登录与验证码

问题 原因 处置
登录页出现空白方框 + 「验证码加载失败,请检查网络」 前端 captchaRequired 默认 true,读取 /api/auth/captcha-config 失败时静默忽略,页面残留加载不出来的验证码框 默认值改 false,改为 fail-safe:只有后端明确返回 required === true 才显示;请求失败按「不需要验证码」处理
开关位置 后端 application.yml 的 app.captcha.required 关掉后应显示「测试模式:行为验证码已跳过」
换网络/换 IP 后接口 403 跨域白名单 CORS 需放行内网网段(已修复 0d2a5fc)

八、文件写入与文本处理的坑

  • 本机文件**换行符不统一**:Login.vue、main.js 是 CRLF;ReportExport.vue、DataImportService.java、docs/*.md 是 LF。用 [System.IO.File]::WriteAllText 时必须匹配原换行符,否则后续 -replace / 字符串匹配会失败。
  • main.js 带 BOM(EF BB BF),改写时要用 New-Object System.Text.UTF8Encoding($true)。
  • git checkout -- <文件> 会把 LF 转成 CRLF(本仓库 core.autocrlf=true),会让后续基于 LF 的替换失效;操作前先确认真实换行符。
  • PowerShell 多行中文替换建议写 *.py 脚本用 python 执行(apply_patch 在本机不可用)。
  • 字符串替换**注意锚点唯一性**:| enterprise_name | varchar(200) | 企业名称 | 在 docs/database.md 出现 4 次,直接 replace 会改错表;必须先截取目标章节再替换。
  • 读 .xls:本机 python 无 xlrd,可用 Excel COM(New-Object -ComObject Excel.Application → Workbooks.Open → Cells.Item(r,c).Text,记得 Quit() + ReleaseComObject)。

九、浏览器自动化取证的坑

  • tab.playwright.evaluate() 读 DOM 才可信;AX 树可能读到缓存。
  • Playwright locator 对 Element UI 表格内按钮**会超时**(isVisible() 恒为 false);改用 AX 索引 tab.click(index)。
  • tab.drag([x1,y1],[x2,y2]) 拖拽时,坐标必须落在**当前视口**内(本机内嵌浏览器视口很小,约 319×790),否则报 Coordinate is outside the active tab content viewport。
  • tab.click 的 AX 索引**在页面刷新后会失效**,可能命中别的控件;每次操作前重新 cua.getTab(...) 取新索引。
  • 截图:const fs = await import('fs'); fs.writeFileSync(path, Buffer.from(await tab.getScreenshot()))(require 不可用)。
  • 改 .vue 后需要 tab.reload()。
  • 临时脚本/文件(_*.*)未经用户同意**不要删**。

十、Git 双仓库工作流

仓库 remote 分支 地址
个人 origin master https://gitee.com/zhizhijie/traffic-audit.git
公司 gitea main http://61.183.254.94:3000/r/trafficAudit.git(账号 zyj)

每次改动的固定顺序:
1. 测试 + 写《功能测试报告》 + 更新《工作日结》;
2. git fetch origin → 合并个人仓库新提交(避免覆盖用户改动);
3. git fetch gitea → 与远端 main 对比合并 → 禁止强推;
4. git commit → git push。

  • 凭据只走本机 git/临时 askpass,**禁止写进仓库任何文件**。
  • 公司 gitea 网络不通时记录为遗留问题,**不要**用强推绕过。

十一、当前已知遗留问题(截至 2026-09-16)

# 问题 影响 状态
1 8 月源文件缺 2023 年 Sheet 已用 7 月文件补录 2023-12 解决 已解决
2 2026-01 ~ 2026-07 的 last_* 为空 这几期改动前即为空,非本次引入 待用户确认是否补
3 2026-01 ~ 2026-07 的 H203-1 unified_credit_code / report_unit 为空 新列本期才读取,历史期未回填 待用户确认是否重导
4 预览弹窗「共 0 行」与「月度覆盖:1~8月均有数据」口径不同 易误解 待用户确认改文案
5 公司 gitea 推送 网络无响应,未推成功 待补推
6 仓库根目录大量 _*.* 临时文件 体积/可读性 经用户同意后再清理

2026-09-16 傍晚更新:遗留问题 4(预览弹窗「共 0 行」文案)已按用户确认修改完毕——汇总大表改为显示「指标 N 项」,其它报表显示「共 N 行明细」。