From 3da801d6e61db632c05be6f479cce3851838ddcd Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Sun, 10 May 2026 21:43:26 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BA=AE=E8=89=B2=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=BC=80=E5=8F=91=E8=AE=A1=E5=88=92=20(P3,?= =?UTF-8?q?=20AI=20=E8=87=AA=E4=B8=BB=E5=AE=8C=E6=88=90=E9=A2=84=E5=A4=87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- docs/todo/亮色主题切换.md | 313 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 docs/todo/亮色主题切换.md diff --git a/docs/todo/亮色主题切换.md b/docs/todo/亮色主题切换.md new file mode 100644 index 0000000..3b96b8d --- /dev/null +++ b/docs/todo/亮色主题切换.md @@ -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)` | 浅色下阴影减弱 | + +### 切换机制 + +- 用 `` / `` 切换 +- 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 的浅色版本 */ +} +``` + +`` 默认值在 `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((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