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