fix(ui): label a market row's availability from the row, not from a missing key count - #248
Merged
Merged
Conversation
…issing key count 游客市场每一行的「可用性」都渲染成「无 key」,而同一行的绿点是亮的、「使用」按钮 是可点的 —— 同一格里两处文案互相打脸。 一个市场行的可用性只有**一个**事实:`avail`(绿点 / 「使用」按钮的 disabled / 「仅可用」筛选 / 展开详情的「当前可用」四处都读它)。`keys` 只是**有计数时才存在** 的补充说明:登录态由 `modelsToView()` 从 `/api/models` 的 `available_keys` 填, 游客兜底表 `data.js > MARKET` 按 rant 2026-08-19T15:54:06「虚构数据已移除」不带计数 (同源被删的还有 `multi` / `success`)。可用性 pill 却只认 `keys`,于是 `m.keys || 0` 恒为 0,游客 7/7 行都落进「无 key」档。 jsdom 实测(真 `ui/index.html` + 四个真脚本,只 stub `fetch`):游客腿 7 行中 6 行 圆点亮、按钮可点、pill 却写「无 key」;登录腿是阳性对照 —— 三档计数 pill 都正常, 说明 pill 本身没坏,坏的是游客数据里被读的那个字段不存在。 改法:pill 先看计数(≥2 / ==1),没有计数时回落到 `m.avail`(新键 `mk.avail.on`)。 **不给兜底表补手写计数** —— 那是把虚构的运营数据摆给游客看。 CI:`catalog_gate::market_availability_pill_agrees_with_the_row_it_renders` 同时钉住 消费侧(pill 必须读 `m.avail`)与数据侧(`MARKET` 行不得出现手写 `keys`), `js_function_body_stops_at_the_right_place` 自证提取器并有合成输入对照。
argszero
added a commit
that referenced
this pull request
Sep 15, 2026
Ships the 18 PRs merged since v0.7.24 (#242-#259). Schema 14 -> 15 (two covering indexes, applied at startup). No config change, so no deployment-side config.toml edit is needed. Two themes: Perf on the NFS dev database - #259: stop mapping the db (PRAGMA mmap_size 64MB -> 0) and stop a real write per request (dao::touch_api_key gains a 60s guard). Measured on the live dev db: mmap=64MB 1.7-3.1s per COUNT / 250 MiB read vs mmap=0 ~10.5ms / 80 KiB; mmap=0 alone still leaves ~1.2s behind any write, so the pair is required. - #242: codify the two emergency indexes in a v15 migration and gate the conditional joins at the plan level. - #243: read the sharing page's earn total from one batched aggregate. Frontend: display must equal what it filters on, and one fact, one source - #250 one writer for the transaction cache; #251 clear every session slot at the identity boundary and give the wallet view a loader; #253 one shared writer for the wallet/dashboard month-changes; #254 boot loads only the destination view; #255 a model row's identity is the model, not its index; #256 the marketplace source follows the session, not whether data arrived; #257 the sidebar advertises only digits that work; #258 the admin total-balance card sums the gift amount its caption names. i18n - #249 every backend error reaches the wordlist, and the comment stripper stops mangling UTF-8; #252 the backend stops inventing Chinese display labels in response data fields. Forms and robustness - #244 a non-auth boot failure no longer looks like being logged out; #245 a credential 401 is no longer read as a session expiry; #246 wire timestamps reach the renderer unsliced; #247 inline cards submit from every field; #248 a market row's availability label comes from that row. - Cargo.toml / Cargo.lock: 0.7.24 -> 0.7.25. - CHANGELOG.md: v0.7.25 entry. - ui/index.html: cache-bust left as-is; the UI PRs in this release already advanced it past the value deployed with v0.7.24 (app.js 20260915-13, i18n.js 20260915-3). cargo test 288 passed; cargo fmt --check clean; clippy unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On the guest marketplace every row's availability cell reads "No key", while on the same row the availability dot is green and the 使用 / Use button is enabled — two pieces of copy on one row contradicting each other.
A market row's availability has exactly one fact:
avail. It is what the dot (.dot), thedisabledstate of the 使用 button, the "Available only" filter and the expanded detail's "当前可用 / 当前繁忙" all render.keysis not a second fact — it only exists when a count is known: the logged-in path fills it from/api/models→available_keysviamodelsToView(), and the guest fallback table (data.js > MARKET) deliberately carries no count (rant 2026-08-19T15:54:06:multi/successwere removed as fabricated data). The availability pill, however, read onlykeys, som.keys || 0was 0 and every guest row fell into the "no key" branch.Measured in jsdom with the real
ui/index.html+ the four real scripts (onlyfetchstubbed):keys=3/1/0) render correctly, so the pill itself is not broken; what is missing is the field it reads on guest rowsRelated Issue
Changes
ui/js/app.js:availPill()keeps the count states (>=2multi,==1tight) and falls back to the row's ownavailwhen no count is present, so the cell can no longer contradict the rest of the row.ui/js/i18n.js: new keymk.avail.on(zh 「可用」 / en "Available") — the honest label when only "usable" is known.mk.avail.multi/mk.avail.tight/mk.avail.noneunchanged.ui/index.html: cache-busti18n.js/app.js.src/catalog_gate.rs: new gatemarket_availability_pill_agrees_with_the_row_it_renderspinning both halves — the consumer must consultm.avail(with the fallback table's booleanavailas the positive control that the field name is real), andMARKETrows must not carry a hand-writtenkeyscount (that would put fabricated operational data in front of guests).js_function_body_stops_at_the_right_placeproves the extractor stops at the right place and that the assertion has teeth via a synthetic input.src/i18n_pack.rs: key-count constants follow the +1 key (the extractor's own output was used for calibration, not hand arithmetic).ui/README.md: new convention section + key-count sentence kept in sync.Not the fix: adding hand-written counts to
MARKET. That is the same thing v1.22 cleaned up (multi/success); if guests are to see a real count it has to come from/api/models.Tests
cargo test— 262 passed / 0 failed (was 260; +2 new gate tests)cargo fmt --check— cleancargo clippy— only the pre-existing warning atsrc/protocol.rs:662A/B evidence (
tmp/c2128_*, all UI mutations injected fromtmp/through env vars — the work tree is never rewritten):v0_orig(pinnedecc654capp.js/i18n.js){B1, B2, B3}m_swap(pill reads onlym.avail, count states dropped){C2}m_fabricate(competing fix: hand-writtenkeysinMARKET){}MARKET-must-not-carry-keyshalf goes red)live{}In-place gate legs (byte-identical restore verified by md5):
m_nofallback→ red at the consumer assertion;m_fabricate→ red at the data assertion.Checklist
fix/)