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