100 lines
6.1 KiB
Markdown
100 lines
6.1 KiB
Markdown
# 侧边栏项目树 + 消息区对齐 + 空态清理 — 实施计划
|
||
|
||
配套需求:用户 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()`:项目行点击选中+展开/收起(`collapsedProjects` Set,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) }`。
|
||
- **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: 待用户批准后实施
|