zzw
3 天以前 7858c25faa53dd2f4c0faae58618565ac5bb50ae
HANDOFF.md
@@ -404,12 +404,12 @@
- 本会话进展:用户给出 **AXU1 流程总览的口径变更**——第一版**不按原始需求**,改为 **① 简化业务流程 + ② 只提供网络版、不提供离线单机版**。
- **第一版简化流程(10 步,已确认;2026-09-20 细化验收链)**:T员故障上报 → XCB助理审核(**分配承修单位、拆单、生成工程单号**)→ CMB领导审批 → JCC助理审批 → JCC处长审批 → XCB助理派单(**显示未派单故障,勾选后一键派单,按承修单位生成派工单**)→ 厂家线下修理 → 厂家上报完工信息 → 完工验收流程(验收申请 → 质检员验收 → 质检负责人验收 → 完工验收打印输出 → 修后质量评级)→ 验收完成。
- 连带口径变更:① 取消艇长审批环节(原待确认清单第 9 条 → 已解决:不纳入第一版);② 取消全部离线能力(单机版/离线填写、数据包导入导出);③ 取消“XCB助理完工处理/导出完工项目”环节;④ 报价处理移出主流程;⑤ JCC助理审批确认为必经环节。
- 连带口径变更:① 取消T长审批环节(原待确认清单第 9 条 → 已解决:不纳入第一版);② 取消全部离线能力(单机版/离线填写、数据包导入导出);③ 取消“XCB助理完工处理/导出完工项目”环节;④ 报价处理移出主流程;⑤ JCC助理审批确认为必经环节。
- 已同步落盘:`requirement\界面还原.html`(新增全局口径条 + AXU1 卡片重写 + AXU2/AXU13 受影响标注)、`requirement\前44页需求梳理.md`(第 2 节业务总览、3.3 流程总览、4.1/6.2/6.3/第 7 节标注、第 9 节新增 14–17 条、术语表)、`requirement\工程状态机设计.md`(审批顺序、任务状态机、流转表/矩阵、新增待确认 11–12)、`requirement\决策表_待确认项.md`(全局口径、AXU1 行已核对、C-8 已解决、新增 C-12–C-15)。
- 当时待办的后续处理:C-12/C-13/C-14/C-15 均已解决;AXU3/AXU4 已于 2026-09-16 核对完成;A 组下一步为 AXU5,B 组工程状态机 10 项仍待答。
**2026-09-14 用户答复(已回填全部文档)**:
- ① 艇长环节不纳入第一版(确认);② 报价处理移出主流程,“报价管理”菜单与模块整体不做(C-14 已解决);③ JCC 助理审批为必经环节(确认);④ C-12 离线/数据包相关功能**整体取消,对应菜单项一并删除**(数据包导入、完工信息导入、导出待完工数据包、报价导出/导入);⑤ AXU2 数据包导入:只做网络版、无导入功能,**无需核对**(页面与菜单项删除)。
- ① T长环节不纳入第一版(确认);② 报价处理移出主流程,“报价管理”菜单与模块整体不做(C-14 已解决);③ JCC 助理审批为必经环节(确认);④ C-12 离线/数据包相关功能**整体取消,对应菜单项一并删除**(数据包导入、完工信息导入、导出待完工数据包、报价导出/导入);⑤ AXU2 数据包导入:只做网络版、无导入功能,**无需核对**(页面与菜单项删除)。
- 已解决:**C-13 派单口径**(2026-09-16 确认)——XCB助理审核仍负责分配承修单位、拆单、生成工程单号;后续派单页按故障选择、按承修单位生成派工单,不再重新分配承修单位或修改厂家。剩余:B 组工程状态机 10 项;A 组下一步 AXU5 CMB领导审批。(C-15 术语已于 2026-09-14 答复:统一写“T员验收”)
- 后续进展:A 组已于 2026-09-16 完成 AXU3/AXU4,下一步为 AXU5 CMB领导审批(AXU0/AXU1/AXU15 已完成,AXU2 免核对)。
@@ -469,7 +469,7 @@
当前纳入模块:XCB助理派单(AXU10)→ 完工情况处理(AXU14)→ 完工信息上报(AXU15)→ 完工验收(验收申请 → 质检员验收 → 质检负责人验收 → 完工验收打印输出 → 修后质量评级)→ 系统管理 → 统计报表。原临抢修工程管理中的 CMB领导已阅(AXU9)、已派工程(AXU11)、已派工程单(AXU12)、工程单打印输出(AXU13)以及技术文件管理(AXU16)暂不处理;监测信息、查询、基础信息和技术文件管理不再主动展开,除非用户后续补充需求。
原始需求流程(存档,已不采用):故障上报(数据包导入)→ 艇长(批量/单项)→ 大队助理(XCB)审批 → CMB领导审批 → JCC助理审批 → JCC处长审批 → …… → 完工信息上报 → 验收;含单机版/离线数据包与报价导出导入环节。
原始需求流程(存档,已不采用):故障上报(数据包导入)→ T长(批量/单项)→ 大队助理(XCB)审批 → CMB领导审批 → JCC助理审批 → JCC处长审批 → …… → 完工信息上报 → 验收;含单机版/离线数据包与报价导出导入环节。
关键规则(来自截图备注):
- 派单规则(2026-09-20 确认):JCC处长审批完成后进入XCB助理派单页面,显示“未派单”的故障一览;勾选一个或多个故障后点击“一键派单”,系统按每个故障的承修单位生成派工单。一个故障有多个承修单位时,每个承修单位各生成一张派工单。
@@ -517,7 +517,7 @@
6. 【已解决 2026-09-20】“键派单”确认应为“一键派单”;修改、生成临修工程单、删除亚复(疑为清除重复)等原截图业务按钮暂不需要。
7. 无截图模块页面设计:监测信息、查询(工程单/工程项目/故障信息/销项)、报价管理(导出待报价/修船办初审/JCC审核)、基础信息(JC信息/用户数据范围);系统管理菜单已确认包含承修单位管理、产品结构树管理、设备基础库管理;完工验收5菜单已确认,字段与页面细节仍待设计。
8. 【已解决】首页统计卡片完整清单(2026-09-10):实为“按X号统计表”表头 11 列(X号/当前状态/停靠泊位/TD/工程总数/销项总数/重大故障/未完工/完工待试验/已完工/待处理),非散列卡片;“JC信息”=舰船信息(2026-08-26)、TD=艇队(2026-09-10)均已确认。
9. 【已解决 2026-09-11】艇长环节不纳入第一版(简化流程从 T员故障上报直接进入 XCB助理审核)。
9. 【已解决 2026-09-11】T长环节不纳入第一版(简化流程从 T员故障上报直接进入 XCB助理审核)。
10. 字典数据:故障影响(示例“供气”)、故障性质(示例“重大”)已确认按可配置字典字段处理,其他取值待补;X号“当前状态”其他取值待补。
11. 术语勘误(OCR):白修=自修、T员队验收=T员验收(2026-09-14 确认统一写“T员验收”);H 为敏感词代称,非密材料统一写“是否涉H”(2026-09-16)。
12. 【待办·提醒用户】器材系统对接文档:用户已有文档,需要时向用户索取(器材目录表结构、器材ID、接口方式等)。
@@ -593,7 +593,7 @@
## 11. 收尾快照(2026-09-14 周一晚,用户关机前)
- **本会话(2026-09-11 晚 / 2026-09-14)结论已全部落盘**:`requirement\界面还原.html`、`requirement\前44页需求梳理.md`、`requirement\工程状态机设计.md`、`requirement\决策表_待确认项.md`、`requirement\敏感词字典.md` + 本文件;无临时文件残留(已核验),无进行中的未保存工作。
- **本次已解决的待确认项**:C-8(艇长环节不纳入第一版)、C-12(离线/数据包功能整体取消 + 对应菜单项删除)、C-14(报价管理菜单与模块整体不做)、C-15(术语统一写“T员验收”);AXU2 数据包导入免核对(页面取消)。
- **本次已解决的待确认项**:C-8(T长环节不纳入第一版)、C-12(离线/数据包功能整体取消 + 对应菜单项删除)、C-14(报价管理菜单与模块整体不做)、C-15(术语统一写“T员验收”);AXU2 数据包导入免核对(页面取消)。
- **仍未答复(下次开工从这里接)**:
  1. C-13 派单口径已于 2026-09-16 解决:XCB助理审核负责分配承修单位、拆单、生成工程单号;派单页按故障选择、按承修单位生成派工单。
  2. AXU3/AXU4 已于 2026-09-16 完成;A 组下一步为 AXU5 CMB领导审批。
@@ -725,4 +725,603 @@
- 非管理员用户的完工填报派工单单位匹配当前按 `DEPT_NAME`,不是按 `DEPT_ID`。本次验证通过;如存在同名部门,应改为按部门 ID 精确匹配。
- 历史演示派工单可能保留旧 `T_CONTRACTOR` 名称,非管理员 cj 用户可能看不到这些历史单;`admin` 不受单位过滤影响。
- `.codex-run`、Office 锁文件 `requirement\~$原始需求.docx` 和 `emergency-repair-web/public/新建 文本文档.txt` 属本地联调或临时文件,不应提交。
- 本轮代码与交接文档提交并推送公司 Git 仓库 `main` 分支;后续启动、构建和排错命令沿用第 16 节。
- 本轮代码已提交并推送公司 Git 仓库 `main` 分支,提交 `757dcb3`;交接文件回填提交记录。后续启动、构建和排错命令沿用第 16 节。
## 18. 收尾快照(2026-10-06 周一,需求 20 菜单权限管理收尾)
**本轮完成内容**
- 需求 20:菜单权限管理取消租户权限和角色权限的双重授权,改为单步设置角色权限。当前用户本身没有租户归属,因此不再设置租户权限。
- 权限树继续展示菜单节点和按钮节点,不按 `menuType` 过滤;切换角色后,已保存权限复选框正常反显。
- 菜单权限接口只保留 `roleId` / `roleMenuIds`,删除租户菜单授权及 `/api/system/tenants`。
- 修复雪花 ID 经浏览器 JSON 解析后精度丢失的问题:后端返回字符串 ID,前端选中态按字符串处理。
**主要文件**
- 后端:`emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java`、`emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java`、`emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`。
- 前端:`emergency-repair-web/src/views/system/MenuPermission.vue`。
**验证结果**
- 后端 `mvn -B -DskipTests compile` 通过;前端 `npm run build` 通过。
- 接口:`GET /api/system/menu-permissions?roleId=2106221661022490625` 返回字符串型 `roleMenuIds` 共 14 条。
- 浏览器:`node .codex-run/verify-menu-permission.js` 输出 `hasTenantPanel: false`、`buttonNodeCount: 76`、`checkedMatchesSaved: true`、`hasError: false`;截图 `.codex-run/menu-permission-verified.png`。
- 页面确认按钮节点保留,切换角色后权限勾选可正常反显。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`,后端 `http://127.0.0.1:8091`,DM8 `127.0.0.1:5236`,Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
- 后端日志:`.codex-run/backend-20261006-menu-permission-fixed.out.log`、`.codex-run/backend-20261006-menu-permission-fixed.err.log`。
**接手注意**
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码与交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 19. 收尾快照(2026-10-06 周一,需求 21-22 菜单权限入口与错误日志)
**本轮完成内容**
- 需求 21:移除独立“菜单权限管理”菜单,在角色管理操作列新增“权限设置”按钮,并复用菜单/按钮权限树弹窗;旧 `/system/menu-permissions` 路由和页面已删除。
- 需求 22:系统管理新增“系统配置 / 权限配置 / 日志管理”三个二级目录;组织机构、承修单位、产品结构树、设备基础库、工程专业、T队专业、三员控制归入系统配置,用户管理、角色管理、菜单管理归入权限配置,登录日志、操作日志、错误日志归入日志管理。
- 错误日志为新增功能:`GlobalExceptionHandler` 捕获未处理的非业务异常并异步写入 `LX.T_SYS_ERROR_LOG`;业务校验异常不记录。列表支持模块、异常类型、时间筛选,详情展示完整堆栈。
- 新库初始化和旧库迁移均会删除旧菜单并补齐二级目录的父子菜单关系;权限树继续保留菜单节点和按钮节点,角色切换后复选框可反显。
**主要文件**
- 后端:`emergency-repair-server/src/main/java/com/emergencyrepair/system/entity/SysErrorLog.java`、`.../mapper/SysErrorLogMapper.java`、`.../log/ErrorLogRecorder.java`、`.../common/GlobalExceptionHandler.java`、`.../bootstrap/DataInitializer.java`、`.../bootstrap/DatabaseBootstrap.java`、`.../system/controller/SystemController.java`、`.../system/service/SystemService.java`、`.../system/service/ButtonPermissionCatalog.java`。
- 前端:`emergency-repair-web/src/views/system/RoleManage.vue`、`RolePermissionDialog.vue`、`ErrorLogManage.vue`、`emergency-repair-web/src/router/index.js`、`MenuManage.vue`;`MenuPermission.vue` 已删除。
**验证结果**
- 后端 `mvn -B -DskipTests clean package` 通过;前端 `npm run build` 通过,仅有既有包体积告警。
- `node .codex-run/verify-req21-22.js` 通过:三个二级目录和错误日志菜单正常显示,旧菜单不存在,角色管理“权限设置”弹窗按钮节点数为 78 且反显正常。
- 人为访问非法错误日志详情 ID 后,记录自动落库并可在错误日志页面查看;验证用临时记录已从数据库清理。
- 截图:`.codex-run/role-permission-dialog-verified.png`、`.codex-run/error-log-verified.png`。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`;后端 `http://127.0.0.1:8091`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
- 后端日志:`.codex-run/backend-20261006-req21-22.out.log`、`.codex-run/backend-20261006-req21-22.err.log`。
**接手注意**
- 错误日志当前覆盖进入 Spring MVC 全局异常处理的异常;启动阶段异常、异步线程中未进入该处理器的异常暂不会自动落库。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码与交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 20. 收尾快照(2026-10-06 周一,需求 23-25 系统配置、完工查阅与菜单父节点)
**本轮完成内容**
- 需求 23:系统名称和版本改为关键词配置,codename 分别为 `rk_SystemName`、`rk_SystemVer`。登录页、页头、Logo 替代文本和浏览器标题使用配置值;页头版本使用红色显示。
- 需求 24:新增“完工信息查阅”功能,菜单 `/completion/query`,接口 `GET /api/work-orders/completion/query`。查询结果按故障汇总,一个故障展开多张派工单;故障编号、rk_X号、设备、工程名称及损坏情况、上报单位、上报日期、序号这 7 列使用单元格纵向合并。每张派工单的完工处理情况和更换器材支持多条明细。
- 需求 24 的查询条件包括关键词、承修单位、完工状态和完工日期。关键词匹配故障、派工单、工程编号、承修人和明细内容。
- 需求 25:菜单管理编辑时,“上级菜单”改为可编辑级联选择器;编辑时排除当前菜单及其全部下级,按钮类型只能选择菜单类型父节点。
- 需求 25 后端同步增加父节点存在性、自引用和循环层级校验,避免通过接口构造循环菜单树。
**主要文件**
后端:
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/CompletionFaultQueryItem.java`(新增)
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/controller/WorkOrderController.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java`
前端:
- `emergency-repair-web/src/views/completion/CompletionQuery.vue`(新增)
- `emergency-repair-web/src/views/system/MenuManage.vue`
- `emergency-repair-web/src/components/AppHeader.vue`、`Login.vue`、`RepairLogo.vue`、`layout/AppLayout.vue`、`router/index.js`、`utils/sensitive.js`、`main.js`
- `emergency-repair-web/public/sensitive-words.json`、`public/index.html`
- `requirement/敏感词字典.json`
**验证结果**
- 后端 `mvn -B -DskipTests compile` 通过;前端 `npm run build` 通过,仅有既有包体积告警。
- `node .codex-run/verify-req23-25.js`:页面标题和页头使用“临抢修管理系统 / 网络版”,版本颜色为 `rgb(255, 107, 107)`;完工查阅显示故障 `GZ-2026-012`、处理情况和器材;菜单编辑父节点显示“故障管理”且可编辑。
- 接口实测:临时同一故障插入两张派工单和两条完工记录后,`GET /api/work-orders/completion/query?keyword=ZZ-MERGE-TEST-20261006` 返回 1 个故障、2 张派工单,每条各 1 条处理情况和 1 条器材。
- 浏览器合并实测:页面生成 2 张派工单行,故障编号单元格只出现 1 次,7 个故障信息列均有 `rowspan=2`,两张单各自的处理情况和器材均正常显示,无网络异常;截图 `.codex-run/completion-query-merge-verified.png`。临时数据库记录已清理。
- 菜单父节点接口实测:临时创建父子菜单成功;把父菜单移动到其子菜单下返回“上级菜单不能选择当前菜单的下级”;把子菜单移动到其他父节点成功;临时菜单已清理。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`;后端 `http://127.0.0.1:8091`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
- 后端日志:`.codex-run/backend-20261006-req23-25-v2.out.log`、`.codex-run/backend-20261006-req23-25-v2.err.log`。
**接手注意**
- 完工信息查阅当前只汇总已经存在完工填报记录 `T_COMPLETION_INFO` 的派工单;仅完工处理但未填报完工信息的派工单不会出现在查阅结果中。
- 完工查阅接口当前一次返回全部匹配结果,没有分页;数据量进一步增大时建议增加分页或导出策略。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码、需求文件和交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 27. 收尾快照(2026-10-07 周三,CMB 审批后 JCC 助理列表未刷新)
**问题与根因**
- `rk_第二审批人审批` 通过后进入 `rk_第三审批人审批`,页面可能不显示已进入 `CMB_APPROVED` 状态的数据。
- CMB、JCC 助理、JCC 处长三个审批路由共用 `SimpleApproval.vue`,并共用同一个 keep-alive 缓存名 `SimpleApproval`。路由切换时组件实例被复用,但原代码只在 `created()` 查询一次,未在 `stage` 变化时重新加载。
**修复内容**
- 监听 `stage`,审批环节切换时清空旧关键词、选中项和列表,并按新状态立即查询。
- 增加 `activated()` 刷新逻辑:缓存页签再次激活时重新加载当前审批环节数据。
**主要文件**
- `emergency-repair-web/src/views/fault/SimpleApproval.vue`
**验证结果**
- 前端 `npm run build` 通过,仅有既有包体积告警。
- 真实接口数据验证:`XCB_REVIEWED` 为 `0` 条,`CMB_APPROVED` 为 `3` 条。
- 浏览器联调 `node .codex-run/verify-cmb-jcc-refresh.js` 返回 `pass: true`:直接进入 CMB 显示 `0` 条;切到 JCC 助理后重新查询并显示 `3` 条;从其他页签返回 JCC 助理后仍重新查询并显示 `3` 条。
- 截图:`.codex-run/cmb-jcc-refresh-verified.png`。
**当前运行状态(2026-10-07)**
- 前端 PID `57312`,监听 `http://localhost:8082`;后端 PID `56124`,监听 `http://127.0.0.1:8091`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;后端日志:`.codex-run/backend-20261007-req28-30-final.out.log`、`.codex-run/backend-20261007-req28-30-final.err.log`。
**接手注意**
- `.codex-run`、Office 锁文件及 `emergency-repair-web/public/新建 文本文档.txt` 仍为本地临时文件,不应提交。
- `emergency-repair-web/public/sensitive-words.json` 是用户既有未提交修改,本轮不纳入提交。
## 28. 收尾快照(2026-10-07 周三,业务字典改为发布后可修改)
**实现方式**
- 将任务状态、完工状态、验收状态字典迁移到 `emergency-repair-web/public/dict.js`,以 `window.__APP_DICT__` 暴露运行时配置。
- 原 `src/utils/dict.js` 保留为适配层,提供内置兜底字典、运行时字典合并和加载函数;`src/main.js` 在挂载应用前加载 `dict.js?ts=时间戳`,避免浏览器缓存旧字典。
- 前端构建后文件位于 `dist/dict.js`。发布后直接修改该文件中的 `text`、`type` 或状态项,刷新页面即可生效,无需重新执行 `npm run build`。
**主要文件**
- `emergency-repair-web/public/dict.js`
- `emergency-repair-web/src/utils/dict.js`
- `emergency-repair-web/src/main.js`
**验证结果**
- 前端 `npm run build` 通过,`dist/dict.js` 正常生成,仅有既有包体积告警。
- 临时将 `public/dict.js` 中 `UNREPORTED.text` 改为 `未上报[外部测试]`,不重新构建,仅刷新故障上报页面后筛选下拉立即显示新文字;恢复原值后刷新也立即恢复。
- 浏览器实际请求包含 `http://localhost:8082/dict.js?ts=...`;应用在字典加载完成后再挂载,接口不可用时仍使用内置兜底字典。
**发布后操作**
- 编辑部署目录中的 `dist/dict.js`,保存后刷新浏览器即可。不要再重新构建前端,否则会用当前源码字典覆盖手工修改。
## 21. 收尾快照(2026-10-06 周一,需求 21 权限设置范围切换)
**本轮完成内容**
- 角色管理“权限设置”弹窗增加“全部 / 已设置”切换,交互方式与“用户设置”保持一致。
- “全部”显示完整菜单及按钮权限树,保留“全选”和原有权限反显。
- “已设置”仅显示当前角色已授权节点及其父级路径;没有已设置权限时显示空状态提示。
- 切换范围时会保留当前尚未保存的勾选状态,切回“全部”后恢复完整树及当前选中权限。
- 弹窗每次重新打开默认回到“全部”。
**主要文件**
- `emergency-repair-web/src/views/system/RolePermissionDialog.vue`
- `requirement/改进20261003.txt`(补充需求 21 的范围切换口径)
**验证结果**
- 前端 `npm run build` 通过,仅有既有包体积告警。
- `node .codex-run/verify-req21-22.js` 通过:左侧无“菜单权限管理”,角色管理存在“权限设置”。
- 全部视图显示 119 个复选框、13 个已勾选、1 个半选;已设置视图显示 14 个节点,均为当前已设置节点或父级路径;切回全部后勾选状态恢复,无网络异常。
- 截图:`.codex-run/role-permission-assigned-scope.png`。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`;后端 `http://127.0.0.1:8091`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
**接手注意**
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码、需求文件和交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 22. 收尾快照(2026-10-06 周一,需求 26 日志日期范围分隔符)
**本轮完成内容**
- 修复登录日志、操作日志、错误日志三个页面日期范围组件中间“至”显示不完整的问题。
- 三个页面的 `.el-range-separator` 固定为 `18px` 并居中显示,避免 Element UI 默认百分比宽度在 260px 日期控件中被压缩裁切。
**主要文件**
- `emergency-repair-web/src/views/system/LoginLogManage.vue`
- `emergency-repair-web/src/views/system/OperationLogManage.vue`
- `emergency-repair-web/src/views/system/ErrorLogManage.vue`
- `requirement/改进20261003.txt`(补充需求 26)
**验证结果**
- 前端 `npm run build` 通过,仅有既有包体积告警。
- `node .codex-run/verify-req26.js` 通过:三个日志页面均找到“至”,实际宽度、`clientWidth` 和 `scrollWidth` 均为 `18px`,计算样式为 `flex-basis: 18px`、`min-width: 18px`、居中,无网络异常。
- 截图:`.codex-run/login-log-date-separator.png`、`.codex-run/operation-log-date-separator.png`、`.codex-run/error-log-date-separator.png`。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`;后端 `http://127.0.0.1:8091`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
**接手注意**
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码、需求文件和交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 23. 收尾快照(2026-10-06 周一,需求 27 设备选择范围)
**本轮完成内容**
- 新增故障选择 `rk_X号`(产品结构树 `side` 类型节点)后,设备选择器只以所选节点为根展示其下级,不再同时返回型号根节点和整棵产品结构树。
- 设备选择器打开锁定范围时自动展开返回的 `side` 根节点,首屏直接显示第一层系统节点,后续继续按原逻辑懒加载。
- `xNo` 为空时仍返回完整产品结构树,不影响产品结构树管理和不按 `rk_X号` 筛选的设备选择场景。
**主要文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`
- `emergency-repair-web/src/components/ProductTreePicker.vue`
- `requirement/改进20261003.txt`(补充需求 27)
**验证结果**
- 后端 `mvn -B -DskipTests compile`、`mvn -B -DskipTests package` 通过;前端 `npm run build` 通过,仅有既有包体积告警。
- `GET /api/system/tree/product/side-roots?xNo=203` 修复后只返回 1 个根节点:`id=1280000000000009729`、`name=203`、`layer=side`、`level=2`;`201 / 203 / 301 / 测试T` 分别只返回对应节点。
- `node .codex-run/verify-req27.js` 通过:根节点文本仅为 `203`,自动展开 1 个根节点,首屏显示其下级系统节点,无网络异常。
- 请求链路确认:`/api/system/tree/product/side-roots?xNo=203` 后继续请求 `/api/system/tree/product/children?parentId=1280000000000009729`。截图:`.codex-run/req27-side-tree.png`。
**当前运行状态(2026-10-06)**
- 前端 `http://localhost:8082`,PID `138164`;后端 `http://127.0.0.1:8091`,PID `148268`;DM8 `127.0.0.1:5236`;Edge CDP `9222`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
- 后端日志:`.codex-run/backend-20261006-req27.out.log`、`.codex-run/backend-20261006-req27.err.log`。
**接手注意**
- 需求 26 已提交并推送,提交 `f651ad5`(`fix: show full date range separator in log filters`)。需求 27 已提交并推送,提交 `f9114ff`(`fix: limit equipment picker to selected X number`)。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码、需求文件和交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 24. 收尾快照(2026-10-06 周一,菜单名称被启动初始化覆盖)
**问题与修复**
- 手工把系统配置下的“产品结构树管理”改为“产品结构树”后,后端重启会恢复“管理”二字。
- 原因是 `DataInitializer.ensureMenu()` 每次启动都会拿代码中的默认名称覆盖已存在菜单。
- 已改为只在新建菜单时使用默认名称;已存在菜单只修复父节点、排序、类型和可见性,名称由菜单管理页面维护。
- 新建数据库的默认菜单名称同步改为“产品结构树”。
**主要文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java`
**验证结果**
- 后端 `mvn -B -DskipTests compile`、`mvn -B -DskipTests package` 通过。
- 将数据库菜单 `id=2101493905517301763`、`url=/system/product-tree` 的名称改为“产品结构树”后,使用新 jar 重启后端,接口再次查询仍为“产品结构树”。
- 新后端 PID `151580`,监听 `8091`;日志:`.codex-run/backend-20261006-menu-name.out.log`、`.codex-run/backend-20261006-menu-name.err.log`。
## 25. 收尾快照(2026-10-07 周三,清空故障及完工业务数据)
**本次操作**
- 清空 `LX.T_FAULT`、`LX.T_WORK_ORDER`、`LX.T_COMPLETION_INFO`、`LX.T_ACCEPTANCE` 四张业务表。
- 清空前数量:故障 `23`、派工单 `8`、完工信息 `6`、验收 `6`;清空后均为 `0`。
- 同步关闭启动演示业务数据回填:新增配置 `app.seed-demo-data=false`,避免 `T_FAULT` 为空时后端重启又自动生成 16 条演示故障及完工数据。
**主要文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java`
- `emergency-repair-server/src/main/resources/application.yml`
**验证结果**
- 后端 `mvn -B -DskipTests clean package` 通过。
- 使用新 jar 重启后再次查询,四张业务表仍均为 `0` 行;登录接口 `200`,前端首页 `200`。
- 当前后端 PID `21528`,监听 `8091`;日志:`.codex-run/backend-20261007-cleared.out.log`、`.codex-run/backend-20261007-cleared.err.log`。
- 如需重新灌入演示业务数据,将 `app.seed-demo-data` 临时设为 `true` 后重启。
## 26. 收尾快照(2026-10-07 周三,需求 28-30 扩展属性与新增故障默认值)
**需求口径**
- 需求 30 编号已确认;新增故障里的“责任”就是“负责人”。
- 部门扩展属性“负责rk_T”的值就是 `rk_X号`,值必须是产品结构树 `side` 类型节点,单选。
- 新增故障的 `rk_X号` 默认值只取登录用户所属部门的扩展属性;即使用户扩展属性也设置了“负责rk_T”,仍以部门设置为准。
- “rk_TD专业”与现有“rk_T队专业”是同一字段,代码字段为 `teamMajor`,当前界面暂时沿用“rk_T队专业”。
- 外部 `CSICZB_ZB.SYS_DEPT`、`CSICZB_ZB.SYS_USER` 由其他系统维护,本项目只读;扩展属性保存到本地新表。
**本轮完成内容**
- `DatabaseBootstrap` 自动创建 `LX.T_SYS_DEPT_EXT`(`DEPT_ID`、`RESPONSIBLE_X_NO` 及审计字段)和 `LX.T_SYS_USER_EXT`(`USER_ID`、`ENGINEERING_MAJOR`、`TEAM_MAJOR`、`RESPONSIBLE_X_NO` 及审计字段)。
- 组织机构页面增加“扩展属性”按钮和弹窗,可设置部门“负责rk_T”;列表显示已设置值。
- 用户管理列表展开显示工程专业、rk_T队专业、负责rk_T三列,未设置时显示“未设置”;表格最后增加固定“操作”列,提供“编辑属性”按钮打开设置弹窗。
- 新增故障弹窗默认带出:上报单位为当前登录人的单位、负责人为当前登录人、`rk_X号`为当前部门扩展属性、工程专业和 rk_T队专业为当前用户扩展属性。
- 用户扩展属性为空时,工程专业和 rk_T队专业不再默认选择配置列表第一项。
**接口与权限**
- `GET/PUT /api/system/depts/{deptId}/ext`:查询和保存部门扩展属性。
- `GET/PUT /api/system/users/{userId}/ext`:查询和保存用户扩展属性。
- `/api/auth/login`、`/api/auth/me` 返回 `userId`、`deptId`、`engineeringMajor`、`teamMajor`、`deptResponsibleXNo`、`responsibleXNo`。
- 按钮权限新增 `system:organization:ext`(扩展属性设置)、`system:users:ext`(扩展属性设置)。
**主要变更文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/auth/AuthController.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DatabaseBootstrap.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/dto/Requests.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/controller/SystemController.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/ButtonPermissionCatalog.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/system/service/SystemService.java`
- `emergency-repair-web/src/views/Login.vue`
- `emergency-repair-web/src/views/fault/FaultReport.vue`
- `emergency-repair-web/src/views/system/OrganizationManage.vue`
- `emergency-repair-web/src/views/system/UserManage.vue`
- `requirement/改进20261003.txt`(补充需求 28-30)
**验证结果**
- 后端 `mvn -B -DskipTests clean package` 通过;前端 `npm run build` 通过,仅有既有包体积告警。
- `node .codex-run/verify-req28-30.js` 返回 `pass: true`。
- 部门 `1390477009348739073 / sy区域` 设置 `rk_X号=201`,用户 `123 / yszl` 设置工程专业 `动力专业`、rk_T队专业 `液压专业`、负责 `202`。
- 新增故障实际默认值为:上报单位 `sy区域`、负责人 `助理用户(演示)`、`rk_X号=201`、rk_T队专业 `液压专业`、工程专业 `动力专业`。
- 用户管理页面实测表头顺序为工程专业、rk_T队专业、负责rk_T、状态、操作,行内扩展值正常,操作列每行显示“编辑属性”;截图:`.codex-run/req29-user-ext.png`。
- 截图:`.codex-run/req28-org-ext.png`、`.codex-run/req29-user-ext.png`、`.codex-run/req30-fault-defaults.png`。
- 验证后已清除临时部门、用户扩展属性,查询确认 `configured=false` 且字段为空。
**当前运行状态(2026-10-07)**
- 后端 PID `56124`,监听 `http://127.0.0.1:8091`;前端 PID `57312`,监听 `http://localhost:8082`。
- 为 UI 验证启动的 headless Edge PID `95756`,CDP 端口 `9222`;配置目录 `.codex-run/edge-profile-req28-30`。
- 后端日志:`.codex-run/backend-20261007-req28-30-final.out.log`、`.codex-run/backend-20261007-req28-30-final.err.log`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
**接手注意**
- 开发环境敏感词配置会把 `rk_T` 显示为“梯”,因此页面截图中可能显示“负责梯”;代码和后端字段仍是 `rk_T`。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
- 本轮代码、需求文件和交接记录一并提交并推送公司 Git 仓库 `main` 分支。
## 27. 收尾快照(2026-10-09 周五,需求 32 工程单打印修正与验证)
**本轮修正内容**
- 工程单 Word 模板的最右列独立为 `UnitNo` 栏,列宽 `400` twips;该列跨联头、表头和数据行纵向合并,单元格文字方向为 `btLr`(从下到上竖排)。
- 移除联头中原来的“第{unitNo}联”,改为右侧 `UnitNo:{unitNo}`,四联依次替换为 `1/2/3/4`。
- 联头补回 `ZB型号:{zbModel}`。渲染时按故障 `xNo` 定位产品结构树 `side/SIDE` 节点,取其父节点名称作为 `zbModel`。
- 增加四联名称配置:每联可在后台业务配置中单独设置名称,Word 顶部按 `第1联    上报人` 的格式输出。
- 新建独立业务配置文件 `emergency-repair-server/config/business-config.yml`,把 `fault-code.prefix`、工程单模板路径和四联名称集中维护,避免每次改业务参数都动主 `application.yml`。
- 默认模板版本升级为 `engineering-order-template-v3`;启动时若模板缺少版本标记、`{zbModel}` 或 `{unitDisplay}`,会自动生成新版模板。运营人员仍可在 `emergency-repair-server/config/engineering-order-template.docx` 上用 Word 调整版式。
- 主 `application.yml` 通过 `spring.config.import` 引入独立业务配置;配置文件缺失时不影响程序启动。
**主要文件**
- `emergency-repair-server/config/business-config.yml`
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/service/EngineeringOrderPrintService.java`
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/service/BusinessService.java`
- `emergency-repair-server/src/main/resources/application.yml`
- `emergency-repair-server/config/engineering-order-template.docx`
- `emergency-repair-web/src/views/fault/EngineeringPrint.vue`
**验证结果**
- 将四联名称临时改为 `1=上报人`、`2=审核人` 后重启,生成 Word 实际输出 `第1联    上报人 | 第2联    审核人 | 第3联 | 第4联`,确认外部业务配置文件已被读取;恢复 `2` 为空后再次验证输出为 `第1联    上报人 | 第2联 | 第3联 | 第4联`。
- 使用 `admin / admin123` 登录成功,查询到 6 条故障并调用 `POST /api/faults/engineering-print`,实际下载生成 Word。
- 生成文档解析结果:4 个表格(四联)、3 个分页符;每联 8 行,其中 6 行数据。
- 四联右侧 `UnitNo` 分别为 `1/2/3/4`;最右单元格具备 `vMerge`、`textDirection=btLr`、`tcW=400`。
- 文档中 `{zbModel}`、`{unitNo}`、`{unitName}`、`{unitDisplay}` 残留数量均为 0。
- 当前产品树 `201` 的 `side` 节点父节点为 `型号s44444`;生成联头实际为 `X号:201 ZB型号:型号s44444 专业:动力专业…`。
- 四联顶部标题实际为 `第1联    上报人`、`第2联`、`第3联`、`第4联`。
- 本轮后端重新打包并启动成功;前端构建此前已通过,仅有既有 webpack 包体积告警。
**当前运行状态(2026-10-09)**
- 前端 `http://localhost:8082`,PID `144352`;后端 `http://127.0.0.1:8091`,PID `218764`。
- DM8 `127.0.0.1:5236`;登录 `admin / admin123`;业务 schema `LX`。
- 后端日志:`.codex-run/backend-20261009-business-config-v3.out.log`、`.codex-run/backend-20261009-business-config-v3.err.log`。
- 本轮重新打包并重启后,磁盘模板已确认升级为 `engineering-order-template-v3`;独立业务配置已生效。
**接手注意**
- 不要提交 `.codex-run`、`engineering-order-verify.docx`、Office 锁文件 `config/~$gineering-order-template.docx` 或 `emergency-repair-web/public/新建 文本文档.txt`。
- `engineering-order-template.docx` 已是 v3;如 WPS 正在占用该文件,后端启动时不会覆盖,打印服务会使用内存中的 v3 默认模板,关闭 WPS 后重启即可恢复磁盘模板自动升级。
- 若后续修改联头或表格列,模板版本标记仍需保留;需要强制升级模板时再提升 `TEMPLATE_VERSION`。
## 29. 修正快照(2026-10-09 周五,工程单四联名称位置修正)
**用户澄清**
- 四联名称不能放在 Word 顶部作为标题,必须写在原来 `UnitNo` 的最右列竖排位置,并用它替换原来的 `UnitNo` 文本。
**本轮修正**
- 默认模板版本由 `engineering-order-template-v3` 升级为 `engineering-order-template-v4`。
- 最右列单元格占位符由 `UnitNo:{unitNo}` 改为 `{unitDisplay}`,继续保留 `vMerge`、`btLr` 竖排和 `400` twips 列宽。
- 移除表格上方的 `{unitDisplay}` 标题段落;输出后四联右侧依此显示 `第1联    上报人`、`第2联`、`第3联`、`第4联`。
- `config/business-config.yml` 的 `unit-names` 配置方式不变,后续只需调整各联名称。
**验证结果**
- 后端 `mvn -B -DskipTests compile` 与 `mvn -B -DskipTests package` 通过。
- 重启后磁盘模板已升级为 `engineering-order-template-v4`,模板正文中已无 `UnitNo`,`{unitDisplay}` 位于最右竖排单元格。
- 实际调用 `POST /api/faults/engineering-print` 生成 Word 并解析:4 个表格、3 个分页符,`UnitNo` 残留 `0`,`第1联    上报人` 位于最右竖排单元格,其他三联分别为 `第2联`、`第3联`、`第4联`。
- 验证文件:`.codex-run/engineering-order-unit-display-right.docx`。
**当前运行状态(2026-10-09)**
- 前端 `http://localhost:8082`,PID `144352`;后端 `http://127.0.0.1:8091`,PID `216492`。
- 后端日志:`.codex-run/backend-20261009-unit-display-right.out.log`、`.codex-run/backend-20261009-unit-display-right.err.log`。
## 30. 修正快照(2026-10-09 周五,工程单模板原位填充并保留 Word 样式)
**用户澄清**
- 工程单打印不应重新构造一份空白 Word,而应打开现有 Word 模板,按模板中的 `{}` 标识填写数据,并保留模板原有样式。
**本轮修正**
- `EngineeringOrderPrintService` 改为先读取 `config/engineering-order-template.docx`,在模板文档对象上复制正文并填充标记,不再通过 `new XWPFDocument()` 创建空白目标文档。
- 保留模板包内的 `styles.xml`、页眉、页脚、主题、图片等资源;正文段落和表格的段落样式、字体、字号、加粗、边框、列宽等随模板副本保留。
- 标记替换同时支持 `{field}` 和 `{{ field }}`,并支持标记跨多个 Word run 的情况;替换值优先写入标记起始 run,以保留该处原有字体格式。
- `ensureTemplate()` 仅在模板文件不存在时生成默认模板;已有模板不再因版本标记或占位符检查被自动覆盖,便于运营人员直接用 Word 维护版式。
- `openTemplate()` 始终优先使用磁盘模板,磁盘模板缺失时才回退到内存默认模板。
**主要文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/service/EngineeringOrderPrintService.java`
- `emergency-repair-server/config/engineering-order-template.docx`
**验证结果**
- 后端 `mvn -B -DskipTests package` 通过。
- 使用当前默认模板调用 `POST /api/faults/engineering-print`,生成 `.codex-run/engineering-order-template-style-smoke.docx`:占位符残留 `0`、四联头 `4` 个、分页符 `3` 个。
- 另用带 `styles.xml`、3 组页眉页脚、`theme1.xml`、`fontTable.xml` 的 `临修工程完工验收单.docx` 作为模板,在独立 `8092` 端口启动后端生成 `.codex-run/engineering-order-styled-template-output.docx`。
- 输出中 `styles.xml`、页眉页脚、主题、字体表均存在;经 XML 规范化对比,样式、页眉、页脚内容与源模板一致。输出中没有 `{}` 或 `{{}}` 残留,四联和 3 个分页符正常。
- 样式验证期间临时 `8092` 进程已停止,主后端和前端保持运行。
**当前运行状态(2026-10-09)**
- 前端 `http://localhost:8082`,PID `144352`;后端 `http://127.0.0.1:8091`,PID `224748`。
- 后端日志:`.codex-run/backend-20261009-template-style.out.log`、`.codex-run/backend-20261009-template-style.err.log`。
- 登录 `admin / admin123`;数据库 `SYSDBA/SYSDBA`,业务 schema `LX`。
**接手注意**
- 已有 `engineering-order-template.docx` 会按原样使用,不再自动升级覆盖;如需重建默认模板,先备份并删除该文件,或在代码中显式生成。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
## 31. 修正快照(2026-10-09 周五,工程单非明细表重复末行修复)
**问题现象**
- 工程单模板包含上方 X 号/型号信息表、中间故障明细表和下方签字表。打印后上方信息表的最后一行被复制成多条,下方签字日期行也被重复增加。
**原因与修正**
- 原逻辑只要模板中出现任意 `{}` 占位符,就把每一张表的最后一行都按记录数展开。
- 现改为按表格内容识别:只有包含 `faultCode`、`equipmentName`、`repairRequirement` 等明细字段的表格才展开最后一行;信息表和签字表只替换字段,不复制行。
**验证结果**
- 后端 `mvn -B -DskipTests package` 通过。
- 使用当前实际模板和 6 条故障数据生成 `.codex-run/engineering-order-template-row-fix.docx`。
- 第 1 张信息表固定 `2` 行,第 2 张明细表为 `7` 行(表头 1 行 + 数据 6 行),第 3 张签字表固定 `3` 行;四联均一致。
- 输出占位符残留 `0`,分页符 `3` 个。
**当前运行状态(2026-10-09)**
- 前端 `http://localhost:8082`,PID `144352`;后端 `http://127.0.0.1:8091`,PID `225740`。
- 后端日志:`.codex-run/backend-20261009-template-table-rows.out.log`、`.codex-run/backend-20261009-template-table-rows.err.log`。
## 32. 修正快照(2026-10-09 周五,工程单签字表固定一页底部)
**问题现象**
- 模板把签字表移到页面最下方,中间用 11 个空段落撑高。6 条明细打印后,签字表被挤到下一页;四联实际输出为 7 页,中间还有空白页。
**原因与修正**
- 空段落撑高会随明细行数变化,6 行明细时必然溢出;原来四联间使用独立分页段落,在上一页排满时也可能先落到下一页,再产生空白页。
- 渲染时删除明细表与底部签字表之间的纯空段落,以及签字表后的纯空段落。
- 将模板最后一张表设为 `vertAnchor=margin`、`tblpYSpec=bottom`,直接固定到文本区域底部,不再依赖空段落撑高。
- 四联分页改为在下一联首个正文元素上设置 `w:pageBreakBefore`,不再额外插入独立分页段落,避免空白页。
**验证结果**
- 后端 `mvn -B -DskipTests package` 通过。
- 6 条记录生成 `.codex-run/engineering-order-template-one-page.docx`,Word 实际统计 `4` 页,四联分别在第 `1/2/3/4` 页。
- 每联表格固定为:信息表 `2` 行、明细表 `7` 行、签字表 `3` 行;签字表纵向位置约 `427.9pt`,位于文本区域底部,未与明细表重叠。
- 2 条记录生成 `.codex-run/engineering-order-template-two-records.docx`,仍为 `4` 页,签字表同样固定在底部。
- 输出中 `pageBreakBefore` 为 `3` 个,占位符残留 `0`。
**当前运行状态(2026-10-09)**
- 前端 `http://localhost:8082`,PID `144352`;后端 `http://127.0.0.1:8091`,PID `223880`。
- 后端日志:`.codex-run/backend-20261009-template-one-page.out.log`、`.codex-run/backend-20261009-template-one-page.err.log`。
## 33. 修正快照(2026-10-10 星期六,工程单打印单条记录禁止跨页)
**用户澄清**
- 工程单打印不限制每页记录条数,可以多页输出;关键是**一条故障记录不能跨页**,且记录高度随文本多少变化,必须动态计算,不能写死行高或条数。
- 第 1 个表格(X 号/型号信息)与第 3 个表格(签字表)分别固定在每页顶部和底部,由程序动态生成,模板不需要再改位置。
**本轮修正**
- `EngineeringOrderPrintService.configureDetailTablePagination` 继续对每一行设置 `w:cantSplit`(行不可拆)。
- 新增 `configureCellParagraphPagination(row)`:对行内所有单元格段落设置 `w:keepLines`(段落不可拆到两页)。
- 两者配合后,行高仍由 Word 按实际文本动态排版,没有固定行高、固定每页条数或字符数阈值。
**主要文件**
- `emergency-repair-server/src/main/java/com/emergencyrepair/business/service/EngineeringOrderPrintService.java`(第 488-514 行附近)
**验证结果**
- 后端 `mvn -B -DskipTests clean package` 通过(JDK `C:\Program Files\Java\jdk1.8.0_172`,Maven `D:\solidDir\apache-maven-3.6.1`)。
- 实际调用 `POST /api/faults/engineering-print`(6 条故障)生成 `.codex-run/engineering-order-dynamic-pagination-2.docx`:`cantSplit` 28 个、`keepLines` 224 个、`tblHeader` 4 个、四联分页 `pageBreakBefore` 3 个、占位符残留 0。
- 正常数据经 Word 导出 `.codex-run/engineering-order-normal-fresh.pdf` 为 4 页,一联一页。
- 长文本边界测试:把第 1 条明细的单元格文本放大到约 900 字符(`.codex-run/engineering-order-long-row-fresh2.docx`),Word 重新分页后为 5 页;`.codex-run/engineering-order-long-row-fresh2.pdf` 中该记录的全部文本只出现在第 1 页,其余 5 条记录与签字表顺延到第 2 页,记录未跨页。
- 渲染截图:`.codex-run/word-export-long-row-fresh/page-1.png` 至 `page-5.png`;逐页字符统计脚本 `.codex-run/count_marker_chars.py`。
- 注意:用 .NET `ZipArchive` 改写 docx 会让 Word 报“文件可能已经损坏”,必须用 Python `zipfile` 重写测试文档。
**当前运行状态(2026-10-10)**
- 后端 `http://127.0.0.1:8091`,PID `180416`,标准 fat jar 启动:`java -cp target\emergency-repair-server-1.0.0-SNAPSHOT.jar org.springframework.boot.loader.JarLauncher`。
- 后端日志:`.codex-run/backend-20261010-dynamic-pagination-8.out.log`、`.codex-run/backend-20261010-dynamic-pagination-8.err.log`。
- 前端 `http://localhost:8082`,进程 PID `232852`,日志:`.codex-run/frontend-20261010-dynamic-pagination.out.log`、`.codex-run/frontend-20261010-dynamic-pagination.err.log`。
- 登录 `admin / admin123`,打印接口测试使用 `Authorization: Bearer demo-admin-token`。
**接手注意**
- 极端情况下若单条记录的实际排版高度超过一整页,任何 Word 行级约束都无法让它完整放在一页;当前业务数据不存在该情况。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
## 34. 修正快照(2026-10-10 星期六,工程单按明细分组连续打印四联)
**用户澄清**
- 同一个明细数据的 4 联必须连续打印,再打印下一个明细数据的 4 联,不能先打印所有明细的第 1 联再打印第 2 联。
**本轮修正**
- `EngineeringOrderPrintService.renderUnits` 调整为外层遍历明细记录、内层遍历 1-4 联。
- 每张明细表只渲染当前一条记录,并在下一张联表前设置分页;保留单条记录 `cantSplit + keepLines`,避免记录跨页。
- 主要文件:`emergency-repair-server/src/main/java/com/emergencyrepair/business/service/EngineeringOrderPrintService.java`。
**验证结果**
- 使用 6 条故障数据调用 `POST /api/faults/engineering-print`,生成 `.codex-run/engineering-order-per-record-units.docx` 和对应 PDF。
- DOCX 顶层元素顺序确认:明细 1 的第1/2/3/4联连续,随后是明细 2、3、4、5、6 的各自四联。
- 共 48 张联表、24 页;每联标签各 6 次,占位符残留 0,`pageBreakBefore` 23 个。
- PDF 页分组确认:第 1-4 页为明细 1,第 5-8 页为明细 2,依次到第 21-24 页为明细 6。
- 后端当前运行 PID `243948`,监听 `http://127.0.0.1:8091`;前端 PID `232852`,监听 `http://localhost:8082`。
- 后端日志:`.codex-run/backend-20261010-per-record-units.out.log`、`.codex-run/backend-20261010-per-record-units.err.log`。
## 35. 修正快照(2026-10-10 星期六,工程单打印分页问题定位)
**用户反馈**
- 用户反馈“结果不对,每页明细数据都只有一条”。
**定位结论**
- 最初怀疑用户打开的是 `2026-10-10 12:45:28` 生成的旧版文件,但后续确认该结论不成立:真正的根因是当前代码在展开明细表时,只替换了数据行,模板中作为联头的第 1 行用了空值替换,导致右侧竖排单元格的联号/联名被写成空字符串。详见第 36 节。
- 当前代码已改为单张明细表内按“记录 1 的第 1-4 联、记录 2 的第 1-4 联……”顺序渲染,并保留 `cantSplit + keepLines`;不再把同一故障的四联整体 `keepNext` 绑定,避免长记录把整组推到下一页。
**当前代码验证**
- 用同一批 6 条故障重新调用 `POST /api/faults/engineering-print`,生成 `.codex-run/engineering-order-current.docx`。
- 当前 DOCX 只有 `1` 张明细表,短记录可在同页排多条,四联顺序连续;联号/联名的最终验证见第 36 节。
- 当前文件另存验证副本:`C:\Users\Lenovo\Downloads\工程单-当前后台验证-20261010-135834.docx`。
**边界说明**
- 全量 22 条数据测试时,部分测试记录的“工程名称及损坏情况”超过 300 个字符,单联高度已接近或超过一页可用明细区域;这种情况下 WPS 无法把四联或同页多条记录强行压在页内,即使去掉 `keepNext` 也仍会一联一页。
- 这不是当前分组代码造成的;当前代码已消除了旧版“一联一张顶层表格”的硬分页。
**运行状态(2026-10-10 13:58)**
- 前端 `http://localhost:8082`,PID `232852`,端口已监听。
- 后端 `http://127.0.0.1:8091`,PID `247224`,启动时间 `2026-10-10 13:46:23`,端口已监听。
## 36. 修正快照(2026-10-10 星期六,工程单联号/联名未显示修复)
**用户反馈**
- 用户反馈“联号和联名页没显示”,即 Word 工程单最右侧竖排单元格里的“第N联 上报人”为空。
**根因**
- 模板明细表第 1 行是联头行(含最右侧 `{unitDisplay}` 竖排单元格),最后一行是数据行。
- 旧逻辑只展开并写入数据行,联头行用空值替换,导致联号/联名被写成空字符串,输出里只剩数据、没有联头标识。
**代码修改**
- `EngineeringOrderPrintService.renderUnits` 改为调用 `renderDetailTable(detailTable, records, unitNames)`。
- 新增 `renderDetailTable`:按“故障1的第1至4联,故障2的第1至4联……”逐组复制模板联头行和数据行,并对每联正确写入 `unitNo`、`unitName`、`unitDisplay`。
- `unitDisplay` 格式为 `第N联`,配置了名称时追加四个空格和名称,例如 `第1联    上报人`。
- `configureDetailTablePagination` 保留每行 `cantSplit` 和段落 `keepLines`,显式清除旧 `keepNext`,只让联头行与自己的数据行保持 `keepNext`;不再把同一故障的四联绑成整体。
**配置**
- 联名仍取自 `emergency-repair-server/config/business-config.yml` 的 `app.engineering-print.unit-names`。
- 当前配置:`1: 上报人`,`2/3/4` 为空,因此第 2/3/4 联只显示“第2联/第3联/第4联”。
**验证结果**
- 后端 `mvn -B -DskipTests package` 通过(JDK `C:\Program Files\Java\jdk1.8.0_172`,Maven `D:\solidDir\apache-maven-3.6.1`)。
- 新后端 PID `248156`,监听 `http://127.0.0.1:8091`;前端 PID `232852`,监听 `http://localhost:8082`。
- 使用前 17 条故障调用 `POST /api/faults/engineering-print`,Header 为 `Authorization: Bearer demo-admin-token`,生成 `.codex-run/engineering-order-labels-verified.docx` 与 `.pdf`。
- XML 检查:1 张明细表、136 行,即 17 条故障 × 4 联 × 2 行。
- `第1联    上报人`、`第2联`、`第3联`、`第4联` 各出现 17 次;`{unitNo}`、`{unitName}`、`{unitDisplay}` 残留均为 0。
- PDF 共 29 页,已渲染到 `.codex-run/engineering-order-labels-pages/`;第 1、4 页可见最右侧竖排联号,第 1 页有明细,不再只有顶部和签字表。
**运行状态(2026-10-10 14:21)**
- 前端 `http://localhost:8082`,PID `232852`。
- 后端 `http://127.0.0.1:8091`,PID `248156`,启动时间 `2026-10-10 14:20:00`。
- 后端日志:`.codex-run/backend-20261010-unit-labels.out.log`、`.codex-run/backend-20261010-unit-labels.err.log`。
- 验证文件:`.codex-run/engineering-order-labels-verified.docx`、`.codex-run/engineering-order-labels-verified.pdf`。
**注意事项**
- 不要重新把同一故障的四联用 `keepNext` 绑成整块,否则长记录会把整组推到下一页。
- 若用户再看旧文件会误以为未修复,需重新在页面触发一次打印;旧 `.docx` 不会被后台回写。
- 不要提交 `.codex-run`、Office 锁文件或 `emergency-repair-web/public/新建 文本文档.txt`。
## 37. 修正快照(2026-10-10 星期六,原打印工程单按逻辑页输出四联)
**用户澄清**
- 原“打印工程单”的重复单位是逻辑页,不是单条记录:先按记录动态分页,再把每个逻辑页的数据分别输出为第 1、2、3、4 联。
- “打印工程单2”已经稳定,本轮不改它的 `renderLegacyGroupedUnits()` 和最后一列纵向合并逻辑。
**代码修改**
- `EngineeringOrderPrintService.renderPagedUnits()` 保留页级四联输出:每个逻辑页生成 1-4 联,每联单独分页。
- `paginateRecords()` 的可用高度系数由 `0.75` 调整为 `0.50`,防止长文本明细把同一联表挤到续页。
- 明细行继续保留 `cantSplit + keepLines`,一条记录不能跨页;模板页眉和签字页脚继续通过 Word header/footer 在每页重复。
- 主要文件:`emergency-repair-server/src/main/java/com/emergencyrepair/business/service/EngineeringOrderPrintService.java`。
**验证结果**
- 后端 `mvn -q -DskipTests package` 通过。
- 使用 `.codex-run/engineering-print-all-request.json` 的 22 条故障调用 `POST /api/faults/engineering-print`,生成 `.codex-run/engineering-order-page-repeat-v3.docx`。
- XML 结构:28 张联表、28 个联号标记;Word 实际 28 页,等于 7 个逻辑页乘 4 联,没有联表续页。
- Word 检查确认每页都有页眉和签字页脚;第 1 联到第 4 联按逻辑页连续输出。
**运行状态(2026-10-10 16:48)**
- 前端 `http://localhost:8082`,PID `232852`,端口已监听。
- 后端 `http://127.0.0.1:8091`,PID `261356`,端口已监听;由当前 Codex 终端前台托管。
- 登录账号 `admin / admin123`。
## 38. 修正快照(2026-10-10 星期六,工程单打印页面去掉表格内部滚动条)
**用户反馈**
- 调整布局去掉最右侧工作区滚动条后,表格内部又出现了滚动条;用户不希望表格本身显示滚动条。
**本轮修正**
- `EngineeringPrint.vue` 保持页面纵向 flex 布局,工作区不再产生外滚动条。
- 对 Element UI 的 `.el-table__body-wrapper` 和 `.el-table__fixed-body-wrapper` 同时隐藏滚动条,滚动能力保留,避免 20 条数据时底部内容无法访问。
- 主要文件:`emergency-repair-web/src/views/fault/EngineeringPrint.vue`。
**验证结果**
- CDP 桌面视口 `1440x900`:工作区 `clientHeight=792`、`scrollHeight=792`,外滚动条不存在。
- `.el-table__body-wrapper` 仍可滚动,计算样式 `scrollbar-width: none`,滚动条不可见。
- 页面截图:`.codex-run/engineering-print-layout-current.png`。
**当前运行状态(2026-10-10)**
- 前端 `http://localhost:8082`,PID `232852`;后端 `http://127.0.0.1:8091`,PID `261356`。