229 lines
7.2 KiB
HTML
229 lines
7.2 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Local Management Agent</title>
|
|
<style>
|
|
:root {
|
|
--bg: #f4f5f7;
|
|
--card: #fff;
|
|
--text: #1f2937;
|
|
--muted: #6b7280;
|
|
--line: #e5e7eb;
|
|
--accent: #2563eb;
|
|
--danger: #b91c1c;
|
|
--ok: #047857;
|
|
}
|
|
* { box-sizing: border-box; }
|
|
body {
|
|
margin: 0;
|
|
font: 15px/1.45 system-ui, Segoe UI, sans-serif;
|
|
color: var(--text);
|
|
background: var(--bg);
|
|
}
|
|
header, main { max-width: 1100px; margin: 0 auto; padding: 0 1.25rem; }
|
|
header {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
padding-top: 1.5rem;
|
|
padding-bottom: 1rem;
|
|
}
|
|
h1 { font-size: 1.35rem; margin: 0; }
|
|
h2 { font-size: 1rem; margin: 0 0 0.85rem; }
|
|
.badge {
|
|
font-size: 0.8rem;
|
|
padding: 0.2rem 0.55rem;
|
|
border-radius: 999px;
|
|
background: #e5e7eb;
|
|
color: var(--muted);
|
|
}
|
|
.badge.ok { background: #d1fae5; color: var(--ok); }
|
|
.badge.bad { background: #fee2e2; color: var(--danger); }
|
|
nav {
|
|
max-width: 1100px;
|
|
margin: 0 auto 1rem;
|
|
padding: 0 1.25rem;
|
|
display: flex;
|
|
gap: 0.4rem;
|
|
}
|
|
nav button, .row button, .row select {
|
|
font: inherit;
|
|
border: 1px solid var(--line);
|
|
background: var(--card);
|
|
border-radius: 6px;
|
|
padding: 0.4rem 0.75rem;
|
|
cursor: pointer;
|
|
}
|
|
nav button.active, .row button.primary {
|
|
background: var(--accent);
|
|
border-color: var(--accent);
|
|
color: #fff;
|
|
}
|
|
button:disabled { opacity: 0.45; cursor: default; }
|
|
.panel {
|
|
display: none;
|
|
background: var(--card);
|
|
border: 1px solid var(--line);
|
|
border-radius: 10px;
|
|
padding: 1rem 1.1rem 1.2rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
.panel.active { display: block; }
|
|
.row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem;
|
|
align-items: center;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
input, textarea, select {
|
|
font: inherit;
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
padding: 0.4rem 0.6rem;
|
|
}
|
|
input[type="text"], textarea { flex: 1; min-width: 12rem; }
|
|
textarea { width: 100%; min-height: 4.5rem; font-family: ui-monospace, Consolas, monospace; }
|
|
.meta { color: var(--muted); font-size: 0.9rem; }
|
|
dl {
|
|
display: grid;
|
|
grid-template-columns: 10rem 1fr;
|
|
gap: 0.35rem 0.8rem;
|
|
margin: 0;
|
|
}
|
|
dt { color: var(--muted); }
|
|
dd { margin: 0; word-break: break-all; }
|
|
table { width: 100%; border-collapse: collapse; }
|
|
th, td { text-align: left; padding: 0.4rem 0.35rem; border-bottom: 1px solid var(--line); }
|
|
th { color: var(--muted); font-weight: 600; font-size: 0.8rem; }
|
|
td.name { cursor: pointer; color: var(--accent); }
|
|
td.name.file { color: var(--text); }
|
|
pre {
|
|
margin: 0.5rem 0 0;
|
|
padding: 0.75rem;
|
|
background: #0f172a;
|
|
color: #e2e8f0;
|
|
border-radius: 8px;
|
|
overflow: auto;
|
|
max-height: 22rem;
|
|
white-space: pre-wrap;
|
|
}
|
|
.shots { display: flex; flex-wrap: wrap; gap: 0.75rem; }
|
|
.shots figure { margin: 0; }
|
|
.shots img { max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px; }
|
|
#video-canvas {
|
|
width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
cursor: crosshair;
|
|
background: #111;
|
|
}
|
|
.error {
|
|
display: none;
|
|
max-width: 1100px;
|
|
margin: 0 auto 1rem;
|
|
padding: 0.65rem 1.25rem;
|
|
color: var(--danger);
|
|
}
|
|
.error.show { display: block; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>Local Management Agent</h1>
|
|
<span id="health" class="badge">checking</span>
|
|
</header>
|
|
<p id="error" class="error"></p>
|
|
<nav>
|
|
<button data-tab="status" class="active">Status</button>
|
|
<button data-tab="files">Files</button>
|
|
<button data-tab="screenshot">Screenshot</button>
|
|
<button data-tab="video">Video</button>
|
|
<button data-tab="exec">Command</button>
|
|
</nav>
|
|
<main>
|
|
<section id="status" class="panel active">
|
|
<div class="row">
|
|
<h2>Host status</h2>
|
|
<button id="refresh-status" class="primary" type="button">Refresh</button>
|
|
</div>
|
|
<dl id="status-fields"></dl>
|
|
<div class="row" style="margin-top:1rem">
|
|
<span id="startup-state" class="meta">Startup: —</span>
|
|
<button id="startup-add" type="button">Add to startup</button>
|
|
<button id="startup-remove" type="button">Remove from startup</button>
|
|
</div>
|
|
</section>
|
|
<section id="files" class="panel">
|
|
<div class="row">
|
|
<input id="file-path" type="text" placeholder="Directory path, e.g. C:\Users">
|
|
<button id="file-up" type="button">Up</button>
|
|
<button id="file-list" class="primary" type="button">List</button>
|
|
</div>
|
|
<p id="file-meta" class="meta"></p>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Name</th><th>Type</th><th>Size</th><th>Modified</th></tr>
|
|
</thead>
|
|
<tbody id="file-rows"></tbody>
|
|
</table>
|
|
</section>
|
|
<section id="screenshot" class="panel">
|
|
<div class="row">
|
|
<label>Format
|
|
<select id="shot-format">
|
|
<option value="png">PNG</option>
|
|
<option value="jpeg">JPEG</option>
|
|
</select>
|
|
</label>
|
|
<label>Quality
|
|
<input id="shot-quality" type="number" min="1" max="100" value="80" style="width:5rem">
|
|
</label>
|
|
<button id="shot-capture" class="primary" type="button">Capture</button>
|
|
</div>
|
|
<div id="shot-gallery" class="shots"></div>
|
|
</section>
|
|
<section id="video" class="panel">
|
|
<div class="row">
|
|
<button id="video-start" class="primary" type="button">Start</button>
|
|
<button id="video-stop" type="button" disabled>Stop</button>
|
|
<label>FPS
|
|
<input id="video-fps" type="number" min="1" max="15" value="5" style="width:4.5rem">
|
|
</label>
|
|
<label>Quality
|
|
<input id="video-quality" type="number" min="1" max="100" value="40" style="width:5rem">
|
|
</label>
|
|
<label>Monitor
|
|
<input id="video-monitor" type="number" min="0" value="0" style="width:4.5rem">
|
|
</label>
|
|
</div>
|
|
<canvas id="video-canvas" width="1280" height="720"></canvas>
|
|
<p id="video-meta" class="meta"></p>
|
|
<div class="row" style="margin-top:0.75rem">
|
|
<input id="video-text" type="text" placeholder="Type text for the focused field">
|
|
<button id="video-send" class="primary" type="button">Send</button>
|
|
</div>
|
|
</section>
|
|
<section id="exec" class="panel">
|
|
<div class="row">
|
|
<textarea id="exec-command" placeholder="ipconfig /all"></textarea>
|
|
</div>
|
|
<div class="row">
|
|
<label>Timeout (sec)
|
|
<input id="exec-timeout" type="number" min="0" max="120" value="30" style="width:5rem">
|
|
</label>
|
|
<button id="exec-run" class="primary" type="button">Run</button>
|
|
</div>
|
|
<p id="exec-meta" class="meta"></p>
|
|
<pre id="exec-out"></pre>
|
|
</section>
|
|
</main>
|
|
<script src="/app.js"></script>
|
|
</body>
|
|
</html>
|