Files
multi-simadmin/public/index.html
T
2026-07-07 23:04:32 +08:00

167 lines
8.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Multi SimAdmin Island</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<div class="island-bg" aria-hidden="true">
<span class="cloud cloud-a"></span>
<span class="cloud cloud-b"></span>
<span class="leaf leaf-a"></span>
<span class="leaf leaf-b"></span>
</div>
<div id="appShell" class="island-shell">
<aside class="nook-sidebar" aria-label="设备岛屿列表">
<header class="island-card sidebar-card pattern-default">
<div class="ribbon compact-ribbon" aria-label="Multi SimAdmin">
<span class="ribbon-back ribbon-back-left"></span>
<span class="ribbon-back ribbon-back-right"></span>
<span class="ribbon-fold ribbon-fold-left"></span>
<span class="ribbon-fold ribbon-fold-right"></span>
<span class="ribbon-front"></span>
<span class="ribbon-text">SimAdmin 岛屿</span>
</div>
<p class="sidebar-subtitle">像 NookPhone 一样管理每个 CPE 小岛</p>
<div class="sidebar-actions">
<button id="homeBtn" class="animal-btn default-btn" type="button">返回首页</button>
<button id="refreshBtn" class="animal-btn primary-btn" type="button">刷新状态</button>
</div>
<button id="addInstanceBtn" class="animal-btn primary-btn block-btn" type="button"> 添加设备地址</button>
</header>
<section class="wallet-row" id="fleetStats"></section>
<label class="search-pill" aria-label="搜索设备">
<span></span>
<input id="instanceSearch" type="search" placeholder="搜索设备、标签、地址…" autocomplete="off" />
</label>
<nav class="island-tabs" id="statusFilters" aria-label="状态筛选">
<button class="tab-leaf active" data-filter="all">全部</button>
<button class="tab-leaf" data-filter="online">在线</button>
<button class="tab-leaf" data-filter="auth">需登录</button>
<button class="tab-leaf" data-filter="offline">离线</button>
</nav>
<div id="instances" class="island-list"></div>
<footer class="config-note">
<span>本地配置</span>
<code id="configPath">config.json</code>
</footer>
</aside>
<main class="nook-workspace">
<header class="workspace-hero island-card pattern-app-teal">
<div>
<p id="activeKicker" class="eyebrow">NO ISLAND SELECTED</p>
<h1 id="activeName">选择一个 SimAdmin 小岛</h1>
<p id="activeMeta">查看设备、SIM、网络、短信、eSIM、OTA 与原始管理页面。</p>
</div>
<div class="hero-actions">
<button id="loginBtn" type="button" class="animal-btn default-btn" disabled>登录/刷新会话</button>
<a id="openExternal" href="#" target="_blank" rel="noreferrer" class="animal-btn default-btn disabled">原站打开</a>
</div>
</header>
<nav class="phone-dock" aria-label="主视图">
<button class="phone-app active app-teal" data-view="dashboard"><span>🏝️</span><b>总览</b></button>
<button class="phone-app app-yellow" data-view="api"><span>{}</span><b>接口</b></button>
<button class="phone-app app-blue" data-view="rawpage"><span></span><b>原页</b></button>
<button id="densityBtn" class="phone-app app-green" type="button"><span></span><b>密度</b></button>
</nav>
<section id="dashboardView" class="view active dashboard-view">
<section class="signal-board island-card pattern-app-yellow">
<div class="section-ribbon color-app-yellow">小岛告示牌</div>
<div id="signalPanel" class="signal-grid"></div>
</section>
<section id="overview" class="nook-metrics"></section>
<section class="module-board island-card pattern-default">
<div class="board-head">
<div class="section-ribbon color-app-green">功能应用</div>
<div id="moduleTabs" class="module-tabs"></div>
</div>
<div id="featureGrid" class="app-grid"></div>
</section>
</section>
<section id="apiView" class="view api-layout">
<aside class="api-catalog island-card pattern-purple">
<div class="section-ribbon color-purple">API 地图</div>
<div id="endpointList" class="endpoint-list"></div>
</aside>
<section class="api-console island-card pattern-default">
<div class="console-toolbar">
<select id="methodSelect" aria-label="请求方法">
<option>GET</option>
<option>POST</option>
<option>DELETE</option>
</select>
<input id="endpointInput" value="/api/device" spellcheck="false" aria-label="接口路径" />
<button id="runEndpoint" class="animal-btn primary-btn" type="button">发送</button>
</div>
<textarea id="requestBody" class="request-body" placeholder='POST/DELETE 请求体 JSON,例如 {"enabled":true}'></textarea>
<pre id="rawOutput" class="raw-output">选择设备后可调用统一代理接口。</pre>
</section>
</section>
<section id="rawpageView" class="view rawpage-view">
<div class="frame-toolbar island-card pattern-app-blue">
<span id="frameHint">原始 SimAdmin 页面会在下方显示;若目标站禁止 iframe,请使用“原站打开”。</span>
</div>
<section id="emptyState" class="empty-state island-card pattern-default">
<div class="section-ribbon color-app-pink">等待登岛</div>
<h3>还没有选择设备</h3>
<p>在左侧选择一个小岛后,这里会加载原 SimAdmin 页面。</p>
</section>
<iframe id="frame" class="frame" title="SimAdmin instance" hidden></iframe>
</section>
</main>
</div>
<dialog id="loginDialog">
<form method="dialog" id="loginForm" class="login-card island-card pattern-default">
<div class="section-ribbon color-app-teal">会话通行证</div>
<h3>登录 SimAdmin</h3>
<p>输入该实例管理员密码;只发送到本地聚合服务,不写入浏览器存储。</p>
<input id="passwordInput" type="password" placeholder="管理员密码" autocomplete="current-password" />
<menu>
<button value="cancel" class="animal-btn default-btn">取消</button>
<button id="submitLogin" value="default" class="animal-btn primary-btn">登录</button>
</menu>
</form>
</dialog>
<dialog id="instanceDialog">
<form method="dialog" id="instanceForm" class="instance-form island-card pattern-default">
<div id="instanceFormRibbon" class="section-ribbon color-app-green">添加设备地址</div>
<p class="form-help">配置会立即写入本地 config.json,并更新左侧设备列表。</p>
<input type="hidden" id="instanceOriginalId" />
<label>设备 ID <input id="instanceIdInput" required pattern="[a-zA-Z0-9_.-]+" placeholder="home-cpe" /></label>
<label>显示名称 <input id="instanceNameInput" required placeholder="客厅 CPE" /></label>
<label>设备地址 <input id="instanceUrlInput" required type="url" placeholder="http://192.168.1.1" /></label>
<label>描述 <textarea id="instanceDescInput" placeholder="位置、用途或备注"></textarea></label>
<label>标签 <input id="instanceTagsInput" placeholder="home, 5g, backup" /></label>
<label>管理员密码 <input id="instancePasswordInput" type="password" placeholder="留空表示无密码或清除已保存密码" autocomplete="new-password" /></label>
<menu class="form-menu">
<button value="cancel" 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>
<div id="toast" class="toast" hidden></div>
<script src="/app.js" type="module"></script>
</body>
</html>