Skip to main content

cool_core/entity/
mod.rs

1//! 实体模块
2//!
3//! 对应 TypeScript 版本的 `entity/`
4
5#[cfg(feature = "mongo")]
6pub mod mongo;
7#[cfg(feature = "mongo")]
8pub use mongo::*;
9
10use chrono::{DateTime, Utc};
11use sea_orm::entity::prelude::*;
12use serde::{Deserialize, Serialize};
13
14/// 基础实体 trait
15///
16/// 所有实体都应该实现此 trait,提供统一的基础字段
17pub trait BaseEntity: EntityTrait {
18    /// 获取 ID 列
19    fn id_column() -> Self::Column;
20    /// 获取创建时间列
21    fn create_time_column() -> Self::Column;
22    /// 获取更新时间列
23    fn update_time_column() -> Self::Column;
24}
25
26/// 软删除实体 trait
27///
28/// 支持软删除的实体应该实现此 trait
29pub trait SoftDeleteEntity: BaseEntity {
30    /// 获取删除时间列
31    fn delete_time_column() -> Self::Column;
32}
33
34/// 多租户实体 trait
35///
36/// 支持多租户的实体应该实现此 trait
37pub trait TenantEntity: BaseEntity {
38    /// 获取租户 ID 列
39    fn tenant_id_column() -> Self::Column;
40}
41
42/// 基础模型字段
43///
44/// 用于在 Model 中嵌入基础字段
45#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
46pub struct BaseFields {
47    /// 创建时间
48    #[serde(rename = "createTime")]
49    pub create_time: Option<DateTime<Utc>>,
50    /// 更新时间
51    #[serde(rename = "updateTime")]
52    pub update_time: Option<DateTime<Utc>>,
53}
54
55impl Default for BaseFields {
56    fn default() -> Self {
57        let now = Utc::now();
58        Self {
59            create_time: Some(now),
60            update_time: Some(now),
61        }
62    }
63}
64
65/// 软删除字段
66#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
67pub struct SoftDeleteFields {
68    /// 删除时间
69    #[serde(rename = "deleteTime", skip_serializing_if = "Option::is_none")]
70    pub delete_time: Option<DateTime<Utc>>,
71}
72
73/// 多租户字段
74#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
75pub struct TenantFields {
76    /// 租户 ID
77    #[serde(rename = "tenantId", skip_serializing_if = "Option::is_none")]
78    pub tenant_id: Option<i64>,
79}
80
81/// 通用 ID 类型
82pub type Id = i64;
83
84/// 分页查询参数
85#[derive(Debug, Clone, Serialize, Deserialize, Default)]
86pub struct PageQuery {
87    /// 当前页码(从 1 开始)
88    #[serde(default = "default_page")]
89    pub page: u64,
90    /// 每页条数
91    #[serde(default = "default_size")]
92    pub size: u64,
93    /// 排序字段
94    pub order: Option<String>,
95    /// 排序方式: "asc" | "desc"
96    pub sort: Option<String>,
97    /// 关键字搜索
98    #[serde(rename = "keyWord")]
99    pub key_word: Option<String>,
100}
101
102fn default_page() -> u64 {
103    1
104}
105
106fn default_size() -> u64 {
107    20
108}
109
110impl PageQuery {
111    /// 获取偏移量
112    pub fn offset(&self) -> u64 {
113        (self.page.saturating_sub(1)) * self.size
114    }
115
116    /// 是否升序
117    pub fn is_asc(&self) -> bool {
118        self.sort
119            .as_ref()
120            .map(|s| s.to_lowercase() == "asc")
121            .unwrap_or(false)
122    }
123}
124
125/// 列表查询参数
126#[derive(Debug, Clone, Serialize, Deserialize, Default)]
127pub struct ListQuery {
128    /// 排序字段
129    pub order: Option<String>,
130    /// 排序方式: "asc" | "desc"
131    pub sort: Option<String>,
132    /// 关键字搜索
133    #[serde(rename = "keyWord")]
134    pub key_word: Option<String>,
135}
136
137/// 删除参数
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct DeleteParam {
140    /// 要删除的 ID 列表
141    pub ids: Vec<Id>,
142}
143
144/// 新增返回结果
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct AddResult {
147    /// 新增的 ID
148    pub id: Id,
149}
150
151/// 批量新增返回结果
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct BatchAddResult {
154    /// 新增的 ID 列表
155    pub ids: Vec<Id>,
156}
157
158/// 查询选项(对齐 TS 版 QueryOp,保留核心字段)
159#[derive(Debug, Clone, Default)]
160pub struct QueryOption {
161    /// 需要模糊查询的字段
162    pub key_word_like_fields: Vec<String>,
163    /// 查询字段
164    pub select: Vec<String>,
165    /// 字段模糊查询
166    pub field_like: Vec<FieldCondition>,
167    /// 字段相等查询
168    pub field_eq: Vec<FieldCondition>,
169    /// 排序配置
170    pub order_by: Vec<(String, bool)>, // (字段, 是否升序)
171    /// 关联配置
172    pub joins: Vec<JoinOption>,
173    /// 额外的 AND 条件(字符串片段),用于快速拼接简单 where
174    pub where_and: Vec<String>,
175    /// 左连接配置(与 joins 等价,此处为兼容 TS 命名)
176    pub left_join: Vec<JoinOption>,
177    /// 自定义 where 片段(带参数),用于复杂过滤
178    pub extra_where: Vec<WhereFragment>,
179}
180
181impl QueryOption {
182    pub fn new() -> Self {
183        Self::default()
184    }
185
186    pub fn key_word_like_fields<I, S>(mut self, fields: I) -> Self
187    where
188        I: IntoIterator<Item = S>,
189        S: Into<String>,
190    {
191        self.key_word_like_fields = fields.into_iter().map(Into::into).collect();
192        self
193    }
194
195    pub fn select<I, S>(mut self, fields: I) -> Self
196    where
197        I: IntoIterator<Item = S>,
198        S: Into<String>,
199    {
200        self.select = fields.into_iter().map(Into::into).collect();
201        self
202    }
203
204    pub fn add_field_eq(
205        mut self,
206        column: impl Into<String>,
207        request_param: impl Into<String>,
208    ) -> Self {
209        self.field_eq
210            .push(FieldCondition::with_param(column, request_param));
211        self
212    }
213
214    pub fn add_field_like(
215        mut self,
216        column: impl Into<String>,
217        request_param: impl Into<String>,
218    ) -> Self {
219        self.field_like
220            .push(FieldCondition::with_param(column, request_param));
221        self
222    }
223
224    pub fn add_order_by(mut self, column: impl Into<String>, asc: bool) -> Self {
225        self.order_by.push((column.into(), asc));
226        self
227    }
228
229    pub fn add_left_join(
230        mut self,
231        entity: impl Into<String>,
232        alias: impl Into<String>,
233        condition: impl Into<String>,
234        join_type: JoinType,
235    ) -> Self {
236        self.left_join.push(JoinOption {
237            entity: entity.into(),
238            alias: alias.into(),
239            condition: condition.into(),
240            join_type,
241        });
242        self
243    }
244
245    pub fn add_where_and(mut self, cond: impl Into<String>) -> Self {
246        self.where_and.push(cond.into());
247        self
248    }
249
250    pub fn add_where_raw<I, V>(mut self, sql: impl Into<String>, params: I) -> Self
251    where
252        I: IntoIterator<Item = V>,
253        V: Into<serde_json::Value>,
254    {
255        self.extra_where.push(WhereFragment {
256            sql: sql.into(),
257            params: params.into_iter().map(Into::into).collect(),
258        });
259        self
260    }
261
262    /// 通过函数式方式追加 where 片段(便捷包装)
263    pub fn add_where_with<F>(mut self, f: F) -> Self
264    where
265        F: FnOnce(WhereBuilder) -> WhereBuilder,
266    {
267        let builder = f(WhereBuilder::new());
268        self.extra_where.extend(builder.build());
269        self
270    }
271}
272
273/// 字段条件
274#[derive(Debug, Clone)]
275pub struct FieldCondition {
276    /// 数据库列名
277    pub column: String,
278    /// 请求参数名
279    pub request_param: String,
280}
281
282impl FieldCondition {
283    pub fn new(column: impl Into<String>) -> Self {
284        let col = column.into();
285        Self {
286            request_param: col.clone(),
287            column: col,
288        }
289    }
290
291    pub fn with_param(column: impl Into<String>, request_param: impl Into<String>) -> Self {
292        Self {
293            column: column.into(),
294            request_param: request_param.into(),
295        }
296    }
297}
298
299/// 关联选项
300#[derive(Debug, Clone)]
301pub struct JoinOption {
302    /// 关联实体名
303    pub entity: String,
304    /// 别名
305    pub alias: String,
306    /// 关联条件
307    pub condition: String,
308    /// 关联类型: "inner" | "left"
309    pub join_type: JoinType,
310}
311
312/// 关联类型
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
314pub enum JoinType {
315    /// 内连接
316    Inner,
317    /// 左连接
318    #[default]
319    Left,
320}
321
322/// 自定义 where 片段(带参数)
323#[derive(Debug, Clone)]
324pub struct WhereFragment {
325    /// SQL 片段(不含 WHERE/AND)
326    pub sql: String,
327    /// 参数列表,对应 `?` 占位符
328    pub params: Vec<serde_json::Value>,
329}
330
331/// where 片段构造器,便于以函数式方式累加过滤条件
332#[derive(Default)]
333pub struct WhereBuilder {
334    frags: Vec<WhereFragment>,
335}
336
337impl WhereBuilder {
338    pub fn new() -> Self {
339        Self { frags: Vec::new() }
340    }
341
342    /// 添加等值条件:`column = ?`
343    pub fn eq(mut self, column: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
344        self.frags.push(WhereFragment {
345            sql: format!("{} = ?", column.into()),
346            params: vec![value.into()],
347        });
348        self
349    }
350
351    /// 添加模糊条件:`column LIKE ?`,自动包裹 `%`
352    pub fn like(mut self, column: impl Into<String>, value: impl Into<String>) -> Self {
353        self.frags.push(WhereFragment {
354            sql: format!("{} LIKE ?", column.into()),
355            params: vec![serde_json::Value::String(format!("%{}%", value.into()))],
356        });
357        self
358    }
359
360    /// 添加自定义 SQL 片段
361    pub fn raw<I, V>(mut self, sql: impl Into<String>, params: I) -> Self
362    where
363        I: IntoIterator<Item = V>,
364        V: Into<serde_json::Value>,
365    {
366        self.frags.push(WhereFragment {
367            sql: sql.into(),
368            params: params.into_iter().map(Into::into).collect(),
369        });
370        self
371    }
372
373    pub fn build(self) -> Vec<WhereFragment> {
374        self.frags
375    }
376}