208 lines
5.9 KiB
Markdown
208 lines
5.9 KiB
Markdown
# ADR 001: Pinia 状态管理迁移
|
||
|
||
## 状态
|
||
已实施
|
||
|
||
## 日期
|
||
2026-02-04
|
||
|
||
## 背景
|
||
|
||
前端更新管理模块存在以下问题:
|
||
- **代码重复**:UpdatePanel.vue 和 UpdateNotification.vue 都维护了相同的状态和逻辑
|
||
- **事件监听重复**:两个组件都注册了 download-progress 和 download-complete 事件
|
||
- **工具函数重复**:parseEventData、formatFileSize、formatSpeed 在多处定义
|
||
- **状态管理混乱**:useUpdate composable 使用单例模式,但 Ref 解构会丢失响应性
|
||
|
||
## 决策
|
||
|
||
采用 **Pinia Store** 方案统一管理前端状态。
|
||
|
||
### 方案对比(10 维度分析)
|
||
|
||
| 方案 | 得分 | 成本(2年) | 风险 | 可维护性 |
|
||
|------|------|-------------|------|---------|
|
||
| Pinia Store | **78.3/100** | 21 人天 | 低 (2.0/10) | 优秀 (9.0/10) |
|
||
| Singleton Composable | 65.0/100 | 40 人天 | 高 (6.0/10) | 中等 (6.5/10) |
|
||
| Provide/Inject | 60.0/100 | 35 人天 | 中 (4.5/10) | 中等 (6.0/10) |
|
||
|
||
**Pinia 核心优势**:
|
||
- ✅ 全局唯一的响应式状态
|
||
- ✅ DevTools 支持,便于调试
|
||
- ✅ TypeScript 友好
|
||
- ✅ 自动代码分割
|
||
- ✅ 降低 47.5% 的长期维护成本
|
||
|
||
## 实施细节
|
||
|
||
### 1. 安装 Pinia
|
||
```bash
|
||
npm install pinia
|
||
```
|
||
|
||
### 2. 创建 Update Store
|
||
**文件**:`frontend/src/stores/update.ts`
|
||
|
||
**核心功能**:
|
||
- 状态管理:updateInfo, checking, downloading, installing, downloadProgress
|
||
- 方法:checkForUpdates, downloadUpdate, installUpdate
|
||
- 工具函数:formatFileSize, formatSpeed
|
||
- 事件监听:setupEventListeners, removeEventListeners
|
||
|
||
### 3. 更新 main.js
|
||
集成 Pinia 到应用:
|
||
```javascript
|
||
import { createPinia } from 'pinia'
|
||
|
||
const app = createApp(App)
|
||
const pinia = createPinia()
|
||
|
||
app.use(pinia)
|
||
```
|
||
|
||
### 4. 组件迁移
|
||
|
||
#### App.vue
|
||
- 使用 `useUpdateStore()` 替代 `useUpdate()`
|
||
- 在 onMounted 中设置事件监听
|
||
- 启动后 3 秒自动检查更新
|
||
|
||
#### UpdatePanel.vue
|
||
- 从 store 获取状态:`updateStore.checking`, `updateStore.downloadProgress` 等
|
||
- 移除本地重复状态和方法
|
||
- 仅保留文件路径记录(downloadedFile)
|
||
|
||
#### UpdateNotification.vue
|
||
- 使用 store 的计算属性:`updateStore.downloading`, `updateStore.installing`
|
||
- 移除本地工具函数(parseEventData, formatFileSize)
|
||
- 移除重复的事件监听器
|
||
- 保留 UI 逻辑(Modal 显示和更新)
|
||
|
||
### 5. 清理
|
||
- 删除 `frontend/src/composables/useUpdate.js`
|
||
- 移除组件中对旧 composable 的引用
|
||
|
||
## 迁移清单
|
||
|
||
- [x] 安装 Pinia
|
||
- [x] 创建 stores/update.ts
|
||
- [x] 更新 main.js
|
||
- [x] 迁移 App.vue
|
||
- [x] 迁移 UpdatePanel.vue
|
||
- [x] 迁移 UpdateNotification.vue
|
||
- [x] 删除 useUpdate.js
|
||
- [x] 验证无残留引用
|
||
|
||
## 影响范围
|
||
|
||
### 修改的文件
|
||
1. `frontend/package.json` - 添加 pinia 依赖
|
||
2. `frontend/src/main.js` - 集成 Pinia
|
||
3. `frontend/src/stores/update.ts` - 新建
|
||
4. `frontend/src/App.vue` - 使用 store
|
||
5. `frontend/src/components/UpdatePanel.vue` - 使用 store
|
||
6. `frontend/src/components/UpdateNotification.vue` - 使用 store
|
||
|
||
### 删除的文件
|
||
1. `frontend/src/composables/useUpdate.js` - 已迁移到 store
|
||
|
||
## 效果
|
||
|
||
### 代码质量提升
|
||
- **减少重复**:删除 200+ 行重复代码
|
||
- **统一管理**:所有更新相关状态集中在一个 store
|
||
- **响应性保证**:Pinia 自动处理响应式,无解构丢失问题
|
||
|
||
### 开发体验改善
|
||
- **DevTools 集成**:可以实时查看和修改状态
|
||
- **类型安全**:TypeScript 支持完善
|
||
- **调试便利**:状态变化可追踪
|
||
|
||
### 维护成本降低
|
||
- **单一数据源**:状态变化路径清晰
|
||
- **事件监听统一**:只注册一次,全局共享
|
||
- **未来扩展性**:可轻松添加更多 store(如 theme, config)
|
||
|
||
## 后续计划
|
||
|
||
### 短期
|
||
- [ ] 添加单元测试(store actions)
|
||
- [ ] 添加 E2E 测试(更新流程)
|
||
- [ ] 性能监控(事件监听开销)
|
||
|
||
### 长期
|
||
- [x] 迁移 theme 管理到 Pinia(useTheme → stores/theme)✅
|
||
- [x] 迁移 config 管理到 Pinia ✅
|
||
- [ ] 统一所有全局状态管理
|
||
|
||
## 参考
|
||
|
||
- [Pinia 官方文档](https://pinia.vuejs.org/)
|
||
- [Vue 3 Composition API](https://vuejs.org/api/composition-api-setup.html)
|
||
- [Agent 分析报告](../.claude/projects/E--wk-lab-go-desk/)
|
||
|
||
## 作者
|
||
|
||
Claude Code with User Decision
|
||
|
||
---
|
||
|
||
**变更记录**:
|
||
- 2026-02-04: 初始版本,完成 Pinia 迁移(更新管理)
|
||
- 2026-02-04: 第二次迁移,完成 theme 和 config 管理到 Pinia
|
||
|
||
## 第二次迁移:Theme & Config(2026-02-04)
|
||
|
||
### 新增 Stores
|
||
|
||
#### 1. Theme Store(`frontend/src/stores/theme.ts`)
|
||
**功能**:
|
||
- 管理亮色/暗色主题
|
||
- 跟随系统主题变化
|
||
- 主题持久化(localStorage)
|
||
|
||
**核心方法**:
|
||
- `toggleTheme()` - 切换主题
|
||
- `setLightTheme()` / `setDarkTheme()` - 设置特定主题
|
||
- `initTheme()` - 初始化(检测系统偏好)
|
||
- `removeSystemThemeListener()` - 清理监听器
|
||
|
||
**计算属性**:
|
||
- `isDark` / `isLight` - 主题判断
|
||
- `tooltipText` - 提示文本
|
||
|
||
#### 2. Config Store(`frontend/src/stores/config.ts`)
|
||
**功能**:
|
||
- 管理应用配置(标签页、默认页等)
|
||
- 从后端加载配置
|
||
- 保存配置到后端
|
||
|
||
**核心方法**:
|
||
- `loadConfig()` - 加载配置
|
||
- `saveConfig()` - 保存配置
|
||
- `isTabVisible()` - 检查 Tab 可见性
|
||
- `getTab()` - 获取 Tab 配置
|
||
|
||
**计算属性**:
|
||
- `visibleTabs` - 可见标签页列表
|
||
- `allTabs` - 所有标签页
|
||
- `defaultTab` - 默认标签页
|
||
|
||
### 组件迁移
|
||
|
||
#### 更新的文件
|
||
1. `frontend/src/main.js` - 使用 themeStore.initTheme()
|
||
2. `frontend/src/components/ThemeToggle.vue` - 使用 themeStore
|
||
3. `frontend/src/components/CodeEditor.vue` - 使用 themeStore.isDark
|
||
4. `frontend/src/App.vue` - 使用 configStore
|
||
|
||
#### 删除的文件
|
||
1. `frontend/src/composables/useTheme.ts` - 已迁移到 store
|
||
|
||
### 效果
|
||
- **统一管理**:主题和配置状态集中管理
|
||
- **简化组件**:移除组件内的重复逻辑
|
||
- **响应性保证**:所有状态变化自动响应
|
||
- **DevTools 支持**:可以实时查看和修改状态
|
||
- **构建成功**:✓ built in 34.28s
|