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