open_lark/service/cloud_docs/bitable/v1/app_table/
create.rs1use 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 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#[derive(Debug, Default)]
41pub struct CreateTableRequest {
42 api_request: ApiRequest,
43 app_token: String,
45 table: TableData,
47}
48
49impl CreateTableRequest {
50 pub fn builder() -> CreateTableRequestBuilder {
51 CreateTableRequestBuilder::default()
52 }
53
54 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 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 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#[derive(Debug, Clone, Default, Serialize, Deserialize)]
97pub struct TableData {
98 pub name: String,
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub default_view_name: Option<String>,
103 #[serde(skip_serializing_if = "Option::is_none")]
105 pub fields: Option<Vec<TableField>>,
106}
107
108impl TableData {
109 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 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 pub fn with_fields(mut self, fields: Vec<TableField>) -> Self {
126 self.fields = Some(fields);
127 self
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct TableField {
134 pub field_name: String,
136 #[serde(rename = "type")]
138 pub field_type: i32,
139 #[serde(skip_serializing_if = "Option::is_none")]
141 pub property: Option<serde_json::Value>,
142}
143
144impl TableField {
145 pub fn text(name: impl ToString) -> Self {
147 Self {
148 field_name: name.to_string(),
149 field_type: 1, property: None,
151 }
152 }
153
154 pub fn number(name: impl ToString) -> Self {
156 Self {
157 field_name: name.to_string(),
158 field_type: 2, property: None,
160 }
161 }
162
163 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, property: Some(serde_json::json!({"options": options_value})),
174 }
175 }
176
177 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, property: Some(serde_json::json!({"options": options_value})),
188 }
189 }
190
191 pub fn date(name: impl ToString) -> Self {
193 Self {
194 field_name: name.to_string(),
195 field_type: 5, property: None,
197 }
198 }
199}
200
201#[derive(Serialize)]
202struct CreateTableRequestBody {
203 table: TableData,
204}
205
206#[derive(Deserialize, Debug)]
207pub struct CreateTableResponse {
208 pub table_id: String,
210 pub default_view_id: String,
212 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}