diff --git a/src-tauri/src/commands/proxy.rs b/src-tauri/src/commands/proxy.rs index b10ce6b2e..05a7b18e0 100644 --- a/src-tauri/src/commands/proxy.rs +++ b/src-tauri/src/commands/proxy.rs @@ -11,7 +11,7 @@ use crate::store::AppState; pub async fn start_proxy_server( state: tauri::State<'_, AppState>, ) -> Result { - state.proxy_service.start(true).await + state.proxy_service.start().await } /// 启动代理服务器(带 Live 配置接管) diff --git a/src-tauri/src/database/dao/proxy.rs b/src-tauri/src/database/dao/proxy.rs index ef3dc36f9..53bffeeeb 100644 --- a/src-tauri/src/database/dao/proxy.rs +++ b/src-tauri/src/database/dao/proxy.rs @@ -16,19 +16,18 @@ impl Database { let result = { let conn = lock_conn!(self.conn); conn.query_row( - "SELECT enabled, listen_address, listen_port, max_retries, + "SELECT listen_address, listen_port, max_retries, request_timeout, enable_logging, live_takeover_active FROM proxy_config WHERE id = 1", [], |row| { Ok(ProxyConfig { - enabled: row.get::<_, i32>(0)? != 0, - listen_address: row.get(1)?, - listen_port: row.get::<_, i32>(2)? as u16, - max_retries: row.get::<_, i32>(3)? as u8, - request_timeout: row.get::<_, i32>(4)? as u64, - enable_logging: row.get::<_, i32>(5)? != 0, - live_takeover_active: row.get::<_, i32>(6).unwrap_or(0) != 0, + listen_address: row.get(0)?, + listen_port: row.get::<_, i32>(1)? as u16, + max_retries: row.get::<_, i32>(2)? as u8, + request_timeout: row.get::<_, i32>(3)? as u64, + enable_logging: row.get::<_, i32>(4)? != 0, + live_takeover_active: row.get::<_, i32>(5).unwrap_or(0) != 0, }) }, ) @@ -57,7 +56,7 @@ impl Database { COALESCE((SELECT created_at FROM proxy_config WHERE id = 1), datetime('now')), datetime('now'))", rusqlite::params![ - if config.enabled { 1 } else { 0 }, + 0, // 已移除自动启用逻辑,保留列但固定为 0 config.listen_address, config.listen_port as i32, config.max_retries as i32, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b393e4461..7c6a3d723 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -524,12 +524,12 @@ pub fn run() { } } - // 异常退出恢复 + 自动启动代理服务器 + // 异常退出恢复 let app_handle = app.handle().clone(); tauri::async_runtime::spawn(async move { let state = app_handle.state::(); - // 检查是否有 Live 备份(表示上次有接管状态) + // 检查是否有 Live 备份(表示上次异常退出时可能处于接管状态) let has_backups = match state.db.has_any_live_backup().await { Ok(v) => v, Err(e) => { @@ -537,55 +537,15 @@ pub fn run() { false } }; + // 检查 Live 配置是否仍处于被接管状态(包含占位符) + let live_taken_over = state.proxy_service.detect_takeover_in_live_configs(); - // 获取代理配置 - let proxy_config = match state.db.get_proxy_config().await { - Ok(config) => Some(config), - Err(e) => { - log::error!("启动时获取代理配置失败: {e}"); - None - } - }; - - if has_backups { - // 有备份说明上次退出时有接管状态 - // 检查 Live 配置是否仍处于被接管状态(包含占位符) - let live_taken_over = state.proxy_service.detect_takeover_in_live_configs(); - - if live_taken_over { - // Live 配置仍是接管状态,尝试重新启动代理服务以恢复接管 - log::info!("检测到上次接管状态,正在重新启动代理服务..."); - match state.proxy_service.start(false).await { - Ok(info) => { - log::info!("代理服务器已恢复启动: {}:{}", info.address, info.port); - } - Err(e) => { - // 启动失败,恢复 Live 配置 - log::error!("恢复代理服务失败: {e},正在恢复 Live 配置..."); - if let Err(e) = state.proxy_service.recover_from_crash().await { - log::error!("恢复 Live 配置失败: {e}"); - } else { - log::info!("Live 配置已恢复"); - } - } - } + if has_backups || live_taken_over { + log::warn!("检测到上次异常退出(存在接管残留),正在恢复 Live 配置..."); + if let Err(e) = state.proxy_service.recover_from_crash().await { + log::error!("恢复 Live 配置失败: {e}"); } else { - // Live 配置已经是正常状态,清理残留备份 - log::info!("Live 配置已是正常状态,清理残留备份..."); - if let Err(e) = state.db.delete_all_live_backups().await { - log::warn!("清理残留 Live 备份失败: {e}"); - } - } - } else if let Some(config) = proxy_config { - // 没有备份,检查是否需要自动启动代理服务器(总开关) - if config.enabled { - log::info!("代理服务配置为启用,正在启动..."); - match state.proxy_service.start(true).await { - Ok(info) => { - log::info!("代理服务器自动启动成功: {}:{}", info.address, info.port) - } - Err(e) => log::error!("代理服务器自动启动失败: {e}"), - } + log::info!("Live 配置已恢复"); } } }); @@ -855,20 +815,26 @@ pub async fn cleanup_before_exit(app_handle: &tauri::AppHandle) { if proxy_service.is_running().await { log::info!("检测到代理服务器正在运行,开始清理..."); - // 检查是否处于 Live 接管模式 - if let Ok(is_takeover) = state.db.is_live_takeover_active().await { - if is_takeover { - // 接管模式:停止并恢复配置 - if let Err(e) = proxy_service.stop_with_restore().await { - log::error!("退出时恢复 Live 配置失败: {e}"); - } else { - log::info!("已恢复 Live 配置"); - } + // 检查是否存在 Live 备份(有则视为接管) + let has_backups = match state.db.has_any_live_backup().await { + Ok(v) => v, + Err(e) => { + log::error!("退出时检查 Live 备份失败: {e}"); + false + } + }; + + if has_backups { + // 接管模式:停止并恢复配置 + if let Err(e) = proxy_service.stop_with_restore().await { + log::error!("退出时恢复 Live 配置失败: {e}"); } else { - // 非接管模式:仅停止代理 - if let Err(e) = proxy_service.stop().await { - log::error!("退出时停止代理失败: {e}"); - } + log::info!("已恢复 Live 配置"); + } + } else { + // 非接管模式:仅停止代理 + if let Err(e) = proxy_service.stop().await { + log::error!("退出时停止代理失败: {e}"); } } diff --git a/src-tauri/src/proxy/types.rs b/src-tauri/src/proxy/types.rs index 0b1c73aa5..f00af8de5 100644 --- a/src-tauri/src/proxy/types.rs +++ b/src-tauri/src/proxy/types.rs @@ -3,8 +3,6 @@ use serde::{Deserialize, Serialize}; /// 代理服务器配置 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProxyConfig { - /// 是否启用代理服务 - pub enabled: bool, /// 监听地址 pub listen_address: String, /// 监听端口 @@ -23,7 +21,6 @@ pub struct ProxyConfig { impl Default for ProxyConfig { fn default() -> Self { Self { - enabled: false, listen_address: "127.0.0.1".to_string(), listen_port: 15721, // 使用较少占用的高位端口 max_retries: 3, diff --git a/src-tauri/src/services/proxy.rs b/src-tauri/src/services/proxy.rs index 8b867f7c8..a21fbeaf2 100644 --- a/src-tauri/src/services/proxy.rs +++ b/src-tauri/src/services/proxy.rs @@ -41,31 +41,16 @@ impl ProxyService { } /// 启动代理服务器 - /// - /// - `persist_enabled = true`:将 `proxy_config.enabled` 持久化为启用(用于“总开关”) - /// - `persist_enabled = false`:仅在当前进程启动代理服务(用于“按 App 接管”自动启动) - pub async fn start(&self, persist_enabled: bool) -> Result { + pub async fn start(&self) -> Result { // 1. 获取配置 - let mut config = self + let config = self .db .get_proxy_config() .await .map_err(|e| format!("获取代理配置失败: {e}"))?; - // 2. 仅在需要时持久化 enabled(避免“按 App 接管”自动启动时误打开总开关) - if persist_enabled { - config.enabled = true; - } - // 3. 若已在运行:确保持久化状态(如需要)并返回当前信息 if let Some(server) = self.server.read().await.as_ref() { - if persist_enabled { - self.db - .update_proxy_config(config) - .await - .map_err(|e| format!("保存代理配置失败: {e}"))?; - } - let status = server.get_status().await; return Ok(ProxyServerInfo { address: status.address, @@ -86,14 +71,6 @@ impl ProxyService { // 5. 保存服务器实例 *self.server.write().await = Some(server); - // 6. 持久化 enabled 状态(仅总开关) - if persist_enabled { - self.db - .update_proxy_config(config) - .await - .map_err(|e| format!("保存代理配置失败: {e}"))?; - } - log::info!("代理服务器已启动: {}:{}", info.address, info.port); Ok(info) } @@ -138,7 +115,7 @@ impl ProxyService { } // 5. 启动代理服务器 - match self.start(true).await { + match self.start().await { Ok(info) => Ok(info), Err(e) => { // 启动失败,恢复原始配置 @@ -187,16 +164,16 @@ impl ProxyService { /// 为指定应用开启/关闭 Live 接管 /// - /// - 开启:自动启动代理服务(不影响总开关持久化),仅接管当前 app 的 Live 配置 - /// - 关闭:仅恢复当前 app 的 Live 配置;若总开关未开启且无其它接管,则自动停止代理服务 + /// - 开启:自动启动代理服务,仅接管当前 app 的 Live 配置 + /// - 关闭:仅恢复当前 app 的 Live 配置;若无其它接管,则自动停止代理服务 pub async fn set_takeover_for_app(&self, app_type: &str, enabled: bool) -> Result<(), String> { let app = AppType::from_str(app_type).map_err(|e| format!("无效的应用类型: {e}"))?; let app_type_str = app.as_str(); if enabled { - // 1) 代理服务未运行则自动启动(不持久化总开关) + // 1) 代理服务未运行则自动启动 if !self.is_running().await { - self.start(false).await?; + self.start().await?; } // 2) 已接管则直接返回(幂等) @@ -252,7 +229,7 @@ impl ProxyService { .await .map_err(|e| format!("删除 {app_type_str} Live 备份失败: {e}"))?; - // 3) 若无其它接管,更新旧标志,并在总开关未开启时停止代理服务 + // 3) 若无其它接管,更新旧标志,并停止代理服务 let has_any_backup = self .db .has_any_live_backup() @@ -261,13 +238,7 @@ impl ProxyService { if !has_any_backup { let _ = self.db.set_live_takeover_active(false).await; - let master_enabled = self - .db - .get_proxy_config() - .await - .map_err(|e| format!("获取代理配置失败: {e}"))? - .enabled; - if !master_enabled && self.is_running().await { + if self.is_running().await { // 此时没有任何 app 处于接管状态,停止服务即可 let _ = self.stop().await; } @@ -495,12 +466,6 @@ impl ProxyService { .await .map_err(|e| format!("停止代理服务器失败: {e}"))?; - // 将 enabled 设为 false,避免下次启动时自动开启 - if let Ok(mut config) = self.db.get_proxy_config().await { - config.enabled = false; - let _ = self.db.update_proxy_config(config).await; - } - log::info!("代理服务器已停止"); Ok(()) } else { @@ -513,15 +478,6 @@ impl ProxyService { // 1. 停止代理服务器(即使未运行也继续执行恢复逻辑) if let Err(e) = self.stop().await { log::warn!("停止代理服务器失败(将继续恢复 Live 配置): {e}"); - - // stop() 只有在 server 实例存在时才会把 enabled 设为 false; - // 这里兜底确保“总开关关闭”能落盘关闭状态。 - if let Ok(mut config) = self.db.get_proxy_config().await { - if config.enabled { - config.enabled = false; - let _ = self.db.update_proxy_config(config).await; - } - } } // 2. 恢复原始 Live 配置 @@ -946,7 +902,7 @@ impl ProxyService { /// 从异常退出中恢复(启动时调用) /// - /// 检测到 live_takeover_active=true 但代理未运行时调用此方法。 + /// 检测到 Live 备份残留时调用此方法。 /// 会恢复 Live 配置、清除接管标志、删除备份。 pub async fn recover_from_crash(&self) -> Result<(), String> { // 1. 恢复 Live 配置 @@ -970,7 +926,7 @@ impl ProxyService { /// 检测 Live 配置是否处于“被接管”的残留状态 /// - /// 用于兜底处理:当数据库标志未写入成功(或旧版本遗留)但 Live 文件已经写成代理占位符时, + /// 用于兜底处理:当数据库备份缺失但 Live 文件已经写成代理占位符时, /// 启动流程可以据此触发恢复逻辑。 pub fn detect_takeover_in_live_configs(&self) -> bool { if let Ok(config) = self.read_claude_live() { @@ -1255,9 +1211,8 @@ impl ProxyService { .await .map_err(|e| format!("获取代理配置失败: {e}"))?; - // 保存到数据库(保持 enabled 和 live_takeover_active 状态不变) + // 保存到数据库(保持 live_takeover_active 状态不变) let mut new_config = config.clone(); - new_config.enabled = previous.enabled; new_config.live_takeover_active = previous.live_takeover_active; self.db diff --git a/src/components/proxy/ProxySettingsDialog.tsx b/src/components/proxy/ProxySettingsDialog.tsx index 572e529b0..0a5b8afdb 100644 --- a/src/components/proxy/ProxySettingsDialog.tsx +++ b/src/components/proxy/ProxySettingsDialog.tsx @@ -26,8 +26,11 @@ import { useTranslation } from "react-i18next"; import type { TFunction } from "i18next"; import type { ProxyConfig } from "@/types/proxy"; -// 表单数据类型(不包含 enabled 字段,该字段由后端自动管理) -type ProxyConfigForm = Omit; +// 表单数据类型(仅包含可编辑字段) +type ProxyConfigForm = Pick< + ProxyConfig, + "listen_address" | "listen_port" | "max_retries" | "request_timeout" | "enable_logging" +>; const createProxyConfigSchema = (t: TFunction) => { const requestTimeoutSchema = z @@ -120,19 +123,18 @@ export function ProxySettingsDialog({ useEffect(() => { if (config) { form.reset({ - ...config, + listen_address: config.listen_address, + listen_port: config.listen_port, + max_retries: config.max_retries, + request_timeout: config.request_timeout, + enable_logging: config.enable_logging, }); } }, [config, form]); const onSubmit = async (data: ProxyConfigForm) => { try { - // 添加 enabled 字段(从当前配置中获取,保持不变) - const configToSave: ProxyConfig = { - ...data, - enabled: config?.enabled ?? true, - }; - await updateConfig(configToSave); + await updateConfig(data); closePanel(); } catch (error) { console.error("Save config failed:", error); diff --git a/src/types/proxy.ts b/src/types/proxy.ts index b4eec165e..3a5997e3d 100644 --- a/src/types/proxy.ts +++ b/src/types/proxy.ts @@ -1,5 +1,4 @@ export interface ProxyConfig { - enabled: boolean; listen_address: string; listen_port: number; max_retries: number;