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
9pub trait Action {
11 fn _name(&self) -> String {
13 type_name::<Self>()
14 .rsplit("::")
15 .next()
16 .unwrap()
17 .to_lowercase()
18 }
19 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 fn token(&self) -> bool {
29 true
30 }
31 fn version(&self) -> &'static str {
33 "v1"
34 }
35 fn author(&self) -> &'static str {
37 ""
38 }
39 fn sort(&self) -> usize {
40 99
41 }
42 fn title(&self) -> &'static str;
44 fn description(&self) -> &'static str {
46 ""
47 }
48 fn path(&self) -> &'static str {
50 ""
51 }
52 fn query(&self) -> JsonValue {
54 object! {}
55 }
56 fn tags(&self) -> &'static [&'static str] {
58 &[]
59 }
60 fn icon(&self) -> &'static str {
61 ""
62 }
63 fn public(&self) -> bool {
65 true
66 }
67 fn auth(&mut self) -> bool {
69 true
70 }
71 fn interface_type(&mut self) -> InterfaceType {
73 InterfaceType::API
74 }
75 fn method(&mut self) -> Method {
77 Method::Post
78 }
79 fn content_type(&mut self) -> ContentType {
81 ContentType::Json
82 }
83 fn params(&mut self) -> JsonValue {
85 object! {}
86 }
87 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 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 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 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 if request.has_key(name) {
150 match field["mode"].as_str().unwrap() {
152 "int" => {
153 if !request[name].is_number() {
154 return Err(ApiResponse::fail(
155 -1,
156 format!(
157 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
158 name, field["mode"]
159 )
160 .as_str(),
161 ));
162 }
163 }
164 "string" => {
165 if !request[name].is_string() {
166 return Err(ApiResponse::fail(
167 -1,
168 format!(
169 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
170 name, field["mode"]
171 )
172 .as_str(),
173 ));
174 }
175 if require && request[name].is_empty() {
176 return Err(ApiResponse::fail(
177 -1,
178 format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
179 ));
180 }
181 }
182 "switch" => {
183 if !request[name].is_boolean() {
184 return Err(ApiResponse::fail(
185 -1,
186 format!(
187 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
188 name, field["mode"]
189 )
190 .as_str(),
191 ));
192 }
193 }
194 "select" => {
195 if !request[name].is_array() && !request[name].is_string() {
196 return Err(ApiResponse::fail(
197 -1,
198 format!(
199 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
200 name, field["mode"]
201 )
202 .as_str(),
203 ));
204 }
205 let option = field["option"]
206 .members()
207 .map(|m| m.as_str().unwrap_or(""))
208 .collect::<Vec<&str>>()
209 .join(",");
210 if request[name].is_string()
211 && !field["option"].contains(request[name].as_str().unwrap_or(""))
212 {
213 return Err(ApiResponse::fail(
214 -1,
215 format!(
216 "请求参数选项错误: 参数 [{}] 数据类型应为[{}]之内",
217 name, option
218 )
219 .as_str(),
220 ));
221 }
222 if request[name].is_array() {
223 let res1 = request[name]
224 .members()
225 .map(|m| m.as_str().unwrap_or(""))
226 .collect::<Vec<&str>>();
227 let diff = res1
228 .iter()
229 .filter(|&item| {
230 !field["option"]
231 .members()
232 .map(|m| m.as_str().unwrap_or(""))
233 .collect::<Vec<&str>>()
234 .contains(item)
235 })
236 .collect::<Vec<&&str>>();
237 if !diff.is_empty() {
238 return Err(ApiResponse::fail(
239 -1,
240 format!(
241 "请求参数选项错误: 参数 [{}] 数据 {:?} 应为[{:?}]范围之内",
242 name, diff, option
243 )
244 .as_str(),
245 ));
246 }
247 }
248 }
249 "radio" => {
250 if !request[name].is_string() {
251 return Err(ApiResponse::fail(
252 -1,
253 format!(
254 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
255 name, field["mode"], request[name]
256 )
257 .as_str(),
258 ));
259 }
260 let option = field["option"]
261 .members()
262 .map(|m| m.as_str().unwrap_or(""))
263 .collect::<Vec<&str>>()
264 .join(",");
265 if request[name].is_string()
266 && !field["option"].contains(request[name].as_str().unwrap_or(""))
267 {
268 return Err(ApiResponse::fail(
269 -1,
270 format!(
271 "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
272 name, request[name], option
273 )
274 .as_str(),
275 ));
276 }
277 }
278 _ => {
279 }
281 }
282 } else {
283 if require {
284 return Err(ApiResponse::fail(
285 -1,
286 format!("请求参数错误: 参数[{}]必填", name).as_str(),
287 ));
288 }
289 request[name] = field["def"].clone();
290 }
291 }
292 Ok(())
293 }
294 fn index(&mut self, request: Request) -> ApiResponse;
296 fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
297 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1)
298 .example(1.into())
299 .field();
300 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10)
301 .example(10.into())
302 .field();
303 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
304 .example("".into())
305 .field();
306 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
307 .example(array![])
308 .field();
309 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
310 .example(array![])
311 .field();
312 params
313 }
314 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
315 fn table_select(
316 &mut self,
317 request: JsonValue,
318 table_name: &str,
319 mut fields: Vec<&str>,
320 ) -> JsonValue {
321 let page = request["page"].as_i32().unwrap_or(1);
322 let limit = request["limit"].as_i32().unwrap_or(10);
323
324 let search = request["search"].as_str().unwrap_or("");
325
326 let where_or = request["where_or"].clone();
327 let where_and = request["where_and"].clone();
328
329 let mut tools = self.tools();
330 let db = tools.db.table(table_name);
331
332 if !search.is_empty() {
333 db.where_and(&fields.join("|"), "like", format!("%{}%", search).into());
334 }
335
336 for (key, value) in where_or.entries() {
337 if value.is_empty() {
338 continue;
339 }
340 if value.is_array() {
341 db.where_or(key, "between", value.clone());
342 db.where_or(key, "in", value.clone());
343 } else if value.is_boolean() {
344 db.where_or(key, "=", value.clone());
345 } else {
346 db.where_or(key, "like", format!("%{}%", value).into());
347 }
348 }
349
350 for value in where_and.members() {
351 db.where_and(
352 value[0].as_str().unwrap(),
353 value[1].as_str().unwrap(),
354 value[2].clone(),
355 );
356 }
357
358 let total = (db.clone().count().as_f64().unwrap() / limit as f64).ceil() as i64;
359 let mut db_list = db.clone();
360
361 fields.push("id");
362 db_list.field(&fields.join(","));
363
364 let mut data = db_list.page(page, limit).select();
365 let mut list = array![];
366 for item in data.members_mut() {
367 let value = item["id"].clone();
368 item.remove("id");
369
370 let label = item
371 .entries()
372 .map(|(_, v)| v.as_str().unwrap())
373 .collect::<Vec<&str>>();
374
375 list.push(object! {
376 value: value,
377 label: label.join(" | ").clone(),
378 })
379 .unwrap();
380 }
381 object! {
382 total:total,
383 data:list,
384 }
385 }
386 fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
388 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
389 .example("".into())
390 .field();
391 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
392 .example(array![])
393 .field();
394 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
395 .example(array![])
396 .field();
397 params
398 }
399 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
400 fn table_menu(
401 &mut self,
402 request: JsonValue,
403 table_name: &str,
404 label_field: &str,
405 fields: JsonValue,
406
407 hidd_field: Vec<&str>,
408 show_field: Vec<&str>,
409
410 search_fields: Vec<&str>,
411 _filter_fields: Vec<&str>,
412 ) -> JsonValue {
413 let search = request["search"].as_str().unwrap_or("");
414
415 let order = request["order"].clone();
416 let where_or = request["where_or"].clone();
417 let where_and = request["where_and"].clone();
418 let mut columns = array![];
419 let mut search_name = vec![];
420 let mut search_field = vec![];
421 let mut filter_columns = vec![];
422 let mut table_fields = object! {};
423 let mut table_field_json = vec![];
424
425 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
426 alls_field.retain(|x| !hidd_field.contains(x));
427 if !show_field.is_empty() {
428 alls_field.retain(|x| show_field.contains(x) || *x == "id");
429 }
430
431 for item in alls_field.iter() {
432 let row = fields[item.clone()].clone();
433 let field = row["field"].to_string();
434 let title = row["title"].to_string();
435 let mode = row["mode"].to_string();
436
437 if search_fields.contains(&field.as_str()) {
438 search_name.push(title);
439 search_field.push(field.clone());
440 }
441 filter_columns.push(self.filter_column(row.clone()));
442 columns.push(self.table_column(row.clone())).unwrap();
443 let mut table_field_info = object! {};
444 match mode.as_str() {
445 "table" => table_field_info = row.clone(),
446 "array" => table_field_json.push(field.clone()),
447 _ => {}
448 }
449 if !table_field_info.is_empty() {
450 table_fields[field.as_str()] = table_field_info;
451 }
452 }
453
454 let mut tools = self.tools();
455 let db = tools.db.table(table_name);
456
457 if !search.is_empty() {
458 db.where_and(
459 &search_field.join("|"),
460 "like",
461 format!("%{}%", search).into(),
462 );
463 }
464
465 for (key, value) in where_or.entries() {
466 if value.is_empty() {
467 continue;
468 }
469 if value.is_array() {
470 db.where_or(key, "between", value.clone());
471 db.where_or(key, "in", value.clone());
472 } else if value.is_boolean() {
473 db.where_or(key, "=", value.clone());
474 } else {
475 db.where_or(key, "like", format!("%{}%", value).into());
476 }
477 }
478
479 for value in where_and.members() {
480 db.where_and(
481 value[0].as_str().unwrap(),
482 value[1].as_str().unwrap(),
483 value[2].clone(),
484 );
485 }
486
487 let mut db_list = db.clone();
488
489 for item in order.members() {
490 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
491 }
492
493 let t = alls_field.join(",");
494 db_list.field(t.as_str());
495
496 if !table_field_json.is_empty() {
497 db_list.json(&table_field_json.join(","));
498 }
499
500 let mut data = db_list.select();
501
502 let mut table_datas = object! {};
503 let mut ids = HashMap::new();
504
505 for item in data.members_mut() {
506 for (field, _) in table_fields.entries() {
507 if table_datas[field].is_empty() {
508 table_datas[field] = array![];
509 }
510 let _ = table_datas[field].push(item[field].clone());
511 }
512 }
513 for (field, info) in table_fields.entries_mut() {
514 let _ = info["fields"].push("id");
515 let fields_k = info["fields"]
516 .members()
517 .map(|x| x.as_str().unwrap())
518 .collect::<Vec<&str>>();
519 let table_name = info["table"].clone();
520 let mut data_list = self
521 .tools()
522 .db
523 .table(table_name.as_str().unwrap())
524 .where_and("id", "in", table_datas[field].clone())
525 .field(&fields_k.join(","))
526 .select();
527
528 for item in data_list.members_mut() {
529 let id = item["id"].as_str().unwrap_or("").to_string();
530 item.remove("id");
531 let label = item
532 .entries()
533 .map(|(_, v)| v.as_str().unwrap())
534 .collect::<Vec<&str>>();
535 ids.insert(
536 id.clone(),
537 object! {
538 value: id.clone(),
539 label:label.join(" | ").clone(),
540 },
541 );
542 }
543 }
544
545 for item in data.members_mut() {
546 for (field, _) in table_fields.entries() {
547 if item[field].is_empty() {
548 continue;
549 }
550 item[field] = ids[item[field].as_str().unwrap()].clone();
551 }
552 }
553
554 object! {
555 data:data,
556 columns:columns,
557 search_name:search_name.join("/"),
558 filter_columns:filter_columns,
559 label_field:label_field,
560 btn_all:array![],
561 btn_api:array![]
562 }
563 }
564 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
566 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "")
567 .example("".into())
568 .field();
569 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
570 .example("".into())
571 .field();
572 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
573 .example(array![])
574 .field();
575 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
576 .example(array![])
577 .field();
578 params
579 }
580 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
581 fn table_tree(
582 &mut self,
583 request: JsonValue,
584 table_name: &str,
585 pid_field: &str,
586 label_field: &str,
587 fields: JsonValue,
588 hidd_field: Vec<&str>,
589 show_field: Vec<&str>,
590 search_fields: Vec<&str>,
591 _filter_fields: Vec<&str>,
592 ) -> JsonValue {
593 let search = request["search"].as_str().unwrap_or("");
594
595 let pid = request["pid"].clone();
596
597 let order = request["order"].clone();
598 let where_or = request["where_or"].clone();
599 let where_and = request["where_and"].clone();
600 let mut columns = array![];
601 let mut search_name = vec![];
602 let mut search_field = vec![];
603 let mut filter_columns = vec![];
604 let mut table_field_json = vec![];
605 let mut table_fields = object! {};
606
607 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
608 alls_field.retain(|x| !hidd_field.contains(x));
609 if !show_field.is_empty() {
610 alls_field.retain(|x| show_field.contains(x) || *x == "id");
611 }
612
613 for item in alls_field.iter() {
614 let row = fields[item.clone()].clone();
615 let field = row["field"].to_string();
616 let title = row["title"].to_string();
617 let mode = row["mode"].to_string();
618
619 if search_fields.contains(&field.as_str()) {
620 search_name.push(title);
621 search_field.push(field.clone());
622 }
623 filter_columns.push(self.filter_column(row.clone()));
624 columns.push(self.table_column(row.clone())).unwrap();
625 let mut table_field_info = object! {};
626 match mode.as_str() {
627 "table" => table_field_info = row.clone(),
628 "array" => table_field_json.push(field.clone()),
629 _ => {}
630 }
631 if !table_field_info.is_empty() {
632 table_fields[field.as_str()] = table_field_info;
633 }
634 }
635
636 let mut tools = self.tools();
637 let db = tools.db.table(table_name);
638 db.where_and(pid_field, "=", pid);
639 if !search.is_empty() {
640 db.where_and(
641 &search_field.join("|"),
642 "like",
643 format!("%{}%", search).into(),
644 );
645 }
646
647 for (key, value) in where_or.entries() {
648 if value.is_empty() {
649 continue;
650 }
651 if value.is_array() {
652 db.where_or(key, "in", value.clone());
654 } else if value.is_boolean() {
655 db.where_or(key, "=", value.clone());
656 } else {
657 db.where_or(key, "like", format!("%{}%", value).into());
658 }
659 }
660
661 for value in where_and.members() {
662 db.where_and(
663 value[0].as_str().unwrap(),
664 value[1].as_str().unwrap(),
665 value[2].clone(),
666 );
667 }
668
669 let mut db_list = db.clone();
670
671 for item in order.members() {
672 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
673 }
674 let t = alls_field.join(",");
675 db_list.field(t.as_str());
676 if !table_field_json.is_empty() {
677 db_list.json(&table_field_json.join(","));
678 }
679 let mut data = db_list.select();
680
681 let mut table_datas = object! {};
682 let mut ids = HashMap::new();
683
684 for item in data.members_mut() {
685 for (field, _) in table_fields.entries() {
686 if table_datas[field].is_empty() {
687 table_datas[field] = array![];
688 }
689 let _ = table_datas[field].push(item[field].clone());
690 }
691 }
692 for (field, info) in table_fields.entries_mut() {
693 let _ = info["fields"].push("id");
694 let fields_k = info["fields"]
695 .members()
696 .map(|x| x.as_str().unwrap())
697 .collect::<Vec<&str>>();
698 let table_name = info["table"].clone();
699 let mut data_list = self
700 .tools()
701 .db
702 .table(table_name.as_str().unwrap())
703 .where_and("id", "in", table_datas[field].clone())
704 .field(&fields_k.join(","))
705 .select();
706
707 for item in data_list.members_mut() {
708 let id = item["id"].as_str().unwrap_or("").to_string();
709 item.remove("id");
710 let label = item
711 .entries()
712 .map(|(_, v)| v.as_str().unwrap())
713 .collect::<Vec<&str>>();
714 ids.insert(
715 id.clone(),
716 object! {
717 value: id.clone(),
718 label:label.join(" | ").clone(),
719 },
720 );
721 }
722 }
723
724 let mut list = array![];
725 for item in data.members_mut() {
726 for (field, _) in table_fields.entries() {
727 if item[field].is_empty() {
728 continue;
729 }
730 item[field] = ids[item[field].as_str().unwrap()].clone();
731 }
732 let _ = list.push(object! {
733 id:item["id"].as_str().unwrap(),
734 label:item[label_field].as_str().unwrap(),
735 data:item.clone(),
736 });
737 }
738
739 object! {
740 data:list,
741 columns:columns,
742 search_name:search_name.join("/"),
743 filter_columns:filter_columns,
744 pid_field:pid_field,
745 btn_all:array![],
746 btn_api:array![]
747 }
748 }
749 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
751 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1)
752 .example(1.into())
753 .field();
754 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10)
755 .example(10.into())
756 .field();
757 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
758 .example("".into())
759 .field();
760 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![])
761 .example(array![array!["id", false]])
762 .field();
763 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
764 .example(array![])
765 .field();
766 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
767 .example(array![])
768 .field();
769 params
770 }
771 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
779 fn table_list(
780 &mut self,
781 request: JsonValue,
782 table_name: &str,
783 fields: JsonValue,
784 hidd_field: Vec<&str>,
785 show_field: Vec<&str>,
786 search_fields: Vec<&str>,
787 filter_fields: Vec<&str>,
788 ) -> JsonValue {
789 let page = request["page"].as_i32().unwrap_or(1);
790 let limit = request["limit"].as_i32().unwrap_or(10);
791 let search = request["search"].as_str().unwrap_or("");
792 let order = request["order"].clone();
793 let where_or = request["where_or"].clone();
794 let where_and = request["where_and"].clone();
795 let mut columns = array![];
796 let mut search_name = vec![];
797 let mut search_field = vec![];
798 let mut filter_columns = vec![];
799
800 let mut table_fields = object! {};
801
802 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
803 alls_field.retain(|x| !hidd_field.contains(x));
804 if !show_field.is_empty() {
805 alls_field.retain(|x| show_field.contains(x) || *x == "id");
806 }
807
808 for item in alls_field.iter() {
809 let key = item.clone();
810 let field = fields[key]["field"].as_str().unwrap();
811 let title = fields[key]["title"].as_str().unwrap();
812 let mode = fields[key]["mode"].as_str().unwrap();
813
814 if search_fields.contains(&field) {
815 search_name.push(title);
816 search_field.push(field);
817 }
818 if filter_fields.contains(&field) {
819 filter_columns.push(self.filter_column(fields[key].clone()));
820 }
821 columns
822 .push(self.table_column(fields[key].clone()))
823 .unwrap();
824 let table_field_info = if mode == "table" {
825 fields[key].clone()
826 } else {
827 JsonValue::Null
828 };
829 if !table_field_info.is_empty() {
830 table_fields[field] = table_field_info;
831 }
832 }
833
834 let mut tools = self.tools();
835 let db = tools.db.table(table_name);
836
837 if !search.is_empty() {
838 db.where_and(
839 &search_field.join("|"),
840 "like",
841 format!("%{}%", search).into(),
842 );
843 }
844
845 for (key, value) in where_or.entries() {
846 if value.is_empty() {
847 continue;
848 }
849 if value.is_array() {
850 db.where_or(key, "in", value.clone());
852 } else if value.is_boolean() {
853 db.where_or(key, "=", value.clone());
854 } else {
855 db.where_or(key, "like", format!("%{}%", value).into());
856 }
857 }
858
859 for value in where_and.members() {
860 db.where_and(
861 value[0].as_str().unwrap(),
862 value[1].as_str().unwrap(),
863 value[2].clone(),
864 );
865 }
866
867 let total = db.clone().count().as_f64().unwrap();
868 let mut db_list = db.clone();
870
871 for item in order.members() {
872 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
873 }
874
875 let t = alls_field.join(",");
876 db_list.field(t.as_str());
877
878 let mut data = db_list.page(page, limit).select();
879
880 let mut table_datas = object! {};
881 let mut ids = HashMap::new();
882
883 for item in data.members_mut() {
884 if table_fields.is_empty() {
885 continue;
886 }
887 for (field, _) in table_fields.entries() {
888 if table_datas[field].is_empty() {
889 table_datas[field] = array![];
890 }
891 let _ = table_datas[field].push(item[field].clone());
892 }
893 }
894 for (field, info) in table_fields.entries_mut() {
895 let _ = info["fields"].push("id");
896 let fields_k = info["fields"]
897 .members()
898 .map(|x| x.as_str().unwrap())
899 .collect::<Vec<&str>>();
900 let table_name = info["table"].clone();
901 let mut data_list = self
902 .tools()
903 .db
904 .table(table_name.as_str().unwrap())
905 .where_and("id", "in", table_datas[field].clone())
906 .field(&fields_k.join(","))
907 .select();
908
909 for item in data_list.members_mut() {
910 let id = item["id"].as_str().unwrap_or("").to_string();
911 item.remove("id");
912 let label = item
913 .entries()
914 .map(|(_, v)| v.to_string())
915 .collect::<Vec<String>>();
916 ids.insert(
917 id.clone(),
918 object! {
919 value: id.clone(),
920 label:label.join(" | ").clone(),
921 },
922 );
923 }
924 }
925
926 for item in data.members_mut() {
927 if table_fields.is_empty() {
928 continue;
929 }
930 for (field, _) in table_fields.entries() {
931 if item[field].is_empty() {
932 continue;
933 }
934 let key = item[field].as_str().unwrap_or("");
935 if key.is_empty() {
936 continue;
937 }
938 if ids.get(key).is_none() {
939 continue;
940 }
941 item[field] = ids.get(key).unwrap().clone();
942 }
943 }
944
945 object! {
946 total:total,
947 data:data,
948 columns:columns,
949 search_name:search_name.join("/"),
950 filter_columns:filter_columns,
951 btn_all:array![],
952 btn_api:array![],
953 btn_ids:array![]
954 }
955 }
956 fn table_column(&mut self, field: JsonValue) -> JsonValue {
957 object! {
958 name:field["field"].clone(),
959 label:field["title"].clone(),
960 align:"center",
961 field:field["field"].clone(),
962 sortable:true,
963 mode:field["mode"].clone(),
964 }
965 }
966 fn filter_column(&mut self, field: JsonValue) -> JsonValue {
967 object! {
968 name:field["field"].clone(),
969 label:field["title"].clone(),
970 mode:field["mode"].clone(),
971 option:field["option"].clone(),
972 api:field["api"].clone(),
973 }
974 }
975 fn tools(&mut self) -> Tools {
977 let tools = PLUGIN_TOOLS.lock().unwrap();
978 let tools = tools.get("tools").unwrap().clone();
979 tools
980 }
981 fn btn(&mut self) -> Btn {
984 let mut btn = Btn::new(self.api().as_str());
985 btn.fields(self.params().clone());
986 btn.icon(self.icon());
987 btn.desc(self.description());
988 btn.title(self.title());
989 btn.btn_type(BtnType::Api);
990 btn.btn_color(BtnColor::Primary);
991 btn.path(self.api().clone().replace(".", "/").as_str());
992 btn
993 }
994}
995#[derive(Debug, Clone)]
996pub struct Btn {
997 api: String,
998 title: String,
999 desc: String,
1000 btn_type: BtnType,
1001 color: BtnColor,
1002 icon: String,
1003 cnd: Vec<JsonValue>,
1004 url: String,
1005 path: String,
1006 fields: JsonValue,
1007}
1008impl Btn {
1009 pub fn new(api: &str) -> Self {
1010 Self {
1011 api: api.to_string(),
1012 title: "".to_string(),
1013 desc: "".to_string(),
1014 btn_type: BtnType::Api,
1015 color: BtnColor::Primary,
1016 icon: "".to_string(),
1017 cnd: vec![],
1018 url: "".to_string(),
1019 path: "".to_string(),
1020 fields: object! {},
1021 }
1022 }
1023 pub fn path(&mut self, path: &str) -> &mut Self {
1024 self.path = path.to_string();
1025 self
1026 }
1027 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1028 self.cnd = cnd;
1029 self
1030 }
1031 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1032 self.btn_type = btn_type;
1033 self
1034 }
1035 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1036 self.color = btn_color;
1037 self
1038 }
1039 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1040 self.fields = fields;
1041 self
1042 }
1043 pub fn url(&mut self, url: &str) -> &mut Self {
1044 self.url = url.to_string();
1045 self
1046 }
1047 pub fn title(&mut self, title: &str) -> &mut Self {
1048 self.title = title.to_string();
1049 self
1050 }
1051 pub fn desc(&mut self, desc: &str) -> &mut Self {
1052 self.desc = desc.to_string();
1053 self
1054 }
1055 pub fn icon(&mut self, icon: &str) -> &mut Self {
1056 self.icon = icon.to_string();
1057 self
1058 }
1059 pub fn json(&mut self) -> JsonValue {
1060 object! {
1061 api:self.api.clone(),
1062 title:self.title.clone(),
1063 desc:self.desc.clone(),
1064 btn_type:self.btn_type.clone().str(),
1065 color:self.color.clone().str(),
1066 icon:self.icon.clone(),
1067 cnd:self.cnd.clone(),
1068 url:self.url.clone(),
1069 path:self.path.clone(),
1070 fields:self.fields.clone()
1071 }
1072 }
1073}
1074
1075#[derive(Debug, Clone)]
1077pub enum InterfaceType {
1078 API,
1079 BTN,
1080 MENU,
1081}
1082
1083impl InterfaceType {
1084 pub fn str(self) -> &'static str {
1085 match self {
1086 InterfaceType::API => "api",
1087 InterfaceType::BTN => "btn",
1088 InterfaceType::MENU => "menu",
1089 }
1090 }
1091 pub fn types() -> Vec<&'static str> {
1092 vec!["api", "btn", "menu"]
1093 }
1094}
1095
1096#[derive(Debug, Clone)]
1098pub enum BtnType {
1099 Form,
1101 FormDownload,
1103 FormCustom,
1105 FormData,
1106 Url,
1108 Api,
1110 Download,
1112 Path,
1114 DialogCustom,
1116}
1117
1118impl BtnType {
1119 fn str(self) -> &'static str {
1120 match self {
1121 BtnType::Form => "form",
1122 BtnType::FormDownload => "form_download",
1123 BtnType::FormCustom => "form_custom",
1124 BtnType::FormData => "form_data",
1125 BtnType::Api => "api",
1126 BtnType::Download => "download",
1127 BtnType::Url => "url",
1128 BtnType::Path => "path",
1129 BtnType::DialogCustom => "dialog_custom",
1130 }
1131 }
1132}
1133#[derive(Debug, Clone)]
1135pub enum BtnColor {
1136 Primary,
1137 Red,
1138 Blue,
1139 Yellow,
1140 Green,
1141}
1142
1143impl BtnColor {
1144 fn str(self) -> &'static str {
1145 match self {
1146 BtnColor::Primary => "primary",
1147 BtnColor::Red => "negative",
1148 BtnColor::Blue => "info",
1149 BtnColor::Yellow => "warning",
1150 BtnColor::Green => "positive",
1151 }
1152 }
1153}