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