Skip to content

fix(ui): restore data-label coverage and colspan parity in the admin models table - #162

Merged
argszero merged 1 commit into
mainfrom
fix/admin-models-data-label-colspan
Sep 11, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/admin-models-data-label-colspan

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

renderAdminModels() (admin 模型管理 table, #model-body) was the only one of the seven table renderers that broke the interface conventions documented in ui/README.md — and it broke two of them at once. Both were introduced by the same commit that created the table (98a7a9b), i.e. the table has shipped this way since birth.

1. data-label coverage was 1 of 8 cells.
The README states the convention twice (所有表格 td 必须带 data-label, enforced by td::before { content: attr(data-label) } under @media (max-width:560px)). Under 560px the thead is hidden and every row is rendered as a card, so seven of the eight fields appeared with no label at all. The other six renderers are complete: mk-body 7/7, share-body 8/8, api-keys 6/6, emp-body 7/7, dept-body 7/7, ops-body 4/4. The seven missing labels (厂商 / 模型 / 输入价 / 输出价 / 上下文 / 最大输出 / 读图) were added as literal strings, matching the existing convention — the other renderers' ~30 labels are all literals, not i18n-driven, so a literal set is the minimal consistent change.

2. Empty/error rows used colspan=7 against an eight-column table.
The 读图 column has been present since the table was created, so loadErrorRow(7, …) / emptyRow(7, …) under-covered the table. The other six renderers' colspan arguments all match their own column counts exactly (7/8/6/7/7/4).

Bumped the asset cache-bust 20260911-6 → 20260911-7 (5 refs in ui/index.html).

Related Issue

Changes

  • 修复说明:ui/js/app.js — add the 7 missing data-label attributes in renderAdminModels(); change loadErrorRow(7,…) and emptyRow(7,…) to 8.
  • ui/index.html — cache-bust -6 → -7 (CSS + 4 scripts).
  • 涉及配置/数据结构的改动已同步示例文件 — not applicable, no config or data-structure change.

Tests

  • cargo test 全部通过 — 148 passed; 0 failed.
  • cargo fmt --check 通过.
  • cargo clippy --all-targets -- -D warnings 通过(无新增 warning).
  • 新增/更新了单元测试(如适用)— not applicable: this is a static markup fix with no Rust code path; verified instead with a headless-browser A/B harness (below).

Measured before/after evidence (headless Chrome, both trees produced by the same generator; baseline rebuilt from git HEAD, matched by identity key = cell text):

Axis Before After
Card mode @≤560px, labelled cells 1/8 (matchMedia true, thead display:none) 8/8 — the same 7 identity-keyed cells gained a label
Desktop @1400px thead table-header-group, 8 cells unchanged — no desktop regression
Desktop error row cell width 984px / 1044px = 94.3% (60px gap) 1044px / 1044px = 100%
Mobile error row card mode does not render colspan (block layout) unchanged

Gate: node --check ×4 OK; i18n key-set parity 762 == 762, 0 unresolved static keys.

Checklist

  • 分支命名符合约定(fix/admin-models-data-label-colspan)
  • Commit message 使用 Conventional Commits 格式(fix(ui): …)
  • 单一职责,改动最小化

…models table

`renderAdminModels()` was the only one of the seven table renderers that
violated the interface conventions documented in `ui/README.md`, in two ways
at once (both introduced by the same commit that created the table, 98a7a9b):

1. `data-label` coverage was 1 of 8 cells. Under `@media (max-width:560px)`
   the thead is hidden and each row is rendered as a card via
   `td::before { content: attr(data-label) }`, so seven of the eight fields
   were displayed without any label. The other six renderers are complete
   (mk-body 7/7, share-body 8/8, api-keys 6/6, emp-body 7/7, dept-body 7/7,
   ops-body 4/4). Added the seven missing labels as literal strings, matching
   the existing convention used by the other renderers (they are all literal
   rather than i18n-driven).

2. The empty and error rows used `colspan=7` against an eight-column table
   (the 读图 column has existed since the table was created), so the cell
   under-covered the table: measured in Chrome at 1400px the cell was 984px
   of a 1044px table, leaving a 60px gap. Both rows now use `colspan=8`.

Bumped the asset cache-bust to 20260911-7.

Verified in a headless Chrome A/B harness, with both the baseline and the
fixed tree produced by the same generator (baseline rebuilt from git HEAD):
card mode @<=560px goes from 1/8 to 8/8 labelled cells over the same seven
identity-keyed cells, while desktop keeps the thead rendered; the desktop
error row goes from 94.3% to 100% of the table width. Mobile card mode is
unaffected by the colspan change (thead hidden -> block layout).
@argszero
argszero merged commit d8031b9 into main Sep 11, 2026
1 check passed
argszero added a commit that referenced this pull request Sep 13, 2026
ui/ writes each table's column count by hand in several places — the <thead>,
the empty-state emptyRow(N, …) colspan, the load-failure loadErrorRow(N, …)
colspan, and the number of <td> in the row template. Nothing fails at runtime
when they disagree: a short colspan just paints the row narrow, a long one is
silently clipped, and the empty/error row is only visible when the list is
empty or the request failed. That is how #97 happened (adding an 8th column to
the admin models table left the empty state at colspan=7); #162 only fixed the
symptom by hand.

src/table_gate.rs is a test-only gate in the same shape as catalog_gate.rs and
i18n_pack.rs (#[cfg(test)] in main.rs, zero new dependencies, no regex, no JS
execution, no browser). It reads ui/index.html and ui/js/app.js as text and
asserts, for every <tbody> table:

  - positive control: exactly the seven registered tables are found, each with
    its true <thead> column count (a scanner bug that returns an empty set fails
    here instead of letting the set assertions pass vacuously);
  - emptyRow(N) colspan == the table's column count;
  - loadErrorRow(N) colspan == the table's column count;
  - the row template has exactly one <td> per column, with whole-row colspan
    cells (the marketplace detail row) excluded;
  - the only literal colspan is that detail row, and index.html contains none;
  - the transactions table derives its colspan from columns.length instead of
    hard-coding a number;
  - <tbody> containers receive <tr>-shaped rows (loadErrorRow) and never a bare
    <div> — the browser hoists a bare <div> out of the table and the retry
    button then loses setLiveError's container-level delegation.

The assertions are split per dimension so a single failure names the dimension
that drifted. Site-to-container attribution is positional (the nearest preceding
$("#id").innerHTML assignment / setLiveError($("#id"), …)), not a JS parse.

Tests: 9 new; cargo test 226 -> 235, fmt and clippy clean.

A/B: six mutations, each applied alone and restored byte-identically (md5
verified), produce five distinct red sets — empty colspan, thead column count,
row-template cell count, error-row colspan, and the literal/dynamic colspan pair.
An 8th thead column and an unregistered new table both trip the positive control
(same assertion, different inputs — recorded honestly). The unmutated tree is
green on all six legs, as a live control.
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