open_lark/card/components/interactive_components/
multi_select_static.rs

1use serde::{Deserialize, Serialize};
2
3use crate::card::components::{
4    content_components::plain_text::PlainText,
5    interactive_components::{input::InputConfirm, select_static::SelectStaticOption},
6};
7
8/// 下拉选择-多选
9#[derive(Debug, Serialize, Deserialize)]
10pub struct MultiSelectStatic {
11    /// 组件的标签。下拉选择-多选组件取固定值 multi_select_static。
12    tag: String,
13    /// 组件边框样式。可选值:
14    ///
15    /// default:带边框样式
16    /// text:不带边框的纯文本样式
17    #[serde(skip_serializing_if = "Option::is_none")]
18    r#type: Option<String>,
19    /// 表单容器中组件的唯一标识。当多选组件内嵌在表单容器时,该属性生效,
20    /// 用于识别用户提交的数据属于哪个组件。
21    ///
22    /// 注意:当多选组件嵌套在表单容器中时,该字段必填且需在卡片全局内唯一。
23    #[serde(skip_serializing_if = "Option::is_none")]
24    name: Option<String>,
25    /// 用户未选择选项时,下拉选择组件内的占位文本。
26    #[serde(skip_serializing_if = "Option::is_none")]
27    placeholder: Option<PlainText>,
28    /// 下拉选择组件的宽度。支持以下枚举值:
29    ///
30    /// - default:默认宽度:
31    ///     - 当组件带边框时(即 "type":"default"),默认宽度值固定为 282 px
32    ///     - 当组件不带边框时(即 "type":"text"),组件宽度自适应选择器的内容宽度
33    /// - fill:组件宽度将撑满父容器宽度
34    /// - [100,∞)px:自定义固定数值宽度,如 200px。最小值为
35    ///   100px。超出父容器宽度时,按撑满父容器宽度展示
36    #[serde(skip_serializing_if = "Option::is_none")]
37    width: Option<String>,
38    /// 多选组件的选项是否必选。当组件内嵌在表单容器中时,该属性可用。其它情况将报错或不生效。
39    /// 可取值:
40    ///
41    /// - true:多选组件必选。当用户点击表单容器的“提交”时,未选择多选选项,
42    ///   则前端提示“有必填项未填写”,不会向开发者的服务端发起回传请求。
43    /// - false:多选组件可选。当用户点击表单容器的“提交”时,未选择多选选项,
44    ///   仍提交表单容器中的数据。
45    #[serde(skip_serializing_if = "Option::is_none")]
46    required: Option<bool>,
47    /// 是否禁用该多选组件。可选值:
48    ///
49    /// - true:禁用该多选组件,组件展示自定义的占位文本或选项初始值,且终端用户不可修改交互
50    /// - false:多选组件保持可用状态
51    #[serde(skip_serializing_if = "Option::is_none")]
52    disabled: Option<bool>,
53    /// 多选组件默认选中的选项。数组项的值需要和 options.value 对应。
54    #[serde(skip_serializing_if = "Option::is_none")]
55    selected_values: Option<Vec<String>>,
56    /// 选项的配置。
57    #[serde(skip_serializing_if = "Option::is_none")]
58    options: Option<Vec<SelectStaticOption>>,
59    /// 二次确认弹窗配置。指在用户提交时弹出二次确认弹窗提示;只有用户点击确认后,
60    /// 才提交输入的内容。该字段默认提供了确认和取消按钮,你只需要配置弹窗的标题与内容即可。
61    ///
62    /// 注意:confirm 字段仅在用户点击包含提交属性的按钮时才会触发二次确认弹窗。
63    #[serde(skip_serializing_if = "Option::is_none")]
64    confirm: Option<InputConfirm>,
65}
66
67impl Default for MultiSelectStatic {
68    fn default() -> Self {
69        Self {
70            tag: "multi_select_static".to_string(),
71            r#type: None,
72            name: None,
73            required: None,
74            disabled: None,
75            placeholder: None,
76            width: None,
77            options: None,
78            confirm: None,
79            selected_values: None,
80        }
81    }
82}
83
84impl MultiSelectStatic {
85    pub fn new() -> Self {
86        Self::default()
87    }
88
89    pub fn r#type(mut self, r#type: &str) -> Self {
90        self.r#type = Some(r#type.to_string());
91        self
92    }
93
94    pub fn name(mut self, name: &str) -> Self {
95        self.name = Some(name.to_string());
96        self
97    }
98
99    pub fn required(mut self, required: bool) -> Self {
100        self.required = Some(required);
101        self
102    }
103
104    pub fn disabled(mut self, disabled: bool) -> Self {
105        self.disabled = Some(disabled);
106        self
107    }
108
109    pub fn placeholder(mut self, placeholder: PlainText) -> Self {
110        self.placeholder = Some(placeholder);
111        self
112    }
113
114    pub fn width(mut self, width: &str) -> Self {
115        self.width = Some(width.to_string());
116        self
117    }
118
119    pub fn values(mut self, values: Vec<&str>) -> Self {
120        self.selected_values = Some(values.iter().map(|v| v.to_string()).collect());
121        self
122    }
123
124    pub fn options(mut self, options: Vec<SelectStaticOption>) -> Self {
125        self.options = Some(options);
126        self
127    }
128
129    pub fn confirm(mut self, confirm: InputConfirm) -> Self {
130        self.confirm = Some(confirm);
131        self
132    }
133}
134
135#[cfg(test)]
136mod test {
137    use serde_json::json;
138
139    use crate::card::{
140        components::{
141            content_components::plain_text::PlainText,
142            interactive_components::{
143                multi_select_static::MultiSelectStatic, select_static::SelectStaticOption,
144            },
145        },
146        icon::FeishuCardTextIcon,
147    };
148
149    #[test]
150    fn test_select_static() {
151        let select_static = MultiSelectStatic::new()
152            .r#type("default")
153            .name("multi_select_departments")
154            .required(true)
155            .disabled(false)
156            .placeholder(PlainText::text("默认提示文本"))
157            .width("default")
158            .values(vec![])
159            .options(vec![SelectStaticOption::new("我是交互组件", "selectDemo1")
160                .icon(
161                    FeishuCardTextIcon::new()
162                        .token("chat-forbidden_outlined")
163                        .color("orange")
164                        .img_key("img_v2_38811724"),
165                )
166                .value("selectDemo1")]);
167
168        let json = json!({
169          "tag": "multi_select_static", // 组件标签。
170          "type": "default", // 组件边框样式。默认值 default。
171          "name":"multi_select_departments", // 表单容器中组件的自定义唯一标识,当多选组件内嵌在表单容器时,该属性生效,用于识别用户提交的是哪个组件的数据。
172          "required": true, // 选项是否必填。当多选组件内嵌在表单容器时,该属性可用。其它情况将报错或不生效。
173          "disabled": false, // 选项是否禁用。
174          "placeholder": {
175            // 下拉选择组件内的占位文本。
176            "tag": "plain_text",
177            "content": "默认提示文本"
178          },
179          "width": "default",  // 下拉选择组件的宽度。
180          "selected_values": [], // 选项初始值。数组项的值需要和 options.value 对应。
181          "options": [
182            // 选项配置
183            {
184              "text": {
185                // 选项名称
186                "tag": "plain_text",
187                "content": "我是交互组件"
188              },
189              "icon": {
190                // 添加图标作为选项前缀图标。支持自定义或使用图标库中的图标。
191                "tag": "standard_icon", // 图标类型。
192                "token": "chat-forbidden_outlined", // 图标的 token。仅在 tag 为 standard_icon 时生效。
193                "color": "orange", // 图标颜色。仅在 tag 为 standard_icon 时生效。
194                "img_key": "img_v2_38811724" // 图片的 key。仅在 tag 为 custom_icon 时生效。
195              },
196              "value": "selectDemo1" // 选项回调值,支持 string 类型数据。
197            }
198          ],
199        });
200
201        assert_eq!(serde_json::to_value(&select_static).unwrap(), json);
202    }
203}