From 078a3a6a53aba8e922e3ce3da23b9f8adbac3b88 Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Sun, 25 Jan 2026 03:46:22 +0800 Subject: [PATCH] feat(backend): add CommonConfigEnabledByApp to ProviderMeta - Add CommonConfigEnabledByApp struct for per-app tracking - Add common_config_enabled and common_config_enabled_by_app to ProviderMeta - Add is_empty() method to CommonConfigSnippets - Skip serializing empty common_config_snippets in config.json --- src-tauri/src/app_config.rs | 18 +++++++++++++++++- src-tauri/src/provider.rs | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index 9b4a7b0e9..e53dfe397 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -320,6 +320,20 @@ pub struct CommonConfigSnippets { } impl CommonConfigSnippets { + /// 检查是否所有字段都为空 + pub fn is_empty(&self) -> bool { + let is_blank = |value: &Option| { + value + .as_ref() + .map(|snippet| snippet.trim().is_empty()) + .unwrap_or(true) + }; + is_blank(&self.claude) + && is_blank(&self.codex) + && is_blank(&self.gemini) + && is_blank(&self.opencode) + } + /// 获取指定应用的通用配置片段 pub fn get(&self, app: &AppType) -> Option<&String> { match app { @@ -359,7 +373,9 @@ pub struct MultiAppConfig { #[serde(default)] pub skills: SkillStore, /// 通用配置片段(按应用分治) - #[serde(default)] + /// 注意:此字段主要用于从旧版 config.json 迁移数据到数据库 + /// 迁移成功后会被清空,空时不写入 config.json + #[serde(default, skip_serializing_if = "CommonConfigSnippets::is_empty")] pub common_config_snippets: CommonConfigSnippets, /// Claude 通用配置片段(旧字段,用于向后兼容迁移) #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/src-tauri/src/provider.rs b/src-tauri/src/provider.rs index d13020737..bb0e7ff0e 100644 --- a/src-tauri/src/provider.rs +++ b/src-tauri/src/provider.rs @@ -191,6 +191,17 @@ pub struct ProviderProxyConfig { pub proxy_password: Option, } +/// 通用配置启用状态(按应用) +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct CommonConfigEnabledByApp { + #[serde(skip_serializing_if = "Option::is_none")] + pub claude: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub codex: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub gemini: Option, +} + /// 供应商元数据 #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ProviderMeta { @@ -227,6 +238,18 @@ pub struct ProviderMeta { /// 供应商单独的代理配置 #[serde(rename = "proxyConfig", skip_serializing_if = "Option::is_none")] pub proxy_config: Option, + /// 是否启用通用配置片段(用于跨供应商保持勾选状态) + #[serde( + rename = "commonConfigEnabled", + skip_serializing_if = "Option::is_none" + )] + pub common_config_enabled: Option, + /// 按应用记录通用配置启用状态(优先于 commonConfigEnabled) + #[serde( + rename = "commonConfigEnabledByApp", + skip_serializing_if = "Option::is_none" + )] + pub common_config_enabled_by_app: Option, } impl ProviderManager {