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