feat(tui): 主入口 Manage-Backup 与配置入口 Edit-Config(第一轮第六块·完成)

Manage-Backup.ps1:不带参数进 TUI 主菜单(备份 / 恢复 / 配置);带 -Action 直接做那个动作,可配 -Quiet 走无头。退出码原样传出(计划任务靠它);只有两种情况由它自己给码:进不了交互界面(2)与菜单里按 Esc(0)。

动作目前仍是**子进程**:一份编排、两个前端是终局目标(ADR-0012),但那要求先把编排从入口脚本下沉进模块。先让 TUI 能用起来,等下沉做完把子进程调用换成进程内直调,界面层不受影响。

-Quiet 与交互两条路的输出处理**故意不同**:-Quiet 时调用方要拿输出(管道 / 日志 / 计划任务),所以捕获并转发;交互时让子进程继承控制台,输出实时、顺序正确、还能接键盘。这套转发收进模块函数 Invoke-BakNRetEntryScript(垫片与主入口共用同一处逻辑)。

Edit-Config.ps1:把已做好的清单编辑器挂上(外科式改写 + 校验通过才落盘 + 时间戳备份);设置与名录两个界面明确报"还没做"并返回非零,而不是假装成功。

判据 7 条。过程中夹具又踩了"& 不传退出码"这个事实(我在垫片那层修过,却在测试夹具这一层又犯)—— 所以断言里改用 -File 调入口;输出检查走**文件重定向**而不是管道捕获(与 E2E 同一个理由:沙箱下给子进程建管道可能失败,写文件不会)。

验收:test.ps1 9/9 全绿(5.1 与 7);真实清单只读冒烟 4/4。
This commit is contained in:
Shuery committed 2026-09-27 20:41:39 +08:00
1 parent 4e3c0461c0
commit c2bae35506
6 files changed
+257

No files matched your search

+86
View File
@@ -0,0 +1,86 @@
<#
.SYNOPSIS
配置管理入口:改清单 / 改设置 / 改名录。
.DESCRIPTION
三个界面共用一个底色(ADR-0013):**外科式改写**(只动被编辑的那一处,注释与其它行一字节不动)、
**校验通过才落盘**(先写临时文件、用模块自己的读取器验、过了才原子替换)、**保存前留时间戳备份**
(logs\config-backups\)。
目前只有**清单**界面做完了;设置(BackupConfig.psd1)与名录(SoftwareCatalog.psd1)分别是
第二轮与第三轮的工作 —— 现在选它们会明确说"还没做"并返回非零,而不是假装成功。
进不了交互界面时明确失败(退出码 2)而不是挂起:TUI 的异常不该改退出码,但"根本没法交互"
是个必须让调用方知道的状态。
.EXAMPLE
.\Edit-Config.ps1 -Target List
.EXAMPLE
.\Edit-Config.ps1 -Target List -ListPath .\BackupList.txt -InputScript @('Enter','Down','Enter')
#>
[CmdletBinding()]
param(
[ValidateSet('List', 'Settings', 'Catalog')][string]$Target,
[string]$ListPath,
[string[]]$InputScript
)
$ErrorActionPreference = 'Stop'
$savedVerbosePreference = $VerbosePreference
$VerbosePreference = 'SilentlyContinue'
Import-Module (Join-Path $PSScriptRoot 'BakNRet\BakNRet.psd1') -Force
$VerbosePreference = $savedVerbosePreference
if (-not $ListPath) { $ListPath = Join-Path $PSScriptRoot 'BackupList.txt' }
function Invoke-BakNRetListEditorEntry {
param([string]$Path, [string[]]$Script)
$driver = New-BakNRetInputDriver -Script $Script -NonInteractive:$([bool]$Script)
$result = Invoke-BakNRetBackupListEditor -Path $Path -Driver $driver
if ($result.Saved) {
Write-Host ("已保存:{0}" -f $Path) -ForegroundColor Green
Write-Host ("原文件备份:{0}" -f $result.BackupPath) -ForegroundColor DarkGray
return 0
}
if ($result.Error) {
Write-Host $result.Error -ForegroundColor Yellow
return 1
}
Write-Host '没有改动。' -ForegroundColor DarkGray
return 0
}
if ($Target -eq 'List') {
exit (Invoke-BakNRetListEditorEntry -Path $ListPath -Script $InputScript)
}
if ($Target) {
Write-Host ("{0} 的编辑器还没做:清单已完成;设置与名录分别是第二轮与第三轮的工作。" -f $Target) -ForegroundColor Yellow
exit 1
}
# 不带 -Target:进配置菜单
if ([Console]::IsOutputRedirected -and -not $InputScript) {
Write-Host '没有可用的控制台,也没有给出 -InputScript:无法进入交互界面。' -ForegroundColor Red
Write-Host '要非交互执行,请指定目标,例如:-Target List' -ForegroundColor Red
exit 2
}
$driver = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$items = @(
[pscustomobject]@{ Key = 'List'; Text = '清单 BackupList.txt —— 改方向,改完校验' }
[pscustomobject]@{ Key = 'Settings'; Text = '设置 BackupConfig.psd1 —— 还没做(第二轮)' }
[pscustomobject]@{ Key = 'Catalog'; Text = '名录 SoftwareCatalog.psd1 —— 还没做(第三轮)' }
)
$picked = Invoke-BakNRetMenu -Title '配置' -Items $items -Driver $driver -MultiSelect $false -Hint '↑↓ 选择 回车 进入 Esc 返回'
if ($picked.Action -ne 'confirm') { exit 0 }
if ($picked.Chosen.Key -eq 'List') {
exit (Invoke-BakNRetListEditorEntry -Path $ListPath -Script $InputScript)
}
Write-Host ("{0} 的编辑器还没做。" -f $picked.Chosen.Key) -ForegroundColor Yellow
exit 1