docs: 亮色主题切换开发计划 (P3, AI 自主完成预备)
5 个 Stage 分阶段推进: - Stage 1: 109 处 inline hex/rgba 颜色替换为 var(--color-*) - Stage 2: :root 拆 [data-theme="dark/light"] 两套, 浅色色板抄 Linear/Vercel - Stage 3: themeStore + 切换按钮 + localStorage 持久化 - Stage 4: 浅色色板调试 + 半透明色反相 / ECharts 重渲染 / AuroraCanvas 处理 - Stage 5: vitest + Playwright 本地无头浏览器深/浅截图回归 预期 AI 连续工时 7-9 小时, 人工 3.5-5 天。 关键发现: 项目未实际使用 Arco (CLAUDE.md 写错), 颜色高度集中 (Top 4 文件占 75%, Top 10 颜色占 60%+ 已有对应 var)。 待用户启动 /loop 后 AI 自主完成, 完成时输出截图 + 完成报告。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c2c811a8fe
commit
3da801d6e6
313
docs/todo/亮色主题切换.md
Normal file
313
docs/todo/亮色主题切换.md
Normal file
@ -0,0 +1,313 @@
|
||||
# 亮色主题切换(dark / light theme toggle)
|
||||
|
||||
**状态**:待开发
|
||||
**创建日期**:2026-04-28
|
||||
**优先级**:P3(影视工具默认深色更专业,浅色主要服务非影视用户 / 白天强光环境 / 投资人 demo)
|
||||
|
||||
---
|
||||
|
||||
## 需求背景
|
||||
|
||||
当前界面是深色固定主题(参考 Linear / Vercel 风格)。部分用户在强光环境 / 白天工作 / 习惯亮色的场景下希望能切换。
|
||||
|
||||
不走传统"产品+设计师"流程,直接由 AI 从代码层做改造。
|
||||
|
||||
---
|
||||
|
||||
## 现状分析(关键发现)
|
||||
|
||||
### ✅ 基础设施已就位
|
||||
|
||||
- `web/src/index.css` `:root` 集中定义了 **35 个 CSS variable**(`--color-bg-page`、`--color-text-primary` 等)
|
||||
- 全项目 **525 处** 引用了 `var(--color-*)`,集中可控
|
||||
- **未使用 Arco Design**(CLAUDE.md 写错了,实际 `grep @arco-design = 0`)→ 不需要适配第三方 UI 库主题,少了一大块工作量
|
||||
|
||||
### ⚠️ 109 处 inline 颜色散落在 `.tsx`
|
||||
|
||||
热点文件(占 75%):
|
||||
|
||||
| 文件 | inline 颜色数 |
|
||||
|---|---|
|
||||
| `pages/DashboardPage.tsx` | 31 |
|
||||
| `pages/TeamDashboardPage.tsx` | 21 |
|
||||
| `components/RecordDetailModal.tsx` | 17 |
|
||||
| `components/ReferenceList.tsx` | 12 |
|
||||
| 其他 | 28 |
|
||||
|
||||
颜色种类高度收敛(前 10 高频占 60%+):
|
||||
|
||||
```
|
||||
17次 #8b8ea8 ← 已有 var: --color-text-secondary
|
||||
10次 #888 ← 同上语义
|
||||
6次 rgba(255,255,255,0.06) ← 已有 var: --color-bg-card / --color-bg-input-bar
|
||||
5次 rgba(255,255,255,0.08) ← 已有 var: --color-bg-hover
|
||||
5次 #f1f0ff ← 已有 var: --color-text-primary
|
||||
6次 #6c63ff ← 已有 var: --color-primary
|
||||
```
|
||||
|
||||
→ 大部分是机械性 grep+replace,不是创造性设计。
|
||||
|
||||
---
|
||||
|
||||
## 浅色主题色板设计
|
||||
|
||||
直接抄 Linear / Vercel 的浅色方案(这俩就是当前深色主题模仿的对象,他们都有官方浅色版)。
|
||||
|
||||
### 核心规则
|
||||
|
||||
| 类别 | 深色(现状) | 浅色(新增) | 说明 |
|
||||
|---|---|---|---|
|
||||
| 页面背景 | `#07070f` | `#fafafa` | 主背景,深色近黑/浅色近白 |
|
||||
| 卡片背景 | `rgba(255,255,255,0.06)` | `rgba(0,0,0,0.04)` | **半透明色反相**:白半透明 → 黑半透明 |
|
||||
| Hover | `rgba(255,255,255,0.08)` | `rgba(0,0,0,0.06)` | 同上 |
|
||||
| 输入框背景 | `rgba(255,255,255,0.06)` | `#ffffff` | 浅色下输入框直接给纯白更醒目 |
|
||||
| 主文字 | `#f1f0ff`(亮紫白)| `#171823`(深紫黑)| 反相,保留紫调一致性 |
|
||||
| 次文字 | `#8b8ea8` | `#6b6e85` | 同上 |
|
||||
| 边框 | `rgba(255,255,255,0.10)` | `rgba(0,0,0,0.08)` | 半透明反相 |
|
||||
| 主色(按钮)| `#6c63ff` | `#5048cc` | 浅色背景下加深 18%,对比度足 |
|
||||
| 强调色 | `#00b8e6` | `#0099cc` | 同上原则 |
|
||||
| 成功 | `#00b894` | `#00a37e` | 浅色下加深 |
|
||||
| 危险 | `#e74c3c` | `#d63a2a` | 同上 |
|
||||
| 警告 | `#f39c12` | `#d4860a` | 同上 |
|
||||
| Modal 阴影 | `rgba(0,0,0,0.6)` | `rgba(0,0,0,0.15)` | 浅色下阴影减弱 |
|
||||
|
||||
### 切换机制
|
||||
|
||||
- 用 `<html data-theme="dark">` / `<html data-theme="light">` 切换
|
||||
- CSS 选择器 `[data-theme="dark"] :root { ... }` / `[data-theme="light"] :root { ... }` 各定义一套
|
||||
- 默认 `data-theme="dark"`(保留现有体验)
|
||||
- 用户切换后 localStorage 持久化,下次访问保持
|
||||
|
||||
---
|
||||
|
||||
## 改造步骤(分阶段,每阶段一次提交,不做大 PR)
|
||||
|
||||
### Stage 1 — inline 颜色全部替换为 var(不破坏现有体验)
|
||||
|
||||
**目标**:所有 `style={{ color: '#xxx' }}` / `background: 'rgba(...)'` 改成 `style={{ color: 'var(--color-xxx)' }}`,深色继续工作不变。
|
||||
|
||||
**具体改动**:
|
||||
|
||||
1. **DashboardPage.tsx** — 31 处
|
||||
- 大部分是图表 axis / legend / tooltip 颜色,对照现有 var 替换
|
||||
- ECharts 配置里的 `axisLine.lineStyle.color` / `tooltip.backgroundColor` 等改用 `getComputedStyle(document.documentElement).getPropertyValue('--color-xxx')` 动态读取(支持主题切换实时刷新图表)
|
||||
2. **TeamDashboardPage.tsx** — 21 处(类似 DashboardPage)
|
||||
3. **RecordDetailModal.tsx** — 17 处(弹窗各 section 标题 / 边框 / 背景)
|
||||
4. **ReferenceList.tsx** — 12 处
|
||||
5. **VideoGenerationPage / VideoDetailModal / ProfilePage / AuroraCanvas** — 共 ~28 处
|
||||
|
||||
**新增的 var**(覆盖现有 `:root` 没有的颜色):
|
||||
- `--color-modal-overlay`(替代各处 `rgba(0,0,0,0.6)` / `rgba(0,0,0,0.7)`)
|
||||
- `--color-text-tertiary`(替代各处 `#888` / `#555`)
|
||||
- `--color-bg-modal`(替代各处 `#1a1a2e` / `#111118`)
|
||||
- `--color-shadow`(替代各处 `rgba(0,0,0,0.4)` 之类)
|
||||
|
||||
**验收**:
|
||||
- `git diff` 看 109 处全部 `style={{ ... '#xxx' ... }}` 变 `var(--color-xxx)`
|
||||
- 浏览器跑起来,肉眼对比改前改后无变化(因为 var 值还是原来的深色值)
|
||||
|
||||
**预估**:1-1.5 天(人)/ 2-3 小时(AI 连续 grep+sed+verify)
|
||||
|
||||
### Stage 2 — `:root` 拆 dark / light 两套
|
||||
|
||||
**目标**:CSS 层面准备好两套值,但不切换(默认 dark,等 Stage 3 切按钮)。
|
||||
|
||||
**改动**:`web/src/index.css`
|
||||
|
||||
```css
|
||||
[data-theme="dark"] {
|
||||
--color-bg-page: #07070f;
|
||||
--color-text-primary: #f1f0ff;
|
||||
/* ... 35 个 var 全部 */
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
--color-bg-page: #fafafa;
|
||||
--color-text-primary: #171823;
|
||||
/* ... 同样 35 个 var 的浅色版本 */
|
||||
}
|
||||
```
|
||||
|
||||
`<html data-theme="dark">` 默认值在 `index.html` 写死,等 Stage 3 才动。
|
||||
|
||||
**验收**:
|
||||
- 手动改 `index.html` 的 `data-theme="light"` 看一眼整页效果
|
||||
- 不要求完美,对比强烈一眼能看出"啊它确实是浅色了"就行
|
||||
- 列出"看着丑"的地方,进 Stage 4 修
|
||||
|
||||
**预估**:0.5 天(人)/ 1 小时(AI)
|
||||
|
||||
### Stage 3 — themeStore + 切换按钮 + 持久化
|
||||
|
||||
**改动**:
|
||||
|
||||
1. 新建 `web/src/store/theme.ts`(Zustand 风格,保持和其他 store 一致):
|
||||
```typescript
|
||||
import { create } from 'zustand';
|
||||
|
||||
type Theme = 'dark' | 'light';
|
||||
|
||||
interface ThemeState {
|
||||
theme: Theme;
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'airdrama-theme';
|
||||
const initialTheme: Theme =
|
||||
(localStorage.getItem(STORAGE_KEY) as Theme) || 'dark';
|
||||
document.documentElement.dataset.theme = initialTheme;
|
||||
|
||||
export const useThemeStore = create<ThemeState>((set, get) => ({
|
||||
theme: initialTheme,
|
||||
toggleTheme: () => {
|
||||
const next = get().theme === 'dark' ? 'light' : 'dark';
|
||||
document.documentElement.dataset.theme = next;
|
||||
localStorage.setItem(STORAGE_KEY, next);
|
||||
set({ theme: next });
|
||||
},
|
||||
}));
|
||||
```
|
||||
|
||||
2. 顶部加切换按钮(建议放 `Sidebar.tsx` 底部 / 用户头像旁,月亮/太阳 SVG 图标)
|
||||
|
||||
3. ECharts 等动态依赖 CSS var 的图表,订阅 theme 变化重新 render(用 `useThemeStore((s) => s.theme)` 作为 key 触发重渲染)
|
||||
|
||||
**验收**:
|
||||
- 点击按钮深↔浅切换流畅
|
||||
- 刷新页面保持上次选择
|
||||
- 登录页 / 错误页等所有路由都生效
|
||||
|
||||
**预估**:0.5 天(人)/ 1 小时(AI)
|
||||
|
||||
### Stage 4 — 浅色色板调试 / 边角料修复
|
||||
|
||||
切完之后**一定**会发现:
|
||||
- 某个按钮文字不可见(对比度不足)
|
||||
- 某个磁玻璃 backdrop 太透看不清
|
||||
- 某个图表的 grid line 浅色下消失
|
||||
- ECharts tooltip 颜色没跟着切
|
||||
|
||||
**做法**:每页跑一遍,列 bug 表,逐个调整 `[data-theme="light"]` 块里的具体值。
|
||||
|
||||
**预估**:1-1.5 天(人)/ 2-3 小时(AI 配合用户截图反馈)
|
||||
|
||||
### Stage 5 — 回归 vitest + 手测
|
||||
|
||||
- vitest 跑一遍(不会因为颜色变化挂,主要看依赖 DOM 结构的 snapshot test 没崩)
|
||||
- 每个页面深 / 浅各走一遍:登录页 / 生成页 / 个人中心 / 7 个 admin 页 / 视频详情弹窗 / 任务详情弹窗 / 公告弹窗 / Toast
|
||||
|
||||
**预估**:0.5-1 天(人)/ 1 小时(AI 跑测试 + 用户走手测)
|
||||
|
||||
---
|
||||
|
||||
## 关键技术点(容易踩坑)
|
||||
|
||||
### 1. 半透明色反相不能简单替换
|
||||
|
||||
`rgba(255,255,255, 0.06)` 不是变成 `rgba(0,0,0, 0.06)`,**透明度也要调整**。白半透明在深色背景下肉眼看是"浅色卡片";黑半透明在浅色背景下看是"深色卡片",但人眼对深色对比的敏感度不同。
|
||||
|
||||
**经验值**:浅色透明度通常比深色 -20%~-40%。比如深色 0.06 对应浅色 0.04。
|
||||
|
||||
### 2. ECharts 等图表的颜色需要 JS 同步切换
|
||||
|
||||
CSS variable 改了,但 ECharts 已经渲染的图表不会自动重新读 var。两种方案:
|
||||
|
||||
- **方案 A**:图表内部颜色用 `getComputedStyle(document.documentElement).getPropertyValue('--color-xxx').trim()`,且组件内 `useEffect(theme => render)` 触发重渲染。
|
||||
- **方案 B**:所有图表配置传入颜色直接读 themeStore 的 theme 值,动态返回不同 hex。
|
||||
|
||||
推荐 A(保持单一颜色源)。
|
||||
|
||||
### 3. AuroraCanvas 极光动效
|
||||
|
||||
登录页 `AuroraCanvas.tsx` 是 canvas 画的极光渐变,硬编码紫色调。
|
||||
- **暗色**:紫蓝极光好看
|
||||
- **浅色**:极光放在白底上会刺眼
|
||||
|
||||
方案:浅色模式下整个 AuroraCanvas 直接 `display: none`,背景换成 `#fafafa` 纯净白,反而更"高级"。
|
||||
|
||||
### 4. 玻璃效果 backdrop-filter
|
||||
|
||||
不少地方用 `backdrop-filter: blur(24px)` + 白半透明做磨砂玻璃。浅色下 backdrop-filter 仍然有效,但底层颜色要换成黑半透明(`rgba(0,0,0,0.04)`)。
|
||||
|
||||
### 5. 主色对比度(WCAG AA)
|
||||
|
||||
`#6c63ff` 紫色按钮:
|
||||
- 深色背景 + 白字:对比度 ~7.1(AAA 级别)✓
|
||||
- 浅色背景 + 白字:对比度 ~4.4(接近 AA 边界,但按钮上的小字可能不够)
|
||||
- 解决:浅色模式 `--color-primary: #5048cc`(加深 18%),按钮上白字对比度 ~6.8(AAA)
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
|
||||
切换前后两种主题下都要看:
|
||||
|
||||
- [ ] 登录页(含 AuroraCanvas 切换)
|
||||
- [ ] 生成页(卡片 / 输入框 / @ 标签 / 滚动条)
|
||||
- [ ] 提示词标签(缩略图 / 文字)
|
||||
- [ ] 任务卡片各种状态(生成中 / 完成 / 失败)
|
||||
- [ ] 个人中心(消费图表)
|
||||
- [ ] 公告弹窗(HTML 渲染)
|
||||
- [ ] Toast / 各种 Modal / Dropdown
|
||||
- [ ] 7 个 admin 页(Dashboard / Users / Records / Settings / Security / Logs / Assets)
|
||||
- [ ] 团管 4 个页(TeamDashboard / TeamMembers / TeamRecords / TeamAssets)
|
||||
- [ ] 火山 EP / 任务详情 / 录像弹窗
|
||||
|
||||
---
|
||||
|
||||
## 工作量预估
|
||||
|
||||
| Stage | 描述 | 人工时 | AI 工时 |
|
||||
|---|---|---|---|
|
||||
| 1 | inline 颜色 → var | 1-1.5 天 | 2-3 小时 |
|
||||
| 2 | dark/light 两套 var | 0.5 天 | 1 小时 |
|
||||
| 3 | themeStore + 切换按钮 | 0.5 天 | 1 小时 |
|
||||
| 4 | 浅色色板调试 | 1-1.5 天 | 2-3 小时 |
|
||||
| 5 | 回归测试 | 0.5-1 天 | 1 小时 |
|
||||
| **总计** | | **3.5-5 天** | **7-9 小时(AI 连续)** |
|
||||
|
||||
---
|
||||
|
||||
## 不做的
|
||||
|
||||
- **跟随系统主题**(`prefers-color-scheme: light`):以后再加,初版手动切换就够
|
||||
- **多套主题**(如 sepia 米色 / 高对比度无障碍模式):用户没要求
|
||||
- **管理后台和用户端独立主题**:保持一致更简单
|
||||
- **每个团队管理员可定制配色**:复杂度爆炸,不做
|
||||
|
||||
---
|
||||
|
||||
## 风险点
|
||||
|
||||
1. **改 `:root` 默认 hex 写法 → 改成 `[data-theme]` 选择器后,原来组件的 var 引用都还能正确解析**(CSS 优先级要确认。`[data-theme="dark"]` 选择器优先级 0,1,0;`:root` 优先级 0,0,1。前者会胜出 ✓)
|
||||
2. **AuroraCanvas 在浅色下隐藏** 的产品决策需要用户确认(也可以保留,但调淡)
|
||||
3. **ECharts 重渲染开销**:每次切主题所有图表 re-render 一遍,仪表盘 6 个图表加起来 ~200ms 卡顿可接受
|
||||
4. **localStorage 在隐身模式 / 用户禁用时**:fallback 到 dark,不报错
|
||||
|
||||
---
|
||||
|
||||
## 参考资料
|
||||
|
||||
- Linear 浅色主题色板:https://linear.app(直接 toggle 看)
|
||||
- Vercel 浅色主题:https://vercel.com(同上)
|
||||
- WCAG 对比度计算:https://webaim.org/resources/contrastchecker/
|
||||
- `prefers-color-scheme` MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
|
||||
---
|
||||
|
||||
## Critical Files
|
||||
|
||||
修改:
|
||||
- `web/src/index.css` — `:root` 拆 `[data-theme="dark/light]` 两套
|
||||
- `web/src/store/theme.ts` — **新建**
|
||||
- `web/src/pages/DashboardPage.tsx` — 31 处颜色替换
|
||||
- `web/src/pages/TeamDashboardPage.tsx` — 21 处
|
||||
- `web/src/components/RecordDetailModal.tsx` — 17 处
|
||||
- `web/src/components/ReferenceList.tsx` — 12 处
|
||||
- `web/src/components/Sidebar.tsx` — 加切换按钮(位置待定)
|
||||
- 其余 ~28 处 inline 颜色散落的组件
|
||||
|
||||
不动:
|
||||
- 后端代码(纯前端改造)
|
||||
- DB schema
|
||||
- 现有路由 / API
|
||||
Loading…
x
Reference in New Issue
Block a user