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