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