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    /// API 名称
16    fn api(&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        let action = t[4].to_lowercase();
21        format!("{plugin}.{module}.{action}")
22    }
23    /// 是否需要密钥
24    fn token(&self) -> bool {
25        true
26    }
27    /// 版本号
28    fn version(&self) -> &'static str {
29        "v1"
30    }
31    /// 作者
32    fn author(&self) -> &'static str {
33        ""
34    }
35    fn sort(&self) -> usize {
36        99
37    }
38    /// 功能标题
39    fn title(&self) -> &'static str;
40    /// 功能描述
41    fn description(&self) -> &'static str {
42        ""
43    }
44    /// 请求地址路径
45    fn path(&self) -> &'static str {
46        ""
47    }
48    /// 请求地址参数
49    fn query(&self) -> JsonValue {
50        object! {}
51    }
52    /// 归属标签
53    fn tags(&self) -> &'static [&'static str] {
54        &[]
55    }
56    fn icon(&self) -> &'static str {
57        ""
58    }
59    /// 是否公开
60    fn public(&self) -> bool {
61        true
62    }
63    /// 是否权限组显示
64    fn auth(&self) -> bool {
65        true
66    }
67    /// 接口类型 btn api menu
68    fn interface_type(&self) -> InterfaceType {
69        InterfaceType::API
70    }
71    /// 允许的请求类型
72    fn method(&mut self) -> Method {
73        Method::Post
74    }
75    /// 请求类型
76    fn content_type(&mut self) -> ContentType {
77        ContentType::Json
78    }
79    /// 是否检查参数
80    fn params_check(&mut self) -> bool {
81        true
82    }
83    /// 请求body参数
84    fn params(&mut self) -> JsonValue {
85        object! {}
86    }
87    /// 成功响应
88    fn success(&mut self) -> ApiResponse {
89        let mut data = object! {};
90        data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0).example(0.into()).swagger();
91        data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "").example("成功".into()).swagger();
92        data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
93        data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true).example(true.into()).swagger();
94        ApiResponse::success(data, "请求成功")
95    }
96    /// 失败响应
97    fn error(&mut self) -> ApiResponse {
98        let mut data = object! {};
99        data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000).example(1000.into()).swagger();
100        data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "").example("失败".into()).swagger();
101        data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
102        data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false).example(false.into()).swagger();
103        ApiResponse::error(data, "请求失败")
104    }
105    /// 外部入口
106    fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
107        if self.public() && !self.method().str().is_empty() && self.method().str().to_lowercase() != request.method.str().to_lowercase() {
108            return Err(ApiResponse::fail(
109                -1,
110                format!(
111                    "Request type error: Actual [{}] Expected [{}]",
112                    request.method.str(),
113                    self.method().str()
114                ).as_str(),
115            ));
116        }
117        let params = self.params().clone();
118        if self.params_check() {
119            self.check(&mut request.query.clone(), self.query().clone())?;
120            self.check(&mut request.body, params)?;
121        }
122        let res = self.index(request.clone());
123        match res.success {
124            true => Ok(res),
125            false => Err(res),
126        }
127    }
128    /// 入参验证
129    fn check(&mut self, request: &mut JsonValue, params: JsonValue) -> Result<(), ApiResponse> {
130        let req = request.clone();
131        for (name, _) in req.entries() {
132            if !params.has_key(name) {
133                request.remove(name);
134            }
135        }
136        for (name, field) in params.entries() {
137            let require = field["require"].as_bool().unwrap_or(false);
138            let title = field["title"].as_str().unwrap_or("");
139            if request.has_key(name) {
140                // 判断输入类型
141                match field["mode"].as_str().unwrap() {
142                    "key" => {
143                        if !request[name].is_string() {
144                            return Err(ApiResponse::fail(
145                                900001,
146                                format!(
147                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
148                                    name, field["mode"]
149                                ).as_str(),
150                            ));
151                        }
152                        if require && request[name].is_empty() {
153                            return Err(ApiResponse::fail(
154                                900014,
155                                format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
156                            ));
157                        }
158                    }
159                    "text" | "table" => {
160                        if !request[name].is_string() {
161                            return Err(ApiResponse::fail(
162                                900002,
163                                format!(
164                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
165                                    name, field["mode"]
166                                ).as_str(),
167                            ));
168                        }
169                        if require && request[name].is_empty() {
170                            return Err(ApiResponse::fail(
171                                900002,
172                                format!("{} 必填", title).as_str(),
173                            ));
174                        }
175                    }
176                    "file" => {
177                        if !request[name].is_array() && !request[name].is_string() {
178                            return Err(ApiResponse::fail(
179                                900003,
180                                format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
181                            ));
182                        }
183                        if require && request[name].is_empty() {
184                            return Err(ApiResponse::fail(
185                                900002,
186                                format!("{} 必填", title).as_str(),
187                            ));
188                        }
189                    }
190                    "int" => {
191                        if !request[name].is_number() {
192                            return Err(ApiResponse::fail(
193                                900013,
194                                format!(
195                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
196                                    name, field["mode"]
197                                ).as_str(),
198                            ));
199                        }
200                    }
201                    "timestamp" => {
202                        if !request[name].is_number() {
203                            return Err(ApiResponse::fail(
204                                900013,
205                                format!(
206                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
207                                    name, field["mode"]
208                                ).as_str(),
209                            ));
210                        }
211                    }
212                    "float" => {
213                        if !request[name].is_string() && !request[name].is_number() {
214                            return Err(ApiResponse::fail(
215                                900023,
216                                format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
217                            ));
218                        }
219                        if require && request[name].is_empty() {
220                            return Err(ApiResponse::fail(
221                                900004,
222                                format!("{} 必填", title).as_str(),
223                            ));
224                        }
225                    }
226                    "string" | "code" | "pass" | "email" | "location" | "color" | "date" | "barcode" | "datetime" | "editor" => {
227                        if !request[name].is_string() {
228                            return Err(ApiResponse::fail(
229                                -1,
230                                format!(
231                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
232                                    name, field["mode"]
233                                ).as_str(),
234                            ));
235                        }
236                        if require && request[name].is_empty() {
237                            return Err(ApiResponse::fail(
238                                900004,
239                                format!("{} 必填", title).as_str(),
240                            ));
241                        }
242                    }
243                    "dict" => {
244                        if require && request[name].is_empty() {
245                            return Err(ApiResponse::fail(
246                                900005,
247                                format!("{} 必填", title).as_str(),
248                            ));
249                        }
250                    }
251                    "switch" => {
252                        if !request[name].is_boolean() {
253                            return Err(ApiResponse::fail(
254                                -1,
255                                format!(
256                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
257                                    name, field["mode"]
258                                ).as_str(),
259                            ));
260                        }
261                    }
262                    "select" => {
263                        if !request[name].is_array() && !request[name].is_string() {
264                            return Err(ApiResponse::fail(
265                                -1,
266                                format!(
267                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
268                                    name, field["mode"]
269                                ).as_str(),
270                            ));
271                        }
272                        let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
273                        if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
274                        {
275                            return Err(ApiResponse::fail(
276                                -1,
277                                format!(
278                                    "请求参数选项错误: 参数 [{}] 数据类型应为[{}]之内",
279                                    name, option
280                                ).as_str(),
281                            ));
282                        }
283                        if request[name].is_array() {
284                            let res1 = request[name].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>();
285                            let diff = res1.iter().filter(|&item| {
286                                !field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().contains(item)
287                            }).collect::<Vec<&&str>>();
288                            if !diff.is_empty() {
289                                return Err(ApiResponse::fail(
290                                    -1,
291                                    format!(
292                                        "请求参数选项错误: 参数 [{}] 数据 {:?} 应为[{:?}]范围之内",
293                                        name, diff, option
294                                    ).as_str(),
295                                ));
296                            }
297                        }
298                    }
299                    "radio" => {
300                        if !request[name].is_string() {
301                            return Err(ApiResponse::fail(
302                                -1,
303                                format!(
304                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
305                                    name, field["mode"], request[name]
306                                ).as_str(),
307                            ));
308                        }
309                        let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
310                        if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
311                        {
312                            return Err(ApiResponse::fail(
313                                -1,
314                                format!(
315                                    "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
316                                    name, request[name], option
317                                ).as_str(),
318                            ));
319                        }
320                    }
321                    "array" => {
322                        if !request[name].is_array() {
323                            return Err(ApiResponse::fail(
324                                900009,
325                                format!(
326                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
327                                    name, field["mode"]
328                                ).as_str(),
329                            ));
330                        }
331                        if require && request[name].is_empty() {
332                            return Err(ApiResponse::fail(
333                                900010,
334                                format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
335                            ));
336                        }
337                    }
338                    "object" => {
339                        if !request[name].is_object() {
340                            return Err(ApiResponse::fail(
341                                900009,
342                                format!(
343                                    "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
344                                    name, field["mode"]
345                                ).as_str(),
346                            ));
347                        }
348                        if require && request[name].is_empty() {
349                            return Err(ApiResponse::fail(
350                                900006,
351                                format!("{} 必填", title).as_str(),
352                            ));
353                        }
354                    }
355                    _ => {
356                        println!("检查未知类型: {}", field["mode"])
357                    }
358                }
359            } else {
360                if require {
361                    return Err(ApiResponse::fail(
362                        900007,
363                        format!("{} 必填", title).as_str(),
364                    ));
365                }
366                request[name] = field["def"].clone();
367            }
368        }
369        Ok(())
370    }
371    /// 内部入口
372    fn index(&mut self, request: Request) -> ApiResponse;
373    fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
374        params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
375        params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
376        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
377        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
378        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
379        params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
380        params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 50, "id").example("id".into()).field();
381        params
382    }
383    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
384    fn table_select(
385        &mut self,
386        request: JsonValue,
387        table_name: &str,
388        fields: Vec<&str>,
389    ) -> JsonValue {
390        let page = request["page"].as_i32().unwrap_or(1);
391        let limit = request["limit"].as_i32().unwrap_or(10);
392
393        let search = request["search"].as_str().unwrap_or("");
394
395        let field_id = request["field"].as_str().unwrap_or("id");
396
397        let where_or = request["where_or"].clone();
398        let where_and = request["where_and"].clone();
399
400        let mut tools = self.tools();
401        let db = tools.db.table(table_name);
402
403        if !search.is_empty() {
404            db.where_and(&fields.join("|"), "like", format!("%{}%", search).into());
405        }
406
407        for (key, value) in where_or.entries() {
408            if value.is_empty() {
409                continue;
410            }
411            if value.is_array() {
412                db.where_or(key, "between", value.clone());
413                db.where_or(key, "in", value.clone());
414            } else if value.is_boolean() {
415                db.where_or(key, "=", value.clone());
416            } else {
417                db.where_or(key, "like", format!("%{}%", value).into());
418            }
419        }
420
421        for value in where_and.members() {
422            db.where_and(
423                value[0].as_str().unwrap(),
424                value[1].as_str().unwrap(),
425                value[2].clone(),
426            );
427        }
428
429        let total = (db.clone().count().as_f64().unwrap() / limit as f64).ceil() as i64;
430        let mut db_list = db.clone();
431
432        db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
433
434        let mut data = db_list.page(page, limit).select();
435        let mut list = array![];
436        for item in data.members_mut() {
437            let value = item[field_id].clone();
438            item.remove(field_id);
439
440            let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
441
442            list.push(object! {
443                value: value,
444                label: label.join(" | ").clone(),
445            }).unwrap();
446        }
447        object! {
448            total:total,
449            data:list,
450        }
451    }
452    /// 菜单表格接收参数
453    fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
454        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
455        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
456        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
457        params
458    }
459    #[allow(clippy::too_many_arguments)]
460    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
461    fn table_menu(
462        &mut self,
463        request: JsonValue,
464        table_name: &str,
465        label_field: &str,
466        fields: JsonValue,
467
468        hidd_field: Vec<&str>,
469        show_field: Vec<&str>,
470
471        search_fields: Vec<&str>,
472        _filter_fields: Vec<&str>,
473    ) -> JsonValue {
474        let search = request["search"].as_str().unwrap_or("");
475
476        let order = request["order"].clone();
477        let where_or = request["where_or"].clone();
478        let where_and = request["where_and"].clone();
479        let mut columns = array![];
480        let mut search_name = vec![];
481        let mut search_field = vec![];
482        let mut filter_columns = vec![];
483        let mut table_fields = object! {};
484        let mut table_field_json = vec![];
485
486        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
487        alls_field.retain(|x| !hidd_field.contains(x));
488        if !show_field.is_empty() {
489            alls_field.retain(|x| show_field.contains(x) || *x == "id");
490        }
491
492        for item in alls_field.iter() {
493            let row = &fields[item.to_string()];
494            let field = row["field"].to_string();
495            let title = row["title"].to_string();
496            let mode = row["mode"].to_string();
497
498            if search_fields.contains(&field.as_str()) {
499                search_name.push(title);
500                search_field.push(field.clone());
501            }
502            filter_columns.push(self.filter_column(row.clone()));
503            columns.push(self.table_column(row.clone())).unwrap();
504            let mut table_field_info = object! {};
505            match mode.as_str() {
506                "table" => table_field_info = row.clone(),
507                "array" => table_field_json.push(field.clone()),
508                _ => {}
509            }
510            if !table_field_info.is_empty() {
511                table_fields[field.as_str()] = table_field_info;
512            }
513        }
514
515        let mut tools = self.tools();
516        let db = tools.db.table(table_name);
517
518        if !search.is_empty() {
519            db.where_and(
520                &search_field.join("|"),
521                "like",
522                format!("%{}%", search).into(),
523            );
524        }
525
526        for (key, value) in where_or.entries() {
527            if value.is_empty() {
528                continue;
529            }
530            if value.is_array() {
531                db.where_or(key, "between", value.clone());
532                db.where_or(key, "in", value.clone());
533            } else if value.is_boolean() {
534                db.where_or(key, "=", value.clone());
535            } else {
536                db.where_or(key, "like", format!("%{}%", value).into());
537            }
538        }
539
540        for value in where_and.members() {
541            db.where_and(
542                value[0].as_str().unwrap(),
543                value[1].as_str().unwrap(),
544                value[2].clone(),
545            );
546        }
547
548        let mut db_list = db.clone();
549
550        for item in order.members() {
551            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
552        }
553
554        let t = alls_field.join(",");
555        db_list.field(t.as_str());
556
557        if !table_field_json.is_empty() {
558            db_list.json(&table_field_json.join(","));
559        }
560
561        let mut data = db_list.select();
562
563        let mut table_datas = object! {};
564        let mut ids = HashMap::new();
565
566        for item in data.members_mut() {
567            for (field, _) in table_fields.entries() {
568                if table_datas[field].is_empty() {
569                    table_datas[field] = array![];
570                }
571                let _ = table_datas[field].push(item[field].clone());
572            }
573        }
574        for (field, info) in table_fields.entries_mut() {
575            let _ = info["fields"].push("id");
576            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
577            let table_name = info["table"].clone();
578            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();
579
580            for item in data_list.members_mut() {
581                let id = item["id"].as_str().unwrap_or("").to_string();
582                item.remove("id");
583                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
584                ids.insert(
585                    id.clone(),
586                    object! {
587                        value: id.clone(),
588                        label:label.join(" | ").clone(),
589                    },
590                );
591            }
592        }
593
594        for item in data.members_mut() {
595            for (field, _) in table_fields.entries() {
596                if item[field].is_empty() {
597                    continue;
598                }
599                item[field] = ids[item[field].as_str().unwrap()].clone();
600            }
601        }
602
603        object! {
604            data:data,
605            columns:columns,
606            search_name:search_name.join("/"),
607            filter_columns:filter_columns,
608            label_field:label_field,
609            btn_all:array![],
610            btn_api:array![]
611        }
612    }
613    /// 树型表格接收参数
614    fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
615        params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
616        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
617        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
618        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
619        params
620    }
621    #[allow(clippy::too_many_arguments)]
622    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
623    fn table_tree(
624        &mut self,
625        request: JsonValue,
626        table_name: &str,
627        pid_field: &str,
628        label_field: &str,
629        fields: JsonValue,
630        hidd_field: Vec<&str>,
631        show_field: Vec<&str>,
632        search_fields: Vec<&str>,
633        _filter_fields: Vec<&str>,
634    ) -> JsonValue {
635        let search = request["search"].as_str().unwrap_or("");
636
637        let pid = request["pid"].clone();
638
639        let order = request["order"].clone();
640        let where_or = request["where_or"].clone();
641        let where_and = request["where_and"].clone();
642        let mut columns = array![];
643        let mut search_name = vec![];
644        let mut search_field = vec![];
645        let mut filter_columns = vec![];
646        let mut table_field_json = vec![];
647        let mut table_fields = object! {};
648
649        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
650        alls_field.retain(|x| !hidd_field.contains(x));
651        if !show_field.is_empty() {
652            alls_field.retain(|x| show_field.contains(x) || *x == "id");
653        }
654
655        for item in alls_field.iter() {
656            let row = fields[item.to_string()].clone();
657            let field = row["field"].to_string();
658            let title = row["title"].to_string();
659            let mode = row["mode"].to_string();
660
661            if search_fields.contains(&field.as_str()) {
662                search_name.push(title);
663                search_field.push(field.clone());
664            }
665            filter_columns.push(self.filter_column(row.clone()));
666            columns.push(self.table_column(row.clone())).unwrap();
667            let mut table_field_info = object! {};
668            match mode.as_str() {
669                "table" => table_field_info = row.clone(),
670                "array" => table_field_json.push(field.clone()),
671                _ => {}
672            }
673            if !table_field_info.is_empty() {
674                table_fields[field.as_str()] = table_field_info;
675            }
676        }
677
678        let mut tools = self.tools();
679        let db = tools.db.table(table_name);
680        db.where_and(pid_field, "=", pid);
681        if !search.is_empty() {
682            db.where_and(
683                &search_field.join("|"),
684                "like",
685                format!("%{}%", search).into(),
686            );
687        }
688
689        for (key, value) in where_or.entries() {
690            if value.is_empty() {
691                continue;
692            }
693            if value.is_array() {
694                // db.where_or(key, "between", value.clone());
695                db.where_or(key, "in", value.clone());
696            } else if value.is_boolean() {
697                db.where_or(key, "=", value.clone());
698            } else {
699                db.where_or(key, "like", format!("%{}%", value).into());
700            }
701        }
702
703        for value in where_and.members() {
704            db.where_and(
705                value[0].as_str().unwrap(),
706                value[1].as_str().unwrap(),
707                value[2].clone(),
708            );
709        }
710
711        let mut db_list = db.clone();
712
713        for item in order.members() {
714            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
715        }
716        let t = alls_field.join(",");
717        db_list.field(t.as_str());
718        if !table_field_json.is_empty() {
719            db_list.json(&table_field_json.join(","));
720        }
721        let mut data = db_list.select();
722
723        let mut table_datas = object! {};
724        let mut ids = HashMap::new();
725
726        for item in data.members_mut() {
727            for (field, _) in table_fields.entries() {
728                if table_datas[field].is_empty() {
729                    table_datas[field] = array![];
730                }
731                let _ = table_datas[field].push(item[field].clone());
732            }
733        }
734        for (field, info) in table_fields.entries_mut() {
735            let _ = info["fields"].push("id");
736            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
737            let table_name = info["table"].clone();
738            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();
739
740            for item in data_list.members_mut() {
741                let id = item["id"].as_str().unwrap_or("").to_string();
742                item.remove("id");
743                let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
744                ids.insert(
745                    id.clone(),
746                    object! {
747                        value: id.clone(),
748                        label:label.join(" | ").clone(),
749                    },
750                );
751            }
752        }
753
754        let mut list = array![];
755        for item in data.members_mut() {
756            for (field, _) in table_fields.entries() {
757                if item[field].is_empty() {
758                    continue;
759                }
760                item[field] = ids[item[field].as_str().unwrap()].clone();
761            }
762            let _ = list.push(object! {
763                id:item["id"].as_str().unwrap(),
764                label:item[label_field].as_str().unwrap(),
765                data:item.clone(),
766            });
767        }
768
769        object! {
770            data:list,
771            columns:columns,
772            search_name:search_name.join("/"),
773            filter_columns:filter_columns,
774            pid_field:pid_field,
775            btn_all:array![],
776            btn_api:array![]
777        }
778    }
779    /// 表格接收参数
780    fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
781        params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
782        params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
783        params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
784        params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
785        params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
786        params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
787        params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
788        params
789    }
790    /// 列表表格渲染
791    /// * table_name 表名
792    /// * fields 全部模型字段集合
793    /// * hidd_field 需要隐藏的字段集合
794    /// * show_field 需要显示的字段集合
795    /// * search_fields 搜索字段集合
796    /// * filter_fields 高级搜索字段集合
797    #[allow(clippy::too_many_arguments)]
798    #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
799    fn table_list(
800        &mut self,
801        request: JsonValue,
802        table_name: &str,
803        fields: JsonValue,
804        hidd_field: Vec<&str>,
805        show_field: Vec<&str>,
806        search_fields: Vec<&str>,
807        filter_fields: Vec<&str>,
808    ) -> JsonValue {
809        let page = request["page"].as_i32().unwrap_or(1);
810        let limit = request["limit"].as_i32().unwrap_or(10);
811        let search = request["search"].as_str().unwrap_or("");
812        let order = request["order"].clone();
813        let where_or = request["where_or"].clone();
814        let where_and = request["where_and"].clone();
815        let mut columns = array![];
816        let mut search_name = vec![];
817        let mut search_field = vec![];
818        let mut filter_columns = vec![];
819
820        let mut table_fields = object! {};
821
822        let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
823        alls_field.retain(|x| !hidd_field.contains(x));
824        if !show_field.is_empty() {
825            alls_field.retain(|x| show_field.contains(x) || *x == "id");
826        }
827
828        for item in alls_field.iter() {
829            let key = item.to_string();
830            let field = fields[key.clone()]["field"].as_str().unwrap();
831            let title = fields[key.clone()]["title"].as_str().unwrap();
832            let mode = fields[key.clone()]["mode"].as_str().unwrap();
833
834            if search_fields.contains(&field) {
835                search_name.push(title);
836                search_field.push(field);
837            }
838            if filter_fields.contains(&field) {
839                filter_columns.push(self.filter_column(fields[key.clone()].clone()));
840            }
841            columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
842            let table_field_info = if mode == "table" {
843                fields[key.clone()].clone()
844            } else {
845                JsonValue::Null
846            };
847            if !table_field_info.is_empty() {
848                table_fields[field] = table_field_info;
849            }
850        }
851
852        let mut tools = self.tools();
853        let db = tools.db.table(table_name);
854
855        if !search.is_empty() {
856            db.where_and(
857                &search_field.join("|"),
858                "like",
859                format!("%{}%", search).into(),
860            );
861        }
862
863        for (key, value) in where_or.entries() {
864            if value.is_empty() {
865                continue;
866            }
867            if value.is_array() {
868                // db.where_or(key, "between", value.clone());
869                db.where_or(key, "in", value.clone());
870            } else if value.is_boolean() {
871                db.where_or(key, "=", value.clone());
872            } else {
873                db.where_or(key, "like", format!("%{}%", value).into());
874            }
875        }
876
877        for value in where_and.members() {
878            db.where_and(
879                value[0].as_str().unwrap(),
880                value[1].as_str().unwrap(),
881                value[2].clone(),
882            );
883        }
884
885        let total = db.clone().count().as_f64().unwrap();
886        let mut db_list = db.clone();
887
888        for item in order.members() {
889            db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
890        }
891
892        let t = alls_field.join(",");
893        db_list.field(t.as_str());
894        let mut data = db_list.page(page, limit).select();
895
896        let mut table_datas = object! {};
897        let mut ids = HashMap::new();
898
899        for item in data.members_mut() {
900            if table_fields.is_empty() {
901                continue;
902            }
903            for (field, _) in table_fields.entries() {
904                if table_datas[field].is_empty() {
905                    table_datas[field] = array![];
906                }
907                let _ = table_datas[field].push(item[field].clone());
908            }
909        }
910        for (field, info) in table_fields.entries_mut() {
911            let _ = info["fields"].push("id");
912            let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
913            let table_name = info["table"].clone();
914            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();
915
916            for item in data_list.members_mut() {
917                let id = item["id"].as_str().unwrap_or("").to_string();
918                item.remove("id");
919                let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
920                ids.insert(
921                    id.clone(),
922                    object! {
923                        value: id.clone(),
924                        label:label.join(" | ").clone(),
925                    },
926                );
927            }
928        }
929
930        for item in data.members_mut() {
931            if table_fields.is_empty() {
932                continue;
933            }
934            for (field, _) in table_fields.entries() {
935                if item[field].is_empty() {
936                    continue;
937                }
938                let key = item[field].as_str().unwrap_or("");
939                if key.is_empty() {
940                    continue;
941                }
942                if !ids.contains_key(key) {
943                    continue;
944                }
945                item[field] = ids.get(key).unwrap().clone();
946            }
947        }
948
949        object! {
950            total:total,
951            data:data,
952            columns:columns,
953            search_name:search_name.join("/"),
954            filter_columns:filter_columns,
955            btn_all:array![],
956            btn_api:array![],
957            btn_ids:array![]
958        }
959    }
960    fn table_column(&mut self, field: JsonValue) -> JsonValue {
961        object! {
962            name:field["field"].clone(),
963            label:field["title"].clone(),
964            align:"center",
965            field:field["field"].clone(),
966            sortable:true,
967            mode:field["mode"].clone(),
968            dec:field["dec"].clone(),
969            fields:field["fields"].clone()
970        }
971    }
972    fn filter_column(&mut self, field: JsonValue) -> JsonValue {
973        object! {
974            name:field["field"].clone(),
975            label:field["title"].clone(),
976            mode:field["mode"].clone(),
977            option:field["option"].clone(),
978            api:field["api"].clone(),
979            fields:field["fields"].clone()
980        }
981    }
982    /// 使用工具
983    fn tools(&mut self) -> Tools {
984        let tools = PLUGIN_TOOLS.lock().unwrap();
985        let tools = tools.get("tools").unwrap().clone();
986        tools
987    }
988    /// 使用配置
989    fn config(&mut self, name: &str) -> JsonValue {
990        if CONFIG.lock().unwrap().get(name).is_none() {
991            object! {}
992        } else {
993            CONFIG.lock().unwrap().get(name).unwrap().clone()
994        }
995    }
996    /// 按钮信息
997    /// * cnd 显示条件 vec![vec!["xxx","=","yyy"],vec!["zzz","=","eee"]]
998    fn btn(&mut self) -> Btn {
999        let mut btn = Btn::new(self.api().as_str());
1000        btn.fields(self.params().clone());
1001        btn.tags(self.tags());
1002        btn.icon(self.icon());
1003        btn.desc(self.description());
1004        btn.auth(self.auth());
1005        btn.public(self.public());
1006        btn.title(self.title());
1007        btn.btn_type(BtnType::Api);
1008        btn.btn_color(BtnColor::Primary);
1009        btn.path(self.api().clone().replace(".", "/").as_str());
1010        btn.pass(false);
1011        btn.addon();
1012        btn
1013    }
1014    /// 设置全局变量
1015    fn set_global_data(&mut self, key: &str, value: JsonValue) {
1016        GLOBAL_DATA.with(|data| {
1017            data.borrow_mut()[key] = value;
1018        });
1019    }
1020    /// 获取全局变量数据
1021    fn get_global_data(&mut self) -> JsonValue {
1022        GLOBAL_DATA.with(|data| {
1023            data.borrow().clone()
1024        })
1025    }
1026    /// 获取全局变量指定字段数据
1027    fn get_global_data_key(&mut self, key: &str) -> JsonValue {
1028        GLOBAL_DATA.with(|data| {
1029            data.borrow()[key].clone()
1030        })
1031    }
1032}
1033#[derive(Debug, Clone)]
1034pub struct Btn {
1035    api: String,
1036    title: String,
1037    desc: String,
1038    tags: &'static [&'static str],
1039    auth: bool,
1040    public: bool,
1041    btn_type: BtnType,
1042    color: BtnColor,
1043    icon: String,
1044    cnd: Vec<JsonValue>,
1045    url: String,
1046    path: String,
1047    fields: JsonValue,
1048    addon: String,
1049    /// 是否需要密码
1050    pass: bool,
1051}
1052impl Btn {
1053    pub fn new(api: &str) -> Self {
1054        Self {
1055            api: api.to_string(),
1056            title: "".to_string(),
1057            desc: "".to_string(),
1058            btn_type: BtnType::Api,
1059            color: BtnColor::Primary,
1060            icon: "".to_string(),
1061            auth: false,
1062            public: false,
1063            cnd: vec![],
1064            url: "".to_string(),
1065            path: "".to_string(),
1066            fields: object! {},
1067            tags: &[],
1068            pass: false,
1069            addon: "".to_string(),
1070        }
1071    }
1072
1073    pub fn addon(&mut self) -> &mut Self {
1074        self.addon = self.api.split('.').nth(0).unwrap().to_string();
1075        self
1076    }
1077    pub fn path(&mut self, path: &str) -> &mut Self {
1078        self.path = path.to_string();
1079        self
1080    }
1081    pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1082        self.cnd = cnd;
1083        self
1084    }
1085    pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1086        self.btn_type = btn_type;
1087        self
1088    }
1089    pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1090        self.color = btn_color;
1091        self
1092    }
1093    pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1094        self.fields = fields;
1095        self
1096    }
1097    pub fn pass(&mut self, pass: bool) -> &mut Self {
1098        self.pass = pass;
1099        self
1100    }
1101    pub fn url(&mut self, url: &str) -> &mut Self {
1102        self.url = url.to_string();
1103        self
1104    }
1105    pub fn title(&mut self, title: &str) -> &mut Self {
1106        self.title = title.to_string();
1107        self
1108    }
1109    pub fn desc(&mut self, desc: &str) -> &mut Self {
1110        self.desc = desc.to_string();
1111        self
1112    }
1113    pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1114        self.tags = tags;
1115        self
1116    }
1117    pub fn public(&mut self, public: bool) -> &mut Self {
1118        self.public = public;
1119        self
1120    }
1121    pub fn auth(&mut self, auth: bool) -> &mut Self {
1122        self.auth = auth;
1123        self
1124    }
1125    pub fn icon(&mut self, icon: &str) -> &mut Self {
1126        self.icon = icon.to_string();
1127        self
1128    }
1129    pub fn json(&mut self) -> JsonValue {
1130        object! {
1131            addon:self.addon.to_string() ,
1132            api:self.api.clone(),
1133            title:self.title.clone(),
1134            desc:self.desc.clone(),
1135            auth:self.auth,
1136            public:self.public,
1137            btn_type:self.btn_type.clone().str(),
1138            color:self.color.clone().str(),
1139            icon:self.icon.clone(),
1140            cnd:self.cnd.clone(),
1141            url:self.url.clone(),
1142            path:self.path.clone(),
1143            fields:self.fields.clone(),
1144            tags:self.tags,
1145            pass:self.pass,
1146        }
1147    }
1148}
1149
1150/// 接口类型
1151#[derive(Debug, Clone)]
1152pub enum InterfaceType {
1153    API,
1154    BTN,
1155    MENU,
1156}
1157
1158impl InterfaceType {
1159    pub fn str(&self) -> &'static str {
1160        match self {
1161            InterfaceType::API => "api",
1162            InterfaceType::BTN => "btn",
1163            InterfaceType::MENU => "menu",
1164        }
1165    }
1166    pub fn types() -> Vec<&'static str> {
1167        vec!["api", "btn", "menu"]
1168    }
1169}
1170
1171/// 按钮类型
1172#[derive(Debug, Clone)]
1173pub enum BtnType {
1174    /// 表单
1175    Form,
1176    /// 表单下载
1177    FormDownload,
1178    /// 表单自定义
1179    FormCustom,
1180    FormData,
1181    /// 外部跳转
1182    Url,
1183    /// api请求
1184    Api,
1185    /// 下载
1186    Download,
1187    /// 内部跳转
1188    Path,
1189    /// 弹窗-定制页面
1190    DialogCustom,
1191    /// 表单->API->弹出自定义窗口
1192    FormApiDialogCustom,
1193    /// 预览
1194    Preview,
1195}
1196
1197impl BtnType {
1198    fn str(self) -> &'static str {
1199        match self {
1200            BtnType::Form => "form",
1201            BtnType::FormDownload => "form_download",
1202            BtnType::FormCustom => "form_custom",
1203            BtnType::FormData => "form_data",
1204            BtnType::Api => "api",
1205            BtnType::Download => "download",
1206            BtnType::Url => "url",
1207            BtnType::Path => "path",
1208            BtnType::DialogCustom => "dialog_custom",
1209            BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1210            BtnType::Preview => "preview",
1211        }
1212    }
1213}
1214/// 按钮颜色
1215#[derive(Debug, Clone)]
1216pub enum BtnColor {
1217    Primary,
1218    Red,
1219    Blue,
1220    Yellow,
1221    Green,
1222}
1223
1224impl BtnColor {
1225    fn str(self) -> &'static str {
1226        match self {
1227            BtnColor::Primary => "primary",
1228            BtnColor::Red => "negative",
1229            BtnColor::Blue => "info",
1230            BtnColor::Yellow => "warning",
1231            BtnColor::Green => "positive",
1232        }
1233    }
1234}
1235
1236
1237pub struct Dashboard {
1238    /// 名称
1239    title: String,
1240    /// 数据
1241    data: JsonValue,
1242    /// 显示样式
1243    model: DashboardModel,
1244    /// 渲染样式
1245    class: String,
1246    /// 描述
1247    desc: String,
1248}
1249impl Dashboard {
1250    pub fn new(title: &str) -> Dashboard {
1251        Dashboard {
1252            title: title.to_string(),
1253            data: JsonValue::Null,
1254            model: DashboardModel::Number,
1255            class: "col-4".to_string(),
1256            desc: "".to_string(),
1257        }
1258    }
1259    pub fn data(&mut self, data: JsonValue) -> &mut Self {
1260        self.data = data;
1261        self
1262    }
1263    pub fn class(&mut self, name: &str) -> &mut Self {
1264        self.class = name.to_string();
1265        self
1266    }
1267    pub fn model(&mut self, dashboard_model: DashboardModel) -> &mut Self {
1268        self.model = dashboard_model;
1269        self
1270    }
1271    pub fn desc(&mut self, desc: &str) -> &mut Self {
1272        self.desc = desc.to_string();
1273        self
1274    }
1275    pub fn json(&self) -> JsonValue {
1276        object! {
1277            title: self.title.clone(),
1278            data: self.data.clone(),
1279            class: self.class.clone(),
1280            model: self.model.str(),
1281            desc: self.desc.clone(),
1282        }
1283    }
1284}
1285
1286pub enum DashboardModel {
1287    Number,
1288    EchartsBar,
1289}
1290
1291impl DashboardModel {
1292    pub fn str(&self) -> &'static str {
1293        match self {
1294            Self::Number => "number",
1295            Self::EchartsBar => "echarts-bar",
1296        }
1297    }
1298}