cool_core/config/
mod.rs

1//! 配置模块
2//!
3//! 对应 TypeScript 版本的 `interface.ts` 中的配置定义
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Cool 框架主配置
9#[derive(Debug, Clone, Serialize, Deserialize, Default)]
10#[serde(default)]
11pub struct CoolConfig {
12    /// 是否自动导入数据库
13    pub init_db: bool,
14    /// 是否自动导入模块菜单
15    pub init_menu: bool,
16    /// 判断是否初始化的方式: "file" | "db"
17    pub init_judge: String,
18    /// Eps 接口文档
19    pub eps: bool,
20    /// 多租户配置
21    pub tenant: Option<TenantConfig>,
22    /// 多语言配置
23    pub i18n: Option<I18nConfig>,
24    /// CRUD 配置
25    pub crud: CrudConfig,
26    /// 文件上传配置
27    pub file: Option<FileConfig>,
28    /// Redis 配置
29    pub redis: Option<RedisConfig>,
30    /// JWT 配置
31    pub jwt: JwtConfig,
32}
33
34/// 多租户配置
35#[derive(Debug, Clone, Serialize, Deserialize, Default)]
36pub struct TenantConfig {
37    /// 是否开启
38    pub enable: bool,
39    /// 需要过滤多租户的 URL
40    #[serde(default)]
41    pub urls: Vec<String>,
42}
43
44/// 多语言配置
45#[derive(Debug, Clone, Serialize, Deserialize, Default)]
46pub struct I18nConfig {
47    /// 是否开启
48    pub enable: bool,
49    /// 支持的语言列表
50    #[serde(default)]
51    pub languages: Vec<String>,
52    /// 翻译服务地址
53    pub service_url: Option<String>,
54}
55
56/// CRUD 配置
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct CrudConfig {
59    /// 软删除
60    #[serde(default = "default_soft_delete")]
61    pub soft_delete: bool,
62    /// 分页查询每页条数
63    #[serde(default = "default_page_size")]
64    pub page_size: u64,
65    /// 插入方式: "normal" | "save"
66    #[serde(default = "default_upsert")]
67    pub upsert: String,
68}
69
70impl Default for CrudConfig {
71    fn default() -> Self {
72        Self {
73            soft_delete: true,
74            page_size: 20,
75            upsert: "normal".to_string(),
76        }
77    }
78}
79
80fn default_soft_delete() -> bool {
81    true
82}
83
84fn default_page_size() -> u64 {
85    20
86}
87
88fn default_upsert() -> String {
89    "normal".to_string()
90}
91
92/// 文件上传配置
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct FileConfig {
95    /// 上传模式: "local" | "cloud" | "other"
96    pub mode: String,
97    /// 本地上传文件地址前缀
98    pub domain: Option<String>,
99    /// 阿里云 OSS 配置
100    pub oss: Option<OssConfig>,
101    /// 腾讯云 COS 配置
102    pub cos: Option<CosConfig>,
103    /// 七牛云配置
104    pub qiniu: Option<QiniuConfig>,
105    /// AWS S3 配置
106    pub aws: Option<AwsConfig>,
107}
108
109/// 阿里云 OSS 配置
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct OssConfig {
112    pub access_key_id: String,
113    pub access_key_secret: String,
114    pub bucket: String,
115    pub endpoint: String,
116    pub timeout: Option<String>,
117    pub exp_after: Option<u64>,
118    pub max_size: Option<u64>,
119    pub host: Option<String>,
120    pub public_domain: Option<String>,
121}
122
123/// 腾讯云 COS 配置
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct CosConfig {
126    pub access_key_id: String,
127    pub access_key_secret: String,
128    pub bucket: String,
129    pub region: String,
130    pub public_domain: String,
131    pub duration_seconds: Option<u64>,
132    pub allow_prefix: Option<String>,
133    pub allow_actions: Option<Vec<String>>,
134}
135
136/// 七牛云配置
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct QiniuConfig {
139    pub access_key_id: String,
140    pub access_key_secret: String,
141    pub bucket: String,
142    pub region: String,
143    pub public_domain: String,
144    pub upload_url: Option<String>,
145    pub file_key: Option<String>,
146}
147
148/// AWS S3 配置
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct AwsConfig {
151    pub access_key_id: String,
152    pub secret_access_key: String,
153    pub bucket: String,
154    pub region: String,
155    pub fields: Option<HashMap<String, String>>,
156    pub conditions: Option<Vec<serde_json::Value>>,
157    pub expires: Option<u64>,
158    pub public_domain: Option<String>,
159    pub force_path_style: Option<bool>,
160}
161
162/// Redis 配置
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct RedisConfig {
165    pub host: String,
166    pub port: u16,
167    pub password: Option<String>,
168    pub db: u8,
169}
170
171impl RedisConfig {
172    /// 获取连接 URL
173    pub fn url(&self) -> String {
174        match &self.password {
175            Some(pwd) if !pwd.is_empty() => {
176                format!("redis://:{}@{}:{}/{}", pwd, self.host, self.port, self.db)
177            }
178            _ => format!("redis://{}:{}/{}", self.host, self.port, self.db),
179        }
180    }
181}
182
183/// JWT 配置
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct JwtConfig {
186    /// 密钥
187    #[serde(default = "default_jwt_secret")]
188    pub secret: String,
189    /// 过期时间(秒)
190    #[serde(default = "default_jwt_expire")]
191    pub expire: u64,
192    /// 刷新过期时间(秒)
193    #[serde(default = "default_jwt_refresh_expire")]
194    pub refresh_expire: u64,
195}
196
197impl Default for JwtConfig {
198    fn default() -> Self {
199        Self {
200            secret: "cool-admin-rust".to_string(),
201            expire: 7200,
202            refresh_expire: 604800,
203        }
204    }
205}
206
207fn default_jwt_secret() -> String {
208    "cool-admin-rust".to_string()
209}
210
211fn default_jwt_expire() -> u64 {
212    7200
213}
214
215fn default_jwt_refresh_expire() -> u64 {
216    604800
217}
218
219/// 模块配置
220#[derive(Debug, Clone, Serialize, Deserialize, Default)]
221pub struct ModuleConfig {
222    /// 模块名称
223    pub name: String,
224    /// 模块描述
225    pub description: String,
226    /// 模块加载顺序,默认为0,值越大越优先加载
227    #[serde(default)]
228    pub order: i32,
229}
230
231/// 数据库配置
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct DatabaseConfig {
234    /// 数据库类型: "mysql" | "postgres" | "sqlite"
235    pub r#type: String,
236    /// 主机地址
237    pub host: Option<String>,
238    /// 端口
239    pub port: Option<u16>,
240    /// 用户名
241    pub username: Option<String>,
242    /// 密码
243    pub password: Option<String>,
244    /// 数据库名
245    pub database: String,
246    /// 最大连接数
247    #[serde(default = "default_max_connections")]
248    pub max_connections: u32,
249    /// 最小连接数
250    #[serde(default = "default_min_connections")]
251    pub min_connections: u32,
252    /// 连接超时(秒)
253    #[serde(default = "default_connect_timeout")]
254    pub connect_timeout: u64,
255    /// 是否打印 SQL 日志
256    #[serde(default)]
257    pub logging: bool,
258    /// 是否同步数据库结构
259    #[serde(default)]
260    pub synchronize: bool,
261}
262
263fn default_max_connections() -> u32 {
264    100
265}
266
267fn default_min_connections() -> u32 {
268    5
269}
270
271fn default_connect_timeout() -> u64 {
272    10
273}
274
275impl DatabaseConfig {
276    /// 获取数据库连接 URL
277    pub fn url(&self) -> String {
278        match self.r#type.as_str() {
279            "sqlite" => format!("sqlite://{}?mode=rwc", self.database),
280            "mysql" => {
281                format!(
282                    "mysql://{}:{}@{}:{}/{}",
283                    self.username.as_deref().unwrap_or("root"),
284                    self.password.as_deref().unwrap_or(""),
285                    self.host.as_deref().unwrap_or("localhost"),
286                    self.port.unwrap_or(3306),
287                    self.database
288                )
289            }
290            "postgres" => {
291                format!(
292                    "postgres://{}:{}@{}:{}/{}",
293                    self.username.as_deref().unwrap_or("postgres"),
294                    self.password.as_deref().unwrap_or(""),
295                    self.host.as_deref().unwrap_or("localhost"),
296                    self.port.unwrap_or(5432),
297                    self.database
298                )
299            }
300            _ => panic!("不支持的数据库类型: {}", self.r#type),
301        }
302    }
303}