br_plugin/
action.rs

1use std::any::type_name;
2use json::{array, JsonValue, object};
3use crate::{BtnColor, BtnMode, PLUGIN_TOOLS, Response, Tools};
4use crate::model::{ModelTemp};
5
6/// 动作
7pub trait Action {
8    /// 作者
9    fn author(&mut self) -> &'static str {
10        "Blue Rain"
11    }
12    /// 动标题
13    fn title(&mut self) -> &'static str;
14    /// 动作api
15    fn api(&mut self) -> String {
16        let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
17        if t.len() == 3 {
18            // println!("未知的api: {} {}", type_name::<Self>(), self.title());
19            return "".to_string();
20        }
21        let plugin = t[2];
22        let module = t[3];
23        let action = t[4];
24        format!("{plugin}.{module}.{action}")
25    }
26
27    /// 支持模式
28    /// org 企业模式
29    /// admin 平台模式
30    /// user 普通模式
31    fn mode(&mut self) -> Vec<&'static str> {
32        vec![]
33    }
34    /// 菜单 icon
35    fn icon(&mut self) -> &'static str { "" }
36
37    /// 菜单排序
38    fn menu_sort(&mut self) -> usize { 0 }
39
40    /// 是否开放接口
41    fn openapi(&mut self) -> bool { false }
42
43    /// 是否使用密钥
44    fn token(&mut self) -> bool { true }
45    /// API描述
46    fn describe(&mut self) -> &'static str { "" }
47    /// 是否公开
48    fn public(&mut self) -> bool { true }
49    /// 是否权限组显示
50    fn auth(&mut self) -> bool { true }
51    /// 接口类型 btn api menu
52    fn interface_type(&mut self) -> InterfaceType {
53        InterfaceType::Api
54    }
55    /// 依赖接口
56    fn dependent(&mut self) -> Vec<&'static str> {
57        vec![]
58    }
59    /// 请求参数入口
60    fn params(&mut self) -> JsonValue { object! {} }
61    /// 检测
62    fn _check(&mut self, mut request: JsonValue) -> (bool, String, JsonValue) {
63        let params = self.params();
64
65        let mut new_request = object! {};
66        for (key, field) in params.entries() {
67            match field["require"].as_bool().unwrap() {
68                true => {
69                    if request[key].is_null() && !field["def"].is_empty() {
70                        request[key] = field["def"].clone();
71                    }
72                    if request[key].is_null() {
73                        return (false, format!("缺少参数 {}: {}\r\n错误API: {}", key, field["title"], self.api()), request);
74                    }
75                    if request[key].is_string() && request[key].is_empty() {
76                        return (false, format!("请填写【{}】内容\r\n错误API: {}", field["title"], self.api()), request);
77                    }
78                }
79                false => {
80                    if request[key].is_null() {
81                        request[key] = field["def"].clone();
82                    }
83                    match field["mode"].as_str().unwrap() {
84                        "switch" => {
85                            if request[key].is_empty() {
86                                request[key] = field["def"].clone();
87                            }
88                        }
89                        _ => {
90                            if request[key].is_empty() || request[key].is_empty() {
91                                request[key] = field["def"].clone();
92                            }
93                        }
94                    }
95                    if request[key] == *"null" {
96                        request[key] = field["def"].clone();
97                    }
98                }
99            }
100            new_request[key] = request[key].clone();
101        }
102        (true, "验证通过".to_string(), new_request)
103    }
104    /// 执行参数入口
105    fn run(&mut self, header: JsonValue, request: JsonValue) -> Response {
106        let (state, msg, request) = self._check(request.clone());
107        if !state {
108            return self.fail(&msg);
109        }
110        self.index(header.clone(), request.clone())
111    }
112    /// 执行参数入口
113    fn get(&mut self, header: JsonValue, request: JsonValue) -> Result<JsonValue, String> {
114        let (state, msg, request) = self._check(request.clone());
115        if !state {
116            let re = self.fail(&msg);
117            return Err(re.get_data_msg());
118        }
119        let t = self.index(header.clone(), request.clone());
120        if t.clone().get_data_code() != 0 {
121            return Err(t.clone().get_data_msg());
122        }
123        Ok(t.get_data_data())
124    }
125
126    fn index(&mut self, header: JsonValue, request: JsonValue) -> Response;
127    /// 业务成功返回
128    fn success(&mut self, data: JsonValue, msg: &str) -> Response {
129        Response::success(data, msg).clone()
130    }
131    /// 业务错误返回
132    fn fail(&mut self, msg: &str) -> Response {
133        Response::fail(msg).clone()
134    }
135    /// 业务错误返回
136    fn error(&mut self, code: usize, msg: String) -> Response {
137        Response::error(code, msg).clone()
138    }
139    fn notify(&mut self, msg: &str, btn_name: &str, path: &str) -> Response {
140        Response::notify(msg, btn_name, path).clone()
141    }
142    /// 登陆返回
143    fn login(&mut self, msg: &str) -> Response {
144        Response::login(msg).clone()
145    }
146    /// 下载返回
147    fn download(&mut self, filename: &str) -> Response {
148        Response::download(filename).clone()
149    }
150    /// 下载并删除文件所在目录
151    fn download_delete_dir(&mut self, filename: &str) -> Response {
152        Response::download_delete_dir(filename).clone()
153    }
154    /// 重定型返回
155    fn redirect(&mut self, url: &str) -> Response {
156        Response::redirect(url).clone()
157    }
158    /// 获取工具集合
159    fn tools(&mut self) -> Tools {
160        PLUGIN_TOOLS.lock().unwrap().get("tools").unwrap().clone()
161    }
162    /// 获取菜单信息
163    /// * title 菜单名称
164    fn menu_info(&mut self, title: &str) -> JsonValue {
165        let api = self.api();
166        let apis: Vec<&str> = api.split(".").collect();
167        let info = object! {
168            title:if title.is_empty() {self.title()}else{title},
169            api:self.api(),
170            addon:apis[0],
171            model:apis[1],
172            action:apis[2],
173            icon:self.icon(),
174            path:format!("/{}",self.api().replace(".","/")),
175            interface_type:self.interface_type().str()
176        };
177        info
178    }
179    fn btn_info_data(&mut self, title: &str) -> JsonValue {
180        let mut params = array![];
181        for (_field, item) in self.params().entries() {
182            params.push(item.clone()).unwrap();
183        }
184        let api = self.api();
185        let apis: Vec<&str> = api.split(".").collect();
186        let info = object! {
187            title:if title.is_empty() {self.title()}else{title},
188            api:self.api(),
189            addon:apis[0],
190            model:apis[1],
191            action:apis[2],
192            icon:self.icon(),
193            path:format!("/{}",self.api().replace(".","/")),
194            params:params,
195            interface_type:self.interface_type().str()
196        };
197        info
198    }
199    /// 获取按钮信息
200    /// * title 菜单名称
201    /// * mode 按钮模式
202    /// * color 按钮颜色
203    /// * match_condition 显示条件
204    fn btn_info(&mut self, title: &str, mode: BtnMode, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
205        let mut btn = object! {};
206        if title.is_empty() {
207            btn["title"] = self.title().into();
208        } else {
209            btn["title"] = title.into();
210        }
211        btn["api"] = self.api().into();
212        let mut params = array![];
213        for (_, item) in self.params().entries() {
214            params.push(item.clone()).unwrap();
215        }
216        btn["params"] = params;
217        btn["color"] = JsonValue::from(color.from());
218        btn["icon"] = JsonValue::from(self.icon());
219        btn["mode"] = JsonValue::from(mode.from());
220        btn["match_condition"] = match_condition.into();
221        if btn["mode"].as_str().unwrap()=="form_custom" {
222            btn["path"] = format!("/{}", self.api().replace(".", "/")).into();
223        }
224        btn
225    }
226    /// 获取跳转按钮信息
227    /// * title 菜单名称
228    /// * mode 按钮模式
229    /// * color 按钮颜色
230    /// * match_condition 显示条件
231    fn btn_info_to(&mut self, title: &str, path: &str, mode: BtnMode, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
232        let mut btn = object! {};
233        if title.is_empty() {
234            btn["title"] = self.title().into();
235        } else {
236            btn["title"] = title.into();
237        }
238        btn["api"] = self.api().into();
239        let mut params = array![];
240        for (_, item) in self.params().entries() {
241            params.push(item.clone()).unwrap();
242        }
243        if path.is_empty() {
244            btn["path"] = format!("/{}", self.api().replace(".", "/")).into();
245        } else {
246            btn["path"] = JsonValue::from(path);
247        }
248        btn["params"] = params;
249        btn["color"] = JsonValue::from(color.from());
250        btn["mode"] = JsonValue::from(mode.from());
251        btn["match_condition"] = match_condition.into();
252        btn
253    }
254    /// 获取自定义页面按钮信息
255    /// * title 菜单名称
256    /// * mode 按钮模式
257    /// * color 按钮颜色
258    /// * match_condition 显示条件
259    fn btn_custom_info(&mut self, title: &str) -> JsonValue {
260        let mut btn = object! {};
261        if title.is_empty() {
262            btn["title"] = self.title().into();
263        } else {
264            btn["title"] = title.into();
265        }
266        btn["api"] = self.api().into();
267        let mut params = array![];
268        for (_, item) in self.params().entries() {
269            params.push(item.clone()).unwrap();
270        }
271        btn["params"] = params;
272        btn["auth"] = self.auth().into();
273        btn
274    }
275}
276
277
278/// 模型模版
279pub struct ActionTemp {
280    pub model: ModelTemp,
281}
282
283impl Action for ActionTemp {
284    fn title(&mut self) -> &'static str {
285        "测试api"
286    }
287    fn index(&mut self, _header: JsonValue, _request: JsonValue) -> Response {
288        self.fail("无效API")
289    }
290}
291
292pub enum InterfaceType {
293    Api,
294    Btn,
295    Menu,
296}
297
298impl InterfaceType {
299    pub fn str(self) -> &'static str {
300        match self {
301            InterfaceType::Api => "api",
302            InterfaceType::Btn => "btn",
303            InterfaceType::Menu => "menu"
304        }
305    }
306}