第四章:完整工作流演示
本章通过一个完整的案例,演示 OpenSpec 的实际使用流程。
案例:添加暗黑模式
假设我们要为一个 React 项目添加暗黑模式功能。
第一步:创建提案
/opsx:propose "添加暗黑模式,用户可以在亮色和暗色主题之间切换"
AI 分析后,创建目录结构:
openspec/changes/add-dark-mode/
├── proposal.md
├── specs/
│ └── requirements.md
├── design.md
└── tasks.md
proposal.md 内容示例
# 提案:添加暗黑模式
## 背景
当前应用只有亮色主题,在夜间或弱光环境下使用体验不佳。
## 目标
- 支持亮色/暗色主题切换
- 自动跟随系统主题偏好
- 用户偏好持久化
## 成功标准
- 用户可以通过开关切换主题
- 切换后所有组件正确显示
- 刷新页面后保持用户选择
specs/requirements.md 内容示例
# 需求规范
## 功能需求
1. 添加主题切换开关(位于导航栏右侧)
2. 支持三种模式:
- Light(亮色)
- Dark(暗色)
- System(跟随系统)
3. 用户选择保存到 localStorage
4. 默认值为 System
## 视觉需求
- 暗色模式背景色:#1a1a2e
- 暗色模式文字色:#eaeaea
- 所有组件需要适配两种主题
## 场景
### 场景 1:首次访问
用户首次访问,检测系统主题,自动应用
### 场景 2:手动切换
用户点击切换按钮,主题立即改变
### 场景 3:重新访问
用户再次访问,恢复上次选择的主题
design.md 内容示例
# 技术设计
## 方案
使用 React Context + CSS Variables 实现
## 文件结构
src/ ├── components/ │ └── ThemeToggle.tsx # 主题切换按钮 ├── contexts/ │ └── ThemeContext.tsx # 主题上下文 ├── hooks/ │ └── useTheme.ts # 主题 Hook └── styles/ └── theme.css # 主题变量
## 实现细节
1. ThemeContext 管理当前主题状态
2. CSS Variables 定义颜色变量
3. localStorage 持久化用户选择
4. matchMedia 监听系统主题变化
## 颜色变量
```css
:root {
--bg-primary: #ffffff;
--text-primary: #1a1a2e;
}
[data-theme="dark"] {
--bg-primary: #1a1a2e;
--text-primary: #eaeaea;
}
### tasks.md 内容示例
```markdown
# 实现任务
## 1. 创建主题系统
- [ ] 1.1 创建 ThemeContext.tsx
- [ ] 1.2 创建 useTheme hook
- [ ] 1.3 创建 theme.css 变量文件
## 2. 创建切换组件
- [ ] 2.1 创建 ThemeToggle 组件
- [ ] 2.2 添加太阳/月亮图标
- [ ] 2.3 实现点击切换逻辑
## 3. 集成到应用
- [ ] 3.1 在 App.tsx 包裹 ThemeProvider
- [ ] 3.2 在导航栏添加 ThemeToggle
- [ ] 3.3 更新现有组件使用 CSS 变量
## 4. 持久化和系统适配
- [ ] 4.1 实现 localStorage 存储
- [ ] 4.2 实现系统主题监听
- [ ] 4.3 处理首次访问的默认主题
第二步:审查规范
这是最关键的一步!
仔细阅读 AI 生成的文档:
# 查看 proposal
cat openspec/changes/add-dark-mode/proposal.md
# 查看需求
cat openspec/changes/add-dark-mode/specs/requirements.md
# 查看设计
cat openspec/changes/add-dark-mode/design.md
# 查看任务
cat openspec/changes/add-dark-mode/tasks.md
确认无误
如果文档符合预期,告诉 AI:
规范文档看起来不错,可以开始实现了
需要修改
如果有问题,直接指出:
design.md 里的颜色方案我们改用 Tailwind 的 dark: 前缀,不用 CSS Variables
tasks.md 里需要添加单元测试任务
AI 会更新文档,直到你满意为止。
第三步:应用实现
确认规范后,开始实现:
/opsx:apply
实现过程
AI 会按 tasks.md 的顺序执行:
开始实现暗黑模式功能...
✓ 1.1 创建 ThemeContext.tsx
创建了主题上下文,包含 theme、setTheme、toggleTheme
✓ 1.2 创建 useTheme hook
封装了主题状态获取和切换方法
✓ 1.3 创建 theme.css 变量文件
定义了亮色和暗色模式的颜色变量
✓ 2.1 创建 ThemeToggle 组件
创建了带有太阳/月亮图标的切换按钮
✓ 2.2 添加太阳/月亮图标
使用 lucide-react 图标库
✓ 2.3 实现点击切换逻辑
点击时切换主题并保存到 localStorage
✓ 3.1 在 App.tsx 包裹 ThemeProvider
在应用根节点添加了主题提供者
✓ 3.2 在导航栏添加 ThemeToggle
在 Header 组件右侧添加了切换按钮
✓ 3.3 更新现有组件使用 CSS 变量
更新了 Button、Card、Input 等组件
✓ 4.1 实现 localStorage 存储
主题选择持久化到 localStorage
✓ 4.2 实现系统主题监听
使用 matchMedia 监听系统主题变化
✓ 4.3 处理首次访问的默认主题
首次访问时检测系统偏好
🎉 所有任务完成!
第四步:验证功能
实现完成后,手动测试:
# 启动应用
npm run dev
# 测试以下场景:
# 1. 点击切换按钮,主题是否正确切换
# 2. 刷新页面,主题是否保持
# 3. 切换系统主题,应用是否跟随
验证命令
/opsx:verify
AI 会对比 specs/ 和代码,报告是否符合规范。
第五步:归档变更
功能测试通过后,归档记录:
/opsx:archive
变更被移动到:
openspec/changes/add-dark-mode/
→ openspec/archive/2025-03-16-add-dark-mode/
目录结构:
openspec/archive/2025-03-16-add-dark-mode/
├── proposal.md
├── specs/
├── design.md
├── tasks.md
└── summary.md # 新增:实现摘要
summary.md 内容示例
# 实现摘要
## 完成时间
2025-03-16
## 实现内容
- ✅ ThemeContext 和 useTheme hook
- ✅ ThemeToggle 组件(太阳/月亮图标)
- ✅ CSS 变量主题系统
- ✅ localStorage 持久化
- ✅ 系统主题自动适配
## 新增文件
- src/contexts/ThemeContext.tsx
- src/hooks/useTheme.ts
- src/components/ThemeToggle.tsx
- src/styles/theme.css
## 修改文件
- src/App.tsx
- src/components/Header.tsx
- src/components/Button.tsx
- src/components/Card.tsx
- src/components/Input.tsx
## 备注
实现过程顺利,无需调整规范
完整流程图
开始
│
▼
/opsx:propose "描述你的需求"
│
▼
AI 创建规范文档
│
▼
你审查规范文档
│
├─ 不满意 ──→ 告诉 AI 修改 ──→ 回到审查
│
└─ 满意 ─────→ /opsx:apply
│
▼
AI 实现代码
│
▼
你测试验证
│
├─ 有问题 ──→ 告诉 AI 修复 ──→ 继续测试
│
└─ 没问题 ──→ /opsx:archive
│
▼
归档完成
│
▼
开始下一个功能