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