open_lark/service/cloud_docs/sheets/v3/float_image/
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    service::sheets::v3::SpreadsheetSheetService,
16};
17
18impl SpreadsheetSheetService {
19    /// 创建浮动图片
20    pub async fn create_float_image(
21        &self,
22        request: CreateFloatImageRequest,
23        option: Option<RequestOption>,
24    ) -> SDKResult<BaseResponse<CreateFloatImageResponseData>> {
25        let mut api_req = request.api_request;
26        api_req.http_method = Method::POST;
27        api_req.api_path = SHEETS_V3_SPREADSHEET_FLOAT_IMAGES
28            .replace("{}", &request.spreadsheet_token)
29            .replace("{}", &request.sheet_id);
30        api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
31
32        let api_resp = Transport::request(api_req, &self.config, option).await?;
33
34        Ok(api_resp)
35    }
36}
37
38/// 创建浮动图片请求
39#[derive(Default, Debug, Serialize, Deserialize)]
40pub struct CreateFloatImageRequest {
41    #[serde(skip)]
42    api_request: ApiRequest,
43    /// spreadsheet 的 token
44    spreadsheet_token: String,
45    /// sheet 的 id
46    sheet_id: String,
47    /// 浮动图片信息
48    float_image: FloatImageData,
49}
50
51impl CreateFloatImageRequest {
52    pub fn builder() -> CreateFloatImageRequestBuilder {
53        CreateFloatImageRequestBuilder::default()
54    }
55}
56
57#[derive(Default)]
58pub struct CreateFloatImageRequestBuilder {
59    request: CreateFloatImageRequest,
60}
61
62impl CreateFloatImageRequestBuilder {
63    pub fn spreadsheet_token(mut self, spreadsheet_token: impl ToString) -> Self {
64        self.request.spreadsheet_token = spreadsheet_token.to_string();
65        self
66    }
67
68    pub fn sheet_id(mut self, sheet_id: impl ToString) -> Self {
69        self.request.sheet_id = sheet_id.to_string();
70        self
71    }
72
73    pub fn float_image(mut self, float_image: FloatImageData) -> Self {
74        self.request.float_image = float_image;
75        self
76    }
77
78    pub fn build(mut self) -> CreateFloatImageRequest {
79        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
80        self.request
81    }
82}
83
84impl_executable_builder_owned!(
85    CreateFloatImageRequestBuilder,
86    SpreadsheetSheetService,
87    CreateFloatImageRequest,
88    BaseResponse<CreateFloatImageResponseData>,
89    create_float_image
90);
91
92/// 浮动图片数据
93#[derive(Default, Debug, Serialize, Deserialize)]
94pub struct FloatImageData {
95    /// 图片token
96    pub image_token: String,
97    /// 图片位置
98    pub position: ImagePosition,
99    /// 图片大小
100    pub size: ImageSize,
101    /// 浮动图片 ID(仅在响应时存在)
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub float_image_id: Option<String>,
104    /// 图片名称
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub name: Option<String>,
107}
108
109/// 图片位置
110#[derive(Default, Debug, Serialize, Deserialize)]
111pub struct ImagePosition {
112    /// 起始列索引(从0开始)
113    pub start_col_index: i32,
114    /// 起始行索引(从0开始)
115    pub start_row_index: i32,
116    /// 在单元格内的水平偏移量(像素)
117    #[serde(default)]
118    pub offset_x: f64,
119    /// 在单元格内的垂直偏移量(像素)
120    #[serde(default)]
121    pub offset_y: f64,
122}
123
124/// 图片大小
125#[derive(Default, Debug, Serialize, Deserialize)]
126pub struct ImageSize {
127    /// 图片宽度(像素)
128    pub width: f64,
129    /// 图片高度(像素)
130    pub height: f64,
131}
132
133impl FloatImageData {
134    /// 创建浮动图片
135    pub fn new(image_token: impl ToString, position: ImagePosition, size: ImageSize) -> Self {
136        Self {
137            image_token: image_token.to_string(),
138            position,
139            size,
140            float_image_id: None,
141            name: None,
142        }
143    }
144
145    /// 设置图片名称
146    pub fn with_name(mut self, name: impl ToString) -> Self {
147        self.name = Some(name.to_string());
148        self
149    }
150}
151
152impl ImagePosition {
153    /// 创建图片位置
154    pub fn new(col_index: i32, row_index: i32) -> Self {
155        Self {
156            start_col_index: col_index,
157            start_row_index: row_index,
158            offset_x: 0.0,
159            offset_y: 0.0,
160        }
161    }
162
163    /// 设置偏移量
164    pub fn with_offset(mut self, offset_x: f64, offset_y: f64) -> Self {
165        self.offset_x = offset_x;
166        self.offset_y = offset_y;
167        self
168    }
169}
170
171impl ImageSize {
172    /// 创建图片大小
173    pub fn new(width: f64, height: f64) -> Self {
174        Self { width, height }
175    }
176
177    /// 创建正方形图片大小
178    pub fn square(size: f64) -> Self {
179        Self {
180            width: size,
181            height: size,
182        }
183    }
184}
185
186/// 创建浮动图片响应体最外层
187#[derive(Deserialize, Debug)]
188pub struct CreateFloatImageResponseData {
189    /// 浮动图片 ID
190    pub float_image_id: String,
191    /// 浮动图片信息
192    #[serde(flatten)]
193    pub float_image: FloatImageData,
194}
195
196impl ApiResponseTrait for CreateFloatImageResponseData {
197    fn data_format() -> ResponseFormat {
198        ResponseFormat::Data
199    }
200}
201
202#[cfg(test)]
203#[allow(unused_variables, unused_unsafe)]
204mod test {
205    use super::*;
206    use serde_json::json;
207
208    #[test]
209    fn test_float_image_creation() {
210        let position = ImagePosition::new(1, 1).with_offset(10.0, 20.0);
211        let size = ImageSize::new(200.0, 150.0);
212        let float_image =
213            FloatImageData::new("img_token_123", position, size).with_name("示例图片");
214
215        assert_eq!(float_image.image_token, "img_token_123");
216        assert_eq!(float_image.position.start_col_index, 1);
217        assert_eq!(float_image.position.offset_x, 10.0);
218        assert_eq!(float_image.size.width, 200.0);
219        assert_eq!(float_image.name.as_ref().unwrap(), "示例图片");
220    }
221
222    #[test]
223    fn test_create_float_image_response() {
224        let json = json!({
225            "float_image_id": "fimg_001",
226            "image_token": "img_token_123",
227            "position": {
228                "start_col_index": 1,
229                "start_row_index": 1,
230                "offset_x": 10.0,
231                "offset_y": 20.0
232            },
233            "size": {
234                "width": 200.0,
235                "height": 150.0
236            },
237            "name": "示例图片"
238        });
239
240        let response: CreateFloatImageResponseData = serde_json::from_value(json).unwrap();
241        assert_eq!(response.float_image_id, "fimg_001");
242        assert_eq!(response.float_image.image_token, "img_token_123");
243    }
244}