Sfoglia il codice sorgente

refactor(config): 重构配置存储为增量覆盖模式

- 新增 stripDefaults 函数,移除与默认值相同的配置项
- 新增 readOverrides 和 writeOverrides 函数封装覆盖项读写
- 新增 sameValue 和 overridesEqual 辅助函数用于值比较
- 删除 loadConfigFile 函数,统一使用 readOverrides 读取
- readConfigFile 改为基于默认值与覆盖项合并生成完整配置
- updateConfigFile 改为只写入与默认值不同的项,避免冗余存储
- migrateLegacySmartShooter 改为操作覆盖项而非完整配置对象
panqiuyao 2 giorni fa
parent
commit
237d773d65
1 ha cambiato i file con 67 aggiunte e 47 eliminazioni
  1. 67 47
      electron/utils/config.js

+ 67 - 47
electron/utils/config.js

@@ -14,72 +14,92 @@ const LEGACY_SMARTSHOOTER5 = {
   controlPath: "C:\\Program Files\\Smart Shooter 5",
   controlPath: "C:\\Program Files\\Smart Shooter 5",
 }
 }
 
 
-function migrateLegacySmartShooter(config) {
-  if (!config || config.smartShooter6Migrated) return { config, changed: false }
-  const stillFactoryDefault = config.controlType === LEGACY_SMARTSHOOTER5.controlType
-    && config.controlPath === LEGACY_SMARTSHOOTER5.controlPath
-  config.smartShooter6Migrated = true
-  if (!stillFactoryDefault) return { config, changed: true }
-  config.controlType = defaultConfig.controlType
-  config.controlPath = defaultConfig.controlPath
-  config.SmartShooterPath = config.SmartShooterPath || LEGACY_SMARTSHOOTER5.controlPath
-  config.SmartShooter6Path = defaultConfig.SmartShooter6Path
-  return { config, changed: true }
+function sameValue(a, b) {
+  return JSON.stringify(a) === JSON.stringify(b)
+}
+
+// 用户目录只保留和 utils 默认值不同的项
+function stripDefaults(overrides) {
+  const next = { ...overrides }
+  for (const key of Object.keys(next)) {
+    if (Object.prototype.hasOwnProperty.call(defaultConfig, key) && sameValue(next[key], defaultConfig[key])) {
+      delete next[key]
+    }
+  }
+  return next
+}
+
+function overridesEqual(a, b) {
+  const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})])
+  for (const key of keys) {
+    if (!sameValue(a[key], b[key])) return false
+  }
+  return true
+}
+
+function readOverrides() {
+  if (!fs.existsSync(configPath)) return {}
+  const data = fs.readFileSync(configPath, 'utf8');
+  const parsed = JSON.parse(data);
+  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}
+  return parsed
+}
+
+function writeOverrides(overrides) {
+  fs.writeFileSync(configPath, JSON.stringify(overrides, null, 2), 'utf8');
+}
+
+function migrateLegacySmartShooter(overrides) {
+  if (!overrides || overrides.smartShooter6Migrated) return { overrides, changed: false }
+  const merged = { ...defaultConfig, ...overrides }
+  const stillFactoryDefault = merged.controlType === LEGACY_SMARTSHOOTER5.controlType
+    && merged.controlPath === LEGACY_SMARTSHOOTER5.controlPath
+  const next = { ...overrides, smartShooter6Migrated: true }
+  if (!stillFactoryDefault) return { overrides: next, changed: true }
+  next.controlType = defaultConfig.controlType
+  next.controlPath = defaultConfig.controlPath
+  next.SmartShooterPath = overrides.SmartShooterPath || LEGACY_SMARTSHOOTER5.controlPath
+  next.SmartShooter6Path = defaultConfig.SmartShooter6Path
+  return { overrides: next, changed: true }
 }
 }
 
 
 /**
 /**
- * 读取配置文件
+ * 读取配置:utils 里的默认值打底,用户目录里只覆盖改过的项
  */
  */
 function readConfigFile() {
 function readConfigFile() {
 
 
   try {
   try {
-    if (fs.existsSync(configPath)) {
-      const data = fs.readFileSync(configPath, 'utf8');
-      const parsed = JSON.parse(data);
-      const { config: merged, changed } = migrateLegacySmartShooter({
-        ...defaultConfig,
-        ...parsed,
-      });
-      if (changed) {
-        fs.writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf8');
-      }
-
-      return merged;
-    } else {
-      console.log('配置文件不存在');
-      // 创建空白JSON文件
-      fs.writeFileSync(configPath, '{}', 'utf8');
-      return {
-        ...defaultConfig,
-      };
+    const overrides = readOverrides()
+    const { overrides: migrated, changed } = migrateLegacySmartShooter(overrides)
+    const stored = stripDefaults(migrated)
+    if (changed || !overridesEqual(overrides, stored)) {
+      writeOverrides(stored)
     }
     }
+
+    return {
+      ...defaultConfig,
+      ...stored,
+    };
   } catch (error) {
   } catch (error) {
     console.error('读取配置文件出错:', error);
     console.error('读取配置文件出错:', error);
     return null;
     return null;
   }
   }
 }
 }
 
 
-function loadConfigFile() {
-  if (!fs.existsSync(configPath)) {
-    return { ...defaultConfig }
-  }
-  const data = fs.readFileSync(configPath, 'utf8');
-  return {
-    ...defaultConfig,
-    ...JSON.parse(data),
-  }
-}
-
 /**
 /**
- * 一次写入多项配置,避免 controlType 和安装目录被分成几次写入后互相覆盖
+ * 一次写入多项调整。和默认值相同的项不写进用户目录
  */
  */
 function updateConfigFile(partial) {
 function updateConfigFile(partial) {
   try {
   try {
-    const config = {
-      ...loadConfigFile(),
-      ...partial,
+    const next = { ...readOverrides() }
+    for (const [key, value] of Object.entries(partial)) {
+      if (Object.prototype.hasOwnProperty.call(defaultConfig, key) && sameValue(value, defaultConfig[key])) {
+        delete next[key]
+      } else {
+        next[key] = value
+      }
     }
     }
-    fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
+    writeOverrides(stripDefaults(next))
     console.log(`成功写入配置项: ${Object.keys(partial).join(', ')}`);
     console.log(`成功写入配置项: ${Object.keys(partial).join(', ')}`);
   } catch (error) {
   } catch (error) {
     console.error('写入配置文件出错:', error);
     console.error('写入配置文件出错:', error);