Skip to content

feat(ui): redesign settings/admin/ops views on the landed component layer - #157

Merged
argszero merged 1 commit into
mainfrom
feat/ui-settings-admin-ops
Sep 11, 2026
Merged

argszero merged 1 commit into
mainfrom
feat/ui-settings-admin-ops

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Slice 6/6 (final) of the full-site UI redesign (rant 2026-09-11T16:23:43), covering the last three views: settings, admin and ops. Built on the design-token / shared-component layers landed by PR1–PR5, so no new visual primitives are introduced — only the remaining pages are aligned with the approved prototype.

Settings (#view-settings)

  • Endpoint card reworked into the prototype's three .endpoint-row blocks: three-column grid (.ep-tag label → .ep-url single-line mono URL → .ep-copy button) with the .ep-desc description flowing below at column 2 (.ep-copy stays right-aligned).
  • Added the missing OpenAI Responses /v1/responses endpoint. The backend route already exists (src/gateway.rs), it was simply not surfaced in the UI.
  • Account section: added the email field (read-only, explains that the email is the login identity).
  • Preferences: added a default-model <select> fed by the real /api/models payload through the existing marketplace loader (no hard-coded model list).
  • Page-head breadcrumb (crumb) added, matching the other redesigned views.

Admin (#view-admin)

  • Employees pane: added member search (#emp-search, wired through the shared wireSearch helper) and the prototype columns (member / role / department / permanent points / gift points / available).
  • Toolbars aligned with the prototype using the .grow spacer so the primary action sits flush right (verified with a geometry probe: 0 px right-edge gap).
  • Page-head breadcrumb added. The existing 4 tabs and all their behaviour are preserved.

Ops (#view-ops)

  • Runtime pane extended with "Today's calls (hourly)" — a .bar-list of 24 hourly bars (#ops-hours).
  • Added "Upstream key health" — a .mini-list (#ops-keys) grouping listed keys per provider into healthy / abnormal pills.
  • Page-head breadcrumb added. The existing 2 tabs are preserved.

Backend

  • GET /api/ops/runtime now also returns today_hours (24 buckets, zero-filled 0–23) and key_health (per-provider total / on / off).
  • Zero-filling matters: a GROUP BY on the hour omits hours without calls, which would shift the whole bar chart left — the same trap already fixed for the transactions trend (txTrendDays) and the dashboard trend (dashTrendDays).
  • New test ops_runtime_credits_users in src/routes/mod.rs.

Docs

  • ui/README.md: updated settings / admin / ops descriptions and fixed a stale .search-box reference (the class was renamed .search in PR3).

Related rant

rant 2026-09-11T16:23:43 (project aitokenpool) — final slice; it is marked completed once this PR is merged.

Tests

  • cargo test — 148 passed, 0 failed
  • cargo fmt --check — clean
  • cargo clippy --all-targets — clean (no warnings)
  • node --check on app.js / api.js / data.js / i18n.js — all clean
  • i18n ZH/EN exact parity: 762 = 762 keys, 0 missing, 0 unresolved data-i18n in index.html (only expected dynamic key is share.day.*, built at runtime and present in both locales)
  • Headless two-theme DOM-marker check (settings / admin / ops, light + dark): expected crumbs, member rows, stat cards, 24 hour bars, key-health items, pills; 0 load-error rows; EN build has 0 ZH-only markers (remaining CJK strings are pre-existing runtime-i18n'ed titles and the language selector)
  • Geometry probe PASS: all 3 endpoint rows render on one line with the description below at column 2 and the copy button flush right; toolbar .grow spacer leaves a 0 px gap
  • Visual review of the rendered screenshots (dark settings/ops, light admin)

…ayer

rant 2026-09-11T16:23:43(全站 UI 重设计)第 6/6 片:设置 + 管理 + 运营三个视图。

- 设置:端点卡片改为原型 .endpoint-row 三行(.ep-tag 标签 → .ep-url 单行 url →
  .ep-copy 复制按钮,描述 .ep-desc 在第二列下方换行),补 OpenAI Responses
  /v1/responses(后端 src/gateway.rs 已实现);账号补邮箱字段;偏好补默认模型下拉
  (数据来自真实 /api/models);补页面面包屑。
- 管理:成员列表补搜索(#emp-search)+ 原型列(成员/角色/部门/永久点数/赠送点数/可用),
  工具栏用 .grow 占位对齐原型,补页面面包屑。
- 运营:运行概览补「今日调用量(按小时)」24 根柱(后端 /api/ops/runtime 新增
  today_hours,0-23 全量补零)+「上游 key 健康」mini-list(key_health 按厂商
  total/on/off 聚合),补页面面包屑。
- README 更新设置/管理/运营三视图说明;修正过期 .search-box → .search 描述。

Gates: cargo test 148 passed / fmt + clippy clean / node --check x4 /
i18n ZH-EN 762=762 parity / headless 双主题 DOM 标记 + 几何探针 PASS。
@argszero
argszero merged commit 09e4121 into main Sep 11, 2026
1 check passed
@argszero
argszero deleted the feat/ui-settings-admin-ops branch September 11, 2026 11:06
@argszero argszero mentioned this pull request Sep 11, 2026
13 tasks
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
`ui/index.html` carries every `data-i18n` string twice: once as the
element's static text (the fallback) and once in the pack
(`ui/js/i18n.js`). `applyStatic()` overwrites the element with the pack
value on DOMContentLoaded, so the fallback is normally invisible — but it
is still a second source of truth, and two of its entries state things
that are no longer true:

- `ops.hours.sub`: 「按小时用量记录 · 本地时区」. The backend buckets
  `today_hours` by UTC (`src/routes/ops.rs:5`, `:115`) and the pack says
  「服务端 UTC 时区」. Introduced already-contradictory in 09e4121 (#157).
- `settings.ep.note`: 「部署后替换为你的网关域名(原型占位说明)」 — a
  verbatim copy of the prototype (docs/prototype/aitokenpool-console.html:705)
  including the 「原型占位说明」 marker. The endpoint card became
  config-driven in e74f7fc (#96) and the pack was updated then; only the
  static fallback was left behind.

Both static strings are now identical to their pack entry. Data-only
(HTML text), zero behaviour change: the rendered UI already showed the
pack value, so no user-visible output changes. No i18n key added or
removed (786 keys before and after), no JS/CSS touched, so no cache-bust.

The remaining fallback divergences are deliberate older wording (which is
the fallback's purpose) and are left alone; only false/stale text is a
defect.

Co-authored-by: argszero <argszero@argszerodeMac-mini.local>
argszero added a commit that referenced this pull request Sep 15, 2026
…263)

The three configuration cards in Settings (account / notifications /
preferences) each render a control that looks operable but has no consumer
anywhere:

- `#settings-nickname`: editable, filled from the real `/api/me`, but there is
  no write path for a nickname at all -- `UPDATE users` only touches
  `dept_id` / `verified` / `password_hash` -- and no listener, so an edit is
  silently discarded on the next `renderSettings`. Its own card sibling
  `#settings-email` is already `readonly` with a hint: commit 09e4121 (#157)
  did both for the email and missed the nickname.
- `#prefs-model`: filled from the real `/api/models`, but no listener, no
  storage key and no reader (`openChat` is only ever called with an explicit
  model). Its three card siblings (lang / theme / density) all persist and
  take effect.
- the three notification toggles: rendered *checked*, with no id, no name and
  no reader -- the repository has no notification subsystem at all.

The fix is not "make them work" (that needs a backend route and a consumer that
do not exist); it is the repository's own idiom for "capability not open"
(`#withdraw-btn`: `disabled` plus a short note): declare the control inert and
say why, in both language packs. Wired siblings are left untouched.

- `#settings-nickname` and `#prefs-model` get `readonly` / `disabled` plus a
  hint; the three notification toggles get `disabled` plus a card-level hint
  (they also lose the misleading `checked`).
- Three new i18n keys, both packs.
- New static gate
  `state_gate::settings_controls_are_either_live_or_marked_inert`, scoped
  explicitly to those three cards: a control that is not consumed must be
  marked inert, a control that is consumed must not be, and a card holding an
  inert control must carry a hint whose key exists in both packs.
- Companion extractor self-test: "filled" is not "consumed", and neither is
  "persisted" -- writing the value to `localStorage` with no reader is the
  half-fix this gate rejects.
- `ui/README.md` convention section; `ui/index.html` cache-bust
  `i18n.js?v=...-4`; `src/i18n_pack.rs` positive-control constants recalibrated
  to the values the gates reported.
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