br_addon/
action.rs

1use crate::request::{ContentType, Method, Request};
2use crate::{CONFIG, GLOBAL_DATA, PLUGIN_TOOLS};
3use crate::{ApiResponse, Tools};
4use br_fields::Field;
5use json::{array, object, JsonValue};
6use std::any::type_name;
7use std::collections::HashMap;
8
9/// 功能接口
10pub trait Action {
11    /// 功能名称
12    fn _name(&self) -> String {
13        type_name::<Self>().rsplit("::").next().unwrap().to_lowercase()
14    }
15    /// 模块名称
16    fn module_name(&self) -> String {
17        let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
18        let plugin = t[2].to_lowercase();
19        let module = t[3].to_lowercase();
20        format!("{plugin}.{module}")
21    }
22    /// 插件名称
23    fn addon_name(&self) -> String {
24        let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
25        t[2].to_lowercase()
26    }
27    /// API 名称
28    fn api(&self) -> String {
29        let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
30        let plugin = t[2].to_lowercase();
31        let module = t[3].to_lowercase();
32        let action = t[4].to_lowercase();
33        format!("{plugin}.{module}.{action}")
34    }
35    /// 是否需要密钥
36    fn token(&self) -> bool {
37        true
38    }
39
40    fn sort(&self) -> usize {
41        99
42    }
43    /// 功能标题
44    fn title(&self) -> &'static str;
45    /// 功能描述
46    fn description(&self) -> &'static str {
47        ""
48    }
49    /// 请求地址路径
50    fn path(&self) -> &'static str {
51        ""
52    }
53    /// 请求地址参数
54    fn query(&self) -> JsonValue {
55        object! {}
56    }
57    /// 标签范围
58    fn tags(&self) -> &'static [&'static str] {
59        &[]
60    }
61    fn icon(&self) -> &'static str {
62        ""
63    }
64    /// 是否公开
65    fn public(&self) -> bool {
66        true
67    }
68    /// 是否权限组显示
69    fn auth(&self) -> bool {
70        true
71    }
72    /// 接口类型 btn api menu
73    fn interface_type(&self) -> InterfaceType {
74        InterfaceType::API
75    }
76    /// 允许的请求类型
77    fn method(&mut self) -> Method {
78        Method::Post
79    }
80    /// 请求类型
81    fn content_type(&mut self) -> ContentType {
82        ContentType::Json
83    }
84    /// 是否检查参数
85    fn params_check(&mut self) -> bool {
86        true
87    }
88    /// 请求body参数
89    fn params(&mut self) -> JsonValue {
90        object! {}
91    }
92    /// 成功响应
93    fn success(&mut self) -> ApiResponse {
94        let mut data = object! {};
95        data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0).example(0.into()).swagger();
96        data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "").example("成功".into()).swagger();
97        data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
98        data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true).example(true.into()).swagger();
99        data["timestamp"] = br_fields::datetime::Timestamp::new(true, "timestamp", "时间戳", 0, 0.0).swagger();
100        ApiResponse::success(data, "请求成功")
101    }
102    /// 失败响应
103    fn error(&mut self) -> ApiResponse {
104        let mut data = object! {};
105        data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000).example(1000.into()).swagger();
106        data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "").example("失败".into()).swagger();
107        data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
108        data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false).example(false.into()).swagger();
109        data["timestamp"] = br_fields::datetime::Timestamp::new(true, "timestamp", "时间戳", 0, 0.0).swagger();
110        ApiResponse::error(data, "请求失败")
111    }
112    /// 外部入口
113    fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
114        if self.public() && !self.method().str().is_empty() && self.method().str().to_lowercase() != request.method.str().to_lowercase() {
115            return Err(ApiResponse::fail(
116                -1,
117                format!(
118                    "Request type error: Actual [{}] Expected [{}]",
119                    request.method.str(),
120                    self.method().str()
121                ).as_str(),
122            ));
123        }
124        let params = self.params().clone();
125        if self.params_check() {
126            self.check(&mut request.query.clone(), self.query().clone())?;
127            self.check(&mut request.body, params)?;
128        }
129        let res = self.index(request.clone());
130        match res.success {
131            true => Ok(res),
132            false => Err(res),
133        }
134    }
135    /// 入参验证
136    fn check(&mut self, request: &mut JsonValue, params: JsonValue) -> Result<(), ApiResponse> {
137        let req = request.clone();
138        for (name, _) in req.entries() {
139            if !params.has_key(name) {
140                request.remove(name);
141            }
142        }
143        for (name, field) in params.entries() {
144            let require = field["require"].as_bool().unwrap_or(false);
145            let title = field["title"].as_str().unwrap_or("");
146            if request.has_key(name) {
147                // 判断输入类型
148                match field["mode"].as_str().unwrap() {
149                    "key" => {
150                        if !request[name].is_string() {
151                            return Err(ApiResponse::fail(
152                                900_001,
153                                format!(
154                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
155                                    name, field["mode"]
156                                ).as_str(),
157                            ));
158                        }
159                        if require && request[name].is_empty() {
160                            return Err(ApiResponse::fail(
161                                900014,
162                                format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
163                            ));
164                        }
165                    }
166                    "text" | "table" | "tree" => {
167                        if !request[name].is_string() {
168                            return Err(ApiResponse::fail(
169                                900002,
170                                format!(
171                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
172                                    name, field["mode"]
173                                ).as_str(),
174                            ));
175                        }
176                        if require && request[name].is_empty() {
177                            return Err(ApiResponse::fail(
178                                900002,
179                                format!("{title} 必填").as_str(),
180                            ));
181                        }
182                    }
183                    "file" => {
184                        if !request[name].is_array() && !request[name].is_string() {
185                            return Err(ApiResponse::fail(
186                                900003,
187                                format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
188                            ));
189                        }
190                        if require && request[name].is_empty() {
191                            return Err(ApiResponse::fail(
192                                900002,
193                                format!("{title} 必填").as_str(),
194                            ));
195                        }
196                    }
197                    "int" => {
198                        if require && request[name].to_string().is_empty() {
199                            return Err(ApiResponse::fail(
200                                900_002,
201                                format!("{title} 必填").as_str(),
202                            ));
203                        }
204                        if !request[name].to_string().is_empty() {
205                            match request[name].to_string().parse::<i64>() {
206                                Ok(_) => {}
207                                Err(_) => {
208                                    return Err(ApiResponse::fail(
209                                        900013,
210                                        format!(
211                                            "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
212                                            name, field["mode"]
213                                        ).as_str(),
214                                    ));
215                                }
216                            }
217                        }
218                    }
219                    "timestamp" => {
220                        if require && request[name].to_string().is_empty() {
221                            return Err(ApiResponse::fail(
222                                900002,
223                                format!("{title} 必填").as_str(),
224                            ));
225                        }
226                        if !request[name].to_string().is_empty() {
227                            if request[name].is_array() && request[name].len() == 2 {
228                                // 如果是数组,遍历每个元素
229                                for item in request[name].members() {
230                                    match item.to_string().parse::<f64>() {
231                                        Ok(_) => {}
232                                        Err(_) => {
233                                            return Err(ApiResponse::fail(
234                                                900_013,
235                                                format!(
236                                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
237                                                    name, field["mode"]
238                                                ).as_str(),
239                                            ));
240                                        }
241                                    }
242                                }
243                            } else {
244                                match request[name].to_string().parse::<f64>() {
245                                    Ok(_) => {}
246                                    Err(_) => {
247                                        return Err(ApiResponse::fail(
248                                            900013,
249                                            format!(
250                                                "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
251                                                name, field["mode"]
252                                            ).as_str(),
253                                        ));
254                                    }
255                                }
256                            }
257                        }
258                    }
259                    "float" => {
260                        if require && request[name].to_string().is_empty() {
261                            return Err(ApiResponse::fail(
262                                900002,
263                                format!("{title} 必填").as_str(),
264                            ));
265                        }
266                        if !request[name].to_string().is_empty() {
267                            match request[name].to_string().parse::<f64>() {
268                                Ok(_) => {}
269                                Err(_) => {
270                                    return Err(ApiResponse::fail(
271                                        900023,
272                                        format!(
273                                            "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
274                                            name, field["mode"]
275                                        ).as_str(),
276                                    ));
277                                }
278                            }
279                        }
280                    }
281                    "string" | "time" | "code" | "pass" | "email" | "location" | "color" | "date" | "barcode" | "datetime" | "editor" | "tel" => {
282                        if !request[name].is_string() {
283                            return Err(ApiResponse::fail(
284                                -1,
285                                format!(
286                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
287                                    name, field["mode"]
288                                ).as_str(),
289                            ));
290                        }
291                        if require && request[name].is_empty() {
292                            return Err(ApiResponse::fail(
293                                900004,
294                                format!("{title} 必填").as_str(),
295                            ));
296                        }
297                    }
298                    "dict" => {
299                        if require && request[name].is_empty() {
300                            return Err(ApiResponse::fail(
301                                900005,
302                                format!("{title} 必填").as_str(),
303                            ));
304                        }
305                    }
306                    "switch" => {
307                        match request[name].to_string().parse::<bool>() {
308                            Ok(e) => {
309                                request[name] = e.into();
310                            }
311                            Err(_) => {
312                                return Err(ApiResponse::fail(
313                                    -1,
314                                    format!("请求参数数据类型错误: 参数 [{name}] 数据类型应为[{}]", field["mode"]).as_str(),
315                                ));
316                            }
317                        }
318                    }
319                    "select" => {
320                        if !request[name].is_array() && !request[name].is_string() {
321                            return Err(ApiResponse::fail(
322                                -1,
323                                format!(
324                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
325                                    name, field["mode"]
326                                ).as_str(),
327                            ));
328                        }
329                        let value = if request[name].is_array() {
330                            request[name].members().map(|m| m.to_string()).collect::<Vec<String>>()
331                        } else {
332                            request[name].to_string().split(",").map(|x| x.to_string()).collect::<Vec<String>>()
333                        };
334                        let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>();
335
336                        let require = field["require"].as_bool().unwrap();
337                        for item in value.clone() {
338                            if !option.contains(&&*item.clone()) && (item.is_empty() && require) {
339                                let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
340                                return Err(ApiResponse::fail(-1, format!("请求参数选项错误: 参数 [{item}] 数据类型应为[{option}]之内").as_str()));
341                            }
342                        }
343                        request[name] = value.into();
344                    }
345                    "radio" => {
346                        if !request[name].is_string() {
347                            return Err(ApiResponse::fail(
348                                -1,
349                                format!(
350                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
351                                    name, field["mode"], request[name]
352                                ).as_str(),
353                            ));
354                        }
355                        let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
356                        if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
357                        {
358                            return Err(ApiResponse::fail(
359                                -1,
360                                format!(
361                                    "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
362                                    name, request[name], option
363                                ).as_str(),
364                            ));
365                        }
366                    }
367                    "array" | "polygon" => {
368                        if !request[name].is_array() {
369                            return Err(ApiResponse::fail(
370                                900_009,
371                                format!(
372                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
373                                    name, field["mode"]
374                                ).as_str(),
375                            ));
376                        }
377                        if require && request[name].is_empty() {
378                            return Err(ApiResponse::fail(
379                                900010,
380                                format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
381                            ));
382                        }
383                    }
384                    "object" => {
385                        if !request[name].is_object() {
386                            return Err(ApiResponse::fail(
387                                900009,
388                                format!(
389                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
390                                    name, field["mode"]
391                                ).as_str(),
392                            ));
393                        }
394                        if require && request[name].is_empty() {
395                            return Err(ApiResponse::fail(
396                                900006,
397                                format!("{title} 必填").as_str(),
398                            ));
399                        }
400                    }
401                    _ => {
402                        println!("检查未知类型: {}", field["mode"])
403                    }
404                }
405            } else {
406                if require {
407                    return Err(ApiResponse::fail(
408                        900007,
409                        format!("{title} 必填").as_str(),
410                    ));
411                }
412                request[name] = field["def"].clone();
413            }
414        }
415        Ok(())
416    }
417    /// 内部入口
418    fn index(&mut self, request: Request) -> ApiResponse;
419    /// 表单查询
420    fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
421        params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
422        params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
423        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
424        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
425        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
426        params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
427        params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 50, "id").example("id".into()).field();
428        params
429    }
430    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
431    fn table_select(
432        &mut self,
433        request: JsonValue,
434        table_name: &str,
435        fields: Vec<&str>,
436    ) -> JsonValue {
437        let page = request["page"].as_i32().unwrap_or(1);
438        let limit = request["limit"].as_i32().unwrap_or(10);
439
440        let search = request["search"].as_str().unwrap_or("");
441
442        let field_id = request["field"].as_str().unwrap_or("id");
443
444        let where_or = request["where_or"].clone();
445        let where_and = request["where_and"].clone();
446
447        let mut tools = self.tools();
448        let db = tools.db.table(table_name);
449
450        if !search.is_empty() {
451            db.where_and(&fields.join("|"), "like", format!("%{search}%").into());
452        }
453
454        for (key, value) in where_or.entries() {
455            if value.is_empty() {
456                continue;
457            }
458            if value.is_array() {
459                db.where_or(key, "between", value.clone());
460                db.where_or(key, "in", value.clone());
461            } else if value.is_boolean() {
462                db.where_or(key, "=", value.clone());
463            } else {
464                db.where_or(key, "like", format!("%{value}%").into());
465            }
466        }
467
468        for value in where_and.members() {
469            db.where_and(
470                value[0].as_str().unwrap(),
471                value[1].as_str().unwrap(),
472                value[2].clone(),
473            );
474        }
475
476        let total = (db.clone().count().as_f64().unwrap() / f64::from(limit)).ceil() as i64;
477        let mut db_list = db.clone();
478
479        db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
480
481        let mut data = db_list.page(page, limit).select();
482        let mut list = array![];
483        for item in data.members_mut() {
484            let value = item[field_id].clone();
485            item.remove(field_id);
486
487            let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
488
489            list.push(object! {
490                value: value,
491                label: label.join(" | ").clone(),
492            }).unwrap();
493        }
494        object! {
495            total:total,
496            data:list,
497        }
498    }
499    /// 树形查询
500    fn params_table_tree_select(&mut self, mut params: JsonValue) -> JsonValue {
501        params["ids"] = br_fields::text::Array::new(false, "ids", "加载已选中数据", array![]).field();
502        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
503        params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 20, "").example("".into()).field();
504        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
505        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
506        params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
507        params
508    }
509    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
510    fn table_tree_select(
511        &mut self,
512        request: JsonValue,
513        table_name: &str,
514        pid_field: &str,
515        label_field: &str,
516        fields: Vec<&str>,
517    ) -> JsonValue {
518        let ids = request["ids"].clone();
519        let search = request["search"].as_str().unwrap_or("");
520        let pid_id = request["pid"].as_str().unwrap_or("id");
521
522        let where_or = request["where_or"].clone();
523        let where_and = request["where_and"].clone();
524
525        let mut tools = self.tools();
526        let db = tools.db.table(table_name);
527
528        db.where_and(pid_field, "=", pid_id.into());
529
530        if !search.is_empty() {
531            db.where_and("id", "in", search.into());
532        }
533
534        for (key, value) in where_or.entries() {
535            if value.is_empty() {
536                continue;
537            }
538            if value.is_array() {
539                db.where_or(key, "between", value.clone());
540                db.where_or(key, "in", value.clone());
541            } else if value.is_boolean() {
542                db.where_or(key, "=", value.clone());
543            } else {
544                db.where_or(key, "like", format!("%{value}%").into());
545            }
546        }
547
548        for value in where_and.members() {
549            db.where_and(
550                value[0].as_str().unwrap(),
551                value[1].as_str().unwrap(),
552                value[2].clone(),
553            );
554        }
555
556        db.field(format!("id,{},{}", pid_field, fields.join(",")).as_str());
557
558        let mut data = db.select();
559        for item in data.members_mut() {
560            let children = self.tools().db.table(table_name).where_and(pid_field, "=", item["id"].clone()).select();
561            if children.is_empty() {
562                item["lazy"] = false.into();
563            } else {
564                item["lazy"] = true.into();
565            }
566        }
567
568        let ids_list = if ids.is_empty() {
569            vec![]
570        } else {
571            let list = self.tools().db.table(table_name).where_and("id", "in", ids).field(format!("id,{},{}", pid_field, fields.join(",")).as_str()).select();
572            let mut t = vec![];
573            for item in list.members() {
574                let mut v = vec![];
575                let mut pid = item[pid_field].to_string();
576                v.push(item[label_field].to_string());
577                loop {
578                    if pid.is_empty() {
579                        break;
580                    }
581                    let find = self.tools().db.table(table_name).where_and("id", "=", pid.into()).field(format!("id,{},{}", pid_field, fields.join(",")).as_str()).find();
582                    pid = find[pid_field].to_string();
583                    v.push(find[label_field].to_string());
584                }
585                v.reverse();
586                t.push(object! {
587                    id:item["id"].clone(),
588                    label:v.join("/"),
589                });
590            }
591            t
592        };
593
594
595        object! {
596            data:data,
597            label_field:label_field,
598            pid_field:pid_field,
599            ids:ids_list.clone()
600
601        }
602    }
603    /// 菜单表格接收参数
604    fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
605        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
606        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
607        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
608        params
609    }
610    #[allow(clippy::too_many_arguments)]
611    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
612    fn table_menu(
613        &mut self,
614        request: JsonValue,
615        table_name: &str,
616        label_field: &str,
617        fields: JsonValue,
618
619        hidd_field: Vec<&str>,
620        show_field: Vec<&str>,
621
622        search_fields: Vec<&str>,
623        _filter_fields: Vec<&str>,
624    ) -> JsonValue {
625        let search = request["search"].as_str().unwrap_or("");
626
627        let order = request["order"].clone();
628        let where_or = request["where_or"].clone();
629        let where_and = request["where_and"].clone();
630        let mut columns = array![];
631        let mut search_name = vec![];
632        let mut search_field = vec![];
633        let mut filter_columns = vec![];
634        let mut table_fields = object! {};
635        let mut table_field_json = vec![];
636
637        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
638        alls_field.retain(|x| !hidd_field.contains(x));
639        if !show_field.is_empty() {
640            alls_field.retain(|x| show_field.contains(x) || *x == "id");
641        }
642
643        for item in alls_field.iter() {
644            let row = &fields[item.to_string()];
645            let field = row["field"].to_string();
646            let title = row["title"].to_string();
647            let mode = row["mode"].to_string();
648
649            if search_fields.contains(&field.as_str()) {
650                search_name.push(title);
651                search_field.push(field.clone());
652            }
653            filter_columns.push(self.filter_column(row.clone()));
654            columns.push(self.table_column(row.clone())).unwrap();
655            let mut table_field_info = object! {};
656            match mode.as_str() {
657                "table" => table_field_info = row.clone(),
658                "array" => table_field_json.push(field.clone()),
659                _ => {}
660            }
661            if !table_field_info.is_empty() {
662                table_fields[field.as_str()] = table_field_info;
663            }
664        }
665
666        let mut tools = self.tools();
667        let db = tools.db.table(table_name);
668
669        if !search.is_empty() {
670            db.where_and(
671                &search_field.join("|"),
672                "like",
673                format!("%{search}%").into(),
674            );
675        }
676
677        for (key, value) in where_or.entries() {
678            if value.is_empty() {
679                continue;
680            }
681            if value.is_array() {
682                db.where_or(key, "between", value.clone());
683                db.where_or(key, "in", value.clone());
684            } else if value.is_boolean() {
685                db.where_or(key, "=", value.clone());
686            } else {
687                db.where_or(key, "like", format!("%{value}%").into());
688            }
689        }
690
691        for value in where_and.members() {
692            db.where_and(
693                value[0].as_str().unwrap(),
694                value[1].as_str().unwrap(),
695                value[2].clone(),
696            );
697        }
698
699        let mut db_list = db.clone();
700
701        for item in order.members() {
702            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
703        }
704
705        let t = alls_field.join(",");
706        db_list.field(t.as_str());
707
708        if !table_field_json.is_empty() {
709            db_list.json(&table_field_json.join(","));
710        }
711
712        let mut data = db_list.select();
713
714        let mut table_datas = object! {};
715        let mut ids = HashMap::new();
716
717        for item in data.members_mut() {
718            for (field, _) in table_fields.entries() {
719                if table_datas[field].is_empty() {
720                    table_datas[field] = array![];
721                }
722                let _ = table_datas[field].push(item[field].clone());
723            }
724        }
725        for (field, info) in table_fields.entries_mut() {
726            let _ = info["fields"].push("id");
727            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
728            let table_name = info["table"].clone();
729            let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
730
731            for item in data_list.members_mut() {
732                let id = item["id"].as_str().unwrap_or("").to_string();
733                item.remove("id");
734                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
735                ids.insert(
736                    id.clone(),
737                    object! {
738                        value: id.clone(),
739                        label:label.join(" | ").clone(),
740                    },
741                );
742            }
743        }
744
745        for item in data.members_mut() {
746            for (field, _) in table_fields.entries() {
747                if item[field].is_empty() {
748                    continue;
749                }
750                item[field] = ids[item[field].as_str().unwrap()].clone();
751            }
752        }
753
754        object! {
755            data:data,
756            columns:columns,
757            search_name:search_name.join("/"),
758            filter_columns:filter_columns,
759            label_field:label_field,
760            btn_all:array![],
761            btn_api:array![]
762        }
763    }
764    /// 树型表格接收参数
765    fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
766        params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
767        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
768        params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
769        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
770        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
771        params
772    }
773    #[allow(clippy::too_many_arguments)]
774    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
775    fn table_tree(
776        &mut self,
777        request: JsonValue,
778        table_name: &str,
779        pid_field: &str,
780        label_field: &str,
781        fields: JsonValue,
782        hidd_field: Vec<&str>,
783        show_field: Vec<&str>,
784        search_fields: Vec<&str>,
785        _filter_fields: Vec<&str>,
786    ) -> JsonValue {
787        let search = request["search"].as_str().unwrap_or("");
788
789        let pid = request["pid"].clone();
790
791        let order = request["order"].clone();
792        let where_or = request["where_or"].clone();
793        let where_and = request["where_and"].clone();
794        let mut columns = array![];
795        let mut search_name = vec![];
796        let mut search_field = vec![];
797        let mut filter_columns = vec![];
798        let mut table_field_json = vec![];
799        let mut table_fields = object! {};
800
801        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
802        alls_field.retain(|x| !hidd_field.contains(x));
803        if !show_field.is_empty() {
804            alls_field.retain(|x| show_field.contains(x) || *x == "id");
805        }
806
807        for item in alls_field.iter() {
808            let row = fields[item.to_string()].clone();
809            let field = row["field"].to_string();
810            let title = row["title"].to_string();
811            let mode = row["mode"].to_string();
812
813            if search_fields.contains(&field.as_str()) {
814                search_name.push(title);
815                search_field.push(field.clone());
816            }
817            filter_columns.push(self.filter_column(row.clone()));
818            columns.push(self.table_column(row.clone())).unwrap();
819            let mut table_field_info = object! {};
820            match mode.as_str() {
821                "table" => table_field_info = row.clone(),
822                "array" => table_field_json.push(field.clone()),
823                _ => {}
824            }
825            if !table_field_info.is_empty() {
826                table_fields[field.as_str()] = table_field_info;
827            }
828        }
829
830        let mut tools = self.tools();
831        let db = tools.db.table(table_name);
832        db.where_and(pid_field, "=", pid);
833        if !search.is_empty() {
834            db.where_and(
835                &search_field.join("|"),
836                "like",
837                format!("%{search}%").into(),
838            );
839        }
840
841        for (key, value) in where_or.entries() {
842            if value.is_empty() {
843                continue;
844            }
845            if value.is_array() {
846                // db.where_or(key, "between", value.clone());
847                db.where_or(key, "in", value.clone());
848            } else if value.is_boolean() {
849                db.where_or(key, "=", value.clone());
850            } else {
851                db.where_or(key, "like", format!("%{value}%").into());
852            }
853        }
854
855        for value in where_and.members() {
856            db.where_and(
857                value[0].as_str().unwrap(),
858                value[1].as_str().unwrap(),
859                value[2].clone(),
860            );
861        }
862
863        let mut db_list = db.clone();
864
865        for item in order.members() {
866            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
867        }
868        let t = alls_field.join(",");
869        db_list.field(t.as_str());
870        if !table_field_json.is_empty() {
871            db_list.json(&table_field_json.join(","));
872        }
873        let mut data = db_list.select();
874
875        let mut table_datas = object! {};
876        let mut ids = HashMap::new();
877
878        for item in data.members_mut() {
879            for (field, _) in table_fields.entries() {
880                if table_datas[field].is_empty() {
881                    table_datas[field] = array![];
882                }
883                let _ = table_datas[field].push(item[field].clone());
884            }
885        }
886        for (field, info) in table_fields.entries_mut() {
887            let _ = info["fields"].push("id");
888            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
889            let table_name = info["table"].clone();
890            let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
891
892            for item in data_list.members_mut() {
893                let id = item["id"].as_str().unwrap_or("").to_string();
894                item.remove("id");
895                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
896                ids.insert(
897                    id.clone(),
898                    object! {
899                        value: id.clone(),
900                        label:label.join(" | ").clone(),
901                    },
902                );
903            }
904        }
905
906        let mut list = array![];
907        for item in data.members_mut() {
908            for (field, _) in table_fields.entries() {
909                if item[field].is_empty() {
910                    continue;
911                }
912                item[field] = ids[item[field].as_str().unwrap()].clone();
913            }
914            let _ = list.push(object! {
915                id:item["id"].as_str().unwrap(),
916                code:item["code"].as_str().unwrap(),
917                label:item[label_field].as_str().unwrap(),
918                data:item.clone(),
919            });
920        }
921
922        object! {
923            data:list,
924            columns:columns,
925            search_name:search_name.join("/"),
926            filter_columns:filter_columns,
927            pid_field:pid_field,
928            btn_all:array![],
929            btn_api:array![]
930        }
931    }
932
933    #[allow(clippy::too_many_arguments)]
934    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
935    /// 树形表单
936    fn tree(&mut self, request: JsonValue, table_name: &str, pid_field: &str, label: &str, fields: JsonValue, hidd_field: Vec<&str>, show_field: Vec<&str>, search_fields: Vec<&str>, _filter_fields: Vec<&str>) -> JsonValue {
937        let search = request["search"].as_str().unwrap_or("");
938
939        let pid = request["pid"].clone();
940        let order = request["order"].clone();
941        let where_or = request["where_or"].clone();
942        let where_and = request["where_and"].clone();
943        let mut columns = array![];
944        let mut search_name = vec![];
945        let mut search_field = vec![];
946        let mut filter_columns = vec![];
947        let mut table_field_json = vec![];
948        let mut table_fields = object! {};
949
950        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
951        alls_field.retain(|x| !hidd_field.contains(x));
952        if !show_field.is_empty() {
953            alls_field.retain(|x| show_field.contains(x) || *x == "id");
954        }
955
956        for item in alls_field.iter() {
957            let row = fields[item.to_string()].clone();
958            let field = row["field"].to_string();
959            let title = row["title"].to_string();
960            let mode = row["mode"].to_string();
961
962            if search_fields.contains(&field.as_str()) {
963                search_name.push(title);
964                search_field.push(field.clone());
965            }
966            filter_columns.push(self.filter_column(row.clone()));
967            columns.push(self.table_column(row.clone())).unwrap();
968            let mut table_field_info = object! {};
969            match mode.as_str() {
970                "table" => table_field_info = row.clone(),
971                "array" => table_field_json.push(field.clone()),
972                _ => {}
973            }
974            if !table_field_info.is_empty() {
975                table_fields[field.as_str()] = table_field_info;
976            }
977        }
978
979        let mut tools = self.tools();
980        let db = tools.db.table(table_name);
981        db.where_and(pid_field, "=", pid);
982        if !search.is_empty() {
983            db.where_and(
984                &search_field.join("|"),
985                "like",
986                format!("%{search}%").into(),
987            );
988        }
989
990        for (key, value) in where_or.entries() {
991            if value.is_empty() {
992                continue;
993            }
994            if value.is_array() {
995                db.where_or(key, "in", value.clone());
996            } else if value.is_boolean() {
997                db.where_or(key, "=", value.clone());
998            } else {
999                db.where_or(key, "like", format!("%{value}%").into());
1000            }
1001        }
1002
1003        for value in where_and.members() {
1004            db.where_and(
1005                value[0].as_str().unwrap(),
1006                value[1].as_str().unwrap(),
1007                value[2].clone(),
1008            );
1009        }
1010
1011        let mut db_list = db.clone();
1012
1013        for item in order.members() {
1014            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1015        }
1016        let t = alls_field.join(",");
1017        db_list.field(t.as_str());
1018        if !table_field_json.is_empty() {
1019            db_list.json(&table_field_json.join(","));
1020        }
1021        let mut data = db_list.select();
1022
1023        let mut table_datas = object! {};
1024        let mut ids = HashMap::new();
1025
1026        for item in data.members_mut() {
1027            for (field, _) in table_fields.entries() {
1028                if table_datas[field].is_empty() {
1029                    table_datas[field] = array![];
1030                }
1031                let _ = table_datas[field].push(item[field].clone());
1032            }
1033        }
1034        for (field, info) in table_fields.entries_mut() {
1035            let _ = info["fields"].push("id");
1036            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1037            let table_name = info["table"].clone();
1038            let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
1039
1040            for item in data_list.members_mut() {
1041                let id = item["id"].as_str().unwrap_or("").to_string();
1042                item.remove("id");
1043                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
1044                ids.insert(
1045                    id.clone(),
1046                    object! {
1047                        value: id.clone(),
1048                        label:label.join(" | ").clone(),
1049                    },
1050                );
1051            }
1052        }
1053
1054        for item in data.members_mut() {
1055            for (field, _) in table_fields.entries() {
1056                if item[field].is_empty() {
1057                    continue;
1058                }
1059                item[field] = ids[item[field].as_str().unwrap()].clone();
1060            }
1061            //item["children"] = self.tools().db.table(table_name).where_and(pid_field, "=", item["id"].clone()).select();
1062        }
1063
1064        object! {
1065            data:data,
1066            columns:columns,
1067            search_name:search_name.join("/"),
1068            label:label,
1069            btn_all:array![],
1070            btn_api:array![],
1071            btn_ids:array![]
1072        }
1073    }
1074
1075    /// 表格接收参数
1076    fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
1077        params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
1078        params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
1079        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
1080        params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
1081        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
1082        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
1083        params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
1084        params
1085    }
1086    /// 列表表格渲染
1087    /// * table_name 表名
1088    /// * fields 全部模型字段集合
1089    /// * hidd_field 需要隐藏的字段集合
1090    /// * show_field 需要显示的字段集合
1091    /// * search_fields 搜索字段集合
1092    /// * filter_fields 高级搜索字段集合
1093    #[allow(clippy::too_many_arguments)]
1094    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
1095    fn table_list(
1096        &mut self,
1097        request: JsonValue,
1098        table_name: &str,
1099        fields: JsonValue,
1100        hidd_field: Vec<&str>,
1101        show_field: Vec<&str>,
1102        search_fields: Vec<&str>,
1103        filter_fields: Vec<&str>,
1104    ) -> JsonValue {
1105        let page = request["page"].as_i32().unwrap_or(1);
1106        let limit = request["limit"].as_i32().unwrap_or(10);
1107        let search = request["search"].as_str().unwrap_or("");
1108        let order = request["order"].clone();
1109        let where_or = request["where_or"].clone();
1110        let where_and = request["where_and"].clone();
1111        let mut columns = array![];
1112        let mut search_name = vec![];
1113        let mut search_field = vec![];
1114        let mut filter_columns = vec![];
1115
1116        // 表单关联字段
1117        let mut table_fields = object! {};
1118        // 树形关联字段
1119        let mut tree_fields = object! {};
1120
1121        // 需要处理为json格式的字段
1122        let mut json_fields = vec![];
1123
1124        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
1125        alls_field.retain(|x| !hidd_field.contains(x));
1126        if !show_field.is_empty() {
1127            alls_field.retain(|x| show_field.contains(x) || *x == "id");
1128        }
1129
1130        for item in alls_field.iter() {
1131            let key = item.to_string();
1132            let field = fields[key.clone()]["field"].as_str().unwrap();
1133            let title = fields[key.clone()]["title"].as_str().unwrap();
1134            let mode = fields[key.clone()]["mode"].as_str().unwrap();
1135
1136            if search_fields.contains(&field) {
1137                search_name.push(title);
1138                search_field.push(field);
1139            }
1140            if filter_fields.contains(&field) {
1141                filter_columns.push(self.filter_column(fields[key.clone()].clone()));
1142            }
1143            columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
1144
1145            match mode {
1146                "table" => {
1147                    let table_field_info = if mode == "table" {
1148                        fields[key.clone()].clone()
1149                    } else {
1150                        JsonValue::Null
1151                    };
1152                    if !table_field_info.is_empty() {
1153                        table_fields[field] = table_field_info;
1154                    }
1155                }
1156                "tree" => {
1157                    let table_field_info = if mode == "tree" {
1158                        fields[key.clone()].clone()
1159                    } else {
1160                        JsonValue::Null
1161                    };
1162                    if !table_field_info.is_empty() {
1163                        tree_fields[field] = table_field_info;
1164                    }
1165                }
1166                "object" | "array" | "polygon" => {
1167                    json_fields.push(field);
1168                }
1169                _ => {}
1170            }
1171        }
1172
1173        let mut tools = self.tools();
1174        let db = tools.db.table(table_name);
1175
1176        if !search.is_empty() {
1177            db.where_and(
1178                &search_field.join("|"),
1179                "like",
1180                format!("%{search}%").into(),
1181            );
1182        }
1183
1184        for (key, value) in where_or.entries() {
1185            if value.is_empty() {
1186                continue;
1187            }
1188            if value.is_array() {
1189                db.where_or(key, "in", value.clone());
1190            } else if value.is_boolean() {
1191                db.where_or(key, "=", value.clone());
1192            } else {
1193                db.where_or(key, "like", format!("%{value}%").into());
1194            }
1195        }
1196
1197        for value in where_and.members() {
1198            db.where_and(
1199                value[0].as_str().unwrap(),
1200                value[1].as_str().unwrap(),
1201                value[2].clone(),
1202            );
1203        }
1204
1205        let total = db.clone().count().as_f64().unwrap();
1206        let mut db_list = db.clone();
1207
1208        for item in order.members() {
1209            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1210        }
1211
1212        let t = alls_field.join(",");
1213        db_list.field(t.as_str());
1214        let mut data = db_list.page(page, limit).json(&json_fields.join(",")).select();
1215
1216        let mut table_data = object! {};
1217
1218        for item in data.members_mut() {
1219            if !table_fields.is_empty() {
1220                for (field, field_info) in table_fields.entries() {
1221                    if item[field].is_empty() {
1222                        continue;
1223                    }
1224                    let key = item[field].as_str().unwrap_or("");
1225                    if key.is_empty() {
1226                        continue;
1227                    }
1228                    if !table_data.has_key(field) {
1229                        table_data[field] = object! {};
1230                    }
1231                    if !table_data[field].has_key(key) {
1232                        let mut info = field_info.clone();
1233                        let _ = info["fields"].push("id");
1234                        let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1235                        let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1236                        let id = find["id"].to_string();
1237                        find.remove("id");
1238                        let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1239                        table_data[field][key] = object! {
1240                                value: id.clone(),
1241                                label:label.join(" | ").clone(),
1242                        };
1243                    }
1244                    item[field] = table_data[field][key].clone();
1245                }
1246            }
1247            if !tree_fields.is_empty() {
1248                for (field, field_info) in tree_fields.entries() {
1249                    if item[field].is_empty() {
1250                        continue;
1251                    }
1252                    let key = item[field].as_str().unwrap_or("");
1253                    if key.is_empty() {
1254                        continue;
1255                    }
1256                    if !table_data.has_key(field) {
1257                        table_data[field] = object! {};
1258                    }
1259                    if !table_data[field].has_key(key) {
1260                        let mut info = field_info.clone();
1261                        let pid_field = info["pid_field"].clone().to_string();
1262                        let _ = info["fields"].push("id");
1263                        let _ = info["fields"].push(pid_field.clone());
1264                        let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1265                        let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1266                        let mut pid = find[pid_field.clone()].to_string();
1267                        let mut name_list = vec![];
1268                        let id = find["id"].to_string();
1269                        find.remove("id");
1270                        find.remove(&pid_field);
1271                        let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1272                        name_list.push(label.join(" | ").clone());
1273                        loop {
1274                            if pid.is_empty() {
1275                                break;
1276                            }
1277                            let mut t = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", pid.clone().into()).field(&fields_k.join(",")).find();
1278                            pid = t[pid_field.clone()].to_string();
1279                            t.remove("id");
1280                            t.remove(&pid_field);
1281                            let label = t.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1282                            name_list.push(label.join(" | ").clone());
1283                        }
1284                        name_list.reverse();
1285                        table_data[field][key] = object! {
1286                                value: id.clone(),
1287                                label:name_list.join("/").clone(),
1288                        };
1289                    }
1290                    item[field] = table_data[field][key].clone();
1291                }
1292            }
1293        }
1294
1295        object! {
1296            total:total,
1297            data:data,
1298            columns:columns,
1299            search_name:search_name.join("/"),
1300            filter_columns:filter_columns,
1301            btn_all:array![],
1302            btn_api:array![],
1303            btn_ids:array![]
1304        }
1305    }
1306    fn table_column(&mut self, field: JsonValue) -> JsonValue {
1307        object! {
1308            name:field["field"].clone(),
1309            label:field["title"].clone(),
1310            align:"center",
1311            field:field["field"].clone(),
1312            sortable:true,
1313            mode:field["mode"].clone(),
1314            dec:field["dec"].clone(),
1315            fields:field["fields"].clone()
1316        }
1317    }
1318    fn filter_column(&mut self, field: JsonValue) -> JsonValue {
1319        object! {
1320            name:field["field"].clone(),
1321            label:field["title"].clone(),
1322            mode:field["mode"].clone(),
1323            option:field["option"].clone(),
1324            api:field["api"].clone(),
1325            fields:field["fields"].clone()
1326        }
1327    }
1328    /// 使用工具
1329    fn tools(&mut self) -> Tools {
1330        let tools = PLUGIN_TOOLS.lock().unwrap();
1331        let tools = tools.get("tools").unwrap().clone();
1332        tools
1333    }
1334    /// 使用配置
1335    fn config(&mut self, name: &str) -> JsonValue {
1336        if CONFIG.lock().unwrap().get(name).is_none() {
1337            object! {}
1338        } else {
1339            CONFIG.lock().unwrap().get(name).unwrap().clone()
1340        }
1341    }
1342    /// 按钮信息
1343    /// * cnd 显示条件 vec![vec!["xxx","=","yyy"],vec!["zzz","=","eee"]]
1344    fn btn(&mut self) -> Btn {
1345        let mut btn = Btn::new(self.api().as_str());
1346        btn.fields(self.params().clone());
1347        btn.tags(self.tags());
1348        btn.icon(self.icon());
1349        btn.desc(self.description());
1350        btn.auth(self.auth());
1351        btn.public(self.public());
1352        btn.title(self.title());
1353        btn.btn_type(BtnType::Api);
1354        btn.btn_color(BtnColor::Primary);
1355        btn.path(self.api().clone().replace(".", "/").as_str());
1356        btn.pass(false);
1357        btn.addon();
1358        btn
1359    }
1360    /// 设置全局变量
1361    fn set_global_data(&mut self, key: &str, value: JsonValue) {
1362        GLOBAL_DATA.with(|data| {
1363            data.borrow_mut()[key] = value;
1364        });
1365    }
1366    /// 获取全局变量数据
1367    fn get_global_data(&mut self) -> JsonValue {
1368        GLOBAL_DATA.with(|data| {
1369            data.borrow().clone()
1370        })
1371    }
1372    /// 获取全局变量指定字段数据
1373    fn get_global_data_key(&mut self, key: &str) -> JsonValue {
1374        GLOBAL_DATA.with(|data| {
1375            data.borrow()[key].clone()
1376        })
1377    }
1378}
1379#[derive(Debug, Clone)]
1380pub struct Btn {
1381    api: String,
1382    title: String,
1383    desc: String,
1384    tags: &'static [&'static str],
1385    auth: bool,
1386    public: bool,
1387    btn_type: BtnType,
1388    color: BtnColor,
1389    icon: String,
1390    cnd: Vec<JsonValue>,
1391    url: String,
1392    path: String,
1393    fields: JsonValue,
1394    addon: String,
1395    /// 是否需要密码
1396    pass: bool,
1397}
1398impl Btn {
1399    pub fn new(api: &str) -> Self {
1400        Self {
1401            api: api.to_string(),
1402            title: "".to_string(),
1403            desc: "".to_string(),
1404            btn_type: BtnType::Api,
1405            color: BtnColor::Primary,
1406            icon: "".to_string(),
1407            auth: false,
1408            public: false,
1409            cnd: vec![],
1410            url: "".to_string(),
1411            path: "".to_string(),
1412            fields: object! {},
1413            tags: &[],
1414            pass: false,
1415            addon: "".to_string(),
1416        }
1417    }
1418
1419    pub fn addon(&mut self) -> &mut Self {
1420        self.addon = self.api.split('.').nth(0).unwrap().to_string();
1421        self
1422    }
1423    pub fn path(&mut self, path: &str) -> &mut Self {
1424        self.path = path.to_string();
1425        self
1426    }
1427    pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1428        self.cnd = cnd;
1429        self
1430    }
1431    pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1432        self.btn_type = btn_type;
1433        self
1434    }
1435    pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1436        self.color = btn_color;
1437        self
1438    }
1439    pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1440        self.fields = fields;
1441        self
1442    }
1443    pub fn pass(&mut self, pass: bool) -> &mut Self {
1444        self.pass = pass;
1445        self
1446    }
1447    pub fn url(&mut self, url: &str) -> &mut Self {
1448        self.url = url.to_string();
1449        self
1450    }
1451    pub fn title(&mut self, title: &str) -> &mut Self {
1452        self.title = title.to_string();
1453        self
1454    }
1455    pub fn desc(&mut self, desc: &str) -> &mut Self {
1456        self.desc = desc.to_string();
1457        self
1458    }
1459    pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1460        self.tags = tags;
1461        self
1462    }
1463    pub fn public(&mut self, public: bool) -> &mut Self {
1464        self.public = public;
1465        self
1466    }
1467    pub fn auth(&mut self, auth: bool) -> &mut Self {
1468        self.auth = auth;
1469        self
1470    }
1471    pub fn icon(&mut self, icon: &str) -> &mut Self {
1472        self.icon = icon.to_string();
1473        self
1474    }
1475    pub fn json(&mut self) -> JsonValue {
1476        object! {
1477            addon:self.addon.to_string() ,
1478            api:self.api.clone(),
1479            title:self.title.clone(),
1480            desc:self.desc.clone(),
1481            auth:self.auth,
1482            public:self.public,
1483            btn_type:self.btn_type.clone().str(),
1484            color:self.color.clone().str(),
1485            icon:self.icon.clone(),
1486            cnd:self.cnd.clone(),
1487            url:self.url.clone(),
1488            path:self.path.clone(),
1489            fields:self.fields.clone(),
1490            tags:self.tags,
1491            pass:self.pass,
1492        }
1493    }
1494}
1495
1496/// 接口类型
1497#[derive(Debug, Clone)]
1498pub enum InterfaceType {
1499    API,
1500    BTN,
1501    MENU,
1502}
1503
1504impl InterfaceType {
1505    pub fn str(&self) -> &'static str {
1506        match self {
1507            InterfaceType::API => "api",
1508            InterfaceType::BTN => "btn",
1509            InterfaceType::MENU => "menu",
1510        }
1511    }
1512    pub fn types() -> Vec<&'static str> {
1513        vec!["api", "btn", "menu"]
1514    }
1515}
1516
1517/// 按钮类型
1518#[derive(Debug, Clone)]
1519pub enum BtnType {
1520    /// 表单
1521    Form,
1522    /// 表单下载
1523    FormDownload,
1524    /// 表单自定义
1525    FormCustom,
1526    FormData,
1527    /// 外部跳转
1528    Url,
1529    /// api请求
1530    Api,
1531    /// 下载
1532    Download,
1533    /// 内部跳转
1534    Path,
1535    /// 弹窗-定制页面
1536    DialogCustom,
1537    /// 表单->API->弹出自定义窗口
1538    FormApiDialogCustom,
1539    /// 预览
1540    Preview,
1541}
1542
1543impl BtnType {
1544    fn str(self) -> &'static str {
1545        match self {
1546            BtnType::Form => "form",
1547            BtnType::FormDownload => "form_download",
1548            BtnType::FormCustom => "form_custom",
1549            BtnType::FormData => "form_data",
1550            BtnType::Api => "api",
1551            BtnType::Download => "download",
1552            BtnType::Url => "url",
1553            BtnType::Path => "path",
1554            BtnType::DialogCustom => "dialog_custom",
1555            BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1556            BtnType::Preview => "preview",
1557        }
1558    }
1559}
1560/// 按钮颜色
1561#[derive(Debug, Clone)]
1562pub enum BtnColor {
1563    Primary,
1564    Red,
1565    Blue,
1566    Yellow,
1567    Green,
1568}
1569
1570impl BtnColor {
1571    fn str(self) -> &'static str {
1572        match self {
1573            BtnColor::Primary => "primary",
1574            BtnColor::Red => "negative",
1575            BtnColor::Blue => "info",
1576            BtnColor::Yellow => "warning",
1577            BtnColor::Green => "positive",
1578        }
1579    }
1580}
1581
1582
1583pub struct Dashboard {
1584    /// 名称
1585    title: String,
1586    /// 数据
1587    data: JsonValue,
1588    /// 显示样式
1589    model: DashboardModel,
1590    /// 渲染样式
1591    class: String,
1592    /// 图标
1593    icon: String,
1594    /// 描述
1595    desc: String,
1596    ///数据请求接口
1597    api: String,
1598    ///用户选项,同时也是api接收的参数
1599    options: JsonValue,
1600}
1601impl Dashboard {
1602    pub fn new(title: &str) -> Dashboard {
1603        Dashboard {
1604            title: title.to_string(),
1605            data: JsonValue::Null,
1606            model: DashboardModel::Number,
1607            class: "col-4".to_string(),
1608            icon: "".to_string(),
1609            desc: "".to_string(),
1610            api: "".to_string(),
1611            options: JsonValue::Null,
1612        }
1613    }
1614    pub fn options(&mut self, options: JsonValue) -> &mut Self {
1615        self.options = options;
1616        self
1617    }
1618    pub fn api(&mut self, api: &str) -> &mut Self {
1619        self.api = api.to_string();
1620        self
1621    }
1622    pub fn data(&mut self, data: JsonValue) -> &mut Self {
1623        self.data = data;
1624        self
1625    }
1626    pub fn class(&mut self, name: &str) -> &mut Self {
1627        self.class = name.to_string();
1628        self
1629    }
1630    pub fn icon(&mut self, name: &str) -> &mut Self {
1631        self.icon = name.to_string();
1632        self
1633    }
1634    pub fn model(&mut self, dashboard_model: DashboardModel) -> &mut Self {
1635        self.model = dashboard_model;
1636        self
1637    }
1638    pub fn desc(&mut self, desc: &str) -> &mut Self {
1639        self.desc = desc.to_string();
1640        self
1641    }
1642    pub fn json(&self) -> JsonValue {
1643        object! {
1644            title: self.title.clone(),
1645            data: self.data.clone(),
1646            class: self.class.clone(),
1647            icon: self.icon.clone(),
1648            model: self.model.str(),
1649            desc: self.desc.clone(),
1650            api: self.api.clone(),
1651            options:self.options.clone(),
1652        }
1653    }
1654}
1655
1656pub enum DashboardModel {
1657    /// 数字
1658    Number,
1659    /// 柱状图
1660    EchartsBar,
1661    /// 堆叠柱状图
1662    EchartsStackedBar,
1663    /// 动态排序的柱状图
1664    EchartsBarRace,
1665    /// 饼图
1666    EchartsPie,
1667    /// 中空饼图
1668    EchartsDoughnut,
1669    /// 堆叠折线图
1670    EchartsStackedLine,
1671    /// 面积填充的堆叠折线图
1672    EchartsStackedLineArea,
1673    /// 地图
1674    EchartsGeoGraph,
1675}
1676
1677impl DashboardModel {
1678    pub fn str(&self) -> &'static str {
1679        match self {
1680            Self::Number => "number",
1681            Self::EchartsBar => "echarts-bar",
1682            Self::EchartsStackedBar => "echarts-stacked_bar",
1683            Self::EchartsBarRace => "echarts-bar_race",
1684            Self::EchartsPie => "echarts-pie",
1685            Self::EchartsDoughnut => "echarts-doughnut",
1686            Self::EchartsStackedLine => "echarts-stacked_line",
1687            Self::EchartsStackedLineArea => "echarts-stacked_line_area",
1688            Self::EchartsGeoGraph => "echarts-geo_graph",
1689        }
1690    }
1691}