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
430 }
431 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
432 fn table_select(
433 &mut self,
434 request: JsonValue,
435 table_name: &str,
436 fields: Vec<&str>,
437 ) -> JsonValue {
438 let page = request["page"].as_i32().unwrap_or(1);
439 let limit = request["limit"].as_i32().unwrap_or(10);
440
441 let search = request["search"].as_str().unwrap_or("");
442
443 let field_id = request["field"].as_str().unwrap_or("id");
444
445 let where_or = request["where_or"].clone();
446 let where_and = request["where_and"].clone();
447
448 let mut tools = self.tools();
449 let db = tools.db.table(table_name);
450
451 if !search.is_empty() {
452 db.where_and(&fields.join("|"), "like", format!("%{}%", search).into());
453 }
454
455 for (key, value) in where_or.entries() {
456 if value.is_empty() {
457 continue;
458 }
459 if value.is_array() {
460 db.where_or(key, "between", value.clone());
461 db.where_or(key, "in", value.clone());
462 } else if value.is_boolean() {
463 db.where_or(key, "=", value.clone());
464 } else {
465 db.where_or(key, "like", format!("%{}%", value).into());
466 }
467 }
468
469 for value in where_and.members() {
470 db.where_and(
471 value[0].as_str().unwrap(),
472 value[1].as_str().unwrap(),
473 value[2].clone(),
474 );
475 }
476
477 let total = (db.clone().count().as_f64().unwrap() / limit as f64).ceil() as i64;
478 let mut db_list = db.clone();
479
480 db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
481
482 let mut data = db_list.page(page, limit).select();
483 let mut list = array![];
484 for item in data.members_mut() {
485 let value = item[field_id].clone();
486 item.remove(field_id);
487
488 let label = item
489 .entries()
490 .map(|(_, v)| v.as_str().unwrap())
491 .collect::<Vec<&str>>();
492
493 list.push(object! {
494 value: value,
495 label: label.join(" | ").clone(),
496 })
497 .unwrap();
498 }
499 object! {
500 total:total,
501 data:list,
502 }
503 }
504 fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
506 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
507 .example("".into())
508 .field();
509 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
510 .example(array![])
511 .field();
512 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
513 .example(array![])
514 .field();
515 params
516 }
517 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
518 fn table_menu(
519 &mut self,
520 request: JsonValue,
521 table_name: &str,
522 label_field: &str,
523 fields: JsonValue,
524
525 hidd_field: Vec<&str>,
526 show_field: Vec<&str>,
527
528 search_fields: Vec<&str>,
529 _filter_fields: Vec<&str>,
530 ) -> JsonValue {
531 let search = request["search"].as_str().unwrap_or("");
532
533 let order = request["order"].clone();
534 let where_or = request["where_or"].clone();
535 let where_and = request["where_and"].clone();
536 let mut columns = array![];
537 let mut search_name = vec![];
538 let mut search_field = vec![];
539 let mut filter_columns = vec![];
540 let mut table_fields = object! {};
541 let mut table_field_json = vec![];
542
543 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
544 alls_field.retain(|x| !hidd_field.contains(x));
545 if !show_field.is_empty() {
546 alls_field.retain(|x| show_field.contains(x) || *x == "id");
547 }
548
549 for item in alls_field.iter() {
550 let row = &fields[item.clone()];
551 let field = row["field"].to_string();
552 let title = row["title"].to_string();
553 let mode = row["mode"].to_string();
554
555 if search_fields.contains(&field.as_str()) {
556 search_name.push(title);
557 search_field.push(field.clone());
558 }
559 filter_columns.push(self.filter_column(row.clone()));
560 columns.push(self.table_column(row.clone())).unwrap();
561 let mut table_field_info = object! {};
562 match mode.as_str() {
563 "table" => table_field_info = row.clone(),
564 "array" => table_field_json.push(field.clone()),
565 _ => {}
566 }
567 if !table_field_info.is_empty() {
568 table_fields[field.as_str()] = table_field_info;
569 }
570 }
571
572 let mut tools = self.tools();
573 let db = tools.db.table(table_name);
574
575 if !search.is_empty() {
576 db.where_and(
577 &search_field.join("|"),
578 "like",
579 format!("%{}%", search).into(),
580 );
581 }
582
583 for (key, value) in where_or.entries() {
584 if value.is_empty() {
585 continue;
586 }
587 if value.is_array() {
588 db.where_or(key, "between", value.clone());
589 db.where_or(key, "in", value.clone());
590 } else if value.is_boolean() {
591 db.where_or(key, "=", value.clone());
592 } else {
593 db.where_or(key, "like", format!("%{}%", value).into());
594 }
595 }
596
597 for value in where_and.members() {
598 db.where_and(
599 value[0].as_str().unwrap(),
600 value[1].as_str().unwrap(),
601 value[2].clone(),
602 );
603 }
604
605 let mut db_list = db.clone();
606
607 for item in order.members() {
608 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
609 }
610
611 let t = alls_field.join(",");
612 db_list.field(t.as_str());
613
614 if !table_field_json.is_empty() {
615 db_list.json(&table_field_json.join(","));
616 }
617
618 let mut data = db_list.select();
619
620 let mut table_datas = object! {};
621 let mut ids = HashMap::new();
622
623 for item in data.members_mut() {
624 for (field, _) in table_fields.entries() {
625 if table_datas[field].is_empty() {
626 table_datas[field] = array![];
627 }
628 let _ = table_datas[field].push(item[field].clone());
629 }
630 }
631 for (field, info) in table_fields.entries_mut() {
632 let _ = info["fields"].push("id");
633 let fields_k = info["fields"]
634 .members()
635 .map(|x| x.as_str().unwrap())
636 .collect::<Vec<&str>>();
637 let table_name = info["table"].clone();
638 let mut data_list = self
639 .tools()
640 .db
641 .table(table_name.as_str().unwrap())
642 .where_and("id", "in", table_datas[field].clone())
643 .field(&fields_k.join(","))
644 .select();
645
646 for item in data_list.members_mut() {
647 let id = item["id"].as_str().unwrap_or("").to_string();
648 item.remove("id");
649 let label = item
650 .entries()
651 .map(|(_, v)| v.as_str().unwrap())
652 .collect::<Vec<&str>>();
653 ids.insert(
654 id.clone(),
655 object! {
656 value: id.clone(),
657 label:label.join(" | ").clone(),
658 },
659 );
660 }
661 }
662
663 for item in data.members_mut() {
664 for (field, _) in table_fields.entries() {
665 if item[field].is_empty() {
666 continue;
667 }
668 item[field] = ids[item[field].as_str().unwrap()].clone();
669 }
670 }
671
672 object! {
673 data:data,
674 columns:columns,
675 search_name:search_name.join("/"),
676 filter_columns:filter_columns,
677 label_field:label_field,
678 btn_all:array![],
679 btn_api:array![]
680 }
681 }
682 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
684 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "")
685 .example("".into())
686 .field();
687 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
688 .example("".into())
689 .field();
690 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
691 .example(array![])
692 .field();
693 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
694 .example(array![])
695 .field();
696 params
697 }
698 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
699 fn table_tree(
700 &mut self,
701 request: JsonValue,
702 table_name: &str,
703 pid_field: &str,
704 label_field: &str,
705 fields: JsonValue,
706 hidd_field: Vec<&str>,
707 show_field: Vec<&str>,
708 search_fields: Vec<&str>,
709 _filter_fields: Vec<&str>,
710 ) -> JsonValue {
711 let search = request["search"].as_str().unwrap_or("");
712
713 let pid = request["pid"].clone();
714
715 let order = request["order"].clone();
716 let where_or = request["where_or"].clone();
717 let where_and = request["where_and"].clone();
718 let mut columns = array![];
719 let mut search_name = vec![];
720 let mut search_field = vec![];
721 let mut filter_columns = vec![];
722 let mut table_field_json = vec![];
723 let mut table_fields = object! {};
724
725 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
726 alls_field.retain(|x| !hidd_field.contains(x));
727 if !show_field.is_empty() {
728 alls_field.retain(|x| show_field.contains(x) || *x == "id");
729 }
730
731 for item in alls_field.iter() {
732 let row = fields[item.clone()].clone();
733 let field = row["field"].to_string();
734 let title = row["title"].to_string();
735 let mode = row["mode"].to_string();
736
737 if search_fields.contains(&field.as_str()) {
738 search_name.push(title);
739 search_field.push(field.clone());
740 }
741 filter_columns.push(self.filter_column(row.clone()));
742 columns.push(self.table_column(row.clone())).unwrap();
743 let mut table_field_info = object! {};
744 match mode.as_str() {
745 "table" => table_field_info = row.clone(),
746 "array" => table_field_json.push(field.clone()),
747 _ => {}
748 }
749 if !table_field_info.is_empty() {
750 table_fields[field.as_str()] = table_field_info;
751 }
752 }
753
754 let mut tools = self.tools();
755 let db = tools.db.table(table_name);
756 db.where_and(pid_field, "=", pid);
757 if !search.is_empty() {
758 db.where_and(
759 &search_field.join("|"),
760 "like",
761 format!("%{}%", search).into(),
762 );
763 }
764
765 for (key, value) in where_or.entries() {
766 if value.is_empty() {
767 continue;
768 }
769 if value.is_array() {
770 db.where_or(key, "in", value.clone());
772 } else if value.is_boolean() {
773 db.where_or(key, "=", value.clone());
774 } else {
775 db.where_or(key, "like", format!("%{}%", value).into());
776 }
777 }
778
779 for value in where_and.members() {
780 db.where_and(
781 value[0].as_str().unwrap(),
782 value[1].as_str().unwrap(),
783 value[2].clone(),
784 );
785 }
786
787 let mut db_list = db.clone();
788
789 for item in order.members() {
790 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
791 }
792 let t = alls_field.join(",");
793 db_list.field(t.as_str());
794 if !table_field_json.is_empty() {
795 db_list.json(&table_field_json.join(","));
796 }
797 let mut data = db_list.select();
798
799 let mut table_datas = object! {};
800 let mut ids = HashMap::new();
801
802 for item in data.members_mut() {
803 for (field, _) in table_fields.entries() {
804 if table_datas[field].is_empty() {
805 table_datas[field] = array![];
806 }
807 let _ = table_datas[field].push(item[field].clone());
808 }
809 }
810 for (field, info) in table_fields.entries_mut() {
811 let _ = info["fields"].push("id");
812 let fields_k = info["fields"]
813 .members()
814 .map(|x| x.as_str().unwrap())
815 .collect::<Vec<&str>>();
816 let table_name = info["table"].clone();
817 let mut data_list = self
818 .tools()
819 .db
820 .table(table_name.as_str().unwrap())
821 .where_and("id", "in", table_datas[field].clone())
822 .field(&fields_k.join(","))
823 .select();
824
825 for item in data_list.members_mut() {
826 let id = item["id"].as_str().unwrap_or("").to_string();
827 item.remove("id");
828 let label = item
829 .entries()
830 .map(|(_, v)| v.as_str().unwrap())
831 .collect::<Vec<&str>>();
832 ids.insert(
833 id.clone(),
834 object! {
835 value: id.clone(),
836 label:label.join(" | ").clone(),
837 },
838 );
839 }
840 }
841
842 let mut list = array![];
843 for item in data.members_mut() {
844 for (field, _) in table_fields.entries() {
845 if item[field].is_empty() {
846 continue;
847 }
848 item[field] = ids[item[field].as_str().unwrap()].clone();
849 }
850 let _ = list.push(object! {
851 id:item["id"].as_str().unwrap(),
852 label:item[label_field].as_str().unwrap(),
853 data:item.clone(),
854 });
855 }
856
857 object! {
858 data:list,
859 columns:columns,
860 search_name:search_name.join("/"),
861 filter_columns:filter_columns,
862 pid_field:pid_field,
863 btn_all:array![],
864 btn_api:array![]
865 }
866 }
867 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
869 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1)
870 .example(1.into())
871 .field();
872 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10)
873 .example(10.into())
874 .field();
875 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
876 .example("".into())
877 .field();
878 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![])
879 .example(array![array!["id", false]])
880 .field();
881 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
882 .example(array![])
883 .field();
884 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
885 .example(array![])
886 .field();
887 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id")
888 .example("id".into())
889 .field();
890 params
891 }
892 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
900 fn table_list(
901 &mut self,
902 request: JsonValue,
903 table_name: &str,
904 fields: JsonValue,
905 hidd_field: Vec<&str>,
906 show_field: Vec<&str>,
907 search_fields: Vec<&str>,
908 filter_fields: Vec<&str>,
909 ) -> JsonValue {
910 let page = request["page"].as_i32().unwrap_or(1);
911 let limit = request["limit"].as_i32().unwrap_or(10);
912 let search = request["search"].as_str().unwrap_or("");
913 let order = request["order"].clone();
914 let where_or = request["where_or"].clone();
915 let where_and = request["where_and"].clone();
916 let mut columns = array![];
917 let mut search_name = vec![];
918 let mut search_field = vec![];
919 let mut filter_columns = vec![];
920
921 let mut table_fields = object! {};
922
923 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
924 alls_field.retain(|x| !hidd_field.contains(x));
925 if !show_field.is_empty() {
926 alls_field.retain(|x| show_field.contains(x) || *x == "id");
927 }
928
929 for item in alls_field.iter() {
930 let key = item.clone();
931 let field = fields[key]["field"].as_str().unwrap();
932 let title = fields[key]["title"].as_str().unwrap();
933 let mode = fields[key]["mode"].as_str().unwrap();
934
935 if search_fields.contains(&field) {
936 search_name.push(title);
937 search_field.push(field);
938 }
939 if filter_fields.contains(&field) {
940 filter_columns.push(self.filter_column(fields[key].clone()));
941 }
942 columns
943 .push(self.table_column(fields[key].clone()))
944 .unwrap();
945 let table_field_info = if mode == "table" {
946 fields[key].clone()
947 } else {
948 JsonValue::Null
949 };
950 if !table_field_info.is_empty() {
951 table_fields[field] = table_field_info;
952 }
953 }
954
955 let mut tools = self.tools();
956 let db = tools.db.table(table_name);
957
958 if !search.is_empty() {
959 db.where_and(
960 &search_field.join("|"),
961 "like",
962 format!("%{}%", search).into(),
963 );
964 }
965
966 for (key, value) in where_or.entries() {
967 if value.is_empty() {
968 continue;
969 }
970 if value.is_array() {
971 db.where_or(key, "in", value.clone());
973 } else if value.is_boolean() {
974 db.where_or(key, "=", value.clone());
975 } else {
976 db.where_or(key, "like", format!("%{}%", value).into());
977 }
978 }
979
980 for value in where_and.members() {
981 db.where_and(
982 value[0].as_str().unwrap(),
983 value[1].as_str().unwrap(),
984 value[2].clone(),
985 );
986 }
987
988 let total = db.clone().count().as_f64().unwrap();
989 let mut db_list = db.clone();
991
992 for item in order.members() {
993 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
994 }
995
996 let t = alls_field.join(",");
997 db_list.field(t.as_str());
998
999 let mut data = db_list.page(page, limit).select();
1000
1001 let mut table_datas = object! {};
1002 let mut ids = HashMap::new();
1003
1004 for item in data.members_mut() {
1005 if table_fields.is_empty() {
1006 continue;
1007 }
1008 for (field, _) in table_fields.entries() {
1009 if table_datas[field].is_empty() {
1010 table_datas[field] = array![];
1011 }
1012 let _ = table_datas[field].push(item[field].clone());
1013 }
1014 }
1015 for (field, info) in table_fields.entries_mut() {
1016 let _ = info["fields"].push("id");
1017 let fields_k = info["fields"]
1018 .members()
1019 .map(|x| x.as_str().unwrap())
1020 .collect::<Vec<&str>>();
1021 let table_name = info["table"].clone();
1022 let mut data_list = self
1023 .tools()
1024 .db
1025 .table(table_name.as_str().unwrap())
1026 .where_and("id", "in", table_datas[field].clone())
1027 .field(&fields_k.join(","))
1028 .select();
1029
1030 for item in data_list.members_mut() {
1031 let id = item["id"].as_str().unwrap_or("").to_string();
1032 item.remove("id");
1033 let label = item
1034 .entries()
1035 .map(|(_, v)| v.to_string())
1036 .collect::<Vec<String>>();
1037 ids.insert(
1038 id.clone(),
1039 object! {
1040 value: id.clone(),
1041 label:label.join(" | ").clone(),
1042 },
1043 );
1044 }
1045 }
1046
1047 for item in data.members_mut() {
1048 if table_fields.is_empty() {
1049 continue;
1050 }
1051 for (field, _) in table_fields.entries() {
1052 if item[field].is_empty() {
1053 continue;
1054 }
1055 let key = item[field].as_str().unwrap_or("");
1056 if key.is_empty() {
1057 continue;
1058 }
1059 if !ids.contains_key(key) {
1060 continue;
1061 }
1062 item[field] = ids.get(key).unwrap().clone();
1063 }
1064 }
1065
1066 object! {
1067 total:total,
1068 data:data,
1069 columns:columns,
1070 search_name:search_name.join("/"),
1071 filter_columns:filter_columns,
1072 btn_all:array![],
1073 btn_api:array![],
1074 btn_ids:array![]
1075 }
1076 }
1077 fn table_column(&mut self, field: JsonValue) -> JsonValue {
1078 object! {
1079 name:field["field"].clone(),
1080 label:field["title"].clone(),
1081 align:"center",
1082 field:field["field"].clone(),
1083 sortable:true,
1084 mode:field["mode"].clone(),
1085 dec:field["dec"].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 }
1096 }
1097 fn tools(&mut self) -> Tools {
1099 let tools = PLUGIN_TOOLS.lock().unwrap();
1100 let tools = tools.get("tools").unwrap().clone();
1101 tools
1102 }
1103 fn btn(&mut self) -> Btn {
1106 let mut btn = Btn::new(self.api().as_str());
1107 btn.fields(self.params().clone());
1108 btn.icon(self.icon());
1109 btn.desc(self.description());
1110 btn.auth(self.auth());
1111 btn.public(self.public());
1112 btn.title(self.title());
1113 btn.btn_type(BtnType::Api);
1114 btn.btn_color(BtnColor::Primary);
1115 btn.path(self.api().clone().replace(".", "/").as_str());
1116 btn
1117 }
1118}
1119#[derive(Debug, Clone)]
1120pub struct Btn {
1121 api: String,
1122 title: String,
1123 desc: String,
1124 auth: bool,
1125 public: bool,
1126 btn_type: BtnType,
1127 color: BtnColor,
1128 icon: String,
1129 cnd: Vec<JsonValue>,
1130 url: String,
1131 path: String,
1132 fields: JsonValue,
1133}
1134impl Btn {
1135 pub fn new(api: &str) -> Self {
1136 Self {
1137 api: api.to_string(),
1138 title: "".to_string(),
1139 desc: "".to_string(),
1140 btn_type: BtnType::Api,
1141 color: BtnColor::Primary,
1142 icon: "".to_string(),
1143 auth: false,
1144 public: false,
1145 cnd: vec![],
1146 url: "".to_string(),
1147 path: "".to_string(),
1148 fields: object! {},
1149 }
1150 }
1151 pub fn path(&mut self, path: &str) -> &mut Self {
1152 self.path = path.to_string();
1153 self
1154 }
1155 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1156 self.cnd = cnd;
1157 self
1158 }
1159 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1160 self.btn_type = btn_type;
1161 self
1162 }
1163 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1164 self.color = btn_color;
1165 self
1166 }
1167 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1168 self.fields = fields;
1169 self
1170 }
1171 pub fn url(&mut self, url: &str) -> &mut Self {
1172 self.url = url.to_string();
1173 self
1174 }
1175 pub fn title(&mut self, title: &str) -> &mut Self {
1176 self.title = title.to_string();
1177 self
1178 }
1179 pub fn desc(&mut self, desc: &str) -> &mut Self {
1180 self.desc = desc.to_string();
1181 self
1182 }
1183 pub fn public(&mut self, public: bool) -> &mut Self {
1184 self.public = public;
1185 self
1186 }
1187 pub fn auth(&mut self, auth: bool) -> &mut Self {
1188 self.auth = auth;
1189 self
1190 }
1191 pub fn icon(&mut self, icon: &str) -> &mut Self {
1192 self.icon = icon.to_string();
1193 self
1194 }
1195 pub fn json(&mut self) -> JsonValue {
1196 object! {
1197 api:self.api.clone(),
1198 title:self.title.clone(),
1199 desc:self.desc.clone(),
1200 auth:self.auth,
1201 public:self.public,
1202 btn_type:self.btn_type.clone().str(),
1203 color:self.color.clone().str(),
1204 icon:self.icon.clone(),
1205 cnd:self.cnd.clone(),
1206 url:self.url.clone(),
1207 path:self.path.clone(),
1208 fields:self.fields.clone()
1209 }
1210 }
1211}
1212
1213#[derive(Debug, Clone)]
1215pub enum InterfaceType {
1216 API,
1217 BTN,
1218 MENU,
1219}
1220
1221impl InterfaceType {
1222 pub fn str(self) -> &'static str {
1223 match self {
1224 InterfaceType::API => "api",
1225 InterfaceType::BTN => "btn",
1226 InterfaceType::MENU => "menu",
1227 }
1228 }
1229 pub fn types() -> Vec<&'static str> {
1230 vec!["api", "btn", "menu"]
1231 }
1232}
1233
1234#[derive(Debug, Clone)]
1236pub enum BtnType {
1237 Form,
1239 FormDownload,
1241 FormCustom,
1243 FormData,
1244 Url,
1246 Api,
1248 Download,
1250 Path,
1252 DialogCustom,
1254}
1255
1256impl BtnType {
1257 fn str(self) -> &'static str {
1258 match self {
1259 BtnType::Form => "form",
1260 BtnType::FormDownload => "form_download",
1261 BtnType::FormCustom => "form_custom",
1262 BtnType::FormData => "form_data",
1263 BtnType::Api => "api",
1264 BtnType::Download => "download",
1265 BtnType::Url => "url",
1266 BtnType::Path => "path",
1267 BtnType::DialogCustom => "dialog_custom",
1268 }
1269 }
1270}
1271#[derive(Debug, Clone)]
1273pub enum BtnColor {
1274 Primary,
1275 Red,
1276 Blue,
1277 Yellow,
1278 Green,
1279}
1280
1281impl BtnColor {
1282 fn str(self) -> &'static str {
1283 match self {
1284 BtnColor::Primary => "primary",
1285 BtnColor::Red => "negative",
1286 BtnColor::Blue => "info",
1287 BtnColor::Yellow => "warning",
1288 BtnColor::Green => "positive",
1289 }
1290 }
1291}