10 HTML pages + puro.css + HANDOFF.md + 2 images (~810KB total). Reference artifacts for Stage 3 Vue 3 translation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
638 lines
25 KiB
HTML
638 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="color-scheme" content="dark">
|
|
<title>API Keys — PURO AI</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<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=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="puro.css">
|
|
<style>
|
|
.page-head {
|
|
display: flex; align-items:flex-end; justify-content:space-between;
|
|
margin-bottom: 28px; gap: 24px;
|
|
}
|
|
.page-head h1 { font-size: 28px; font-weight: 700; letter-spacing:-0.02em; margin-bottom:6px; }
|
|
.page-head .sub { color: var(--text-2); font-size: 14px; max-width: 560px; line-height: 1.55; }
|
|
|
|
.summary {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 12px;
|
|
margin-bottom: 24px;
|
|
}
|
|
.summary .cell {
|
|
padding: 14px 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-lg);
|
|
background: rgba(15, 23, 42, 0.5);
|
|
}
|
|
.summary .cell-label {
|
|
font-size: 11px; color: var(--text-3);
|
|
text-transform: uppercase; letter-spacing: 0.1em;
|
|
font-family: var(--font-mono);
|
|
margin-bottom: 8px;
|
|
}
|
|
.summary .cell-value {
|
|
font-family: var(--font-mono);
|
|
font-size: 20px; font-weight: 700;
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
.summary .cell-value .unit { font-size: 12px; color: var(--text-3); margin-left: 4px; }
|
|
|
|
.toolbar {
|
|
display: flex; gap: 10px; align-items: center;
|
|
margin-bottom: 14px;
|
|
}
|
|
.toolbar .search-box {
|
|
flex: 1; max-width: 340px; position: relative;
|
|
}
|
|
.toolbar .search-box input {
|
|
width: 100%; height: 36px;
|
|
padding: 0 12px 0 34px;
|
|
background: rgba(2, 6, 23, 0.5);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-sm);
|
|
color: var(--text-1); font-size: 13px;
|
|
outline: none; font-family: inherit;
|
|
}
|
|
.toolbar .search-box input:focus { border-color: var(--border-2); }
|
|
.toolbar .search-box::before {
|
|
content: ""; position: absolute; left: 12px; top: 50%;
|
|
width: 14px; height: 14px; transform: translateY(-50%);
|
|
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='m20 20-3.5-3.5'/></svg>");
|
|
background-repeat: no-repeat;
|
|
}
|
|
.filter-btn {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 0 12px; height: 36px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-sm);
|
|
background: rgba(2, 6, 23, 0.5);
|
|
color: var(--text-2); font-size: 13px;
|
|
transition: all .12s;
|
|
}
|
|
.filter-btn:hover { border-color: var(--border-2); color: var(--text-0); }
|
|
.filter-btn .dot-count {
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
width: 16px; height: 16px; border-radius: 50%;
|
|
background: var(--cyan); color: #042f2e;
|
|
font-size: 10px; font-weight: 700;
|
|
}
|
|
|
|
/* key card */
|
|
.key-list { display: flex; flex-direction: column; gap: 10px; }
|
|
.key-card {
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-lg);
|
|
background: rgba(15, 23, 42, 0.5);
|
|
padding: 18px 20px;
|
|
transition: all .12s;
|
|
}
|
|
.key-card:hover { border-color: var(--border-2); background: rgba(15, 23, 42, 0.7); }
|
|
.key-card.revoked { opacity: 0.6; }
|
|
|
|
.key-head {
|
|
display: flex; align-items: center; gap: 14px;
|
|
margin-bottom: 14px;
|
|
}
|
|
.key-name {
|
|
font-size: 15px; font-weight: 600;
|
|
display: flex; align-items: center; gap: 10px;
|
|
}
|
|
.key-meta {
|
|
font-family: var(--font-mono); font-size: 11px; color: var(--text-3);
|
|
display: flex; align-items: center; gap: 12px;
|
|
margin-left: auto;
|
|
}
|
|
.key-meta .sep { color: var(--border-2); }
|
|
.key-actions { display: flex; gap: 4px; margin-left: 6px; }
|
|
.icon-act {
|
|
width: 28px; height: 28px;
|
|
border-radius: 6px;
|
|
color: var(--text-3);
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
transition: all .12s;
|
|
}
|
|
.icon-act:hover { color: var(--text-0); background: rgba(255,255,255,0.04); }
|
|
.icon-act.danger:hover { color: var(--red); background: rgba(248,113,113,0.08); }
|
|
|
|
.key-value {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 10px 14px;
|
|
background: rgba(2, 6, 23, 0.6);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-md);
|
|
font-family: var(--font-mono);
|
|
font-size: 13px;
|
|
color: var(--text-1);
|
|
margin-bottom: 14px;
|
|
}
|
|
.key-value .prefix { color: var(--cyan); }
|
|
.key-value .rest { letter-spacing: 0.05em; }
|
|
.key-value .reveal {
|
|
margin-left: auto;
|
|
color: var(--text-3); font-size: 11px;
|
|
padding: 4px 10px; border-radius: 4px;
|
|
cursor: pointer; transition: all .12s;
|
|
}
|
|
.key-value .reveal:hover { color: var(--cyan); background: rgba(34,211,238,0.08); }
|
|
.key-value .copy-btn {
|
|
color: var(--text-3); font-size: 11px;
|
|
padding: 4px 10px; border-radius: 4px;
|
|
cursor: pointer; transition: all .12s;
|
|
}
|
|
.key-value .copy-btn:hover { color: var(--cyan); background: rgba(34,211,238,0.08); }
|
|
|
|
.key-scopes {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 12px;
|
|
padding-top: 14px;
|
|
border-top: 1px dashed var(--border);
|
|
}
|
|
.scope {
|
|
display: flex; flex-direction: column; gap: 4px;
|
|
}
|
|
.scope-label {
|
|
font-size: 10px; color: var(--text-3);
|
|
text-transform: uppercase; letter-spacing: 0.12em;
|
|
font-family: var(--font-mono);
|
|
}
|
|
.scope-val {
|
|
font-size: 12px; color: var(--text-1);
|
|
font-family: var(--font-mono);
|
|
}
|
|
.scope-val.tags {
|
|
display: flex; gap: 4px; flex-wrap: wrap;
|
|
}
|
|
.mini-tag {
|
|
display: inline-flex; align-items: center; gap: 4px;
|
|
padding: 1px 6px;
|
|
background: rgba(255,255,255,0.04);
|
|
border: 1px solid var(--border);
|
|
border-radius: 3px;
|
|
font-size: 10px;
|
|
color: var(--text-2);
|
|
}
|
|
.mini-tag .dot { width: 5px; height: 5px; border-radius: 50%; }
|
|
.mini-tag.all { color: var(--cyan); border-color: rgba(34,211,238,0.25); background: rgba(34,211,238,0.06); }
|
|
.usage-bar {
|
|
height: 4px; background: var(--border);
|
|
border-radius: 2px; overflow: hidden;
|
|
margin-top: 2px;
|
|
}
|
|
.usage-bar span { display: block; height: 100%; background: var(--cyan); }
|
|
.usage-bar.warn span { background: var(--amber); }
|
|
|
|
/* ---------- modal ---------- */
|
|
.backdrop {
|
|
position: fixed; inset: 0;
|
|
background: rgba(2, 6, 23, 0.8);
|
|
backdrop-filter: blur(8px);
|
|
z-index: 100;
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 40px;
|
|
}
|
|
.backdrop.open { display: flex; }
|
|
.modal {
|
|
width: 540px; max-width: 100%;
|
|
background: var(--bg-1);
|
|
border: 1px solid var(--border-2);
|
|
border-radius: var(--r-xl);
|
|
box-shadow: var(--shadow-xl);
|
|
overflow: hidden;
|
|
}
|
|
.modal-head {
|
|
padding: 22px 28px 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex; align-items: center;
|
|
}
|
|
.modal-head h2 {
|
|
font-size: 18px; font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
.modal-head .close {
|
|
margin-left: auto; padding: 6px;
|
|
color: var(--text-3); cursor: pointer;
|
|
border-radius: 6px;
|
|
}
|
|
.modal-head .close:hover { color: var(--text-0); background: rgba(255,255,255,0.04); }
|
|
.modal-body { padding: 22px 28px; }
|
|
.modal-foot {
|
|
padding: 14px 28px 22px;
|
|
border-top: 1px solid var(--border);
|
|
display: flex; gap: 10px; justify-content: flex-end;
|
|
}
|
|
|
|
/* newly-created key callout */
|
|
.new-key-callout {
|
|
padding: 16px;
|
|
border: 1px solid rgba(52, 211, 153, 0.3);
|
|
border-radius: var(--r-md);
|
|
background: rgba(52, 211, 153, 0.05);
|
|
margin-bottom: 18px;
|
|
}
|
|
.new-key-callout .header {
|
|
display: flex; align-items: center; gap: 8px;
|
|
font-size: 13px; font-weight: 600; color: var(--green);
|
|
margin-bottom: 10px;
|
|
}
|
|
.new-key-callout .warn {
|
|
font-size: 12px; color: var(--text-2); margin-top: 10px;
|
|
line-height: 1.55;
|
|
}
|
|
|
|
/* scope picker */
|
|
.scope-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
}
|
|
.scope-opt {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 10px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--r-sm);
|
|
background: rgba(2, 6, 23, 0.4);
|
|
cursor: pointer;
|
|
transition: all .12s;
|
|
}
|
|
.scope-opt:hover { border-color: var(--border-2); }
|
|
.scope-opt.active {
|
|
border-color: var(--cyan);
|
|
background: rgba(34,211,238,0.06);
|
|
}
|
|
.scope-opt .box {
|
|
width: 14px; height: 14px;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--border-2);
|
|
flex-shrink: 0;
|
|
display: flex; align-items: center; justify-content: center;
|
|
}
|
|
.scope-opt.active .box {
|
|
background: var(--cyan); border-color: var(--cyan);
|
|
}
|
|
.scope-opt.active .box::after {
|
|
content: "✓"; color: #042f2e; font-size: 10px; font-weight: 700;
|
|
}
|
|
.scope-opt .label { font-size: 13px; color: var(--text-0); }
|
|
.scope-opt .desc { font-size: 11px; color: var(--text-3); font-family: var(--font-mono); margin-left: auto; }
|
|
|
|
/* topbar (reused) */
|
|
.topbar-user {
|
|
margin-left: auto; display: flex; gap: 10px; align-items: center;
|
|
}
|
|
.user-menu {
|
|
display: flex; align-items: center; gap: 8px;
|
|
padding: 4px 10px 4px 4px;
|
|
border-radius: 100px;
|
|
background: rgba(255,255,255,0.03);
|
|
border: 1px solid var(--border);
|
|
cursor: pointer;
|
|
}
|
|
.user-menu .name { font-size: 13px; font-weight: 500; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="bg-glow soft"></div>
|
|
|
|
<div class="app-shell">
|
|
<!-- SIDEBAR (same as dashboard) -->
|
|
<aside class="app-side">
|
|
<a class="brand" href="Landing.html">
|
|
<svg class="hex" viewBox="0 0 24 24" fill="none">
|
|
<path d="M12 2L21 7V17L12 22L3 17V7L12 2Z" stroke="currentColor" stroke-width="1.8" fill="rgba(34, 211, 238, 0.08)"/>
|
|
<path d="M12 7L17 9.5V14.5L12 17L7 14.5V9.5L12 7Z" fill="currentColor"/>
|
|
</svg>
|
|
PURO
|
|
</a>
|
|
<div class="side-group">
|
|
<div class="side-label">Workspace</div>
|
|
<a class="side-item" href="Dashboard.html"><span class="ico">◆</span>Dashboard</a>
|
|
<a class="side-item active" href="API Keys.html"><span class="ico">⌘</span>API Keys<span class="count">3</span></a>
|
|
<a class="side-item" href="Accounts.html"><span class="ico">⊡</span>订阅账号<span class="count">7</span></a>
|
|
<a class="side-item" href="#"><span class="ico">▤</span>调用日志</a>
|
|
<a class="side-item" href="#"><span class="ico">$</span>账单 & 充值</a>
|
|
</div>
|
|
<div class="side-group">
|
|
<div class="side-label">Resources</div>
|
|
<a class="side-item" href="Docs.html"><span class="ico">📖</span>文档</a>
|
|
<a class="side-item" href="Design System.html"><span class="ico">◆</span>Design System</a>
|
|
</div>
|
|
<div class="side-group" style="margin-top:auto; padding-top:20px; border-top:1px solid var(--border);">
|
|
<a class="side-item" href="#"><span class="ico">⚙</span>设置</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<div class="app-main">
|
|
<header class="app-topbar">
|
|
<h1>API Keys</h1>
|
|
<div class="topbar-user">
|
|
<div class="user-menu"><span class="avatar">Z</span><span class="name">zane</span></div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="app-content">
|
|
<div class="page-head">
|
|
<div>
|
|
<h1>API Keys</h1>
|
|
<div class="sub">每个 key 是一张独立的"通行证",可以单独设置可用的订阅池、限速和预算,泄漏时可以直接吊销而不影响其他 key。</div>
|
|
</div>
|
|
<button class="btn btn-primary btn-lg" onclick="document.getElementById('create-modal').classList.add('open')">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
|
|
创建 Key
|
|
</button>
|
|
</div>
|
|
|
|
<!-- summary -->
|
|
<div class="summary">
|
|
<div class="cell">
|
|
<div class="cell-label">活跃 Keys</div>
|
|
<div class="cell-value tabular">3<span class="unit">/ 10 上限</span></div>
|
|
</div>
|
|
<div class="cell">
|
|
<div class="cell-label">近 7 日调用</div>
|
|
<div class="cell-value tabular">89,402</div>
|
|
</div>
|
|
<div class="cell">
|
|
<div class="cell-label">近 7 日花费</div>
|
|
<div class="cell-value tabular">$24.18<span class="unit">USD</span></div>
|
|
</div>
|
|
<div class="cell">
|
|
<div class="cell-label">已吊销</div>
|
|
<div class="cell-value tabular text-3">2</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- toolbar -->
|
|
<div class="toolbar">
|
|
<div class="search-box">
|
|
<input placeholder="搜索 key 名称或前缀…">
|
|
</div>
|
|
<button class="filter-btn">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 3H2l8 9.46V19l4 2v-8.54z"/></svg>
|
|
筛选 <span class="dot-count">2</span>
|
|
</button>
|
|
<button class="filter-btn">
|
|
全部范围
|
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M6 9l6 6 6-6"/></svg>
|
|
</button>
|
|
<div style="margin-left:auto;"></div>
|
|
<button class="filter-btn">
|
|
显示吊销
|
|
</button>
|
|
</div>
|
|
|
|
<!-- list -->
|
|
<div class="key-list">
|
|
|
|
<div class="key-card">
|
|
<div class="key-head">
|
|
<div class="key-name">
|
|
production
|
|
<span class="badge green">ACTIVE</span>
|
|
</div>
|
|
<div class="key-meta">
|
|
<span>created 2026·03·14</span>
|
|
<span class="sep">·</span>
|
|
<span>last used 2m ago</span>
|
|
<span class="sep">·</span>
|
|
<span class="text-cyan">● in use</span>
|
|
</div>
|
|
<div class="key-actions">
|
|
<button class="icon-act" title="编辑">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4z"/></svg>
|
|
</button>
|
|
<button class="icon-act" title="轮换">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.5 0 4.8 1 6.4 2.6L21 8"/><path d="M21 3v5h-5"/></svg>
|
|
</button>
|
|
<button class="icon-act danger" title="吊销">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="key-value">
|
|
<span class="prefix">sk-puro-</span>
|
|
<span class="rest">••••••••••••••••••••••••4f82</span>
|
|
<span class="reveal">👁 显示</span>
|
|
<span class="copy-btn">复制</span>
|
|
</div>
|
|
|
|
<div class="key-scopes">
|
|
<div class="scope">
|
|
<div class="scope-label">可用订阅池</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag"><span class="dot" style="background:#d97757"></span>claude · 2</span>
|
|
<span class="mini-tag"><span class="dot" style="background:#10a37f"></span>gpt · 2</span>
|
|
<span class="mini-tag"><span class="dot" style="background:#4285f4"></span>gemini · 1</span>
|
|
</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">本月用量</div>
|
|
<div class="scope-val tabular">$14.82 <span class="text-3">/ $50</span></div>
|
|
<div class="usage-bar"><span style="width:30%"></span></div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">速率限制</div>
|
|
<div class="scope-val">120 RPM</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">关联应用</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag">Claude Code</span>
|
|
<span class="mini-tag">Cursor</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="key-card">
|
|
<div class="key-head">
|
|
<div class="key-name">
|
|
staging
|
|
<span class="badge amber">RATE LIMITED</span>
|
|
</div>
|
|
<div class="key-meta">
|
|
<span>created 2026·04·02</span>
|
|
<span class="sep">·</span>
|
|
<span>last used 3h ago</span>
|
|
</div>
|
|
<div class="key-actions">
|
|
<button class="icon-act"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4z"/></svg></button>
|
|
<button class="icon-act"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.5 0 4.8 1 6.4 2.6L21 8"/><path d="M21 3v5h-5"/></svg></button>
|
|
<button class="icon-act danger"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button>
|
|
</div>
|
|
</div>
|
|
<div class="key-value">
|
|
<span class="prefix">sk-puro-</span>
|
|
<span class="rest">••••••••••••••••••••••••ae19</span>
|
|
<span class="reveal">👁 显示</span>
|
|
<span class="copy-btn">复制</span>
|
|
</div>
|
|
<div class="key-scopes">
|
|
<div class="scope">
|
|
<div class="scope-label">可用订阅池</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag all">all pools</span>
|
|
</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">本月用量</div>
|
|
<div class="scope-val tabular">$8.24 <span class="text-3">/ $10</span></div>
|
|
<div class="usage-bar warn"><span style="width:82%"></span></div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">速率限制</div>
|
|
<div class="scope-val">30 RPM</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">关联应用</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag">本地开发</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="key-card">
|
|
<div class="key-head">
|
|
<div class="key-name">
|
|
cli-personal
|
|
<span class="badge">ACTIVE</span>
|
|
</div>
|
|
<div class="key-meta">
|
|
<span>created 2026·04·11</span>
|
|
<span class="sep">·</span>
|
|
<span>last used 18h ago</span>
|
|
</div>
|
|
<div class="key-actions">
|
|
<button class="icon-act"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4z"/></svg></button>
|
|
<button class="icon-act"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.5 0 4.8 1 6.4 2.6L21 8"/><path d="M21 3v5h-5"/></svg></button>
|
|
<button class="icon-act danger"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button>
|
|
</div>
|
|
</div>
|
|
<div class="key-value">
|
|
<span class="prefix">sk-puro-</span>
|
|
<span class="rest">••••••••••••••••••••••••c3d1</span>
|
|
<span class="reveal">👁 显示</span>
|
|
<span class="copy-btn">复制</span>
|
|
</div>
|
|
<div class="key-scopes">
|
|
<div class="scope">
|
|
<div class="scope-label">可用订阅池</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag"><span class="dot" style="background:#d97757"></span>claude · 1</span>
|
|
</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">本月用量</div>
|
|
<div class="scope-val tabular">$1.12 <span class="text-3">/ 无限制</span></div>
|
|
<div class="usage-bar"><span style="width:6%"></span></div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">速率限制</div>
|
|
<div class="scope-val">60 RPM</div>
|
|
</div>
|
|
<div class="scope">
|
|
<div class="scope-label">关联应用</div>
|
|
<div class="scope-val tags">
|
|
<span class="mini-tag">Terminal</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- revoked -->
|
|
<div class="key-card revoked">
|
|
<div class="key-head">
|
|
<div class="key-name">
|
|
<span style="text-decoration:line-through; color:var(--text-2);">old-demo</span>
|
|
<span class="badge red">REVOKED</span>
|
|
</div>
|
|
<div class="key-meta">
|
|
<span>revoked 2026·03·02</span>
|
|
</div>
|
|
</div>
|
|
<div class="key-value" style="opacity:0.7">
|
|
<span class="prefix">sk-puro-</span>
|
|
<span class="rest">••••••••••••••••••••••••0ab3</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- CREATE MODAL -->
|
|
<div class="backdrop" id="create-modal">
|
|
<div class="modal">
|
|
<div class="modal-head">
|
|
<h2>创建新的 API Key</h2>
|
|
<span class="close" onclick="document.getElementById('create-modal').classList.remove('open')">✕</span>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="field">
|
|
<label class="field-label">Key 名称</label>
|
|
<input class="input" placeholder="e.g. production · staging · cursor-macbook">
|
|
<div class="field-hint">仅用于辨识,不会出现在请求中。</div>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label class="field-label">可用订阅池</label>
|
|
<div class="scope-grid">
|
|
<div class="scope-opt active">
|
|
<span class="box"></span>
|
|
<span class="label">Claude 池</span>
|
|
<span class="desc">2 accounts</span>
|
|
</div>
|
|
<div class="scope-opt active">
|
|
<span class="box"></span>
|
|
<span class="label">GPT 池</span>
|
|
<span class="desc">2 accounts</span>
|
|
</div>
|
|
<div class="scope-opt">
|
|
<span class="box"></span>
|
|
<span class="label">Gemini 池</span>
|
|
<span class="desc">1 account</span>
|
|
</div>
|
|
<div class="scope-opt">
|
|
<span class="box"></span>
|
|
<span class="label">Codex 池</span>
|
|
<span class="desc">0 accounts</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:grid; grid-template-columns:1fr 1fr; gap:14px;">
|
|
<div class="field" style="margin-bottom:0">
|
|
<label class="field-label">月度预算 ($USD)</label>
|
|
<input class="input" placeholder="50" type="number">
|
|
<div class="field-hint">达到后自动停用,下月 1 号重置。</div>
|
|
</div>
|
|
<div class="field" style="margin-bottom:0">
|
|
<label class="field-label">速率限制 (RPM)</label>
|
|
<input class="input" placeholder="60" type="number">
|
|
<div class="field-hint">每分钟最大请求数。</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-foot">
|
|
<button class="btn btn-ghost" onclick="document.getElementById('create-modal').classList.remove('open')">取消</button>
|
|
<button class="btn btn-primary">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg>
|
|
创建 Key
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|