open_lark/card/
interactions.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4/// 卡片交互行为类型
5///
6/// 定义卡片组件支持的各种交互行为
7#[derive(Debug, Serialize, Deserialize)]
8#[serde(untagged)]
9pub enum Behaviors {
10    /// 跳转URL行为
11    OpenUrl(OpenUrlBehavior),
12    /// 回调行为
13    Callback(CallbackBehavior),
14    /// 表单行为
15    Form(FormBehavior),
16}
17
18/// 跳转链接交互
19#[derive(Debug, Serialize, Deserialize)]
20pub struct OpenUrlBehavior {
21    /// 声明交互类型。要配置跳转链接交互,取固定值 open_url。
22    r#type: String,
23    /// 兜底跳转地址。
24    default_url: String,
25    /// Android 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
26    #[serde(skip_serializing_if = "Option::is_none")]
27    android_url: Option<String>,
28    /// iOS 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
29    #[serde(skip_serializing_if = "Option::is_none")]
30    ios_url: Option<String>,
31    /// PC 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pc_url: Option<String>,
34}
35
36impl OpenUrlBehavior {
37    pub fn new(default_url: &str) -> Self {
38        Self {
39            r#type: "open_url".to_string(),
40            default_url: default_url.to_string(),
41            android_url: None,
42            ios_url: None,
43            pc_url: None,
44        }
45    }
46
47    pub fn default_url(mut self, url: &str) -> Self {
48        self.default_url = url.to_string();
49        self
50    }
51
52    pub fn android_url(mut self, url: &str) -> Self {
53        self.android_url = Some(url.to_string());
54        self
55    }
56
57    pub fn ios_url(mut self, url: &str) -> Self {
58        self.ios_url = Some(url.to_string());
59        self
60    }
61
62    pub fn pc_url(mut self, url: &str) -> Self {
63        self.pc_url = Some(url.to_string());
64        self
65    }
66}
67
68/// 服务端回传交互
69#[derive(Debug, Serialize, Deserialize)]
70pub struct CallbackBehavior {
71    r#type: String,
72    value: Value,
73}
74
75impl CallbackBehavior {
76    pub fn new(value: Value) -> Self {
77        Self {
78            r#type: "callback".to_string(),
79            value,
80        }
81    }
82}
83
84/// 表单事件交互
85#[derive(Debug, Serialize, Deserialize)]
86pub struct FormBehavior {
87    /// 声明交互类型。要配置表单事件交互,取固定值 form_action。
88    r#type: String,
89    /// 表单事件类型。可取值:
90    ///
91    /// - submit:提交整个表单
92    /// - reset:重置整个表单
93    #[serde(skip_serializing_if = "Option::is_none")]
94    behavior: Option<String>,
95}
96
97impl Default for FormBehavior {
98    fn default() -> Self {
99        Self {
100            r#type: "form_action".to_string(),
101            behavior: None,
102        }
103    }
104}
105
106impl FormBehavior {
107    pub fn new() -> Self {
108        Self::default()
109    }
110
111    pub fn behavior(mut self, behavior: &str) -> Self {
112        self.behavior = Some(behavior.to_string());
113        self
114    }
115}
116
117#[cfg(test)]
118mod test {
119    use serde_json::json;
120
121    use crate::card::interactions::{Behaviors, CallbackBehavior, FormBehavior, OpenUrlBehavior};
122
123    #[test]
124    fn test_open_url() {
125        let jump_behavior = Behaviors::OpenUrl(OpenUrlBehavior::new("xxx"));
126        let json = json!({
127            "type": "open_url",
128            "default_url": "xxx",
129        });
130
131        assert_eq!(serde_json::to_value(&jump_behavior).unwrap(), json)
132    }
133
134    #[test]
135    fn test_callback() {
136        let callback_behavior = Behaviors::Callback(CallbackBehavior::new(json!("hello")));
137        let json = json!({
138            "type": "callback",
139            "value": "hello"
140        });
141
142        assert_eq!(serde_json::to_value(&callback_behavior).unwrap(), json)
143    }
144
145    #[test]
146    fn test_form() {
147        let form_behavior = Behaviors::Form(FormBehavior::new());
148        let json = json!({
149           "type": "form_action",
150        });
151
152        assert_eq!(serde_json::to_value(&form_behavior).unwrap(), json)
153    }
154}