Files
2026Technology-Competition/docs/superpowers/specs/2026-08-30-frontend-beautify-design.md
T
lhl b14c2213bc docs(superpowers): 补录前端美化与交互改造的设计规范与实施计划
- docs/superpowers/specs/2026-08-30-frontend-beautify-design.md
  前端美化与交互改造设计(深色指挥中心 + 文档工作台混合风格,
  单一青绿 #5EEAD4 强调色,chat.html 拆为 chat.html + chat.css + chat.js,
  8 项交互改善,用户决策 10 项)
- docs/superpowers/plans/2026-08-30-frontend-beautify.md
  前端美化与交互改造 Implementation Plan(三步走:机械拆分 → 视觉重塑 →
  交互改造,Task 独立 commit,浏览器手测验证)

按项目文档规则存入 docs/superpowers/ 目录。
2026-08-31 22:33:46 +08:00

17 KiB
Raw Blame History

前端美化与交互改造设计(2026-08-30)

背景与目标

当前前端(src/genesis/server/static/chat.html,单文件 1215 行内联 CSS+JS)沿用 Material/Google 风 #1a73e8 蓝、Inter、胶囊按钮、扁平阴影),功能完整但视觉同质化严重,与"概要设计书自动生成 Agent"的项目定位缺少记忆点。

本次迭代在保持现有功能、API 协议、localStorage 键、所有 DOM id 完全不变的前提下,对整套前端 做视觉重塑 + 8 项交互改善,达成:

  1. 视觉差异化(深色指挥中心 + 文档工作台混合风格,单一青绿强调色)
  2. 体感现代化(拖拽、多行输入、消息气泡操作、骨架屏、空状态快捷指令)
  3. 架构可维护(chat.html 拆为 chat.html + chat.css + chat.jschat_state.js / chat_ws.js 不动)

用户决策(brainstorming 已确认)

# 决策项 选定
1 视觉风格 深色指挥中心 + 文档工作台混合
2 强调色 青绿 #5EEAD4
3 字体策略 系统字体栈(不引入 Google Fonts / JetBrains Mono
4 抽屉遮罩 backdrop-filter: blur(8px)
5 文件拆分 B2chat.html 拆为 chat.html + chat.css + chat.js
6 交互改造 本轮做 8 项(详见 §四)
7 快捷键 只做 Esc + Cmd/Ctrl+K
8 移动端改造 不做(留到下个迭代)
9 消息气泡"重新生成" 不做(避免触发后端协议变更)
10 主题切换 单主题(无 dark/light 切换)

范围

  • 视觉重塑(六大区域,颜色 / 字体 / 间距 / 圆角 / 动效)
  • chat.html 拆分为 chat.html + chat.css + chat.js
  • 8 项交互改善(见 §四)
  • 同步 docs/design.md 增加"前端 UI 设计规范"一节
  • 追加 _AI_USAGE_LOG.md 三条记录(设计 / 实现 / 文档同步)

不做

  • 移动端侧边栏抽屉化(断点 < 768px 的改造)
  • 快捷键 Cmd+Shift+O / Cmd+Shift+S
  • 消息气泡"重新生成"按钮
  • 主题切换(dark/light
  • 后端 API 协议变更
  • localStorage / sessionStorage 键重命名
  • DOM id 变更

架构

文件结构(B2 拆分后)

src/genesis/server/static/
├── chat.html          # 仅 DOM 结构
├── chat.css           # 新增:所有视觉样式
├── chat.js            # 新增:原 chat.html 中 <script> 段(约 700 行)
├── chat_state.js      # 不动
└── chat_ws.js         # 不动

chat.html 改动

  • 头部:删除 <link rel="preconnect"> 与 Google Fonts 的 <link>
  • 头部:新增 <link rel="stylesheet" href="/chat.css">
  • 头部末尾(<body> 之前):保持空白
  • 主体:删除第 10-392 行 <style>...</style> 整段
  • 主体:保留所有 DOM 节点 id(业务逻辑依赖)
  • 末尾:删除第 509-1213 行 <script>...</script> 整段
  • 末尾:新增 <script src="/chat.js" defer></script>
  • 末尾:保留 <script src="/chat_state.js"><script src="/chat_ws.js"> 在 chat.js 之前

chat.js 改造

  • 整体结构保持不变(DOMContentLoaded 后绑定事件 + 启动恢复)
  • 新增函数:groupSessionsbindUploadDragattachBubbleOpsautoResizeTextarearenderProjectMismatchBadgerenderSkeletonrenderEmptyQuickActionsaddInfoaddWarnbindKeyboardShortcuts
  • 保持函数签名与原内联版本一致(避免 chat_state.js 协议变化)

一、设计令牌(chat.css 顶部 :root

:root {
  /* === 颜色 === */
  --bg-base: #0B0F17;
  --bg-surface: #141A24;
  --bg-elevated: #1B2330;
  --bg-input: #0F141C;
  --border-subtle: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.14);
  --text-primary: #E5EAF0;
  --text-secondary: #8B95A7;
  --text-muted: #5C6677;
  --accent: #5EEAD4;
  --accent-soft: rgba(94, 234, 212, 0.15);
  --success: #34D399;
  --warning: #FBBF24;
  --danger: #F87171;
  --info: #60A5FA;

  /* === 字体 === */
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
             "Microsoft YaHei", "Noto Sans CJK SC", system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  /* === 间距 === */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-5: 20px; --sp-6: 24px;

  /* === 圆角 === */
  --r-sm: 6px;  --r-md: 10px; --r-lg: 14px;

  /* === 动效 === */
  --ease: cubic-bezier(.2, 0, 0, 1);
  --dur: .18s;
}

二、各区域视觉规约

2.1 侧边栏(#sidebar

  • 底色 --bg-surface,右 1px --border-subtle
  • 折叠按钮:从右外侧浮出的小竖条,hover 时变 --accent不再旋转 180° 改为左右 chevron« / »)切换
  • 会话项 hover:背景 --bg-elevated,左侧 2px --accent 竖条
  • 会话项 active:左侧 2px --accent 竖条 + 背景 --bg-elevated
  • 折叠态:去掉头像逻辑,改成 4px 圆点(项目色 hash);折叠态下分组标题 display:none

2.2 顶栏(header

  • 底色 --bg-surface + backdrop-filter: blur(12px) + 1px --border-subtle 底边
  • 项目切换器:胶囊改为左 6px 圆点(项目色 hash+ 名字 + chevronhover 出现 1px --accent
  • RAG 胶囊:去掉背景底色,改成 🔘 0 片段 风格的等宽小标签
    • 已索引:实心圆点 + --accent 色 + 等宽数字
    • 未索引:空心圆点 + --text-muted
  • 会话徽标:窄屏下不再 display:none,限制 max-width: 32% + text-overflow: ellipsis

2.3 聊天区(#chat

  • 主区底色 --bg-base,内边距 var(--sp-6)
  • 气泡:去掉阴影,改用 1px 细边 + 内部留白
    • 用户消息--bg-surface + 左侧 2px --accent 竖条 + 字号 14,行高 1.65
    • 助手消息--bg-surface + 1px --border-subtle + 顶头 6px 圆点(--accent 静态)
    • 进度消息--bg-input + dashed 边 --accent-soft,等宽字体
  • 思考中态:3 个等宽方块循环亮起(替代当前 思考中… 文案),用 --accent
  • 消息出现动画:保留 zoomIn,幅度从 0.97 → 0.98

2.4 上传条(#upload-bar

  • 底色 --bg-surface,与主区用 1px --border-subtle 分隔
  • 升级为可拖入区域(详见 §四-2):dragover 时整条出现 dashed --accent 边 + accent-soft 底色
  • select / button 深色样式:底色 --bg-inputfocus 时 0 0 0 2px var(--accent-soft)
  • 项目提示(#proj-hint)改为左侧 4px 三角指示条 + inline note

2.5 输入区(#composer

  • 底色 --bg-surface,顶 1px --border-subtle
  • <input id="input"> 升级为 <textarea id="input" rows="1">(详见 §四-4
  • send 按钮:底色 --accent,文字 --bg-basehover 加 accent-soft 外发光

2.6 项目抽屉(#proj-drawer

  • 整体 --bg-surface,背后遮罩 rgba(11,15,23,.6) + backdrop-filter: blur(8px)
  • 左侧列表项:active 时左侧 2px --accent 竖条 + 背景 --bg-elevated
  • 表单输入:深色底 --bg-inputfocus 时 0 0 0 2px var(--accent-soft)
  • 「高级」details 改为纯线框展开,无背景填充
  • 关闭按钮:hover 红色描边(保留现有语义)

三、关键不变量(兼容性保证)

3.1 必须保留的 DOM id(业务逻辑依赖)

sidebar, sidebar-toggle, brand-logo, brand-name, new-chat, session-list,
main, rag-bar, rag-enabled, rag-stats, impact-btn, sid-badge,
proj-switcher, ps-current, ps-name, ps-menu, chat, upload-bar, file-type,
file-input, upload-btn, upload-status, proj-hint, composer, input, send,
proj-drawer, drawer-list, drawer-form, drawer-close, pf-name, pf-display,
pf-template, pf-write, pf-rules, pf-code, pf-design, pf-save, pf-delete

3.2 必须保留的全局符号

  • window.GenesisState(由 chat_state.js 提供,chat.js 通过回退默认值兜底)
  • window.GenesisWS(由 chat_ws.js 提供,chat.js 通过 connectProgressWs / applyProgressEvent 消费)

3.3 必须保留的 localStorage / sessionStorage 键

  • genesis_sidebar_collapsed
  • genesis_session
  • genesis_rag_enabled
  • genesis_skipped_project_hintsessionStorage

新增键(无冲突):

  • genesis_session_group_collapsed(分组折叠状态,本轮默认全展开,不实际写入)

3.4 必须保留的 API 端点

所有 /api/... 调用与请求体格式不变。

四、交互改造(8 项)

4.1 会话列表按时间分组

  • 位置refreshSessions() 内,对 list.sort(...) 之后插入分组
  • 分组规则:用 updated_at 字符串前缀(YYYY-MM-DD)与今天/昨天日期比较
    • 今天 / 昨天 / 本周(7 天内)/ 本月 / 更早
  • DOM:在 .sess 之间插入 <div class="sess-group">今天</div>,样式: font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; color: var(--text-muted)
  • 不影响:折叠态下分组标题 display:none;分组内 .sess 仍可正常点击
  • 行为:分组标题不可点击,不参与折叠按钮 toggle

4.2 拖拽上传

  • 位置#upload-bar 监听 dragenter / dragover / dragleave / drop
  • 行为
    • dragoverupload-bar.drag-active 类(dashed --accent 边 + accent-soft 底色)
    • dragleaveupload-bar 移除 .drag-active
    • drop:取 e.dataTransfer.files[0],写入 #file-input.files,并按后缀自动选 file-type
      • .xlsxrequirements
      • .docxtemplate(缺省兜底)
      • .zipexisting_system
  • 安全:复用现有 projectHasPrefixedTypeUPLOAD_EXT_RULES 校验
  • 拖入整个文件夹webkitGetAsEntry 拒绝并提示(仅取第一个文件)

4.3 消息气泡操作

  • 触发
    • 用户气泡hover 时右上角浮出 ↺ 引用 按钮(点击把消息文本填到 #input 并 focus
    • 助手气泡hover 时右上角浮出 ⧉ 复制 按钮
  • 不实现↻ 重新生成 按钮(见 §零-9 决策)
  • 实现
    • CSS.msg { position: relative; } .msg .ops { position: absolute; top: -10px; opacity: 0; ... } :hover .ops { opacity: 1; }
    • JS:扩展 addMsg(),内部 appendChild <div class="ops">...</div>;用户/助手不同
  • 复制:用 navigator.clipboard.writeText(text),无 HTTPS 时 fallback document.execCommand('copy')(同步临时 textarea
  • 不存储历史:仅影响本次会话 UI

4.4 输入区多行 + 自动高度

  • 位置<input id="input"> 改为 <textarea id="input" rows="1">
  • 行为
    • input 事件:element.style.height = 'auto'; element.style.height = Math.min(scrollHeight, 160) + 'px'
    • keydownEnter(无 Shift 且无 IME 组合中)= 发送;Shift+Enter = 换行
    • 发送后自动重置高度为 auto(下一帧设回 24px
  • 保留:现有 maxlength=2000
  • IME 兼容keydown 中检查 e.isComposing(中文输入法组合中按 Enter 不应发送)

4.5 顶栏项目不匹配徽章化

  • 位置:在 #rag-bar 之前插入 <span id="proj-mismatch-badge" hidden>
  • 行为
    • 替代现有 renderProjectMismatchHint() 的聊天区插入逻辑
    • 徽章样式:黄色 1px 边 --warning + 圆角 --r-md + 前缀 + "项目: stock ≠ 草稿: foo" 文本
    • 点击展开一个迷你 popover(不打开抽屉),提供"切到该项目"和"保留"两个按钮
    • "保留"逻辑沿用现有 sessionStorage 标记(genesis_skipped_project_hint
  • 不删除旧函数:保留 renderProjectMismatchHint 但改为只调用新徽章渲染函数

4.6 快捷键(仅 2 个)

  • Esc:已有,扩展为同时关闭项目切换器 + 抽屉 + 移动端侧边栏(本轮不做移动端,等价无变化)
  • Cmd/Ctrl + K:切换 #ps-menu(与点击 #ps-current 行为一致),焦点在输入框时也能用
  • 实现位置document.addEventListener('keydown', ...),沿用现有 Escape 监听并扩展
  • 可视提示:项目切换器 hover 时显示 ⌘KCSS ::after,仅 mac 显示,win/linux 省略)

4.7 骨架屏

  • 位置:启动时(localStoragegenesis_session 时)替换 addMsg('assistant', '正在恢复上次会话…')
  • 样式:3 条消息形状的占位(圆形 8px + 矩形条 --bg-surface),用 linear-gradient@keyframes shimmer 1.4s 循环(亮色 --bg-elevated--bg-surface 交替)
  • 逻辑loadSession() 完成后 skeleton.remove(),最多 5 秒超时兜底
  • 超时处理setTimeout(5000) 强制 remove 并显示错误提示

4.8 空状态快捷指令

  • 位置renderEmptyOrWelcome() 中,无 siddraftProject 已选时
  • 内容:欢迎气泡 + 3 个胶囊按钮:
    • "上传要件定义"(点击触发 #file-input click
    • "查看项目状态"(直接 send('现在什么状态?')
    • "开始生成概要设计书"(send('生成概要设计书')
  • 样式:胶囊 --bg-elevated 底 + 1px --border-subtle 边, hover 出现 --accent
  • 不显示draftProjectnull 时(保持现有欢迎语)

五、错误分级样式(4.10

  • 位置:扩展 addMsg(),新增可选 level 参数:'info' | 'warn' | 'error'
  • 样式
    • info--info 1px 边 + rgba(96,165,250,.12)
    • warn--warning 1px 边 + rgba(251,191,36,.12)
    • error--danger 1px 边 + rgba(248,113,113,.12)
  • 兼容性:现有所有 addMsg('error', ...) 调用不变(默认仍走 error 样式)
  • 新增助手函数addInfo(text) / addWarn(text),内部调用 addMsg('info' / 'warn', text)
  • 本轮替换点(仅本轮改造涉及的错误,不全量替换):
    • 上传类型不匹配 → addWarn(客户端校验,非后端失败)
    • 项目名不能为空 → addWarn(客户端校验)
    • 加载会话失败 → addError(现有)
    • 网络/服务器错误 → addError(现有)

六、错误处理

场景 行为
chat.css / chat.js 加载失败(404/网络) 页面降级显示,肉眼可见(无样式白板)。可在 README 提示开发者
Google Fonts 已无 link,不会再失败 N/A
localStorage 不可用(隐私模式) 沿用现有 try/catch,输出到 console.warn 而非 addError
拖拽 API 不可用(旧浏览器) if (!('draggable' in document.createElement('div')) return; 静默退出
IME 中文输入中按 Enter e.isComposing 检查,不发送,保持原换行
快捷键冲突(浏览器原生 Cmd+K 始终 e.preventDefault(),已知会拦截 Firefox 切搜索栏

七、测试策略

由于本轮为纯前端样式与交互改造,且不新增可被 pytest 覆盖的逻辑,采用:

  1. 手动回归清单(见 docs/superpowers/specs/2026-08-30-frontend-beautify-checklist.md 本 spec 不展开)
  2. 截图对比(实施前用浏览器截 5 张关键页面对照,实施后比对)
  3. 关键流程脚本测试(用户手动跑通):
    • 新建会话 → 选项目 → 上传要件 → 发送"生成概要设计书" → 收到下载链接
    • 切换项目 → 不匹配徽章出现 → 点击"切到该项目" → 徽章消失
    • 拖拽上传 xlsx → 自动选 requirements → 上传成功
    • 输入多行(Shift+Enter)→ 发送(Enter)→ 高度重置
    • hover 助手气泡 → 复制 → 粘贴验证
    • Esc 关闭抽屉;Cmd+K 打开/关闭项目切换器
    • 启动恢复会话时显示骨架屏 → 加载完成消失

八、实施步骤(写作计划阶段会细化)

  1. 建文件骨架chat.html 拆分为 chat.html + chat.css + chat.js,机械搬移不改样式
  2. 写 chat.css 令牌:root 全部变量
  3. 重写 chat.css 样式:六大区域按 §二 改造
  4. chat.js 加 8 项交互:按 §四 / §五 顺序(不依赖外网)
  5. 本地手动回归:见 §七
  6. 同步 docs/design.md:新增"前端 UI 设计规范"一节
  7. 更新 _AI_USAGE_LOG.md:三条记录

九、风险与回滚

风险 缓解
内联 CSS/JS 拆分影响加载顺序 <link><head><script defer><body> 末尾;chat_state.js / chat_ws.js 保持同步加载
改 class 破坏后端 后端不读 class;仅核对 id 列表(§三-1)
系统字体在 win / linux 上回退差异 字体栈已含 PingFang / Microsoft YaHei / Noto Sans CJK 兜底
backdrop-filter 性能 限定在抽屉遮罩 + 顶栏,不滥用
localStorage 新增键冲突 全部以 genesis_ 前缀
拖入文件夹行为 拒绝并 toast 提示"请拖入单个文件"

回滚git checkout 上一版本,删除 chat.css / chat.js 即可。

十、里程碑外(后续)

  • 移动端侧边栏抽屉化(< 768px 断点)
  • 快捷键 Cmd+Shift+O(项目抽屉)/ Cmd+Shift+S(侧边栏折叠)
  • 消息气泡"重新生成"按钮(需后端协议扩展)
  • 深色 / 浅色主题切换
  • 国际化(i18n)文案
  • 设计系统独立文件(static/design-tokens.css)供未来复用