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
17 changes: 10 additions & 7 deletions ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,21 @@ ui/
- **刷新恢复**:DOMContentLoaded 先 `pendingHashView = viewFromHash()`;登录成功恢复 `pendingHashView || "dashboard"`(游客浏览 / 未登录态不冲突);
- **游客拦截**:游客访问受限 hash(如 `#/settings`)→ `switchView` 内 `GUEST_VIEWS` 拦截(toast 提示),视图与 URL 均保持原状、不入栈新条目。

## 交易汇总条约定(v1.19,rant 2026-08-17T20:39:30 B
## 交易汇总卡约定(v1.19 → v1.23 改版,rant 2026-09-11T16:23:43 第 7 节

- 交易记录页卡片顶部(表格上方)有**紧凑汇总条** `#tx-summary`(`.tx-summary`,三列 inline,不引入新布局):**总收入 / 总支出 / 净变化**,正数 `+` 绿(`var(--ok)`)、负数 `-` 红(`var(--danger-text)`)、零值中性显示 `0`;
- **随 tab 过滤联动**:切换「全部 / 消费 / 收益」tab 即时重算;且与表格**列筛选**一致——汇总基于 `filterRows(list, TX_COLUMNS, txTable.filters)`(`buildDataTable` 的筛选逻辑抽出的公共函数),反映与表格可见行相同的过滤集,**不受分页影响**;
- 窄屏(≤560px)自动收窄间距 / 字号,`flex-wrap` 换行兜底。
- 交易记录页顶部为**汇总卡** `#tx-summary`(`.stat-grid` + 5 张 `.stat-card`,改用 PR3 通用组件层):**消费 / 收益 / 点数变化 / Token 合计 / 记录数**,正数 `var(--ok)`、负数 `var(--danger-text)`、零值中性;
- **口径不变**(数据契约未动):汇总值来自后端 `summary` 全量 SQL 聚合(`filterRows(list, TX_COLUMNS, txTable.filters)` 为无 summary 时的兜底),**不受分页影响**;「记录数」取后端 `total`(真分页下即当前筛选条件的全量条数);
- 工具栏右侧 `#tx-count` 同步显示 `tx.pager.count`(共 N 条),与汇总卡的记录数同源;
- 图表:`#tx-trend` 改用原型 `.trend` 双色柱状(消费 / 收益两柱 + `.legend`),数据源仍是 `/api/transactions/trend`;**x 轴按请求窗口补零,保证左→右时间递增且柱距恒定**(后端 GROUP BY 只返回有交易的桶,缺行会导致柱子左移——原型同款 bug 的根因);
- 窄屏(≤560px)`.stat-grid` 两列、`.trend` 高度收紧。

## select 美化约定(v1.19,rant 2026-08-17T20:39:30 C)

- 全站 `select` **移除原生箭头**(`appearance:none` + `-webkit-appearance:none`),改用**自定义 SVG 下拉箭头**:`--select-arrow` CSS 变量(内联 data-URI,深色主题浅色箭头 `#aab6c8`、亮色主题深色箭头 `#55627a`,`url("data:image/svg+xml,…")` 内空格须 `%20` 编码);
- `padding-right` 预留箭头空间(`select.input` 30px / `.th-filter` 24px / page-size 22px);**hover / focus 边框同 input**(`var(--accent)`,focus 加 `box-shadow: 0 0 0 1px var(--accent)` 光圈);`disabled` 态 `opacity:.55` + `not-allowed`;
- **覆盖所有 select 来源**:静态 `.input`(市场筛选、共享表单三级联动、设置页)、动态 `select.th-filter`(表格列筛选)、`select[data-page-size]`(分页器每页条数);
- ⚠️ 注意:这些选择器的规则**必须用 `background-color` 而非 `background` 简写**(简写会把 `background-image` 置 none 抹掉箭头);`select.input option { background: var(--bg-card) }`(下拉项深色)与 `select.input.input-error`(错误红边框)保持不动。
- ⚠️ 注意:这些选择器的规则**必须用 `background-color` 而非 `background` 简写**(简写会把 `background-image` 置 none 抹掉箭头);`select.input option { background: var(--bg-card) }`(下拉项深色)与 `select.input.input-error`(错误红边框)保持不动;
- ⚠️ `.th-filter` 自带 `width:100%`(表头列筛选需要撑满单元格),因此**工具栏里的直属 select 必须显式 `width:auto`**(`.toolbar > select`)——否则交易页时间范围下拉会拉伸到整行(C1978 视觉复查发现)。

## toast 队列约定(v1.19,rant 2026-08-17T20:39:30 D)

Expand Down Expand Up @@ -259,7 +262,7 @@ ui/

## 交易记录导出 CSV 约定(v1.20,rant 2026-08-17T20:46:57 E)

- 入口:交易页 tab 下右对齐 **`#tx-export-btn`「导出 CSV」**(`.toolbar` justify-end + `btn-ghost`),`bindEvents` 绑 `exportTxCsv`;
- 入口:交易页 page-head 右上 **`#tx-export-btn`「导出 CSV」**(`.btn.btn-secondary.btn-sm`),`bindEvents` 绑 `exportTxCsv`;
- 数据范围:**当前筛选可见行** = tab(全部/消费/收益)→ `filterRows(list, TX_COLUMNS, txTable.filters)`(与表格、汇总条同一数据源);无数据 → toast info 不导出;
- 格式:**UTF-8 BOM**(`"\uFEFF"` 前缀)+ `\r\n` 换行 + 表头 `时间,类型,模型 / Key,Token 用量,点数,状态`;类型用 `TX_TYPE` 中文映射;点数正负号原值;字段含 `,`/`"`/换行按 RFC4180 双引号转义(`cell()` 助手);
- 下载:`Blob(type="text/csv;charset=utf-8")` → `URL.createObjectURL` → 临时 `<a download>` click → `remove()` → `setTimeout 1s` revoke;文件名 **`aitokenpool-transactions-YYYYMMDD.csv`**(`new Date()` 本地日期);
Expand Down Expand Up @@ -304,7 +307,7 @@ ui/

## 界面国际化 i18n 约定(v1.21.1,rant 2026-08-18T20:49:22 + 21:40:10 去中英混排)

- **语言包**:`ui/js/i18n.js` 零依赖 IIFE,`I18N = { zh, en }` 双词典(563 键 ×2,覆盖导航/登录/视图标题/通用/仪表盘/市场/共享/钱包/交易/设置/管理/运营/聊天/游客/相对时间/帮助/tour/主题/错误映射);`window.t(key, vars)` 查当前语言,**缺失回退 zh,再缺回退 key 本身**;`{var}` 占位符插值;
- **语言包**:`ui/js/i18n.js` 零依赖 IIFE,`I18N = { zh, en }` 双词典(733 键 ×2,覆盖导航/登录/视图标题/通用/仪表盘/市场/共享/钱包/交易/设置/管理/运营/聊天/游客/相对时间/帮助/tour/主题/错误映射);`window.t(key, vars)` 查当前语言,**缺失回退 zh,再缺回退 key 本身**;`{var}` 占位符插值;
- **切换机制**:设置页「偏好 → 界面语言」下拉(`#prefs-lang`,zh/en)→ `I18n.setLang()`:写 `localStorage('atp_lang')` + `document.documentElement.lang` 同步(zh→`zh-CN` / en→`en`)+ 派发 `atp:langchange` → app.js 重渲染 `renderNav()` + `renderView(activeView)` + `document.title`(引导中额外 `renderTourStep()`);**首载**:localStorage → `navigator.language` 前缀(`zh*`→zh,否则 en)→ 默认 zh;切换即时生效无需刷新;
- **静态文案**:`index.html` 内静态中文用 `data-i18n` / `data-i18n-ph`(placeholder)/ `data-i18n-title`(title)标记,`applyStatic()` 启动时与每次切换时批量替换;**容器含表单控件的 `<label>` 用 `<label><span data-i18n="KEY">文本</span><input…></label>` 结构**(避免 innerHTML 替换销毁控件);
- **动态文案**:`app.js` 面向用户字符串全部走 `t('key')`;**语言敏感常量存 key 而非文案**(NAV/VIEW_TITLE/TOUR_STEPS/HELP_KEYS 存 key,渲染时 `T()` 解析;SHARE_STATUS/RAISE_STATUS 的 `text` 为函数;TX_COLUMNS 的 `title`/`options` 为函数;`DAY_LABELS` 动态 `T("share.day."+n)`)——保证切换语言后重渲染即时生效;
Expand Down
93 changes: 34 additions & 59 deletions ui/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -343,53 +343,16 @@ select.input option { background: var(--bg-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); }
.tx-summary .ts-item { display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.tx-summary .ts-label { color: var(--text-mute); font-size: 12px; }
.tx-summary .ts-value { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tx-summary .ts-value.ok { color: var(--ok); }
.tx-summary .ts-value.danger { color: var(--danger-text); }

/* 交易趋势图(rant 2026-08-23T16:01:07 需求 2):SVG 折线图,无外部依赖 */
.tx-trend { padding: 8px 16px 6px; border-bottom: 1px solid var(--border); }
.tx-trend-title { color: var(--text-mute); font-size: 11px; margin-bottom: 1px; }
/* 指标切换(rant 2026-08-23T16:17:18 需求 2) */
.tx-trend-switch { display: flex; gap: 5px; margin: 4px 0 6px; flex-wrap: wrap; }
.tsw-btn {
border: 1px solid var(--border);
background: transparent;
color: var(--text-dim);
padding: 2px 10px;
border-radius: 999px;
cursor: pointer;
font-size: 11px;
}
.tsw-btn:hover { color: var(--text); }
.tsw-btn.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); }
.tx-trend-chart { position: relative; }
.tx-trend svg { width: 100%; height: auto; display: block; }
.tx-trend-axis { fill: var(--text-mute); font-size: 8px; }
/* 平滑折线 + 渐变面积(sparkline 化,rant 2026-08-24T10:51:57.821209:
无网格线、无数据点圆、渐变 0.35→0、teal 主题色系——消费用主强调色区分) */
.tx-trend svg .trend-line { fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.tx-trend svg .trend-area { stroke: none; }
/* 悬停引导线 + tooltip */
.tx-trend-guide { position: absolute; top: 2px; bottom: 6px; width: 1px; background: var(--text-dim); opacity: 0.45; display: none; pointer-events: none; }
.tx-trend-tip {
position: absolute; display: none; pointer-events: none;
background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
padding: 6px 9px; font-size: 12px; color: var(--text);
box-shadow: var(--shadow); z-index: 5; white-space: nowrap; line-height: 1.5;
}
.tx-trend-tip b { color: var(--accent-text); font-weight: 600; }
.tx-trend-legend { display: flex; gap: 10px; font-size: 10px; color: var(--text-mute); padding-top: 2px; align-items: center; }
.tx-trend-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 3px; vertical-align: middle; }
.tx-trend-dot.exp { background: var(--accent); }
.tx-trend-dot.inc { background: var(--ok); }
.tx-trend-dot.net { background: var(--accent-text); }
.tx-trend-dot.tok { background: var(--warn); }
.tx-trend-empty { color: var(--text-mute); font-size: 13px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
/* 交易汇总卡(rant 2026-09-11T16:23:43 第 7 节:原型 .stat-grid + .stat-card 取代旧 inline 汇总条;
.stat-grid 的 auto-fit 栅格已在上方定义,卡片内不再需要底部分隔线) */

/* 交易趋势卡(rant 2026-09-11T16:23:43 第 7 节):改用原型 .trend 双色柱状图渲染
(renderTxTrend → .trend-col/.trend-pair/.trend-bar,类定义见上方「图表」节),
旧 SVG 折线图(.tx-trend-title / .tx-trend-switch / .tsw-btn / .tx-trend-chart /
.tx-trend-axis / .trend-line / .trend-area / 悬停 guide+tip / .tx-trend-legend/dot)
及 .tx-trend-empty 随之移除——趋势空态复用 .empty.compact。
.trend 高度固定(150px),窄屏由媒体查询收窄。 */


.table-wrap { overflow-x: auto; }
.table-wrap.compact { margin-top: 4px; }
Expand All @@ -409,9 +372,7 @@ select.input option { background: var(--bg-card); }
.table th.num { text-align: right; }
.table th.num .th-sort { text-align: right; }
/* Token 用量明细(rant 2026-08-21T14:53:20:输入/缓存命中/输出 随行展示,等宽小字) */
.tx-brk { margin-top: 2px; font-size: 11px; line-height: 1.2; color: var(--text-dim); white-space: nowrap; }
.tx-brk .brk-c { color: var(--accent); }
.tx-brk .brk-o { color: var(--ok); }

/* 斑马纹(rant 15:50:05 A.3:行 hover 高亮保留,hover 覆盖斑马纹) */
.table tbody tr:nth-child(even) { background: var(--table-stripe); }
.table tbody tr:hover { background: var(--bg-hover); }
Expand Down Expand Up @@ -453,8 +414,11 @@ select.input option { background: var(--bg-card); }
.badge.accent { color: var(--accent-text); border-color: color-mix(in oklch, var(--accent) 40%, transparent); background: var(--accent-soft); }
.badge.dim { color: var(--text-mute); }

.toolbar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.toolbar .input { max-width: 240px; }
/* 工具栏内的下拉不得占满整行:.th-filter 的 width:100% 是给表头列筛选行的,
直接放进 flex 工具栏会被拉伸到整宽(C1978 视觉复查发现)。工具栏直属 select 一律按内容宽度。 */
.toolbar > select { width: auto; max-width: 240px; }
.toolbar-count { align-self: center; color: var(--text-mute); font-size: 12px; margin-left: auto; }

/* 搜索增强(rant 18:06:09 D:清空 × 按钮 + <mark> 关键词高亮;
Expand Down Expand Up @@ -849,10 +813,22 @@ mark {
.page-head p { color: var(--text-mute); margin-top: 2px; }

.wallet-hero { display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; }
.balance-big { font-size: 42px; font-weight: 800; color: var(--accent-text); line-height: 1.2; }
.balance-big {
font-family: var(--font-mono); font-variant-numeric: tabular-nums;
font-size: clamp(34px, 5vw, 54px); font-weight: 800; letter-spacing: -0.03em; line-height: 1;
color: var(--accent-text); margin-top: 8px;
}
.balance-big .unit { font-size: 16px; font-weight: 500; color: var(--text-mute); margin-left: 6px; }
/* wallet-hero 的标签/提示(原型 h3 12px muted + hint 行;rant 2026-09-11T16:23:43 第 6 节) */
.wallet-hero-label { font-size: 12px; color: var(--text-mute); margin-bottom: 0; }
.wallet-hero-hint { display: block; margin-top: 10px; }
.wallet-hero-hint b { color: var(--text); font-weight: 600; }
.wallet-hero-note { display: block; margin-top: 10px; }
.wallet-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.wallet-note { font-size: 12px; }
.wallet-hint { color: var(--text-mute); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 充值/加额表单动作行(原型 .row:横向按钮排布,不占满整行) */
.form .row, .row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---------- 消费模拟(聊天 Mock · US-6) ---------- */

Expand All @@ -875,10 +851,10 @@ mark {
.modal-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.modal-head h3 { font-size: 16px; margin: 0; }

/* 模态框操作行 / 充值预设(US-4*/
.topup-presets { display: flex; gap: 8px; margin-top: 6px; }
.topup-presets .btn { min-width: 72px; }
.topup-presets .btn.active { background: var(--accent-soft); border-color: color-mix(in oklch, var(--accent) 50%, transparent); color: var(--accent-text); }
/* 模态框操作行 / 充值预设(US-4;rant 2026-09-11T16:23:43 第 6 节:改用原型 .chip + .on 选中态)*/
.topup-presets { gap: 8px; margin-top: 2px; }
.topup-presets .chip { min-width: 64px; justify-content: center; }
.topup-presets .chip.on { border-color: var(--accent); color: var(--accent-text); background: var(--accent-soft); }
.chat-log {
flex: 1; overflow-y: auto;
background: var(--bg-soft); border: 1px solid var(--border);
Expand Down Expand Up @@ -1189,9 +1165,8 @@ textarea.input:focus { border-color: var(--accent); }
/* 网关端点卡片窄屏:chip 与 URL 上下排(原型 responsive 规则) */
.gw-ep { grid-template-columns: 1fr; gap: 6px; }
.gw-chip { justify-self: start; }
/* 交易汇总条窄屏(rant 20:39:30 B) */
.tx-summary { gap: 18px; padding: 10px 12px 8px; }
.tx-summary .ts-value { font-size: 16px; }
/* 交易汇总卡窄屏(rant 2026-09-11T16:23:43 第 7 节:stat-grid 两列,与仪表盘一致) */
.tx-summary { padding: 0; }
/* 移动端表格卡片化(rant 18:06:09 C:隐藏表头,行 → label:value 卡片,不再横滚) */
.table { display: block; }
.table thead { display: none; }
Expand Down
Loading
Loading