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;
8use crate::tables::Tables;
9
10pub trait Action {
12 fn _name(&self) -> String {
14 type_name::<Self>().rsplit("::").next().unwrap().to_lowercase()
15 }
16 fn module_name(&self) -> String {
18 let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
19 let plugin = t[2].to_lowercase();
20 let module = t[3].to_lowercase();
21 format!("{plugin}.{module}")
22 }
23 fn addon_name(&self) -> String {
25 let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
26 t[2].to_lowercase()
27 }
28 fn api(&self) -> String {
30 let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
31 let plugin = t[2].to_lowercase();
32 let module = t[3].to_lowercase();
33 let action = t[4].to_lowercase();
34 format!("{plugin}.{module}.{action}")
35 }
36 fn token(&self) -> bool {
38 true
39 }
40
41 fn sort(&self) -> usize {
42 99
43 }
44 fn title(&self) -> &'static str;
46 fn description(&self) -> &'static str {
48 ""
49 }
50 fn path(&self) -> &'static str {
52 ""
53 }
54 fn query(&self) -> JsonValue {
56 object! {}
57 }
58 fn tags(&self) -> &'static [&'static str] {
60 &[]
61 }
62 fn icon(&self) -> &'static str {
63 ""
64 }
65 fn public(&self) -> bool {
67 true
68 }
69 fn auth(&self) -> bool {
71 true
72 }
73 fn interface_type(&self) -> InterfaceType {
75 InterfaceType::API
76 }
77 fn method(&mut self) -> Method {
79 Method::Post
80 }
81 fn content_type(&mut self) -> ContentType {
83 ContentType::Json
84 }
85 fn params_check(&mut self) -> bool {
87 true
88 }
89 fn params(&mut self) -> JsonValue {
91 object! {}
92 }
93 fn success(&mut self) -> ApiResponse {
95 let mut data = object! {};
96 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0).example(0.into()).swagger();
97 data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "").example("成功".into()).swagger();
98 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
99 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true).example(true.into()).swagger();
100 data["timestamp"] = br_fields::datetime::Timestamp::new(true, "timestamp", "时间戳", 0, 0.0).swagger();
101 ApiResponse::success(data, "请求成功")
102 }
103 fn error(&mut self) -> ApiResponse {
105 let mut data = object! {};
106 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000).example(1000.into()).swagger();
107 data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "").example("失败".into()).swagger();
108 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
109 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false).example(false.into()).swagger();
110 data["timestamp"] = br_fields::datetime::Timestamp::new(true, "timestamp", "时间戳", 0, 0.0).swagger();
111 ApiResponse::error(data, "请求失败")
112 }
113 fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
115 if self.public() && !self.method().str().is_empty() && self.method().str().to_lowercase() != request.method.str().to_lowercase() {
116 return Err(ApiResponse::fail(
117 -1,
118 format!(
119 "Request type error: Actual [{}] Expected [{}]",
120 request.method.str(),
121 self.method().str()
122 ).as_str(),
123 ));
124 }
125 let params = self.params().clone();
126 if self.params_check() {
127 self.check(&mut request.query.clone(), self.query().clone())?;
128 self.check(&mut request.body, params)?;
129 }
130 let res = self.index(request.clone());
131 match res.success {
132 true => Ok(res),
133 false => Err(res),
134 }
135 }
136 fn check(&mut self, request: &mut JsonValue, params: JsonValue) -> Result<(), ApiResponse> {
138 let req = request.clone();
139 for (name, _) in req.entries() {
140 if !params.has_key(name) {
141 request.remove(name);
142 }
143 }
144 for (name, field) in params.entries() {
145 let require = field["require"].as_bool().unwrap_or(false);
146 let title = field["title"].as_str().unwrap_or("");
147 if request.has_key(name) {
148 match field["mode"].as_str().unwrap() {
150 "key" => {
151 if !request[name].is_string() {
152 return Err(ApiResponse::fail(
153 900_001,
154 format!(
155 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
156 name, field["mode"]
157 ).as_str(),
158 ));
159 }
160 if require && request[name].is_empty() {
161 return Err(ApiResponse::fail(
162 900014,
163 format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
164 ));
165 }
166 }
167 "text" | "table" | "tree" => {
168 if !request[name].is_string() {
169 return Err(ApiResponse::fail(
170 900002,
171 format!(
172 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
173 name, field["mode"]
174 ).as_str(),
175 ));
176 }
177 if require && request[name].is_empty() {
178 return Err(ApiResponse::fail(
179 900002,
180 format!("{title} 必填").as_str(),
181 ));
182 }
183 }
184 "file" => {
185 if !request[name].is_array() && !request[name].is_string() {
186 return Err(ApiResponse::fail(
187 900003,
188 format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
189 ));
190 }
191 if require && request[name].is_empty() {
192 return Err(ApiResponse::fail(
193 900002,
194 format!("{title} 必填").as_str(),
195 ));
196 }
197 }
198 "int" => {
199 if require && request[name].to_string().is_empty() {
200 return Err(ApiResponse::fail(
201 900_002,
202 format!("{title} 必填").as_str(),
203 ));
204 }
205 if !request[name].to_string().is_empty() {
206 match request[name].to_string().parse::<i64>() {
207 Ok(_) => {}
208 Err(_) => {
209 return Err(ApiResponse::fail(
210 900013,
211 format!(
212 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
213 name, field["mode"]
214 ).as_str(),
215 ));
216 }
217 }
218 }
219 }
220 "timestamp" => {
221 if require && request[name].to_string().is_empty() {
222 return Err(ApiResponse::fail(
223 900002,
224 format!("{title} 必填").as_str(),
225 ));
226 }
227 if !request[name].to_string().is_empty() {
228 if request[name].is_array() && request[name].len() == 2 {
229 for item in request[name].members() {
231 match item.to_string().parse::<f64>() {
232 Ok(_) => {}
233 Err(_) => {
234 return Err(ApiResponse::fail(
235 900_013,
236 format!(
237 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
238 name, field["mode"]
239 ).as_str(),
240 ));
241 }
242 }
243 }
244 } else {
245 match request[name].to_string().parse::<f64>() {
246 Ok(_) => {}
247 Err(_) => {
248 return Err(ApiResponse::fail(
249 900013,
250 format!(
251 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
252 name, field["mode"]
253 ).as_str(),
254 ));
255 }
256 }
257 }
258 }
259 }
260 "float" => {
261 if require && request[name].to_string().is_empty() {
262 return Err(ApiResponse::fail(
263 900002,
264 format!("{title} 必填").as_str(),
265 ));
266 }
267 if !request[name].to_string().is_empty() {
268 match request[name].to_string().parse::<f64>() {
269 Ok(_) => {}
270 Err(_) => {
271 return Err(ApiResponse::fail(
272 900023,
273 format!(
274 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
275 name, field["mode"]
276 ).as_str(),
277 ));
278 }
279 }
280 }
281 }
282 "string" | "time" | "code" | "pass" | "email" | "location" | "color" | "date" | "barcode" | "datetime" | "editor" | "tel" => {
283 if !request[name].is_string() {
284 return Err(ApiResponse::fail(
285 -1,
286 format!(
287 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
288 name, field["mode"]
289 ).as_str(),
290 ));
291 }
292 if require && request[name].is_empty() {
293 return Err(ApiResponse::fail(
294 900004,
295 format!("{title} 必填").as_str(),
296 ));
297 }
298 }
299 "dict" => {
300 if require && request[name].is_empty() {
301 return Err(ApiResponse::fail(
302 900005,
303 format!("{title} 必填").as_str(),
304 ));
305 }
306 }
307 "switch" => {
308 match request[name].to_string().parse::<bool>() {
309 Ok(e) => {
310 request[name] = e.into();
311 }
312 Err(_) => {
313 return Err(ApiResponse::fail(
314 -1,
315 format!("请求参数数据类型错误: 参数 [{name}] 数据类型应为[{}]", field["mode"]).as_str(),
316 ));
317 }
318 }
319 }
320 "select" => {
321 if !request[name].is_array() && !request[name].is_string() {
322 return Err(ApiResponse::fail(
323 -1,
324 format!(
325 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
326 name, field["mode"]
327 ).as_str(),
328 ));
329 }
330 let value = if request[name].is_array() {
331 request[name].members().map(|m| m.to_string()).collect::<Vec<String>>()
332 } else {
333 request[name].to_string().split(",").map(|x| x.to_string()).collect::<Vec<String>>()
334 };
335 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>();
336
337 let require = field["require"].as_bool().unwrap();
338 for item in value.clone() {
339 if !option.contains(&&*item.clone()) && (item.is_empty() && require) {
340 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
341 return Err(ApiResponse::fail(-1, format!("请求参数选项错误: 参数 [{item}] 数据类型应为[{option}]之内").as_str()));
342 }
343 }
344 request[name] = value.into();
345 }
346 "radio" => {
347 if !request[name].is_string() {
348 return Err(ApiResponse::fail(
349 -1,
350 format!(
351 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
352 name, field["mode"], request[name]
353 ).as_str(),
354 ));
355 }
356 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
357 if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
358 {
359 return Err(ApiResponse::fail(
360 -1,
361 format!(
362 "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
363 name, request[name], option
364 ).as_str(),
365 ));
366 }
367 }
368 "array" | "polygon" => {
369 if !request[name].is_array() {
370 return Err(ApiResponse::fail(
371 900_009,
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 900010,
381 format!("请求参数数据类型错误: 参数 [{name}] 不能为空").as_str(),
382 ));
383 }
384 }
385 "object" => {
386 if !request[name].is_object() {
387 return Err(ApiResponse::fail(
388 900009,
389 format!(
390 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
391 name, field["mode"]
392 ).as_str(),
393 ));
394 }
395 if require && request[name].is_empty() {
396 return Err(ApiResponse::fail(
397 900006,
398 format!("{title} 必填").as_str(),
399 ));
400 }
401 }
402 _ => {
403 println!("检查未知类型: {}", field["mode"])
404 }
405 }
406 } else {
407 if require {
408 return Err(ApiResponse::fail(
409 900007,
410 format!("{title} 必填").as_str(),
411 ));
412 }
413 request[name] = field["def"].clone();
414 }
415 }
416 Ok(())
417 }
418 fn index(&mut self, request: Request) -> ApiResponse;
420 fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
422 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
423 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
424 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
425 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
426 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
427 params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
428 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 50, "id").example("id".into()).field();
429 params
430 }
431 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
432 fn table_select(
433 &mut self,
434 request: JsonValue,
435 table_name: &str,
436 fields: Vec<&str>,
437 ) -> JsonValue {
438 let page = request["page"].as_i32().unwrap_or(1);
439 let limit = request["limit"].as_i32().unwrap_or(10);
440
441 let search = request["search"].as_str().unwrap_or("");
442
443 let field_id = request["field"].as_str().unwrap_or("id");
444
445 let where_or = request["where_or"].clone();
446 let where_and = request["where_and"].clone();
447
448 let mut tools = self.tools();
449 let db = tools.db.table(table_name);
450
451 if !search.is_empty() {
452 db.where_and(&fields.join("|"), "like", format!("%{search}%").into());
453 }
454
455 for (key, value) in where_or.entries() {
456 if value.is_empty() {
457 continue;
458 }
459 if value.is_array() {
460 db.where_or(key, "between", value.clone());
461 db.where_or(key, "in", value.clone());
462 } else if value.is_boolean() {
463 db.where_or(key, "=", value.clone());
464 } else {
465 db.where_or(key, "like", format!("%{value}%").into());
466 }
467 }
468
469 for value in where_and.members() {
470 db.where_and(
471 value[0].as_str().unwrap(),
472 value[1].as_str().unwrap(),
473 value[2].clone(),
474 );
475 }
476
477 let total = (db.clone().count().as_f64().unwrap() / f64::from(limit)).ceil() as i64;
478 let mut db_list = db.clone();
479
480 db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
481
482 let mut data = db_list.page(page, limit).select();
483 let mut list = array![];
484 for item in data.members_mut() {
485 let value = item[field_id].clone();
486 item.remove(field_id);
487
488 let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
489
490 list.push(object! {
491 value: value,
492 label: label.join(" | ").clone(),
493 }).unwrap();
494 }
495 object! {
496 total:total,
497 data:list,
498 }
499 }
500 fn params_table_tree_select(&mut self, mut params: JsonValue) -> JsonValue {
502 params["ids"] = br_fields::text::Array::new(false, "ids", "加载已选中数据", array![]).field();
503 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
504 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 20, "").example("".into()).field();
505 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
506 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
507 params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
508 params
509 }
510 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
511 fn table_tree_select(
512 &mut self,
513 request: JsonValue,
514 table_name: &str,
515 pid_field: &str,
516 label_field: &str,
517 fields: Vec<&str>,
518 ) -> JsonValue {
519 let ids = request["ids"].clone();
520 let search = request["search"].as_str().unwrap_or("");
521 let pid_id = request["pid"].as_str().unwrap_or("id");
522
523 let where_or = request["where_or"].clone();
524 let where_and = request["where_and"].clone();
525
526 let mut tools = self.tools();
527 let db = tools.db.table(table_name);
528
529 db.where_and(pid_field, "=", pid_id.into());
530
531 if !search.is_empty() {
532 db.where_and("id", "in", search.into());
533 }
534
535 for (key, value) in where_or.entries() {
536 if value.is_empty() {
537 continue;
538 }
539 if value.is_array() {
540 db.where_or(key, "between", value.clone());
541 db.where_or(key, "in", value.clone());
542 } else if value.is_boolean() {
543 db.where_or(key, "=", value.clone());
544 } else {
545 db.where_or(key, "like", format!("%{value}%").into());
546 }
547 }
548
549 for value in where_and.members() {
550 db.where_and(
551 value[0].as_str().unwrap(),
552 value[1].as_str().unwrap(),
553 value[2].clone(),
554 );
555 }
556
557 db.field(format!("id,{},{}", pid_field, fields.join(",")).as_str());
558
559 let mut data = db.select();
560 for item in data.members_mut() {
561 let children = self.tools().db.table(table_name).where_and(pid_field, "=", item["id"].clone()).select();
562 if children.is_empty() {
563 item["lazy"] = false.into();
564 } else {
565 item["lazy"] = true.into();
566 }
567 }
568
569 let ids_list = if ids.is_empty() {
570 vec![]
571 } else {
572 let list = self.tools().db.table(table_name).where_and("id", "in", ids).field(format!("id,{},{}", pid_field, fields.join(",")).as_str()).select();
573 let mut t = vec![];
574 for item in list.members() {
575 let mut v = vec![];
576 let mut pid = item[pid_field].to_string();
577 v.push(item[label_field].to_string());
578 loop {
579 if pid.is_empty() {
580 break;
581 }
582 let find = self.tools().db.table(table_name).where_and("id", "=", pid.into()).field(format!("id,{},{}", pid_field, fields.join(",")).as_str()).find();
583 pid = find[pid_field].to_string();
584 v.push(find[label_field].to_string());
585 }
586 v.reverse();
587 t.push(object! {
588 id:item["id"].clone(),
589 label:v.join("/"),
590 });
591 }
592 t
593 };
594
595
596 object! {
597 data:data,
598 label_field:label_field,
599 pid_field:pid_field,
600 ids:ids_list.clone()
601
602 }
603 }
604 fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
606 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
607 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
608 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
609 params
610 }
611 #[allow(clippy::too_many_arguments)]
612 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
613 fn table_menu(
614 &mut self,
615 request: JsonValue,
616 table_name: &str,
617 label_field: &str,
618 fields: JsonValue,
619
620 hidd_field: Vec<&str>,
621 show_field: Vec<&str>,
622 search_fields: Vec<&str>,
623 ) -> JsonValue {
624 let search = request["search"].as_str().unwrap_or("");
625
626 let order = request["order"].clone();
627 let where_or = request["where_or"].clone();
628 let where_and = request["where_and"].clone();
629 let mut columns = array![];
630 let mut search_name = vec![];
631 let mut search_field = vec![];
632 let mut filter_columns = vec![];
633 let mut table_fields = object! {};
634 let mut table_field_json = vec![];
635
636 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
637 alls_field.retain(|x| !hidd_field.contains(x));
638 if !show_field.is_empty() {
639 alls_field.retain(|x| show_field.contains(x) || *x == "id");
640 }
641
642 for item in alls_field.iter() {
643 let row = &fields[item.to_string()];
644 let field = row["field"].to_string();
645 let title = row["title"].to_string();
646 let mode = row["mode"].to_string();
647
648 if search_fields.contains(&field.as_str()) {
649 search_name.push(title);
650 search_field.push(field.clone());
651 }
652 filter_columns.push(self.filter_column(row.clone()));
653 columns.push(self.table_column(row.clone())).unwrap();
654 let mut table_field_info = object! {};
655 match mode.as_str() {
656 "table" => table_field_info = row.clone(),
657 "array" => table_field_json.push(field.clone()),
658 _ => {}
659 }
660 if !table_field_info.is_empty() {
661 table_fields[field.as_str()] = table_field_info;
662 }
663 }
664
665 let mut tools = self.tools();
666 let db = tools.db.table(table_name);
667
668 if !search.is_empty() {
669 db.where_and(
670 &search_field.join("|"),
671 "like",
672 format!("%{search}%").into(),
673 );
674 }
675
676 for (key, value) in where_or.entries() {
677 if value.is_empty() {
678 continue;
679 }
680 if value.is_array() {
681 db.where_or(key, "between", value.clone());
682 db.where_or(key, "in", value.clone());
683 } else if value.is_boolean() {
684 db.where_or(key, "=", value.clone());
685 } else {
686 db.where_or(key, "like", format!("%{value}%").into());
687 }
688 }
689
690 for value in where_and.members() {
691 db.where_and(
692 value[0].as_str().unwrap(),
693 value[1].as_str().unwrap(),
694 value[2].clone(),
695 );
696 }
697
698 let mut db_list = db.clone();
699
700 for item in order.members() {
701 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
702 }
703
704 let t = alls_field.join(",");
705 db_list.field(t.as_str());
706
707 if !table_field_json.is_empty() {
708 db_list.json(&table_field_json.join(","));
709 }
710
711 let mut data = db_list.select();
712
713 let mut table_datas = object! {};
714 let mut ids = HashMap::new();
715
716 for item in data.members_mut() {
717 for (field, _) in table_fields.entries() {
718 if table_datas[field].is_empty() {
719 table_datas[field] = array![];
720 }
721 let _ = table_datas[field].push(item[field].clone());
722 }
723 }
724 for (field, info) in table_fields.entries_mut() {
725 let _ = info["fields"].push("id");
726 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
727 let table_name = info["table"].clone();
728 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();
729
730 for item in data_list.members_mut() {
731 let id = item["id"].as_str().unwrap_or("").to_string();
732 item.remove("id");
733 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
734 ids.insert(
735 id.clone(),
736 object! {
737 value: id.clone(),
738 label:label.join(" | ").clone(),
739 },
740 );
741 }
742 }
743
744 for item in data.members_mut() {
745 for (field, _) in table_fields.entries() {
746 if item[field].is_empty() {
747 continue;
748 }
749 item[field] = ids[item[field].as_str().unwrap()].clone();
750 }
751 }
752
753 object! {
754 data:data,
755 columns:columns,
756 search_name:search_name.join("/"),
757 label_field:label_field,
758 btn_all:array![],
759 btn_api:array![],
760 btn_ids:array![],
761 }
762 }
763 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
765 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
766 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
767 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
768 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
769 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
770 params
771 }
772 #[allow(clippy::too_many_arguments)]
773 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
774 fn table_tree(
775 &mut self,
776 request: JsonValue,
777 table_name: &str,
778 pid_field: &str,
779 label_field: &str,
780 fields: JsonValue,
781 hidd_field: Vec<&str>,
782 show_field: Vec<&str>,
783 search_fields: Vec<&str>,
784 _filter_fields: Vec<&str>,
785 ) -> JsonValue {
786 let search = request["search"].as_str().unwrap_or("");
787
788 let pid = request["pid"].clone();
789
790 let order = request["order"].clone();
791 let where_or = request["where_or"].clone();
792 let where_and = request["where_and"].clone();
793 let mut columns = array![];
794 let mut search_name = vec![];
795 let mut search_field = vec![];
796 let mut filter_columns = vec![];
797 let mut table_field_json = vec![];
798 let mut table_fields = object! {};
799
800 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
801 alls_field.retain(|x| !hidd_field.contains(x));
802 if !show_field.is_empty() {
803 alls_field.retain(|x| show_field.contains(x) || *x == "id");
804 }
805
806 for item in alls_field.iter() {
807 let row = fields[item.to_string()].clone();
808 let field = row["field"].to_string();
809 let title = row["title"].to_string();
810 let mode = row["mode"].to_string();
811
812 if search_fields.contains(&field.as_str()) {
813 search_name.push(title);
814 search_field.push(field.clone());
815 }
816 filter_columns.push(self.filter_column(row.clone()));
817 columns.push(self.table_column(row.clone())).unwrap();
818 let mut table_field_info = object! {};
819 match mode.as_str() {
820 "table" => table_field_info = row.clone(),
821 "array" => table_field_json.push(field.clone()),
822 _ => {}
823 }
824 if !table_field_info.is_empty() {
825 table_fields[field.as_str()] = table_field_info;
826 }
827 }
828
829 let mut tools = self.tools();
830 let db = tools.db.table(table_name);
831 db.where_and(pid_field, "=", pid);
832 if !search.is_empty() {
833 db.where_and(
834 &search_field.join("|"),
835 "like",
836 format!("%{search}%").into(),
837 );
838 }
839
840 for (key, value) in where_or.entries() {
841 if value.is_empty() {
842 continue;
843 }
844 if value.is_array() {
845 db.where_or(key, "in", value.clone());
847 } else if value.is_boolean() {
848 db.where_or(key, "=", value.clone());
849 } else {
850 db.where_or(key, "like", format!("%{value}%").into());
851 }
852 }
853
854 for value in where_and.members() {
855 db.where_and(
856 value[0].as_str().unwrap(),
857 value[1].as_str().unwrap(),
858 value[2].clone(),
859 );
860 }
861
862 let mut db_list = db.clone();
863
864 for item in order.members() {
865 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
866 }
867 let t = alls_field.join(",");
868 db_list.field(t.as_str());
869 if !table_field_json.is_empty() {
870 db_list.json(&table_field_json.join(","));
871 }
872 let mut data = db_list.select();
873
874 let mut table_datas = object! {};
875 let mut ids = HashMap::new();
876
877 for item in data.members_mut() {
878 for (field, _) in table_fields.entries() {
879 if table_datas[field].is_empty() {
880 table_datas[field] = array![];
881 }
882 let _ = table_datas[field].push(item[field].clone());
883 }
884 }
885 for (field, info) in table_fields.entries_mut() {
886 let _ = info["fields"].push("id");
887 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
888 let table_name = info["table"].clone();
889 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();
890
891 for item in data_list.members_mut() {
892 let id = item["id"].as_str().unwrap_or("").to_string();
893 item.remove("id");
894 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
895 ids.insert(
896 id.clone(),
897 object! {
898 value: id.clone(),
899 label:label.join(" | ").clone(),
900 },
901 );
902 }
903 }
904
905 let mut list = array![];
906 for item in data.members_mut() {
907 for (field, _) in table_fields.entries() {
908 if item[field].is_empty() {
909 continue;
910 }
911 item[field] = ids[item[field].as_str().unwrap()].clone();
912 }
913 let _ = list.push(object! {
914 id:item["id"].as_str().unwrap(),
915 code:item["code"].as_str().unwrap(),
916 label:item[label_field].as_str().unwrap(),
917 data:item.clone(),
918 });
919 }
920
921 object! {
922 data:list,
923 columns:columns,
924 search_name:search_name.join("/"),
925 filter_columns:filter_columns,
926 pid_field:pid_field,
927 btn_all:array![],
928 btn_api:array![]
929 }
930 }
931
932 #[allow(clippy::too_many_arguments)]
933 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
934 fn tree(&mut self, request: JsonValue, table_name: &str, pid_field: &str, label: &str, fields: JsonValue, hidd_field: Vec<&str>, show_field: Vec<&str>, search_fields: Vec<&str>, _filter_fields: Vec<&str>) -> JsonValue {
936 let search = request["search"].as_str().unwrap_or("");
937
938 let pid = request["pid"].clone();
939 let order = request["order"].clone();
940 let where_or = request["where_or"].clone();
941 let where_and = request["where_and"].clone();
942 let mut columns = array![];
943 let mut search_name = vec![];
944 let mut search_field = vec![];
945 let mut filter_columns = vec![];
946 let mut table_field_json = vec![];
947 let mut table_fields = object! {};
948
949 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
950 alls_field.retain(|x| !hidd_field.contains(x));
951 if !show_field.is_empty() {
952 alls_field.retain(|x| show_field.contains(x) || *x == "id");
953 }
954
955 for item in alls_field.iter() {
956 let row = fields[item.to_string()].clone();
957 let field = row["field"].to_string();
958 let title = row["title"].to_string();
959 let mode = row["mode"].to_string();
960
961 if search_fields.contains(&field.as_str()) {
962 search_name.push(title);
963 search_field.push(field.clone());
964 }
965 filter_columns.push(self.filter_column(row.clone()));
966 columns.push(self.table_column(row.clone())).unwrap();
967 let mut table_field_info = object! {};
968 match mode.as_str() {
969 "table" => table_field_info = row.clone(),
970 "array" => table_field_json.push(field.clone()),
971 _ => {}
972 }
973 if !table_field_info.is_empty() {
974 table_fields[field.as_str()] = table_field_info;
975 }
976 }
977
978 let mut tools = self.tools();
979 let db = tools.db.table(table_name);
980 db.where_and(pid_field, "=", pid);
981 if !search.is_empty() {
982 db.where_and(
983 &search_field.join("|"),
984 "like",
985 format!("%{search}%").into(),
986 );
987 }
988
989 for (key, value) in where_or.entries() {
990 if value.is_empty() {
991 continue;
992 }
993 if value.is_array() {
994 db.where_or(key, "in", value.clone());
995 } else if value.is_boolean() {
996 db.where_or(key, "=", value.clone());
997 } else {
998 db.where_or(key, "like", format!("%{value}%").into());
999 }
1000 }
1001
1002 for value in where_and.members() {
1003 db.where_and(
1004 value[0].as_str().unwrap(),
1005 value[1].as_str().unwrap(),
1006 value[2].clone(),
1007 );
1008 }
1009
1010 let mut db_list = db.clone();
1011
1012 for item in order.members() {
1013 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1014 }
1015 let t = alls_field.join(",");
1016 db_list.field(t.as_str());
1017 if !table_field_json.is_empty() {
1018 db_list.json(&table_field_json.join(","));
1019 }
1020 let mut data = db_list.select();
1021
1022 let mut table_datas = object! {};
1023 let mut ids = HashMap::new();
1024
1025 for item in data.members_mut() {
1026 for (field, _) in table_fields.entries() {
1027 if table_datas[field].is_empty() {
1028 table_datas[field] = array![];
1029 }
1030 let _ = table_datas[field].push(item[field].clone());
1031 }
1032 }
1033 for (field, info) in table_fields.entries_mut() {
1034 let _ = info["fields"].push("id");
1035 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1036 let table_name = info["table"].clone();
1037 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();
1038
1039 for item in data_list.members_mut() {
1040 let id = item["id"].as_str().unwrap_or("").to_string();
1041 item.remove("id");
1042 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
1043 ids.insert(
1044 id.clone(),
1045 object! {
1046 value: id.clone(),
1047 label:label.join(" | ").clone(),
1048 },
1049 );
1050 }
1051 }
1052
1053 for item in data.members_mut() {
1054 for (field, _) in table_fields.entries() {
1055 if item[field].is_empty() {
1056 continue;
1057 }
1058 item[field] = ids[item[field].as_str().unwrap()].clone();
1059 }
1060 }
1062
1063 object! {
1064 data:data,
1065 columns:columns,
1066 search_name:search_name.join("/"),
1067 label:label,
1068 btn_all:array![],
1069 btn_api:array![],
1070 btn_ids:array![]
1071 }
1072 }
1073
1074 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
1076 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
1077 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
1078 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
1079 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
1080 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
1081 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
1082 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
1083 params
1084 }
1085 #[allow(clippy::too_many_arguments)]
1093 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
1094 fn table_list(
1095 &mut self,
1096 request: JsonValue,
1097 table_name: &str,
1098 fields: JsonValue,
1099 hidd_field: Vec<&str>,
1100 show_field: Vec<&str>,
1101 search_fields: Vec<&str>,
1102 filter_fields: Vec<&str>,
1103 ) -> JsonValue {
1104 let page = request["page"].as_i32().unwrap_or(1);
1105 let limit = request["limit"].as_i32().unwrap_or(10);
1106 let search = request["search"].as_str().unwrap_or("");
1107 let order = request["order"].clone();
1108 let where_or = request["where_or"].clone();
1109 let where_and = request["where_and"].clone();
1110 let mut columns = array![];
1111 let mut search_name = vec![];
1112 let mut search_field = vec![];
1113 let mut filter_columns = vec![];
1114
1115 let mut table_fields = object! {};
1117 let mut tree_fields = object! {};
1119
1120 let mut json_fields = vec![];
1122
1123 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
1124 alls_field.retain(|x| !hidd_field.contains(x));
1125 if !show_field.is_empty() {
1126 alls_field.retain(|x| show_field.contains(x) || *x == "id");
1127 }
1128
1129 for item in alls_field.iter() {
1130 let key = item.to_string();
1131 let field = fields[key.clone()]["field"].as_str().unwrap();
1132 let title = fields[key.clone()]["title"].as_str().unwrap();
1133 let mode = fields[key.clone()]["mode"].as_str().unwrap();
1134
1135 if search_fields.contains(&field) {
1136 search_name.push(title);
1137 search_field.push(field);
1138 }
1139 if filter_fields.contains(&field) {
1140 filter_columns.push(self.filter_column(fields[key.clone()].clone()));
1141 }
1142 columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
1143
1144 match mode {
1145 "table" => {
1146 let table_field_info = if mode == "table" {
1147 fields[key.clone()].clone()
1148 } else {
1149 JsonValue::Null
1150 };
1151 if !table_field_info.is_empty() {
1152 table_fields[field] = table_field_info;
1153 }
1154 }
1155 "tree" => {
1156 let table_field_info = if mode == "tree" {
1157 fields[key.clone()].clone()
1158 } else {
1159 JsonValue::Null
1160 };
1161 if !table_field_info.is_empty() {
1162 tree_fields[field] = table_field_info;
1163 }
1164 }
1165 "object" | "array" | "polygon" => {
1166 json_fields.push(field);
1167 }
1168 _ => {}
1169 }
1170 }
1171
1172 let mut tools = self.tools();
1173 let db = tools.db.table(table_name);
1174
1175 if !search.is_empty() {
1176 db.where_and(
1177 &search_field.join("|"),
1178 "like",
1179 format!("%{search}%").into(),
1180 );
1181 }
1182
1183 for (key, value) in where_or.entries() {
1184 if value.is_empty() {
1185 continue;
1186 }
1187 if value.is_array() {
1188 db.where_or(key, "in", value.clone());
1189 } else if value.is_boolean() {
1190 db.where_or(key, "=", value.clone());
1191 } else {
1192 db.where_or(key, "like", format!("%{value}%").into());
1193 }
1194 }
1195
1196 for value in where_and.members() {
1197 db.where_and(
1198 value[0].as_str().unwrap(),
1199 value[1].as_str().unwrap(),
1200 value[2].clone(),
1201 );
1202 }
1203
1204 let total = db.clone().count().as_f64().unwrap();
1205 let mut db_list = db.clone();
1206
1207 for item in order.members() {
1208 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1209 }
1210
1211 let t = alls_field.join(",");
1212 db_list.field(t.as_str());
1213 let mut data = db_list.page(page, limit).json(&json_fields.join(",")).select();
1214
1215 let mut table_data = object! {};
1216
1217 for item in data.members_mut() {
1218 if !table_fields.is_empty() {
1219 for (field, field_info) in table_fields.entries() {
1220 if item[field].is_empty() {
1221 continue;
1222 }
1223 let key = item[field].as_str().unwrap_or("");
1224 if key.is_empty() {
1225 continue;
1226 }
1227 if !table_data.has_key(field) {
1228 table_data[field] = object! {};
1229 }
1230 if !table_data[field].has_key(key) {
1231 let mut info = field_info.clone();
1232 let _ = info["fields"].push("id");
1233 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1234 let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1235 let id = find["id"].to_string();
1236 find.remove("id");
1237 let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1238 table_data[field][key] = object! {
1239 value: id.clone(),
1240 label:label.join(" | ").clone(),
1241 };
1242 }
1243 item[field] = table_data[field][key].clone();
1244 }
1245 }
1246 if !tree_fields.is_empty() {
1247 for (field, field_info) in tree_fields.entries() {
1248 if item[field].is_empty() {
1249 continue;
1250 }
1251 let key = item[field].as_str().unwrap_or("");
1252 if key.is_empty() {
1253 continue;
1254 }
1255 if !table_data.has_key(field) {
1256 table_data[field] = object! {};
1257 }
1258 if !table_data[field].has_key(key) {
1259 let mut info = field_info.clone();
1260 let pid_field = info["pid_field"].clone().to_string();
1261 let _ = info["fields"].push("id");
1262 let _ = info["fields"].push(pid_field.clone());
1263 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1264 let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1265 let mut pid = find[pid_field.clone()].to_string();
1266 let mut name_list = vec![];
1267 let id = find["id"].to_string();
1268 find.remove("id");
1269 find.remove(&pid_field);
1270 let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1271 name_list.push(label.join(" | ").clone());
1272 loop {
1273 if pid.is_empty() {
1274 break;
1275 }
1276 let mut t = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", pid.clone().into()).field(&fields_k.join(",")).find();
1277 pid = t[pid_field.clone()].to_string();
1278 t.remove("id");
1279 t.remove(&pid_field);
1280 let label = t.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1281 name_list.push(label.join(" | ").clone());
1282 }
1283 name_list.reverse();
1284 table_data[field][key] = object! {
1285 value: id.clone(),
1286 label:name_list.join("/").clone(),
1287 };
1288 }
1289 item[field] = table_data[field][key].clone();
1290 }
1291 }
1292 }
1293
1294 object! {
1295 total:total,
1296 data:data,
1297 columns:columns,
1298 search_name:search_name.join("/"),
1299 filter_columns:filter_columns,
1300 btn_all:array![],
1301 btn_api:array![],
1302 btn_ids:array![]
1303 }
1304 }
1305 #[allow(clippy::too_many_arguments)]
1313 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
1314 fn table_edit_list(
1315 &mut self,
1316 request: JsonValue,
1317 table_name: &str,
1318 fields: JsonValue,
1319 hidd_field: Vec<&str>,
1320 show_field: Vec<&str>,
1321 search_fields: Vec<&str>,
1322 edit_fields: Vec<&str>,
1323 ) -> JsonValue {
1324 let page = request["page"].as_i32().unwrap_or(1);
1325 let limit = request["limit"].as_i32().unwrap_or(10);
1326 let search = request["search"].as_str().unwrap_or("");
1327 let order = request["order"].clone();
1328 let where_or = request["where_or"].clone();
1329 let where_and = request["where_and"].clone();
1330 let mut columns = array![];
1331 let mut search_name = vec![];
1332 let mut search_field = vec![];
1333 let mut edit_columns = vec![];
1334
1335 let mut table_fields = object! {};
1337 let mut tree_fields = object! {};
1339
1340 let mut json_fields = vec![];
1342
1343 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
1344 alls_field.retain(|x| !hidd_field.contains(x));
1345 if !show_field.is_empty() {
1346 alls_field.retain(|x| show_field.contains(x) || *x == "id");
1347 }
1348
1349 for item in alls_field.iter() {
1350 let key = item.to_string();
1351 let field = fields[key.clone()]["field"].as_str().unwrap();
1352 let title = fields[key.clone()]["title"].as_str().unwrap();
1353 let mode = fields[key.clone()]["mode"].as_str().unwrap();
1354
1355 if search_fields.contains(&field) {
1356 search_name.push(title);
1357 search_field.push(field);
1358 }
1359 if edit_fields.contains(&field) {
1360 edit_columns.push(self.filter_column(fields[key.clone()].clone()));
1361 }
1362 columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
1363
1364 match mode {
1365 "table" => {
1366 let table_field_info = if mode == "table" {
1367 fields[key.clone()].clone()
1368 } else {
1369 JsonValue::Null
1370 };
1371 if !table_field_info.is_empty() {
1372 table_fields[field] = table_field_info;
1373 }
1374 }
1375 "tree" => {
1376 let table_field_info = if mode == "tree" {
1377 fields[key.clone()].clone()
1378 } else {
1379 JsonValue::Null
1380 };
1381 if !table_field_info.is_empty() {
1382 tree_fields[field] = table_field_info;
1383 }
1384 }
1385 "object" | "array" | "polygon" => {
1386 json_fields.push(field);
1387 }
1388 _ => {}
1389 }
1390 }
1391
1392 let mut tools = self.tools();
1393 let db = tools.db.table(table_name);
1394
1395 if !search.is_empty() {
1396 db.where_and(
1397 &search_field.join("|"),
1398 "like",
1399 format!("%{search}%").into(),
1400 );
1401 }
1402
1403 for (key, value) in where_or.entries() {
1404 if value.is_empty() {
1405 continue;
1406 }
1407 if value.is_array() {
1408 db.where_or(key, "in", value.clone());
1409 } else if value.is_boolean() {
1410 db.where_or(key, "=", value.clone());
1411 } else {
1412 db.where_or(key, "like", format!("%{value}%").into());
1413 }
1414 }
1415
1416 for value in where_and.members() {
1417 db.where_and(
1418 value[0].as_str().unwrap(),
1419 value[1].as_str().unwrap(),
1420 value[2].clone(),
1421 );
1422 }
1423
1424 let total = db.clone().count().as_f64().unwrap();
1425 let mut db_list = db.clone();
1426
1427 for item in order.members() {
1428 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
1429 }
1430
1431 let t = alls_field.join(",");
1432 db_list.field(t.as_str());
1433 let mut data = db_list.page(page, limit).json(&json_fields.join(",")).select();
1434
1435 let mut table_data = object! {};
1436
1437 for item in data.members_mut() {
1438 if !table_fields.is_empty() {
1439 for (field, field_info) in table_fields.entries() {
1440 if item[field].is_empty() {
1441 continue;
1442 }
1443 let key = item[field].as_str().unwrap_or("");
1444 if key.is_empty() {
1445 continue;
1446 }
1447 if !table_data.has_key(field) {
1448 table_data[field] = object! {};
1449 }
1450 if !table_data[field].has_key(key) {
1451 let mut info = field_info.clone();
1452 let _ = info["fields"].push("id");
1453 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1454 let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1455 let id = find["id"].to_string();
1456 find.remove("id");
1457 let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1458 table_data[field][key] = object! {
1459 value: id.clone(),
1460 label:label.join(" | ").clone(),
1461 };
1462 }
1463 item[field] = table_data[field][key].clone();
1464 }
1465 }
1466 if !tree_fields.is_empty() {
1467 for (field, field_info) in tree_fields.entries() {
1468 if item[field].is_empty() {
1469 continue;
1470 }
1471 let key = item[field].as_str().unwrap_or("");
1472 if key.is_empty() {
1473 continue;
1474 }
1475 if !table_data.has_key(field) {
1476 table_data[field] = object! {};
1477 }
1478 if !table_data[field].has_key(key) {
1479 let mut info = field_info.clone();
1480 let pid_field = info["pid_field"].clone().to_string();
1481 let _ = info["fields"].push("id");
1482 let _ = info["fields"].push(pid_field.clone());
1483 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
1484 let mut find = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", key.into()).field(&fields_k.join(",")).find();
1485 let mut pid = find[pid_field.clone()].to_string();
1486 let mut name_list = vec![];
1487 let id = find["id"].to_string();
1488 find.remove("id");
1489 find.remove(&pid_field);
1490 let label = find.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1491 name_list.push(label.join(" | ").clone());
1492 loop {
1493 if pid.is_empty() {
1494 break;
1495 }
1496 let mut t = self.tools().db.table(info["table"].as_str().unwrap()).where_and("id", "=", pid.clone().into()).field(&fields_k.join(",")).find();
1497 pid = t[pid_field.clone()].to_string();
1498 t.remove("id");
1499 t.remove(&pid_field);
1500 let label = t.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
1501 name_list.push(label.join(" | ").clone());
1502 }
1503 name_list.reverse();
1504 table_data[field][key] = object! {
1505 value: id.clone(),
1506 label:name_list.join("/").clone(),
1507 };
1508 }
1509 item[field] = table_data[field][key].clone();
1510 }
1511 }
1512 }
1513
1514 object! {
1515 total:total,
1516 data:data,
1517 columns:columns,
1518 search_name:search_name.join("/"),
1519 edit_columns:edit_columns
1520 }
1521 }
1522 #[allow(clippy::too_many_arguments)]
1523 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql", feature = "pgsql"))]
1524 fn table(&mut self) -> Tables {
1525 Tables::new(self.tools().db.clone())
1526 }
1527 fn table_column(&mut self, field: JsonValue) -> JsonValue {
1528 object! {
1529 name:field["field"].clone(),
1530 label:field["title"].clone(),
1531 align:"center",
1532 field:field["field"].clone(),
1533 sortable:true,
1534 mode:field["mode"].clone(),
1535 dec:field["dec"].clone(),
1536 fields:field["fields"].clone()
1537 }
1538 }
1539 fn filter_column(&mut self, field: JsonValue) -> JsonValue {
1540 object! {
1541 name:field["field"].clone(),
1542 label:field["title"].clone(),
1543 mode:field["mode"].clone(),
1544 option:field["option"].clone(),
1545 api:field["api"].clone(),
1546 fields:field["fields"].clone()
1547 }
1548 }
1549 fn tools(&mut self) -> Tools {
1551 let tools = PLUGIN_TOOLS.lock().unwrap();
1552 let tools = tools.get("tools").unwrap().clone();
1553 tools
1554 }
1555 fn config(&mut self, name: &str) -> JsonValue {
1557 if CONFIG.lock().unwrap().get(name).is_none() {
1558 object! {}
1559 } else {
1560 CONFIG.lock().unwrap().get(name).unwrap().clone()
1561 }
1562 }
1563 fn btn(&mut self) -> Btn {
1566 let mut btn = Btn::new(self.api().as_str());
1567 btn.fields(self.params().clone());
1568 btn.tags(self.tags());
1569 btn.icon(self.icon());
1570 btn.desc(self.description());
1571 btn.auth(self.auth());
1572 btn.public(self.public());
1573 btn.title(self.title());
1574 btn.btn_type(BtnType::Api);
1575 btn.btn_color(BtnColor::Primary);
1576 btn.path(self.api().clone().replace(".", "/").as_str());
1577 btn.pass(false);
1578 btn.addon();
1579 btn
1580 }
1581 fn set_global_data(&mut self, key: &str, value: JsonValue) {
1583 GLOBAL_DATA.with(|data| {
1584 data.borrow_mut()[key] = value;
1585 });
1586 }
1587 fn get_global_data(&mut self) -> JsonValue {
1589 GLOBAL_DATA.with(|data| {
1590 data.borrow().clone()
1591 })
1592 }
1593 fn get_global_data_key(&mut self, key: &str) -> JsonValue {
1595 GLOBAL_DATA.with(|data| {
1596 data.borrow()[key].clone()
1597 })
1598 }
1599}
1600#[derive(Debug, Clone)]
1601pub struct Btn {
1602 api: String,
1603 title: String,
1604 desc: String,
1605 tags: &'static [&'static str],
1606 auth: bool,
1607 public: bool,
1608 btn_type: BtnType,
1609 color: BtnColor,
1610 icon: String,
1611 cnd: Vec<JsonValue>,
1612 url: String,
1613 path: String,
1614 fields: JsonValue,
1615 addon: String,
1616 pass: bool,
1618}
1619impl Btn {
1620 pub fn new(api: &str) -> Self {
1621 Self {
1622 api: api.to_string(),
1623 title: "".to_string(),
1624 desc: "".to_string(),
1625 btn_type: BtnType::Api,
1626 color: BtnColor::Primary,
1627 icon: "".to_string(),
1628 auth: false,
1629 public: false,
1630 cnd: vec![],
1631 url: "".to_string(),
1632 path: "".to_string(),
1633 fields: object! {},
1634 tags: &[],
1635 pass: false,
1636 addon: "".to_string(),
1637 }
1638 }
1639
1640 pub fn addon(&mut self) -> &mut Self {
1641 self.addon = self.api.split('.').nth(0).unwrap().to_string();
1642 self
1643 }
1644 pub fn path(&mut self, path: &str) -> &mut Self {
1645 self.path = path.to_string();
1646 self
1647 }
1648 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1649 self.cnd = cnd;
1650 self
1651 }
1652 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1653 self.btn_type = btn_type;
1654 self
1655 }
1656 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1657 self.color = btn_color;
1658 self
1659 }
1660 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1661 self.fields = fields;
1662 self
1663 }
1664 pub fn pass(&mut self, pass: bool) -> &mut Self {
1665 self.pass = pass;
1666 self
1667 }
1668 pub fn url(&mut self, url: &str) -> &mut Self {
1669 self.url = url.to_string();
1670 self
1671 }
1672 pub fn title(&mut self, title: &str) -> &mut Self {
1673 self.title = title.to_string();
1674 self
1675 }
1676 pub fn desc(&mut self, desc: &str) -> &mut Self {
1677 self.desc = desc.to_string();
1678 self
1679 }
1680 pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1681 self.tags = tags;
1682 self
1683 }
1684 pub fn public(&mut self, public: bool) -> &mut Self {
1685 self.public = public;
1686 self
1687 }
1688 pub fn auth(&mut self, auth: bool) -> &mut Self {
1689 self.auth = auth;
1690 self
1691 }
1692 pub fn icon(&mut self, icon: &str) -> &mut Self {
1693 self.icon = icon.to_string();
1694 self
1695 }
1696 pub fn json(&mut self) -> JsonValue {
1697 object! {
1698 addon:self.addon.to_string() ,
1699 api:self.api.clone(),
1700 title:self.title.clone(),
1701 desc:self.desc.clone(),
1702 auth:self.auth,
1703 public:self.public,
1704 btn_type:self.btn_type.clone().str(),
1705 color:self.color.clone().str(),
1706 icon:self.icon.clone(),
1707 cnd:self.cnd.clone(),
1708 url:self.url.clone(),
1709 path:self.path.clone(),
1710 fields:self.fields.clone(),
1711 tags:self.tags,
1712 pass:self.pass,
1713 }
1714 }
1715}
1716
1717#[derive(Debug, Clone)]
1719pub enum InterfaceType {
1720 API,
1721 BTN,
1722 MENU,
1723}
1724
1725impl InterfaceType {
1726 pub fn str(&self) -> &'static str {
1727 match self {
1728 InterfaceType::API => "api",
1729 InterfaceType::BTN => "btn",
1730 InterfaceType::MENU => "menu",
1731 }
1732 }
1733 pub fn types() -> Vec<&'static str> {
1734 vec!["api", "btn", "menu"]
1735 }
1736}
1737
1738#[derive(Debug, Clone)]
1740pub enum BtnType {
1741 Form,
1743 FormDownload,
1745 FormCustom,
1747 FormData,
1748 Url,
1750 Api,
1752 Download,
1754 Path,
1756 DialogCustom,
1758 FormApiDialogCustom,
1760 Preview,
1762}
1763
1764impl BtnType {
1765 fn str(self) -> &'static str {
1766 match self {
1767 BtnType::Form => "form",
1768 BtnType::FormDownload => "form_download",
1769 BtnType::FormCustom => "form_custom",
1770 BtnType::FormData => "form_data",
1771 BtnType::Api => "api",
1772 BtnType::Download => "download",
1773 BtnType::Url => "url",
1774 BtnType::Path => "path",
1775 BtnType::DialogCustom => "dialog_custom",
1776 BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1777 BtnType::Preview => "preview",
1778 }
1779 }
1780}
1781#[derive(Debug, Clone)]
1783pub enum BtnColor {
1784 Primary,
1785 Red,
1786 Blue,
1787 Yellow,
1788 Green,
1789}
1790
1791impl BtnColor {
1792 fn str(self) -> &'static str {
1793 match self {
1794 BtnColor::Primary => "primary",
1795 BtnColor::Red => "negative",
1796 BtnColor::Blue => "info",
1797 BtnColor::Yellow => "warning",
1798 BtnColor::Green => "positive",
1799 }
1800 }
1801}
1802
1803
1804pub struct Dashboard {
1805 title: String,
1807 data: JsonValue,
1809 model: DashboardModel,
1811 class: String,
1813 icon: String,
1815 desc: String,
1817 api: String,
1819 options: JsonValue,
1821}
1822impl Dashboard {
1823 pub fn new(title: &str) -> Dashboard {
1824 Dashboard {
1825 title: title.to_string(),
1826 data: JsonValue::Null,
1827 model: DashboardModel::Number,
1828 class: "col-4".to_string(),
1829 icon: "".to_string(),
1830 desc: "".to_string(),
1831 api: "".to_string(),
1832 options: JsonValue::Null,
1833 }
1834 }
1835 pub fn options(&mut self, options: JsonValue) -> &mut Self {
1836 self.options = options;
1837 self
1838 }
1839 pub fn api(&mut self, api: &str) -> &mut Self {
1840 self.api = api.to_string();
1841 self
1842 }
1843 pub fn data(&mut self, data: JsonValue) -> &mut Self {
1844 self.data = data;
1845 self
1846 }
1847 pub fn class(&mut self, name: &str) -> &mut Self {
1848 self.class = name.to_string();
1849 self
1850 }
1851 pub fn icon(&mut self, name: &str) -> &mut Self {
1852 self.icon = name.to_string();
1853 self
1854 }
1855 pub fn model(&mut self, dashboard_model: DashboardModel) -> &mut Self {
1856 self.model = dashboard_model;
1857 self
1858 }
1859 pub fn desc(&mut self, desc: &str) -> &mut Self {
1860 self.desc = desc.to_string();
1861 self
1862 }
1863 pub fn json(&self) -> JsonValue {
1864 object! {
1865 title: self.title.clone(),
1866 data: self.data.clone(),
1867 class: self.class.clone(),
1868 icon: self.icon.clone(),
1869 model: self.model.str(),
1870 desc: self.desc.clone(),
1871 api: self.api.clone(),
1872 options:self.options.clone(),
1873 }
1874 }
1875}
1876
1877pub enum DashboardModel {
1878 Number,
1880 EchartsBar,
1882 EchartsStackedBar,
1884 EchartsBarRace,
1886 EchartsPie,
1888 EchartsDoughnut,
1890 EchartsStackedLine,
1892 EchartsStackedLineArea,
1894 EchartsGeoGraph,
1896}
1897
1898impl DashboardModel {
1899 pub fn str(&self) -> &'static str {
1900 match self {
1901 Self::Number => "number",
1902 Self::EchartsBar => "echarts-bar",
1903 Self::EchartsStackedBar => "echarts-stacked_bar",
1904 Self::EchartsBarRace => "echarts-bar_race",
1905 Self::EchartsPie => "echarts-pie",
1906 Self::EchartsDoughnut => "echarts-doughnut",
1907 Self::EchartsStackedLine => "echarts-stacked_line",
1908 Self::EchartsStackedLineArea => "echarts-stacked_line_area",
1909 Self::EchartsGeoGraph => "echarts-geo_graph",
1910 }
1911 }
1912}