fix(web): 列表 meta 行数字组靠左跟排——修 active 静默后的左侧缺口(bump 0.38.7)

active 徽章静默后,无 skill 行的 meta 左槽空置,条/tok 整组右挤留出一块
"缺了东西"的空白。数字组改靠左填槽,仅时间锚行尾;删无意义的 right-group。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-07-03 16:55:32 +08:00
parent 2937b75143
commit 259dde502d
4 changed files with 8 additions and 5 deletions

View File

@ -21,6 +21,9 @@
## 已完成关键能力 ## 已完成关键能力
### 2026-07-03 / web 列表 meta 行数字组改靠左跟排——修 active 静默后的左侧"缺口"(bump 0.38.7)
用户发截图:0.38.6 active 徽章静默后,无 skill 的行(列表主体)meta 行左槽空了,数字组(条/tok)又被 `.num.right-group{margin-left:auto}` 整组挤右,中间留出一块像缺了东西。修:数字组改靠左跟排填上左槽,只有 time-ago 锚行尾(`margin-left:auto` 移到 time-ago);模板删掉已无意义的 `right-group` class。"条/tok"跨行对齐由原有 min-width+右对齐槽位保持。改 `web/static/dev.html` + `web/static/js/chat.js`
### 2026-07-03 / web status 徽章改"默认态静默"——active 不挂徽章,终态行淡化(bump 0.38.6) ### 2026-07-03 / web status 徽章改"默认态静默"——active 不挂徽章,终态行淡化(bump 0.38.6)
运行圆点落地后暴露 status 徽章两问题:「进行中」(生命周期 active)与「运行中」(run_status)语义撞车;列表主体都是 active,每行重复挂蓝徽章是零信息噪音、还占 meta 行首槽。设计原则定为**默认态静默、例外态着色、瞬时态用动效**:active 不再渲染徽章(列表行 + 中栏 chat-meta 同规则,chat-meta 终态徽章保留兼解释"输入框为什么消失");completed/abandoned 徽章保留且整行淡化(`st-*` class,opacity .68,hover 恢复——st- 前缀防撞选中态 .task-row.active);绿脉冲点成为唯一动效信号,与生命周期解耦。筛选下拉「进行中」文案不动(筛选语境无歧义)。顺手删掉不再被渲染的 `.badge.active` CSS。改 `web/static/js/chat.js` + `web/static/dev.html` 运行圆点落地后暴露 status 徽章两问题:「进行中」(生命周期 active)与「运行中」(run_status)语义撞车;列表主体都是 active,每行重复挂蓝徽章是零信息噪音、还占 meta 行首槽。设计原则定为**默认态静默、例外态着色、瞬时态用动效**:active 不再渲染徽章(列表行 + 中栏 chat-meta 同规则,chat-meta 终态徽章保留兼解释"输入框为什么消失");completed/abandoned 徽章保留且整行淡化(`st-*` class,opacity .68,hover 恢复——st- 前缀防撞选中态 .task-row.active);绿脉冲点成为唯一动效信号,与生命周期解耦。筛选下拉「进行中」文案不动(筛选语境无歧义)。顺手删掉不再被渲染的 `.badge.active` CSS。改 `web/static/js/chat.js` + `web/static/dev.html`

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。 # 改版本只动这一行。
__version__ = "0.38.6" __version__ = "0.38.7"

View File

@ -552,10 +552,10 @@
align-items: baseline; font-variant-numeric: tabular-nums; } align-items: baseline; font-variant-numeric: tabular-nums; }
.task-row .meta > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } .task-row .meta > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.task-row .meta .badge { flex-shrink: 0; } .task-row .meta .badge { flex-shrink: 0; }
/* 数字槽位:固定 min-width + 右对齐;time-ago 也锁宽 → 整个右侧组位置稳定,跨行"条/tok"才能对齐 */ /* 数字组靠左跟排(active 徽章静默后左槽常空,整组右挤会留出一块"缺口");
固定 min-width + 右对齐让"条/tok"跨行对齐;只有时间锚在行尾 */
.task-row .meta .num { flex-shrink: 0; text-align: right; min-width: 44px; } .task-row .meta .num { flex-shrink: 0; text-align: right; min-width: 44px; }
.task-row .meta .num.right-group { margin-left: auto; } /* 把数字+时间整组挤到右侧 */ .task-row .meta .time-ago { flex-shrink: 0; text-align: right; min-width: 64px; margin-left: auto; }
.task-row .meta .time-ago { flex-shrink: 0; text-align: right; min-width: 64px; }
.task-row .badge { .task-row .badge {
display: inline-block; padding: 0 6px; border-radius: var(--r-md); font-size: 11px; display: inline-block; padding: 0 6px; border-radius: var(--r-md); font-size: 11px;
background: #eef; color: #336; background: #eef; color: #336;

View File

@ -206,7 +206,7 @@ function renderTaskList(tasks, append = false) {
${statusLabel ? `<span class="badge ${t.status}">${statusLabel}</span>` : ""} ${statusLabel ? `<span class="badge ${t.status}">${statusLabel}</span>` : ""}
${runIndicatorHtml(t)} ${runIndicatorHtml(t)}
${t.skill ? `<span class="muted" title="${escapeHtml(t.skill)}">${escapeHtml(t.skill)}</span>` : ""} ${t.skill ? `<span class="muted" title="${escapeHtml(t.skill)}">${escapeHtml(t.skill)}</span>` : ""}
<span class="num right-group">${t.n_messages || 0} </span> <span class="num">${t.n_messages || 0} </span>
<span class="num" title="${escapeHtml(taskUsageTooltip(t))}">${fmtTokens(t.tokens)} tok</span> <span class="num" title="${escapeHtml(taskUsageTooltip(t))}">${fmtTokens(t.tokens)} tok</span>
<span class="muted time-ago" title="${escapeHtml(fmtTime(t.updated_at))}">${escapeHtml(fmtTimeAgo(t.updated_at))}</span> <span class="muted time-ago" title="${escapeHtml(fmtTime(t.updated_at))}">${escapeHtml(fmtTimeAgo(t.updated_at))}</span>
</div> </div>