br_addon/
action.rs

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