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