Skip to main content

larkrs_client/bitable/
mod.rs

1pub mod table;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Debug, Serialize, Deserialize, Default)]
8pub struct SearchRecordsResponse {
9    pub items: Vec<Record>,
10    pub page_token: Option<String>,
11    pub has_more: bool,
12    pub total: i32,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct Record {
17    pub record_id: String,
18    pub fields: HashMap<String, Value>,
19    #[serde(default)]
20    pub created_by: Option<UserId>,
21    #[serde(default)]
22    pub created_time: Option<i64>,
23    #[serde(default)]
24    pub last_modified_by: Option<UserId>,
25    #[serde(default)]
26    pub last_modified_time: Option<i64>,
27}
28
29#[derive(Debug, Serialize, Deserialize)]
30pub struct UserId {
31    pub user_id: Option<String>,
32    pub open_id: Option<String>,
33    pub union_id: Option<String>,
34}
35
36#[derive(Debug, Serialize, Deserialize, Default)]
37pub struct SearchRecordsCond {
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub filter: Option<Filter>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub sort: Option<Vec<Sort>>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub field_names: Option<Vec<String>>,
44    pub view_id: String,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub automatic_fields: Option<bool>,
47}
48
49/// Enum for filter conjunction types
50#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
51#[serde(rename_all = "lowercase")]
52pub enum FilterConjunction {
53    And,
54    Or,
55}
56
57impl Default for FilterConjunction {
58    fn default() -> Self {
59        FilterConjunction::And
60    }
61}
62
63/// Enum for filter operator types
64#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
65#[serde(rename_all = "camelCase")]
66pub enum FilterOperator {
67    Is,
68    IsNot,
69    Contains,
70    DoesNotContain,
71    IsEmpty,
72    IsNotEmpty,
73    IsGreater,
74    IsGreaterEqual,
75    IsLess,
76    IsLessEqual,
77}
78
79#[derive(Debug, Serialize, Deserialize)]
80pub struct Filter {
81    pub conditions: Vec<FilterCondition>,
82    #[serde(default)]
83    pub conjunction: FilterConjunction,
84}
85
86#[derive(Debug, Serialize, Deserialize)]
87pub struct FilterCondition {
88    pub field_name: String,
89    pub operator: FilterOperator,
90    pub value: Vec<String>,
91}
92
93#[derive(Debug, Serialize, Deserialize)]
94pub struct Sort {
95    pub field_name: String,
96    #[serde(default)]
97    pub desc: bool,
98}
99
100#[derive(Debug, Serialize, Deserialize)]
101pub struct SortKey {
102    pub field_name: String,
103    #[serde(rename = "order")]
104    pub sort_order: SortOrder,
105}
106
107#[derive(Debug, Serialize, Deserialize)]
108#[serde(rename_all = "UPPERCASE")]
109pub enum SortOrder {
110    Asc,
111    Desc,
112}
113
114#[derive(Debug, Serialize, Deserialize)]
115pub struct BatchCreateRecordsRequest {
116    pub records: Vec<RecordCreate>,
117}
118
119impl From<Value> for BatchCreateRecordsRequest {
120    fn from(value: Value) -> Self {
121        match value {
122            Value::Array(array) => {
123                let records = array
124                    .iter()
125                    .filter_map(|item| {
126                        item.as_object().map(|obj| RecordCreate {
127                            fields: obj.clone().into_iter().collect(),
128                        })
129                    })
130                    .collect();
131                Self { records }
132            }
133            _ => Self { records: vec![] },
134        }
135    }
136}
137
138#[derive(Debug, Serialize, Deserialize)]
139pub struct RecordCreate {
140    pub fields: HashMap<String, Value>,
141}
142
143#[derive(Debug, Serialize, Deserialize, Default)]
144pub struct FieldsListResponse {
145    pub items: Vec<Field>,
146    #[serde(default)]
147    pub page_token: String,
148    #[serde(default)]
149    pub has_more: bool,
150    #[serde(default)]
151    pub total: i32,
152}
153
154#[derive(Debug, Serialize, Deserialize)]
155pub struct Field {
156    pub field_name: String,
157    pub field_id: String,
158    #[serde(rename = "type")]
159    pub field_type: i32,
160    #[serde(default)]
161    pub property: Value,
162    #[serde(rename = "ui_type", default)]
163    pub ui_type: Option<String>,
164    #[serde(default)]
165    pub description: Option<String>,
166    #[serde(default)]
167    pub is_primary: Option<bool>,
168}
169
170#[derive(Debug, Serialize, Deserialize)]
171pub struct FieldInfo {
172    pub field_name: String,          // 字段名称
173    pub description: Option<String>, // 字段描述
174    pub is_primary: Option<bool>,    // 是否为主键
175    pub ui_type: Option<String>,     // UI类型
176    pub write_type: Option<String>,  // 写入时传递的类型
177}
178
179impl From<FieldsListResponse> for Vec<FieldInfo> {
180    fn from(response: FieldsListResponse) -> Self {
181        response
182            .items
183            .into_iter()
184            .map(|field| {
185                let write_type = match field.ui_type.as_deref() {
186                    Some("Text") => Some("String".to_string()),
187                    Some("SingleSelect") => Some("String".to_string()),
188                    Some("DateTime") => Some("Timestamp".to_string()),
189                    Some("MultiSelect") => Some("Array<String>".to_string()),
190                    _ => Some("String".to_string()),
191                };
192
193                FieldInfo {
194                    field_name: field.field_name,
195                    description: field.description,
196                    is_primary: field.is_primary,
197                    ui_type: field.ui_type,
198                    write_type,
199                }
200            })
201            .collect()
202    }
203}