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