| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>DoTouch.AI 管理后台</title>
- <link rel="stylesheet" href="../web-v1.1.0/style.css">
- <style>
- .console { display:flex; min-height:100vh; }
- .sidebar { width:236px; flex-shrink:0; background:var(--card); border-right:1px solid var(--border); padding:20px 14px; position:sticky; top:0; height:100vh; display:flex; flex-direction:column; }
- .sidebar .logo { padding:0 10px 18px; border-bottom:1px solid var(--border); }
- .sidebar .logo svg { height:34px; }
- .side-nav { margin-top:14px; flex:1; }
- .side-nav a { display:flex; align-items:center; gap:10px; padding:11px 12px; border-radius:10px; color:var(--muted); font-size:14px; margin-bottom:4px; cursor:pointer; }
- .side-nav a:hover { color:var(--text); background:rgba(124,92,255,.08); }
- .side-nav a.active { color:var(--text); background:rgba(124,92,255,.15); font-weight:600; }
- .side-nav a .ico { width:20px; text-align:center; }
- .side-user { border-top:1px solid var(--border); padding:14px 12px 6px; }
- .side-user .name { font-size:13px; font-weight:700; }
- .side-user .role-tag { display:inline-block; font-size:10.5px; color:var(--gold); background:rgba(255,194,77,.1); border:1px solid rgba(255,194,77,.3); padding:1px 8px; border-radius:999px; margin-top:4px; }
- .main { flex:1; min-width:0; padding:26px 32px 60px; }
- .main-head { display:flex; justify-content:space-between; align-items:center; margin-bottom:24px; flex-wrap:wrap; gap:12px; }
- .main-head h1 { font-size:22px; font-weight:800; }
- .main-head .sub { color:var(--muted); font-size:13px; margin-top:3px; }
- .tab-panel { display:none; }
- .tab-panel.active { display:block; }
- .stat-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:16px; }
- .stat-card { background:var(--card); border:1px solid var(--border); border-radius:14px; padding:20px; }
- .stat-card .lbl { font-size:12px; color:var(--muted); }
- .stat-card .val { font-size:26px; font-weight:800; margin-top:6px; }
- .stat-card .val.green { color:var(--green-l); }
- .stat-card .val.purple { color:var(--purple-l); }
- .stat-card .val.gold { color:var(--gold); }
- .stat-card .sub2 { font-size:11.5px; color:var(--muted); margin-top:4px; }
- .bar-chart { display:flex; align-items:flex-end; gap:10px; height:130px; padding:14px 6px 0; }
- .bar-col { flex:1; display:flex; flex-direction:column; align-items:center; gap:6px; }
- .bar { width:70%; max-width:34px; border-radius:6px 6px 2px 2px; background:linear-gradient(180deg,var(--green),rgba(0,229,160,.25)); min-height:6px; }
- .bar-lbl { font-size:10.5px; color:var(--muted); }
- .sec-title { font-size:15px; font-weight:700; margin:26px 0 12px; display:flex; justify-content:space-between; align-items:center; }
- .sec-title a { font-size:12.5px; color:var(--purple-l); }
- .filter-bar { display:flex; gap:10px; flex-wrap:wrap; align-items:center; margin-bottom:16px; }
- .search-box { flex:1; min-width:200px; background:var(--card); border:1px solid var(--border); border-radius:10px; padding:10px 16px; color:var(--text); font-size:13.5px; font-family:inherit; outline:none; }
- .search-box:focus { border-color:var(--purple); }
- .filter-tag { border:1px solid var(--border); background:var(--card); color:var(--muted); border-radius:999px; padding:7px 15px; font-size:12.5px; cursor:pointer; font-family:inherit; }
- .filter-tag.active { border-color:var(--purple); color:#fff; background:rgba(124,92,255,.2); }
- .op-btn { font-size:12px; padding:4px 10px; border-radius:7px; border:1px solid var(--border); background:var(--card2); color:var(--muted); cursor:pointer; margin-right:6px; font-family:inherit; }
- .op-btn:hover { color:var(--text); border-color:var(--purple); }
- .op-btn.danger:hover { border-color:#FF6B6B; color:#FF8A8A; }
- .status-badge { font-size:11px; padding:2px 10px; border-radius:999px; white-space:nowrap; }
- .status-badge.active { color:var(--green-l); background:rgba(0,229,160,.1); border:1px solid rgba(0,229,160,.3); }
- .status-badge.disabled { color:var(--muted); background:rgba(154,163,192,.1); border:1px solid rgba(154,163,192,.3); }
- .status-badge.pending { color:var(--gold); background:rgba(255,194,77,.1); border:1px solid rgba(255,194,77,.3); }
- .pager { display:flex; justify-content:flex-end; gap:8px; margin-top:14px; align-items:center; font-size:12.5px; color:var(--muted); }
- .pager button { background:var(--card); border:1px solid var(--border); color:var(--text); padding:6px 12px; border-radius:8px; cursor:pointer; font-family:inherit; }
- .setting-row { display:flex; justify-content:space-between; align-items:center; padding:15px 18px; border-bottom:1px solid var(--border); font-size:13.5px; flex-wrap:wrap; gap:8px; }
- .setting-row:last-child { border-bottom:none; }
- .setting-row .desc { color:var(--muted); font-size:12px; margin-top:3px; }
- .setting-row input, .setting-row select { background:var(--card2); border:1px solid var(--border); border-radius:8px; padding:8px 12px; color:var(--text); font-family:inherit; font-size:13px; outline:none; }
- .switch { position:relative; width:42px; height:24px; flex-shrink:0; }
- .switch input { opacity:0; width:0; height:0; }
- .switch .sl { position:absolute; inset:0; background:var(--card2); border:1px solid var(--border); border-radius:999px; cursor:pointer; transition:.2s; }
- .switch .sl::before { content:""; position:absolute; width:18px; height:18px; border-radius:50%; background:var(--muted); top:2px; left:2px; transition:.2s; }
- .switch input:checked + .sl { background:var(--purple); border-color:var(--purple); }
- .switch input:checked + .sl::before { transform:translateX(18px); background:#fff; }
- .batch-bar { display:flex; gap:10px; align-items:center; background:rgba(124,92,255,.07); border:1px solid rgba(124,92,255,.25); border-radius:12px; padding:12px 16px; margin-bottom:16px; font-size:13px; }
- @media (max-width:860px){ .console{flex-direction:column;} .sidebar{width:100%;height:auto;position:static;} .main{padding:20px;} }
- </style>
- </head>
- <body>
- <div class="dev-note">v1.0.0 · 平台管理后台审阅稿 · 对接 /v1/admin/stats · /v1/admin/users · /v1/admin/models</div>
- <div class="console">
- <aside class="sidebar">
- <div class="logo">
- <svg viewBox="0 0 460 120" xmlns="http://www.w3.org/2000/svg">
- <defs><linearGradient id="ag" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#9B7BFF"/><stop offset="1" stop-color="#5C3DF0"/></linearGradient></defs>
- <g transform="translate(0,6) scale(0.92)"><circle cx="50" cy="50" r="33" stroke="rgba(124,92,255,.3)" stroke-width="1.5" stroke-dasharray="2 7" fill="none"/><g stroke="#00E5A0" stroke-width="1.8" opacity=".55"><line x1="50" y1="50" x2="76" y2="26"/><line x1="50" y1="50" x2="26" y2="76"/><line x1="50" y1="50" x2="78" y2="75"/></g><circle cx="50" cy="50" r="7.5" fill="url(#ag)"/><circle cx="76" cy="26" r="4" fill="#00E5A0"/><circle cx="26" cy="76" r="4" fill="#00E5A0"/><circle cx="78" cy="75" r="4" fill="#00E5A0"/></g>
- <text x="128" y="78" font-size="50" font-weight="700" fill="#E8ECF8" font-family="inherit">DoTouch</text><text x="348" y="78" font-size="50" font-weight="700" fill="url(#ag)" font-family="inherit">.AI</text>
- </svg>
- </div>
- <nav class="side-nav">
- <a class="active" data-tab="overview"><span class="ico">📊</span>运营概览</a>
- <a data-tab="users"><span class="ico">👥</span>用户管理</a>
- <a data-tab="models"><span class="ico">🧠</span>模型管理</a>
- <a data-tab="orders"><span class="ico">💸</span>交易流水</a>
- <a data-tab="quotas"><span class="ico">🚦</span>限额管理</a>
- <a data-tab="settings"><span class="ico">⚙️</span>系统设置</a>
- </nav>
- <div class="side-user">
- <div class="name">平台管理员</div>
- <span class="role-tag">ADMIN</span>
- </div>
- </aside>
- <main class="main">
- <div class="main-head">
- <div>
- <h1>运营概览</h1>
- <div class="sub">DoTouch.AI 平台数据 · 2026-08-08</div>
- </div>
- <a class="btn btn-primary btn-sm" href="../web-v1.1.0/index.html" style="font-size:12.5px;">← 返回官网</a>
- </div>
- <!-- ══ Tab 1: 概览 ══ -->
- <div class="tab-panel active" id="tab-overview">
- <div class="stat-grid">
- <div class="stat-card"><div class="lbl">注册用户</div><div class="val purple">1,284</div><div class="sub2">今日 +37</div></div>
- <div class="stat-card"><div class="lbl">总收入(累计充值)</div><div class="val green"><span class="price-usd" data-usd="8642.50">$8,642.50</span></div><div class="sub2">本月 <span class="price-usd" data-usd="1290">$1,290</span></div></div>
- <div class="stat-card"><div class="lbl">总 Token 消耗</div><div class="val">128.4M</div><div class="sub2">今日 4.2M</div></div>
- <div class="stat-card"><div class="lbl">今日请求</div><div class="val">32,118</div><div class="sub2">成功率 99.2%</div></div>
- </div>
- <div class="sec-title">收入趋势(近 30 天)</div>
- <div class="card">
- <div class="bar-chart">
- <div class="bar-col"><div class="bar" style="height:20%"></div><span class="bar-lbl">7/10</span></div>
- <div class="bar-col"><div class="bar" style="height:32%"></div><span class="bar-lbl">7/15</span></div>
- <div class="bar-col"><div class="bar" style="height:28%"></div><span class="bar-lbl">7/20</span></div>
- <div class="bar-col"><div class="bar" style="height:45%"></div><span class="bar-lbl">7/25</span></div>
- <div class="bar-col"><div class="bar" style="height:38%"></div><span class="bar-lbl">7/30</span></div>
- <div class="bar-col"><div class="bar" style="height:62%"></div><span class="bar-lbl">8/04</span></div>
- <div class="bar-col"><div class="bar" style="height:78%"></div><span class="bar-lbl">8/08</span></div>
- </div>
- </div>
- <div class="sec-title">最近注册</div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>邮箱</th><th>注册时间</th><th>充值</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td class="price">tran.bao@example.com</td><td style="color:var(--muted);">2026-08-08 03:12</td><td class="price"><span class="price-usd" data-usd="5">$5.00</span></td><td><span class="status-badge active">active</span></td></tr>
- <tr><td class="price">le.minh@example.com</td><td style="color:var(--muted);">2026-08-08 02:58</td><td class="price">—</td><td><span class="status-badge active">active</span></td></tr>
- <tr><td class="price">phan.thu@example.com</td><td style="color:var(--muted);">2026-08-08 02:41</td><td class="price"><span class="price-usd" data-usd="10">$10.00</span></td><td><span class="status-badge active">active</span></td></tr>
- </tbody>
- </table>
- </div>
- <div class="sec-title">今日交易</div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>时间</th><th>用户</th><th>类型</th><th>金额</th><th>渠道</th></tr></thead>
- <tbody>
- <tr><td style="color:var(--muted);">03:12</td><td class="price">tran.bao@…</td><td><span class="tag tag-purple">deposit</span></td><td class="price">+<span class="price-usd" data-usd="5">$5.00</span></td><td>MoMo</td></tr>
- <tr><td style="color:var(--muted);">02:41</td><td class="price">phan.thu@…</td><td><span class="tag tag-purple">deposit</span></td><td class="price">+<span class="price-usd" data-usd="10">$10.00</span></td><td>ZaloPay</td></tr>
- <tr><td style="color:var(--muted);">02:30</td><td class="price">nguyen.anh@…</td><td><span class="tag tag-green">usage</span></td><td class="price">-<span class="price-usd" data-usd="0.0032">$0.0032</span></td><td>—</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- <!-- ══ Tab 2: 用户管理 ══ -->
- <div class="tab-panel" id="tab-users">
- <div class="filter-bar">
- <input class="search-box" type="text" placeholder="搜索邮箱 / 用户 ID...">
- <button class="filter-tag active">全部</button>
- <button class="filter-tag">活跃</button>
- <button class="filter-tag">已封禁</button>
- <button class="filter-tag">管理员</button>
- </div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>ID</th><th>邮箱</th><th>角色</th><th>状态</th><th>余额</th><th>注册时间</th><th>操作</th></tr></thead>
- <tbody>
- <tr><td class="price">cmsjc9029</td><td class="price">test@example.com</td><td><span class="role-tag" style="color:var(--gold);">admin</span></td><td><span class="status-badge active">active</span></td><td class="price"><span class="price-usd" data-usd="23.5">$23.50</span></td><td style="color:var(--muted);">2026-08-08</td><td><button class="op-btn">封禁</button><button class="op-btn danger">降级</button></td></tr>
- <tr><td class="price">cmsjd1044</td><td class="price">tran.bao@example.com</td><td><span class="tag tag-gray">user</span></td><td><span class="status-badge active">active</span></td><td class="price"><span class="price-usd" data-usd="5">$5.00</span></td><td style="color:var(--muted);">2026-08-08</td><td><button class="op-btn">封禁</button><button class="op-btn">提权</button></td></tr>
- <tr><td class="price">cmsje2201</td><td class="price">le.minh@example.com</td><td><span class="tag tag-gray">user</span></td><td><span class="status-badge active">active</span></td><td class="price">$0.00</td><td style="color:var(--muted);">2026-08-08</td><td><button class="op-btn">封禁</button><button class="op-btn">提权</button></td></tr>
- <tr><td class="price">cmsjf5517</td><td class="price">spam@example.com</td><td><span class="tag tag-gray">user</span></td><td><span class="status-badge disabled">banned</span></td><td class="price">$0.00</td><td style="color:var(--muted);">2026-08-01</td><td><button class="op-btn">解封</button></td></tr>
- </tbody>
- </table>
- </div>
- <div class="pager"><span>第 1 / 257 页</span><button>‹</button><button>›</button></div>
- </div>
- <!-- ══ Tab 3: 模型管理 ══ -->
- <div class="tab-panel" id="tab-models">
- <div class="batch-bar">
- <b>批量工具:</b>
- <button class="op-btn" style="border-color:rgba(0,229,160,.4);color:var(--green-l);">按上游价 × 0.7 批量定价</button>
- <button class="op-btn" style="border-color:rgba(255,194,77,.4);color:var(--gold);">一键上架全部</button>
- <span style="color:var(--muted);font-size:12px;">共 236 个模型 · 推荐 11 · 待定价 225</span>
- </div>
- <div class="filter-bar">
- <input class="search-box" type="text" placeholder="搜索模型 ID / 供应商...">
- <button class="filter-tag active" data-cat="all">全部 (236)</button>
- <button class="filter-tag" data-cat="chat">对话 (153)</button>
- <button class="filter-tag" data-cat="vision">视觉 (21)</button>
- <button class="filter-tag" data-cat="image">图像 (19)</button>
- <button class="filter-tag" data-cat="speech">语音 (43)</button>
- </div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>模型 ID</th><th>供应商</th><th>分类</th><th>上下文</th><th>输入 / 1M</th><th>输出 / 1M</th><th>状态</th><th>推荐</th><th>操作</th></tr></thead>
- <tbody>
- <tr><td><b>glm-5.2</b></td><td>Zhipu</td><td><span class="tag tag-purple">对话</span></td><td class="price">1M</td><td class="price"><span class="price-usd" data-usd="0.98">$0.98</span></td><td class="price"><span class="price-usd" data-usd="3.08">$3.08</span></td><td><span class="status-badge active">active</span></td><td>⭐</td><td><button class="op-btn">定价</button><button class="op-btn danger">下架</button></td></tr>
- <tr><td><b>deepseek-v4-flash</b></td><td>DeepSeek</td><td><span class="tag tag-green">对话</span></td><td class="price">1M</td><td class="price"><span class="price-usd" data-usd="0.14">$0.14</span></td><td class="price"><span class="price-usd" data-usd="0.28">$0.28</span></td><td><span class="status-badge active">active</span></td><td>⭐</td><td><button class="op-btn">定价</button><button class="op-btn danger">下架</button></td></tr>
- <tr><td><b>deepseek-v4-pro</b></td><td>DeepSeek</td><td><span class="tag tag-gold">对话</span></td><td class="price">1M</td><td class="price"><span class="price-usd" data-usd="0.42">$0.42</span></td><td class="price"><span class="price-usd" data-usd="0.84">$0.84</span></td><td><span class="status-badge active">active</span></td><td>⭐</td><td><button class="op-btn">定价</button><button class="op-btn danger">下架</button></td></tr>
- <tr><td><b>qwen3-max</b></td><td>Alibaba</td><td><span class="tag tag-purple">对话</span></td><td class="price">256K</td><td class="price"><span class="price-usd" data-usd="2.10">$2.10</span></td><td class="price"><span class="price-usd" data-usd="8.40">$8.40</span></td><td><span class="status-badge active">active</span></td><td>⭐</td><td><button class="op-btn">定价</button><button class="op-btn danger">下架</button></td></tr>
- <tr><td><b>kimi-k2.7-code</b></td><td>Moonshot</td><td><span class="tag tag-green">对话</span></td><td class="price">256K</td><td class="price"><span class="price-usd" data-usd="0.70">$0.70</span></td><td class="price"><span class="price-usd" data-usd="2.80">$2.80</span></td><td><span class="status-badge active">active</span></td><td>⭐</td><td><button class="op-btn">定价</button><button class="op-btn danger">下架</button></td></tr>
- <tr><td><b>qwen-image-3.0</b></td><td>Alibaba</td><td><span class="tag tag-purple">图像</span></td><td class="price">—</td><td class="price"><span class="price-usd" data-usd="0.14">$0.14</span>/张</td><td class="price">—</td><td><span class="status-badge pending">pending</span></td><td>—</td><td><button class="op-btn">定价</button><button class="op-btn">上架</button></td></tr>
- <tr><td><b>qwen-tts-2025-05-22</b></td><td>Alibaba</td><td><span class="tag tag-gray">语音</span></td><td class="price">—</td><td class="price"><span class="price-usd" data-usd="0.0014">$0.0014</span>/字符</td><td class="price">—</td><td><span class="status-badge pending">pending</span></td><td>—</td><td><button class="op-btn">定价</button><button class="op-btn">上架</button></td></tr>
- <tr><td><b>… 共 236 个模型(全量已入库,seed 幂等)</b></td><td colspan="8" style="color:var(--muted);font-size:12.5px;">完整清单见 GET /v1/admin/models · 同步上游 POST /v1/admin/models/sync(待接百炼 Key)</td></tr>
- </tbody>
- </table>
- </div>
- <div class="pager"><span>第 1 / 24 页</span><button>‹</button><button>›</button></div>
- </div>
- <!-- ══ Tab 4: 交易流水 ══ -->
- <div class="tab-panel" id="tab-orders">
- <div class="filter-bar">
- <input class="search-box" type="text" placeholder="搜索用户 / 参考 ID...">
- <button class="filter-tag active">全部</button>
- <button class="filter-tag">充值</button>
- <button class="filter-tag">用量扣费</button>
- <button class="filter-tag">退款</button>
- </div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>时间</th><th>用户</th><th>类型</th><th>金额</th><th>参考</th><th>渠道</th></tr></thead>
- <tbody>
- <tr><td style="color:var(--muted);">2026-08-08 03:12</td><td class="price">tran.bao@…</td><td><span class="tag tag-purple">deposit</span></td><td class="price">+<span class="price-usd" data-usd="5">$5.00</span></td><td class="price">stripe_pi_8f3k…</td><td>MoMo</td></tr>
- <tr><td style="color:var(--muted);">2026-08-08 02:41</td><td class="price">phan.thu@…</td><td><span class="tag tag-purple">deposit</span></td><td class="price">+<span class="price-usd" data-usd="10">$10.00</span></td><td class="price">zalopay_9x2m…</td><td>ZaloPay</td></tr>
- <tr><td style="color:var(--muted);">2026-08-08 02:30</td><td class="price">nguyen.anh@…</td><td><span class="tag tag-green">usage</span></td><td class="price">-<span class="price-usd" data-usd="0.0032">$0.0032</span></td><td class="price">req_glm52_88a1</td><td>—</td></tr>
- <tr><td style="color:var(--muted);">2026-08-07 22:30</td><td class="price">nguyen.anh@…</td><td><span class="tag tag-purple">deposit</span></td><td class="price">+<span class="price-usd" data-usd="20">$20.00</span></td><td class="price">stripe_pi_7d2k…</td><td>Stripe</td></tr>
- <tr><td style="color:var(--muted);">2026-08-07 18:02</td><td class="price">nguyen.anh@…</td><td><span class="tag tag-green">usage</span></td><td class="price">-<span class="price-usd" data-usd="0.0084">$0.0084</span></td><td class="price">req_qwen3_41c9</td><td>—</td></tr>
- </tbody>
- </table>
- </div>
- <div class="pager"><span>第 1 / 89 页</span><button>‹</button><button>›</button></div>
- </div>
- <!-- ══ Tab 6: 限额管理 ══ -->
- <div class="tab-panel" id="tab-quotas">
- <div class="filter-bar">
- <input class="search-box" type="text" placeholder="搜索用户 / Key...">
- <button class="filter-tag active">全部</button>
- <button class="filter-tag" style="color:var(--gold);">超限</button>
- <button class="filter-tag" style="color:var(--green-l);">预警中</button>
- <button class="op-btn" style="border-color:rgba(124,92,255,.5);color:var(--purple-l);margin-left:auto;">+ 设置默认限额</button>
- </div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>对象</th><th>类型</th><th>每日限额 (请求/Token/费用)</th><th>当前用量</th><th>状态</th><th>操作</th></tr></thead>
- <tbody>
- <tr><td><b>test-e2e@dotouch.ai</b></td><td><span class="tag tag-purple">账号</span></td><td class="price">— / — / —</td><td class="price">1,284 req · 4.2M tokens · $3.85</td><td><span class="status-badge active">正常</span></td><td><button class="op-btn">配置</button></td></tr>
- <tr><td class="price">production (dt_8e75••••)</td><td><span class="tag tag-gray">API Key</span></td><td class="price">10,000 / 100M / $5</td><td class="price">6,420 req · 82M · $3.85</td><td><span class="status-badge pending">预警中 (82%)</span></td><td><button class="op-btn">配置</button></td></tr>
- <tr><td class="price">staging (dt_cb90••••)</td><td><span class="tag tag-gray">API Key</span></td><td class="price">10,000 / 100M / $5</td><td class="price">2,310 req · 30M · $1.10</td><td><span class="status-badge active">正常</span></td><td><button class="op-btn">配置</button></td></tr>
- <tr><td class="price">local-dev (dt_5f2a••••)</td><td><span class="tag tag-gray">API Key</span></td><td class="price">10,000 / 100M / $5</td><td class="price">10,000 req · 120M · $5.30</td><td><span class="status-badge disabled">超限 (429)</span></td><td><button class="op-btn">配置</button><button class="op-btn danger">解除</button></td></tr>
- </tbody>
- </table>
- </div>
- <div class="pager"><span>第 1 / 12 页</span><button>‹</button><button>›</button></div>
- <div class="sec-title">限额事件(QuotaEvent 审计)</div>
- <div class="table-wrap">
- <table class="data">
- <thead><tr><th>时间</th><th>对象</th><th>类型</th><th>维度</th><th>窗口</th><th>阈值/当前</th><th>动作</th></tr></thead>
- <tbody>
- <tr><td style="color:var(--muted);">2026-08-08 03:47</td><td class="price">local-dev (dt_5f2a••••)</td><td>Key</td><td>requests</td><td>daily</td><td class="price">10,000 / 10,000</td><td><span class="status-badge disabled">block</span></td></tr>
- <tr><td style="color:var(--muted);">2026-08-08 03:40</td><td class="price">production (dt_8e75••••)</td><td>Key</td><td>requests</td><td>daily</td><td class="price">10,000 / 8,000</td><td><span class="status-badge pending">alert</span></td></tr>
- <tr><td style="color:var(--muted);">2026-08-07 22:15</td><td class="price">staging (dt_cb90••••)</td><td>Key</td><td>cost</td><td>daily</td><td class="price">500¢ / 410¢</td><td><span class="status-badge pending">alert</span></td></tr>
- </tbody>
- </table>
- </div>
- <div class="notice" style="margin-top:14px;">💡 接口对接:GET /v1/admin/quotas(全局视图)· PUT /v1/admin/users/:id/limits / keys/:id/limits(覆盖)· GET /v1/admin/quota-events(审计)· 新用户默认不限(需求 v1.0)</div>
- </div>
- <!-- ══ Tab 5: 系统设置 ══ -->
- <div class="tab-panel" id="tab-settings">
- <div class="card" style="padding:0;overflow:hidden;margin-bottom:18px;">
- <div class="sec-title" style="padding:16px 18px 0;margin-top:0;">货币与汇率</div>
- <div class="setting-row"><div><b>美元 → 越南盾</b><div class="desc">充值结算汇率 · 接入实时汇率 API(TODO)</div></div><input type="text" value="25,400" style="width:110px;"></div>
- <div class="setting-row"><div><b>美元 → 人民币</b><div class="desc">展示汇率</div></div><input type="text" value="7.20" style="width:110px;"></div>
- <div class="setting-row"><div><b>实时汇率自动更新</b><div class="desc">接入第三方汇率 API 后启用</div></div><label class="switch"><input type="checkbox"><span class="sl"></span></label></div>
- </div>
- <div class="card" style="padding:0;overflow:hidden;margin-bottom:18px;">
- <div class="sec-title" style="padding:16px 18px 0;margin-top:0;">安全策略</div>
- <div class="setting-row"><div><b>邮箱验证码有效期</b><div class="desc">注册 / 重置密码验证码</div></div><input type="text" value="15 分钟" style="width:110px;"></div>
- <div class="setting-row"><div><b>验证码重发冷却</b></div><input type="text" value="60 秒" style="width:110px;"></div>
- <div class="setting-row"><div><b>登录失败锁定</b><div class="desc">5 次 / 15 分钟</div></div><input type="text" value="5 次" style="width:110px;"></div>
- <div class="setting-row"><div><b>API 限流</b><div class="desc">每 Key 每分钟请求数</div></div><input type="text" value="60" style="width:110px;"></div>
- <div class="setting-row"><div><b>JWT 过期时间</b></div><input type="text" value="7d" style="width:110px;"></div>
- </div>
- <div class="card" style="padding:0;overflow:hidden;margin-bottom:18px;">
- <div class="sec-title" style="padding:16px 18px 0;margin-top:0;">邮件服务(SMTP)</div>
- <div class="setting-row"><div><b>SMTP 主机</b><div class="desc">生产环境必填(当前为 stub,验证码打印到日志)</div></div><input type="text" placeholder="smtp.example.com" style="width:200px;"></div>
- <div class="setting-row"><div><b>发件人</b></div><input type="text" value="noreply@dotouch.ai" style="width:200px;"></div>
- <div class="setting-row"><div><b>SMTP 状态</b></div><span class="status-badge pending">未配置</span></div>
- </div>
- <div class="card" style="padding:0;overflow:hidden;margin-bottom:18px;">
- <div class="sec-title" style="padding:16px 18px 0;margin-top:0;">上游(阿里云百炼)</div>
- <div class="setting-row"><div><b>DASHSCOPE_API_KEY</b><div class="desc">当前为占位符,配置后启用 /admin/models/sync 自动同步</div></div><span class="status-badge pending">待配置</span></div>
- <div class="setting-row"><div><b>基础地址</b></div><input type="text" value="https://dashscope.aliyuncs.com/compatible-mode/v1" style="width:340px;"></div>
- </div>
- <div class="card" style="padding:0;overflow:hidden;">
- <div class="sec-title" style="padding:16px 18px 0;margin-top:0;">支付渠道</div>
- <div class="setting-row"><div><b>Stripe</b><div class="desc">国际卡 / PayPal</div></div><label class="switch"><input type="checkbox" checked><span class="sl"></span></label></div>
- <div class="setting-row"><div><b>MoMo</b><div class="desc">越南本地(需主体或聚合商)</div></div><label class="switch"><input type="checkbox" checked><span class="sl"></span></label></div>
- <div class="setting-row"><div><b>ZaloPay</b></div><label class="switch"><input type="checkbox" checked><span class="sl"></span></label></div>
- <div class="setting-row"><div><b>Alipay</b><div class="desc">国内用户</div></div><label class="switch"><input type="checkbox"><span class="sl"></span></label></div>
- </div>
- </div>
- </main>
- </div>
- <script src="../web-v1.1.0/i18n.js"></script>
- <script>
- document.querySelectorAll('.side-nav a').forEach(a => a.addEventListener('click', () => {
- document.querySelectorAll('.side-nav a').forEach(x => x.classList.remove('active'));
- document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
- a.classList.add('active');
- document.getElementById('tab-' + a.dataset.tab).classList.add('active');
- document.querySelector('.main-head h1').textContent = a.textContent.trim();
- }));
- document.querySelectorAll('.filter-tag').forEach(btn => btn.addEventListener('click', () => {
- btn.parentElement.querySelectorAll('.filter-tag').forEach(b => b.classList.remove('active'));
- btn.classList.add('active');
- }));
- </script>
- </body>
- </html>
|