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