feat(webui): FastAPI REST + WebSocket-консоль + MCP-эндпоинт + браузерный UI
- server.py: /api/power/*, /api/status, /api/history, /ws/console, /mcp (MCPServer streamable-http) - auth: Bearer-токен (ATXPI_WEB_TOKEN) для /api/* и /mcp/*; WS — через ?token= - статика: index.html, app.js, style.css + vendored xterm.js (работает офлайн на Pi) - lightweight: один процесс uvicorn, без node/сборки - install.sh: отдаю сервис-юзеру владение atxpi/ и /etc/atxpi (pyc/tmp/audit)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
:root {
|
||||
--bg: #0b0f14;
|
||||
--panel: #121a22;
|
||||
--panel2: #17222d;
|
||||
--text: #d7d7d7;
|
||||
--muted: #7a8691;
|
||||
--accent: #4e8cff;
|
||||
--danger: #ff5c5c;
|
||||
--ok: #48d597;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
}
|
||||
.hidden { display: none !important; }
|
||||
.muted { color: var(--muted); }
|
||||
.err { color: var(--danger); }
|
||||
.spacer { flex: 1; }
|
||||
|
||||
/* логин */
|
||||
#login {
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.card {
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--panel2);
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
width: 320px;
|
||||
text-align: center;
|
||||
}
|
||||
.card input {
|
||||
width: 100%; padding: 10px 12px; margin: 8px 0 14px;
|
||||
border-radius: 8px; border: 1px solid var(--panel2);
|
||||
background: var(--bg); color: var(--text);
|
||||
}
|
||||
|
||||
/* app */
|
||||
#app { max-width: 900px; margin: 0 auto; padding: 24px; }
|
||||
header {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding-bottom: 14px; border-bottom: 1px solid var(--panel2);
|
||||
}
|
||||
header h1 { margin: 0; font-size: 20px; }
|
||||
.badge {
|
||||
padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 600;
|
||||
background: var(--panel2); color: var(--muted);
|
||||
}
|
||||
.status-line { color: var(--muted); margin: 14px 0; font-size: 13px; }
|
||||
|
||||
.btn {
|
||||
border: 1px solid var(--panel2); background: var(--panel2); color: var(--text);
|
||||
padding: 8px 14px; border-radius: 8px; cursor: pointer; font-size: 14px;
|
||||
}
|
||||
.btn:hover { border-color: var(--accent); }
|
||||
.btn.primary { background: var(--accent); border-color: var(--accent); color: #04121f; font-weight: 600; }
|
||||
.btn.danger:hover { border-color: var(--danger); }
|
||||
|
||||
/* консоль */
|
||||
.console-panel {
|
||||
margin-top: 16px;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--panel2);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.console-bar {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
padding: 10px 14px; background: var(--panel2); font-size: 13px;
|
||||
}
|
||||
#term { height: 360px; padding: 8px; }
|
||||
Reference in New Issue
Block a user