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 http::Transport,
10 req_option::RequestOption,
11 SDKResult,
12 },
13 impl_executable_builder_owned,
14};
15
16use super::AppTableService;
17
18impl AppTableService {
19 pub async fn create(
21 &self,
22 request: CreateTableRequest,
23 option: Option<RequestOption>,
24 ) -> SDKResult<BaseResponse<CreateTableResponse>> {
25 let mut api_req = request.api_request;
26 api_req.http_method = Method::POST;
27 api_req.api_path = format!("/open-apis/bitable/v1/apps/{}/tables", request.app_token);
28 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
29 api_req.body = serde_json::to_vec(&CreateTableRequestBody {
30 table: request.table,
31 })?;
32
33 let api_resp = Transport::request(api_req, &self.config, option).await?;
34 Ok(api_resp)
35 }
36}
37
38#[derive(Debug, Default)]
40pub struct CreateTableRequest {
41 api_request: ApiRequest,
42 app_token: String,
44 table: TableData,
46}
47
48impl CreateTableRequest {
49 pub fn builder() -> CreateTableRequestBuilder {
50 CreateTableRequestBuilder::default()
51 }
52
53 pub fn new(app_token: impl ToString, table: TableData) -> Self {
55 Self {
56 api_request: ApiRequest::default(),
57 app_token: app_token.to_string(),
58 table,
59 }
60 }
61}
62
63#[derive(Default)]
64pub struct CreateTableRequestBuilder {
65 request: CreateTableRequest,
66}
67
68impl CreateTableRequestBuilder {
69 pub fn app_token(mut self, app_token: impl ToString) -> Self {
71 self.request.app_token = app_token.to_string();
72 self
73 }
74
75 pub fn table(mut self, table: TableData) -> Self {
77 self.request.table = table;
78 self
79 }
80
81 pub fn build(self) -> CreateTableRequest {
82 self.request
83 }
84}
85
86impl_executable_builder_owned!(
87 CreateTableRequestBuilder,
88 AppTableService,
89 CreateTableRequest,
90 BaseResponse<CreateTableResponse>,
91 create
92);
93
94#[derive(Debug, Clone, Default, Serialize, Deserialize)]
96pub struct TableData {
97 pub name: String,
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub default_view_name: Option<String>,
102 #[serde(skip_serializing_if = "Option::is_none")]
104 pub fields: Option<Vec<TableField>>,
105}
106
107impl TableData {
108 pub fn new(name: impl ToString) -> Self {
110 Self {
111 name: name.to_string(),
112 default_view_name: None,
113 fields: None,
114 }
115 }
116
117 pub fn with_default_view_name(mut self, view_name: impl ToString) -> Self {
119 self.default_view_name = Some(view_name.to_string());
120 self
121 }
122
123 pub fn with_fields(mut self, fields: Vec<TableField>) -> Self {
125 self.fields = Some(fields);
126 self
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct TableField {
133 pub field_name: String,
135 #[serde(rename = "type")]
137 pub field_type: i32,
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub property: Option<serde_json::Value>,
141}
142
143impl TableField {
144 pub fn text(name: impl ToString) -> Self {
146 Self {
147 field_name: name.to_string(),
148 field_type: 1, property: None,
150 }
151 }
152
153 pub fn number(name: impl ToString) -> Self {
155 Self {
156 field_name: name.to_string(),
157 field_type: 2, property: None,
159 }
160 }
161
162 pub fn single_select(name: impl ToString, options: Vec<String>) -> Self {
164 let options_value: Vec<serde_json::Value> = options
165 .into_iter()
166 .map(|opt| serde_json::json!({"name": opt}))
167 .collect();
168
169 Self {
170 field_name: name.to_string(),
171 field_type: 3, property: Some(serde_json::json!({"options": options_value})),
173 }
174 }
175
176 pub fn multi_select(name: impl ToString, options: Vec<String>) -> Self {
178 let options_value: Vec<serde_json::Value> = options
179 .into_iter()
180 .map(|opt| serde_json::json!({"name": opt}))
181 .collect();
182
183 Self {
184 field_name: name.to_string(),
185 field_type: 4, property: Some(serde_json::json!({"options": options_value})),
187 }
188 }
189
190 pub fn date(name: impl ToString) -> Self {
192 Self {
193 field_name: name.to_string(),
194 field_type: 5, property: None,
196 }
197 }
198}
199
200#[derive(Serialize)]
201struct CreateTableRequestBody {
202 table: TableData,
203}
204
205#[derive(Deserialize, Debug)]
206pub struct CreateTableResponse {
207 pub table_id: String,
209 pub default_view_id: String,
211 pub field_id_list: Vec<String>,
213}
214
215impl ApiResponseTrait for CreateTableResponse {
216 fn data_format() -> ResponseFormat {
217 ResponseFormat::Data
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn test_create_table_request() {
227 let table = TableData::new("测试数据表")
228 .with_default_view_name("主视图")
229 .with_fields(vec![
230 TableField::text("标题"),
231 TableField::number("数量"),
232 TableField::single_select("状态", vec!["进行中".to_string(), "已完成".to_string()]),
233 ]);
234
235 let request = CreateTableRequest::builder()
236 .app_token("bascnmBA*****yGehy8")
237 .table(table)
238 .build();
239
240 assert_eq!(request.app_token, "bascnmBA*****yGehy8");
241 assert_eq!(request.table.name, "测试数据表");
242 }
243
244 #[test]
245 fn test_table_field_types() {
246 let text_field = TableField::text("标题");
247 assert_eq!(text_field.field_type, 1);
248 assert_eq!(text_field.field_name, "标题");
249
250 let number_field = TableField::number("数量");
251 assert_eq!(number_field.field_type, 2);
252
253 let select_field =
254 TableField::single_select("状态", vec!["A".to_string(), "B".to_string()]);
255 assert_eq!(select_field.field_type, 3);
256 assert!(select_field.property.is_some());
257 }
258}