open_lark/card/components/containers/
form.rs

1use serde::{Deserialize, Serialize};
2
3use crate::card::components::{interactive_components::input::InputConfirm, CardElement};
4
5/// 表单容器
6#[derive(Debug, Serialize, Deserialize)]
7pub struct FormContainer {
8    /// 表单容器的标签。固定值为 form。
9    tag: String,
10    /// 表单容器的唯一标识。用于识别用户提交的数据属于哪个表单容器。在同一张卡片内,
11    /// 该字段的值全局唯一。
12    name: String,
13    /// 表单容器的子节点。可内嵌其它容器类组件和展示、交互组件,不支持内嵌表格、图表、
14    /// 和表单容器组件。
15    elements: Vec<CardElement>,
16    /// 按钮的类型。可选值:
17    ///
18    /// - default:黑色字体按钮,有边框
19    /// - primary:蓝色字体按钮,有边框
20    /// - danger:红色字体按钮,有边框
21    /// - text:黑色字体按钮,无边框
22    /// - primary_text:蓝色字体按钮,无边框
23    /// - danger_text:红色字体按钮,无边框
24    /// - primary_filled:蓝底白字按钮
25    /// - danger_filled:红底白字按钮
26    /// - laser:镭射按钮
27    #[serde(skip_serializing_if = "Option::is_none")]
28    r#type: Option<String>,
29    /// 二次确认弹窗配置。指在用户提交时弹出二次确认弹窗提示;只有用户点击确认后,
30    /// 才提交输入的内容。该字段默认提供了确认和取消按钮,你只需要配置弹窗的标题与内容即可。
31    ///
32    /// 注意:confirm 字段仅在用户点击包含提交属性的按钮时才会触发二次确认弹窗。
33    #[serde(skip_serializing_if = "Option::is_none")]
34    confirm: Option<InputConfirm>,
35}
36
37impl Default for FormContainer {
38    fn default() -> Self {
39        FormContainer {
40            tag: "form".to_string(),
41            name: "".to_string(),
42            elements: vec![],
43            r#type: None,
44            confirm: None,
45        }
46    }
47}
48
49impl FormContainer {
50    pub fn new() -> Self {
51        FormContainer::default()
52    }
53
54    pub fn name(mut self, name: &str) -> Self {
55        self.name = name.to_string();
56        self
57    }
58
59    pub fn elements(mut self, elements: Vec<CardElement>) -> Self {
60        self.elements = elements;
61        self
62    }
63
64    pub fn r#type(mut self, r#type: &str) -> Self {
65        self.r#type = Some(r#type.to_string());
66        self
67    }
68
69    pub fn confirm(mut self, confirm: InputConfirm) -> Self {
70        self.confirm = Some(confirm);
71        self
72    }
73}
74
75#[cfg(test)]
76mod test {
77    use serde_json::json;
78
79    use crate::card::components::{
80        content_components::plain_text::PlainText,
81        interactive_components::{button::FeishuCardButton, input::FeishuCardInput},
82        CardElement,
83    };
84
85    use super::*;
86
87    #[test]
88    fn test_form_container() {
89        let form = FormContainer::new().name("form_1").elements(vec![
90            CardElement::InputForm(FeishuCardInput::new().name("reason").required(true)),
91            CardElement::Button(
92                FeishuCardButton::new()
93                    .action_type("form_submit")
94                    .name("submit")
95                    .r#type("primary")
96                    .text(PlainText::text("提交").tag("lark_md")),
97            ),
98        ]);
99
100        let expect = json!( {
101          "tag": "form",    // 表单容器的标签。
102          "name": "form_1", // 该表单容器的唯一标识。用于识别用户在交互后,提交的是哪个表单容器的数据。
103          "elements": [
104            {
105              "tag": "input",   // 为表单容器内添加一个输入框组件。
106              "name": "reason", // 输入框组件的唯一标识。用于识别用户在交互后,提交的是哪个表单项的数据。在表单容器中所有的交互组件中,该字段必填,否则数据会发送失败。
107              "required": true  // 是否必填。为 true 时点击按钮后会做必填校验。
108            },
109            {
110              "tag": "button", // 表单容器内的按钮组件。
111              "action_type": "form_submit", // 将当前按钮与提交事件绑定。用户点击后,将触发表单容器的提交事件,异步提交所有已填写的表单项内容
112              "name": "submit", // 按钮组件的唯一标识,用于识别用户在交互后,点击的是哪个按钮。在表单容器中所有的交互组件中,该字段必填,否则数据会发送失败。
113              "text": { // 按钮上的文本。
114                "content": "提交",
115                "tag": "lark_md"
116              },
117              "type": "primary", // 按钮的样式类型。
118            }
119          ]
120        });
121
122        assert_eq!(json!(form), expect);
123    }
124}