Skip to content

feat(ui): redesign wallet/transactions views on the landed component layer - #156

Merged
argszero merged 1 commit into
mainfrom
feat/ui-wallet-transactions
Sep 11, 2026
Merged

feat(ui): redesign wallet/transactions views on the landed component layer#156
argszero merged 1 commit into
mainfrom
feat/ui-wallet-transactions

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Fifth slice of the full console UI redesign — the wallet and transactions views, adapted to the new prototype (docs/prototype/aitokenpool-console.html) while keeping every existing behaviour the prototype does not cover.

Source instruction (verbatim, for traceability): the host rant 2026-09-11T16:23:43

  1. 钱包
  • wallet-hero:大字号余额(.balance-big + .unit「点」)+ 「永久点数 X · 每日赠送点数当日有效」说明
  • 动作按钮:充值(primary)/ 申请加额(secondary)/ 提现(disabled,标「暂不支持」)
  • 充值行内卡片:预设金额 chips(100/500/1000/5000)+ 自定义金额 + 确认/取消
  • 申请加额行内卡片:申请点数 + 申请原因(textarea)+ 提交
  • 保留现有「行内展开、不用弹窗」的既有约定
  1. 交易记录
  • page-head 右上「导出 CSV」(保留现有导出逻辑)
  • tab:全部/消费/收益(保留现有 data-tx-tab;注意现有列筛选里还有 withdraw/gift 类型,后端已支持,不要砍掉
  • 工具栏:时间范围下拉 + 记录数(#tx-count)
  • 汇总 stat-grid(.tx-summary:消费/收益/点数变化/Token 合计/记录数)
  • 每日消费/收益趋势图(.trend + legend)—— x 轴必须左→右时间递增(原型此 bug 已修复,实现时勿反向)
  • 明细表:时间、类型、模型/Key、输入、缓存、输出、合计 Token、点数
  • ⚠️ 必须保留线上已有的强功能,原型未体现但绝不能丢:a. 列筛选整行 … b. 自定义时间段 … c. 后端真分页 … d. 数字列的单位换行展示(tokenBrk 提示)

Related Issue

None — this repository currently has zero open issues; the work is driven by the host rant quoted above. Previous slices: #152 (design tokens), #153 (login + sidebar), #154 (component layer), #155 (dashboard / marketplace / sharing).

Changes

  • Wallet — page head gains the prototype crumb; wallet-hero now shows the big balance with the unit plus the permanent-points hint, and splits the actions into primary (top-up) / secondary (raise request, withdraw-disabled) buttons. Top-up presets switched to prototype .chip elements (selected state .on) and gained the 5000 preset.
  • Transactions — the summary bar is now a .stat-grid of five .stat-card entries (expense / income / net / tokens / record count) built on the shared component layer from feat(ui): add shared component layer (stat-card/pill/tag/toolbar/bar-list) + define missing button variants (rant 2026-09-11, PR3) #154; the record count also appears in the toolbar as #tx-count, and the CSV export button moved to the page head as in the prototype.
  • Trend chart#tx-trend renders the prototype dual-bar .trend (consume vs earn) from the same /api/transactions/trend payload. Buckets are zero-filled across the requested window, so the x axis stays left-to-right chronological with a constant bar pitch — the backend GROUP BY only returns buckets that have transactions, and the missing rows are exactly what shifted the bars in the prototype.
  • Deliberately preserved (not visible in the prototype): the entire column filter row (stable DOM — inputs are not destroyed on re-render — delegated container events and IME composition guard), the 24h and custom time ranges including the datetime-local inputs, server-side pagination with page-size switching, tokenBrk breakdown titles, and the withdraw / gift filter types.
  • CSS.toolbar > select is width:auto; the column-filter .th-filter carries width:100% for table cells, which stretched the time-range dropdown across the whole row. Dead .tx-summary / .tx-trend selectors removed. Component-only change, no build step.
  • i18n — new keys for every added/changed string, six obsolete keys dropped; ZH and EN dictionaries remain at exact parity (733 keys each).
  • No backend change — this is a pure front-end adaptation and the API contract is untouched.

Tests

  • cargo test148 passed / 0 failed
  • cargo fmt --check — clean; cargo clippy --all-targets -- -D warnings — clean
  • node --check on app.js, i18n.js, api.js, data.js
  • i18n gate: ZH/EN key sets identical, no missing keys, no placeholder mismatches, every data-i18n key resolves
  • Headless visual check (local HTTP + headless Chrome, both themes, ZH and EN builds): wallet and transaction views render real data — 5 summary cards, 11 trend columns / 22 bars, populated table with pager, 7 column-filter inputs, 12 token-breakdown titles, no load-error rows, and the EN build keeps no residual Chinese or raw keys
  • Geometry probe on the live page confirms the time-range <select> is ~109px wide instead of full width, the trend renders 11 left-to-right columns over a 603px chart, and the month rows are present

Checklist

  • Branch name follows the convention (feat/)
  • Commit message uses Conventional Commits
  • Single responsibility, minimal diff (UI only)

…layer

Adapt the wallet and transactions views to the new high-fidelity prototype
(rant 2026-09-11T16:23:43, section 6/7), keeping every existing behaviour the
prototype does not cover.

Wallet:
- page-head gains a crumb; wallet-hero shows the big balance with unit, the
  permanent-points hint and primary/secondary action buttons
- topup presets become prototype .chip elements (select state .on) and now
  include the 5000 preset

Transactions:
- summary bar becomes a .stat-grid of 5 .stat-card entries (expense / income /
  net / tokens / record count) using the shared component layer; the pager
  count moves to a toolbar #tx-count
- trend card renders the prototype dual-bar .trend chart (consume vs earn) from
  the same /api/transactions/trend payload; buckets are zero-filled over the
  requested window so the x axis stays left-to-right chronological with a
  constant bar pitch (the backend GROUP BY omits days without transactions)
- detail card gets a heading and card-sub, and the CSV export button moves to
  the page head, matching the prototype

Preserved on purpose (prototype does not show these): the whole column filter
row (stable DOM, delegated events, IME guard), the 24h and custom time range
(including the datetime-local inputs), server-side pagination with page size
switching, the three-tier token breakdown titles and the withdraw/gift types.

CSS: .toolbar > select is width:auto (the column-filter .th-filter inherits
width:100%, which stretched the time range dropdown across the whole row),
dead .tx-summary/.tx-trend selectors removed. i18n gains the new keys, ZH/EN
stay at exact parity (733 keys each).
@argszero
argszero merged commit 41bb6d1 into main Sep 11, 2026
1 check passed
@argszero
argszero deleted the feat/ui-wallet-transactions branch September 11, 2026 10:39
argszero added a commit that referenced this pull request Sep 11, 2026
发布 v0.7.21(rant 2026-09-11T21:03:06)。

- Cargo.toml / Cargo.lock: 0.7.20 → 0.7.21
- ui/index.html: cache-bust ?v=20260911-2 → ?v=20260911-3(5 处资源引用)
- CHANGELOG.md: 新增 v0.7.21 条目,概括 6 片全站 UI 重设计
  (#152 OKLCH 设计 token 层 / #153 登录页左右分栏 + 侧边栏 / #154 共享组件层 /
  #155 仪表盘·市场·共享 / #156 钱包·交易 / #157 设置·管理·运营)

本次为纯前端改动,后端契约未变;部署结构不变(数据库仍留 NAS,不启用 WAL)。

Gates: cargo test 148 passed / cargo fmt --check clean / cargo clippy clean /
node --check x4 / i18n ZH-EN 762=762 exact parity.

Co-authored-by: argszero <argszero@argszerodeMac-mini.local>
argszero added a commit that referenced this pull request Sep 13, 2026
…e's x axis is time (#218)

`GET /api/dashboard`'s `series` was a sparse day-bucket list: `GROUP BY
date(time)` emits a row only for days that actually have transactions, and
`ui/js/app.js::renderMonthChanges` feeds that list straight into
`sparkline()`, which places point i at an INDEX-based x
(`pad + i*(w - 2*pad)/(len - 1)`) rather than at its date. Days without
transactions were therefore collapsed instead of being shown as zero:

  * a week with a single active day degenerated to a lone `M` command, i.e.
    no line at all, while the number above it still rendered;
  * a week with two active days was drawn as one straight line across the
    full 7-day width, claiming a trend the data does not support.

Every sibling time series in this tree is zero-filled to its own window and
says why: `routes/ops.rs::runtime` fills hours 0..23 ('若不补零前端柱状图会
整体左移'), `app.js::dashTrendDays` and `app.js::txTrendDays` fill their day
buckets, and the guest branch of this very function always hands over 7
points. This was the only consumer that did not, so treat it as the omission
it is: `f525242` (#79) wired the sparse series up and the siblings were fixed
afterwards (#155/#156 and the ops PR6).

Fix: build the window with a recursive CTE (today plus the previous 6 days,
UTC) and a LEFT JOIN whose ON clause carries the user filter. The filter has
to stay in the JOIN condition: in WHERE it would drop exactly the empty days
this change exists to add. Only `src/routes/wallet.rs` changes; the window
semantics (a 7-day day-key window anchored on date('now', '-6 days'), UTC)
and the `month` / `net` windows of C2049 are untouched.

Evidence, all driven through the real router:
- `dashboard_series_is_a_zero_filled_seven_day_window`: 7 rows, ascending,
  the date set compared against chrono (`Utc::now()`) as an independent
  authority rather than derived from the CTE.
- `dashboard_series_zero_fills_inside_the_user_and_the_window`: per-day
  values equal a plain per-day SUM for the same user; another user's row
  inside the window and this user's row outside it never appear; a positive
  control re-checks a zero-filled day after a later transaction lands on it.
- `wallet_summary_and_dashboard`'s `!series.is_empty()` (trivially true once
  the window is filled) is rewritten into the shape assertion it meant.
- A/B, each mutation applied alone and reverted with the file's md5 restored:
  the pre-change sparse query reddens 3 tests (including both new ones); an
  off-by-one window (`-5 days`) reddens 2, a different set; carrying the user
  filter in WHERE reddens those same 3; comparing a datetime column against a
  date key reddens exactly 1 (the value test). Unmutated tree: 222 passed,
  0 failed.
- jsdom end-to-end (real `ui/index.html` plus the four real scripts, only
  `fetch` stubbed), fed the exact series the patched handler returns: 7
  points / 6 line segments / 7 tooltips, against 1 point / 0 segments for the
  pre-change shape. The 14-day bar chart on the same page keeps rendering 14
  columns in every leg.

Display / API shape only: no ledger, balance or settlement change. No `ui/`
or i18n key touched, so the i18n gate counts are unchanged.
`cargo fmt --check` and `cargo clippy --all-targets -- -D warnings` are clean;
`cargo test` goes from 220 to 222.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant