br_addon/
action.rs

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