ux(installer): 双专家审计修复 — P0 取消按钮 + P1 表单优化 + 品牌视觉
基于 UX Auditor + CTO Reviewer 两路并行审计报告的交叉修复: P0 — 进度窗口逃生通道 (UX F1): - ControlBox=$true, X 按钮触发 "取消安装?" 确认 - $BWInstallDone 标记: Phase 7 完成后 X 不再弹确认 P1 — 授权码 "跳过" 按钮误导 (UX F6): - "跳过" → "取消安装", 明确传达后果 P1 — Gitea 空密码静默通过 (UX F10): - 添加 lblError 红字验证: "用户名和密码不能为空" - btnOK 改为手动 Click 事件验证, 不再自动 DialogResult P1 — Gitea 对话框缺少上下文 (UX F11): - 新增说明: "用于下载 Bookworm 配置文件,由管理员提供" P2 — 内部术语暴露 (UX F13): - "crypto-helper.js 缺失" → "Bookworm 启动工具包下载失败" + 3 点排查提示 P2 — 品牌视觉统一 (UX Visual): - 进度窗口: 白底 + Bookworm 蓝紫(#5865F2) Phase 标签 + 右下角计时器 - TopMost=$false (不遮挡其他窗口) - ProgressBar Style=Continuous (平滑) - 全局计时器 $BWStartTime + $BWElapsedLabel "Nm Ns" 实时显示 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d60911f65
commit
8a6611d96e
133
auto-setup.ps1
133
auto-setup.ps1
@ -61,53 +61,82 @@ $global:BWStatusLabel = $null
|
||||
$global:BWProgressBar = $null
|
||||
|
||||
function Show-ProgressForm {
|
||||
# 统一品牌色
|
||||
$brandBlue = [System.Drawing.Color]::FromArgb(88, 101, 242) # Bookworm 蓝紫
|
||||
$brandDark = [System.Drawing.Color]::FromArgb(30, 31, 46)
|
||||
$uiFont = "Segoe UI"
|
||||
|
||||
$global:BWProgressForm = New-Object System.Windows.Forms.Form
|
||||
$global:BWProgressForm.Text = "Bookworm Portable Setup"
|
||||
$global:BWProgressForm.Size = New-Object System.Drawing.Size(520, 200)
|
||||
$global:BWProgressForm.Text = "Bookworm Portable Setup v1.5.1"
|
||||
$global:BWProgressForm.Size = New-Object System.Drawing.Size(520, 230)
|
||||
$global:BWProgressForm.StartPosition = "CenterScreen"
|
||||
$global:BWProgressForm.FormBorderStyle = "FixedDialog"
|
||||
$global:BWProgressForm.MaximizeBox = $false
|
||||
$global:BWProgressForm.MinimizeBox = $false
|
||||
$global:BWProgressForm.TopMost = $true
|
||||
$global:BWProgressForm.ControlBox = $false
|
||||
$global:BWProgressForm.TopMost = $false # P2: 不遮挡其他窗口
|
||||
$global:BWProgressForm.ControlBox = $true # P0 F1: 允许关闭 (触发确认)
|
||||
$global:BWProgressForm.BackColor = [System.Drawing.Color]::White
|
||||
|
||||
# X 按钮关闭时弹确认
|
||||
$global:BWProgressForm.Add_FormClosing({
|
||||
param($s, $e)
|
||||
if (-not $global:BWInstallDone) {
|
||||
$r = [System.Windows.Forms.MessageBox]::Show(
|
||||
"安装尚未完成。`n确定要取消安装吗?",
|
||||
"取消安装", "YesNo", "Warning")
|
||||
if ($r -eq "No") { $e.Cancel = $true; return }
|
||||
Bw-Log "ABORT" "用户手动取消安装"
|
||||
}
|
||||
})
|
||||
|
||||
$titleLabel = New-Object System.Windows.Forms.Label
|
||||
$titleLabel.Location = New-Object System.Drawing.Point(20, 18)
|
||||
$titleLabel.Size = New-Object System.Drawing.Size(480, 24)
|
||||
$titleLabel.Text = "Bookworm 智能助手 — 自动安装中, 请稍候..."
|
||||
$titleLabel.Font = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Bold)
|
||||
$titleLabel.Location = New-Object System.Drawing.Point(20, 16)
|
||||
$titleLabel.Size = New-Object System.Drawing.Size(480, 26)
|
||||
$titleLabel.Text = "Bookworm 智能助手 — 自动安装中"
|
||||
$titleLabel.Font = New-Object System.Drawing.Font($uiFont, 12, [System.Drawing.FontStyle]::Bold)
|
||||
$titleLabel.ForeColor = $brandDark
|
||||
$global:BWProgressForm.Controls.Add($titleLabel)
|
||||
|
||||
$global:BWPhaseLabel = New-Object System.Windows.Forms.Label
|
||||
$global:BWPhaseLabel.Location = New-Object System.Drawing.Point(20, 50)
|
||||
$global:BWPhaseLabel.Size = New-Object System.Drawing.Size(480, 22)
|
||||
$global:BWPhaseLabel.Text = "[0/$TOTAL_PHASES] 初始化..."
|
||||
$global:BWPhaseLabel.Font = New-Object System.Drawing.Font("Segoe UI", 10)
|
||||
$global:BWPhaseLabel.ForeColor = [System.Drawing.Color]::DarkBlue
|
||||
$global:BWPhaseLabel.Font = New-Object System.Drawing.Font($uiFont, 10)
|
||||
$global:BWPhaseLabel.ForeColor = $brandBlue
|
||||
$global:BWProgressForm.Controls.Add($global:BWPhaseLabel)
|
||||
|
||||
$global:BWStatusLabel = New-Object System.Windows.Forms.Label
|
||||
$global:BWStatusLabel.Location = New-Object System.Drawing.Point(20, 78)
|
||||
$global:BWStatusLabel.Size = New-Object System.Drawing.Size(480, 22)
|
||||
$global:BWStatusLabel.Text = ""
|
||||
$global:BWStatusLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9)
|
||||
$global:BWStatusLabel.ForeColor = [System.Drawing.Color]::DimGray
|
||||
$global:BWStatusLabel.Font = New-Object System.Drawing.Font($uiFont, 9)
|
||||
$global:BWStatusLabel.ForeColor = [System.Drawing.Color]::FromArgb(120, 120, 140)
|
||||
$global:BWProgressForm.Controls.Add($global:BWStatusLabel)
|
||||
|
||||
$global:BWProgressBar = New-Object System.Windows.Forms.ProgressBar
|
||||
$global:BWProgressBar.Location = New-Object System.Drawing.Point(20, 110)
|
||||
$global:BWProgressBar.Size = New-Object System.Drawing.Size(480, 22)
|
||||
$global:BWProgressBar.Location = New-Object System.Drawing.Point(20, 112)
|
||||
$global:BWProgressBar.Size = New-Object System.Drawing.Size(480, 20)
|
||||
$global:BWProgressBar.Minimum = 0
|
||||
$global:BWProgressBar.Maximum = $TOTAL_PHASES
|
||||
$global:BWProgressBar.Value = 0
|
||||
$global:BWProgressBar.Style = [System.Windows.Forms.ProgressBarStyle]::Continuous # P3: 平滑
|
||||
$global:BWProgressForm.Controls.Add($global:BWProgressBar)
|
||||
|
||||
$global:BWElapsedLabel = New-Object System.Windows.Forms.Label
|
||||
$global:BWElapsedLabel.Location = New-Object System.Drawing.Point(400, 136)
|
||||
$global:BWElapsedLabel.Size = New-Object System.Drawing.Size(100, 18)
|
||||
$global:BWElapsedLabel.Text = ""
|
||||
$global:BWElapsedLabel.Font = New-Object System.Drawing.Font($uiFont, 8)
|
||||
$global:BWElapsedLabel.ForeColor = [System.Drawing.Color]::Silver
|
||||
$global:BWElapsedLabel.TextAlign = [System.Drawing.ContentAlignment]::TopRight
|
||||
$global:BWProgressForm.Controls.Add($global:BWElapsedLabel)
|
||||
|
||||
$hint = New-Object System.Windows.Forms.Label
|
||||
$hint.Location = New-Object System.Drawing.Point(20, 140)
|
||||
$hint.Size = New-Object System.Drawing.Size(480, 18)
|
||||
$hint.Text = "首次安装约 5-10 分钟 (依赖下载) | 日志: $BWLogFile"
|
||||
$hint.Font = New-Object System.Drawing.Font("Segoe UI", 8)
|
||||
$hint.ForeColor = [System.Drawing.Color]::Gray
|
||||
$hint.Location = New-Object System.Drawing.Point(20, 136)
|
||||
$hint.Size = New-Object System.Drawing.Size(380, 32)
|
||||
$hint.Text = "首次安装约 5-10 分钟 (依赖下载)`n关闭窗口可取消安装"
|
||||
$hint.Font = New-Object System.Drawing.Font($uiFont, 8)
|
||||
$hint.ForeColor = [System.Drawing.Color]::Silver
|
||||
$global:BWProgressForm.Controls.Add($hint)
|
||||
|
||||
$global:BWProgressForm.Show() | Out-Null
|
||||
@ -115,6 +144,11 @@ function Show-ProgressForm {
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
}
|
||||
|
||||
# 全局安装完成标记 (Close-ProgressForm 前设为 $true, 避免 X 按钮弹确认)
|
||||
$global:BWInstallDone = $false
|
||||
# 全局计时器
|
||||
$global:BWStartTime = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
|
||||
function Update-Progress($phase, $title) {
|
||||
if ($global:BWProgressForm -and -not $global:BWProgressForm.IsDisposed) {
|
||||
try {
|
||||
@ -132,6 +166,11 @@ function Update-Progress-SubStatus($msg) {
|
||||
try {
|
||||
$shortMsg = if ($msg.Length -gt 70) { $msg.Substring(0, 67) + "..." } else { $msg }
|
||||
$global:BWStatusLabel.Text = $shortMsg
|
||||
# 刷新总耗时
|
||||
if ($global:BWElapsedLabel -and $global:BWStartTime) {
|
||||
$sec = [int]$global:BWStartTime.Elapsed.TotalSeconds
|
||||
$global:BWElapsedLabel.Text = "$([int]($sec / 60))m $($sec % 60)s"
|
||||
}
|
||||
$global:BWStatusLabel.Refresh()
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
} catch {}
|
||||
@ -139,6 +178,7 @@ function Update-Progress-SubStatus($msg) {
|
||||
}
|
||||
|
||||
function Close-ProgressForm {
|
||||
$global:BWInstallDone = $true # 关闭时不再弹 "取消安装?" 确认
|
||||
if ($global:BWProgressForm -and -not $global:BWProgressForm.IsDisposed) {
|
||||
try { $global:BWProgressForm.Close(); $global:BWProgressForm.Dispose() } catch {}
|
||||
}
|
||||
@ -277,8 +317,8 @@ function Show-AuthCodeDialog($attempt = 1, $maxAttempts = 3) {
|
||||
|
||||
$btnCancel = New-Object System.Windows.Forms.Button
|
||||
$btnCancel.Location = New-Object System.Drawing.Point(350, 145)
|
||||
$btnCancel.Size = New-Object System.Drawing.Size(80, 35)
|
||||
$btnCancel.Text = "跳过"
|
||||
$btnCancel.Size = New-Object System.Drawing.Size(90, 35)
|
||||
$btnCancel.Text = "取消安装"
|
||||
$btnCancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
|
||||
$form.CancelButton = $btnCancel
|
||||
$form.Controls.Add($btnCancel)
|
||||
@ -295,65 +335,84 @@ function Show-AuthCodeDialog($attempt = 1, $maxAttempts = 3) {
|
||||
function Show-GiteaCredentialDialog {
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "Bookworm - Gitea 登录"
|
||||
$form.Size = New-Object System.Drawing.Size(420, 280)
|
||||
$form.Size = New-Object System.Drawing.Size(420, 300)
|
||||
$form.StartPosition = "CenterScreen"
|
||||
$form.FormBorderStyle = "FixedDialog"
|
||||
$form.MaximizeBox = $false
|
||||
$form.TopMost = $true
|
||||
$form.BackColor = [System.Drawing.Color]::White
|
||||
|
||||
$lblInfo = New-Object System.Windows.Forms.Label
|
||||
$lblInfo.Location = New-Object System.Drawing.Point(20, 15)
|
||||
$lblInfo.Size = New-Object System.Drawing.Size(360, 25)
|
||||
$lblInfo.Text = "输入 Gitea 账号 (code.letcareme.com)"
|
||||
$lblInfo.Font = New-Object System.Drawing.Font("Segoe UI", 10)
|
||||
$lblInfo.Size = New-Object System.Drawing.Size(360, 40)
|
||||
$lblInfo.Text = "输入 Gitea 账号 (code.letcareme.com)`n用于下载 Bookworm 配置文件,由管理员提供。"
|
||||
$lblInfo.Font = New-Object System.Drawing.Font("Segoe UI", 9)
|
||||
$form.Controls.Add($lblInfo)
|
||||
|
||||
$lblUser = New-Object System.Windows.Forms.Label
|
||||
$lblUser.Location = New-Object System.Drawing.Point(20, 50)
|
||||
$lblUser.Location = New-Object System.Drawing.Point(20, 65)
|
||||
$lblUser.Size = New-Object System.Drawing.Size(80, 25)
|
||||
$lblUser.Text = "用户名:"
|
||||
$form.Controls.Add($lblUser)
|
||||
|
||||
$txtUser = New-Object System.Windows.Forms.TextBox
|
||||
$txtUser.Location = New-Object System.Drawing.Point(100, 48)
|
||||
$txtUser.Location = New-Object System.Drawing.Point(100, 63)
|
||||
$txtUser.Size = New-Object System.Drawing.Size(280, 25)
|
||||
$txtUser.Font = New-Object System.Drawing.Font("Consolas", 11)
|
||||
$form.Controls.Add($txtUser)
|
||||
|
||||
$lblPass = New-Object System.Windows.Forms.Label
|
||||
$lblPass.Location = New-Object System.Drawing.Point(20, 90)
|
||||
$lblPass.Location = New-Object System.Drawing.Point(20, 105)
|
||||
$lblPass.Size = New-Object System.Drawing.Size(80, 25)
|
||||
$lblPass.Text = "密码:"
|
||||
$form.Controls.Add($lblPass)
|
||||
|
||||
$txtPass = New-Object System.Windows.Forms.TextBox
|
||||
$txtPass.Location = New-Object System.Drawing.Point(100, 88)
|
||||
$txtPass.Location = New-Object System.Drawing.Point(100, 103)
|
||||
$txtPass.Size = New-Object System.Drawing.Size(280, 25)
|
||||
$txtPass.PasswordChar = '*'
|
||||
$txtPass.Font = New-Object System.Drawing.Font("Consolas", 11)
|
||||
$form.Controls.Add($txtPass)
|
||||
|
||||
# P1 F10: 空值验证提示
|
||||
$lblError = New-Object System.Windows.Forms.Label
|
||||
$lblError.Location = New-Object System.Drawing.Point(100, 135)
|
||||
$lblError.Size = New-Object System.Drawing.Size(280, 20)
|
||||
$lblError.Text = ""
|
||||
$lblError.Font = New-Object System.Drawing.Font("Segoe UI", 8)
|
||||
$lblError.ForeColor = [System.Drawing.Color]::Red
|
||||
$form.Controls.Add($lblError)
|
||||
|
||||
$btnOK = New-Object System.Windows.Forms.Button
|
||||
$btnOK.Location = New-Object System.Drawing.Point(200, 140)
|
||||
$btnOK.Location = New-Object System.Drawing.Point(200, 165)
|
||||
$btnOK.Size = New-Object System.Drawing.Size(90, 35)
|
||||
$btnOK.Text = "登录"
|
||||
$btnOK.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
||||
$form.AcceptButton = $btnOK
|
||||
$form.Controls.Add($btnOK)
|
||||
|
||||
$btnCancel = New-Object System.Windows.Forms.Button
|
||||
$btnCancel.Location = New-Object System.Drawing.Point(300, 140)
|
||||
$btnCancel.Location = New-Object System.Drawing.Point(300, 165)
|
||||
$btnCancel.Size = New-Object System.Drawing.Size(80, 35)
|
||||
$btnCancel.Text = "取消"
|
||||
$btnCancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
|
||||
$form.CancelButton = $btnCancel
|
||||
$form.Controls.Add($btnCancel)
|
||||
|
||||
# OK 按钮手动验证 (不用 DialogResult, 防止空值直接关闭)
|
||||
$btnOK.Add_Click({
|
||||
if (-not $txtUser.Text.Trim() -or -not $txtPass.Text) {
|
||||
$lblError.Text = "用户名和密码不能为空"
|
||||
return
|
||||
}
|
||||
$form.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
||||
$form.Close()
|
||||
})
|
||||
$form.AcceptButton = $btnOK
|
||||
|
||||
$form.Add_Shown({ $txtUser.Focus() })
|
||||
$result = $form.ShowDialog()
|
||||
|
||||
if ($result -eq [System.Windows.Forms.DialogResult]::OK -and $txtUser.Text -and $txtPass.Text) {
|
||||
return @{ User = $txtUser.Text; Pass = $txtPass.Text }
|
||||
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
|
||||
return @{ User = $txtUser.Text.Trim(); Pass = $txtPass.Text }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
@ -805,8 +864,8 @@ if (Test-Path (Join-Path $BootDir ".git")) {
|
||||
$bootCloneUrl = if ($cred) { $BootUrl -replace '://', "://$($cred.User):$($cred.Pass)@" } else { $BootUrl }
|
||||
$r = Run-CmdWithUI "git" @("clone", "--depth", "1", $bootCloneUrl, $BootDir) "克隆 boot 仓库" 180000
|
||||
if (-not (Test-Path (Join-Path $BootDir "crypto-helper.js"))) {
|
||||
Log-Fail "boot 仓库克隆失败 (crypto-helper.js 缺失)"
|
||||
Show-MsgBox "boot 仓库克隆失败。`n请检查网络和 Gitea 凭证。" "克隆失败" "OK" "Error"
|
||||
Log-Fail "启动工具包下载失败"
|
||||
Show-MsgBox "Bookworm 启动工具包下载失败。`n`n请检查:`n1. Gitea 账号和密码是否正确`n2. 网络连接是否正常`n3. 代理软件是否已启动`n`n然后重新运行安装器即可。" "下载失败" "OK" "Error"
|
||||
exit 1
|
||||
}
|
||||
Log-OK "boot 仓库克隆成功 → $BootDir"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user