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