docs: 更新 CLAUDE.md 与 README.md 反映最新架构

CLAUDE.md:
- 修正覆盖策略描述(Halo 2.25 用 UnoCSS + BEM 类,非 Tailwind)
- 补充 injector.ts 侧边栏注入方案与 halo-core.css 核心地位
- 新增真实环境验证工作流章节

README.md:
- 补充验证过的页面列表与 JDK 25 构建说明
- 补全项目结构中 styles/overrides/ 目录

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 22:54:24 +08:00
parent 42df299791
commit c1c05d9bd4
2 changed files with 69 additions and 15 deletions
+58 -12
View File
@@ -6,12 +6,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
Halo 暗色模式插件 — 为 Halo 2.25 后台管理面板提供深色/浅色模式切换。不修改 Halo 核心代码,完全通过插件机制实现。 Halo 暗色模式插件 — 为 Halo 2.25 后台管理面板提供深色/浅色模式切换。不修改 Halo 核心代码,完全通过插件机制实现。
**核心技术栈**Java 21(后端插件骨架)、Vue 3 + TypeScript(前端 UI)、OKLCH 色彩空间(CSS 变量体系)、Gradle(构建) **核心技术栈**Java(插件骨架,编译目标 21)、Vue 3 + TypeScript(前端 UI)、OKLCH 色彩空间(CSS 变量体系)、Gradle(构建)
**⚠️ 构建环境**:本机没有 JDK 21,构建必须使用 JDK 25(路径已硬编码在 `gradle.properties``org.gradle.java.home`)。`options.release = 21` 保证字节码兼容 Halo API。不要改回 toolchain 方式——那会因找不到 JDK 21 而失败。
## 常用命令 ## 常用命令
```bash ```bash
# 后端 — 启用插件并启动 Halo 开发服务器 # 后端 — 启用插件并启动 Halo 开发服务器(需要 Docker
./gradlew haloServer ./gradlew haloServer
# 后端 — 构建插件 JAR(产物在 build/libs/ # 后端 — 构建插件 JAR(产物在 build/libs/
@@ -52,6 +54,7 @@ halo-dark-mode-plugin/
├── 前端 (Vue 3 / TypeScript) ← 核心实现 ├── 前端 (Vue 3 / TypeScript) ← 核心实现
│ ├── index.ts ← definePlugin() 入口,注册路由+组件 │ ├── index.ts ← definePlugin() 入口,注册路由+组件
│ ├── injector.ts ← ThemeToggle 侧边栏注入器(MutationObserver 方案)
│ ├── composables/ │ ├── composables/
│ │ ├── useDarkMode.ts ← 单例状态管理(light/dark/auto + localStorage 持久化) │ │ ├── useDarkMode.ts ← 单例状态管理(light/dark/auto + localStorage 持久化)
│ │ └── useSystemPreference.ts ← matchMedia 系统偏好监听 │ │ └── useSystemPreference.ts ← matchMedia 系统偏好监听
@@ -60,8 +63,13 @@ halo-dark-mode-plugin/
│ ├── views/ │ ├── views/
│ │ └── SettingsView.vue ← 设置页面(浅色/深色/跟随系统 三选一) │ │ └── SettingsView.vue ← 设置页面(浅色/深色/跟随系统 三选一)
│ └── styles/ │ └── styles/
│ ├── index.css ← 样式入口(@import 聚合)
│ ├── variables.css ← 40+ CSS 变量(:root 浅色 + [data-halo-theme="dark"] 深色) │ ├── variables.css ← 40+ CSS 变量(:root 浅色 + [data-halo-theme="dark"] 深色)
│ └── overrides/ ← 按区域分层覆盖(layout/components/forms/editor/scrollbar/utilities │ └── overrides/
│ ├── halo-core.css ← ★ 核心:真实 DOM 类名覆盖(最重要)
│ ├── layout.css ← 侧边栏/内容区/页脚
│ ├── components.css ← 旧版组件类覆盖(部分已失效,见下)
│ ├── forms.css / editor.css / scrollbar.css / utilities.css
└── 构建链 └── 构建链
└── processUiResources ← Gradle task: ui/dist/ → resources/main/ui/ └── processUiResources ← Gradle task: ui/dist/ → resources/main/ui/
@@ -73,9 +81,38 @@ halo-dark-mode-plugin/
- **触发方式**`document.documentElement` 上设置/移除 `data-halo-theme="dark"` 属性 - **触发方式**`document.documentElement` 上设置/移除 `data-halo-theme="dark"` 属性
- **CSS 变量体系**:所有颜色通过 `--halo-*` 前缀的 CSS 自定义属性控制,一个语义变量对应一个视觉属性 - **CSS 变量体系**:所有颜色通过 `--halo-*` 前缀的 CSS 自定义属性控制,一个语义变量对应一个视觉属性
- **颜色空间**:全部使用 OKLCH(感知均匀,暗色模式天然适配Chrome 111+/Firefox 113+/Safari 15.4+ - **颜色空间**:全部使用 OKLCH(感知均匀,暗色模式天然适配)
- **暗色配色策略**:用亮度层次区分背景(越"高"的层越亮),中性色含微量蓝色调,强调色略降饱和 - **暗色配色策略**:用亮度层次区分背景(越"高"的层越亮),中性色含微量蓝色调,强调色略降饱和
### ⚠️ 最关键的教训:Halo 2.25 用 UnoCSS,不是 Tailwind
Halo 2.25 的 Console 实际使用 **UnoCSS**hash 类如 `uno-*`)加 **BEM 语义类**。**不要写 `.bg-white``.text-gray-900``.v-card` 这类 Tailwind/Vuetify 原子选择器**——它们在真实 DOM 中不存在,覆盖会静默失效。
真实 DOM 里的容器类名(已被 `halo-core.css` 覆盖):
| 语义 | 真实类名 |
|------|---------|
| 页面顶栏 | `.page-header` / `.page-header__title-text` |
| 列表卡片容器 | `.card-wrapper` |
| 文章/用户列表项标题 | `.entity-field-title` / `.entity-field-title-body` |
| 分页 | `.pagination` / `.pagination__btn` |
| 标签 | `.tag-default` / `.tag-content` |
| 模态框 | `.modal-content` / `.modal-header` / `.modal-body` / `.modal-footer` |
| 详情页描述项 | `.description-item-wrapper` / `.description-item__label` / `.description-item__content` |
| Toast | `.toast-container .toast-body` |
| 用户头像 | `.avatar-wrapper` / `.avatar-circle` |
新增覆盖时:**先到真实环境确认类名,不要凭经验写**。
### 覆盖策略(重写后)
`halo-core.css` 是主要覆盖文件,按语义类精准覆盖。它包含三类规则:
1. **BEM 语义类**(如 `.card-wrapper`)— 直接 `[data-halo-theme="dark"] .card-wrapper { background-color: var(--halo-bg-card) }`
2. **通用 UnoCSS 工具类**(如 `.bg-gray-50``.hover:text-gray-600`)— 批量覆盖文字/背景/边框
3. **根背景兜底**`html, body { background-color: var(--halo-bg-body) !important }`body 不设暗色会在溢出时露白)
`components.css` 等旧文件里的 Tailwind/Vuetify 选择器部分已失效,保留但优先维护 `halo-core.css`
### 状态管理 ### 状态管理
- `useDarkMode()` 是**模块级单例** — 所有组件共享同一份 `theme` ref 和 `isDark` computed - `useDarkMode()` 是**模块级单例** — 所有组件共享同一份 `theme` ref 和 `isDark` computed
@@ -83,23 +120,32 @@ halo-dark-mode-plugin/
- 持久化:`localStorage` key `halo-dark-mode-theme`,默认 `auto` - 持久化:`localStorage` key `halo-dark-mode-theme`,默认 `auto`
- FOUC 防护:插件 bundle 顶部同步执行脚本,DOM 渲染前设置 `data-halo-theme` - FOUC 防护:插件 bundle 顶部同步执行脚本,DOM 渲染前设置 `data-halo-theme`
### ThemeToggle 侧边栏注入
Halo 扩展点系统**没有侧边栏插槽**。`injector.ts``MutationObserver` 监听 `.sidebar__profile` 元素出现,在其上方插入容器并挂载 `ThemeToggle.vue` 组件。这是当前 Halo 插件体系下的合理变通方案。
### 前端入口 ### 前端入口
- `definePlugin()``@halo-dev/ui-shared` 导入(非 `@halo-dev/console-shared`,那是旧版 plugin-starter 的源 - `definePlugin()``@halo-dev/ui-shared` 导入(非旧版 `@halo-dev/console-shared`
- 路由使用 `() => import(...)` 懒加载 - 路由使用 `() => import(...)` 懒加载
- 构建使用 `@halo-dev/ui-plugin-bundler-kit``viteConfig()` 包装器 - 构建使用 `@halo-dev/ui-plugin-bundler-kit``viteConfig()` 包装器
### 覆盖策略
三级渐进覆盖:
1. **CSS 变量注入**~80% 场景)— 通过 `--halo-*` 变量重定义 Tailwind 颜色语义
2. **选择器覆盖**~17% 场景)— `[data-halo-theme="dark"]` 前缀高特异性选择器
3. **组件穿透**~3% 场景)— FormKit/编辑器等第三方组件的自有 CSS 变量接口
### 后端 ### 后端
后端极简 — `DarkModePlugin extends BasePlugin` 仅含 `start()`/`stop()` 生命周期钩子。所有核心逻辑在前端。插件不依赖后端 Setting API。 后端极简 — `DarkModePlugin extends BasePlugin` 仅含 `start()`/`stop()` 生命周期钩子。所有核心逻辑在前端。插件不依赖后端 Setting API。
## 验证工作流(必须)
对 CSS 覆盖的任何改动,都要在**真实 Halo 环境**验证,不能只靠 `vite build` 通过:
1. 打开官方 demo 站 `https://demo.halocms.site/console`,登录 `demo / P@ssw0rd123..`
2. 用 Playwright 的 `page.addStyleTag({ path: 'ui/build/dist/style.css' })` 注入构建产物,并 `document.documentElement.setAttribute('data-halo-theme', 'dark')`
3. 遍历页面,扫描 `main *` 中残留的白色背景(`rgb(255,255,255)` 且尺寸 >100×40)和深色文字(`rgb(17,24,39)` 等)元素,记录其真实类名
4. 新增覆盖后重新构建、重新注入、重新扫描,直到零残留
5. 最终 `./gradlew build` 打 JAR,确认 `ui/style.css` 已更新
第三方插件页面(链接/订阅/瞬间等)在 demo 站已装,可一并验证。
## 项目文档 ## 项目文档
- `设计文档.md` — 完整的技术设计(架构图、CSS 变量清单、调色板、组件覆盖策略、实现阶段划分、测试策略) - `设计文档.md` — 完整的技术设计(架构图、CSS 变量清单、调色板、组件覆盖策略、实现阶段划分、测试策略)
+11 -3
View File
@@ -12,10 +12,11 @@ Halo 2.25 暗色模式插件 — 为 Halo 后台管理面板提供深色/浅色
- ⚙️ **设置页面**:提供详细的模式选择界面(菜单 → 偏好设置 → 深色模式) - ⚙️ **设置页面**:提供详细的模式选择界面(菜单 → 偏好设置 → 深色模式)
- 🎨 **OKLCH 色彩空间**:感知均匀,暗色模式天然适配,WCAG AA 对比度保证 - 🎨 **OKLCH 色彩空间**:感知均匀,暗色模式天然适配,WCAG AA 对比度保证
- 📦 **零后端依赖**:纯前端实现,不需要后端 API - 📦 **零后端依赖**:纯前端实现,不需要后端 API
-**覆盖已验证**:仪表盘、内容管理(文章/页面/评论)、链接、订阅、瞬间、用户、主题、设置、编辑器、模态框等页面已针对 Halo 2.25 真实 DOM 逐一验证
## 开发环境 ## 开发环境
- Java 21+ - Java 21+(Halo 插件编译要求;本机开发使用 JDK 25 + `--release 21`
- Node.js 18+ - Node.js 18+
- pnpm - pnpm
@@ -55,7 +56,7 @@ pnpm test:unit # 单元测试
## 项目结构 ## 项目结构
``` ```text
├── build.gradle # 根构建(BOM 2.25.0, DevTools 0.8.0 ├── build.gradle # 根构建(BOM 2.25.0, DevTools 0.8.0
├── settings.gradle # 包含 :ui 子项目 ├── settings.gradle # 包含 :ui 子项目
├── src/ ├── src/
@@ -79,7 +80,14 @@ pnpm test:unit # 单元测试
└── styles/ └── styles/
├── index.css # 样式入口 ├── index.css # 样式入口
├── variables.css # 40+ CSS 变量(浅色 + 深色) ├── variables.css # 40+ CSS 变量(浅色 + 深色)
└── overrides/ # 组件覆盖样式 └── overrides/
├── halo-core.css # ★ 核心:真实 DOM 类名覆盖
├── layout.css # 侧边栏/内容区/页脚
├── components.css # 组件类覆盖
├── forms.css # FormKit 表单
├── editor.css # 富文本编辑器
├── scrollbar.css # 滚动条
└── utilities.css # 通用工具类
``` ```
## 许可证 ## 许可证