use std::collections::HashMap; use tauri::State; use crate::app_config::AppType; use crate::error::AppError; use crate::provider::Provider; use crate::services::{EndpointLatency, ProviderService, ProviderSortUpdate, SpeedtestService}; use crate::store::AppState; use std::str::FromStr; /// 获取所有供应商 #[tauri::command] pub fn get_providers( state: State<'_, AppState>, app: String, ) -> Result, String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::list(state.inner(), app_type).map_err(|e| e.to_string()) } /// 获取当前供应商ID #[tauri::command] pub fn get_current_provider(state: State<'_, AppState>, app: String) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::current(state.inner(), app_type).map_err(|e| e.to_string()) } /// 添加供应商 #[tauri::command] pub fn add_provider( state: State<'_, AppState>, app: String, provider: Provider, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::add(state.inner(), app_type, provider).map_err(|e| e.to_string()) } /// 更新供应商 #[tauri::command] pub fn update_provider( state: State<'_, AppState>, app: String, provider: Provider, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::update(state.inner(), app_type, provider).map_err(|e| e.to_string()) } /// 删除供应商 #[tauri::command] pub fn delete_provider( state: State<'_, AppState>, app: String, id: String, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::delete(state.inner(), app_type, &id) .map(|_| true) .map_err(|e| e.to_string()) } /// 切换供应商 fn switch_provider_internal(state: &AppState, app_type: AppType, id: &str) -> Result<(), AppError> { ProviderService::switch(state, app_type, id) } #[cfg_attr(not(feature = "test-hooks"), doc(hidden))] pub fn switch_provider_test_hook( state: &AppState, app_type: AppType, id: &str, ) -> Result<(), AppError> { switch_provider_internal(state, app_type, id) } #[tauri::command] pub fn switch_provider( state: State<'_, AppState>, app: String, id: String, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; switch_provider_internal(&state, app_type, &id) .map(|_| true) .map_err(|e| e.to_string()) } fn import_default_config_internal(state: &AppState, app_type: AppType) -> Result<(), AppError> { ProviderService::import_default_config(state, app_type) } #[cfg_attr(not(feature = "test-hooks"), doc(hidden))] pub fn import_default_config_test_hook( state: &AppState, app_type: AppType, ) -> Result<(), AppError> { import_default_config_internal(state, app_type) } /// 导入当前配置为默认供应商 #[tauri::command] pub fn import_default_config(state: State<'_, AppState>, app: String) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; import_default_config_internal(&state, app_type) .map(|_| true) .map_err(Into::into) } /// 查询供应商用量 #[allow(non_snake_case)] #[tauri::command] pub async fn queryProviderUsage( state: State<'_, AppState>, #[allow(non_snake_case)] providerId: String, // 使用 camelCase 匹配前端 app: String, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::query_usage(state.inner(), app_type, &providerId) .await .map_err(|e| e.to_string()) } /// 测试用量脚本(使用当前编辑器中的脚本,不保存) #[allow(non_snake_case)] #[tauri::command] pub async fn testUsageScript( state: State<'_, AppState>, #[allow(non_snake_case)] providerId: String, app: String, #[allow(non_snake_case)] scriptCode: String, timeout: Option, #[allow(non_snake_case)] accessToken: Option, #[allow(non_snake_case)] userId: Option, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::test_usage_script( state.inner(), app_type, &providerId, &scriptCode, timeout.unwrap_or(10), accessToken.as_deref(), userId.as_deref(), ) .await .map_err(|e| e.to_string()) } /// 读取当前生效的配置内容 #[tauri::command] pub fn read_live_provider_settings(app: String) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::read_live_settings(app_type).map_err(|e| e.to_string()) } /// 测试第三方/自定义供应商端点的网络延迟 #[tauri::command] pub async fn test_api_endpoints( urls: Vec, #[allow(non_snake_case)] timeoutSecs: Option, ) -> Result, String> { SpeedtestService::test_endpoints(urls, timeoutSecs) .await .map_err(|e| e.to_string()) } /// 获取自定义端点列表 #[tauri::command] pub fn get_custom_endpoints( state: State<'_, AppState>, app: String, #[allow(non_snake_case)] providerId: String, ) -> Result, String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::get_custom_endpoints(state.inner(), app_type, &providerId) .map_err(|e| e.to_string()) } /// 添加自定义端点 #[tauri::command] pub fn add_custom_endpoint( state: State<'_, AppState>, app: String, #[allow(non_snake_case)] providerId: String, url: String, ) -> Result<(), String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::add_custom_endpoint(state.inner(), app_type, &providerId, url) .map_err(|e| e.to_string()) } /// 删除自定义端点 #[tauri::command] pub fn remove_custom_endpoint( state: State<'_, AppState>, app: String, #[allow(non_snake_case)] providerId: String, url: String, ) -> Result<(), String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::remove_custom_endpoint(state.inner(), app_type, &providerId, url) .map_err(|e| e.to_string()) } /// 更新端点最后使用时间 #[tauri::command] pub fn update_endpoint_last_used( state: State<'_, AppState>, app: String, #[allow(non_snake_case)] providerId: String, url: String, ) -> Result<(), String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::update_endpoint_last_used(state.inner(), app_type, &providerId, url) .map_err(|e| e.to_string()) } /// 更新多个供应商的排序 #[tauri::command] pub fn update_providers_sort_order( state: State<'_, AppState>, app: String, updates: Vec, ) -> Result { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::update_sort_order(state.inner(), app_type, updates).map_err(|e| e.to_string()) }