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