Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 161 additions & 27 deletions ui/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,18 @@ body {
}
.btn-primary:hover { background: color-mix(in oklch, var(--accent) 86%, var(--fg)); }
.btn-ghost { background: transparent; }
/* 次级按钮(原型 .btn-secondary):透明底 + 描边,hover 转 accent 边与柔和底 */
.btn-secondary { background: transparent; color: var(--text); }
.btn-secondary:hover { border-color: color-mix(in oklch, var(--accent) 55%, var(--border)); background: var(--accent-soft); }
.btn-danger {
background: transparent;
border-color: transparent;
color: var(--danger);
}
.btn-danger:hover { background: var(--danger-soft); border-color: var(--danger); }
.btn-block { width: 100%; }
/* 小尺寸按钮(原型 .btn-sm):侧边栏退出登录等紧凑位置使用 */
.btn-sm { padding: 5px 11px; font-size: 12.5px; }
.btn:disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
/* 按钮按压反馈(rant 18:06:09 E::active 轻微下压;disabled 不触发) */
.btn:active:not(:disabled) { transform: scale(0.98); }
Expand Down Expand Up @@ -334,23 +339,9 @@ select.input option { background: var(--bg-card); }
gap: 14px;
margin-bottom: 4px;
}
.stat {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px 18px;
transition: transform .15s ease, border-color .18s ease, box-shadow .18s ease;
}
/* 统计卡 hover 微抬升(rant 18:06:09 E) */
.stat:hover {
transform: translateY(-2px);
border-color: var(--card-hover-border);
box-shadow: var(--card-shadow);
}
.stat .label { color: var(--text-mute); font-size: 12px; }
.stat .value { font-size: 24px; font-weight: 700; margin-top: 4px; }
.stat .sub { color: var(--text-dim); font-size: 12px; }
.stat.accent .value { color: var(--accent-text); }
/* 统计卡(rant 18:06:09 E hover 微抬升)——原型 .stat-card 为规范名,
定义见本节末尾「通用组件层」;此处保留 .sub 副说明的历史写法 */
.stat-card .sub { color: var(--text-dim); font-size: 12px; }

/* 交易汇总条(rant 20:39:30 B:紧凑 inline 条,随 tab/筛选联动) */
.tx-summary { display: flex; flex-wrap: wrap; gap: 28px; padding: 12px 16px 10px; border-bottom: 1px solid var(--border); }
Expand Down Expand Up @@ -438,6 +429,8 @@ select.input option { background: var(--bg-card); }
.density-options .check { display: flex; align-items: center; gap: 6px; flex-direction: row; color: var(--text-dim); font-size: 13px; cursor: pointer; }
.density-options input { accent-color: var(--accent); }

/* 状态徽标:规范类为原型 .pill-* / .tag(定义见「通用组件层」),
.badge 保留为兼容别名(带语义色点),外部/历史标记仍可直接使用 */
.badge {
display: inline-flex;
align-items: center;
Expand All @@ -464,9 +457,13 @@ select.input option { background: var(--bg-card); }
.toolbar .input { max-width: 240px; }
.toolbar-count { align-self: center; color: var(--text-mute); font-size: 12px; margin-left: auto; }

/* 搜索增强(rant 18:06:09 D:清空 × 按钮 + <mark> 关键词高亮) */
.search-box { position: relative; display: block; }
.search-box .input { padding-right: 30px; }
/* 搜索增强(rant 18:06:09 D:清空 × 按钮 + <mark> 关键词高亮;
rant 2026-09-11T16:23:43:类名对齐原型 .search) */
.search { position: relative; display: block; }
.search .input { padding-right: 30px; }
/* 工具栏内搜索框按原型弹性伸缩(原型 .toolbar .search) */
.toolbar .search { flex: 1; min-width: 180px; max-width: 320px; }
.toolbar .search .input { max-width: none; }
.search-clear {
position: absolute;
right: 6px;
Expand Down Expand Up @@ -619,13 +616,7 @@ mark {
.mini-item.net .t { color: var(--accent-text); }

.bar-list { display: flex; flex-direction: column; gap: 12px; }
.bar-row .bar-label { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 4px; }
.bar-row .bar-label .n { color: var(--text-mute); }
.bar {
height: 8px; border-radius: 999px;
background: var(--bg-hover); overflow: hidden;
}
.bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), color-mix(in oklch, var(--accent) 55%, var(--ok))); border-radius: 999px; }
.bar-row .bar-top .n { color: var(--text-mute); }

/* 空状态(rant 15:50:05 A.4:图标 + 文案 + 可选行动按钮) */
.empty-state {
Expand Down Expand Up @@ -1029,6 +1020,144 @@ mark {
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ============================================================
通用组件层(rant 2026-09-11T16:23:43 第三节)
原型 docs/prototype/aitokenpool-console.html 的可复用类在此落成,
PR4–PR6 的视图只需组装、不再各自发明样式。
命名对齐原型(pill/tag/stat-card/trend/bar-track…),
线上历史类名保留兼容别名,避免同一次改动里做 DOM 迁移。
============================================================ */

/* ---- 徽标 / 标签 ---- */
/* 原型 .pill 系列:无描边、柔和底色、等宽字体(状态类徽标的新形态) */
.pill {
display: inline-flex; align-items: center; gap: 5px;
padding: 2px 9px; border-radius: 999px;
font-size: 11.5px; font-weight: 600;
font-family: var(--font-mono); letter-spacing: .03em;
}
.pill-ok { background: var(--ok-soft); color: var(--ok); }
.pill-warn { background: var(--warn-soft); color: var(--warn); }
.pill-danger { background: var(--danger-soft); color: var(--danger); }
.pill-muted { background: var(--fg-soft); color: var(--muted); }
.pill-accent { background: var(--accent-soft); color: var(--accent); }

/* 原型 .tag 系列:细描边胶囊,用于能力/属性标注(旗舰 / 推理 / 读图…) */
.tag {
display: inline-flex; align-items: center;
padding: 2px 9px; border: 1px solid var(--border);
border-radius: 999px; font-size: 11.5px; color: var(--muted);
}
.tag-accent { border-color: color-mix(in oklch, var(--accent) 45%, var(--border)); color: var(--accent); }

/* ---- 卡片 / 栅格 ---- */
/* card-sub:卡片标题下的副说明(原型 .card .card-sub) */
.card-sub { color: var(--muted); font-size: 12.5px; margin-bottom: 14px; }
/* spread:标题左 / 动作右的一行(原型 .spread) */
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
/* 三等分栅格 + 主次分栏(原型 .card-grid-3 / .split) */
.card-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 16px; }
.split { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; align-items: start; margin-top: 16px; }
/* 栅格内卡片不再堆叠外边距(原型同名规则) */
.split > .card + .card, .card-grid > .card + .card, .card-grid-3 > .card + .card { margin-top: 0; }

/* stat-card:原型统计卡(等宽大数值 + 单位 + 可选 delta);
作为 .stat 的别名提供,供 PR4–PR6 直接按原型类名书写 */
.stat-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px 18px;
transition: transform .15s ease, border-color .18s ease, box-shadow .18s ease;
}
.stat-card:hover { transform: translateY(-2px); border-color: var(--card-hover-border); box-shadow: var(--card-shadow); }
.stat-card .label { font-size: 12px; color: var(--text-mute); display: flex; align-items: center; gap: 6px; }
.stat-card .value {
font-family: var(--font-mono); font-variant-numeric: tabular-nums;
font-size: 24px; font-weight: 700; line-height: 1.15; margin-top: 4px;
}
.stat-card .value .unit { font-size: 13px; color: var(--text-mute); margin-left: 4px; }
.stat-card .delta { font-size: 11.5px; font-family: var(--font-mono); }
.stat-card .delta.ok { color: var(--ok); }
.stat-card .delta.danger { color: var(--danger-text); }
.stat-card.accent .value { color: var(--accent-text); }
.stat-card.accent {
border-color: color-mix(in oklch, var(--accent) 40%, var(--border));
background: linear-gradient(180deg, var(--accent-soft), transparent 70%), var(--bg-card);
}

/* ---- 表格 ---- */
/* table.dt:原型数据表——等宽大写表头 + 单位数右对齐(.table 的结构化别名) */
table.dt { width: 100%; border-collapse: collapse; font-size: 13px; }
table.dt th, table.dt td { padding: 11px 14px; text-align: left; border-bottom: 1px solid var(--table-row-border); white-space: nowrap; }
table.dt thead th {
font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .06em;
text-transform: uppercase; color: var(--text-mute); font-weight: 500;
}
table.dt tbody tr:nth-child(even) { background: var(--table-stripe); }
table.dt tbody tr:hover { background: var(--bg-hover); }
table.dt tbody tr:last-child td { border-bottom: 0; }
table.dt td.num, table.dt th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
/* 厂商/模型合并单元格(原型 .provider-cell + .model-name + .dot) */
.provider-cell { display: flex; align-items: center; gap: 9px; }
.model-name { font-family: var(--mono); font-size: 12.5px; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; }
.dot.muted { background: var(--muted); }

/* ---- 工具栏 / 搜索 ---- */
/* .search 的原型定位规则见上方「搜索增强」(线上既有实现即原型形态) */
.toolbar .grow { flex: 1; }

/* ---- 表单 ---- */
/* label.f:原型表单标签(纵向 label + 说明文字) */
.form label.f { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; color: var(--text-dim); }
/* 文本域沿用输入框外观(原型 input.i/select.i/textarea.i) */
textarea.input { resize: vertical; min-height: 76px; }
textarea.input:focus { border-color: var(--accent); }
/* check-line:整行复选(原型 .check-line);.checkbox-line / .checkbox 为其线上历史别名 */
.check-line { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); }
.check-line input { accent-color: var(--accent); width: 15px; height: 15px; }
.checkbox, .checkbox-line { flex-direction: row !important; align-items: center; gap: 8px; }
.checkbox input, .checkbox-line input { accent-color: var(--accent); width: 14px; height: 14px; }
/* 交易页自定义时间段的 datetime-local 输入:与 .input 同观感 */
.tx-range-input {
background: var(--bg-soft); border: 1px solid var(--border); color: var(--text);
border-radius: var(--radius-sm); padding: 8px 12px; font-size: 13px; outline: none;
max-width: 210px;
}
.tx-range-input:focus { border-color: var(--accent); }
/* hint:字段级浅色提示(比 .form-hint 更轻) */
.hint { font-size: 11.5px; color: color-mix(in oklch, var(--muted) 82%, transparent); }

/* ---- 图表 ---- */
/* .trend 双色柱状图(原型 .trend / .trend-col / .trend-pair / .trend-bar / .trend-x / .legend) */
.trend { display: flex; align-items: flex-end; gap: 10px; height: 150px; padding-top: 10px; }
.trend-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
.trend-pair { display: flex; align-items: flex-end; gap: 3px; height: 118px; width: 100%; justify-content: center; }
.trend-bar { width: 9px; border-radius: 3px 3px 0 0; min-height: 2px; }
.trend-bar.consume { background: var(--accent); }
.trend-bar.earn { background: color-mix(in oklch, var(--ok) 80%, var(--muted)); }
.trend-x { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.legend { display: flex; gap: 16px; font-size: 11.5px; color: var(--muted); margin-top: 10px; }
.legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: 5px; }
.legend i.consume { background: var(--accent); }
.legend i.earn { background: color-mix(in oklch, var(--ok) 80%, var(--muted)); }

/* .bar-track / .bar-fill:原型横向条(.bar > i 的结构化别名,供新视图使用) */
.bar-track { height: 8px; border-radius: 999px; background: var(--fg-soft); overflow: hidden; }
.bar-fill { height: 100%; border-radius: 999px; background: var(--accent); }
.bar-fill.alt { background: color-mix(in oklch, var(--accent) 45%, var(--muted)); }
/* .bar-row .bar-top:原型「名称左 / 数值右」的行头(线上 .bar-label 为其别名) */
.bar-row .bar-top { display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 5px; }

/* ---- 空态 ---- */
/* .empty = .empty-state 的原型别名(纯文案空态,无图标) */
.empty { text-align: center; color: var(--muted); padding: 40px 20px; font-size: 13px; }
.empty.compact { padding: 16px 8px; }

/* ---- 面包屑 ---- */
.crumb { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 6px; }

/* ---------- 响应式预留 ---------- */

@media (max-width: 900px) {
Expand All @@ -1046,6 +1175,11 @@ mark {
@media (max-width: 560px) {
.stat-grid { grid-template-columns: 1fr 1fr; }
.card-grid { grid-template-columns: 1fr; }
/* 通用组件层窄屏(原型 responsive):三等分栅格与主次分栏堆叠;趋势图收紧高度 */
.card-grid-3 { grid-template-columns: 1fr; }
.split { grid-template-columns: 1fr; }
.trend { height: 120px; }
.trend-pair { height: 92px; }
.api-key-card { margin-top: 12px; }
/* 网关端点卡片窄屏:chip 与 URL 上下排(原型 responsive 规则) */
.gw-ep { grid-template-columns: 1fr; gap: 6px; }
Expand Down
10 changes: 5 additions & 5 deletions ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ <h2 data-i18n="view.marketplace">模型市场</h2>
<p data-i18n="view.marketplace.sub">浏览 / 搜索各家模型,按点数计价</p>
</header>
<div class="toolbar">
<span class="search-box">
<span class="search">
<input id="mk-search" class="input" data-i18n-ph="mk.search.ph" placeholder="搜索模型名 / 厂商…">
<button type="button" class="search-clear" hidden aria-label="清空搜索" data-i18n-title="mk.clear" title="清空搜索">×</button>
</span>
Expand Down Expand Up @@ -430,7 +430,7 @@ <h3 data-i18n="settings.endpoints">接入方式</h3>
<div class="card api-key-card">
<h3 data-i18n="settings.apikey">API Key</h3>
<p class="muted" data-i18n="settings.apikey.sub">用于本地工具 / 代码接入平台的密钥。独占整行,避免表格字段挤压。</p>
<span class="search-box" style="display:block;margin-bottom:10px">
<span class="search" style="display:block;margin-bottom:10px">
<input id="ak-search" class="input" data-i18n-ph="settings.ak.search.ph" placeholder="搜索 key 名字…">
<button type="button" class="search-clear" hidden aria-label="清空搜索" data-i18n-title="common.search" title="清空搜索">×</button>
</span>
Expand Down Expand Up @@ -535,7 +535,7 @@ <h3 data-i18n="admin.usage.byDept">按部门用量</h3>
<div class="stat-grid" id="dept-stats"></div>
<div id="dept-demo-note"></div>
<div class="toolbar">
<span class="search-box">
<span class="search">
<input id="od-search" class="input" data-i18n-ph="admin.org.search.ph" placeholder="搜索部门…">
<button type="button" class="search-clear" hidden aria-label="清空搜索" title="清空搜索">×</button>
</span>
Expand Down Expand Up @@ -572,7 +572,7 @@ <h3 id="dept-form-title">添加部门</h3>

<div class="admin-pane hidden" data-admin-pane="models">
<div class="toolbar">
<span class="search-box">
<span class="search">
<input id="model-search" class="input" data-i18n-ph="admin.models.search.ph" placeholder="搜索模型…">
<button type="button" class="search-clear" hidden aria-label="清空搜索" title="清空搜索">×</button>
</span>
Expand Down Expand Up @@ -666,7 +666,7 @@ <h2 data-i18n="view.ops">运营视图</h2>
<h3 data-i18n="ops.users.title">用户充值</h3>
<p class="muted" data-i18n="ops.users.sub">运营者 = 宿主本人(职责最小化:仅运行概览 + 充值)。按用户名 / 邮箱定位用户 → 输入点数金额 → 确认后余额增加<strong>永久有效点数</strong>并产生一条交易记录。</p>
<div class="toolbar">
<span class="search-box">
<span class="search">
<input id="ops-search" class="input" data-i18n-ph="ops.users.search.ph" placeholder="搜索用户名 / 邮箱…">
<button type="button" class="search-clear" hidden aria-label="清空搜索" title="清空搜索">×</button>
</span>
Expand Down
Loading
Loading