open_lark/service/cloud_docs/bitable/v1/app_table/
create.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    core::{
6        api_req::ApiRequest,
7        api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8        constants::AccessTokenType,
9        endpoints::cloud_docs::*,
10        http::Transport,
11        req_option::RequestOption,
12        SDKResult,
13    },
14    impl_executable_builder_owned,
15};
16
17use super::AppTableService;
18
19impl AppTableService {
20    /// 新增一个数据表
21    pub async fn create(
22        &self,
23        request: CreateTableRequest,
24        option: Option<RequestOption>,
25    ) -> SDKResult<BaseResponse<CreateTableResponse>> {
26        let mut api_req = request.api_request;
27        api_req.http_method = Method::POST;
28        api_req.api_path = BITABLE_V1_TABLE_CREATE.replace("{app_token}", &request.app_token);
29        api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
30        api_req.body = serde_json::to_vec(&CreateTableRequestBody {
31            table: request.table,
32        })?;
33
34        let api_resp = Transport::request(api_req, &self.config, option).await?;
35        Ok(api_resp)
36    }
37}
38
39/// 新增数据表请求
40#[derive(Debug, Default)]
41pub struct CreateTableRequest {
42    api_request: ApiRequest,
43    /// 多维表格的 app_token
44    app_token: String,
45    /// 数据表信息
46    table: TableData,
47}
48
49impl CreateTableRequest {
50    pub fn builder() -> CreateTableRequestBuilder {
51        CreateTableRequestBuilder::default()
52    }
53
54    /// 创建新增数据表请求
55    pub fn new(app_token: impl ToString, table: TableData) -> Self {
56        Self {
57            api_request: ApiRequest::default(),
58            app_token: app_token.to_string(),
59            table,
60        }
61    }
62}
63
64#[derive(Default)]
65pub struct CreateTableRequestBuilder {
66    request: CreateTableRequest,
67}
68
69impl CreateTableRequestBuilder {
70    /// 多维表格的 app_token
71    pub fn app_token(mut self, app_token: impl ToString) -> Self {
72        self.request.app_token = app_token.to_string();
73        self
74    }
75
76    /// 数据表信息
77    pub fn table(mut self, table: TableData) -> Self {
78        self.request.table = table;
79        self
80    }
81
82    pub fn build(self) -> CreateTableRequest {
83        self.request
84    }
85}
86
87impl_executable_builder_owned!(
88    CreateTableRequestBuilder,
89    AppTableService,
90    CreateTableRequest,
91    BaseResponse<CreateTableResponse>,
92    create
93);
94
95/// 数据表数据
96#[derive(Debug, Clone, Default, Serialize, Deserialize)]
97pub struct TableData {
98    /// 数据表名称
99    pub name: String,
100    /// 数据表的默认视图名称,不填则默认为"数据表"
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub default_view_name: Option<String>,
103    /// 数据表初始字段
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub fields: Option<Vec<TableField>>,
106}
107
108impl TableData {
109    /// 创建数据表数据
110    pub fn new(name: impl ToString) -> Self {
111        Self {
112            name: name.to_string(),
113            default_view_name: None,
114            fields: None,
115        }
116    }
117
118    /// 设置默认视图名称
119    pub fn with_default_view_name(mut self, view_name: impl ToString) -> Self {
120        self.default_view_name = Some(view_name.to_string());
121        self
122    }
123
124    /// 设置初始字段
125    pub fn with_fields(mut self, fields: Vec<TableField>) -> Self {
126        self.fields = Some(fields);
127        self
128    }
129}
130
131/// 字段信息
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct TableField {
134    /// 字段名称
135    pub field_name: String,
136    /// 字段类型
137    #[serde(rename = "type")]
138    pub field_type: i32,
139    /// 字段属性,不同字段类型对应不同的属性结构
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub property: Option<serde_json::Value>,
142}
143
144impl TableField {
145    /// 创建文本字段
146    pub fn text(name: impl ToString) -> Self {
147        Self {
148            field_name: name.to_string(),
149            field_type: 1, // 多行文本
150            property: None,
151        }
152    }
153
154    /// 创建数字字段
155    pub fn number(name: impl ToString) -> Self {
156        Self {
157            field_name: name.to_string(),
158            field_type: 2, // 数字
159            property: None,
160        }
161    }
162
163    /// 创建单选字段
164    pub fn single_select(name: impl ToString, options: Vec<String>) -> Self {
165        let options_value: Vec<serde_json::Value> = options
166            .into_iter()
167            .map(|opt| serde_json::json!({"name": opt}))
168            .collect();
169
170        Self {
171            field_name: name.to_string(),
172            field_type: 3, // 单选
173            property: Some(serde_json::json!({"options": options_value})),
174        }
175    }
176
177    /// 创建多选字段
178    pub fn multi_select(name: impl ToString, options: Vec<String>) -> Self {
179        let options_value: Vec<serde_json::Value> = options
180            .into_iter()
181            .map(|opt| serde_json::json!({"name": opt}))
182            .collect();
183
184        Self {
185            field_name: name.to_string(),
186            field_type: 4, // 多选
187            property: Some(serde_json::json!({"options": options_value})),
188        }
189    }
190
191    /// 创建日期字段
192    pub fn date(name: impl ToString) -> Self {
193        Self {
194            field_name: name.to_string(),
195            field_type: 5, // 日期
196            property: None,
197        }
198    }
199}
200
201#[derive(Serialize)]
202struct CreateTableRequestBody {
203    table: TableData,
204}
205
206#[derive(Deserialize, Debug)]
207pub struct CreateTableResponse {
208    /// 数据表信息
209    pub table_id: String,
210    /// 数据表的默认视图 ID
211    pub default_view_id: String,
212    /// 数据表初始字段的 field_id 列表
213    pub field_id_list: Vec<String>,
214}
215
216impl ApiResponseTrait for CreateTableResponse {
217    fn data_format() -> ResponseFormat {
218        ResponseFormat::Data
219    }
220}
221
222#[cfg(test)]
223#[allow(unused_variables, unused_unsafe)]
224mod tests {
225    use super::*;
226
227    #[test]
228    fn test_create_table_request() {
229        let table = TableData::new("测试数据表")
230            .with_default_view_name("主视图")
231            .with_fields(vec![
232                TableField::text("标题"),
233                TableField::number("数量"),
234                TableField::single_select("状态", vec!["进行中".to_string(), "已完成".to_string()]),
235            ]);
236
237        let request = CreateTableRequest::builder()
238            .app_token("bascnmBA*****yGehy8")
239            .table(table)
240            .build();
241
242        assert_eq!(request.app_token, "bascnmBA*****yGehy8");
243        assert_eq!(request.table.name, "测试数据表");
244    }
245
246    #[test]
247    fn test_table_field_types() {
248        let text_field = TableField::text("标题");
249        assert_eq!(text_field.field_type, 1);
250        assert_eq!(text_field.field_name, "标题");
251
252        let number_field = TableField::number("数量");
253        assert_eq!(number_field.field_type, 2);
254
255        let select_field =
256            TableField::single_select("状态", vec!["A".to_string(), "B".to_string()]);
257        assert_eq!(select_field.field_type, 3);
258        assert!(select_field.property.is_some());
259    }
260}