<#
|
一键打包部署包(含"去密自检")—— 2026-09-27 新增
|
用法:
|
powershell -NoProfile -ExecutionPolicy Bypass -File pack-deploy.ps1
|
powershell -NoProfile -ExecutionPolicy Bypass -File pack-deploy.ps1 -OutRoot "E:\试验" -SkipFrontend
|
做四件事:
|
1) mvn clean package 构建后端 jar
|
2) 解压 jar 检查内置 application.yml:必须全是占位符(禁止 sk- 密钥 / 明文口令),不合格直接中止
|
3) npm run build 构建前端 dist(可 -SkipFrontend)
|
4) 组装 deploy 目录结构(backend / frontend / db / README-部署说明.txt),输出到 <OutRoot>\traffic-audit-deploy-<yyyyMMdd>
|
#>
|
param(
|
[string]$OutRoot = 'E:\试验',
|
[switch]$SkipFrontend
|
)
|
|
$ErrorActionPreference = 'Stop'
|
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$tplDir = Join-Path $root 'deploy-templates' # 打包模板件(已入库,2026-09-27 起)
|
$jarRel = 'traffic-audit-server\target\traffic-audit-server-1.0.0-SNAPSHOT.jar'
|
$jar = Join-Path $root $jarRel
|
|
Write-Host '[1/5] 构建后端(mvn clean package -DskipTests)...'
|
Push-Location $root
|
cmd /c "mvn.cmd -q clean package -DskipTests -f traffic-audit-server\pom.xml > pack-build.log 2>&1"
|
$rc = $LASTEXITCODE
|
Pop-Location
|
if ($rc -ne 0) { throw '后端构建失败,详见 pack-build.log' }
|
if (-not (Test-Path $jar)) { throw "未找到构建产物:$jar" }
|
Write-Host (" 产物:{0:N1} MB" -f ((Get-Item $jar).Length / 1MB))
|
|
Write-Host '[2/5] 去密自检:解压 jar 检查 BOOT-INF/classes/application.yml ...'
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($jar)
|
try {
|
$entry = $zip.Entries | Where-Object { $_.FullName -eq 'BOOT-INF/classes/application.yml' }
|
if (-not $entry) { throw 'jar 内缺少 BOOT-INF/classes/application.yml' }
|
$sr = New-Object System.IO.StreamReader($entry.Open())
|
$text = $sr.ReadToEnd()
|
$sr.Close()
|
} finally { $zip.Dispose() }
|
|
$bad = @()
|
if ($text -match 'sk-[A-Za-z0-9]{16,}') { $bad += '疑似明文 API key(sk-…)' }
|
foreach ($line in ($text -split "`n")) {
|
if ($line -match '^\s*(password|api-key|secret)\s*:\s*(.+)$') {
|
$v = $matches[2].Trim().Trim('"')
|
if ($v -and -not $v.StartsWith('${')) { $bad += ("$($matches[1]) 不是占位符") }
|
}
|
}
|
if ($bad.Count -gt 0) {
|
throw ('去密自检未通过:' + ($bad -join ';') + '。请检查 traffic-audit-server\src\main\resources\application.yml')
|
}
|
Write-Host ' 通过:jar 内置配置全部为占位符,无明文密钥/口令。'
|
|
Write-Host '[3/5] 构建前端(npm run build,可 -SkipFrontend 跳过)...'
|
if (-not $SkipFrontend) {
|
Push-Location (Join-Path $root 'traffic-audit-web')
|
cmd /c "npm.cmd run build > ..\pack-front.log 2>&1"
|
$rc2 = $LASTEXITCODE
|
Pop-Location
|
if ($rc2 -ne 0) { throw '前端构建失败,详见 pack-front.log' }
|
Write-Host ' 前端 dist 已重建'
|
}
|
|
Write-Host '[4/5] 组装部署目录...'
|
$stamp = Get-Date -Format 'yyyyMMdd'
|
$dest = Join-Path $OutRoot ("traffic-audit-deploy-" + $stamp)
|
$n = 2
|
while (Test-Path $dest) { $dest = Join-Path $OutRoot ("traffic-audit-deploy-" + $stamp + "-" + $n); $n++ }
|
New-Item -ItemType Directory -Force -Path (Join-Path $dest 'backend'), (Join-Path $dest 'frontend'), (Join-Path $dest 'db') | Out-Null
|
|
Copy-Item $jar (Join-Path $dest 'backend') -Force
|
Copy-Item (Join-Path $tplDir 'backend\application.yml') (Join-Path $dest 'backend') -Force
|
Copy-Item (Join-Path $tplDir 'backend\start-backend.cmd') (Join-Path $dest 'backend') -Force
|
Copy-Item (Join-Path $tplDir 'backend\start-backend.sh') (Join-Path $dest 'backend') -Force
|
Copy-Item (Join-Path $root 'traffic-audit-web\dist') (Join-Path $dest 'frontend') -Recurse -Force
|
Copy-Item (Join-Path $tplDir 'frontend\nginx.conf.example') (Join-Path $dest 'frontend') -Force
|
Copy-Item (Join-Path $tplDir 'db\*.sql') (Join-Path $dest 'db') -Force
|
|
# docs:运行时模板 + 用户文档;排除开发过程文档与缓存/备份(减小体积、避免把内部清单带出去)
|
$docsDest = Join-Path $dest 'backend\docs'
|
New-Item -ItemType Directory -Force -Path $docsDest | Out-Null
|
cmd /c "robocopy `"$root\docs`" `"$docsDest`" /E /NFL /NDL /NJH /NJS /NP /XD _cache 工作日结 功能测试报告 问题汇总 /XF 生成_*.xlsx _bak_* >nul"
|
if ($LASTEXITCODE -ge 8) { throw "docs 复制失败(robocopy 返回 $LASTEXITCODE)" }
|
# db 脚本也放一份到 docs(与旧包一致:docs/init.sql 等)
|
Copy-Item (Join-Path $tplDir 'db\init.sql'), (Join-Path $tplDir 'db\sql_city_bus.sql'), (Join-Path $tplDir 'db\sql_city_taxi.sql'), (Join-Path $tplDir 'db\sql_wyc.sql') $docsDest -Force -ErrorAction SilentlyContinue
|
|
# README:用旧包模板并替换日期占位
|
$readme = Get-Content (Join-Path $tplDir 'README-部署说明.txt') -Raw -Encoding UTF8
|
$readme = $readme.Replace('{stamp}', $stamp)
|
Set-Content -LiteralPath (Join-Path $dest 'README-部署说明.txt') -Value $readme -Encoding UTF8
|
|
Write-Host '[5/5] 汇总...'
|
$files = Get-ChildItem $dest -Recurse -File
|
Write-Host (" 输出目录:{0}" -f $dest)
|
Write-Host (" 文件数:{0} 合计:{1:N2} MB" -f $files.Count, (($files | Measure-Object Length -Sum).Sum / 1MB))
|
Write-Host ' 提醒:把包拷到部署机后,只需改 backend\application.yml 里的数据库三处 + 需要时填 deepseek.api-key。'
|