Files
2026Technology-Competition/docs/design-web-chat-v3.md
T
lhl e6702a2009 feat(web): 前端 v3 — 移除 Aura Pipeline 痕迹 / 项目切换器 / 删除会话 / 抽屉化项目配置 / 侧边栏折叠
按 docs/design-web-chat-v3.md 实施,仅前端改动,JS 与后端 0 改动:
- 移除品牌区 "Aura Pipeline" 装饰小标与 header 面包屑装饰
- 顶栏项目切换器(#proj-switcher):按钮 + 下拉菜单,含「不选择项目」+ 项目列表 + 「+ 项目管理」;
  存在项目时自动绑首项(用户显式选过则不覆盖),项目被外部删除自动回退
- 会话项 hover 显示 × 删除图标 → confirm → DELETE /api/sessions/{sid};删的是当前会话自动 newSession
- 侧边栏 #sidebar-toggle 按钮整体折叠 56↔264px,状态 localStorage 持久化,刷新保持
- 项目配置(7 字段表单 + 列表 + 保存/删除)整体迁入主区右侧 #proj-drawer(460px 滑入,Esc 关闭);
  侧边栏 #proj-panel / #proj-form 已移除
- 全量 558 passed, 覆盖率 99.10%
2026-08-28 00:01:13 +08:00

257 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端改造 v3 设计文档
| 字段 | 值 |
|---|---|
| 文档版本 | v3.0 |
| 生效日期 | 2026-08-27 |
| 关联提交 | d6361cf(前置:v2 聊天前端美化) |
| 关联 AGENTS.md | 概设书自动生成 Agent 规范 |
## 1. 背景与目标
v2 聊天前端(commit `916c5be` / `d6361cf`)将 Web 前端由分步表单升级为 Aura Space 风格的对话式 SPA,但仍存在以下待解决问题:
1. 品牌区与头部出现了 "Aura Pipeline" 装饰性小标,与本项目实际品牌不一致。
2. 侧边栏仅可新建/加载会话,**无删除入口**;长期使用后历史会话堆积。
3. "项目" 是会话级(每会话项目独立可配置),但 UI 上没有显式的「项目上下文」指示;用户难以判断当前会话归属哪个项目。
4. 侧边栏固定 264px 始终展开,长会话列表与项目配置同时呈现会滚动拥挤。
5. 项目配置(7 个字段的表单)塞在侧边栏折叠面板中,宽度不足,输入体验差。
本次改造仅涉及前端,**后端 API 不变**(已确认 `DELETE /api/sessions/{id}` 等端点已就位)。
## 2. 范围与非范围
**In scope**
- 仅修改 `src/genesis/server/static/chat.html`CSS + 装饰性 HTML + JS 增量逻辑)
- 新增 ID`#proj-switcher``#ps-current``#ps-menu``#sidebar-toggle``#proj-drawer``#drawer-close``#drawer-list`
- 删除 DOM 节点:`.brand-sub``.crumb``#proj-panel`(含 `#proj-form`)—— 项目配置整体迁至抽屉
- JS 新增:`loadProjects` 自动绑首项、`deleteSession(sid)``openProjectDrawer`/`closeProjectDrawer``toggleSidebar` 及其事件绑定
- JS 修改:`refreshSessions` 在每条 `.sess` 内追加删除按钮
**Out of scope**
- 后端任何文件(store/service/app/data_models/parsers/impact/qa/writer/chat/inference
- 数据库 schema(沿用现有 `projects` 表)
- 引入新依赖(无 npm / 无外部 JS)
- 模板/生成/影响调查/QA 等业务逻辑
## 3. 关键决策与权衡
### 3.1 项目归属语义
**决策**:存在项目时,`currentProject` 自动绑定第一个项目(`GET /api/projects``name` 升序);用户可在顶栏下拉切换。无项目时维持 `currentProject=null` 的"无项目"模式(用户上传全部 5 类资料)。
**权衡**
- 选择"默认绑第一项"而非"必须选项目"——允许空仓库试用与脚本化无项目流程
- 选择"字母序第一"而非"最近使用"——避免引入新的排序状态,`ProjectsStore` 已用 `ORDER BY name`store.py: `ProjectsStore.list`
### 3.2 项目切换器形态
**决策**:顶栏 `<h1>` 之后插入 `#proj-switcher`(按钮 + 弹出菜单),菜单含「不选择项目」+ 所有项目 + 分隔线 + 「+ 项目管理(打开抽屉)」。
**权衡**
- 选择"顶栏下拉"而非"侧边栏图标入口"——顶栏常驻且与品牌区相邻,认知负担低
- 选择"菜单中含 '+ 项目管理'"而非"独立项目设置按钮"——单入口避免 UI 元素冗余
### 3.3 会话删除
**决策**:每条 `.sess` hover 时右侧出现 `×` 图标,点击触发原生 `confirm('确认删除该会话?此操作不可撤销。')`,确认后 `fetch('DELETE /api/sessions/{sid}')``await refreshSessions()`;若删除的是当前会话则 `newSession()` 自动重建并清空 localStorage。
**权衡**
- 选择"原生 confirm"而非"内嵌确认条"——减少 CSS 工作量,且浏览器 confirm 不可被误绕过;副作用是阻塞主线程(接受)
- 选择"hover 显示 ×"而非"始终显示 ×"——减少视觉噪声;副作用是触屏设备无 hover 行为——但本应用主要面向桌面 Web 评审系统
### 3.4 侧边栏折叠
**决策**:头部加 `#sidebar-toggle` 按钮(一根 `«` / `»`),切换 56px / 264px,状态写入 `localStorage['genesis_sidebar_collapsed']`,刷新后恢复。
**权衡**
- 选择"图标条"而非"完全隐藏"——保留可发现性
- 选择"localStorage 持久化"而非"临时态"——折叠是高频操作,每次进系统都重新展开体验差
- 56px 宽度下隐藏文字与按钮文字(`.brand-name` / `.sess .name` / `.sess .meta` / `#new-chat span`),仅保留图标与可点击区
### 3.5 项目配置抽屉
**决策**`#proj-drawer` `position: fixed; right: 0; width: 420px; height: 100vh;`,默认 `transform: translateX(100%)` 隐藏;`transform: translateX(0)` 显示,过渡 300ms ease。内部 35% 左侧列表 + 65% 右侧表单。
**权衡**
- 选择"浮层抽屉"而非"推开主区"`main { margin-right }`)——浮层动画更简单、聊天上下文不被截断;副作用是主区被遮挡,但抽屉 `×` 关闭即时
- 选择"420px 宽"而非"全屏"——保留聊天区侧边可见性
- 7 字段表单沿用 `#pf-name/display/template/write_instruction/rules/code/design` ID,避免与已有 CSS 冲突
## 4. UI 改造细节
### 4.1 品牌区(侧边栏顶部)
```
旧: 新:
┌──────────────────┐ ┌──────────────────┐
│ [G] Genesis │ │ [G] Genesis │
│ AURA PIPELINE│ │ │
└──────────────────┘ └──────────────────┘
```
- 删除 `<div class="brand-sub">Aura Pipeline</div>` 节点
- 删除 `.brand-sub { ... }` 样式
### 4.2 顶栏(`header`
```
旧: 新:
┌────────────────────────────────────┐ ┌──────────────────────────────────────────┐
│ AURA / Genesis 概要设计书 Agent [badge]│ Genesis 概要设计书 Agent [项目: stock ▾] [badge]│
└────────────────────────────────────┘ └──────────────────────────────────────────┘
```
- 删除 `<span class="crumb">Pipeline</span>``.crumb``.crumb::before` 样式
- 新增 `#proj-switcher`label "项目" + 按钮显示当前项目名(无项目时"未选择")+ 下拉菜单
### 4.3 侧边栏折叠
```
展开:┌────────────┐ 折叠:┌─┐
│ brand │ │G│
│ + 新会话 │ │+│
│ 会话历史 │ │≡│
│ ... │ │…│
│ │ │ │
└────────────┘ └─┘
264px 56px
```
- 头部右上 `«` 按钮 → 切换
- 折叠态隐藏文字、保留图标与可点击区
### 4.4 会话列表项(侧边栏)
```
┌─────────────────────────┐
│ 会话名 │
│ uploading · projA × │ ← × 默认 opacity:0, hover 整条 .sess 时显示
└─────────────────────────┘
```
- `.sess``display:flex; align-items:center;`
- `.sess .info { flex:1; min-width:0; }` 包裹 `.name` / `.meta`
- `.sess .del { opacity:0; transition; padding; }``.sess:hover .del { opacity:1; }`
### 4.5 项目抽屉(主区右侧)
```
┌──── drawer-head ─────┐
│ 项目配置 × │
├──── drawer-body ─────┤
│ ┌──list──┐ ┌─form─┐ │
│ │ stock │ │ name │ │
│ │ projA │ │ display │ │
│ │ projB │ │ template│ │
│ │ │ │ ... │ │
│ │ │ │[保存] │ │
│ │ │ │[删除] │ │
│ └────────┘ └──────┘ │
└─────────────────────┘
```
- 宽度 420px,右侧滑入
- 列表项 `.drawer-item`(含 display_name + 选中态)
- 表单沿用 `#pf-*` ID
- 底部"保存项目" / "删除项目"(删除当前选中项目;不可删除当前有会话的项目——为简化,暂不限制,由用户自决)
## 5. JS 状态机
新增状态:
- `projectsLoaded: boolean` — 首屏 `loadProjects` 完成后置 true
- `drawerOpen: boolean`
- `sidebarCollapsed: boolean`(镜像自 localStorage
新增函数:
- `applyProjectContext()` — 顶栏下拉文案同步、徽章同步、`updateUploadBar()` 触发
- `renderProjectSwitcher()` — 渲染下拉菜单项目列表
- `toggleProjectSwitcher(open?: boolean)` — 控制菜单开/关
- `deleteSession(sid, ev)``confirm``fetch DELETE``refreshSessions`,若是当前会话则 `newSession()`
- `openProjectDrawer(projectName?)``drawerOpen=true`,列表选中目标项目,表单填充(新建模式 `projectName=''` 时表单清空)
- `closeProjectDrawer()``drawerOpen=false`
- `renderDrawerList()` — 渲染抽屉项目列表
- `loadDrawerForm(projectName?)` — 填充表单(新建时清空)
- `saveDrawerProject()` — 收集 `pf-*``POST /api/projects``loadProjects()` + `applyProjectContext()` + 关闭抽屉
- `deleteDrawerProject()``confirm``DELETE /api/projects/{name}``loadProjects()` + 若删的是 currentProject 回退到首项
- `toggleSidebar(force?)` — 切换 `#sidebar.collapsed` 并写 localStorage
修改函数:
- `loadProjects()` 末尾追加:若 `currentProject===null``projects.length>0``currentProject=projects[0].name`;再调 `applyProjectContext()``renderProjectSwitcher()`
- `refreshSessions()` 渲染 `.sess` 时追加 `<button class="del" title="删除会话">×</button>``onclick=deleteSession(...)`
- 启动序列:先 `toggleSidebar(undefined)` 读 localStorage 决定初始态
事件绑定新增:
- `#ps-current` click → `toggleProjectSwitcher()`
- 任意 `#proj-switcher` 外点击 → 关闭下拉
- `Esc` 键 → 关闭下拉与抽屉
- `#sidebar-toggle` click → `toggleSidebar()`
- 抽屉列表项 click → `loadDrawerForm(name)`
- `#drawer-close` click → `closeProjectDrawer()`
- "保存项目" / "删除项目" 按钮
## 6. CSS 新增 / 删除 / 修改
新增:
- `.proj-switcher``.ps-current``.ps-menu``.ps-item``.ps-item.active``.ps-sep``.ps-manage`
- `#sidebar.collapsed` 系列(width 56px + 隐藏文本节点)
- `#sidebar-toggle`(侧边栏头部右上角)
- `.sess .del`(删除按钮,hover 显示)
- `#proj-drawer``.drawer``.drawer-head``.drawer-close``.drawer-body``.drawer-list``.drawer-item``.drawer-form``#proj-drawer button``#proj-drawer input`
删除:
- `.brand-sub`
- `.crumb``.crumb::before`
修改:
- `.sess { display:flex; align-items:center; }` —— 由块布局改为 flex
- `.sess .name` / `.sess .meta` 由直接子元素改为 `.sess .info` 包裹(JS 同时修改)
- 顶栏 gap 调整(`gap: 14px`)——容纳项目下拉
- 侧边栏 padding 调整,brand 与会话区垂直间距不变
## 7. 兼容性矩阵
| 已有 JS 引用 | 状态 |
|---|---|
| `document.getElementById('chat')` 等 21 个 ID | 全部保留 |
| 类名:`msg(+role)``bubble``progress-item(ok/warn)``actions``typing``sess(active)``name``meta` | 全部保留 |
| 变量:`sid``currentProject``activeProject` | 保留含义,新增值为函数内局部 |
## 8. 验证方案
手工验证 4 场景(启动 `python scripts/serve.py --fake`):
1. **顶栏下拉切项目**:创建项目 A、B → 下拉切换 → 新建会话 → 会话归属所选项目
2. **抽屉管理项目**:抽屉里创建/编辑/删除项目 → 顶栏下拉同步更新
3. **侧边栏折叠**:点 `«` → 56px 折叠;刷新页面 → 折叠态保持
4. **删除会话**:hover 侧边栏某会话 → 点 × → confirm → 会话移除;删的是当前会话 → 自动重建
自动化测试:
- `python -m pytest` 全量 558+ 项确保后端无回归
- `test_root_serves_frontend` 确保 HTML 含 "Genesis"(已通过)
## 9. 风险与缓解
| 风险 | 缓解 |
|---|---|
| 抽屉打开时遮住聊天区 | 默认浮层;提供 × 关闭,Esc 关闭 |
| 侧边栏折叠态文字消失影响可发现性 | `title` 属性悬浮提示 |
| 顶栏下拉 + 抽屉同时打开造成视觉冲突 | 抽屉打开时强制关闭下拉 |
| localStorage 损坏(无 `genesis_sidebar_collapsed` | `toggleSidebar()` 读取时做 `try/catch` 兜底为 `false` |
| 删除当前会话后 refreshSessions 与 activeProject 不同步 | `deleteSession` 内统一调用 `newSession()` 而非仅 `refreshSessions` |
| `loadProjects` 自动绑首项与用户既有"不选择项目"预期冲突 | 用户可在下拉菜单显式选"不选择项目"覆盖 |
## 10. 交付物
- `src/genesis/server/static/chat.html` 修改(含 CSS / HTML / JS
- `docs/design-web-chat-v3.md`(本文)
- `_AI_USAGE_LOG.md` 追加一条
- Git commit 包含上述文件变更
## 11. 后续(非本次范围)
- 抽屉内删除项目时联动删除/迁移所属会话(当前仅删项目,sessions 表 `project` 字段会变孤儿引用)
- 顶栏下拉支持"按项目过滤"侧边栏会话列表
- 抽屉内增加"项目详情预览"(已配置路径 + 关联会话数)
- 触屏端会话删除手势(hover-only 局限)