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