Initial commit: RHINE LAB · ANALYSIS OS:三维界面与动效实验(本仓库不含个人归档索引数据)
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
<#
|
||||
Rhine Lab UI · 一键启动(桌面那个脚本调的就是它)
|
||||
|
||||
做三件事:
|
||||
1. 确保本地归档后端(「数据库」,127.0.0.1:43117)在跑;没装开机自启就顺手装上。
|
||||
2. 在单独窗口里启动界面(npm run dev),窗口关掉即停止界面。
|
||||
3. 等界面真的响应了,再用默认浏览器打开它。
|
||||
|
||||
顺序很重要:先等后端首轮扫描结束再起界面。因为 back 端启动时会重建快照,
|
||||
而 npm run dev 的 predev 也会重建一次,两边同时写同一批文件会互相踩。
|
||||
|
||||
用法:
|
||||
-Mode start 一键启动(默认)
|
||||
-Mode stop 停掉界面与后端
|
||||
-Mode status 只看状态
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('start', 'stop', 'status')]
|
||||
[string]$Mode = 'start'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$ServiceScript = Join-Path $PSScriptRoot 'archive-service.ps1'
|
||||
$ConfigPath = Join-Path $ProjectRoot 'archive.config.json'
|
||||
$LogDir = Join-Path $ProjectRoot 'logs'
|
||||
$UiPidFile = Join-Path $LogDir 'ui.pid'
|
||||
$UiLog = Join-Path $LogDir 'ui.log'
|
||||
$UiErrLog = Join-Path $LogDir 'ui.err.log'
|
||||
$UiPortFirst = 5173
|
||||
$UiPortLast = 5185
|
||||
$UiMarker = 'ANALYSIS OS'
|
||||
|
||||
function Write-Head($text) { Write-Host ''; Write-Host " $text" -ForegroundColor Cyan }
|
||||
function Write-Ok($text) { Write-Host " $text" -ForegroundColor Green }
|
||||
function Write-Info($text) { Write-Host " $text" -ForegroundColor Gray }
|
||||
function Write-Warn2($text) { Write-Host " $text" -ForegroundColor Yellow }
|
||||
|
||||
function Get-ArchiveConfig {
|
||||
if (-not (Test-Path -LiteralPath $ConfigPath)) { throw "缺少配置文件:$ConfigPath" }
|
||||
return (Get-Content -LiteralPath $ConfigPath -Raw -Encoding UTF8 | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Find-UiPort {
|
||||
foreach ($p in $UiPortFirst..$UiPortLast) {
|
||||
try {
|
||||
$r = Invoke-WebRequest -Uri "http://127.0.0.1:$p/" -TimeoutSec 2 -UseBasicParsing
|
||||
if ($r.StatusCode -eq 200 -and ([string]$r.Content) -like "*$UiMarker*") { return $p }
|
||||
} catch { }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function Wait-UiPort {
|
||||
param([int]$TimeoutSec = 240)
|
||||
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
||||
while ((Get-Date) -lt $deadline) {
|
||||
$p = Find-UiPort
|
||||
if ($p -gt 0) { return $p }
|
||||
Start-Sleep -Milliseconds 1000
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function Get-RecordedUiPid {
|
||||
if (-not (Test-Path -LiteralPath $UiPidFile)) { return 0 }
|
||||
$raw = (Get-Content -LiteralPath $UiPidFile -Raw).Trim()
|
||||
$value = 0
|
||||
if ([int]::TryParse($raw, [ref]$value)) { return $value }
|
||||
return 0
|
||||
}
|
||||
|
||||
function Stop-Ui {
|
||||
$stopped = $false
|
||||
|
||||
$recorded = Get-RecordedUiPid
|
||||
if ($recorded -gt 0 -and (Get-Process -Id $recorded -ErrorAction SilentlyContinue)) {
|
||||
& taskkill.exe /PID $recorded /T /F 2>&1 | Out-Null
|
||||
Write-Ok "已关闭界面窗口(进程树 $recorded)"
|
||||
$stopped = $true
|
||||
}
|
||||
|
||||
# 兜底:按命令行找这个项目的 vite 进程(例如用户自己敲的 npm run dev)
|
||||
$extra = @()
|
||||
foreach ($p in (Get-CimInstance Win32_Process -ErrorAction SilentlyContinue)) {
|
||||
$cl = [string]$p.CommandLine
|
||||
if ($cl -and $cl -like "*$ProjectRoot*vite*") { $extra += [int]$p.ProcessId }
|
||||
}
|
||||
foreach ($t in ($extra | Sort-Object -Unique)) {
|
||||
Stop-Process -Id $t -Force -ErrorAction SilentlyContinue
|
||||
$stopped = $true
|
||||
}
|
||||
if (-not $stopped) { Write-Warn2 '界面本来就没在运行。' }
|
||||
Remove-Item -LiteralPath $UiPidFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
function Show-Status {
|
||||
Write-Head '界面'
|
||||
$port = Find-UiPort
|
||||
if ($port -gt 0) {
|
||||
$recorded = Get-RecordedUiPid
|
||||
Write-Ok "在运行:http://127.0.0.1:$port/ (记录的 PID $recorded)"
|
||||
} else {
|
||||
Write-Info '未运行'
|
||||
}
|
||||
Write-Head '归档后端'
|
||||
& $ServiceScript -Action status
|
||||
}
|
||||
|
||||
switch ($Mode) {
|
||||
'status' { Show-Status }
|
||||
|
||||
'stop' {
|
||||
Write-Head '停止档案库'
|
||||
Stop-Ui
|
||||
& "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" `
|
||||
-NoProfile -ExecutionPolicy Bypass -File $ServiceScript -Action stop
|
||||
Write-Host ''
|
||||
}
|
||||
|
||||
'start' {
|
||||
Write-Head '启动档案库'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ServiceScript)) {
|
||||
throw "找不到服务脚本:$ServiceScript"
|
||||
}
|
||||
|
||||
# 1) 后端(「数据库」)
|
||||
# 放进子进程调用:这样它的 exit 码语义明确,也不会把本脚本一起 exit 掉。
|
||||
# (直接在同一个会话里 & 调用时 $LASTEXITCODE 可能是 $null,而 $null -ne 0 为真,
|
||||
# 会把「后端其实好好的」误报成失败。)
|
||||
Write-Info '检查归档后端……'
|
||||
& "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" `
|
||||
-NoProfile -ExecutionPolicy Bypass -File $ServiceScript -Action ensure
|
||||
$backendOk = ($LASTEXITCODE -eq 0)
|
||||
if (-not $backendOk) {
|
||||
Write-Warn2 '归档后端没能就绪 —— 界面照常启动,但 LOCAL ARCHIVE 面板与「文件位置」会不可用。'
|
||||
}
|
||||
|
||||
$cfg = Get-ArchiveConfig
|
||||
|
||||
# 2) 界面
|
||||
$port = Find-UiPort
|
||||
if ($port -gt 0) {
|
||||
Write-Ok "界面已经在跑:http://127.0.0.1:$port/"
|
||||
} else {
|
||||
if (-not (Test-Path -LiteralPath $LogDir)) { New-Item -ItemType Directory -Path $LogDir -Force | Out-Null }
|
||||
$npm = (Get-Command npm.cmd -ErrorAction SilentlyContinue)
|
||||
if (-not $npm) { throw '找不到 npm.cmd,请确认 Node.js 已正确安装。' }
|
||||
|
||||
Write-Info '启动界面(后台静默运行 npm run dev,日志写进 logs\ui.log)……'
|
||||
# 隐藏窗口 + 重定向输出:一是干净,二是万一起不来,日志就在手边可查。
|
||||
# (反过来,不重定向时 Start-Process 在非交互宿主里可能连窗口都建不出来,
|
||||
# 表现就是「什么都没发生」,排查时毫无线索。)
|
||||
$proc = Start-Process -FilePath $npm.Source -ArgumentList @('run', 'dev') `
|
||||
-WorkingDirectory $ProjectRoot -PassThru -WindowStyle Hidden `
|
||||
-RedirectStandardOutput $UiLog -RedirectStandardError $UiErrLog
|
||||
Set-Content -LiteralPath $UiPidFile -Value $proc.Id -Encoding ASCII
|
||||
|
||||
Write-Info '等待界面就绪(predev 会先重建一次索引,约十几秒)……'
|
||||
$port = Wait-UiPort -TimeoutSec 300
|
||||
if ($port -le 0) {
|
||||
Write-Warn2 '界面在超时前没有响应。下面是它自己的输出:'
|
||||
Write-Host ''
|
||||
if (Test-Path -LiteralPath $UiLog) { Get-Content -LiteralPath $UiLog -Tail 20 -Encoding UTF8 | ForEach-Object { Write-Host " $_" } }
|
||||
if ((Test-Path -LiteralPath $UiErrLog) -and (Get-Item -LiteralPath $UiErrLog).Length -gt 0) {
|
||||
Write-Host ''
|
||||
Write-Host ' --- stderr ---' -ForegroundColor DarkGray
|
||||
Get-Content -LiteralPath $UiErrLog -Tail 20 -Encoding UTF8 | ForEach-Object { Write-Host " $_" }
|
||||
}
|
||||
Write-Host ''
|
||||
exit 1
|
||||
}
|
||||
Write-Ok "界面已就绪:http://127.0.0.1:$port/"
|
||||
}
|
||||
|
||||
# 3) 开浏览器
|
||||
Start-Process ("http://127.0.0.1:$port/") | Out-Null
|
||||
Write-Ok '已用默认浏览器打开。'
|
||||
|
||||
Write-Host ''
|
||||
Write-Info "归档根:$($cfg.root)"
|
||||
Write-Info '要停止:运行「启动档案库.cmd stop」(界面与后端一起停)'
|
||||
Write-Info "界面日志:$UiLog"
|
||||
Write-Host ''
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user