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