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