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