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