feat(运维): 新增 stop-dev.ps1 一键停止脚本 + 桌面启停入口文档(含编码坑修复记录)
1个文件已修改
2个文件已添加
125 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_一键启停脚本与桌面入口_2026-09-19.md 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-18.md 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
stop-dev.ps1 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Ò»¼üÆôÍ£½Å±¾Óë×ÀÃæÈë¿Ú_2026-09-19.md
New file
@@ -0,0 +1,52 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_一键启停脚本与桌面入口_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
1. **新增 `stop-dev.ps1`(项目根目录)**:与既有 `start-dev.ps1` é…å¥—的一键停止脚本。
   - æŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ã€æ•´æ ‘结束:`cmd.exe /c mvn.cmd ... spring-boot:run`、`cmd.exe /c npm.cmd run serve`,
     ç”¨ `taskkill /T /F` è¿žå¸¦å­è¿›ç¨‹ï¼ˆmaven java â†’ app java;npm node â†’ cmd â†’ vue-cli-service node);
   - å…œåº•再按命令行特征精确匹配孤儿进程:`java.exe` å« `TrafficAuditApplication`、`node.exe` å« `vue-cli-service`;
   - ç»“束后校验 8090/8080 æ˜¯å¦å·²é‡Šæ”¾ï¼›
   - æ˜Žç¡®ä¸ç¢°å…¶å®ƒ node/java è¿›ç¨‹ï¼ˆå¦‚ Codex çš„ `node_repl`)与用户自己开的 cmd çª—口。
2. **桌面一键入口**(工作区外,不入库):
   - `D:\桌面\启动交通审核系统.bat`:调用 `start-dev.ps1`(已在跑则跳过、不在跑则拉起并等待就绪),最后打开 `http://localhost:8080`;
     å¸¦å‚æ•° `nobrowser` å¯åªå¯æœåŠ¡ä¸å¼¹æµè§ˆå™¨ã€‚
   - `D:\桌面\停止交通审核系统.bat`:调用 `stop-dev.ps1`。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å€¼ |
| --- | --- |
| æ—¥æœŸ | 2026-09-19 00:4x–00:5x |
| é¡¹ç›® | `D:\文档\ChatGPT\traffic-audit` |
| æœåŠ¡ | åŽç«¯ 8090(Spring Boot)、前端 8080(Vue)、MySQL 3308 |
| è„šæœ¬ç¼–ç  | `.ps1` = UTF-8 **with BOM**;`.bat` = **GBK(936) + CRLF**,首行 `chcp 936` |
## ä¸‰ã€ç”¨ä¾‹è¡¨
| ç¼–号 | ç”¨ä¾‹ | è¾“å…¥/操作 | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T01 | å·²åœ¨è¿è¡Œæ—¶å¯åŠ¨ï¼ˆæ­£å‘Â·å¹‚ç­‰ï¼‰ | æœåŠ¡åœ¨è·‘æ—¶æ‰§è¡Œ `启动交通审核系统.bat nobrowser` | è·³è¿‡å¯åŠ¨ï¼Œä¸æ–°å»ºé‡å¤è¿›ç¨‹ | æ‰“印「后端已在运行(8090 æœ‰ç›‘听),跳过启动。」「前端已在运行(8080 æœ‰ç›‘听),跳过启动。」,随后校验「后端: OK,已就绪」「前端: OK,已就绪」 | âœ… é€šè¿‡ |
| T02 | æœªè¿è¡Œæ—¶å¯åŠ¨ï¼ˆæ­£å‘ï¼‰ | æœåŠ¡å·²åœæ—¶æ‰§è¡Œ `启动交通审核系统.bat nobrowser` | æ‹‰èµ·å‰åŽç«¯å¹¶ç­‰å¾…就绪 | æ–°å»ºåŽç«¯é“¾ï¼ˆcmd PID 8964 â†’ java â†’ app java)与前端链(cmd PID 26024 â†’ node â†’ cmd â†’ node);`backend.log` å‡ºçް `Tomcat started on port(s): 8090` ä¸Ž `Started TrafficAuditApplication`(00:48:33) | âœ… é€šè¿‡ |
| T03 | åœæ­¢æœåŠ¡ï¼ˆæ­£å‘ï¼‰ | æ‰§è¡Œ `停止交通审核系统.bat` | ä¸¤ä¸ªè¿›ç¨‹æ ‘被结束,端口释放 | åŽç«¯ 5 ä¸ªè¿›ç¨‹ã€å‰ç«¯ 5 ä¸ªè¿›ç¨‹è¢«ç»“束;打印「端口 8090:已释放」「端口 8080:已释放」 | âœ… é€šè¿‡ |
| T04 | å¯åœé—­çŽ¯å¯ç”¨æ€§ï¼ˆæ­£å‘ï¼‰ | åœ â†’ å¯ ä¹‹åŽè®¿é—®é¡µé¢æŽ¥å£ | å‰ç«¯ 8080、后端接口均正常 | å‰ç«¯ `HTTP 200`;后端 `/api/import/batches` `HTTP 200`(能取到最近「市州单表批量导入(物流(物流园区)/8月)」批次) | âœ… é€šè¿‡ |
| T05 | ä¸è¯¯æ€ï¼ˆè´Ÿå‘) | æ‰§è¡Œåœæ­¢è„šæœ¬æœŸé—´è§‚å¯Ÿ Codex è‡ªèº« | Codex å†…æ ¸ `node_repl` ä¸Žå…¶å®ƒ cmd çª—口不受影响 | åœæ­¢è„šæœ¬ä»åœ¨æ­£å¸¸è¿è¡Œï¼ˆæœ¬ä¼šè¯å·¥å…·è°ƒç”¨æœªä¸­æ–­ï¼‰ï¼Œå…¨ç¨‹æœªåŒ¹é… `node_repl` | âœ… é€šè¿‡ |
## å››ã€å‘现的问题与处置
| ç¼–号 | é—®é¢˜ | æ ¹å›  | å¤„ç½® |
| --- | --- | --- | --- |
| P01 | ç¬¬ä¸€ç‰ˆ `.bat` è¿è¡Œæ—¶å¤§é‡æŠ¥ `'xx' is not recognized as an internal or external command`,且命令行被截断(如 `'xecutionPolicy'`) | æ‰¹å¤„理文件必须使用 **CRLF** æ¢è¡Œï¼Œé¦–版写成了 LF,cmd é€è¡Œè§£æžé”™ä½ | æ”¹ä¸ºæŒ‰è¡Œæ•°ç»„ `-join "\`r\`n"` å†™å‡ºï¼Œå¤æµ‹æ­£å¸¸ |
| P02 | é¦–版 `stop-dev.ps1` æŠ¥ `UnexpectedToken`/「字符串缺少终止符」,中文提示被读成乱码 | Windows PowerShell 5.1 è¯»å–**无 BOM** çš„ UTF-8 è„šæœ¬æ—¶æŒ‰ ANSI(936) è§£é‡Šï¼Œå¤šå­—节序列被打断 | æ”¹å†™ä¸º **UTF-8 with BOM**(与既有 `start-dev.ps1` ä¸€è‡´ï¼‰ï¼Œå¤æµ‹æ­£å¸¸ |
| P03 | åœæ­¢è„šæœ¬æŒ‰åç§°æ¨¡ç³Šåœè¿›ç¨‹æœ‰è¯¯æ€é£Žé™© | â€”— | åªæŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ + ç²¾ç¡®å‘½ä»¤è¡Œç‰¹å¾ã€åŒ¹é…ï¼Œ`taskkill /T` ç»“束整树,不按进程名批量杀 |
## äº”、遗留与说明
1. ä¸¤ä¸ªæ¡Œé¢ `.bat` ä½äºŽå·¥ä½œåŒºå¤–(`D:\桌面`),**不入 git**;`stop-dev.ps1` å·²å…¥åº“,与 `start-dev.ps1` é…å¥—。
2. æœåŠ¡ä»ä»¥ `cmd /c ... > log` æ–¹å¼å¸¸é©»ï¼š**关掉启动窗口会带走服务**(本次报错即由此而来)。日常用桌面「启动」入口双击即可恢复。
3. è‹¥ç«¯å£æœªå®Œå…¨é‡Šæ”¾ï¼ˆæžç«¯æƒ…况),停止脚本会提示「仍在监听,请重跑一次」。
## å…­ã€ç»“论
5 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ï¼šå¯åŠ¨è„šæœ¬å¹‚ç­‰è·³è¿‡ã€åœæ­¢è„šæœ¬æŒ‰ PID æ•´æ ‘结束并释放 8090/8080、
启停闭环后页面与接口均正常,且不影响 Codex è‡ªèº«è¿›ç¨‹ã€‚两个编码问题(LF æ¢è¡Œã€ç¼º BOM)已定位并修复复测。
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-18.md
@@ -248,4 +248,18 @@
| å¤©é—¨ç‰©æµæºæ–‡ä»¶ H/J/K ä¸ºç©ºï¼ˆåº“内 0,定稿 16677.7 / 500) | **待用户明日向同事索取源数据**后再导入 |
| è†å·ž/黄石「规划内 / è§„划外」拆分口径与定稿不同(合计一致) | **待用户向同事确认口径** |
> ç”¨æˆ· 2026-09-19 00:5x åé¦ˆï¼šã€Œä»Šå¤©å…ˆæ—©ç‚¹ä¼‘息」,以上三项次日跟进。
> ç”¨æˆ· 2026-09-19 00:5x åé¦ˆï¼šã€Œä»Šå¤©å…ˆæ—©ç‚¹ä¼‘息」,以上三项次日跟进。
### 6.6 æ–°å¢žä¸€é”®å¯åœï¼ˆ2026-09-19 00:5x)
- **背景**:用户反映页面报「数据查询失败/导入记录加载失败」。核查为后端(8090)与前端(8080)进程都已退出
  ï¼ˆMySQL æ­£å¸¸ï¼Œ`SELECT 1` é€šè¿‡ï¼‰ï¼›åŽŸå› æ˜¯æœåŠ¡ä»¥ `cmd /c ... > log` æŒ‚在启动窗口下,**关掉启动窗口就把服务带走了**。
  å·²é‡å¯å¹¶å®žæµ‹ `/api/import/batches`、`/api/data/list` å‡ HTTP 200。
- **新增 `stop-dev.ps1`**(项目根目录):按「启动用的 cmd çˆ¶è¿›ç¨‹ + ç²¾ç¡®å‘½ä»¤è¡Œç‰¹å¾ã€æ•´æ ‘ `taskkill /T /F`,
  å…œåº•匹配孤儿 `java(TrafficAuditApplication)` / `node(vue-cli-service)`,结束后校验 8090/8080 æ˜¯å¦é‡Šæ”¾ï¼›
  ä¸ç¢° `node_repl` ä¸Žç”¨æˆ·è‡ªå·±çš„ cmd çª—口。
- **新增桌面入口**(工作区外,不入库):`D:\桌面\启动交通审核系统.bat`(已在跑则跳过、不在跑则拉起,带 `nobrowser` å‚数可只启服务)、
  `D:\桌面\停止交通审核系统.bat`。
- **编码坑(已修)**:`.bat` å¿…é¡» CRLF + GBK(936)(首版写了 LF,cmd è§£æžæŠ¥é”™ï¼‰ï¼›`.ps1` å¿…é¡» UTF-8 **with BOM**
  ï¼ˆé¦–版无 BOM,PS 5.1 æŒ‰ ANSI è¯»ï¼Œä¸­æ–‡æ‰“断字符串导致 `UnexpectedToken`)。
- **测试**:《功能测试报告_一键启停脚本与桌面入口_2026-09-19.md》,5 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ï¼ˆåœ¨è·‘跳过/未跑拉起/停止释放端口/启停闭环接口 200/不误杀)。
stop-dev.ps1
New file
@@ -0,0 +1,57 @@
<#
  ä¸€é”®åœæ­¢å‰åŽç«¯ï¼ˆä¸Ž start-dev.ps1 é…å¥—)
  ç”¨æ³•:powershell -NoProfile -ExecutionPolicy Bypass -File stop-dev.ps1
  è¯´æ˜Žï¼š
  - åªåœæœ¬é¡¹ç›®ç›¸å…³è¿›ç¨‹ï¼šcmd.exe /c mvn.cmd ... spring-boot:run、cmd.exe /c npm.cmd run serve,
    ä»¥åŠå®ƒä»¬çš„子进程(java / node / vue-cli-service),按进程树 taskkill /T /F;
  - å…œåº•再按命令行特征精确匹配 java(TrafficAuditApplication) ä¸Ž node(vue-cli-service) çš„孤儿进程;
  - ä¸ç¢°å…¶å®ƒ node/java è¿›ç¨‹ï¼ˆä¾‹å¦‚ Codex çš„ node_repl)与用户自己开的 cmd çª—口;
  - ç»“束后检查 8090/8080 æ˜¯å¦å·²é‡Šæ”¾ã€‚
#>
$ErrorActionPreference = 'Continue'
function Test-PortListening($port) {
  try { return [bool](Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction Stop) }
  catch { return $false }
}
function Stop-Tree($label, $procId) {
  Write-Host ("{0}:停止进程树 PID={1}" -f $label, $procId)
  & taskkill.exe /T /F /PID $procId 2>&1 | ForEach-Object { if ($_ -and $_ -notmatch '^SUCCESS') { "    $_" } }
}
# ---------- 1) æŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ã€æ•´æ ‘结束 ----------
$roots = @(
  @{ Label = '后端'; Pattern = 'spring-boot:run' },
  @{ Label = '前端'; Pattern = 'npm.cmd run serve' }
)
$found = $false
$cmdProcs = Get-CimInstance Win32_Process -Filter "Name='cmd.exe'" -ErrorAction SilentlyContinue
foreach ($r in $roots) {
  $hits = @($cmdProcs | Where-Object { $_.CommandLine -and $_.CommandLine -like ('*' + $r.Pattern + '*') })
  if ($hits.Count -eq 0) { Write-Host ("{0}:未发现启动进程(可能已停止)" -f $r.Label); continue }
  $found = $true
  foreach ($h in $hits) { Stop-Tree $r.Label $h.ProcessId }
}
# ---------- 2) å…œåº•:孤儿 java / node ----------
$orphans = @(
  @{ Label = '后端(java å…œåº•)'; Name = 'java.exe'; Pattern = 'TrafficAuditApplication' },
  @{ Label = '前端(node å…œåº•)'; Name = 'node.exe'; Pattern = 'vue-cli-service' },
  @{ Label = '前端(inner cmd å…œåº•)'; Name = 'cmd.exe'; Pattern = 'vue-cli-service serve' }
)
foreach ($o in $orphans) {
  $hits = @(Get-CimInstance Win32_Process -Filter ("Name='" + $o.Name + "'") -ErrorAction SilentlyContinue |
            Where-Object { $_.CommandLine -and $_.CommandLine -like ('*' + $o.Pattern + '*') })
  foreach ($h in $hits) { $found = $true; Stop-Tree $o.Label $h.ProcessId }
}
if (-not $found) { Write-Host '没有发现需要停止的前后端进程。' }
# ---------- 3) æ ¡éªŒç«¯å£ ----------
Start-Sleep -Seconds 4
foreach ($port in 8090, 8080) {
  if (Test-PortListening $port) { Write-Host ("端口 {0}:仍在监听(未完全停止,请重跑一次)" -f $port) }
  else { Write-Host ("端口 {0}:已释放" -f $port) }
}