1use crate::request::{ContentType, Method, Request};
2use crate::{CONFIG, GLOBAL_DATA, 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>().rsplit("::").next().unwrap().to_lowercase()
14 }
15 fn api(&self) -> String {
17 let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
18 let plugin = t[2].to_lowercase();
19 let module = t[3].to_lowercase();
20 let action = t[4].to_lowercase();
21 format!("{plugin}.{module}.{action}")
22 }
23 fn token(&self) -> bool {
25 true
26 }
27
28 fn sort(&self) -> usize {
29 99
30 }
31 fn title(&self) -> &'static str;
33 fn description(&self) -> &'static str {
35 ""
36 }
37 fn path(&self) -> &'static str {
39 ""
40 }
41 fn query(&self) -> JsonValue {
43 object! {}
44 }
45 fn tags(&self) -> &'static [&'static str] {
47 &[]
48 }
49 fn icon(&self) -> &'static str {
50 ""
51 }
52 fn public(&self) -> bool {
54 true
55 }
56 fn auth(&self) -> bool {
58 true
59 }
60 fn interface_type(&self) -> InterfaceType {
62 InterfaceType::API
63 }
64 fn method(&mut self) -> Method {
66 Method::Post
67 }
68 fn content_type(&mut self) -> ContentType {
70 ContentType::Json
71 }
72 fn params_check(&mut self) -> bool {
74 true
75 }
76 fn params(&mut self) -> JsonValue {
78 object! {}
79 }
80 fn success(&mut self) -> ApiResponse {
82 let mut data = object! {};
83 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0).example(0.into()).swagger();
84 data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "").example("成功".into()).swagger();
85 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
86 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true).example(true.into()).swagger();
87 ApiResponse::success(data, "请求成功")
88 }
89 fn error(&mut self) -> ApiResponse {
91 let mut data = object! {};
92 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000).example(1000.into()).swagger();
93 data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "").example("失败".into()).swagger();
94 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
95 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false).example(false.into()).swagger();
96 ApiResponse::error(data, "请求失败")
97 }
98 fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
100 if self.public() && !self.method().str().is_empty() && self.method().str().to_lowercase() != request.method.str().to_lowercase() {
101 return Err(ApiResponse::fail(
102 -1,
103 format!(
104 "Request type error: Actual [{}] Expected [{}]",
105 request.method.str(),
106 self.method().str()
107 ).as_str(),
108 ));
109 }
110 let params = self.params().clone();
111 if self.params_check() {
112 self.check(&mut request.query.clone(), self.query().clone())?;
113 self.check(&mut request.body, params)?;
114 }
115 let res = self.index(request.clone());
116 match res.success {
117 true => Ok(res),
118 false => Err(res),
119 }
120 }
121 fn check(&mut self, request: &mut JsonValue, params: JsonValue) -> Result<(), ApiResponse> {
123 let req = request.clone();
124 for (name, _) in req.entries() {
125 if !params.has_key(name) {
126 request.remove(name);
127 }
128 }
129 for (name, field) in params.entries() {
130 let require = field["require"].as_bool().unwrap_or(false);
131 let title = field["title"].as_str().unwrap_or("");
132 if request.has_key(name) {
133 match field["mode"].as_str().unwrap() {
135 "key" => {
136 if !request[name].is_string() {
137 return Err(ApiResponse::fail(
138 900_001,
139 format!(
140 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
141 name, field["mode"]
142 ).as_str(),
143 ));
144 }
145 if require && request[name].is_empty() {
146 return Err(ApiResponse::fail(
147 900014,
148 format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
149 ));
150 }
151 }
152 "text" | "table" => {
153 if !request[name].is_string() {
154 return Err(ApiResponse::fail(
155 900002,
156 format!(
157 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
158 name, field["mode"]
159 ).as_str(),
160 ));
161 }
162 if require && request[name].is_empty() {
163 return Err(ApiResponse::fail(
164 900002,
165 format!("{title} 必填").as_str(),
166 ));
167 }
168 }
169 "file" => {
170 if !request[name].is_array() && !request[name].is_string() {
171 return Err(ApiResponse::fail(
172 900003,
173 format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
174 ));
175 }
176 if require && request[name].is_empty() {
177 return Err(ApiResponse::fail(
178 900002,
179 format!("{title} 必填").as_str(),
180 ));
181 }
182 }
183 "int" => {
184 if require && request[name].to_string().is_empty() {
185 return Err(ApiResponse::fail(
186 900_002,
187 format!("{title} 必填").as_str(),
188 ));
189 }
190 if !request[name].to_string().is_empty() {
191 match request[name].to_string().parse::<i64>() {
192 Ok(_) => {}
193 Err(_) => {
194 return Err(ApiResponse::fail(
195 900013,
196 format!(
197 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
198 name, field["mode"]
199 ).as_str(),
200 ));
201 }
202 }
203 }
204 }
205 "timestamp" => {
206 if require && request[name].to_string().is_empty() {
207 return Err(ApiResponse::fail(
208 900002,
209 format!("{title} 必填").as_str(),
210 ));
211 }
212 if !request[name].to_string().is_empty() {
213 if request[name].is_array() && request[name].len() == 2 {
214 for item in request[name].members() {
216 match item.to_string().parse::<f64>() {
217 Ok(_) => {}
218 Err(_) => {
219 return Err(ApiResponse::fail(
220 900_013,
221 format!(
222 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
223 name, field["mode"]
224 ).as_str(),
225 ));
226 }
227 }
228 }
229 } else {
230 match request[name].to_string().parse::<f64>() {
231 Ok(_) => {}
232 Err(_) => {
233 return Err(ApiResponse::fail(
234 900013,
235 format!(
236 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
237 name, field["mode"]
238 ).as_str(),
239 ));
240 }
241 }
242 }
243 }
244 }
245 "float" => {
246 if require && request[name].to_string().is_empty() {
247 return Err(ApiResponse::fail(
248 900002,
249 format!("{title} 必填").as_str(),
250 ));
251 }
252 if !request[name].to_string().is_empty() {
253 match request[name].to_string().parse::<f64>() {
254 Ok(_) => {}
255 Err(_) => {
256 return Err(ApiResponse::fail(
257 900023,
258 format!(
259 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
260 name, field["mode"]
261 ).as_str(),
262 ));
263 }
264 }
265 }
266 }
267 "string" | "time" | "code" | "pass" | "email" | "location" | "color" | "date" | "barcode" | "datetime" | "editor" | "tel" => {
268 if !request[name].is_string() {
269 return Err(ApiResponse::fail(
270 -1,
271 format!(
272 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
273 name, field["mode"]
274 ).as_str(),
275 ));
276 }
277 if require && request[name].is_empty() {
278 return Err(ApiResponse::fail(
279 900004,
280 format!("{title} 必填").as_str(),
281 ));
282 }
283 }
284 "dict" => {
285 if require && request[name].is_empty() {
286 return Err(ApiResponse::fail(
287 900005,
288 format!("{title} 必填").as_str(),
289 ));
290 }
291 }
292 "switch" => {
293 match request[name].to_string().parse::<bool>() {
294 Ok(e) => {
295 request[name] = e.into();
296 }
297 Err(_) => {
298 return Err(ApiResponse::fail(
299 -1,
300 format!("请求参数数据类型错误: 参数 [{name}] 数据类型应为[{}]", field["mode"]).as_str(),
301 ));
302 }
303 }
304 }
305 "select" => {
306 if !request[name].is_array() && !request[name].is_string() {
307 return Err(ApiResponse::fail(
308 -1,
309 format!(
310 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
311 name, field["mode"]
312 ).as_str(),
313 ));
314 }
315 let value = if request[name].is_array() {
316 request[name].members().map(|m| m.to_string()).collect::<Vec<String>>()
317 } else {
318 request[name].to_string().split(",").map(|x| x.to_string()).collect::<Vec<String>>()
319 };
320 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>();
321
322 let require = field["require"].as_bool().unwrap();
323 for item in value.clone() {
324 if !option.contains(&&*item.clone()) && (item.is_empty() && require) {
325 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
326 return Err(ApiResponse::fail(-1, format!("请求参数选项错误: 参数 [{item}] 数据类型应为[{option}]之内").as_str()));
327 }
328 }
329 request[name] = value.into();
330 }
331 "radio" => {
332 if !request[name].is_string() {
333 return Err(ApiResponse::fail(
334 -1,
335 format!(
336 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
337 name, field["mode"], request[name]
338 ).as_str(),
339 ));
340 }
341 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
342 if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
343 {
344 return Err(ApiResponse::fail(
345 -1,
346 format!(
347 "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
348 name, request[name], option
349 ).as_str(),
350 ));
351 }
352 }
353 "array" | "polygon" => {
354 if !request[name].is_array() {
355 return Err(ApiResponse::fail(
356 900_009,
357 format!(
358 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
359 name, field["mode"]
360 ).as_str(),
361 ));
362 }
363 if require && request[name].is_empty() {
364 return Err(ApiResponse::fail(
365 900010,
366 format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
367 ));
368 }
369 }
370 "object" => {
371 if !request[name].is_object() {
372 return Err(ApiResponse::fail(
373 900009,
374 format!(
375 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
376 name, field["mode"]
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).example(1.into()).field();
407 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
408 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
409 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
410 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
411 params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
412 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 50, "id").example("id".into()).field();
413 params
414 }
415 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
416 fn table_select(
417 &mut self,
418 request: JsonValue,
419 table_name: &str,
420 fields: Vec<&str>,
421 ) -> JsonValue {
422 let page = request["page"].as_i32().unwrap_or(1);
423 let limit = request["limit"].as_i32().unwrap_or(10);
424
425 let search = request["search"].as_str().unwrap_or("");
426
427 let field_id = request["field"].as_str().unwrap_or("id");
428
429 let where_or = request["where_or"].clone();
430 let where_and = request["where_and"].clone();
431
432 let mut tools = self.tools();
433 let db = tools.db.table(table_name);
434
435 if !search.is_empty() {
436 db.where_and(&fields.join("|"), "like", format!("%{search}%").into());
437 }
438
439 for (key, value) in where_or.entries() {
440 if value.is_empty() {
441 continue;
442 }
443 if value.is_array() {
444 db.where_or(key, "between", value.clone());
445 db.where_or(key, "in", value.clone());
446 } else if value.is_boolean() {
447 db.where_or(key, "=", value.clone());
448 } else {
449 db.where_or(key, "like", format!("%{value}%").into());
450 }
451 }
452
453 for value in where_and.members() {
454 db.where_and(
455 value[0].as_str().unwrap(),
456 value[1].as_str().unwrap(),
457 value[2].clone(),
458 );
459 }
460
461 let total = (db.clone().count().as_f64().unwrap() / f64::from(limit)).ceil() as i64;
462 let mut db_list = db.clone();
463
464 db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
465
466 let mut data = db_list.page(page, limit).select();
467 let mut list = array![];
468 for item in data.members_mut() {
469 let value = item[field_id].clone();
470 item.remove(field_id);
471
472 let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
473
474 list.push(object! {
475 value: value,
476 label: label.join(" | ").clone(),
477 }).unwrap();
478 }
479 object! {
480 total:total,
481 data:list,
482 }
483 }
484 fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
486 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
487 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
488 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
489 params
490 }
491 #[allow(clippy::too_many_arguments)]
492 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
493 fn table_menu(
494 &mut self,
495 request: JsonValue,
496 table_name: &str,
497 label_field: &str,
498 fields: JsonValue,
499
500 hidd_field: Vec<&str>,
501 show_field: Vec<&str>,
502
503 search_fields: Vec<&str>,
504 _filter_fields: Vec<&str>,
505 ) -> JsonValue {
506 let search = request["search"].as_str().unwrap_or("");
507
508 let order = request["order"].clone();
509 let where_or = request["where_or"].clone();
510 let where_and = request["where_and"].clone();
511 let mut columns = array![];
512 let mut search_name = vec![];
513 let mut search_field = vec![];
514 let mut filter_columns = vec![];
515 let mut table_fields = object! {};
516 let mut table_field_json = vec![];
517
518 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
519 alls_field.retain(|x| !hidd_field.contains(x));
520 if !show_field.is_empty() {
521 alls_field.retain(|x| show_field.contains(x) || *x == "id");
522 }
523
524 for item in alls_field.iter() {
525 let row = &fields[item.to_string()];
526 let field = row["field"].to_string();
527 let title = row["title"].to_string();
528 let mode = row["mode"].to_string();
529
530 if search_fields.contains(&field.as_str()) {
531 search_name.push(title);
532 search_field.push(field.clone());
533 }
534 filter_columns.push(self.filter_column(row.clone()));
535 columns.push(self.table_column(row.clone())).unwrap();
536 let mut table_field_info = object! {};
537 match mode.as_str() {
538 "table" => table_field_info = row.clone(),
539 "array" => table_field_json.push(field.clone()),
540 _ => {}
541 }
542 if !table_field_info.is_empty() {
543 table_fields[field.as_str()] = table_field_info;
544 }
545 }
546
547 let mut tools = self.tools();
548 let db = tools.db.table(table_name);
549
550 if !search.is_empty() {
551 db.where_and(
552 &search_field.join("|"),
553 "like",
554 format!("%{search}%").into(),
555 );
556 }
557
558 for (key, value) in where_or.entries() {
559 if value.is_empty() {
560 continue;
561 }
562 if value.is_array() {
563 db.where_or(key, "between", value.clone());
564 db.where_or(key, "in", value.clone());
565 } else if value.is_boolean() {
566 db.where_or(key, "=", value.clone());
567 } else {
568 db.where_or(key, "like", format!("%{value}%").into());
569 }
570 }
571
572 for value in where_and.members() {
573 db.where_and(
574 value[0].as_str().unwrap(),
575 value[1].as_str().unwrap(),
576 value[2].clone(),
577 );
578 }
579
580 let mut db_list = db.clone();
581
582 for item in order.members() {
583 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
584 }
585
586 let t = alls_field.join(",");
587 db_list.field(t.as_str());
588
589 if !table_field_json.is_empty() {
590 db_list.json(&table_field_json.join(","));
591 }
592
593 let mut data = db_list.select();
594
595 let mut table_datas = object! {};
596 let mut ids = HashMap::new();
597
598 for item in data.members_mut() {
599 for (field, _) in table_fields.entries() {
600 if table_datas[field].is_empty() {
601 table_datas[field] = array![];
602 }
603 let _ = table_datas[field].push(item[field].clone());
604 }
605 }
606 for (field, info) in table_fields.entries_mut() {
607 let _ = info["fields"].push("id");
608 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
609 let table_name = info["table"].clone();
610 let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
611
612 for item in data_list.members_mut() {
613 let id = item["id"].as_str().unwrap_or("").to_string();
614 item.remove("id");
615 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
616 ids.insert(
617 id.clone(),
618 object! {
619 value: id.clone(),
620 label:label.join(" | ").clone(),
621 },
622 );
623 }
624 }
625
626 for item in data.members_mut() {
627 for (field, _) in table_fields.entries() {
628 if item[field].is_empty() {
629 continue;
630 }
631 item[field] = ids[item[field].as_str().unwrap()].clone();
632 }
633 }
634
635 object! {
636 data:data,
637 columns:columns,
638 search_name:search_name.join("/"),
639 filter_columns:filter_columns,
640 label_field:label_field,
641 btn_all:array![],
642 btn_api:array![]
643 }
644 }
645 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
647 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
648 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
649 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
650 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
651 params
652 }
653 #[allow(clippy::too_many_arguments)]
654 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
655 fn table_tree(
656 &mut self,
657 request: JsonValue,
658 table_name: &str,
659 pid_field: &str,
660 label_field: &str,
661 fields: JsonValue,
662 hidd_field: Vec<&str>,
663 show_field: Vec<&str>,
664 search_fields: Vec<&str>,
665 _filter_fields: Vec<&str>,
666 ) -> JsonValue {
667 let search = request["search"].as_str().unwrap_or("");
668
669 let pid = request["pid"].clone();
670
671 let order = request["order"].clone();
672 let where_or = request["where_or"].clone();
673 let where_and = request["where_and"].clone();
674 let mut columns = array![];
675 let mut search_name = vec![];
676 let mut search_field = vec![];
677 let mut filter_columns = vec![];
678 let mut table_field_json = vec![];
679 let mut table_fields = object! {};
680
681 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
682 alls_field.retain(|x| !hidd_field.contains(x));
683 if !show_field.is_empty() {
684 alls_field.retain(|x| show_field.contains(x) || *x == "id");
685 }
686
687 for item in alls_field.iter() {
688 let row = fields[item.to_string()].clone();
689 let field = row["field"].to_string();
690 let title = row["title"].to_string();
691 let mode = row["mode"].to_string();
692
693 if search_fields.contains(&field.as_str()) {
694 search_name.push(title);
695 search_field.push(field.clone());
696 }
697 filter_columns.push(self.filter_column(row.clone()));
698 columns.push(self.table_column(row.clone())).unwrap();
699 let mut table_field_info = object! {};
700 match mode.as_str() {
701 "table" => table_field_info = row.clone(),
702 "array" => table_field_json.push(field.clone()),
703 _ => {}
704 }
705 if !table_field_info.is_empty() {
706 table_fields[field.as_str()] = table_field_info;
707 }
708 }
709
710 let mut tools = self.tools();
711 let db = tools.db.table(table_name);
712 db.where_and(pid_field, "=", pid);
713 if !search.is_empty() {
714 db.where_and(
715 &search_field.join("|"),
716 "like",
717 format!("%{search}%").into(),
718 );
719 }
720
721 for (key, value) in where_or.entries() {
722 if value.is_empty() {
723 continue;
724 }
725 if value.is_array() {
726 db.where_or(key, "in", value.clone());
728 } else if value.is_boolean() {
729 db.where_or(key, "=", value.clone());
730 } else {
731 db.where_or(key, "like", format!("%{value}%").into());
732 }
733 }
734
735 for value in where_and.members() {
736 db.where_and(
737 value[0].as_str().unwrap(),
738 value[1].as_str().unwrap(),
739 value[2].clone(),
740 );
741 }
742
743 let mut db_list = db.clone();
744
745 for item in order.members() {
746 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
747 }
748 let t = alls_field.join(",");
749 db_list.field(t.as_str());
750 if !table_field_json.is_empty() {
751 db_list.json(&table_field_json.join(","));
752 }
753 let mut data = db_list.select();
754
755 let mut table_datas = object! {};
756 let mut ids = HashMap::new();
757
758 for item in data.members_mut() {
759 for (field, _) in table_fields.entries() {
760 if table_datas[field].is_empty() {
761 table_datas[field] = array![];
762 }
763 let _ = table_datas[field].push(item[field].clone());
764 }
765 }
766 for (field, info) in table_fields.entries_mut() {
767 let _ = info["fields"].push("id");
768 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
769 let table_name = info["table"].clone();
770 let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
771
772 for item in data_list.members_mut() {
773 let id = item["id"].as_str().unwrap_or("").to_string();
774 item.remove("id");
775 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
776 ids.insert(
777 id.clone(),
778 object! {
779 value: id.clone(),
780 label:label.join(" | ").clone(),
781 },
782 );
783 }
784 }
785
786 let mut list = array![];
787 for item in data.members_mut() {
788 for (field, _) in table_fields.entries() {
789 if item[field].is_empty() {
790 continue;
791 }
792 item[field] = ids[item[field].as_str().unwrap()].clone();
793 }
794 let _ = list.push(object! {
795 id:item["id"].as_str().unwrap(),
796 code:item["code"].as_str().unwrap(),
797 label:item[label_field].as_str().unwrap(),
798 data:item.clone(),
799 });
800 }
801
802 object! {
803 data:list,
804 columns:columns,
805 search_name:search_name.join("/"),
806 filter_columns:filter_columns,
807 pid_field:pid_field,
808 btn_all:array![],
809 btn_api:array![]
810 }
811 }
812 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
814 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
815 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
816 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
817 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
818 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
819 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
820 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
821 params
822 }
823 #[allow(clippy::too_many_arguments)]
831 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
832 fn table_list(
833 &mut self,
834 request: JsonValue,
835 table_name: &str,
836 fields: JsonValue,
837 hidd_field: Vec<&str>,
838 show_field: Vec<&str>,
839 search_fields: Vec<&str>,
840 filter_fields: Vec<&str>,
841 ) -> JsonValue {
842 let page = request["page"].as_i32().unwrap_or(1);
843 let limit = request["limit"].as_i32().unwrap_or(10);
844 let search = request["search"].as_str().unwrap_or("");
845 let order = request["order"].clone();
846 let where_or = request["where_or"].clone();
847 let where_and = request["where_and"].clone();
848 let mut columns = array![];
849 let mut search_name = vec![];
850 let mut search_field = vec![];
851 let mut filter_columns = vec![];
852
853 let mut table_fields = object! {};
855 let mut json_fields = vec![];
857
858 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
859 alls_field.retain(|x| !hidd_field.contains(x));
860 if !show_field.is_empty() {
861 alls_field.retain(|x| show_field.contains(x) || *x == "id");
862 }
863
864 for item in alls_field.iter() {
865 let key = item.to_string();
866 let field = fields[key.clone()]["field"].as_str().unwrap();
867 let title = fields[key.clone()]["title"].as_str().unwrap();
868 let mode = fields[key.clone()]["mode"].as_str().unwrap();
869
870 if search_fields.contains(&field) {
871 search_name.push(title);
872 search_field.push(field);
873 }
874 if filter_fields.contains(&field) {
875 filter_columns.push(self.filter_column(fields[key.clone()].clone()));
876 }
877 columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
878
879 match mode {
880 "table" => {
881 let table_field_info = if mode == "table" {
882 fields[key.clone()].clone()
883 } else {
884 JsonValue::Null
885 };
886 if !table_field_info.is_empty() {
887 table_fields[field] = table_field_info;
888 }
889 }
890 "object" | "array" | "polygon" => {
891 json_fields.push(field);
892 }
893 _ => {}
894 }
895 }
896
897 let mut tools = self.tools();
898 let db = tools.db.table(table_name);
899
900 if !search.is_empty() {
901 db.where_and(
902 &search_field.join("|"),
903 "like",
904 format!("%{search}%").into(),
905 );
906 }
907
908 for (key, value) in where_or.entries() {
909 if value.is_empty() {
910 continue;
911 }
912 if value.is_array() {
913 db.where_or(key, "in", value.clone());
914 } else if value.is_boolean() {
915 db.where_or(key, "=", value.clone());
916 } else {
917 db.where_or(key, "like", format!("%{value}%").into());
918 }
919 }
920
921 for value in where_and.members() {
922 db.where_and(
923 value[0].as_str().unwrap(),
924 value[1].as_str().unwrap(),
925 value[2].clone(),
926 );
927 }
928
929 let total = db.clone().count().as_f64().unwrap();
930 let mut db_list = db.clone();
931
932 for item in order.members() {
933 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
934 }
935
936 let t = alls_field.join(",");
937 db_list.field(t.as_str());
938 let mut data = db_list.page(page, limit).json(&json_fields.join(",")).select();
939
940 let mut table_datas = object! {};
941 let mut ids = HashMap::new();
942
943 for item in data.members_mut() {
944 if table_fields.is_empty() {
945 continue;
946 }
947 for (field, _) in table_fields.entries() {
948 if table_datas[field].is_empty() {
949 table_datas[field] = array![];
950 }
951 let _ = table_datas[field].push(item[field].clone());
952 }
953 }
954 for (field, info) in table_fields.entries_mut() {
955 let _ = info["fields"].push("id");
956 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
957 let table_name = info["table"].clone();
958 let mut data_list = self.tools().db.table(table_name.as_str().unwrap()).where_and("id", "in", table_datas[field].clone()).field(&fields_k.join(",")).select();
959
960 for item in data_list.members_mut() {
961 let id = item["id"].as_str().unwrap_or("").to_string();
962 item.remove("id");
963 let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
964 ids.insert(
965 id.clone(),
966 object! {
967 value: id.clone(),
968 label:label.join(" | ").clone(),
969 },
970 );
971 }
972 }
973
974 for item in data.members_mut() {
975 if table_fields.is_empty() {
976 continue;
977 }
978 for (field, _) in table_fields.entries() {
979 if item[field].is_empty() {
980 continue;
981 }
982 let key = item[field].as_str().unwrap_or("");
983 if key.is_empty() {
984 continue;
985 }
986 if !ids.contains_key(key) {
987 continue;
988 }
989 item[field] = ids.get(key).unwrap().clone();
990 }
991 }
992
993 object! {
994 total:total,
995 data:data,
996 columns:columns,
997 search_name:search_name.join("/"),
998 filter_columns:filter_columns,
999 btn_all:array![],
1000 btn_api:array![],
1001 btn_ids:array![]
1002 }
1003 }
1004 fn table_column(&mut self, field: JsonValue) -> JsonValue {
1005 object! {
1006 name:field["field"].clone(),
1007 label:field["title"].clone(),
1008 align:"center",
1009 field:field["field"].clone(),
1010 sortable:true,
1011 mode:field["mode"].clone(),
1012 dec:field["dec"].clone(),
1013 fields:field["fields"].clone()
1014 }
1015 }
1016 fn filter_column(&mut self, field: JsonValue) -> JsonValue {
1017 object! {
1018 name:field["field"].clone(),
1019 label:field["title"].clone(),
1020 mode:field["mode"].clone(),
1021 option:field["option"].clone(),
1022 api:field["api"].clone(),
1023 fields:field["fields"].clone()
1024 }
1025 }
1026 fn tools(&mut self) -> Tools {
1028 let tools = PLUGIN_TOOLS.lock().unwrap();
1029 let tools = tools.get("tools").unwrap().clone();
1030 tools
1031 }
1032 fn config(&mut self, name: &str) -> JsonValue {
1034 if CONFIG.lock().unwrap().get(name).is_none() {
1035 object! {}
1036 } else {
1037 CONFIG.lock().unwrap().get(name).unwrap().clone()
1038 }
1039 }
1040 fn btn(&mut self) -> Btn {
1043 let mut btn = Btn::new(self.api().as_str());
1044 btn.fields(self.params().clone());
1045 btn.tags(self.tags());
1046 btn.icon(self.icon());
1047 btn.desc(self.description());
1048 btn.auth(self.auth());
1049 btn.public(self.public());
1050 btn.title(self.title());
1051 btn.btn_type(BtnType::Api);
1052 btn.btn_color(BtnColor::Primary);
1053 btn.path(self.api().clone().replace(".", "/").as_str());
1054 btn.pass(false);
1055 btn.addon();
1056 btn
1057 }
1058 fn set_global_data(&mut self, key: &str, value: JsonValue) {
1060 GLOBAL_DATA.with(|data| {
1061 data.borrow_mut()[key] = value;
1062 });
1063 }
1064 fn get_global_data(&mut self) -> JsonValue {
1066 GLOBAL_DATA.with(|data| {
1067 data.borrow().clone()
1068 })
1069 }
1070 fn get_global_data_key(&mut self, key: &str) -> JsonValue {
1072 GLOBAL_DATA.with(|data| {
1073 data.borrow()[key].clone()
1074 })
1075 }
1076}
1077#[derive(Debug, Clone)]
1078pub struct Btn {
1079 api: String,
1080 title: String,
1081 desc: String,
1082 tags: &'static [&'static str],
1083 auth: bool,
1084 public: bool,
1085 btn_type: BtnType,
1086 color: BtnColor,
1087 icon: String,
1088 cnd: Vec<JsonValue>,
1089 url: String,
1090 path: String,
1091 fields: JsonValue,
1092 addon: String,
1093 pass: bool,
1095}
1096impl Btn {
1097 pub fn new(api: &str) -> Self {
1098 Self {
1099 api: api.to_string(),
1100 title: "".to_string(),
1101 desc: "".to_string(),
1102 btn_type: BtnType::Api,
1103 color: BtnColor::Primary,
1104 icon: "".to_string(),
1105 auth: false,
1106 public: false,
1107 cnd: vec![],
1108 url: "".to_string(),
1109 path: "".to_string(),
1110 fields: object! {},
1111 tags: &[],
1112 pass: false,
1113 addon: "".to_string(),
1114 }
1115 }
1116
1117 pub fn addon(&mut self) -> &mut Self {
1118 self.addon = self.api.split('.').nth(0).unwrap().to_string();
1119 self
1120 }
1121 pub fn path(&mut self, path: &str) -> &mut Self {
1122 self.path = path.to_string();
1123 self
1124 }
1125 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1126 self.cnd = cnd;
1127 self
1128 }
1129 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1130 self.btn_type = btn_type;
1131 self
1132 }
1133 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1134 self.color = btn_color;
1135 self
1136 }
1137 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1138 self.fields = fields;
1139 self
1140 }
1141 pub fn pass(&mut self, pass: bool) -> &mut Self {
1142 self.pass = pass;
1143 self
1144 }
1145 pub fn url(&mut self, url: &str) -> &mut Self {
1146 self.url = url.to_string();
1147 self
1148 }
1149 pub fn title(&mut self, title: &str) -> &mut Self {
1150 self.title = title.to_string();
1151 self
1152 }
1153 pub fn desc(&mut self, desc: &str) -> &mut Self {
1154 self.desc = desc.to_string();
1155 self
1156 }
1157 pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1158 self.tags = tags;
1159 self
1160 }
1161 pub fn public(&mut self, public: bool) -> &mut Self {
1162 self.public = public;
1163 self
1164 }
1165 pub fn auth(&mut self, auth: bool) -> &mut Self {
1166 self.auth = auth;
1167 self
1168 }
1169 pub fn icon(&mut self, icon: &str) -> &mut Self {
1170 self.icon = icon.to_string();
1171 self
1172 }
1173 pub fn json(&mut self) -> JsonValue {
1174 object! {
1175 addon:self.addon.to_string() ,
1176 api:self.api.clone(),
1177 title:self.title.clone(),
1178 desc:self.desc.clone(),
1179 auth:self.auth,
1180 public:self.public,
1181 btn_type:self.btn_type.clone().str(),
1182 color:self.color.clone().str(),
1183 icon:self.icon.clone(),
1184 cnd:self.cnd.clone(),
1185 url:self.url.clone(),
1186 path:self.path.clone(),
1187 fields:self.fields.clone(),
1188 tags:self.tags,
1189 pass:self.pass,
1190 }
1191 }
1192}
1193
1194#[derive(Debug, Clone)]
1196pub enum InterfaceType {
1197 API,
1198 BTN,
1199 MENU,
1200}
1201
1202impl InterfaceType {
1203 pub fn str(&self) -> &'static str {
1204 match self {
1205 InterfaceType::API => "api",
1206 InterfaceType::BTN => "btn",
1207 InterfaceType::MENU => "menu",
1208 }
1209 }
1210 pub fn types() -> Vec<&'static str> {
1211 vec!["api", "btn", "menu"]
1212 }
1213}
1214
1215#[derive(Debug, Clone)]
1217pub enum BtnType {
1218 Form,
1220 FormDownload,
1222 FormCustom,
1224 FormData,
1225 Url,
1227 Api,
1229 Download,
1231 Path,
1233 DialogCustom,
1235 FormApiDialogCustom,
1237 Preview,
1239}
1240
1241impl BtnType {
1242 fn str(self) -> &'static str {
1243 match self {
1244 BtnType::Form => "form",
1245 BtnType::FormDownload => "form_download",
1246 BtnType::FormCustom => "form_custom",
1247 BtnType::FormData => "form_data",
1248 BtnType::Api => "api",
1249 BtnType::Download => "download",
1250 BtnType::Url => "url",
1251 BtnType::Path => "path",
1252 BtnType::DialogCustom => "dialog_custom",
1253 BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1254 BtnType::Preview => "preview",
1255 }
1256 }
1257}
1258#[derive(Debug, Clone)]
1260pub enum BtnColor {
1261 Primary,
1262 Red,
1263 Blue,
1264 Yellow,
1265 Green,
1266}
1267
1268impl BtnColor {
1269 fn str(self) -> &'static str {
1270 match self {
1271 BtnColor::Primary => "primary",
1272 BtnColor::Red => "negative",
1273 BtnColor::Blue => "info",
1274 BtnColor::Yellow => "warning",
1275 BtnColor::Green => "positive",
1276 }
1277 }
1278}
1279
1280
1281pub struct Dashboard {
1282 title: String,
1284 data: JsonValue,
1286 model: DashboardModel,
1288 class: String,
1290 icon: String,
1292 desc: String,
1294 api: String,
1296 options: JsonValue,
1298}
1299impl Dashboard {
1300 pub fn new(title: &str) -> Dashboard {
1301 Dashboard {
1302 title: title.to_string(),
1303 data: JsonValue::Null,
1304 model: DashboardModel::Number,
1305 class: "col-4".to_string(),
1306 icon: "".to_string(),
1307 desc: "".to_string(),
1308 api: "".to_string(),
1309 options: JsonValue::Null,
1310 }
1311 }
1312 pub fn options(&mut self, options: JsonValue) -> &mut Self {
1313 self.options = options;
1314 self
1315 }
1316 pub fn api(&mut self, api: &str) -> &mut Self {
1317 self.api = api.to_string();
1318 self
1319 }
1320 pub fn data(&mut self, data: JsonValue) -> &mut Self {
1321 self.data = data;
1322 self
1323 }
1324 pub fn class(&mut self, name: &str) -> &mut Self {
1325 self.class = name.to_string();
1326 self
1327 }
1328 pub fn icon(&mut self, name: &str) -> &mut Self {
1329 self.icon = name.to_string();
1330 self
1331 }
1332 pub fn model(&mut self, dashboard_model: DashboardModel) -> &mut Self {
1333 self.model = dashboard_model;
1334 self
1335 }
1336 pub fn desc(&mut self, desc: &str) -> &mut Self {
1337 self.desc = desc.to_string();
1338 self
1339 }
1340 pub fn json(&self) -> JsonValue {
1341 object! {
1342 title: self.title.clone(),
1343 data: self.data.clone(),
1344 class: self.class.clone(),
1345 icon: self.icon.clone(),
1346 model: self.model.str(),
1347 desc: self.desc.clone(),
1348 api: self.api.clone(),
1349 options:self.options.clone(),
1350 }
1351 }
1352}
1353
1354pub enum DashboardModel {
1355 Number,
1356 EchartsBar,
1357 EchartsPie,
1358 EchartsStackedLine,
1359 EchartsStackedBar,
1360 EchartsDoughnut,
1361 EchartsBarRace,
1362 EchartsGeoGraph,
1363}
1364
1365impl DashboardModel {
1366 pub fn str(&self) -> &'static str {
1367 match self {
1368 Self::Number => "number",
1369 Self::EchartsBar => "echarts-bar",
1370 Self::EchartsPie => "echarts-pie",
1371 Self::EchartsStackedLine => "echarts-stacked_line",
1372 Self::EchartsStackedBar => "echarts-stacked_bar",
1373 Self::EchartsDoughnut => "echarts-doughnut",
1374 Self::EchartsBarRace => "echarts-bar_race",
1375 Self::EchartsGeoGraph => "echarts-geo_graph",
1376 }
1377 }
1378}