64 lines
11 KiB
HTML
64 lines
11 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>设备首页 · Multi SimAdmin Island</title><link rel="stylesheet" href="/styles.css">
|
||
</head>
|
||
<body>
|
||
<div class="island-bg" aria-hidden="true"></div>
|
||
<div id="appShell" class="app-shell">
|
||
<aside class="desktop-sidebar" aria-label="主导航">
|
||
<a class="brand" href="#" data-view="home"><span>🏝️</span><b>SIM 岛</b></a>
|
||
<nav class="side-nav">
|
||
<button type="button" data-view="home" aria-current="page">⌂ <span>设备首页</span></button>
|
||
<button type="button" data-view="detail">◉ <span>设备详情</span></button>
|
||
<button type="button" data-view="rawpage">▣ <span>原始页面</span></button>
|
||
<button type="button" data-view="api">⌁ <span>API 工作台</span></button>
|
||
</nav>
|
||
<div class="sidebar-foot"><span>本地配置</span><code id="configPath">config.json</code></div>
|
||
</aside>
|
||
<div class="app-content">
|
||
<header class="sim-topbar">
|
||
<div><p class="eyebrow">MULTI SIMADMIN</p><h1 id="pageHeading">设备首页</h1><p id="pageSubtitle">集中巡检你的 SimAdmin 设备</p></div>
|
||
<div class="hero-actions"><button id="refreshBtn" class="animal-btn default-btn" type="button">刷新状态</button><button id="addInstanceBtn" class="animal-btn primary-btn" type="button">+ 添加设备</button></div>
|
||
</header>
|
||
<div id="persistentError" class="persistent-message error" role="alert" hidden><span id="persistentErrorText"></span><button id="dismissError" type="button">关闭</button></div>
|
||
<div id="staleBanner" class="persistent-message warn" role="status" hidden></div>
|
||
<main class="sim-main">
|
||
<section id="homeView" class="view active home-view" aria-labelledby="pageHeading">
|
||
<div id="initialLoading" class="state-card" role="status">正在读取本地配置与设备状态…</div>
|
||
<div id="fatalState" class="state-card error" role="alert" hidden><h2>应用无法初始化</h2><p id="fatalText"></p><button id="retryInit" class="animal-btn primary-btn" type="button">重试</button></div>
|
||
<section id="homeContent" hidden>
|
||
<div class="fleet-overview island-card"><div><h2>设备卡片墙</h2><p>状态、资产与连接信息一览</p></div><div id="fleetStats" class="wallet-row"></div></div>
|
||
<div class="home-toolbar island-card">
|
||
<label for="instanceSearch">搜索设备</label><input id="instanceSearch" type="search" placeholder="名称、ID、标签、地址、ICCID…" autocomplete="off">
|
||
<label for="sortSelect">排序</label><select id="sortSelect"><option value="name">名称</option><option value="status">状态</option><option value="latency">延迟</option></select>
|
||
<button id="densityBtn" class="animal-btn default-btn" type="button" aria-pressed="false">紧凑密度</button>
|
||
<nav class="status-filters" id="statusFilters" aria-label="设备状态筛选">
|
||
<button type="button" data-filter="all" aria-pressed="true">全部</button><button type="button" data-filter="online" aria-pressed="false">在线</button><button type="button" data-filter="auth" aria-pressed="false">需登录</button><button type="button" data-filter="offline" aria-pressed="false">离线</button><button type="button" data-filter="unknown" aria-pressed="false">未知</button>
|
||
</nav>
|
||
</div>
|
||
<section id="homeDeviceGrid" class="home-device-grid" aria-label="设备卡片列表"></section>
|
||
</section>
|
||
</section>
|
||
<section id="detailView" class="view detail-view" aria-label="设备详情">
|
||
<header class="workspace-hero island-card"><div><p id="activeKicker" class="eyebrow">DEVICE DETAIL</p><h2 id="activeName">设备详情</h2><p id="activeMeta"></p></div><div class="hero-actions"><button id="backToFleetBtn" class="animal-btn default-btn" type="button">返回首页</button><button id="editActiveBtn" class="animal-btn default-btn" type="button">编辑设备</button><button id="loginBtn" class="animal-btn default-btn" type="button">登录/刷新会话</button><a id="openExternal" class="animal-btn default-btn" href="#" target="_blank" rel="noopener noreferrer">原站打开</a></div></header>
|
||
<section class="detail-layout"><section class="signal-board island-card"><h3>实时状态</h3><div id="signalPanel" class="signal-grid"></div></section><section id="overview" class="nook-metrics" aria-label="关键指标"></section><section class="island-card detail-board"><h3>设备详情</h3><div id="detailDeviceGrid" class="device-detail-grid"></div></section><section class="island-card detail-actions-card"><h3>功能入口</h3><div id="detailActions" class="detail-actions"></div></section></section>
|
||
</section>
|
||
<section id="rawpageView" class="view rawpage-view" aria-label="原始管理页"><div class="frame-toolbar island-card"><button type="button" class="animal-btn default-btn" data-view="detail">返回详情</button><span id="frameHint">若目标站禁止 iframe,请使用“原站打开”。</span></div><iframe id="frame" class="frame" title="SimAdmin 原始管理页面" hidden></iframe></section>
|
||
<section id="apiView" class="view api-layout" aria-label="API 工作台">
|
||
<aside class="api-catalog island-card"><h2>接口目录</h2><label for="endpointSearch">搜索接口</label><input id="endpointSearch" type="search" placeholder="搜索 endpoint"><div id="endpointList" class="endpoint-list"></div></aside>
|
||
<section class="api-console island-card"><div class="console-toolbar"><label for="methodSelect">方法</label><select id="methodSelect"><option>GET</option><option>POST</option><option>PUT</option><option>PATCH</option><option>DELETE</option></select><label for="endpointInput">路径</label><input id="endpointInput" value="/api/device" spellcheck="false"><button id="runEndpoint" class="animal-btn primary-btn" type="button">发送请求</button></div><div id="writeWarning" class="danger-warning" role="alert" hidden>写操作可能改变设备状态。发送前将创建一次性确认令牌。</div><label for="requestBody">JSON 请求体(GET 不发送请求体)</label><textarea id="requestBody" class="request-body" placeholder='{"enabled":true}'></textarea><div class="output-tools"><button id="outputPretty" type="button" aria-pressed="true">Pretty</button><button id="outputRaw" type="button" aria-pressed="false">Raw</button><button id="copyOutput" type="button">复制结果</button></div><pre id="rawOutput" class="raw-output">选择接口不会自动发送。确认设备和参数后点击“发送请求”。</pre></section>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
<nav class="mobile-nav" aria-label="移动端主导航"><button type="button" data-view="home" aria-current="page">⌂<span>首页</span></button><button type="button" data-view="detail">◉<span>详情</span></button><button type="button" data-view="rawpage">▣<span>原页</span></button><button type="button" data-view="api">⌁<span>API</span></button></nav>
|
||
</div>
|
||
<dialog id="loginDialog" aria-labelledby="loginTitle"><form method="dialog" id="loginForm" class="dialog-card"><h2 id="loginTitle">登录 SimAdmin</h2><p>密码仅发送至本地聚合服务。</p><label for="passwordInput">管理员密码</label><input id="passwordInput" type="password" autocomplete="current-password"><p id="loginError" class="form-error" role="alert" hidden></p><menu><button type="button" data-dialog-cancel="loginDialog" class="animal-btn default-btn">取消</button><button id="submitLogin" value="default" class="animal-btn primary-btn">登录</button></menu></form></dialog>
|
||
<dialog id="instanceDialog" aria-labelledby="instanceDialogTitle"><form method="dialog" id="instanceForm" class="dialog-card"><h2 id="instanceDialogTitle">添加设备</h2><input type="hidden" id="instanceOriginalId"><label for="instanceIdInput">设备 ID</label><input id="instanceIdInput" required pattern="[a-zA-Z0-9_.-]+"><label for="instanceNameInput">显示名称</label><input id="instanceNameInput" required><label for="instanceUrlInput">设备地址</label><input id="instanceUrlInput" required type="url"><label for="instanceDescInput">描述</label><textarea id="instanceDescInput"></textarea><label for="instanceTagsInput">标签(逗号分隔)</label><input id="instanceTagsInput"><fieldset id="passwordActions"><legend>保存密码</legend><label><input id="passwordPreserve" type="radio" name="passwordAction" value="preserve" checked> 保留现有密码</label><label><input id="passwordSet" type="radio" name="passwordAction" value="set"> 设置新密码</label><label><input id="passwordClear" type="radio" name="passwordAction" value="clear"> 清除密码</label></fieldset><label id="newPasswordLabel" for="instancePasswordInput" hidden>新密码<input id="instancePasswordInput" type="password" autocomplete="new-password"></label><label id="clearPasswordLabel" class="confirm-check" hidden><input id="clearPasswordConfirm" type="checkbox"> 我确认清除已保存密码</label><p id="instanceFormError" class="form-error" role="alert" hidden></p><menu><button type="button" data-dialog-cancel="instanceDialog" class="animal-btn default-btn">取消</button><button id="deleteInstanceBtn" type="button" class="animal-btn danger-btn" hidden>删除设备</button><button id="saveInstanceBtn" value="default" class="animal-btn primary-btn">保存</button></menu></form></dialog>
|
||
<dialog id="deleteDialog" aria-labelledby="deleteDialogTitle"><form method="dialog" class="dialog-card"><h2 id="deleteDialogTitle">确认删除设备</h2><div id="deleteDetails" class="delete-details"></div><p>此操作将立即写入本地配置,且不可撤销。</p><p id="deleteError" class="form-error" role="alert" hidden></p><menu><button type="button" data-dialog-cancel="deleteDialog" class="animal-btn default-btn">取消</button><button id="confirmDeleteBtn" value="default" class="animal-btn danger-primary">确认删除</button></menu></form></dialog>
|
||
<dialog id="apiDeleteDialog" aria-labelledby="apiDeleteTitle"><form method="dialog" class="dialog-card"><h2 id="apiDeleteTitle">确认发送写操作</h2><p id="apiDeleteDetails"></p><pre id="apiDeleteBody" class="raw-output"></pre><p>该请求将改变设备状态,请核对设备、方法、路径和请求体。</p><menu><button type="button" data-dialog-cancel="apiDeleteDialog" class="animal-btn default-btn">取消</button><button id="confirmApiDelete" value="default" class="animal-btn danger-primary">确认并发送</button></menu></form></dialog>
|
||
<div id="toast" class="toast" aria-live="polite" role="status" hidden></div>
|
||
<script src="/app.js" type="module"></script>
|
||
</body></html>
|