chore: v1 整理 — 清理历史文件、DDL 合并、文档归档

- 清理 1155 个已删除的历史文件(废弃 prompt_logs、tmp、旧 ops 脚本)
- export/ 数据文件从 git 移除(已在 .gitignore)
- demo-miniprogram 从 tmp/ 移入 apps/,添加 CLAUDE.md 注解
- DDL 合并:完整 schema 定义填充到 db/*/schemas/(从 docs/database/ddl/ 复制)
- 39 个 v1 迁移脚本归档到 db/_archived/migrations_v1_merged/
- 4 个迁移变更类 BD_Manual 文档归档到 docs/database/_archived/
- .gitignore 补充 .vite/ 和 apps/*.zip
- settings.json 添加 effortLevel 默认配置
- scripts/ops/ 新增运维脚本入库

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neo
2026-04-06 00:39:27 +08:00
parent 6f8f12314f
commit 779b2f6d52
1340 changed files with 9124 additions and 132087 deletions

View File

@@ -38,27 +38,29 @@ try {
$backendDir = Join-Path $ProjectRoot "apps\backend"
$frontendDir = Join-Path $ProjectRoot "apps\admin-web"
$tenantDir = Join-Path $ProjectRoot "apps\tenant-admin"
if (-not (Test-Path $backendDir)) { throw "后端目录不存在: $backendDir" }
if (-not (Test-Path $frontendDir)) { throw "前端目录不存在: $frontendDir" }
if (-not (Test-Path $tenantDir)) { throw "租户管理后台目录不存在: $tenantDir" }
# ── 端口冲突检测:确保 8000/5173 未被旧进程占用 ──
foreach ($port in @(8000, 5173)) {
# ── 端口冲突检测:确保 8000/5173/5174 未被旧进程占用 ──
foreach ($port in @(8000, 5173, 5174)) {
$listeners = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
if ($listeners) {
foreach ($l in $listeners) {
$pid = $l.OwningProcess
$proc = Get-Process -Id $pid -ErrorAction SilentlyContinue
$procId = $l.OwningProcess
$proc = Get-Process -Id $procId -ErrorAction SilentlyContinue
$procPath = if ($proc) { $proc.Path } else { "未知" }
Write-Host "端口 $port 被占用: PID=$pid ($procPath)" -ForegroundColor Yellow
Write-Host "端口 $port 被占用: PID=$procId ($procPath)" -ForegroundColor Yellow
# 尝试多种方式终止Stop-Process → taskkill /T /F
Write-Host " 正在终止旧进程..." -ForegroundColor Yellow
Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue
Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
# 如果 Stop-Process 不够,用 taskkill 连子进程一起杀
# taskkill 非零退出码不应终止脚本
$ErrorActionPreference = "Continue"
taskkill /PID $pid /T /F 2>$null | Out-Null
taskkill /PID $procId /T /F 2>$null | Out-Null
$ErrorActionPreference = "Stop"
}
@@ -103,6 +105,7 @@ try {
# 前端日志文件(每次用唯一文件名,避免上次进程锁定旧文件)
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$frontendLog = Join-Path $env:TEMP "neozqyy_fe_${ts}.log"
$tenantLog = Join-Path $env:TEMP "neozqyy_ta_${ts}.log"
# 选择 PowerShell 可执行文件:优先 pwsh (7+),回退 powershell (5.1)
$psExe = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
@@ -110,6 +113,7 @@ try {
# ── 生成临时启动脚本(带时间戳,避免旧脚本残留) ──
$beTmp = Join-Path $env:TEMP "neozqyy_start_be_${ts}.ps1"
$feTmp = Join-Path $env:TEMP "neozqyy_start_fe_${ts}.ps1"
$taTmp = Join-Path $env:TEMP "neozqyy_start_ta_${ts}.ps1"
$q = [char]39
# CHANGE 2026-03-07 | 显式使用 .venv 的 python避免 uv run 解析到 miniconda
@@ -126,77 +130,258 @@ try {
# PowerShell 5.1 + 旧版 conhost 不解析 ANSI 转义序列uvicorn 彩色日志
# 显示为 [32m、[0m 等乱码。设置 NO_COLOR=1 禁用颜色输出。
# pwsh 7+ 和 Windows Terminal 原生支持 VT不受影响。
@(
# CHANGE 2026-04-01 | 修复三个显示问题:
# 1. Write-Host 用单引号包裹导致 $env:NEOZQYY_ROOT 不展开 → 改用双引号
# 2. NO_COLOR 对 uvicorn 不生效 → 加 --no-color 参数
# 3. PS 5.1 传统控制台 UTF-8 箭头乱码 → 所有临时脚本开头 chcp 65001
# 并统一设 NO_COLOR=1 禁用 ANSI 转义码
$beLines = @(
"`$env:NEOZQYY_ROOT = ${q}${ProjectRoot}${q}"
""
"# pwsh 7+ 原生支持 ANSIPS 5.1 需要 Windows Terminal 才行"
"# 简单判断PSVersion.Major < 7 且不在 Windows Terminal 中 → 禁用颜色"
"# PS 5.1 + 传统控制台:启用 UTF-8 代码页 + 禁用 ANSI 颜色"
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" Write-Host ${q}[提示] PS 5.1 + 传统控制台,已禁用 ANSI 颜色${q} -ForegroundColor Yellow"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
" Write-Host ${q}[提示] PS 5.1 + 传统控制台,已启用 UTF-8 并禁用 ANSI 颜色${q} -ForegroundColor Yellow"
"}"
""
"Set-Location -LiteralPath ${q}${backendDir}${q}"
"Write-Host ${q}=== 后端 FastAPI ===${q} -ForegroundColor Green"
"Write-Host ${q}NEOZQYY_ROOT=`$env:NEOZQYY_ROOT${q}"
"& ${q}${venvPython}${q} -m uvicorn app.main:app --reload --port 8000"
"Write-Host `"NEOZQYY_ROOT=`$env:NEOZQYY_ROOT`""
"& ${q}${venvPython}${q} -m uvicorn app.main:app --reload --port 8000 --no-use-colors"
"Write-Host ${q}后端已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
) | Set-Content -Path $beTmp -Encoding UTF8
)
$beLines | Set-Content -Path $beTmp -Encoding UTF8
@(
$feLines = @(
"# PS 5.1 + 传统控制台:启用 UTF-8 + 禁用 ANSI"
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
"}"
""
"Set-Location -LiteralPath ${q}${frontendDir}${q}"
"Write-Host ${q}=== 前端 Vite ===${q} -ForegroundColor Green"
"pnpm dev 2>&1 | Tee-Object -FilePath ${q}${frontendLog}${q}"
"Write-Host ${q}=== 前端 Vite (admin-web) ===${q} -ForegroundColor Green"
"cmd /c ${q}pnpm dev 2>&1${q} | Tee-Object -FilePath ${q}${frontendLog}${q}"
"Write-Host ${q}前端已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
) | Set-Content -Path $feTmp -Encoding UTF8
)
$feLines | Set-Content -Path $feTmp -Encoding UTF8
# ── 启动后端 ──
Write-Host "[1/2] 启动后端 FastAPI (http://localhost:8000) ..." -ForegroundColor Yellow
Start-Process $psExe -ArgumentList "-NoExit", "-ExecutionPolicy", "Bypass", "-File", $beTmp
$taLines = @(
"# PS 5.1 + 传统控制台:启用 UTF-8 + 禁用 ANSI"
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
"}"
""
"Set-Location -LiteralPath ${q}${tenantDir}${q}"
"Write-Host ${q}=== 租户管理后台 Vite (tenant-admin) ===${q} -ForegroundColor Green"
"cmd /c ${q}pnpm dev 2>&1${q} | Tee-Object -FilePath ${q}${tenantLog}${q}"
"Write-Host ${q}租户管理后台已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
)
$taLines | Set-Content -Path $taTmp -Encoding UTF8
Start-Sleep -Seconds 2
# ── 启动服务函数 ──
function Start-AllServices {
param([ref]$BeProc, [ref]$FeProc, [ref]$TaProc)
# ── 启动──
Write-Host "[2/2] 启动前端 Vite (http://localhost:5173) ..." -ForegroundColor Yellow
Start-Process $psExe -ArgumentList "-NoExit", "-ExecutionPolicy", "Bypass", "-File", $feTmp
Write-Host "[1/3] 启动FastAPI (http://localhost:8000) ..." -ForegroundColor Yellow
$BeProc.Value = Start-Process $psExe -ArgumentList "-NoExit", "-ExecutionPolicy", "Bypass", "-File", $beTmp -PassThru
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " 两个服务已在新窗口中启动" -ForegroundColor Green
Write-Host " 后端: http://localhost:8000" -ForegroundColor Green
Write-Host " 前端: http://localhost:5173" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Start-Sleep -Seconds 2
# ── 检测前端就绪(匹配 Vite 输出中的 localhost:5173忽略 ANSI 转义码) ──
Write-Host "等待前端 Vite 就绪..." -ForegroundColor Yellow
$timeout = 45
$elapsed = 0
$ready = $false
Write-Host "[2/3] 启动前端 Vite admin-web (http://localhost:5173) ..." -ForegroundColor Yellow
$FeProc.Value = Start-Process $psExe -ArgumentList "-NoExit", "-ExecutionPolicy", "Bypass", "-File", $feTmp -PassThru
while ($elapsed -lt $timeout) {
Start-Sleep -Seconds 1
$elapsed++
if (Test-Path $frontendLog) {
$raw = Get-Content $frontendLog -Raw -ErrorAction SilentlyContinue
if ($raw) {
# 去掉 ANSI 转义序列后再匹配
$clean = $raw -replace '\x1b\[[0-9;]*m', ''
if ($clean -match "localhost:5173" -or $clean -match "ready in") {
$ready = $true
break
Write-Host "[3/3] 启动租户管理后台 Vite tenant-admin (http://localhost:5174) ..." -ForegroundColor Yellow
$TaProc.Value = Start-Process $psExe -ArgumentList "-NoExit", "-ExecutionPolicy", "Bypass", "-File", $taTmp -PassThru
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " 三个服务已在新窗口中启动" -ForegroundColor Green
Write-Host " 后端: http://localhost:8000" -ForegroundColor Green
Write-Host " 管理后台: http://localhost:5173" -ForegroundColor Green
Write-Host " 租户管理后台: http://localhost:5174" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
}
# ── 终止服务函数 ──
function Stop-AllServices {
param($BeProc, $FeProc, $TaProc)
Write-Host ""
Write-Host "正在终止所有服务..." -ForegroundColor Yellow
$ErrorActionPreference = "Continue"
foreach ($info in @(
@{ Name = "后端 FastAPI"; Proc = $BeProc; Port = 8000 },
@{ Name = "前端 admin-web"; Proc = $FeProc; Port = 5173 },
@{ Name = "租户 tenant-admin"; Proc = $TaProc; Port = 5174 }
)) {
$p = $info.Proc
if ($p -and -not $p.HasExited) {
Write-Host " 终止 $($info.Name) (PID=$($p.Id))..." -ForegroundColor Yellow
taskkill /PID $p.Id /T /F 2>$null | Out-Null
}
# 同时按端口清理(防止子进程残留)
$listeners = Get-NetTCPConnection -LocalPort $info.Port -State Listen -ErrorAction SilentlyContinue
foreach ($l in $listeners) {
taskkill /PID $l.OwningProcess /T /F 2>$null | Out-Null
}
}
$ErrorActionPreference = "Stop"
Start-Sleep -Seconds 1
Write-Host " 所有服务已终止" -ForegroundColor Green
}
# ── 等待前端就绪 + 打开浏览器 ──
function Wait-AndOpenBrowser {
Write-Host "等待前端 Vite 就绪..." -ForegroundColor Yellow
$timeout = 45
$elapsed = 0
$feReady = $false
$taReady = $false
while ($elapsed -lt $timeout -and (-not $feReady -or -not $taReady)) {
Start-Sleep -Seconds 1
$elapsed++
if (-not $feReady -and (Test-Path $frontendLog)) {
$raw = Get-Content $frontendLog -Raw -ErrorAction SilentlyContinue
if ($raw) {
$clean = $raw -replace '\x1b\[[0-9;]*m', ''
if ($clean -match "localhost:5173" -or $clean -match "ready in") {
$feReady = $true
Write-Host " admin-web 已就绪(${elapsed}s" -ForegroundColor Green
}
}
}
if (-not $taReady -and (Test-Path $tenantLog)) {
$raw = Get-Content $tenantLog -Raw -ErrorAction SilentlyContinue
if ($raw) {
$clean = $raw -replace '\x1b\[[0-9;]*m', ''
if ($clean -match "localhost:5174" -or $clean -match "ready in") {
$taReady = $true
Write-Host " tenant-admin 已就绪(${elapsed}s" -ForegroundColor Green
}
}
}
}
if ($feReady) { Start-Process "http://localhost:5173" }
else { Write-Host "admin-web 等待超时,请手动打开 http://localhost:5173" -ForegroundColor Red }
if ($taReady) { Start-Process "http://localhost:5174" }
else { Write-Host "tenant-admin 等待超时,请手动打开 http://localhost:5174" -ForegroundColor Red }
}
if ($ready) {
Write-Host "前端已就绪(${elapsed}s打开浏览器..." -ForegroundColor Green
Start-Process "http://localhost:5173"
} else {
Write-Host "等待超时(${timeout}s请手动打开 http://localhost:5173" -ForegroundColor Red
# ── 倒计时函数 ──
function Show-Countdown {
param([int]$Seconds)
for ($i = $Seconds; $i -ge 1; $i--) {
Write-Host "`r 重启倒计时: ${i}s ... " -NoNewline -ForegroundColor Cyan
Start-Sleep -Seconds 1
}
Write-Host "`r 重启倒计时: 0s — 开始启动! " -ForegroundColor Green
Write-Host ""
}
# ── 首次启动 ──
$beProc = $null; $feProc = $null; $taProc = $null
Start-AllServices -BeProc ([ref]$beProc) -FeProc ([ref]$feProc) -TaProc ([ref]$taProc)
Wait-AndOpenBrowser
# ── 交互菜单循环 ──
$running = $true
while ($running) {
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " 操作菜单" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " [1] 终止所有服务" -ForegroundColor Yellow
Write-Host " [2] 重启所有服务(间隔 5 秒倒计时)" -ForegroundColor Yellow
Write-Host " [3] 退出(终止服务并关闭窗口)" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Cyan
$choice = Read-Host "请输入选项 (1/2/3)"
switch ($choice) {
"1" {
Stop-AllServices -BeProc $beProc -FeProc $feProc -TaProc $taProc
$beProc = $null; $feProc = $null; $taProc = $null
}
"2" {
Stop-AllServices -BeProc $beProc -FeProc $feProc -TaProc $taProc
Show-Countdown -Seconds 5
# 重新生成日志文件名(避免旧文件锁定)
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$frontendLog = Join-Path $env:TEMP "neozqyy_fe_${ts}.log"
$tenantLog = Join-Path $env:TEMP "neozqyy_ta_${ts}.log"
# 重新生成临时启动脚本
$beLines = @(
"`$env:NEOZQYY_ROOT = ${q}${ProjectRoot}${q}"
""
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
" Write-Host ${q}[提示] PS 5.1 + 传统控制台,已启用 UTF-8 并禁用 ANSI 颜色${q} -ForegroundColor Yellow"
"}"
""
"Set-Location -LiteralPath ${q}${backendDir}${q}"
"Write-Host ${q}=== 后端 FastAPI ===${q} -ForegroundColor Green"
"Write-Host `"NEOZQYY_ROOT=`$env:NEOZQYY_ROOT`""
"& ${q}${venvPython}${q} -m uvicorn app.main:app --reload --port 8000 --no-use-colors"
"Write-Host ${q}后端已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
)
$beLines | Set-Content -Path $beTmp -Encoding UTF8
$feLines = @(
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
"}"
""
"Set-Location -LiteralPath ${q}${frontendDir}${q}"
"Write-Host ${q}=== 前端 Vite (admin-web) ===${q} -ForegroundColor Green"
"cmd /c ${q}pnpm dev 2>&1${q} | Tee-Object -FilePath ${q}${frontendLog}${q}"
"Write-Host ${q}前端已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
)
$feLines | Set-Content -Path $feTmp -Encoding UTF8
$taLines = @(
"if (`$PSVersionTable.PSVersion.Major -lt 7 -and -not `$env:WT_SESSION) {"
" chcp 65001 | Out-Null"
" `$env:NO_COLOR = ${q}1${q}"
" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8"
"}"
""
"Set-Location -LiteralPath ${q}${tenantDir}${q}"
"Write-Host ${q}=== 租户管理后台 Vite (tenant-admin) ===${q} -ForegroundColor Green"
"cmd /c ${q}pnpm dev 2>&1${q} | Tee-Object -FilePath ${q}${tenantLog}${q}"
"Write-Host ${q}租户管理后台已退出,按任意键关闭...${q} -ForegroundColor Red"
"`$null = `$Host.UI.RawUI.ReadKey(${q}NoEcho,IncludeKeyDown${q})"
)
$taLines | Set-Content -Path $taTmp -Encoding UTF8
$beProc = $null; $feProc = $null; $taProc = $null
Start-AllServices -BeProc ([ref]$beProc) -FeProc ([ref]$feProc) -TaProc ([ref]$taProc)
Wait-AndOpenBrowser
}
"3" {
Stop-AllServices -BeProc $beProc -FeProc $feProc -TaProc $taProc
$running = $false
}
default {
Write-Host " 无效选项,请输入 1、2 或 3" -ForegroundColor Red
}
}
}
} catch {