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