fbc_starter/
base.rs

1use crate::constants::*;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize)]
5pub struct R<T> {
6    pub success: bool,
7    pub code: i32,
8    pub msg: Option<String>,
9    pub data: Option<T>,
10    #[serde(skip)]
11    pub def_exec: bool,
12    pub path: String,
13    pub version: String,
14    pub base_version: String,
15    pub timestamp: i64,
16}
17
18impl<T> R<T> {
19    pub fn new(code: i32, msg: Option<String>, data: Option<T>) -> Self {
20        Self {
21            success: code == SUCCESS_CODE,
22            code,
23            msg,
24            data,
25            def_exec: false,
26            path: String::new(),
27            version: String::new(),
28            base_version: String::new(),
29            timestamp: chrono::Local::now().timestamp_millis(),
30        }
31    }
32
33    pub fn ok() -> Self {
34        Self::new(SUCCESS_CODE, Some(SUCCESS_MESSAGE.into()), None)
35    }
36
37    pub fn ok_with_data(data: T) -> Self {
38        Self::new(SUCCESS_CODE, Some(SUCCESS_MESSAGE.into()), Some(data))
39    }
40
41    pub fn fail() -> Self {
42        Self::new(OPERATION_EX_CODE, None, None)
43    }
44
45    pub fn fail_with_code(code: i32, msg: String) -> Self {
46        Self::new(code, Some(msg.into()), None)
47    }
48
49    pub fn fail_with_message(msg: String) -> Self {
50        Self::new(FAIL_CODE, Some(msg.into()), None)
51    }
52}
53
54/// 游标分页基础响应
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct CursorPageBaseResp<T> {
57    /// 游标(下次翻页带上这参数)
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub cursor: Option<u64>,
60    /// 是否最后一页
61    pub is_last: bool,
62    /// 数据列表
63    pub list: Vec<T>,
64    /// 总数
65    pub total: i64,
66}
67
68impl<T> CursorPageBaseResp<T> {
69    /// 初始化游标分页响应
70    ///
71    /// # 参数
72    /// - `cursor_page`: 游标分页请求(用于获取 cursor 和 is_last)
73    /// - `list`: 数据列表
74    /// - `total`: 总数
75    pub fn init(cursor: Option<u64>, is_last: bool, list: Vec<T>, total: i64) -> Self {
76        Self {
77            cursor,
78            is_last,
79            list,
80            total,
81        }
82    }
83
84    /// 判断是否为空
85    pub fn is_empty(&self) -> bool {
86        self.list.is_empty()
87    }
88
89    /// 创建空的分页响应
90    pub fn empty() -> Self {
91        Self {
92            cursor: None,
93            is_last: true,
94            list: Vec::new(),
95            total: 0,
96        }
97    }
98}
99
100impl<T> Default for CursorPageBaseResp<T> {
101    fn default() -> Self {
102        Self {
103            cursor: None,
104            is_last: false,
105            list: Vec::new(),
106            total: 0,
107        }
108    }
109}
110
111/// 游标翻页基础请求
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct CursorPageBaseReq {
114    /// 页面大小(默认 10,最大 100)
115    #[serde(default = "CursorPageBaseReq::default_page_size")]
116    pub page_size: u32,
117    /// 游标(初始为 None,后续请求附带上次翻页的游标)
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub cursor: Option<u64>,
120}
121
122impl CursorPageBaseReq {
123    fn default_page_size() -> u32 {
124        10
125    }
126
127    /// 是否是第一页(cursor 为空或 None 或者 0)
128    pub fn is_first_page(&self) -> bool {
129        self.cursor
130            .as_ref()
131            .map(|s| *s == 0 || *s < self.page_size as u64)
132            .unwrap_or(true)
133    }
134
135    /// 计算分页参数,返回 (页码, page_size)
136    ///
137    /// 对应 Java 中的 plusPage(),这里固定页码为 1,因为采用游标分页。
138    pub fn plus_page(&self) -> (u32, u32) {
139        (1, self.page_size)
140    }
141}
142
143impl Default for CursorPageBaseReq {
144    fn default() -> Self {
145        Self {
146            page_size: Self::default_page_size(),
147            cursor: None,
148        }
149    }
150}