Files
sms_forwarding/public/admin.html
T
2026-06-24 22:39:12 +08:00

267 lines
10 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">
<title>SMS Gateway 管理台</title>
<link rel="stylesheet" href="/assets/admin.css">
</head>
<body>
<header class="top-nav">
<div class="top-nav__inner">
<a class="brand" href="/admin" aria-label="SMS Gateway 管理台">
<span class="brand__mark" aria-hidden="true"></span>
<span>SMS Gateway</span>
</a>
<nav class="nav-links" aria-label="管理导航">
<a href="#status">状态</a>
<a href="#inbox">收件箱</a>
<a href="#send">短信</a>
<a href="#console">AT 控制台</a>
<a href="#logs">日志</a>
</nav>
<div class="top-nav__actions">
<button class="button button--secondary" id="pushSettingsButton" type="button">推送渠道</button>
<button class="button button--secondary" id="refreshButton" type="button">刷新状态</button>
</div>
</div>
</header>
<main>
<section class="hero-band" id="status">
<div class="container hero-grid">
<div class="hero-copy">
<span class="badge badge--coral" id="readyBadge">连接检测中</span>
<h1>短信网关管理台</h1>
<p>集中查看 ML307A 模组状态、发送短信、执行 AT 命令,并检查运行日志。</p>
</div>
<div class="product-panel" aria-label="运行摘要">
<div class="panel-header">
<span>runtime</span>
<strong id="panelStatus">loading</strong>
</div>
<dl class="runtime-list">
<div>
<dt>模组</dt>
<dd id="modelName">--</dd>
</div>
<div>
<dt>运营商</dt>
<dd id="operator">--</dd>
</div>
<div>
<dt>信号</dt>
<dd id="signalQuality">--</dd>
</div>
<div>
<dt>运行时长</dt>
<dd id="uptime">--</dd>
</div>
</dl>
</div>
</div>
</section>
<section class="section-band section-band--soft">
<div class="container">
<div class="section-heading">
<h2>当前状态</h2>
<p>这些数据来自模组实时 AT 查询,刷新时会串行读取,避免同时发送多条 AT 命令。</p>
</div>
<div class="status-grid">
<article class="feature-card">
<span class="eyebrow">connection</span>
<h3 id="connectionState">--</h3>
<p id="connectionHint">等待状态刷新。</p>
</article>
<article class="feature-card">
<span class="eyebrow">signal</span>
<h3 id="signalValue">--</h3>
<p id="signalHint">RSSI 与误码率将在刷新后显示。</p>
</article>
<article class="feature-card">
<span class="eyebrow">module</span>
<h3 id="moduleModel">--</h3>
<p id="moduleVersion">--</p>
</article>
<article class="feature-card">
<span class="eyebrow">sim</span>
<h3 id="iccid">--</h3>
<p>ICCID 查询来自当前串口模组。</p>
</article>
</div>
</div>
</section>
<section class="section-band">
<div class="container" id="inbox">
<div class="section-heading">
<div>
<span class="badge badge--soft">inbox</span>
<h2>收到的短信</h2>
</div>
<button class="button button--secondary" id="messagesButton" type="button">刷新短信</button>
</div>
<div class="inbox-panel">
<div class="inbox-meta">
<span id="messageCount">最近 0 条</span>
<span>新短信会自动出现在这里</span>
</div>
<div class="message-list" id="messageList" aria-live="polite">
<p class="empty-state empty-state--light">暂无收到的短信。</p>
</div>
</div>
</div>
</section>
<section class="section-band section-band--soft">
<div class="container workbench-grid">
<section class="form-card" id="send">
<div class="section-heading section-heading--compact">
<h2>发送短信</h2>
<p>使用当前 PDU 模式发送短信,提交后等待模组返回发送结果。</p>
</div>
<form id="smsForm" class="stack-form">
<label>
<span>目标号码</span>
<input class="text-input" type="tel" name="phone" autocomplete="tel" placeholder="13800138000" required>
</label>
<label>
<span>短信内容</span>
<textarea class="text-input text-area" name="message" rows="6" placeholder="输入要发送的短信内容" required></textarea>
</label>
<div class="form-actions">
<button class="button button--primary" type="submit">发送短信</button>
<p class="form-status" id="smsStatus" role="status"></p>
</div>
</form>
</section>
<section class="console-card" id="console">
<div class="panel-header">
<span>AT console</span>
<strong id="consoleState">idle</strong>
</div>
<form id="atForm" class="at-form">
<input class="text-input text-input--dark" name="command" value="AT+CSQ" autocomplete="off" spellcheck="false" required>
<button class="button button--secondary-on-dark" type="submit">执行</button>
</form>
<pre class="console-output" id="atOutput">等待命令...</pre>
</section>
</div>
</section>
<section class="section-band section-band--dark" id="logs">
<div class="container">
<div class="dark-heading">
<div>
<span class="badge badge--dark">logs</span>
<h2>运行日志</h2>
</div>
<button class="button button--secondary-on-dark" id="logsButton" type="button">刷新日志</button>
</div>
<div class="log-window" id="logWindow" aria-live="polite">
<p class="empty-state">等待日志加载。</p>
</div>
</div>
</section>
</main>
<div class="modal" id="pushModal" aria-hidden="true">
<div class="modal__backdrop" data-close-push-modal></div>
<section class="modal__dialog" role="dialog" aria-modal="true" aria-labelledby="pushModalTitle">
<div class="modal__header">
<div>
<span class="badge badge--soft">push</span>
<h2 id="pushModalTitle">推送渠道设置</h2>
</div>
<button class="icon-button" id="pushModalClose" type="button" aria-label="关闭推送渠道设置">×</button>
</div>
<div class="push-settings">
<aside class="channel-list-panel" aria-label="推送渠道列表">
<div class="panel-header panel-header--light">
<span>channels</span>
<button class="button button--secondary button--compact" id="pushAddButton" type="button">新增</button>
</div>
<div class="channel-list" id="pushChannelList"></div>
</aside>
<form class="channel-form" id="pushChannelForm">
<fieldset class="form-fieldset" id="pushFormFields" disabled>
<div class="channel-form__grid">
<label class="switch-row">
<input type="checkbox" name="enabled">
<span>启用通道</span>
</label>
<label>
<span>通道名称</span>
<input class="text-input" type="text" name="name" maxlength="80" placeholder="钉钉通知">
</label>
<label>
<span>推送类型</span>
<select class="text-input select-input" name="type">
<option value="dingtalk">钉钉机器人</option>
<option value="feishu">飞书机器人</option>
<option value="telegram">Telegram Bot</option>
<option value="pushplus">PushPlus</option>
<option value="serverchan">Server酱</option>
<option value="post_json">POST JSON</option>
<option value="bark">Bark</option>
<option value="get">GET</option>
<option value="custom">自定义 POST</option>
</select>
</label>
<label class="field-row field-row--wide" data-push-field="url">
<span id="pushUrlLabel">Webhook URL</span>
<input class="text-input" type="text" name="url" autocomplete="off">
</label>
<label class="field-row field-row--wide" data-push-field="secret">
<span id="pushSecretLabel">加签密钥</span>
<input class="text-input" type="password" name="secret" autocomplete="new-password">
</label>
<label class="field-row" data-push-field="key1">
<span id="pushKey1Label">Key1</span>
<input class="text-input" type="text" name="key1" autocomplete="off">
</label>
<label class="field-row" data-push-field="key2">
<span id="pushKey2Label">Key2</span>
<input class="text-input" type="text" name="key2" autocomplete="off">
</label>
<label class="field-row field-row--wide" data-push-field="customBody">
<span>自定义请求体 JSON</span>
<textarea class="text-input text-area text-area--code" name="customBody" rows="7" spellcheck="false"></textarea>
</label>
</div>
</fieldset>
<div class="form-actions channel-form__actions">
<button class="button button--primary" id="pushSaveButton" type="submit">保存设置</button>
<button class="button button--secondary" id="pushTestButton" type="button">发送测试</button>
<button class="button button--danger" id="pushDeleteButton" type="button">删除通道</button>
<p class="form-status" id="pushStatus" role="status"></p>
</div>
</form>
</div>
</section>
</div>
<footer class="footer">
<div class="container footer__inner">
<span class="brand brand--footer"><span class="brand__mark" aria-hidden="true"></span> SMS Gateway</span>
<span>Basic Auth protected management surface</span>
</div>
</footer>
<script src="/assets/admin.js" type="module"></script>
</body>
</html>