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