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