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