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