::BATCH_START @ECHO off SETLOCAL EnableDelayedExpansion TITLE Initializing Script... CD /d %~dp0 SET ScriptPath=\^"%~f0\^" SET ScriptRoot=%~dp0 SET ScriptRoot=\^"!ScriptRoot:~0,-1!\^" SET Args=%* IF DEFINED Args (SET Args=!Args:"=\"!) $null } function Show-YesNoPrompt { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$Message, [string]$Title = "", [ValidateRange(0, 1)] [int]$DefaultIndex = 0, [string[]]$Labels = @("&Yes", "&No"), [string[]]$Helps = @("是", "否") ) if ($Labels.Count -ne $Helps.Count) { throw "Labels 和 Helps 的数量必须相同。" } $choices = for ($i = 0; $i -lt $Labels.Count; $i++) { [System.Management.Automation.Host.ChoiceDescription]::new($Labels[$i], $Helps[$i]) } try { return $Host.UI.PromptForChoice($Title, $Message, $choices, $DefaultIndex) -eq 0 } catch { Write-Error "显示选择提示时出错: $_" return $false } } function Show-MultipleChoicePrompt { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$Message, [Parameter(Mandatory = $true, Position = 1)] [ValidateNotNullOrEmpty()] [string[]]$Options, [string[]]$Helps = @(), [string]$Title = "", [int]$DefaultIndex = 0 ) if ($Helps.Count -eq 0) { $Helps = @("") for ($i = 1; $i -lt $Options.Count; $i++) { $Helps += "" } } if ($Options.Count -ne $Helps.Count) { throw "Options 和 Helps 的数量必须相同。" } if ($DefaultIndex -ge $Options.Count) { $DefaultIndex = $Options.Count - 1 } $currentSelection = $DefaultIndex function Show-Menu { param( [int]$highlightIndex, [string]$title, [string]$message, [string[]]$options, [string[]]$helps, [int]$prevIndex = -1 ) try { # 首次显示时绘制完整菜单 if ($prevIndex -eq -1) { Clear-Host if (-not [string]::IsNullOrEmpty($title)) { Write-Host "$title`n" -ForegroundColor Blue } Write-Host "$message" -ForegroundColor Yellow # 保存初始光标位置 $script:menuTop = [Console]::CursorTop # 首次绘制所有选项 for ($i = 0; $i -lt $options.Count; $i++) { $prefix = if ($i -eq $highlightIndex) { "[>]" } else { "[ ]" } $color = if ($i -eq $highlightIndex) { "Green" } else { "Gray" } Write-Host "$prefix $($options[$i])" -ForegroundColor $color -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($helps[$i])) { " - $($helps[$i])" } else { "" }) -ForegroundColor DarkGray } } # 只更新变化的选项 if ($prevIndex -ne -1) { $safePrevPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $prevIndex) [Console]::SetCursorPosition(0, $safePrevPos) Write-Host "[ ] $($options[$prevIndex])" -ForegroundColor Gray -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($helps[$prevIndex])) { " - $($helps[$prevIndex])" } else { "" }) -ForegroundColor DarkGray } $safeHighlightPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $highlightIndex) [Console]::SetCursorPosition(0, $safeHighlightPos) Write-Host "[>] $($options[$highlightIndex])" -ForegroundColor Green -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($helps[$highlightIndex])) { " - $($helps[$highlightIndex])" } else { "" }) -ForegroundColor DarkGray # 首次显示时绘制操作提示 if ($prevIndex -eq -1) { $safePos = [Math]::Min([Console]::WindowHeight - 2, $menuTop + $options.Count) [Console]::SetCursorPosition(0, $safePos) Write-Host "操作: 使用 ↑ / ↓ 移动 | Enter - 确认" } } finally { # 将光标移动到操作提示下方等待位置 $waitPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $options.Count + 1) [Console]::SetCursorPosition(0, $waitPos) } } $prevSelection = -1 while ($true) { Show-Menu -highlightIndex $currentSelection -title $Title -message $Message -options $Options -helps $Helps -prevIndex $prevSelection $prevSelection = $currentSelection $key = [System.Console]::ReadKey($true) switch ($key.Key) { { $_ -eq [ConsoleKey]::UpArrow } { $currentSelection = [Math]::Max(0, $currentSelection - 1) } { $_ -eq [ConsoleKey]::DownArrow } { $currentSelection = [Math]::Min($Options.Count - 1, $currentSelection + 1) } { $_ -eq [ConsoleKey]::Enter } { Clear-Host return $currentSelection } } } } function Show-MultiSelectPrompt { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$Message, [Parameter(Mandatory = $true, Position = 1)] [ValidateNotNullOrEmpty()] [string[]]$Options, [string[]]$Helps = @(), [string]$Title = "", [int[]]$DefaultSelections = @() ) if ($Helps.Count -eq 0) { $Helps = @("") for ($i = 1; $i -lt $Options.Count; $i++) { $Helps += "" } } if ($Options.Count -ne $Helps.Count) { throw "Options 和 Helps 的数量必须相同。" } $selectedIndices = [System.Collections.Generic.List[int]]::new($DefaultSelections) $currentSelection = 0 function Show-Menu { param( [int]$highlightIndex, [System.Collections.Generic.List[int]]$selectedItems, [int]$prevIndex = -1, [int]$prevHighlight = -1 ) try { # 首次显示时绘制完整菜单 if ($prevIndex -eq -1) { Clear-Host if (-not [string]::IsNullOrEmpty($Title)) { Write-Host "$Title`n" -ForegroundColor Blue } Write-Host "$Message" -ForegroundColor Yellow # 保存初始光标位置 $script:menuTop = [Console]::CursorTop # 首次绘制所有选项 for ($i = 0; $i -lt $Options.Count; $i++) { $isSelected = $selectedItems -contains $i $prefix = if ($isSelected) { "[#]" } else { "[ ]" } $color = if ($i -eq $highlightIndex) { "Green" } elseif ($isSelected) { "Cyan" } else { "Gray" } Write-Host "$prefix $($Options[$i])" -ForegroundColor $color -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($Helps[$i])) { " - $($Helps[$i])" } else { "" }) -ForegroundColor DarkGray } } # 只更新变化的选项 if ($prevIndex -ne -1) { $safePrevPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $prevIndex) [Console]::SetCursorPosition(0, $safePrevPos) $isPrevSelected = $selectedItems -contains $prevIndex $prefix = if ($isPrevSelected) { "[#]" } else { "[ ]" } Write-Host "$prefix $($Options[$prevIndex])" -ForegroundColor $(if ($isPrevSelected) { "Cyan" } else { "Gray" }) -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($Helps[$prevIndex])) { " - $($Helps[$prevIndex])" } else { "" }) -ForegroundColor DarkGray } if ($prevHighlight -ne -1 -and $prevHighlight -ne $highlightIndex) { $safePrevHighlightPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $prevHighlight) [Console]::SetCursorPosition(0, $safePrevHighlightPos) $isPrevHighlightSelected = $selectedItems -contains $prevHighlight $prefix = if ($isPrevHighlightSelected) { "[#]" } else { "[ ]" } Write-Host "$prefix $($Options[$prevHighlight])" -ForegroundColor $(if ($isPrevHighlightSelected) { "Cyan" } else { "Gray" }) -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($Helps[$prevHighlight])) { " - $($Helps[$prevHighlight])" } else { "" }) -ForegroundColor DarkGray } $safeHighlightPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $highlightIndex) [Console]::SetCursorPosition(0, $safeHighlightPos) $isSelected = $selectedItems -contains $highlightIndex $prefix = if ($isSelected) { "[#]" } else { "[ ]" } Write-Host "$prefix $($Options[$highlightIndex])" -ForegroundColor "Green" -NoNewline Write-Host $(if (-not [string]::IsNullOrEmpty($Helps[$highlightIndex])) { " - $($Helps[$highlightIndex])" } else { "" }) -ForegroundColor DarkGray # 首次显示时绘制操作提示 if ($prevIndex -eq -1) { $safePos = [Math]::Min([Console]::WindowHeight - 2, $menuTop + $Options.Count) [Console]::SetCursorPosition(0, $safePos) Write-Host "操作: 使用 ↑ / ↓ 移动 | Space - 选中/取消 | Enter - 确认" } } finally { # 将光标移动到操作提示下方等待位置 $waitPos = [Math]::Min([Console]::WindowHeight - 1, $menuTop + $Options.Count + 1) [Console]::SetCursorPosition(0, $waitPos) } } $prevSelection = -1 $prevHighlight = -1 while ($true) { Show-Menu -highlightIndex $currentSelection -selectedItems $selectedIndices -prevIndex $prevSelection -prevHighlight $prevHighlight $prevHighlight = $currentSelection $key = [System.Console]::ReadKey($true) switch ($key.Key) { { $_ -eq [ConsoleKey]::UpArrow } { $prevSelection = $currentSelection $currentSelection = [Math]::Max(0, $currentSelection - 1) } { $_ -eq [ConsoleKey]::DownArrow } { $prevSelection = $currentSelection $currentSelection = [Math]::Min($Options.Count - 1, $currentSelection + 1) } { $_ -eq [ConsoleKey]::Spacebar } { $prevSelection = $currentSelection if ($selectedIndices.Contains($currentSelection)) { $selectedIndices.Remove($currentSelection) } else { $selectedIndices.Add($currentSelection) } } { $_ -eq [ConsoleKey]::Enter } { Clear-Host return $selectedIndices } } } } function Get-InputWithNoNullOrWhiteSpace { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$Prompt ) while ($true) { try { $response = Read-Host "请输入${Prompt}(必填)" if ([string]::IsNullOrWhiteSpace($response)) { Write-Host "${Prompt}不能为空!" -ForegroundColor Red continue } if ($response -match '^(?!").*(?