Files

134 lines
12 KiB
HTML
Raw Permalink 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">
<base href="/v0/resource/plugins/billing/">
<title>CPA</title>
<link rel="stylesheet" href="./styles/base.css">
<link rel="stylesheet" href="./styles/layout.css">
<link rel="stylesheet" href="./styles/keys.css">
<link rel="stylesheet" href="./styles/usage.css">
<link rel="stylesheet" href="./styles/pricing.css">
<link rel="stylesheet" href="./styles/responsive.css">
</head>
<body class="read-only">
<div class="app-shell">
<header class="workspace-bar">
<nav class="workspace-nav" aria-label="工作区">
<button class="nav-button active" type="button" data-view="stats">统计</button>
<button class="nav-button" type="button" data-view="usage">请求</button>
<button class="nav-button" type="button" data-view="pricing">模型</button>
<button class="nav-button" type="button" data-view="logs">日志</button>
<button class="nav-button admin-only" type="button" data-view="users">用户</button>
</nav>
<div class="topbar-actions">
<div id="demo-perspective" class="demo-perspective hidden" aria-label="演示视角">
<button type="button" data-perspective="admin">管理员示教</button>
<button type="button" data-perspective="user">普通用户视角</button>
</div>
<div class="auth-box"><input id="key" type="password" autocomplete="off" aria-label="管理密钥"></div>
</div>
</header>
<main>
<section id="view-stats" class="view active">
<div class="chart-grid">
<article class="chart-card"><div id="user-usage" class="user-usage"></div></article>
<article class="chart-card"><div id="quota-chart" class="quota-matrix-wrap"></div></article>
</div>
<div class="stats-insight-grid">
<article class="chart-card insight-card"><header><h2>额度健康</h2></header><div id="quota-health"></div></article>
</div>
</section>
<section id="view-users" class="view admin-only">
<div id="key-management" class="user-management">
<div class="user-management-header">
<p id="key-status" class="status"></p>
<div class="user-management-actions">
<button id="reset-all-billing" type="button">重置所有</button>
<button id="create-key" class="primary" type="button">创建 Key</button>
</div>
</div>
<div id="key-rows" class="user-card-grid"></div>
</div>
</section>
<section id="view-usage" class="view">
<div class="section-heading"><div><div id="page-buttons" class="page-buttons admin-only"></div><span id="status" class="status"></span></div><div class="tools">
<details id="usage-filter-panel" class="usage-filter-panel admin-only"><summary>查询过滤</summary><div class="surface usage-filters">
<label class="usage-filter">开始时间<input id="usage-from" type="datetime-local" step="1"></label>
<label class="usage-filter">结束时间<input id="usage-to" type="datetime-local" step="1"></label>
<label class="usage-filter">用户<select id="usage-key"><option value="">全部用户</option></select></label>
<label class="usage-filter">模型<input id="usage-model" list="usage-model-options" placeholder="全部模型"><datalist id="usage-model-options"></datalist></label>
<label class="usage-filter">结果<select id="usage-result"><option value="">全部结果</option><option value="succeeded">成功</option><option value="failed">失败</option><option value="rejected">已拒绝</option><option value="canceled">已取消</option></select></label>
<label class="usage-filter">上游<select id="usage-auth"><option value="">全部上游</option></select></label>
<label class="usage-filter">端点<select id="usage-endpoint"><option value="">全部端点</option><option value="responses">responses</option><option value="compact">compact</option><option value="chat">chat</option></select></label>
<label class="usage-filter request-filter">请求 ID<input id="usage-request-id" placeholder="粘贴完整 Request ID"></label>
<div class="usage-filter-actions"><button id="clear-usage-filters" type="button">清空</button><button id="apply-usage-filters" class="primary" type="button">查询</button></div>
</div></details>
<details class="admin-only"><summary></summary><div id="column-options" class="column-options"></div></details><button id="refresh" class="admin-only" type="button">刷新</button>
</div></div>
<div class="surface"><div class="table-wrap"><table><thead><tr id="headers"></tr></thead><tbody id="rows"></tbody></table></div></div>
</section>
<section id="view-pricing" class="view">
<div class="surface price-panel price-layout">
<aside class="price-sidebar"><div class="price-sidebar-header admin-only"><div><h2>已配置模型</h2><div id="price-status" class="status"></div></div><button id="new-price" class="small" type="button">新增</button></div><div id="price-list" class="price-list"></div></aside>
<section class="price-editor">
<div id="price-editor-content" class="hidden">
<div class="price-editor-header"><h2>模型价格</h2></div>
<div class="price-section"><label class="field price-model-field">模型名称<input id="price-model" placeholder="gpt-5.6-sol"></label><div id="price-source" class="price-source">手动配置</div></div>
<div class="price-section admin-only"><div class="price-section-header"><h3>models.dev 参考价格</h3><button id="refresh-catalog" class="small" type="button">更新目录</button></div><div id="catalog-summary" class="catalog-summary"></div><div class="catalog-toolbar"><input id="catalog-query" placeholder="搜索模型或供应商"><button id="search-catalog" class="small" type="button">搜索</button></div><div id="catalog-results" class="catalog-results"></div></div>
<div class="price-section"><div class="price-section-header"><h3>基础价格 · $ / 1M Token</h3></div><div class="price-grid">
<label>输入<input id="price-input" inputmode="decimal"></label><label>缓存读取<input id="price-cache-read" inputmode="decimal"></label><label>缓存写入<input id="price-cache-write" inputmode="decimal"></label><label>输出<input id="price-output" inputmode="decimal"></label>
</div></div>
<div id="long-price-section" class="price-section hidden"><div class="price-section-header"><h3>长上下文价格</h3><label class="inline-check"><input id="long-enabled" type="checkbox">启用</label></div><div class="price-grid long-grid">
<label class="long-field hidden">输入门槛<input id="long-threshold" type="number" min="0" step="1"></label><label class="long-field hidden">门槛比较<select id="long-comparison"><option value="gt">大于</option><option value="gte">大于等于</option></select></label><label class="long-field hidden">输入<input id="long-input" inputmode="decimal"></label><label class="long-field hidden">缓存读取<input id="long-cache-read" inputmode="decimal"></label><label class="long-field hidden">缓存写入<input id="long-cache-write" inputmode="decimal"></label><label class="long-field hidden">输出<input id="long-output" inputmode="decimal"></label>
</div></div>
<div class="price-section"><div class="price-section-header"><h3>Fast 价格</h3></div><div class="fast-row"><label class="inline-check"><input id="fast-pricing-enabled" type="checkbox">使用倍率计价</label><label class="field">倍率<input id="fast-multiplier" inputmode="decimal" value="2.5"></label></div></div>
<div class="price-actions admin-only"><button id="delete-price" class="danger hidden" type="button">删除</button><button id="clear-price" type="button">清空</button><button id="save-price" class="primary" type="button">保存价格</button></div>
</div>
</section>
</div>
</section>
<section id="view-logs" class="view">
<div class="surface"><div class="table-wrap"><table class="event-table"><thead><tr><th class="left">时间</th><th class="left">事件</th><th class="left">状态</th></tr></thead><tbody id="event-rows"></tbody></table></div></div>
</section>
</main>
</div>
<div id="drawer-overlay" class="drawer-overlay hidden"></div>
<aside id="key-drawer" class="drawer hidden" aria-hidden="true">
<div class="drawer-header"><div><h2 id="drawer-title">管理 Key</h2><p id="drawer-subtitle">修改用户状态、路由和模型权限</p></div><button id="close-drawer" class="icon-button" type="button" aria-label="关闭">×</button></div>
<div class="drawer-body">
<div id="key-editor" class="drawer-form">
<div class="drawer-section"><h3>用户</h3><label class="field">名称<input id="editor-name" placeholder="例如 alice"></label>
<label class="field">完整 Key<input id="editor-secret" class="secret" minlength="6" maxlength="256" placeholder="留空自动生成"></label>
<label class="inline-check"><input id="editor-show-stats" type="checkbox" checked>在统计页显示该用户</label></div>
<div id="managed-fields" class="drawer-form">
<div class="drawer-section"><h3>访问与路由</h3>
<div class="field-row"><label class="field">状态<select id="editor-status"><option value="active">启用</option><option value="disabled">禁用</option><option value="archived">已归档</option></select></label><label class="field">路由<select id="editor-route"><option value="auto">自由选择</option><option value="strict">指定账号</option></select></label></div>
<label class="field">上游账号<select id="editor-upstream"></select></label>
<label class="inline-check"><input id="editor-all-models" type="checkbox">允许全部模型</label>
<label class="field">允许模型规则<input id="editor-models" placeholder="deepseek-*gpt-5.6-sol"></label><p class="field-hint">多个规则用逗号分隔;* 匹配任意字符,未匹配的模型会被拒绝。</p></div>
<div class="drawer-section"><h3>额度与周期</h3>
<div id="billing-preview" class="billing-preview"><div><span>额度</span><strong id="billing-quota-view">$0.0000</strong></div><div><span>已用</span><strong id="billing-spent-view">$0.0000</strong></div><div><span>余额</span><strong id="billing-balance-view">$0.0000</strong></div></div>
<div class="field-row"><label class="field">本周期额度(USD<input id="editor-quota" inputmode="decimal" value="0"></label><label class="field">并发上限<input id="editor-concurrency" type="number" min="1" max="64" step="1" value="4"></label></div>
<div class="field-row"><label class="field">自动重置<select id="editor-reset-period"><option value="none">不重置</option><option value="daily">每天</option><option value="weekly">每周</option><option value="monthly">每月</option></select></label><label class="field">下次重置时间<input id="editor-next-reset" type="datetime-local" step="1"></label></div>
<p class="field-hint">请求结束后按实际费用扣款;最后一个并发请求可能产生负余额。</p>
<div class="billing-tools"><span id="billing-status" class="status"></span><button id="reset-billing" class="small" type="button">立即重置额度</button></div>
</div>
<div id="ledger-section" class="drawer-section"><h3>最近账目</h3><div id="billing-ledger" class="ledger-list"></div></div>
</div>
</div>
<div id="key-stats" class="hidden"><div id="stats-grid" class="stats-grid"></div><h3>最近请求</h3><div id="stats-recent" class="recent-list"></div></div>
</div>
<div id="editor-footer" class="drawer-footer"><button id="archive-key" class="danger hidden" type="button">永久归档</button><div><button id="cancel-editor" type="button">取消</button><button id="save-key" class="primary" type="button">保存</button></div></div>
</aside>
<script src="./ui-config.js"></script>
<script type="module" src="./app/main.js"></script>
</body>
</html>