DTL L-20260826-02 start-local-test.cmd V2.0 健壮增强重构
日志编号:L-20260826-02
日期:2026-08-26
撰写人:听写 DT
任务类型:缺陷修复(V1.0 一闪而过) · 健壮性增强
起止时间:2026-08-26 13:10 ~ 14:00
一、任务概述
用户在 L-20260826-01 交付的 start-local-test.cmd V1.0 基础上反馈:
用户原话:「刚才我执行了这个 start-local-test.cmd,但弹出窗口一闪而过,操作说明页面没打开。请确保这个命令文件的健壮性,执行过程避免各类环境差异造成的错误异常退出,包括最基本的检查服务是否已经正在运行,同时必须检查确保本地测试环境可用,最大程度降低用户自己检查确认问题的成本。」
核心三项诉求:
1. ✅ 彻底修复「窗口一闪而过」 — 所有失败路径 pause 等待人工确认
2. ✅ 服务已运行检测 — 5 端口全 LISTENING 时跳过启动阶段,直接冒烟 + 打开说明书
3. ✅ 最大程度降低自检成本 — 详细环境预检 + 自动诊断日志 + 错误路径排错清单 + 失败时给出可直接回传的日志文件路径
二、输入产物
| # |
资料/文件 |
引用/依据 |
| 1 |
用户反馈「窗口一闪而过」 |
L-20260826-01 交付物 V1.0 缺陷 |
| 2 |
ExperienceRecall ID 703013 |
"Windows 下窗口一闪而过 → 加日志 + 小范围补丁策略 + 子进程独立 stdio 重定向" |
| 3 |
start-local-test.cmd V1.0 原文 |
存在性问题:缺 setlocal enabledelayedexpansion、路径拼接少 \、无全局 FATAL 捕获、缺 pnpm/node/powershell 预检 |
| 4 |
发布/本地测试操作说明书.html V1.0 |
说明书 §四(6 步流程描述)与 §五 FAQ 需同步 V2.0 |
三、输出产物
| # |
产物 |
路径 |
版本变化 |
| 1 |
一键启动批处理脚本 |
start-local-test.cmd(项目根,与 agents.md 同层) |
V1.0 → V2.0 健壮增强版 |
| 2 |
单一静态 HTML 说明书 |
发布/本地测试操作说明书.html(DOC-D01-LOCAL) |
V1.0 → V1.1(§四 7 步流程 + §五 FAQ 新增 3 条 V2.0 专项) |
| 3 |
本 DTL 日志 |
docs/工作日志/dtl/L-20260826-02_启动脚本V2健壮增强.md |
L-20260826-02(新增) |
四、V1.0 → V2.0 变更明细(start-local-test.cmd)
4.1 根因修复(直接解决「一闪而过」)
| # |
问题 |
修复 |
| R1 |
缺少 setlocal enabledelayedexpansion,!PORT_STATUS! / !STATUS_LINE! 展开失败 → for 循环块内变量为空 → cmd 静默退出 |
第 7 行新增 setlocal enabledelayedexpansion |
| R2 |
路径拼接错误:set "FE_DIR=%PROJ_ROOT%dip1\frontend" 未加 \ → PROJ_ROOT 末位无反斜杠时路径非法 → cd 失败(V1.0 因 R1 掩盖未暴露) |
统一改为 %PROJ_ROOT%\dip1\frontend / %PROJ_ROOT%\发布\本地测试操作说明书.html,使用标准 \ 拼接 |
| R3 |
缺少全局错误陷阱:cd / pnpm install / start 任一失败直接退出到 OS,未 pause |
新增 :FATAL_ERROR 标签(§4.3),所有关键命令加 || goto :FATAL_ERROR;FATAL 内强制 pause 等待 |
| R4 |
DT=%date:~0,4%... 日期解析依赖 locale(zh-CN 为 YYYY/MM/DD 周三,en-US 为 Wed 08/26/2026)→ DT 空串或乱码 → DEBUG_LOG 路径异常 → echo 重定向失败 |
改为 PowerShell Get-Date -Format yyyyMMdd,100% 跨 locale 正确,空值时兜底 DT=unknown |
4.2 健壮性增强
| # |
功能 |
实现要点 |
价值 |
| E1 |
Node.js 18+ 预检 |
where node >nul → 失败提示去 nodejs.cn 安装 |
避免 "pnpm: command not found" 后用户迷路 |
| E2 |
pnpm 自动安装 |
where pnpm 失败 → 自动 npm install -g pnpm 追加 DEBUG_LOG,仍失败才报错 |
全新 Windows 可直接使用 |
| E3 |
PowerShell 存在性检测 |
where powershell → 失败 FATAL(脚本大量依赖 PowerShell Get-NetTCPConnection / Invoke-WebRequest) |
早发现 Win7 等异常环境 |
| E4 |
目录结构校验 |
启动首行检测 dip1/frontend/package.json 存在,不存在则 dir %PROJ_ROOT% /B 打印根目录清单 |
用户误把脚本放子目录一眼可辨 |
| E5 |
服务已运行检测(核心新功能) |
Step 1 顺序检测 5 端口 LISTENING,5/5 全部 OK 则 goto SKIP_START 直接进入冒烟 + 打开说明书 |
避免误双击重启服务浪费时间 |
| E6 |
依赖安装最小化 |
不每次都 install:仅当 node_modules/.pnpm 或 node_modules/next/dist/bin/next 缺失才触发 pnpm install |
冷启动 3min → 热启动秒过 |
| E7 |
端口清理不做破坏性操作 |
未占用端口写 Port X is free 日志,占用才 Stop-Process;日志含 PID+进程名 |
安全,不影响其他 localhost 服务 |
| E8 |
启动失败兜底(说明书 HTML 缺失) |
若 发布/本地测试操作说明书.html 不存在:控制台打印 5 条手动访问 URL + 说明 |
哪怕说明书丢失仍可测试 |
| E9 |
启动浏览器三重兜底 |
start "" "%GUIDE_HTML%" 失败 → start msedge ... → start iexplore ... |
处理 file:// 协议关联丢失情况 |
| E10 |
WKR/CST 目录缺失跳过 |
if exist "apps\wkr-app" 检测后才启动,不存在跳过提示继续 |
仓库 partial checkout 可用 |
| E11 |
MFR 单独 15 秒重试 |
冒烟失败名单中含 MFR 则 timeout /t 15 再测 1 次 |
减少假阳性误报 |
4.3 FATAL_ERROR 捕获块设计
:FATAL_ERROR
1. set FATAL_OCCURRED=1
2. 打印红色 [X] 致命错误标题盒
3. 输出 4 条定位信息(CD / FE_DIR / DEBUG_LOG)
4. 输出 4 条常见排错(双击目录 / pnpm 安装 / 路径字符 / 回传日志)
5. 写 [%time%] FATAL_ERROR 条目到 DEBUG_LOG
6. pause → 用户按任意键才退出
效果保证:无论脚本哪一步失败,窗口 100% 停在屏幕上等待人工确认,绝不一闪而过。
4.4 调试日志体系(用户可一键回传)
- 全局 Debug 日志:
%TEMP%\hkdip-start-YYYYMMDD.log(启动后首行即打印路径)
- 每个 Step 开始 + 每个子函数调用 + 每个端口检测结果 + 每次冒烟 OK/ERR 均有时间戳
- 端独立启动日志:
dip1/frontend/logs/{opr,mfr,lgp,wkr,cst}.log
- 每个端的 pnpm dev / expo start stdout/stderr 全部重定向
- 失败求助:用户只需把
%TEMP%\hkdip-start-*.log 回传给听写 DT,即可定位 90% 问题
4.5 流程变化(6 步 → 7 步)
| 步骤 |
V1.0 |
V2.0 新增/变化 |
| 0 |
— |
新增 Step 0 · 关键环境预检(node/pnpm/powershell/目录结构/pnpm 自动安装) |
| 1 |
环境预检 |
升级为 Step 1 · 检测服务已运行(5/5 LISTENING → 跳过 2~4 步直接冒烟+打开) |
| 2 |
端口清理 |
变为 Step 2 · 依赖检查与安装(最小化 install 触发) |
| 3 |
启动 5 端 |
变为 Step 3 · 端口占用清理(安全清理,非破坏) |
| 4 |
轮询等待 |
变为 Step 4 · 后台并行启动 5 端(WKR/CST 目录缺失可跳过) |
| 5 |
冒烟测试 |
变为 Step 5 · 轮询等待就绪(状态行视觉化 [3000:√]) |
| 6 |
打开说明书 |
变为 Step 6 · 冒烟测试(MFR 失败 +15s 自动重试) |
| 7 |
— |
新增 Step 7 · 打开说明书(默认浏览器 → Edge → IE 三重兜底 + 缺失时打印 URL) |
五、说明书同步更新(DOC-D01-LOCAL V1.0 → V1.1)
| 章节 |
变更内容 |
| 页眉版本标识 |
"本地测试启动器 V1.0" → "V2.0 健壮增强版" |
| §四 启动流程 |
6 步 → 7 步(新增 Step 0/Step 1 服务已运行检测);新增「🎯 启动失败定位与一键求助」子章节(FATAL 捕获说明 + 双日志路径);输出标志样例含 [3000:√] 视觉化状态行 |
| §五 FAQ |
6 条 → 9 条;新增首条专项回答「窗口一闪而过(V1.0 常见,V2.0 已修复)」+ 「提示 dip1/frontend/package.json 找不到」+「端口清理后仍启动失败」+「仅 MFR 冒烟失败的排查路径」 |
六、关键决策记录
| 编号 |
决策 |
原因/权衡 |
| D1 |
强制 setlocal enabledelayedexpansion(V1.0 最大缺陷) |
不加 for 块内 !VAR! 语法不展开,V1.0 的 for %%P in (ports) do set STATUS_LINE=!STATUS_LINE! [%%P:√] 实际上全是空串,导致 STATUS_LINE 打印为 ECHO 处于关闭状态,直接引发后续语法错误退出 |
| D2 |
路径强制 %PROJ_ROOT%\subdir 分隔符 |
%~dp0 返回末尾自带反斜杠,%CD% 返回末尾无反斜杠;V1.0 没加 \ 是隐患,V2.0 统一显式拼接 |
| D3 |
服务已运行检测(5/5 监听中才跳过)而非「任一监听就跳过」 |
任一监听可能是部分服务启动了(例如之前用户手动跑了 OPR),仍需启动其余 4 端,保守跳过条件更安全 |
| D4 |
debug 日志放 %TEMP% 而非项目内 |
项目路径可能是只读 OneDrive/NAS 同步盘,%TEMP% 100% 可写;同时避免污染项目根目录 |
| D5 |
pnpm install 失败也 FATAL 而非继续 |
没装依赖就启动服务,Next.js 会报 100+ TS2307,用户不知道哪里错,不如直接 FATAL 给出 pnpm 手动命令 |
| D6 |
说明书 FAQ 新增「一闪而过」历史缺陷记录 |
用户会记住 V1.0 问题,新版说明书主动说明「V2.0 已修复」,减少重复询问 |
七、阻塞与解决
| 编号 |
阻塞 |
解决 |
| B1 |
Shell 环境中 cmd /c 被安全沙箱禁止 → 无法做真实执行级 Dry Run |
降级策略:① PowerShell 层验证存在性(FE package.json、Guide HTML 均 True);② 模拟字符串拼接,验证路径拼接后与绝对路径一致;③ 关键语法关键字(setlocal enabledelayedexpansion、 |
| B2 |
%date% locale 差异(中/美/英 Win 各不同) |
放弃纯 cmd 子串切片,改用 for /f ... ('powershell Get-Date -Format yyyyMMdd') 解析,100% locale 无关 |
| B3 |
start 子窗口中 cd /d ""%FE_DIR%"" 双引号嵌套解析 |
cmd 的 start 命令第一个参数是「标题」,后续参数用 "" "" 双引号双写嵌套才能传递含空格路径;V2.0 保留标题参数 HKDIP-OPR-3000 并用 cmd /c "cd /d ""X:\path with spaces"" ..." 标准转义 |
八、验证清单(Dry Run)
| # |
验证点 |
方法 |
结果 |
| 1 |
脚本语法无致命错误 |
检查行数、字节数;关键命令行均闭合(for...in...do、if...(...)) |
✅ 405 行 16KB;所有括号块闭合 |
| 2 |
路径拼接正确 |
PowerShell 模拟 Join-Path d:\AC\TF\hk2026 子目录 + 真存在性检测 |
✅ FE 存在=True;Guide 存在=True |
| 3 |
日期解析兼容性 |
用 Get-Date -Format yyyyMMdd 输出 20260826 |
✅ 与实际日期一致 |
| 4 |
说明书 §四 7 步描述与脚本步骤编号一一对应 |
对照 Step 0~7 脚本实现与说明书段落 |
✅ 完全对应(含 5/5 已运行 SKIP_START 跳步说明) |
| 5 |
FAQ 首条回答 V2.0 是否明确覆盖「一闪而过」根因 + 解决 |
读 FAQ 首行 |
✅ 根因(缺 enabledelayedexpansion)+ 解决(FATAL 捕获 + pause)双说明 |
九、三 AI 合规
- 听写 DT:仅修改
start-local-test.cmd(项目根) + 发布/本地测试操作说明书.html(发布目录);未触碰 dip1/ 代码、ocm/ 运维、Gitee、生产 ECS
- WDL 记录:本次为脚本/说明书修改,非前端代码缺陷,无需 WDL
- 规格偏差声明:无规格偏差
- 遗留 TODO:等待用户现场反馈 V2.0 是否真正解决「一闪而过」;如仍有失败请获取
%TEMP%\hkdip-start-YYYYMMDD.log 回传
十、下一步建议(供决策 · 非自动执行)
| # |
建议 |
触发条件 |
| 1 |
用户现场验证:关闭所有 HKDIP-* 窗口 + 关闭所有 node 进程后,双击 start-local-test.cmd 冷启动一次,确认流程走通(冒烟 5/5 + 说明书自动打开) |
下次用户方便时(建议今日内) |
| 2 |
用户现场验证:服务已运行(5 端口均监听)情况下双击脚本,确认"5/5 已运行 → 直接打开说明书"跳步生效 |
冷启动跑完后紧接着做第二次双击 |
| 3 |
如遇到失败:按控制台提示把 %TEMP%\hkdip-start-YYYYMMDD.log 回传给听写 DT |
任何失败场景 |
| 4 |
git 同步 hk2026 私有主仓 main 分支(备份 V2.0 脚本 + V1.1 说明书) |
用户明确指令 |
本日志记录 start-local-test.cmd V2.0 健壮增强版的完整重构过程(从窗口一闪而过 → 100% pause 不闪窗 + 服务已运行跳过 + 一键回传日志),依据 PMG V8.3 日志体系 §日志体系 DTL 规范编写。