6.1 KiB
6.1 KiB
侧边栏项目树 + 消息区对齐 + 空态清理 — 实施计划
配套需求:用户 7 条前端优化(侧边栏信息架构重构 + 气泡对齐 + 空态清理)
目标文件:src/genesis/server/static/{chat.html,chat.css,chat.js,chat_state.js}
前端无框架、无构建;后端零改动。
已确认决策
- D1 气泡对齐到文本输入框:左 16px;右留发送按钮宽度(40+10=50px);删除 assistant 头像点。
- D2 点击侧边栏项目名 = 选中该项目(设为当前项目)+ 展开/收起。
- D3 抽屉左侧项目列表保留(仅删除「+新建项目」项)。
- D4 侧边栏折叠态隐藏「项目/其他会话」两段。
- D5 req2 的「提示语及提示词」= 空态主标题 + 建议卡,发送后一并清除。
目标侧边栏
[G Genesis 概要设计书做成Agent]
[+ 新会话]
项目 + ← 仅"+",hover「追加项目」
▾ 股票系统 ⚙ ← 展开显示其会话;⚙ hover「配置」
· 需求A
· 需求B
▾ 人事系统 ⚙
· 需求C
其他会话
· 需求D(project="")
Task 1:chat_state.js 分组纯函数 + node 测试
- 新增
groupSessionsByProject(sessions)→{ byProject: { "<name>": [s...] }, other: [s...] }(project为空者入other)。 tests/test_chat_state.js增加断言:空项目归 other;两项目分别归组。- 运行
node --test tests/test_chat_state.js。
Task 2:chat.html 侧边栏结构 + 移除底部新建项目按钮
- 删除
<h2>会话历史</h2>与<div id="session-list"></div>。 - 新增
#sec-projects(side-head:标题「项目」+#side-add-project「+」)与#project-tree。 - 新增
#sec-others(标题「其他会话」)与#other-session-list。 - 删除
#tb-newproject按钮。
Task 3:chat.css 侧边栏树 + 消息区对齐 + 折叠态
- 新增
.side-section/.side-head/.side-title/.side-add/.proj-group/.proj-row/.proj-caret/.proj-name/.proj-config/.proj-sessions样式;嵌套.sess缩进。 - 折叠态:
#sidebar.collapsed .side-section { display: none; }。 - 消息区:
#chat { max-width: none; margin: 0; padding: var(--sp-6) var(--sp-4); };.msg { padding-right: 50px; };.msg .bubble { max-width: 100%; };删除.msg.assistant::before。
Task 4:chat.js 分组渲染 + 绑定调整 + 空态清理
refreshSessions()改拉全量并按groupSessionsByProject分组 →renderProjectTree()+renderOtherSessions()。- 抽
renderSessItem(s)(复用现有会话行逻辑)。 renderProjectTree():项目行点击选中+展开/收起(collapsedProjectsSet,localStorage 持久化);⚙→openProjectDrawer(name)。#side-add-project→openProjectDrawer(null)(带脏守卫)。renderProjectSwitcher():删除ps-manage「项目管理(打开抽屉)」项及绑定。renderDrawerList():删除di-create「+新建项目」项。send():发消息前chatEl.querySelector('.empty-state')?.remove()。- 删除
#tb-newproject绑定。
Task 5:验证与提交
node --check、node --test、python -m pytest(≥99%)。- 手动核对:气泡对齐、空态清理、项目树/⚙/+、底部无新建项目、未选项目时新会话入「其他会话」。
- 更新
_AI_USAGE_LOG.md并提交。
风险
#sidebar.collapsed下.sess旧样式成为死代码(无害)。- 分组渲染依赖
GET /api/sessions全量返回(已支持project可选)。 - 若某会话的 project 已从项目列表删除,仍会以其 project 名建组渲染(保证不丢会话)。
评审结论与计划调整(plan-eng-review)
采纳的修正
- F1(正确性,req 5)显式「不选择项目」持久化
chat_state.js:autoBindProject(draftProject, projects, explicitNone = false)——explicitNone为真时原样返回draftProject(不移除用户选择);否则维持原自动绑定逻辑。新增 node 断言。chat.js:读写localStorage['genesis_project_explicit_none'];loadProjects()传入该标记;选任意项目 → 清除标记;选「不选择项目」→ 设标记。保证「无项目选择 → 新会话进『其他会话』」成立。
- F2(UX)打开会话所在分组高亮
renderProjectTree():组内任一会话session_id === sid时给.proj-group加.has-active(与.current= 选中项目 区分)。
- F3(DRY)对齐余量单一来源
- 新增 CSS 变量:
--send-size: 40px、--composer-gap: 10px、--composer-gutter: calc(var(--send-size) + var(--composer-gap))。 #send { width/height: var(--send-size) }、#composer-inner { gap: var(--composer-gap) }、.msg { padding-right: var(--composer-gutter) }。
- 新增 CSS 变量:
- F6(清理)删除折叠态死样式
- 移除
#sidebar.collapsed .sess*与#sidebar h2相关规则(折叠态整段隐藏、h2 已不存在)。
- 移除
接受现状(标注,不改)
- F4 project 已删的会话以原 project 名成组渲染(不丢会话)。
- F5 DOM 渲染层无自动化测试;靠纯函数
groupSessionsByProject断言 +node --check+ 手动。 - F7 项目行沿用
div.onclick(非键盘可达),与会话行一致。 - F8
refreshSessions每次拉全量;规模增大时再考虑限制。
受影响任务更新
- Task 1 追加:
autoBindProject第三参数 +groupSessionsByProject+ node 断言。 - Task 3 追加:
--send-size/--composer-gap/--composer-gutter变量;删除折叠死样式。 - Task 4 追加:
explicit_none读写与联动;.has-active渲染。
GSTACK REVIEW REPORT
- STATUS: DONE_WITH_CONCERNS
- REVIEWED: docs/superpowers/plans/2026-09-12-sidebar-project-tree.md
- FINDINGS: F1 正确性(已采纳修复) / F2 UX(已采纳) / F3 DRY(已采纳) / F6 清理(已采纳);F4/F5/F7/F8 接受
- KEY DECISION: 显式「不选择项目」持久化修复(否则 req 5 不成立)
- CONCERN: 渲染层无自动化测试(无 DOM harness);折叠态样式清理后需回归核对
- NEXT: 待用户批准后实施