use serde::{Deserialize, Serialize}; /// 模型配额信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ModelQuota { pub name: String, pub percentage: i32, // 剩余百分比 0-100 pub reset_time: String, // -- 动态参数解析与持久化 -- #[serde(skip_serializing_if = "Option::is_none")] pub display_name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub supports_images: Option, #[serde(skip_serializing_if = "Option::is_none")] pub supports_thinking: Option, #[serde(skip_serializing_if = "Option::is_none")] pub thinking_budget: Option, #[serde(skip_serializing_if = "Option::is_none")] pub recommended: Option, #[serde(skip_serializing_if = "Option::is_none")] pub max_tokens: Option, #[serde(skip_serializing_if = "Option::is_none")] pub max_output_tokens: Option, #[serde(skip_serializing_if = "Option::is_none")] pub supported_mime_types: Option>, } /// 配额数据结构 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct QuotaData { pub models: Vec, pub last_updated: i64, #[serde(default)] pub is_forbidden: bool, /// 禁止访问的原因 (403 详细信息) #[serde(default)] pub forbidden_reason: Option, /// 订阅等级 (FREE/PRO/ULTRA) #[serde(default)] pub subscription_tier: Option, /// 模型淘汰重定向规则表 (old_model_id -> new_model_id) #[serde(default)] pub model_forwarding_rules: std::collections::HashMap, } impl QuotaData { pub fn new() -> Self { Self { models: Vec::new(), last_updated: chrono::Utc::now().timestamp(), is_forbidden: false, forbidden_reason: None, subscription_tier: None, model_forwarding_rules: std::collections::HashMap::new(), } } pub fn add_model(&mut self, model: ModelQuota) { self.models.push(model); } } impl Default for QuotaData { fn default() -> Self { Self::new() } }