Skip to main content

fbc_starter/
base.rs

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