br_addon/
action.rs

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