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/ 目录。
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
# 前端美化与交互改造设计(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.js,chat_state.js / chat_ws.js 不动)
|
||||
|
||||
## 用户决策(brainstorming 已确认)
|
||||
|
||||
| # | 决策项 | 选定 |
|
||||
|---|---|---|
|
||||
| 1 | 视觉风格 | 深色指挥中心 + 文档工作台混合 |
|
||||
| 2 | 强调色 | 青绿 `#5EEAD4` |
|
||||
| 3 | 字体策略 | 系统字体栈(不引入 Google Fonts / JetBrains Mono) |
|
||||
| 4 | 抽屉遮罩 | `backdrop-filter: blur(8px)` |
|
||||
| 5 | 文件拆分 | B2:chat.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 后绑定事件 + 启动恢复)
|
||||
- 新增函数:`groupSessions`、`bindUploadDrag`、`attachBubbleOps`、`autoResizeTextarea`、
|
||||
`renderProjectMismatchBadge`、`renderSkeleton`、`renderEmptyQuickActions`、
|
||||
`addInfo`、`addWarn`、`bindKeyboardShortcuts`
|
||||
- 保持函数签名与原内联版本一致(避免 chat_state.js 协议变化)
|
||||
|
||||
## 一、设计令牌(chat.css 顶部 `:root`)
|
||||
|
||||
```css
|
||||
: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)+ 名字 + chevron,hover 出现 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-input`,focus 时 `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-base`,hover 加 `accent-soft` 外发光
|
||||
|
||||
### 2.6 项目抽屉(`#proj-drawer`)
|
||||
|
||||
- 整体 `--bg-surface`,背后遮罩 `rgba(11,15,23,.6)` + `backdrop-filter: blur(8px)`
|
||||
- 左侧列表项:active 时左侧 2px `--accent` 竖条 + 背景 `--bg-elevated`
|
||||
- 表单输入:深色底 `--bg-input`,focus 时 `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_hint`(sessionStorage)
|
||||
|
||||
新增键(无冲突):
|
||||
|
||||
- `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`
|
||||
- **行为**:
|
||||
- `dragover`:`upload-bar` 加 `.drag-active` 类(dashed `--accent` 边 + `accent-soft` 底色)
|
||||
- `dragleave`:`upload-bar` 移除 `.drag-active`
|
||||
- `drop`:取 `e.dataTransfer.files[0]`,写入 `#file-input.files`,并**按后缀自动选 `file-type`**:
|
||||
- `.xlsx` → `requirements`
|
||||
- `.docx` → `template`(缺省兜底)
|
||||
- `.zip` → `existing_system`
|
||||
- **安全**:复用现有 `projectHasPrefixedType` 与 `UPLOAD_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'`
|
||||
- `keydown`:`Enter`(无 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 时显示 `⌘K`(CSS `::after`,仅 mac 显示,win/linux 省略)
|
||||
|
||||
### 4.7 骨架屏
|
||||
|
||||
- **位置**:启动时(`localStorage` 有 `genesis_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()` 中,无 `sid` 且 `draftProject` 已选时
|
||||
- **内容**:欢迎气泡 + 3 个胶囊按钮:
|
||||
- "上传要件定义"(点击触发 `#file-input` click)
|
||||
- "查看项目状态"(直接 `send('现在什么状态?')`)
|
||||
- "开始生成概要设计书"(`send('生成概要设计书')`)
|
||||
- **样式**:胶囊 `--bg-elevated` 底 + 1px `--border-subtle` 边,
|
||||
hover 出现 `--accent` 边
|
||||
- **不显示**:`draftProject` 为 `null` 时(保持现有欢迎语)
|
||||
|
||||
## 五、错误分级样式(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`)供未来复用
|
||||
Reference in New Issue
Block a user