use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; // SSOT 模式:不再写供应商副本文件 /// 供应商结构体 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Provider { pub id: String, pub name: String, #[serde(rename = "settingsConfig")] pub settings_config: Value, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "websiteUrl")] pub website_url: Option, #[serde(skip_serializing_if = "Option::is_none")] pub category: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "createdAt")] pub created_at: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "sortIndex")] pub sort_index: Option, /// 备注信息 #[serde(skip_serializing_if = "Option::is_none")] pub notes: Option, /// 供应商元数据(不写入 live 配置,仅存于 ~/.cc-switch/config.json) #[serde(skip_serializing_if = "Option::is_none")] pub meta: Option, /// 图标名称(如 "openai", "anthropic") #[serde(skip_serializing_if = "Option::is_none")] pub icon: Option, /// 图标颜色(Hex 格式,如 "#00A67E") #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "iconColor")] pub icon_color: Option, } impl Provider { /// 从现有ID创建供应商 pub fn with_id( id: String, name: String, settings_config: Value, website_url: Option, ) -> Self { Self { id, name, settings_config, website_url, category: None, created_at: None, sort_index: None, notes: None, meta: None, icon: None, icon_color: None, } } } /// 供应商管理器 #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ProviderManager { pub providers: IndexMap, pub current: String, } /// 用量查询脚本配置 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UsageScript { pub enabled: bool, pub language: String, pub code: String, #[serde(skip_serializing_if = "Option::is_none")] pub timeout: Option, /// 用量查询专用的 API Key(通用模板使用) #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "apiKey")] pub api_key: Option, /// 用量查询专用的 Base URL(通用和 NewAPI 模板使用) #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "baseUrl")] pub base_url: Option, /// 访问令牌(用于需要登录的接口,NewAPI 模板使用) #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "accessToken")] pub access_token: Option, /// 用户ID(用于需要用户标识的接口,NewAPI 模板使用) #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "userId")] pub user_id: Option, /// 自动查询间隔(单位:分钟,0 表示禁用自动查询) #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "autoQueryInterval")] pub auto_query_interval: Option, } /// 用量数据 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UsageData { #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "planName")] pub plan_name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub extra: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "isValid")] pub is_valid: Option, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "invalidMessage")] pub invalid_message: Option, #[serde(skip_serializing_if = "Option::is_none")] pub total: Option, #[serde(skip_serializing_if = "Option::is_none")] pub used: Option, #[serde(skip_serializing_if = "Option::is_none")] pub remaining: Option, #[serde(skip_serializing_if = "Option::is_none")] pub unit: Option, } /// 用量查询结果(支持多套餐) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UsageResult { pub success: bool, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option>, // 支持返回多个套餐 #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, } /// 供应商元数据 #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ProviderMeta { /// 自定义端点列表(按 URL 去重存储) #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub custom_endpoints: HashMap, /// 用量查询脚本配置 #[serde(skip_serializing_if = "Option::is_none")] pub usage_script: Option, /// 合作伙伴标记(前端使用 isPartner,保持字段名一致) #[serde(rename = "isPartner", skip_serializing_if = "Option::is_none")] pub is_partner: Option, /// 合作伙伴促销 key,用于识别 PackyCode 等特殊供应商 #[serde( rename = "partnerPromotionKey", skip_serializing_if = "Option::is_none" )] pub partner_promotion_key: Option, } impl ProviderManager { /// 获取所有供应商 pub fn get_all_providers(&self) -> &IndexMap { &self.providers } }