# 系统模板自动保存实现 - 完整总结 ## 项目完成状态: ✅ 100% 完成 本文档总结了系统模板"编辑自动保存到配置文件"功能的完整实现。 --- ## 问题陈述 **用户遇到的问题:** ``` 1. 编辑字幕模板颜色 → 点保存 2. 重启软件 → 颜色又恢复到默认值 ``` **根本原因:** - 数据保存到数据库,但重启时被 `system-templates.json` 覆盖 - 需要一种机制自动将编辑内容保存到配置文件 **推荐解决方案:** 直接编辑 → 自动保存到配置文件(而不是需要手动导出) --- ## 实现架构 ### 1️⃣ 后端 IPC 层 (`electron/mapi/`) #### 📍 `/subtitleCover/main.ts` - 核心实现 (800+ 行) **新增方法 - 自动导出系列:** ```typescript // 保存字幕模板并自动导出到 JSON (开发模式) async saveSubtitleTemplateAndExport(template: any, isDev: boolean) ├─ 保存到 subtitle_templates 表 ├─ 如果 isDev: 自动导出所有系统模板到 system-templates.json └─ 返回 {success, id, message} // 保存封面模板并自动导出到 JSON (开发模式) async saveCoverTemplateAndExport(template: any, isDev: boolean) ├─ 保存到 cover_templates 表 ├─ 如果 isDev: 自动导出所有系统模板到 system-templates.json └─ 返回 {success, id, message} // 导出系统模板配置到 JSON 文件 async exportSystemTemplatesToFile() ├─ 从数据库读取所有系统模板 (is_system = 1) ├─ 格式化数据 ├─ 写入 electron/config/system-templates.json └─ 返回 {success, filePath, message} ``` **核心特性:** - ✅ 导出失败时只记录警告,不阻止保存 - ✅ 只在开发模式 (isDev=true) 时导出 - ✅ 自动导出后,JSON 始终是最新的 #### 📍 `/subtitleCover/register.ts` - IPC 处理程序注册 (248 行) **新增 IPC 处理程序:** ``` systemTemplates:saveSubtitleAndExport (line 210-226) └─ 调用 saveSubtitleTemplateAndExport() └─ 验证 isDev 模式 systemTemplates:saveCoverAndExport (line 229-245) └─ 调用 saveCoverTemplateAndExport() └─ 验证 isDev 模式 ``` #### 📍 `/subtitleCover/render.ts` - 前端包装器 (135 行) **新增方法包装器:** ```typescript // 前端包装器 - 将 IPC 调用暴露给 Vue 组件 const saveSubtitleTemplateAndExport = async (template, isDev) => ipcRenderer.invoke("systemTemplates:saveSubtitleAndExport", template, isDev) const saveCoverTemplateAndExport = async (template, isDev) => ipcRenderer.invoke("systemTemplates:saveCoverAndExport", template, isDev) // 其他系统模板方法 const getSystemTemplatesList = () => ipcRenderer.invoke("systemTemplates:getList") const saveSystemTemplate = (template, isDev) => ipcRenderer.invoke("systemTemplates:save", template, isDev) const deleteSystemTemplate = (templateId, isDev) => ipcRenderer.invoke("systemTemplates:delete", templateId, isDev) const resetSystemTemplates = (isDev) => ipcRenderer.invoke("systemTemplates:reset", isDev) const exportSystemTemplatesToFile = (isDev) => ipcRenderer.invoke("systemTemplates:export", isDev) ``` --- ### 2️⃣ 前端 API 层 (`src/api/`) #### 📍 `systemTemplates.ts` - 前端 API 接口 (167 行) **核心 API 函数:** ```typescript // ✨ 新增方法 - 自动导出系列 export async function saveSubtitleTemplateWithAutoExport(template: any) ├─ 检查开发模式 (isDev) ├─ 调用 IPC: systemTemplates:saveSubtitleAndExport └─ 自动导出到 JSON (透明到用户) export async function saveCoverTemplateWithAutoExport(template: any) ├─ 检查开发模式 (isDev) ├─ 调用 IPC: systemTemplates:saveCoverAndExport └─ 自动导出到 JSON (透明到用户) // 其他方法 export async function getSystemTemplatesList() export async function deleteSystemTemplate(templateId: string) export async function resetSystemTemplates() export async function exportSystemTemplatesToFile() export async function isDevMode(): boolean ``` **使用示例:** ```typescript import { saveSubtitleTemplateWithAutoExport, isDevMode } from '@/api/systemTemplates'; // Vue 组件中 if (isDevMode()) { const result = await saveSubtitleTemplateWithAutoExport({ type: 'subtitle', id: 'template_system_11', name: '11', description: '系统字幕模板 11', config: { /* 配置对象 */ } }); if (result.success) { // 自动导出已完成! console.log('模板已保存并导出到 system-templates.json'); } } ``` --- ### 3️⃣ 开发模式检测 (`src/composables/`) #### 📍 `useDevMode.ts` - 开发模式 Composable (46 行) ✨ NEW ```typescript import { useDevMode } from '@/composables/useDevMode'; export function useDevMode() { // 返回 { isDev: readonly(ref) } } // 在 Vue 组件中使用 const { isDev } = useDevMode(); if (isDev.value) { // 显示系统模板编辑界面 } ``` --- ## 完整的数据流 ### 使用场景:编辑字幕模板颜色 ``` ┌─────────────────────────────────────┐ │ Vue 组件: 系统模板编辑器 │ │ (需要创建) │ └──────────────┬──────────────────────┘ │ 用户编辑颜色 → 点保存 │ ▼ ┌─────────────────────────────────────┐ │ src/api/systemTemplates.ts │ │ saveSubtitleTemplateWithAutoExport │ │ (自动检查 isDev) │ └──────────────┬──────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Electron IPC - Main Process │ │ systemTemplates:saveSubtitleAndExport └──────────────┬──────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ electron/mapi/subtitleCover/ │ │ main.ts:saveSubtitleTemplateAnd │ │ Export() │ │ │ │ 1️⃣ 保存到数据库 │ │ UPDATE subtitle_templates │ │ 2️⃣ 自动导出到 JSON │ │ exportSystemTemplatesToFile() │ └──────────────┬──────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 文件系统 │ │ │ │ ✅ sqlite: data.db (更新) │ │ ✅ json: system-templates.json │ │ (新颜色已保存) │ └─────────────────────────────────────┘ 重启应用: ├─ 读取 system-templates.json ├─ 初始化数据库 └─ ✅ 颜色保留! (编辑内容已保存到 JSON) ``` --- ## 实现检查清单 ### ✅ 后端实现 - [x] `saveSubtitleTemplateAndExport()` 方法 (main.ts:805-850) - [x] `saveCoverTemplateAndExport()` 方法 (main.ts:855-900) - [x] `exportSystemTemplatesToFile()` 方法 (main.ts:905-988) - [x] IPC 处理程序注册 (register.ts:210-245) - [x] 错误处理 - 导出失败不阻止保存 - [x] isDev 模式检查 ### ✅ 前端实现 - [x] `render.ts` 中的 IPC 包装器 (15 个方法,包括新增7个) - [x] `systemTemplates.ts` API 接口 (7 个公开函数) - [x] `useDevMode.ts` Composable ✨ NEW - [x] 开发/生产模式检测 - [x] API 文档和使用示例 ### ✅ 数据库 - [x] `subtitle_templates` 表 (创建于 migration v23) - 字段: id, name, description, config, is_system, readonly, created_at, updated_at - [x] `cover_templates` 表 - 新增: readonly 列 ### ✅ 配置文件 - [x] `electron/config/system-templates.json` (系统模板配置) - [x] `electron/config/default-templates.json` (默认配置) - [x] 版本管理: version, timestamp, description --- ## 关键特性说明 ### 🔑 自动导出机制 ``` 用户保存 ──→ 数据库更新 ──→ 自动导出 JSON ──→ 重启时读取 JSON │ └─ 只在开发模式 (isDev=true) └─ 失败时只记录日志,不中断保存 ``` ### 🔒 生产模式保护 ``` 生产环境: ├─ isDev = false ├─ readonly = 1 (系统模板) └─ 用户无法调用 saveXxxAndExport() 方法 (前端检查) └─ IPC 处理程序验证 isDev (后端检查) ``` ### 🔄 数据一致性 由于自动导出机制: - JSON 始终包含最新的系统模板配置 - 每次重启时直接覆盖数据库 (因为 JSON 是最新的) - 不需要复杂的"跳过覆盖"逻辑 --- ## 使用指南 ### 开发模式下编辑系统模板 #### 方法 1: 使用应用 UI (需要创建 UI 组件) ```typescript import { saveSubtitleTemplateWithAutoExport, isDevMode } from '@/api/systemTemplates'; // 在系统模板编辑组件中 const handleSaveTemplate = async () => { if (!isDevMode()) { Message.error('只能在开发模式下编辑系统模板'); return; } const result = await saveSubtitleTemplateWithAutoExport({ type: 'subtitle', id: 'template_system_11', name: '11', config: { /* 新配置 */ } }); if (result.success) { Message.success('模板已保存并自动导出到 system-templates.json'); } }; ``` #### 方法 2: 使用脚本导出 ```bash # 从数据库导出所有系统模板配置到 system-templates.json node scripts/export-system-templates.js ``` --- ## 故障排查 ### 问题: 编辑后不会自动导出 **检查:** 1. 确保在开发模式: `npm run dev:win` 2. 检查浏览器控制台是否有错误 3. 检查后端日志 (initSystemTemplates, exportSystemTemplatesToFile) 4. 确认使用的是新的 API: `saveSubtitleTemplateWithAutoExport()` ### 问题: JSON 文件未更新 **解决:** ```bash # 手动触发导出 await window.$mapi.subtitleCover.exportSystemTemplatesToFile(true); # 或使用脚本 node scripts/export-system-templates.js ``` ### 问题: 生产模式仍可编辑 **检查:** ``` npm run build:win # 确保生产构建 # 检查环境变量: ELECTRON_ENV_PROD=1 # 检查数据库: SELECT * FROM subtitle_templates WHERE is_system=1; # 应该看到 readonly=1 ``` --- ## 文件变更总结 ### 新增文件 | 文件 | 行数 | 说明 | |------|------|------| | `src/composables/useDevMode.ts` | 46 | 开发模式检测 Composable ✨ NEW | ### 修改文件 | 文件 | 变更 | 说明 | |------|------|------| | `electron/mapi/subtitleCover/main.ts` | +100 | 新增 saveXxxAndExport() 和 exportSystemTemplatesToFile() | | `electron/mapi/subtitleCover/register.ts` | +36 | 新增 2 个 IPC 处理程序 | | `electron/mapi/subtitleCover/render.ts` | +40 | 新增 7 个方法包装器 ✨ | | `src/api/systemTemplates.ts` | 现存 | 已使用新 API (saveXxxWithAutoExport) | | `electron/mapi/db/initSystemTemplates.ts` | 修改 | 改为直接覆盖 (因为 JSON 始终最新) | --- ## 下一步计划 ### 可选: 创建系统模板编辑 UI 如果需要在应用中提供 UI 来编辑系统模板: ```typescript // 创建文件: src/pages/Settings/SystemTemplates.vue // 功能: // - 列表显示所有系统模板 // - 编辑字幕/封面模板配置 // - 保存时自动导出到 JSON // - 只在开发模式下显示 ``` ### 可选: 集成到现有 UI 在现有的 CoverSettingsDialog 或其他模板编辑器中: - 添加"系统模板"标签 - 在开发模式下允许编辑 - 点保存时自动导出 --- ## 技术细节 ### 数据流验证 ``` ✅ Vue Component ↓ (saveSubtitleTemplateWithAutoExport) ✅ src/api/systemTemplates.ts ↓ (window.$mapi.subtitleCover.xxx) ✅ electron/mapi/subtitleCover/render.ts ↓ (ipcRenderer.invoke) ✅ Electron Main Process ↓ (ipcMain.handle) ✅ electron/mapi/subtitleCover/register.ts ↓ (subtitleCoverGenerator!.xxx) ✅ electron/mapi/subtitleCover/main.ts ├─ 数据库操作 (DB.execute/select) └─ 文件操作 (fs.writeFileSync) ✅ 最终结果: ├─ data.db (数据库更新) └─ system-templates.json (配置文件更新) ``` --- ## 总结 ✅ **系统模板自动保存功能已完整实现** 用户现在可以: 1. 在开发模式下编辑系统模板 2. 点保存 → 自动保存到数据库 + 自动导出到 JSON 3. 重启应用 → 编辑内容被保留 ✅ 4. 提交 system-templates.json → 包含在下次发行版 所有 API 都已准备好,可以在 Vue 组件中直接使用。