# 数据分类与代码生成工具 Cherry Studio 数据重构项目的自动化工具集,用于管理数据分类和生成 TypeScript 代码。 **版本**: 2.0.0 **更新日期**: 2025-11-28 > ⚠️ **阶段性使命已完成(重要)** > > 本工具中仅 **代码生成(generate)** 流水线仍在使用。数据提取、一致性/生成校验、重复键检查等命令与脚本已完成阶段性使命,**不再支持,请勿再次运行**。 > > | 仍可用 | 已弃用(不再支持) | > | --- | --- | > | `npm run generate`、`generate:preferences`、`generate:boot-config`、`generate:migration` | `npm run extract`、`validate`、`validate:gen`、`check:duplicates`、`all` | > > 对应脚本文件已加 `DO-NOT-USE-` 前缀(`DO-NOT-USE-extract-inventory.js`、`DO-NOT-USE-validate-consistency.js`、`DO-NOT-USE-validate-generation.js`、`DO-NOT-USE-check-duplicates.js`);运行已弃用的 npm 命令只会打印一行提示。下文中保留的相关章节仅作历史记录,如有疑问请询问作者。 ## 概述 本工具集提供以下功能: - **数据提取**: 扫描源代码,构建数据清单 - **分类管理**: 维护分类映射,支持增量更新 - **代码生成**: 生成 TypeScript 接口和迁移映射 - **验证检查**: 确保清单与分类之间的一致性 ## 目录结构 ``` v2-refactor-temp/tools/data-classify/ ├── scripts/ │ ├── lib/ │ │ └── classificationUtils.js # 共享工具函数(仅被下方已弃用脚本使用) │ ├── generate-all.js # 运行所有生成器 │ ├── generate-preferences.js # 生成 preferenceSchemas.ts │ ├── generate-boot-config.js # 生成 bootConfigSchemas.ts │ ├── generate-migration.js # 生成 PreferencesMappings.ts + BootConfigMappings.ts │ ├── DO-NOT-USE-extract-inventory.js # [已弃用] 从源码提取数据清单 │ ├── DO-NOT-USE-validate-consistency.js # [已弃用] 验证数据一致性 │ ├── DO-NOT-USE-validate-generation.js # [已弃用] 验证生成代码质量 │ └── DO-NOT-USE-check-duplicates.js # [已弃用] 检查重复的目标键 ├── data/ │ ├── classification.json # 分类映射(自动生成,人工维护) │ ├── inventory.json # 数据清单(脚本生成) │ └── target-key-definitions.json # 复杂映射的 target key 定义(人工维护) ├── package.json └── README.md # 本文档 ``` ## 快速开始 ```bash # 进入工具目录 cd v2-refactor-temp/tools/data-classify # 安装依赖 npm install # 生成所有代码(当前唯一仍受支持的流程) npm run generate # 或仅生成单一目标 npm run generate:preferences # 仅生成 preferenceSchemas.ts npm run generate:boot-config # 仅生成 bootConfigSchemas.ts npm run generate:migration # 仅生成 PreferencesMappings.ts + BootConfigMappings.ts ``` > `extract` / `validate` / `validate:gen` / `check:duplicates` / `all` 已弃用,不再支持,详见顶部说明。 ## 可用脚本 | 脚本 | 说明 | 状态 | | ------------------------------ | ------------------------------------------------ | ----------- | | `npm run generate` | 运行所有代码生成器 | ✅ 可用 | | `npm run generate:preferences` | 仅生成 preferenceSchemas.ts | ✅ 可用 | | `npm run generate:boot-config` | 仅生成 bootConfigSchemas.ts | ✅ 可用 | | `npm run generate:migration` | 仅生成 PreferencesMappings.ts + BootConfigMappings.ts | ✅ 可用 | | `npm run extract` | 从源文件提取数据清单 | ⛔ 已弃用 | | `npm run validate` | 验证数据一致性 | ⛔ 已弃用 | | `npm run validate:gen` | 验证生成代码质量 | ⛔ 已弃用 | | `npm run check:duplicates` | 检查重复的目标键 | ⛔ 已弃用 | | `npm run all` | 运行完整工作流 | ⛔ 已弃用 | > ⛔ 标记的命令已完成阶段性使命,**不再支持**,运行只会打印提示。详见顶部说明。 ## 脚本架构 > 注:下图与下表为原始完整工作流的历史记录;其中 `extract-inventory` / `validate-consistency` / `validate-generation` / `check-duplicates` 相关脚本已弃用(文件名已加 `DO-NOT-USE-` 前缀),仅 `generate-*` 仍在使用。 ### 依赖关系图 ``` ┌─────────────────────────────────────────────────────────────┐ │ 共享模块 │ │ scripts/lib/classificationUtils.js │ │ - loadClassification() - traverseClassifications() │ │ - saveClassification() - calculateStats() │ │ - loadInventory() - normalizeType() │ │ - extractPreferencesData() - inferTypeFromValue() │ └─────────────────────────────────────────────────────────────┘ ▲ ▲ │ │ ┌───────────┘ └───────────┐ │ │ ┌───────┴───────┐ ┌────────┴────────┐ │ extract- │ │ validate- │ │ inventory.js │ │ consistency.js │ │ │ │ │ │ 扫描源码 │ │ 检查数据 │ │ 构建清单 │ │ 一致性 │ └───────────────┘ └─────────────────┘ ┌─────────────────────┐ │ generate-all.js │─────────────────────┬──────────────────────┐ │ │ │ │ │ 编排所有生成器 │ │ │ └─────────────────────┘ │ │ │ │ │ │ require() │ require() │ require() ▼ ▼ ▼ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │ generate- │ │ generate- │ │ generate- │ │ preferences.js │ │ boot-config.js │ │ migration.js │ │ │ │ │ │ │ │ 生成 │ │ 生成 │ │ 生成 │ │ preferenceSchemas.ts│ │ bootConfigSchemas.ts│ │ PreferencesMappings │ └─────────────────────┘ └─────────────────────┘ │ BootConfigMappings │ └─────────────────────┘ ┌─────────────────────┐ ┌─────────────────────┐ │ validate- │ │ check- │ │ generation.js │ │ duplicates.js │ │ │ │ │ │ 验证生成代码质量 │ │ 检查重复目标键 │ │ (独立运行) │ │ (独立运行) │ └─────────────────────┘ └─────────────────────┘ ``` ### 脚本详情 | 脚本 | 输入 | 输出 | 依赖 | | ------------------------- | --------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------ | | `generate-preferences.js` | `classification.json` | `preferenceSchemas.ts` | 无 | | `generate-boot-config.js` | `classification.json` | `bootConfigSchemas.ts` | 无 | | `generate-migration.js` | `classification.json` | `PreferencesMappings.ts`, `BootConfigMappings.ts` | 无 | | `generate-all.js` | - | 运行三个生成器 | `generate-preferences.js`, `generate-boot-config.js`, `generate-migration.js` | | `DO-NOT-USE-extract-inventory.js` _(已弃用)_ | 源代码文件 | `data/inventory.json` | `classificationUtils.js` | | `DO-NOT-USE-validate-consistency.js` _(已弃用)_ | `inventory.json`, `classification.json` | `validation-report.md` | `classificationUtils.js` | | `DO-NOT-USE-validate-generation.js` _(已弃用)_ | 生成的 `.ts` 文件 | 控制台输出 | 无 | | `DO-NOT-USE-check-duplicates.js` _(已弃用)_ | `classification.json` | 控制台输出 | 无 | ## 数据分类工作流 > ⚠️ 本节为历史记录:步骤 1(提取)与步骤 4(验证)所用命令已弃用、不再支持,当前仅步骤 3(生成)仍受支持。 ### 1. 提取数据清单 ```bash npm run extract ``` 扫描源文件并提取以下数据源的信息: - **Redux Store**: `src/renderer/store/*.ts` - **Electron Store**: `src/main/services/ConfigManager.ts` - **LocalStorage**: 所有使用 localStorage 的文件 - **Dexie 数据库**: `src/renderer/databases/index.ts` > **注意**: `dexieSettings` 数据源中的字符串字面量 key 会被自动提取,但动态 key(如模板字符串拼接的)需要手动维护。详见下方 [dexieSettings 数据源](#dexiesettings-数据源) 章节。 ### 2. 分类数据 编辑 `data/classification.json` 对每个数据项进行分类: ```json { "originalKey": "theme", "type": "string", "status": "classified", "category": "preferences", "targetKey": "ui.theme_mode" } ``` ### 3. 生成代码 ```bash npm run generate ``` 生成以下 TypeScript 文件: - `src/shared/data/preference/preferenceSchemas.ts` - 偏好配置类型定义与默认值 - `src/shared/data/bootConfig/bootConfigSchemas.ts` - 启动配置类型定义与默认值 - `src/main/data/migration/v2/migrators/mappings/PreferencesMappings.ts` - 偏好迁移映射 - `src/main/data/migration/v2/migrators/mappings/BootConfigMappings.ts` - 启动配置迁移映射 ### 4. 验证 ```bash npm run validate npm run validate:gen ``` 验证内容: - 所有清单项都已分类 - 没有孤立的分类条目 - 命名规范一致 - 没有重复的目标键 - 生成代码结构正确 --- ## 数据分类标准 根据 Cherry Studio 数据重构架构,所有数据需要分类到以下 6 个类别之一: ### 1. 偏好配置 (preferences) **判断标准**: - ✅ 影响应用全局行为的配置 - ✅ 用户可以修改的设置项 - ✅ 简单的数据类型(boolean/string/number/简单 array/object) - ✅ 结构相对稳定,不经常变化 - ✅ 数据量小,可以重建 - ✅ 需要在窗口间同步 **典型例子**: - `showAssistants`: 是否显示助手面板 - `theme`: 主题设置(light/dark/system) - `fontSize`: 字体大小 - `language`: 界面语言 **命名规范**: - 使用点分隔的层级结构:`ui.fontSize`、`system.language` - 分组前缀:`ui.*`(界面)、`system.*`(系统)、`app.*`(应用行为)等 ### 2. 启动配置 (bootConfig) **判断标准**: - ✅ 必须在 Node.js 进程启动的最早阶段同步加载(早于 `app.whenReady`、早于 lifecycle 的 `BeforeReady` 阶段) - ✅ 影响进程级别的行为,一旦进程启动就无法更改 - ✅ 不能存储在 SQLite 中(数据库由 lifecycle `BeforeReady` 阶段初始化,远晚于 boot config 的加载时机) - ✅ 使用同步文件 I/O 读取(`~/.cherrystudio/boot-config.json`,刻意放在 userData 之外,避免鸡生蛋问题) **时序关系**: ``` Boot Config 加载 → bootstrap(初始化 appData 目录)→ app.whenReady → lifecycle BeforeReady(DB 初始化)→ lifecycle WhenReady ``` Boot config 在整个启动链的最前端,为后续所有阶段提供基础配置。 **典型例子**: - `disableHardwareAcceleration`: 硬件加速开关(必须在任何 Electron API 调用前设置) - 应用路径定义等需要在 bootstrap 阶段就确定的配置 **与 preferences 的区别**: | | bootConfig | preferences | | --- | --- | --- | | 加载时机 | 进程启动最早阶段(同步) | lifecycle `BeforeReady` 阶段(异步) | | 存储方式 | JSON 文件(`~/.cherrystudio/boot-config.json`) | SQLite 数据库 | | 访问方式(Main) | `bootConfigService.get()` 同步 | `application.get('PreferenceService').get()` | | 访问方式(Renderer) | `usePreference('BootConfig.*')` 统一访问 | `usePreference('key')` | ### 3. 用户数据 (user_data) **判断标准**: - ✅ 用户创建或输入的内容 - ✅ 不可丢失的重要数据 - ✅ 数据量可能很大 - ✅ 需要完整备份和迁移机制 - ✅ 可能包含敏感信息 **典型例子**: - `topics`: 对话历史 - `messages`: 消息内容 - `files`: 用户上传的文件 - `knowledge_notes`: 知识库笔记 **特殊处理**: - 敏感数据需要加密存储 - 大数据表需要考虑分页和流式处理 ### 4. 缓存数据 (cache) **判断标准**: - ✅ 可以重新生成的数据 - ✅ 主要用于性能优化 - ✅ 丢失后不影响核心功能 - ✅ 有过期时间或清理机制 **典型例子**: - `failed_favicon_*`: 失败的 favicon 缓存 - 搜索结果缓存 - 图片预览缓存 - 模型响应缓存 ### 5. 运行时数据 (runtime) **判断标准**: - ✅ 内存型数据,不需要持久化 - ✅ 生命周期 ≤ 应用进程 - ✅ 应用重启后可以丢失 - ✅ 临时状态信息 **典型例子**: - 当前选中的对话 - 临时的输入状态 - UI 组件的展开/折叠状态 - 网络请求状态 ### 6. 应用资源 (resources) **判断标准**: - ✅ 静态资源文件 - ✅ 随应用分发的内容 - ✅ 不需要用户修改 - ✅ 暂不考虑重构 **典型例子**: - 图标文件 - 本地化翻译文件 - 默认配置文件 - 帮助文档 --- ## 分类决策流程图 ``` 数据项 ↓ 是否必须在进程启动最早阶段同步加载(早于 lifecycle)? ↓ 是 ↓ 否 启动配置 是否用户创建/输入的内容? (bootConfig) ↓ 是 ↓ 否 用户数据 是否需要持久化? ↓ 否 ↓ 是 运行时数据 是否可重新生成? ↓ 是 ↓ 否 缓存数据 是否用户可修改? ↓ 是 ↓ 否 偏好配置 应用资源 ``` --- ## 分类示例 ### 示例 1: Redux settings.showAssistants ```json { "classifications": { "redux": { "settings": [ { "originalKey": "showAssistants", "type": "boolean", "defaultValue": true, "status": "classified", "category": "preferences", "targetKey": "ui.show_assistants" } ] } } } ``` **分析过程**: 1. 数据用途:控制是否显示助手面板 2. 用户可修改:✅ 3. 影响全局:✅ 4. 数据简单:✅ boolean 类型 5. 结论:偏好配置 ### 示例 2: 嵌套结构 (Redux settings with children) ```json { "originalKey": "codeEditor", "type": "object", "children": [ { "originalKey": "enabled", "type": "boolean", "defaultValue": true, "status": "classified", "category": "preferences", "targetKey": "code_editor.enabled" }, { "originalKey": "fontSize", "type": "number", "defaultValue": 14, "status": "classified", "category": "preferences", "targetKey": "code_editor.font_size" } ] } ``` **注意**: 父级项不需要 `status`/`category`/`targetKey`,这些只在叶子节点设置。 ### 示例 3: Dexie topics 表 ```json { "originalKey": "topics", "type": "table", "status": "classified", "category": "user_data", "targetTable": "topic", "notes": "用户对话历史,核心业务数据" } ``` --- ## 命名规范 偏好配置键必须遵循:`namespace.sub.key_name` **规则**: - 至少 2 个由点分隔的段 - 仅使用小写字母、数字、下划线 - 模式:`/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/` **示例**: - `app.theme` (有效) - `chat.input.send_shortcut` (有效) - `Theme` (无效 - 没有点分隔符) - `App.User` (无效 - 大写字母) --- ## 增量更新策略 > ⚠️ 本节描述的提取(`npm run extract`)流程已弃用、不再支持,仅作历史记录。 ### 核心特性 - **保留已分类数据**: 重新运行提取不会丢失已有分类 - **标记删除项**: 删除的数据项被标记但不移除 - **自动发现新项**: 新数据项自动添加到待处理列表 - **自动备份**: 每次运行前自动备份原分类文件 ### 更新流程 1. 代码变更后运行 `npm run extract` 2. 脚本自动备份 `classification.json` 到 `classification.backup.json` 3. 脚本识别新增和删除的数据项 4. 新项添加到 `pending` 数组 5. 删除项标记为 `status: 'classified-deleted'` 6. 手动处理新的待处理项 --- ## 文件格式说明 ### inventory.json 结构 ```json { "metadata": { "generatedAt": "ISO 日期", "version": "版本号" }, "redux": { "moduleName": { "fieldName": { "type": "数据类型", "defaultValue": "默认值" } } }, "electronStore": { ... }, "localStorage": { ... }, "dexie": { ... } } ``` ### classification.json 结构 ```json { "metadata": { "version": "版本号", "lastUpdated": "ISO 日期" }, "classifications": { "redux": { "moduleName": [ { "originalKey": "字段名", "type": "数据类型", "status": "classified|pending|classified-deleted", "category": "preferences|bootConfig|user_data|cache|runtime|resources", "targetKey": "target.key.name" } ] }, "electronStore": { ... }, "localStorage": { ... }, "dexieSettings": { "settings": [ { "originalKey": "字段名", "type": "数据类型", "status": "classified|pending", "category": "preferences", "targetKey": "target.key.name" } ] }, "dexie": { ... } } } ``` ### dexieSettings 数据源 `dexieSettings` 是 classification.json 中与 `redux`、`electronStore`、`localStorage`、`dexie` 并列的第五个顶级数据源,专门用于分类 Dexie IndexedDB 中 `settings` 表的 KV 配置项。 **与 `dexie` 数据源的区别**: | 数据源 | 用途 | 数据结构 | 典型分类 | | --- | --- | --- | --- | | `dexie` | Dexie 的业务数据表(files, topics 等) | 表级别,使用 `targetTable` | `user_data` | | `dexieSettings` | Dexie 的 `settings` 表(KV 配置) | 字段级别,使用 `targetKey` | `preferences`(目前仅支持此分类) | **classification.json 中的结构**: ```json { "classifications": { "dexieSettings": { "settings": [ { "originalKey": "settingKeyName", "type": "string", "defaultValue": "defaultValue", "status": "classified", "category": "preferences", "targetKey": "namespace.key_name" } ] } } } ``` **在代码生成中的作用**: 1. **`generate-preferences.js`**: 作为四大偏好数据源之一(`electronStore`、`redux`、`localStorage`、`dexieSettings`),参与生成 `preferenceSchemas.ts` 2. **`generate-migration.js`**: 生成独立的 `DEXIE_SETTINGS_MAPPINGS` 映射数组,用于迁移器从 Dexie settings 表读取数据 **去重优先级**(当多个数据源映射到相同 targetKey 时): ``` redux (最高) > dexieSettings > localStorage > electronStore (最低) ``` **已知字段清单**(参考 [PR #10162 comment](https://github.com/CherryHQ/cherry-studio/pull/10162#issuecomment-4010796619)): Dexie `settings` 表是一个通用 KV 存储(`{ id: string, value: any }`),所有 `image://` 键由 `ImageStorage` 服务管理。 *固定键*: | Key | Value Type | 迁移目标 | | --- | --- | --- | | `translate:model` | `string` (model id) | preference | | `translate:target:language` | `string` (langCode) | preference | | `translate:source:language` | `string` (langCode) | preference | | `translate:bidirectional:enabled` | `boolean` | preference | | `translate:bidirectional:pair` | `[string, string]` (langCode pair) | preference | | `translate:scroll:sync` | `boolean` | preference | | `translate:markdown:enabled` | `boolean` | preference | | `translate:detect:method` | `string` ('franc'/'llm'/'auto') | preference | | `pinned:models` | `Model[]` | preference | | `image://avatar` | `string` (base64 data URL \| emoji) | preference / file manager | *动态键(基于 pattern)*: | Key Pattern | Value Type | 迁移目标 | | --- | --- | --- | | `image://provider-${providerId}` | `string` (base64 data URL \| emoji \| `''`) | file manager | | `mcp:provider:${provider.key}:servers` | `MCPServer[]` | new table | *已知遗留键(代码中无引用,运行时 IndexedDB 中存在)*: | Key | 说明 | | --- | --- | | `translate:model:prompt` | 已被 Redux `settings.translateModelPrompt` 取代,已迁移到 preference `feature.translate.model_prompt`,跳过 | **注意事项**: - `extract-inventory.js` 会自动提取 `db.settings.get/put/add()` 调用中的**字符串字面量** key;动态 key(模板字符串拼接)无法自动提取,需要**手动添加** - 手动添加的条目在重新提取时会被保留(不会被覆盖或删除) - `dexieSettings` 的 `category` 目前仅支持 `preferences`,代码生成脚本只处理该分类 - `validate-consistency.js` 不会检查 `dexieSettings` 与 inventory 的一致性 - 迁移时通过 `ctx.sources.dexieSettings.get(mapping.originalKey)` 读取数据 - 动态键(含 `${}` 模板的 pattern)需要特殊的迁移逻辑,不能用简单 1:1 映射处理 ### 状态值说明 | Status | 说明 | 操作建议 | | -------------------- | ---------------- | ---------------------------------------- | | `pending` | 待分类 | 需要人工分析并设置 category 和 targetKey | | `classified` | 已分类 | 分类完成,可用于代码生成 | | `classified-deleted` | 已分类但源已删除 | 源代码中已不存在,保留历史记录 | ### targetKey 值说明 对于 `status: "classified"` 的项,`targetKey` 有两种情况: | targetKey | 说明 | 生成行为 | | --------- | ---- | -------- | | 有效值(如 `"ui.theme"`) | 需要迁移到新系统 | 会生成到 preferenceSchemas.ts | | `null` | 已分类,但不需要迁移 | 不会生成到 preferenceSchemas.ts | **使用场景**:当一个数据项经过分析后,确定在新系统中不需要该配置(如已废弃、被其他配置替代、或不再需要持久化),应设置 `status: "classified"` 且 `targetKey: null`。这表示"已完成分类决策,决策结果是不加载该项"。 --- ## 复杂映射支持 ### 概述 除了简单的一对一映射(`originalKey → targetKey`),系统还支持复杂的数据转换: 1. **对象拆分 (1→N)**: 一个源对象拆分为多个 target keys 2. **多源合并 (N→1)**: 多个源数据合并为一个或多个目标 3. **值计算/转换**: 值需要经过计算、格式转换或逻辑处理 4. **条件映射**: 根据源数据的值决定写入哪些目标 ### 架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ classification.json (status: classified) │ │ ───────────────────────────────────────── │ │ 基础数据源,包含所有简单映射的 target keys │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ target-key-definitions.json │ │ ───────────────────────────────────────── │ │ 用途1: 复杂迁移 - 定义需要特殊转换逻辑的 target keys │ │ 用途2: 纯新增 - 添加 v2 新功能的 preferences(非迁移) │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ preferenceSchemas.ts (最终输出) │ └─────────────────────────────────────────────────────────────┘ ``` ### target-key-definitions.json 用于定义无法通过 `classification.json` 简单映射处理的 preference keys。主要用于两个场景: 1. **复杂迁移**: 定义需要特殊转换逻辑(对象拆分、多源合并、值计算等)产生的 target keys 2. **纯新增(非迁移)**: 添加 v2 新功能的 preferences,这些配置不是从旧代码迁移的 **文件结构**: ```json { "metadata": { "version": "1.0.0", "description": "Target key definitions...", "lastUpdated": "2025-01-18" }, "definitions": [ { "targetKey": "app.window.position.x", "type": "number", "defaultValue": 0, "status": "classified", "description": "Window X position (from complex mapping)" } ] } ``` **字段说明**: | 字段 | 必填 | 说明 | | -------------- | ---- | -------------------------------------------------------- | | `targetKey` | ✓ | preference key(必须符合命名规范) | | `type` | ✓ | TypeScript 类型(string, number, boolean, 或自定义类型) | | `defaultValue` | ✓ | 默认值(支持 `VALUE: ...` 特殊格式) | | `status` | ✓ | `classified` 启用,`pending` 禁用 | | `description` | | 可选描述 | #### 纯新增(非迁移)场景 当需要添加一个全新的 preference(不是从旧代码迁移的 v2 新功能)时,直接在 `definitions` 数组中添加即可。 **示例**: 添加 v2 版本新增的功能配置 ```json { "definitions": [ { "targetKey": "feature.new_assistant.enabled", "type": "boolean", "defaultValue": false, "status": "classified", "description": "启用新助手功能(v2 新增,非迁移)" }, { "targetKey": "feature.new_assistant.default_model", "type": "string", "defaultValue": "gpt-4", "status": "classified", "description": "新助手默认模型(v2 新增,非迁移)" } ] } ``` 运行 `npm run generate:preferences` 后,这些 keys 会出现在生成的 `preferenceSchemas.ts` 中。 **与复杂迁移的区别**: - 复杂迁移需要在 `PreferenceTransformers.ts` 和 `ComplexPreferenceMappings.ts` 中实现转换逻辑 - 纯新增只需要在 `target-key-definitions.json` 中定义,无需额外代码 **建议**: 在 `description` 中注明是"复杂迁移"还是"v2 新增,非迁移",便于后续维护。 **defaultValue 特殊格式**: 与 classification.json 保持一致,支持 `VALUE: ...` 特殊格式: ```json // 引用枚举值 { "defaultValue": "VALUE: PreferenceTypes.ThemeMode.system" } // 生成: PreferenceTypes.ThemeMode.system(不加引号) // 引用常量 { "defaultValue": "VALUE: TRANSLATE_PROMPT" } // 生成: TRANSLATE_PROMPT(不加引号) // 特殊 null 值 { "defaultValue": "VALUE: null" } // 生成: null // 普通字符串(不使用 VALUE: 前缀) { "defaultValue": "light" } // 生成: 'light'(带引号) ``` ### 复杂映射实现 复杂映射的转换逻辑定义在以下文件中: ``` src/main/data/migration/v2/migrators/ ├── mappings/ │ ├── PreferencesMappings.ts # 偏好简单映射(自动生成) │ ├── BootConfigMappings.ts # 启动配置映射(自动生成) │ └── ComplexPreferenceMappings.ts # 复杂映射配置 ├── transformers/ │ └── PreferenceTransformers.ts # 转换函数实现 ├── PreferencesMigrator.ts # 偏好迁移执行器 └── BootConfigMigrator.ts # 启动配置迁移执行器 ``` **添加复杂映射的步骤**: 1. 在 `target-key-definitions.json` 中定义 target keys(设 `status: "classified"`) 2. 在 `PreferenceTransformers.ts` 中实现转换函数 3. 在 `ComplexPreferenceMappings.ts` 中添加映射配置 4. 运行 `npm run generate:preferences` 重新生成 preferenceSchemas.ts ### 冲突处理 系统采用**严格模式**:如果简单映射和复杂映射的 target key 有冲突,迁移时会报错。 解决方法:从简单映射(classification.json)中移除冲突的 key,由复杂映射处理。 --- ## 故障排除 ### "Module not found" 错误 ```bash cd v2-refactor-temp/tools/data-classify npm install ``` ### 验证错误 1. 检查 `validation-report.md` 了解详情 2. 修复 `classification.json` 条目 3. 重新运行验证 ### 生成代码问题 1. ~~运行 `npm run validate:gen` 识别问题~~(已弃用,不再支持) 2. 检查源分类数据 3. 使用 `npm run generate` 重新生成 ### 数据项被错误标记为删除 检查提取脚本的模式是否正确匹配代码结构。 ### 如何恢复意外删除的分类 从以下位置恢复 `classification.json`: - 自动备份文件:`classification.backup.json` - Git 历史记录