style(panel): дашборд с рамкой, цветной статус-маркер, сгруппированное меню
UI консольной панели: - Закрытая рамка из box-символов (╔═╗║╠╣╚╝) вместо голых ===; правый бордюр выровнен на всех строках (хелперы B-Top/B-Mid/B-Bot/B-Line + B-Status с цветным маркером ●). - Статус-блок: ● зелёный РАБОТАЕТ / серый ОСТАНОВЛЕН, health цветом по состоянию, строка БД (размер · юзеры · миграция-номер · бэкапов), Node/JWT/LLM/время обновления, URL. - Меню в две выровненные колонки СЕРВЕР | ОБСЛУЖИВАНИЕ (ключи голубые, подписи серые), отдельная строка ДИАГНОСТИКА; промпт с ▶. Чистый рефактор отрисовки — логика switch/функции не тронуты. UTF-8 BOM, парсинг OK, рендер-смоук показал ровное выравнивание. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+65
-20
@@ -68,7 +68,8 @@ $script:Stat = $null
|
|||||||
function Refresh-Status {
|
function Refresh-Status {
|
||||||
$proc = Server-Proc
|
$proc = Server-Proc
|
||||||
$s = @{ running = ($null -ne $proc); procId = '-'; uptime = '-'; health = '—'; healthMs = $null;
|
$s = @{ running = ($null -ne $proc); procId = '-'; uptime = '-'; health = '—'; healthMs = $null;
|
||||||
dbSize = '—'; users = '?'; migr = '-' }
|
dbSize = '—'; users = '?'; migr = '-'; at = (Get-Date -Format 'HH:mm:ss'); backups = 0 }
|
||||||
|
try { $s.backups = @(Get-ChildItem $script:BackupDir -Filter 'learnspace-*.db' -ErrorAction SilentlyContinue).Count } catch {}
|
||||||
if ($proc) {
|
if ($proc) {
|
||||||
$s.procId = $proc.Id
|
$s.procId = $proc.Id
|
||||||
try { $u = (Get-Date) - $proc.StartTime; $s.uptime = ('{0}ч {1}м' -f [int]$u.TotalHours, $u.Minutes) } catch {}
|
try { $u = (Get-Date) - $proc.StartTime; $s.uptime = ('{0}ч {1}м' -f [int]$u.TotalHours, $u.Minutes) } catch {}
|
||||||
@@ -205,6 +206,42 @@ function Run-Cmd($title, $block) {
|
|||||||
[void](Read-Host ' [Enter] вернуться в меню')
|
[void](Read-Host ' [Enter] вернуться в меню')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Рисование рамки/дашборда ──
|
||||||
|
$script:W = 62 # внутренняя ширина рамки (символов)
|
||||||
|
function B-Top { Write-Host (' ╔' + ('═' * ($script:W + 2)) + '╗') -ForegroundColor DarkCyan }
|
||||||
|
function B-Mid { Write-Host (' ╠' + ('═' * ($script:W + 2)) + '╣') -ForegroundColor DarkCyan }
|
||||||
|
function B-Bot { Write-Host (' ╚' + ('═' * ($script:W + 2)) + '╝') -ForegroundColor DarkCyan }
|
||||||
|
function B-Line($text, $color) {
|
||||||
|
$t = [string]$text
|
||||||
|
if ($t.Length -gt $script:W) { $t = $t.Substring(0, $script:W) }
|
||||||
|
Write-Host ' ║ ' -ForegroundColor DarkCyan -NoNewline
|
||||||
|
Write-Host $t.PadRight($script:W) -ForegroundColor $color -NoNewline
|
||||||
|
Write-Host ' ║' -ForegroundColor DarkCyan
|
||||||
|
}
|
||||||
|
# Строка с цветным маркером ● слева (статус). Маркер + пробел = 2 столбца.
|
||||||
|
function B-Status($markerColor, $text, $textColor) {
|
||||||
|
$avail = $script:W - 2
|
||||||
|
$t = [string]$text
|
||||||
|
if ($t.Length -gt $avail) { $t = $t.Substring(0, $avail) }
|
||||||
|
Write-Host ' ║ ' -ForegroundColor DarkCyan -NoNewline
|
||||||
|
Write-Host '●' -ForegroundColor $markerColor -NoNewline
|
||||||
|
Write-Host ' ' -NoNewline
|
||||||
|
Write-Host $t.PadRight($avail) -ForegroundColor $textColor -NoNewline
|
||||||
|
Write-Host ' ║' -ForegroundColor DarkCyan
|
||||||
|
}
|
||||||
|
# Заголовок секции меню (две колонки выравниваются под пунктами).
|
||||||
|
function Menu-Head($left, $right) { Write-Host (' ' + $left.PadRight(34) + $right) -ForegroundColor DarkCyan }
|
||||||
|
# Пункт меню в две колонки: ключ голубой, подпись серая.
|
||||||
|
function Menu-Row($lk, $ll, $rk, $rl) {
|
||||||
|
Write-Host ' ' -NoNewline
|
||||||
|
Write-Host $lk -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host ((' ' + $ll).PadRight(31)) -ForegroundColor Gray -NoNewline
|
||||||
|
if ($rk) {
|
||||||
|
Write-Host $rk -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host (' ' + $rl) -ForegroundColor Gray
|
||||||
|
} else { Write-Host '' }
|
||||||
|
}
|
||||||
|
|
||||||
# ── Неинтерактивные режимы (для start/stop-server.bat) ──
|
# ── Неинтерактивные режимы (для start/stop-server.bat) ──
|
||||||
if ($Stop) { Stop-Server; Start-Sleep -Milliseconds 800; exit }
|
if ($Stop) { Stop-Server; Start-Sleep -Milliseconds 800; exit }
|
||||||
if ($Start) { Start-Server; Start-Sleep -Milliseconds 800; exit }
|
if ($Start) { Start-Server; Start-Sleep -Milliseconds 800; exit }
|
||||||
@@ -215,34 +252,41 @@ $run = $true
|
|||||||
while ($run) {
|
while ($run) {
|
||||||
Clear-Host
|
Clear-Host
|
||||||
$s = $script:Stat
|
$s = $script:Stat
|
||||||
$bar = ' ' + ('=' * 58)
|
$migrShort = $s.migr; if ($s.migr -match '^(\d+)') { $migrShort = $matches[1] }
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host $bar -ForegroundColor DarkCyan
|
B-Top
|
||||||
Write-Host ' LearnSpace — Панель управления' -ForegroundColor Cyan
|
B-Line 'LearnSpace · Панель управления сервером' Cyan
|
||||||
Write-Host $bar -ForegroundColor DarkCyan
|
B-Mid
|
||||||
if ($s.running) {
|
if ($s.running) {
|
||||||
Write-Host (' Статус: РАБОТАЕТ — PID ' + $s.procId + ', порт ' + $script:Port + ', аптайм ' + $s.uptime) -ForegroundColor Green
|
B-Status Green ('РАБОТАЕТ PID ' + $s.procId + ' · порт ' + $script:Port + ' · аптайм ' + $s.uptime) Green
|
||||||
$hc = if ($s.health -eq 'healthy') { 'Green' } else { 'Yellow' }
|
$hc = if ($s.health -eq 'healthy') { 'Green' } else { 'Yellow' }
|
||||||
$hm = if ($s.healthMs -ne $null) { " ($($s.healthMs) ms)" } else { '' }
|
$hm = if ($s.healthMs -ne $null) { " ($($s.healthMs) ms)" } else { '' }
|
||||||
Write-Host (' Health: ' + $s.health + $hm) -ForegroundColor $hc
|
B-Line ('Health: ' + $s.health + $hm) $hc
|
||||||
} else {
|
} else {
|
||||||
Write-Host ' Статус: остановлен' -ForegroundColor Yellow
|
B-Status DarkGray 'ОСТАНОВЛЕН' Yellow
|
||||||
}
|
}
|
||||||
Write-Host (' БД: ' + $s.dbSize + ', пользователей: ' + $s.users + ', миграций до: ' + $s.migr) -ForegroundColor Gray
|
B-Line ('БД ' + $s.dbSize + ' · пользователей: ' + $s.users + ' · миграция: ' + $migrShort + ' · бэкапов: ' + $s.backups) Gray
|
||||||
Write-Host (' Node: ' + $script:NodeVer + ' | .env: CLIENT_ORIGIN=' + $script:EnvSum.origin + ', JWT_SECRET=' + $script:EnvSum.jwt + ', LLM=' + $script:EnvSum.llm) -ForegroundColor DarkGray
|
B-Line ('Node ' + $script:NodeVer + ' · JWT: ' + $script:EnvSum.jwt + ' · LLM: ' + $script:EnvSum.llm + ' · обновлено ' + $s.at) DarkGray
|
||||||
Write-Host (' URL: http://localhost:' + $script:Port) -ForegroundColor DarkGray
|
B-Line ('URL ' + $script:EnvSum.origin) DarkGray
|
||||||
Write-Host $bar -ForegroundColor DarkCyan
|
B-Bot
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host ' [1] Запустить сервер [6] Тесты (npm test)'
|
Menu-Head 'СЕРВЕР' 'ОБСЛУЖИВАНИЕ'
|
||||||
Write-Host ' [2] Остановить сервер [7] Проверка роутов (lint)'
|
Menu-Row '[1]' 'Запустить' '[B]' 'Бэкап БД'
|
||||||
Write-Host ' [3] Перезапустить [8] Открыть сайт в браузере'
|
Menu-Row '[2]' 'Остановить' '[R]' 'Восстановить БД'
|
||||||
Write-Host ' [4] Живые логи (окно) [9] Обновить статус'
|
Menu-Row '[3]' 'Перезапустить' '[A]' 'Создать админа'
|
||||||
Write-Host ' [5] Применить миграции [0] Выход'
|
Menu-Row '[4]' 'Живые логи (окно)' '[W]' 'Сторож (авто-рестарт)'
|
||||||
|
Menu-Row '[5]' 'Применить миграции' '[E]' 'Ошибки в логах'
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host ' Данные и обслуживание:' -ForegroundColor DarkCyan
|
Menu-Head 'ДИАГНОСТИКА И ПРОЧЕЕ' ''
|
||||||
Write-Host ' [B] Бэкап БД [R] Восстановить БД [A] Создать админа [W] Сторож [E] Ошибки'
|
Write-Host ' ' -NoNewline
|
||||||
|
Write-Host '[6]' -ForegroundColor Cyan -NoNewline; Write-Host ' Тесты ' -ForegroundColor Gray -NoNewline
|
||||||
|
Write-Host '[7]' -ForegroundColor Cyan -NoNewline; Write-Host ' Lint роутов ' -ForegroundColor Gray -NoNewline
|
||||||
|
Write-Host '[8]' -ForegroundColor Cyan -NoNewline; Write-Host ' Сайт ' -ForegroundColor Gray -NoNewline
|
||||||
|
Write-Host '[9]' -ForegroundColor Cyan -NoNewline; Write-Host ' Обновить ' -ForegroundColor Gray -NoNewline
|
||||||
|
Write-Host '[0]' -ForegroundColor Cyan -NoNewline; Write-Host ' Выход' -ForegroundColor Gray
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
$c = (Read-Host ' Выбор').Trim().ToUpper()
|
Write-Host ' ▶ ' -ForegroundColor Cyan -NoNewline
|
||||||
|
$c = (Read-Host 'Выбор').Trim().ToUpper()
|
||||||
switch -Regex ($c) {
|
switch -Regex ($c) {
|
||||||
'^1$' { Start-Server; Refresh-Status; Start-Sleep 1 }
|
'^1$' { Start-Server; Refresh-Status; Start-Sleep 1 }
|
||||||
'^2$' { Stop-Server; Refresh-Status; Start-Sleep 1 }
|
'^2$' { Stop-Server; Refresh-Status; Start-Sleep 1 }
|
||||||
@@ -267,3 +311,4 @@ Write-Host ' Панель закрыта. Сервер, если запуще
|
|||||||
Write-Host ' Остановить позже: stop-server.bat или пункт [2] панели.' -ForegroundColor DarkGray
|
Write-Host ' Остановить позже: stop-server.bat или пункт [2] панели.' -ForegroundColor DarkGray
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user