Fix task list scroll container

This commit is contained in:
caoqianming 2026-05-25 08:06:33 +08:00
parent ae6b8630e2
commit 3525399041
2 changed files with 15 additions and 6 deletions

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`
最后更新:2026-05-22(对外路径协议刚性化:system 强约束 + UI 一次性兼容)
最后更新:2026-05-25(dev SPA 左侧任务列表滚动区收窄到 task 列表)
---
@ -21,6 +21,10 @@
## 已完成关键能力
### 2026-05-25
- **dev SPA 左侧滚动条只覆盖 task 列表**:`web/static/dev.html` 左 pane 改成 flex column,顶部 4 行 pane-head(任务标题/新建/搜索筛选/排序)固定不参与滚动;`#task-list` 与 `#task-sentinel` 包进 `#task-scroll`,并把 IntersectionObserver root 从 `#pane-left` 改到 `#task-scroll`,保证无限滚动仍按列表区域触发。`DESIGN.md` 不动(无架构/心智模型变化);`RUN.md` 不动(运行方式无变化)。
### 2026-05-22
- **dev SPA 手机端对话面板顶栏 + chat-meta 紧凑化**:`web/static/dev.html` 手机段(≤640px)对 `#pane-mid > .pane-head``flex-wrap: wrap` + 按钮 `white-space: nowrap`,消除 5 个按钮(导出对话记录/清空对话/完成/废弃/删除)在 320-360px 视口被挤压后"完\n成"这种逐字竖排;同时藏掉 `.label`("对话",mobile-tabs 已亮态指示)和 `.spacer`(flex-wrap 下 spacer 会强制后续按钮换行影响视觉一致)。`#chat-meta` 同段把 `gap` 8px → 6px、藏 `.tid`(8 位 UUID 前缀手机用户用不上)、`.desc` 加 `max-width:60vw` ellipsis(避免长 description 独占一行);三个 model 下拉 label "模型/生图/生视频" 用 `.mdl-text / .mdl-icon` 双 span 渲染,桌面显文字 + 手机显 emoji(💬🖼🎬)—— `renderModelDropdown / renderImageModelDropdown / renderVideoModelDropdown` 三处统一。改动只在手机视口生效,桌面零变化。否决:(a) 折叠成 ⋯ 浮层菜单(用户拒,多一次点击);(b) 改图标按钮(5 个动作含义不直观需 tooltip);(c) 把 emoji 应用到桌面(无解决问题且改动用户已习惯的桌面态)。

View File

@ -206,7 +206,10 @@
header .spacer { flex: 1; }
.pane { border-right: 1px solid var(--border); background: var(--panel); overflow: auto; min-height: 0; }
#pane-left { grid-area: left; }
/* 左 pane:flex column,顶部多行 pane-head 固定,只让 #task-scroll 滚 — 滚动条不再覆盖顶栏 */
#pane-left { grid-area: left; display: flex; flex-direction: column; overflow: hidden; }
#pane-left > .pane-head { flex-shrink: 0; }
#task-scroll { flex: 1; min-height: 0; overflow: auto; }
/* min-height: 0 + overflow: hidden 让内部 flex 子项的 overflow: auto 真正生效(否则被默认 min-height: auto 顶出) */
#pane-mid { grid-area: mid; display: flex; flex-direction: column; border-right: 1px solid var(--border); background: var(--panel); min-height: 0; overflow: hidden; }
#pane-right { grid-area: right; border-right: none; overflow: auto; background: var(--panel); min-height: 0; }
@ -788,8 +791,10 @@
<option value="status,-created_at">状态分组(同状态按时间倒序)</option>
</select>
</div>
<div id="task-list"><div class="empty">加载中…</div></div>
<div id="task-sentinel" style="padding:10px 12px;font-size:11px;color:var(--muted);text-align:center;min-height:1px;"></div>
<div id="task-scroll">
<div id="task-list"><div class="empty">加载中…</div></div>
<div id="task-sentinel" style="padding:10px 12px;font-size:11px;color:var(--muted);text-align:center;min-height:1px;"></div>
</div>
</div>
<!-- middle -->
@ -1489,13 +1494,13 @@ $("filter-q").addEventListener("input", () => {
_filterDebounce = setTimeout(() => loadTaskList(), 300);
});
// 滚动加载:左 pane 整体是 scroll 容器(.pane{overflow:auto}),用 #pane-left 作 root
// 滚动加载:只让 task 列表区域滚,顶部标题 / 新建 / 筛选 / 排序固定。
// rootMargin 提前 200px 触发,体感更顺;阈值 0 即可(刚进入即触发,append 期间 taskLoading 自带防抖)
const _taskScrollObserver = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && state.taskHasMore && !state.taskLoading) {
loadTaskList({ append: true });
}
}, { root: $("pane-left"), rootMargin: "200px 0px" });
}, { root: $("task-scroll"), rootMargin: "200px 0px" });
_taskScrollObserver.observe($("task-sentinel"));
// ───── select task ─────