Files
sub2api-add/plugins/subscription-admin/ui/index.html
T
Qiufeng 5feae3ad41
Business Plugins CI / check (plugin-admin) (push) Successful in 3m13s
Business Plugins CI / check (subscription-admin) (push) Successful in 1m41s
chore: initialize standalone business plugin repository
2026-08-27 23:36:08 +08:00

123 lines
7.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">
<meta name="color-scheme" content="light dark">
<title>订阅管理插件</title>
<link rel="stylesheet" href="__PLUGIN_BASE_PATH__/styles.css">
</head>
<body data-base-path="__PLUGIN_BASE_PATH__">
<main class="shell">
<section id="login-view" class="auth-panel" aria-labelledby="login-title">
<div class="eyebrow">SUB2API EXTENSION</div>
<h1 id="login-title">订阅管理</h1>
<p class="muted">使用 Sub2API 管理员账号登录。普通用户没有访问权限。</p>
<form id="login-form" class="stack" autocomplete="on">
<label>
<span>管理员邮箱</span>
<input name="email" type="email" autocomplete="username" required maxlength="254">
</label>
<label>
<span>密码</span>
<input name="password" type="password" autocomplete="current-password" required maxlength="200">
</label>
<fieldset id="captcha-panel" class="captcha-panel" hidden>
<legend id="captcha-label">安全验证</legend>
<p id="captcha-help" class="muted"></p>
<label>
<span>验证结果</span>
<textarea name="captcha_token" rows="3" maxlength="8192" spellcheck="false" autocomplete="off"></textarea>
</label>
<label id="captcha-randstr-row" hidden>
<span>验证随机串</span>
<input name="captcha_randstr" maxlength="512" autocomplete="off">
</label>
</fieldset>
<button class="primary" type="submit">登录</button>
<p id="login-error" class="error" role="alert" hidden></p>
</form>
</section>
<section id="app-view" hidden>
<header class="topbar">
<div>
<div class="eyebrow">SUB2API EXTENSION</div>
<h1>订阅管理</h1>
</div>
<div class="top-actions">
<span id="operator" class="operator"></span>
<button id="logout" class="secondary" type="button">退出</button>
</div>
</header>
<nav class="tabs" aria-label="插件页面">
<button class="tab active" data-view="overview" type="button">概览</button>
<button class="tab" data-view="plans" type="button">套餐</button>
<button class="tab" data-view="subscriptions" type="button">用户订阅</button>
<button class="tab" data-view="audit" type="button">操作记录</button>
<button class="tab" data-view="settings" type="button">设置</button>
</nav>
<p id="app-error" class="error" role="alert" hidden></p>
<section id="view-overview" class="view stack">
<div class="section-heading"><div><h2>连接概览</h2><p class="muted">Core 是套餐、余额和订阅账本的唯一来源。</p></div><button id="refresh-all" class="secondary" type="button">刷新数据</button></div>
<div class="metric-grid">
<article class="metric"><span>插件状态</span><strong class="status ok">运行中</strong><small>独立服务 · 只读模式</small></article>
<article class="metric"><span>Core 连接</span><strong id="core-status" class="status">检查中</strong><small id="sync-time">尚未同步</small></article>
<article class="metric"><span>可售套餐</span><strong id="plan-count">-</strong><small>来自 Core 套餐目录</small></article>
<article class="metric"><span>订阅实例</span><strong id="subscription-count">-</strong><small>当前分页结果</small></article>
<article class="metric"><span>用户余额</span><strong id="user-balance">-</strong><small>选择用户后显示 Core 余额</small></article>
</div>
<form id="balance-form" class="filter-row balance-form">
<label><span>查询用户余额</span><input name="user_id" inputmode="numeric" pattern="[1-9][0-9]*" placeholder="用户 ID" required></label>
<button class="secondary" type="submit">查询余额</button>
</form>
<div class="notice"><strong>只读试验版</strong><span>余额购买、续费、撤销和外部支付尚未启用。页面不会提交任何写操作。</span></div>
</section>
<section id="view-plans" class="view" hidden>
<div class="section-heading"><div><h2>套餐目录</h2><p class="muted">展示 Core 当前返回的价格、额度和覆盖分组。</p></div><button class="secondary reload" data-target="plans" type="button">刷新</button></div>
<div id="plans-list" class="card-list"></div>
</section>
<section id="view-subscriptions" class="view" hidden>
<div class="section-heading"><div><h2>用户订阅</h2><p class="muted">每个订阅实例独立展示,支持同档位多实例。</p></div><button class="secondary reload" data-target="subscriptions" type="button">刷新</button></div>
<form id="subscription-filter" class="filter-row">
<label><span>用户 ID</span><input name="user_id" inputmode="numeric" pattern="[0-9]*"></label>
<label><span>状态</span><select name="status"><option value="">全部</option><option value="active">active</option><option value="expired">expired</option><option value="revoked">revoked</option></select></label>
<button class="secondary" type="submit">筛选</button>
</form>
<div id="subscriptions-list" class="table-wrap"></div>
<div id="subscription-pagination" class="pagination" hidden>
<span id="subscription-page-info" class="muted"></span>
<div><button id="subscription-prev" class="secondary" type="button">上一页</button><button id="subscription-next" class="secondary" type="button">下一页</button></div>
</div>
</section>
<section id="view-audit" class="view" hidden>
<div class="section-heading"><div><h2>操作记录</h2><p class="muted">仅记录插件会话和只读查询结果,不记录 token 或密码。</p></div><button class="secondary reload" data-target="audit" type="button">刷新</button></div>
<div id="audit-list" class="table-wrap"></div>
</section>
<section id="view-settings" class="view stack" hidden>
<div class="section-heading"><div><h2>插件设置</h2><p class="muted">部署参数由服务端环境变量管理,页面不提供 secret 编辑入口。</p></div></div>
<div class="settings-list">
<div><span>运行模式</span><strong>只读 V1</strong></div>
<div><span>Core API allowlist</span><strong>10 个固定端点</strong></div>
<div><span>会话存储</span><strong>进程内存(重启后需重新登录)</strong></div>
<div><span>Core 凭据</span><strong id="credential-status">检查中</strong></div>
<div><span>余额购买 / 续费 / 撤销</span><strong class="status">未启用</strong></div>
</div>
</section>
</section>
</main>
<dialog id="detail-dialog" class="detail-dialog">
<div class="dialog-heading"><h2>订阅详情</h2><button id="close-detail" class="icon-button" type="button" aria-label="关闭">×</button></div>
<pre id="detail-content"></pre>
</dialog>
<script src="__PLUGIN_BASE_PATH__/app.js" defer></script>
</body>
</html>