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["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
502        params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 20, "").example("".into()).field();
503        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
504        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
505        params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
506        params
507    }
508    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
509    fn table_tree_select(
510        &mut self,
511        request: JsonValue,
512        table_name: &str,
513        pid_field: &str,
514        label_field: &str,
515        fields: Vec<&str>,
516    ) -> JsonValue {
517        let search = request["search"].as_str().unwrap_or("");
518        let pid_id = request["pid"].as_str().unwrap_or("id");
519
520        let where_or = request["where_or"].clone();
521        let where_and = request["where_and"].clone();
522
523        let mut tools = self.tools();
524        let db = tools.db.table(table_name);
525
526        db.where_and(pid_field, "=", pid_id.into());
527
528        if !search.is_empty() {
529            db.where_and("id", "in", search.into());
530        }
531
532        for (key, value) in where_or.entries() {
533            if value.is_empty() {
534                continue;
535            }
536            if value.is_array() {
537                db.where_or(key, "between", value.clone());
538                db.where_or(key, "in", value.clone());
539            } else if value.is_boolean() {
540                db.where_or(key, "=", value.clone());
541            } else {
542                db.where_or(key, "like", format!("%{value}%").into());
543            }
544        }
545
546        for value in where_and.members() {
547            db.where_and(
548                value[0].as_str().unwrap(),
549                value[1].as_str().unwrap(),
550                value[2].clone(),
551            );
552        }
553
554        db.field(format!("id,{},{}", pid_field, fields.join(",")).as_str());
555
556        let mut data = db.select();
557        for item in data.members_mut() {
558            let children = self.tools().db.table(table_name).where_and(pid_field, "=", item["id"].clone()).select();
559            if children.is_empty() {
560                item["lazy"] = false.into();
561            } else {
562                item["lazy"] = true.into();
563            }
564        }
565        object! {
566            data:data,
567            label_field:label_field,
568            pid_field:pid_field
569        }
570    }
571    /// 菜单表格接收参数
572    fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
573        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
574        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
575        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
576        params
577    }
578    #[allow(clippy::too_many_arguments)]
579    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
580    fn table_menu(
581        &mut self,
582        request: JsonValue,
583        table_name: &str,
584        label_field: &str,
585        fields: JsonValue,
586
587        hidd_field: Vec<&str>,
588        show_field: Vec<&str>,
589
590        search_fields: Vec<&str>,
591        _filter_fields: Vec<&str>,
592    ) -> JsonValue {
593        let search = request["search"].as_str().unwrap_or("");
594
595        let order = request["order"].clone();
596        let where_or = request["where_or"].clone();
597        let where_and = request["where_and"].clone();
598        let mut columns = array![];
599        let mut search_name = vec![];
600        let mut search_field = vec![];
601        let mut filter_columns = vec![];
602        let mut table_fields = object! {};
603        let mut table_field_json = vec![];
604
605        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
606        alls_field.retain(|x| !hidd_field.contains(x));
607        if !show_field.is_empty() {
608            alls_field.retain(|x| show_field.contains(x) || *x == "id");
609        }
610
611        for item in alls_field.iter() {
612            let row = &fields[item.to_string()];
613            let field = row["field"].to_string();
614            let title = row["title"].to_string();
615            let mode = row["mode"].to_string();
616
617            if search_fields.contains(&field.as_str()) {
618                search_name.push(title);
619                search_field.push(field.clone());
620            }
621            filter_columns.push(self.filter_column(row.clone()));
622            columns.push(self.table_column(row.clone())).unwrap();
623            let mut table_field_info = object! {};
624            match mode.as_str() {
625                "table" => table_field_info = row.clone(),
626                "array" => table_field_json.push(field.clone()),
627                _ => {}
628            }
629            if !table_field_info.is_empty() {
630                table_fields[field.as_str()] = table_field_info;
631            }
632        }
633
634        let mut tools = self.tools();
635        let db = tools.db.table(table_name);
636
637        if !search.is_empty() {
638            db.where_and(
639                &search_field.join("|"),
640                "like",
641                format!("%{search}%").into(),
642            );
643        }
644
645        for (key, value) in where_or.entries() {
646            if value.is_empty() {
647                continue;
648            }
649            if value.is_array() {
650                db.where_or(key, "between", value.clone());
651                db.where_or(key, "in", value.clone());
652            } else if value.is_boolean() {
653                db.where_or(key, "=", value.clone());
654            } else {
655                db.where_or(key, "like", format!("%{value}%").into());
656            }
657        }
658
659        for value in where_and.members() {
660            db.where_and(
661                value[0].as_str().unwrap(),
662                value[1].as_str().unwrap(),
663                value[2].clone(),
664            );
665        }
666
667        let mut db_list = db.clone();
668
669        for item in order.members() {
670            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
671        }
672
673        let t = alls_field.join(",");
674        db_list.field(t.as_str());
675
676        if !table_field_json.is_empty() {
677            db_list.json(&table_field_json.join(","));
678        }
679
680        let mut data = db_list.select();
681
682        let mut table_datas = object! {};
683        let mut ids = HashMap::new();
684
685        for item in data.members_mut() {
686            for (field, _) in table_fields.entries() {
687                if table_datas[field].is_empty() {
688                    table_datas[field] = array![];
689                }
690                let _ = table_datas[field].push(item[field].clone());
691            }
692        }
693        for (field, info) in table_fields.entries_mut() {
694            let _ = info["fields"].push("id");
695            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
696            let table_name = info["table"].clone();
697            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();
698
699            for item in data_list.members_mut() {
700                let id = item["id"].as_str().unwrap_or("").to_string();
701                item.remove("id");
702                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
703                ids.insert(
704                    id.clone(),
705                    object! {
706                        value: id.clone(),
707                        label:label.join(" | ").clone(),
708                    },
709                );
710            }
711        }
712
713        for item in data.members_mut() {
714            for (field, _) in table_fields.entries() {
715                if item[field].is_empty() {
716                    continue;
717                }
718                item[field] = ids[item[field].as_str().unwrap()].clone();
719            }
720        }
721
722        object! {
723            data:data,
724            columns:columns,
725            search_name:search_name.join("/"),
726            filter_columns:filter_columns,
727            label_field:label_field,
728            btn_all:array![],
729            btn_api:array![]
730        }
731    }
732    /// 树型表格接收参数
733    fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
734        params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
735        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
736        params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
737        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
738        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
739        params
740    }
741    #[allow(clippy::too_many_arguments)]
742    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
743    fn table_tree(
744        &mut self,
745        request: JsonValue,
746        table_name: &str,
747        pid_field: &str,
748        label_field: &str,
749        fields: JsonValue,
750        hidd_field: Vec<&str>,
751        show_field: Vec<&str>,
752        search_fields: Vec<&str>,
753        _filter_fields: Vec<&str>,
754    ) -> JsonValue {
755        let search = request["search"].as_str().unwrap_or("");
756
757        let pid = request["pid"].clone();
758
759        let order = request["order"].clone();
760        let where_or = request["where_or"].clone();
761        let where_and = request["where_and"].clone();
762        let mut columns = array![];
763        let mut search_name = vec![];
764        let mut search_field = vec![];
765        let mut filter_columns = vec![];
766        let mut table_field_json = vec![];
767        let mut table_fields = object! {};
768
769        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
770        alls_field.retain(|x| !hidd_field.contains(x));
771        if !show_field.is_empty() {
772            alls_field.retain(|x| show_field.contains(x) || *x == "id");
773        }
774
775        for item in alls_field.iter() {
776            let row = fields[item.to_string()].clone();
777            let field = row["field"].to_string();
778            let title = row["title"].to_string();
779            let mode = row["mode"].to_string();
780
781            if search_fields.contains(&field.as_str()) {
782                search_name.push(title);
783                search_field.push(field.clone());
784            }
785            filter_columns.push(self.filter_column(row.clone()));
786            columns.push(self.table_column(row.clone())).unwrap();
787            let mut table_field_info = object! {};
788            match mode.as_str() {
789                "table" => table_field_info = row.clone(),
790                "array" => table_field_json.push(field.clone()),
791                _ => {}
792            }
793            if !table_field_info.is_empty() {
794                table_fields[field.as_str()] = table_field_info;
795            }
796        }
797
798        let mut tools = self.tools();
799        let db = tools.db.table(table_name);
800        db.where_and(pid_field, "=", pid);
801        if !search.is_empty() {
802            db.where_and(
803                &search_field.join("|"),
804                "like",
805                format!("%{search}%").into(),
806            );
807        }
808
809        for (key, value) in where_or.entries() {
810            if value.is_empty() {
811                continue;
812            }
813            if value.is_array() {
814                // db.where_or(key, "between", value.clone());
815                db.where_or(key, "in", value.clone());
816            } else if value.is_boolean() {
817                db.where_or(key, "=", value.clone());
818            } else {
819                db.where_or(key, "like", format!("%{value}%").into());
820            }
821        }
822
823        for value in where_and.members() {
824            db.where_and(
825                value[0].as_str().unwrap(),
826                value[1].as_str().unwrap(),
827                value[2].clone(),
828            );
829        }
830
831        let mut db_list = db.clone();
832
833        for item in order.members() {
834            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
835        }
836        let t = alls_field.join(",");
837        db_list.field(t.as_str());
838        if !table_field_json.is_empty() {
839            db_list.json(&table_field_json.join(","));
840        }
841        let mut data = db_list.select();
842
843        let mut table_datas = object! {};
844        let mut ids = HashMap::new();
845
846        for item in data.members_mut() {
847            for (field, _) in table_fields.entries() {
848                if table_datas[field].is_empty() {
849                    table_datas[field] = array![];
850                }
851                let _ = table_datas[field].push(item[field].clone());
852            }
853        }
854        for (field, info) in table_fields.entries_mut() {
855            let _ = info["fields"].push("id");
856            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
857            let table_name = info["table"].clone();
858            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();
859
860            for item in data_list.members_mut() {
861                let id = item["id"].as_str().unwrap_or("").to_string();
862                item.remove("id");
863                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
864                ids.insert(
865                    id.clone(),
866                    object! {
867                        value: id.clone(),
868                        label:label.join(" | ").clone(),
869                    },
870                );
871            }
872        }
873
874        let mut list = array![];
875        for item in data.members_mut() {
876            for (field, _) in table_fields.entries() {
877                if item[field].is_empty() {
878                    continue;
879                }
880                item[field] = ids[item[field].as_str().unwrap()].clone();
881            }
882            let _ = list.push(object! {
883                id:item["id"].as_str().unwrap(),
884                code:item["code"].as_str().unwrap(),
885                label:item[label_field].as_str().unwrap(),
886                data:item.clone(),
887            });
888        }
889
890        object! {
891            data:list,
892            columns:columns,
893            search_name:search_name.join("/"),
894            filter_columns:filter_columns,
895            pid_field:pid_field,
896            btn_all:array![],
897            btn_api:array![]
898        }
899    }
900
901    #[allow(clippy::too_many_arguments)]
902    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
903    /// 树形表单
904    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 {
905        let search = request["search"].as_str().unwrap_or("");
906
907        let pid = request["pid"].clone();
908        let order = request["order"].clone();
909        let where_or = request["where_or"].clone();
910        let where_and = request["where_and"].clone();
911        let mut columns = array![];
912        let mut search_name = vec![];
913        let mut search_field = vec![];
914        let mut filter_columns = vec![];
915        let mut table_field_json = vec![];
916        let mut table_fields = object! {};
917
918        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
919        alls_field.retain(|x| !hidd_field.contains(x));
920        if !show_field.is_empty() {
921            alls_field.retain(|x| show_field.contains(x) || *x == "id");
922        }
923
924        for item in alls_field.iter() {
925            let row = fields[item.to_string()].clone();
926            let field = row["field"].to_string();
927            let title = row["title"].to_string();
928            let mode = row["mode"].to_string();
929
930            if search_fields.contains(&field.as_str()) {
931                search_name.push(title);
932                search_field.push(field.clone());
933            }
934            filter_columns.push(self.filter_column(row.clone()));
935            columns.push(self.table_column(row.clone())).unwrap();
936            let mut table_field_info = object! {};
937            match mode.as_str() {
938                "table" => table_field_info = row.clone(),
939                "array" => table_field_json.push(field.clone()),
940                _ => {}
941            }
942            if !table_field_info.is_empty() {
943                table_fields[field.as_str()] = table_field_info;
944            }
945        }
946
947        let mut tools = self.tools();
948        let db = tools.db.table(table_name);
949        db.where_and(pid_field, "=", pid);
950        if !search.is_empty() {
951            db.where_and(
952                &search_field.join("|"),
953                "like",
954                format!("%{search}%").into(),
955            );
956        }
957
958        for (key, value) in where_or.entries() {
959            if value.is_empty() {
960                continue;
961            }
962            if value.is_array() {
963                db.where_or(key, "in", value.clone());
964            } else if value.is_boolean() {
965                db.where_or(key, "=", value.clone());
966            } else {
967                db.where_or(key, "like", format!("%{value}%").into());
968            }
969        }
970
971        for value in where_and.members() {
972            db.where_and(
973                value[0].as_str().unwrap(),
974                value[1].as_str().unwrap(),
975                value[2].clone(),
976            );
977        }
978
979        let mut db_list = db.clone();
980
981        for item in order.members() {
982            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
983        }
984        let t = alls_field.join(",");
985        db_list.field(t.as_str());
986        if !table_field_json.is_empty() {
987            db_list.json(&table_field_json.join(","));
988        }
989        let mut data = db_list.select();
990
991        let mut table_datas = object! {};
992        let mut ids = HashMap::new();
993
994        for item in data.members_mut() {
995            for (field, _) in table_fields.entries() {
996                if table_datas[field].is_empty() {
997                    table_datas[field] = array![];
998                }
999                let _ = table_datas[field].push(item[field].clone());
1000            }
1001        }
1002        for (field, info) in table_fields.entries_mut() {
1003            let _ = info["fields"].push("id");
1004            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1005            let table_name = info["table"].clone();
1006            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();
1007
1008            for item in data_list.members_mut() {
1009                let id = item["id"].as_str().unwrap_or("").to_string();
1010                item.remove("id");
1011                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
1012                ids.insert(
1013                    id.clone(),
1014                    object! {
1015                        value: id.clone(),
1016                        label:label.join(" | ").clone(),
1017                    },
1018                );
1019            }
1020        }
1021
1022        for item in data.members_mut() {
1023            for (field, _) in table_fields.entries() {
1024                if item[field].is_empty() {
1025                    continue;
1026                }
1027                item[field] = ids[item[field].as_str().unwrap()].clone();
1028            }
1029            //item["children"] = self.tools().db.table(table_name).where_and(pid_field, "=", item["id"].clone()).select();
1030        }
1031
1032        object! {
1033            data:data,
1034            columns:columns,
1035            search_name:search_name.join("/"),
1036            label:label,
1037            btn_all:array![],
1038            btn_api:array![],
1039            btn_ids:array![]
1040        }
1041    }
1042
1043    /// 表格接收参数
1044    fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
1045        params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
1046        params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
1047        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
1048        params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
1049        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
1050        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
1051        params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
1052        params
1053    }
1054    /// 列表表格渲染
1055    /// * table_name 表名
1056    /// * fields 全部模型字段集合
1057    /// * hidd_field 需要隐藏的字段集合
1058    /// * show_field 需要显示的字段集合
1059    /// * search_fields 搜索字段集合
1060    /// * filter_fields 高级搜索字段集合
1061    #[allow(clippy::too_many_arguments)]
1062    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
1063    fn table_list(
1064        &mut self,
1065        request: JsonValue,
1066        table_name: &str,
1067        fields: JsonValue,
1068        hidd_field: Vec<&str>,
1069        show_field: Vec<&str>,
1070        search_fields: Vec<&str>,
1071        filter_fields: Vec<&str>,
1072    ) -> JsonValue {
1073        let page = request["page"].as_i32().unwrap_or(1);
1074        let limit = request["limit"].as_i32().unwrap_or(10);
1075        let search = request["search"].as_str().unwrap_or("");
1076        let order = request["order"].clone();
1077        let where_or = request["where_or"].clone();
1078        let where_and = request["where_and"].clone();
1079        let mut columns = array![];
1080        let mut search_name = vec![];
1081        let mut search_field = vec![];
1082        let mut filter_columns = vec![];
1083
1084        // 表单关联字段
1085        let mut table_fields = object! {};
1086        // 树形关联字段
1087        let mut tree_fields = object! {};
1088
1089        // 需要处理为json格式的字段
1090        let mut json_fields = vec![];
1091
1092        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
1093        alls_field.retain(|x| !hidd_field.contains(x));
1094        if !show_field.is_empty() {
1095            alls_field.retain(|x| show_field.contains(x) || *x == "id");
1096        }
1097
1098        for item in alls_field.iter() {
1099            let key = item.to_string();
1100            let field = fields[key.clone()]["field"].as_str().unwrap();
1101            let title = fields[key.clone()]["title"].as_str().unwrap();
1102            let mode = fields[key.clone()]["mode"].as_str().unwrap();
1103
1104            if search_fields.contains(&field) {
1105                search_name.push(title);
1106                search_field.push(field);
1107            }
1108            if filter_fields.contains(&field) {
1109                filter_columns.push(self.filter_column(fields[key.clone()].clone()));
1110            }
1111            columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
1112
1113            match mode {
1114                "table" => {
1115                    let table_field_info = if mode == "table" {
1116                        fields[key.clone()].clone()
1117                    } else {
1118                        JsonValue::Null
1119                    };
1120                    if !table_field_info.is_empty() {
1121                        table_fields[field] = table_field_info;
1122                    }
1123                }
1124                "tree" => {
1125                    let table_field_info = if mode == "tree" {
1126                        fields[key.clone()].clone()
1127                    } else {
1128                        JsonValue::Null
1129                    };
1130                    if !table_field_info.is_empty() {
1131                        tree_fields[field] = table_field_info;
1132                    }
1133                }
1134                "object" | "array" | "polygon" => {
1135                    json_fields.push(field);
1136                }
1137                _ => {}
1138            }
1139        }
1140
1141        let mut tools = self.tools();
1142        let db = tools.db.table(table_name);
1143
1144        if !search.is_empty() {
1145            db.where_and(
1146                &search_field.join("|"),
1147                "like",
1148                format!("%{search}%").into(),
1149            );
1150        }
1151
1152        for (key, value) in where_or.entries() {
1153            if value.is_empty() {
1154                continue;
1155            }
1156            if value.is_array() {
1157                db.where_or(key, "in", value.clone());
1158            } else if value.is_boolean() {
1159                db.where_or(key, "=", value.clone());
1160            } else {
1161                db.where_or(key, "like", format!("%{value}%").into());
1162            }
1163        }
1164
1165        for value in where_and.members() {
1166            db.where_and(
1167                value[0].as_str().unwrap(),
1168                value[1].as_str().unwrap(),
1169                value[2].clone(),
1170            );
1171        }
1172
1173        let total = db.clone().count().as_f64().unwrap();
1174        let mut db_list = db.clone();
1175
1176        for item in order.members() {
1177            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1178        }
1179
1180        let t = alls_field.join(",");
1181        db_list.field(t.as_str());
1182        let mut data = db_list.page(page, limit).json(&json_fields.join(",")).select();
1183
1184        let mut table_data = object! {};
1185
1186        for item in data.members_mut() {
1187            if !table_fields.is_empty() {
1188                for (field, field_info) in table_fields.entries() {
1189                    if item[field].is_empty() {
1190                        continue;
1191                    }
1192                    let key = item[field].as_str().unwrap_or("");
1193                    if key.is_empty() {
1194                        continue;
1195                    }
1196                    if !table_data.has_key(field) {
1197                        table_data[field] = object! {};
1198                    }
1199                    if !table_data[field].has_key(key) {
1200                        let mut info = field_info.clone();
1201                        let _ = info["fields"].push("id");
1202                        let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1203                        let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1204                        let id = find["id"].to_string();
1205                        find.remove("id");
1206                        let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1207                        table_data[field][key] = object! {
1208                                value: id.clone(),
1209                                label:label.join(" | ").clone(),
1210                        };
1211                    }
1212                    item[field] = table_data[field][key].clone();
1213                }
1214            }
1215            if !tree_fields.is_empty() {
1216                for (field, field_info) in tree_fields.entries() {
1217                    if item[field].is_empty() {
1218                        continue;
1219                    }
1220                    let key = item[field].as_str().unwrap_or("");
1221                    if key.is_empty() {
1222                        continue;
1223                    }
1224                    if !table_data.has_key(field) {
1225                        table_data[field] = object! {};
1226                    }
1227                    if !table_data[field].has_key(key) {
1228                        let mut info = field_info.clone();
1229                        let pid_field = info["pid_field"].clone().to_string();
1230                        let _ = info["fields"].push("id");
1231                        let _ = info["fields"].push(pid_field.clone());
1232                        let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1233                        let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1234                        let id = find["id"].to_string();
1235                        find.remove("id");
1236                        find.remove(&pid_field);
1237                        let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1238                        table_data[field][key] = object! {
1239                                value: id.clone(),
1240                                label:label.join(" | ").clone(),
1241                        };
1242                    }
1243                    item[field] = table_data[field][key].clone();
1244                }
1245            }
1246        }
1247
1248        object! {
1249            total:total,
1250            data:data,
1251            columns:columns,
1252            search_name:search_name.join("/"),
1253            filter_columns:filter_columns,
1254            btn_all:array![],
1255            btn_api:array![],
1256            btn_ids:array![]
1257        }
1258    }
1259    fn table_column(&mut self, field: JsonValue) -> JsonValue {
1260        object! {
1261            name:field["field"].clone(),
1262            label:field["title"].clone(),
1263            align:"center",
1264            field:field["field"].clone(),
1265            sortable:true,
1266            mode:field["mode"].clone(),
1267            dec:field["dec"].clone(),
1268            fields:field["fields"].clone()
1269        }
1270    }
1271    fn filter_column(&mut self, field: JsonValue) -> JsonValue {
1272        object! {
1273            name:field["field"].clone(),
1274            label:field["title"].clone(),
1275            mode:field["mode"].clone(),
1276            option:field["option"].clone(),
1277            api:field["api"].clone(),
1278            fields:field["fields"].clone()
1279        }
1280    }
1281    /// 使用工具
1282    fn tools(&mut self) -> Tools {
1283        let tools = PLUGIN_TOOLS.lock().unwrap();
1284        let tools = tools.get("tools").unwrap().clone();
1285        tools
1286    }
1287    /// 使用配置
1288    fn config(&mut self, name: &str) -> JsonValue {
1289        if CONFIG.lock().unwrap().get(name).is_none() {
1290            object! {}
1291        } else {
1292            CONFIG.lock().unwrap().get(name).unwrap().clone()
1293        }
1294    }
1295    /// 按钮信息
1296    /// * cnd 显示条件 vec![vec!["xxx","=","yyy"],vec!["zzz","=","eee"]]
1297    fn btn(&mut self) -> Btn {
1298        let mut btn = Btn::new(self.api().as_str());
1299        btn.fields(self.params().clone());
1300        btn.tags(self.tags());
1301        btn.icon(self.icon());
1302        btn.desc(self.description());
1303        btn.auth(self.auth());
1304        btn.public(self.public());
1305        btn.title(self.title());
1306        btn.btn_type(BtnType::Api);
1307        btn.btn_color(BtnColor::Primary);
1308        btn.path(self.api().clone().replace(".", "/").as_str());
1309        btn.pass(false);
1310        btn.addon();
1311        btn
1312    }
1313    /// 设置全局变量
1314    fn set_global_data(&mut self, key: &str, value: JsonValue) {
1315        GLOBAL_DATA.with(|data| {
1316            data.borrow_mut()[key] = value;
1317        });
1318    }
1319    /// 获取全局变量数据
1320    fn get_global_data(&mut self) -> JsonValue {
1321        GLOBAL_DATA.with(|data| {
1322            data.borrow().clone()
1323        })
1324    }
1325    /// 获取全局变量指定字段数据
1326    fn get_global_data_key(&mut self, key: &str) -> JsonValue {
1327        GLOBAL_DATA.with(|data| {
1328            data.borrow()[key].clone()
1329        })
1330    }
1331}
1332#[derive(Debug, Clone)]
1333pub struct Btn {
1334    api: String,
1335    title: String,
1336    desc: String,
1337    tags: &'static [&'static str],
1338    auth: bool,
1339    public: bool,
1340    btn_type: BtnType,
1341    color: BtnColor,
1342    icon: String,
1343    cnd: Vec<JsonValue>,
1344    url: String,
1345    path: String,
1346    fields: JsonValue,
1347    addon: String,
1348    /// 是否需要密码
1349    pass: bool,
1350}
1351impl Btn {
1352    pub fn new(api: &str) -> Self {
1353        Self {
1354            api: api.to_string(),
1355            title: "".to_string(),
1356            desc: "".to_string(),
1357            btn_type: BtnType::Api,
1358            color: BtnColor::Primary,
1359            icon: "".to_string(),
1360            auth: false,
1361            public: false,
1362            cnd: vec![],
1363            url: "".to_string(),
1364            path: "".to_string(),
1365            fields: object! {},
1366            tags: &[],
1367            pass: false,
1368            addon: "".to_string(),
1369        }
1370    }
1371
1372    pub fn addon(&mut self) -> &mut Self {
1373        self.addon = self.api.split('.').nth(0).unwrap().to_string();
1374        self
1375    }
1376    pub fn path(&mut self, path: &str) -> &mut Self {
1377        self.path = path.to_string();
1378        self
1379    }
1380    pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1381        self.cnd = cnd;
1382        self
1383    }
1384    pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1385        self.btn_type = btn_type;
1386        self
1387    }
1388    pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1389        self.color = btn_color;
1390        self
1391    }
1392    pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1393        self.fields = fields;
1394        self
1395    }
1396    pub fn pass(&mut self, pass: bool) -> &mut Self {
1397        self.pass = pass;
1398        self
1399    }
1400    pub fn url(&mut self, url: &str) -> &mut Self {
1401        self.url = url.to_string();
1402        self
1403    }
1404    pub fn title(&mut self, title: &str) -> &mut Self {
1405        self.title = title.to_string();
1406        self
1407    }
1408    pub fn desc(&mut self, desc: &str) -> &mut Self {
1409        self.desc = desc.to_string();
1410        self
1411    }
1412    pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1413        self.tags = tags;
1414        self
1415    }
1416    pub fn public(&mut self, public: bool) -> &mut Self {
1417        self.public = public;
1418        self
1419    }
1420    pub fn auth(&mut self, auth: bool) -> &mut Self {
1421        self.auth = auth;
1422        self
1423    }
1424    pub fn icon(&mut self, icon: &str) -> &mut Self {
1425        self.icon = icon.to_string();
1426        self
1427    }
1428    pub fn json(&mut self) -> JsonValue {
1429        object! {
1430            addon:self.addon.to_string() ,
1431            api:self.api.clone(),
1432            title:self.title.clone(),
1433            desc:self.desc.clone(),
1434            auth:self.auth,
1435            public:self.public,
1436            btn_type:self.btn_type.clone().str(),
1437            color:self.color.clone().str(),
1438            icon:self.icon.clone(),
1439            cnd:self.cnd.clone(),
1440            url:self.url.clone(),
1441            path:self.path.clone(),
1442            fields:self.fields.clone(),
1443            tags:self.tags,
1444            pass:self.pass,
1445        }
1446    }
1447}
1448
1449/// 接口类型
1450#[derive(Debug, Clone)]
1451pub enum InterfaceType {
1452    API,
1453    BTN,
1454    MENU,
1455}
1456
1457impl InterfaceType {
1458    pub fn str(&self) -> &'static str {
1459        match self {
1460            InterfaceType::API => "api",
1461            InterfaceType::BTN => "btn",
1462            InterfaceType::MENU => "menu",
1463        }
1464    }
1465    pub fn types() -> Vec<&'static str> {
1466        vec!["api", "btn", "menu"]
1467    }
1468}
1469
1470/// 按钮类型
1471#[derive(Debug, Clone)]
1472pub enum BtnType {
1473    /// 表单
1474    Form,
1475    /// 表单下载
1476    FormDownload,
1477    /// 表单自定义
1478    FormCustom,
1479    FormData,
1480    /// 外部跳转
1481    Url,
1482    /// api请求
1483    Api,
1484    /// 下载
1485    Download,
1486    /// 内部跳转
1487    Path,
1488    /// 弹窗-定制页面
1489    DialogCustom,
1490    /// 表单->API->弹出自定义窗口
1491    FormApiDialogCustom,
1492    /// 预览
1493    Preview,
1494}
1495
1496impl BtnType {
1497    fn str(self) -> &'static str {
1498        match self {
1499            BtnType::Form => "form",
1500            BtnType::FormDownload => "form_download",
1501            BtnType::FormCustom => "form_custom",
1502            BtnType::FormData => "form_data",
1503            BtnType::Api => "api",
1504            BtnType::Download => "download",
1505            BtnType::Url => "url",
1506            BtnType::Path => "path",
1507            BtnType::DialogCustom => "dialog_custom",
1508            BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1509            BtnType::Preview => "preview",
1510        }
1511    }
1512}
1513/// 按钮颜色
1514#[derive(Debug, Clone)]
1515pub enum BtnColor {
1516    Primary,
1517    Red,
1518    Blue,
1519    Yellow,
1520    Green,
1521}
1522
1523impl BtnColor {
1524    fn str(self) -> &'static str {
1525        match self {
1526            BtnColor::Primary => "primary",
1527            BtnColor::Red => "negative",
1528            BtnColor::Blue => "info",
1529            BtnColor::Yellow => "warning",
1530            BtnColor::Green => "positive",
1531        }
1532    }
1533}
1534
1535
1536pub struct Dashboard {
1537    /// 名称
1538    title: String,
1539    /// 数据
1540    data: JsonValue,
1541    /// 显示样式
1542    model: DashboardModel,
1543    /// 渲染样式
1544    class: String,
1545    /// 图标
1546    icon: String,
1547    /// 描述
1548    desc: String,
1549    ///数据请求接口
1550    api: String,
1551    ///用户选项,同时也是api接收的参数
1552    options: JsonValue,
1553}
1554impl Dashboard {
1555    pub fn new(title: &str) -> Dashboard {
1556        Dashboard {
1557            title: title.to_string(),
1558            data: JsonValue::Null,
1559            model: DashboardModel::Number,
1560            class: "col-4".to_string(),
1561            icon: "".to_string(),
1562            desc: "".to_string(),
1563            api: "".to_string(),
1564            options: JsonValue::Null,
1565        }
1566    }
1567    pub fn options(&mut self, options: JsonValue) -> &mut Self {
1568        self.options = options;
1569        self
1570    }
1571    pub fn api(&mut self, api: &str) -> &mut Self {
1572        self.api = api.to_string();
1573        self
1574    }
1575    pub fn data(&mut self, data: JsonValue) -> &mut Self {
1576        self.data = data;
1577        self
1578    }
1579    pub fn class(&mut self, name: &str) -> &mut Self {
1580        self.class = name.to_string();
1581        self
1582    }
1583    pub fn icon(&mut self, name: &str) -> &mut Self {
1584        self.icon = name.to_string();
1585        self
1586    }
1587    pub fn model(&mut self, dashboard_model: DashboardModel) -> &mut Self {
1588        self.model = dashboard_model;
1589        self
1590    }
1591    pub fn desc(&mut self, desc: &str) -> &mut Self {
1592        self.desc = desc.to_string();
1593        self
1594    }
1595    pub fn json(&self) -> JsonValue {
1596        object! {
1597            title: self.title.clone(),
1598            data: self.data.clone(),
1599            class: self.class.clone(),
1600            icon: self.icon.clone(),
1601            model: self.model.str(),
1602            desc: self.desc.clone(),
1603            api: self.api.clone(),
1604            options:self.options.clone(),
1605        }
1606    }
1607}
1608
1609pub enum DashboardModel {
1610    /// 数字
1611    Number,
1612    /// 柱状图
1613    EchartsBar,
1614    /// 堆叠柱状图
1615    EchartsStackedBar,
1616    /// 动态排序的柱状图
1617    EchartsBarRace,
1618    /// 饼图
1619    EchartsPie,
1620    /// 中空饼图
1621    EchartsDoughnut,
1622    /// 堆叠折线图
1623    EchartsStackedLine,
1624    /// 面积填充的堆叠折线图
1625    EchartsStackedLineArea,
1626    /// 地图
1627    EchartsGeoGraph,
1628}
1629
1630impl DashboardModel {
1631    pub fn str(&self) -> &'static str {
1632        match self {
1633            Self::Number => "number",
1634            Self::EchartsBar => "echarts-bar",
1635            Self::EchartsStackedBar => "echarts-stacked_bar",
1636            Self::EchartsBarRace => "echarts-bar_race",
1637            Self::EchartsPie => "echarts-pie",
1638            Self::EchartsDoughnut => "echarts-doughnut",
1639            Self::EchartsStackedLine => "echarts-stacked_line",
1640            Self::EchartsStackedLineArea => "echarts-stacked_line_area",
1641            Self::EchartsGeoGraph => "echarts-geo_graph",
1642        }
1643    }
1644}