1use crate::request::{ContentType, Method, Request};
2use crate::{CONFIG, 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(&mut self) -> bool {
65 true
66 }
67 fn interface_type(&mut 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(&mut self) -> JsonValue {
81 object! {}
82 }
83 fn success(&mut self) -> ApiResponse {
85 let mut data = object! {};
86 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0).example(0.into()).swagger();
87 data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "").example("成功".into()).swagger();
88 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
89 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true).example(true.into()).swagger();
90 ApiResponse::success(data, "请求成功")
91 }
92 fn error(&mut self) -> ApiResponse {
94 let mut data = object! {};
95 data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000).example(1000.into()).swagger();
96 data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "").example("失败".into()).swagger();
97 data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
98 data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false).example(false.into()).swagger();
99 ApiResponse::error(data, "请求失败")
100 }
101 fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
103 if self.method().str().to_lowercase() != request.method.str().to_lowercase() {
104 return Err(ApiResponse::fail(
105 -1,
106 format!(
107 "Request type error: Actual [{}] Expected [{}]",
108 request.method.str(),
109 self.method().str()
110 ).as_str(),
111 ));
112 }
113 let params = self.params().clone();
114 self.check(&mut request.query.clone(), self.query().clone())?;
115 self.check(&mut request.body, params)?;
116 let res = self.index(request.clone());
117 match res.success {
118 true => Ok(res),
119 false => Err(res),
120 }
121 }
122 fn check(&mut self, request: &mut JsonValue, params: JsonValue) -> Result<(), ApiResponse> {
124 let req = request.clone();
125 for (name, _) in req.entries() {
126 if !params.has_key(name) {
127 request.remove(name);
128 }
129 }
130 for (name, field) in params.entries() {
131 let require = field["require"].as_bool().unwrap_or(false);
132 let title = field["title"].as_str().unwrap_or("");
133 if request.has_key(name) {
134 match field["mode"].as_str().unwrap() {
136 "key" => {
137 if !request[name].is_string() {
138 return Err(ApiResponse::fail(
139 900001,
140 format!(
141 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
142 name, field["mode"]
143 ).as_str(),
144 ));
145 }
146 if require && request[name].is_empty() {
147 return Err(ApiResponse::fail(
148 900014,
149 format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
150 ));
151 }
152 }
153 "text" | "table" => {
154 if !request[name].is_string() {
155 return Err(ApiResponse::fail(
156 900002,
157 format!(
158 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
159 name, field["mode"]
160 ).as_str(),
161 ));
162 }
163 if require && request[name].is_empty() {
164 return Err(ApiResponse::fail(
165 900002,
166 format!("{} 必填", title).as_str(),
167 ));
168 }
169 }
170 "file" => {
171 if !request[name].is_array() && !request[name].is_string() {
172 return Err(ApiResponse::fail(
173 900003,
174 format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).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 "int" => {
185 if !request[name].is_number() {
186 return Err(ApiResponse::fail(
187 900013,
188 format!(
189 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
190 name, field["mode"]
191 ).as_str(),
192 ));
193 }
194 }
195 "timestamp" => {
196 if !request[name].is_number() {
197 return Err(ApiResponse::fail(
198 900013,
199 format!(
200 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
201 name, field["mode"]
202 ).as_str(),
203 ));
204 }
205 }
206 "float" => {
207 if !request[name].is_string() && !request[name].is_number() {
208 return Err(ApiResponse::fail(
209 900023,
210 format!("参数 [{}] 数据类型应为[{}]", name, field["mode"]).as_str(),
211 ));
212 }
213 if require && request[name].is_empty() {
214 return Err(ApiResponse::fail(
215 900004,
216 format!("{} 必填", title).as_str(),
217 ));
218 }
219 }
220 "string" | "code" | "pass" | "email" | "location" | "color" => {
221 if !request[name].is_string() {
222 return Err(ApiResponse::fail(
223 -1,
224 format!(
225 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
226 name, field["mode"]
227 ).as_str(),
228 ));
229 }
230 if require && request[name].is_empty() {
231 return Err(ApiResponse::fail(
232 900004,
233 format!("{} 必填", title).as_str(),
234 ));
235 }
236 }
237 "dict" => {
238 if require && request[name].is_empty() {
239 return Err(ApiResponse::fail(
240 900005,
241 format!("{} 必填", title).as_str(),
242 ));
243 }
244 }
245 "switch" => {
246 if !request[name].is_boolean() {
247 return Err(ApiResponse::fail(
248 -1,
249 format!(
250 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
251 name, field["mode"]
252 ).as_str(),
253 ));
254 }
255 }
256 "select" => {
257 if !request[name].is_array() && !request[name].is_string() {
258 return Err(ApiResponse::fail(
259 -1,
260 format!(
261 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
262 name, field["mode"]
263 ).as_str(),
264 ));
265 }
266 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
267 if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
268 {
269 return Err(ApiResponse::fail(
270 -1,
271 format!(
272 "请求参数选项错误: 参数 [{}] 数据类型应为[{}]之内",
273 name, option
274 ).as_str(),
275 ));
276 }
277 if request[name].is_array() {
278 let res1 = request[name].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>();
279 let diff = res1.iter().filter(|&item| {
280 !field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().contains(item)
281 }).collect::<Vec<&&str>>();
282 if !diff.is_empty() {
283 return Err(ApiResponse::fail(
284 -1,
285 format!(
286 "请求参数选项错误: 参数 [{}] 数据 {:?} 应为[{:?}]范围之内",
287 name, diff, option
288 ).as_str(),
289 ));
290 }
291 }
292 }
293 "radio" => {
294 if !request[name].is_string() {
295 return Err(ApiResponse::fail(
296 -1,
297 format!(
298 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
299 name, field["mode"], request[name]
300 ).as_str(),
301 ));
302 }
303 let option = field["option"].members().map(|m| m.as_str().unwrap_or("")).collect::<Vec<&str>>().join(",");
304 if request[name].is_string() && !field["option"].contains(request[name].as_str().unwrap_or(""))
305 {
306 return Err(ApiResponse::fail(
307 -1,
308 format!(
309 "请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
310 name, request[name], option
311 ).as_str(),
312 ));
313 }
314 }
315 "array" => {
316 if !request[name].is_array() {
317 return Err(ApiResponse::fail(
318 900009,
319 format!(
320 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
321 name, field["mode"]
322 ).as_str(),
323 ));
324 }
325 if require && request[name].is_empty() {
326 return Err(ApiResponse::fail(
327 900010,
328 format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
329 ));
330 }
331 }
332 "object" => {
333 if !request[name].is_object() {
334 return Err(ApiResponse::fail(
335 900009,
336 format!(
337 "请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
338 name, field["mode"]
339 ).as_str(),
340 ));
341 }
342 if require && request[name].is_empty() {
343 return Err(ApiResponse::fail(
344 900006,
345 format!("{} 必填", title).as_str(),
346 ));
347 }
348 }
349 _ => {
350 println!("检查未知类型: {}", field["mode"])
351 }
352 }
353 } else {
354 if require {
355 return Err(ApiResponse::fail(
356 900007,
357 format!("{} 必填", title).as_str(),
358 ));
359 }
360 request[name] = field["def"].clone();
361 }
362 }
363 Ok(())
364 }
365 fn index(&mut self, request: Request) -> ApiResponse;
367 fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
368 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
369 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
370 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
371 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
372 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
373 params["params"] = br_fields::text::Object::new(false, "params", "关联数据参数", object! {}).example(object! {}).field();
374 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 50, "id").example("id".into()).field();
375 params
376 }
377 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
378 fn table_select(
379 &mut self,
380 request: JsonValue,
381 table_name: &str,
382 fields: Vec<&str>,
383 ) -> JsonValue {
384 let page = request["page"].as_i32().unwrap_or(1);
385 let limit = request["limit"].as_i32().unwrap_or(10);
386
387 let search = request["search"].as_str().unwrap_or("");
388
389 let field_id = request["field"].as_str().unwrap_or("id");
390
391 let where_or = request["where_or"].clone();
392 let where_and = request["where_and"].clone();
393
394 let mut tools = self.tools();
395 let db = tools.db.table(table_name);
396
397 if !search.is_empty() {
398 db.where_and(&fields.join("|"), "like", format!("%{}%", search).into());
399 }
400
401 for (key, value) in where_or.entries() {
402 if value.is_empty() {
403 continue;
404 }
405 if value.is_array() {
406 db.where_or(key, "between", value.clone());
407 db.where_or(key, "in", value.clone());
408 } else if value.is_boolean() {
409 db.where_or(key, "=", value.clone());
410 } else {
411 db.where_or(key, "like", format!("%{}%", value).into());
412 }
413 }
414
415 for value in where_and.members() {
416 db.where_and(
417 value[0].as_str().unwrap(),
418 value[1].as_str().unwrap(),
419 value[2].clone(),
420 );
421 }
422
423 let total = (db.clone().count().as_f64().unwrap() / limit as f64).ceil() as i64;
424 let mut db_list = db.clone();
425
426 db_list.field(format!("{},{}", field_id, fields.join(",")).as_str());
427
428 let mut data = db_list.page(page, limit).select();
429 let mut list = array![];
430 for item in data.members_mut() {
431 let value = item[field_id].clone();
432 item.remove(field_id);
433
434 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
435
436 list.push(object! {
437 value: value,
438 label: label.join(" | ").clone(),
439 }).unwrap();
440 }
441 object! {
442 total:total,
443 data:list,
444 }
445 }
446 fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
448 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
449 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
450 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
451 params
452 }
453 #[allow(clippy::too_many_arguments)]
454 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
455 fn table_menu(
456 &mut self,
457 request: JsonValue,
458 table_name: &str,
459 label_field: &str,
460 fields: JsonValue,
461
462 hidd_field: Vec<&str>,
463 show_field: Vec<&str>,
464
465 search_fields: Vec<&str>,
466 _filter_fields: Vec<&str>,
467 ) -> JsonValue {
468 let search = request["search"].as_str().unwrap_or("");
469
470 let order = request["order"].clone();
471 let where_or = request["where_or"].clone();
472 let where_and = request["where_and"].clone();
473 let mut columns = array![];
474 let mut search_name = vec![];
475 let mut search_field = vec![];
476 let mut filter_columns = vec![];
477 let mut table_fields = object! {};
478 let mut table_field_json = vec![];
479
480 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
481 alls_field.retain(|x| !hidd_field.contains(x));
482 if !show_field.is_empty() {
483 alls_field.retain(|x| show_field.contains(x) || *x == "id");
484 }
485
486 for item in alls_field.iter() {
487 let row = &fields[item.to_string()];
488 let field = row["field"].to_string();
489 let title = row["title"].to_string();
490 let mode = row["mode"].to_string();
491
492 if search_fields.contains(&field.as_str()) {
493 search_name.push(title);
494 search_field.push(field.clone());
495 }
496 filter_columns.push(self.filter_column(row.clone()));
497 columns.push(self.table_column(row.clone())).unwrap();
498 let mut table_field_info = object! {};
499 match mode.as_str() {
500 "table" => table_field_info = row.clone(),
501 "array" => table_field_json.push(field.clone()),
502 _ => {}
503 }
504 if !table_field_info.is_empty() {
505 table_fields[field.as_str()] = table_field_info;
506 }
507 }
508
509 let mut tools = self.tools();
510 let db = tools.db.table(table_name);
511
512 if !search.is_empty() {
513 db.where_and(
514 &search_field.join("|"),
515 "like",
516 format!("%{}%", search).into(),
517 );
518 }
519
520 for (key, value) in where_or.entries() {
521 if value.is_empty() {
522 continue;
523 }
524 if value.is_array() {
525 db.where_or(key, "between", value.clone());
526 db.where_or(key, "in", value.clone());
527 } else if value.is_boolean() {
528 db.where_or(key, "=", value.clone());
529 } else {
530 db.where_or(key, "like", format!("%{}%", value).into());
531 }
532 }
533
534 for value in where_and.members() {
535 db.where_and(
536 value[0].as_str().unwrap(),
537 value[1].as_str().unwrap(),
538 value[2].clone(),
539 );
540 }
541
542 let mut db_list = db.clone();
543
544 for item in order.members() {
545 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
546 }
547
548 let t = alls_field.join(",");
549 db_list.field(t.as_str());
550
551 if !table_field_json.is_empty() {
552 db_list.json(&table_field_json.join(","));
553 }
554
555 let mut data = db_list.select();
556
557 let mut table_datas = object! {};
558 let mut ids = HashMap::new();
559
560 for item in data.members_mut() {
561 for (field, _) in table_fields.entries() {
562 if table_datas[field].is_empty() {
563 table_datas[field] = array![];
564 }
565 let _ = table_datas[field].push(item[field].clone());
566 }
567 }
568 for (field, info) in table_fields.entries_mut() {
569 let _ = info["fields"].push("id");
570 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
571 let table_name = info["table"].clone();
572 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();
573
574 for item in data_list.members_mut() {
575 let id = item["id"].as_str().unwrap_or("").to_string();
576 item.remove("id");
577 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
578 ids.insert(
579 id.clone(),
580 object! {
581 value: id.clone(),
582 label:label.join(" | ").clone(),
583 },
584 );
585 }
586 }
587
588 for item in data.members_mut() {
589 for (field, _) in table_fields.entries() {
590 if item[field].is_empty() {
591 continue;
592 }
593 item[field] = ids[item[field].as_str().unwrap()].clone();
594 }
595 }
596
597 object! {
598 data:data,
599 columns:columns,
600 search_name:search_name.join("/"),
601 filter_columns:filter_columns,
602 label_field:label_field,
603 btn_all:array![],
604 btn_api:array![]
605 }
606 }
607 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
609 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
610 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
611 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
612 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
613 params
614 }
615 #[allow(clippy::too_many_arguments)]
616 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
617 fn table_tree(
618 &mut self,
619 request: JsonValue,
620 table_name: &str,
621 pid_field: &str,
622 label_field: &str,
623 fields: JsonValue,
624 hidd_field: Vec<&str>,
625 show_field: Vec<&str>,
626 search_fields: Vec<&str>,
627 _filter_fields: Vec<&str>,
628 ) -> JsonValue {
629 let search = request["search"].as_str().unwrap_or("");
630
631 let pid = request["pid"].clone();
632
633 let order = request["order"].clone();
634 let where_or = request["where_or"].clone();
635 let where_and = request["where_and"].clone();
636 let mut columns = array![];
637 let mut search_name = vec![];
638 let mut search_field = vec![];
639 let mut filter_columns = vec![];
640 let mut table_field_json = vec![];
641 let mut table_fields = object! {};
642
643 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
644 alls_field.retain(|x| !hidd_field.contains(x));
645 if !show_field.is_empty() {
646 alls_field.retain(|x| show_field.contains(x) || *x == "id");
647 }
648
649 for item in alls_field.iter() {
650 let row = fields[item.to_string()].clone();
651 let field = row["field"].to_string();
652 let title = row["title"].to_string();
653 let mode = row["mode"].to_string();
654
655 if search_fields.contains(&field.as_str()) {
656 search_name.push(title);
657 search_field.push(field.clone());
658 }
659 filter_columns.push(self.filter_column(row.clone()));
660 columns.push(self.table_column(row.clone())).unwrap();
661 let mut table_field_info = object! {};
662 match mode.as_str() {
663 "table" => table_field_info = row.clone(),
664 "array" => table_field_json.push(field.clone()),
665 _ => {}
666 }
667 if !table_field_info.is_empty() {
668 table_fields[field.as_str()] = table_field_info;
669 }
670 }
671
672 let mut tools = self.tools();
673 let db = tools.db.table(table_name);
674 db.where_and(pid_field, "=", pid);
675 if !search.is_empty() {
676 db.where_and(
677 &search_field.join("|"),
678 "like",
679 format!("%{}%", search).into(),
680 );
681 }
682
683 for (key, value) in where_or.entries() {
684 if value.is_empty() {
685 continue;
686 }
687 if value.is_array() {
688 db.where_or(key, "in", value.clone());
690 } else if value.is_boolean() {
691 db.where_or(key, "=", value.clone());
692 } else {
693 db.where_or(key, "like", format!("%{}%", value).into());
694 }
695 }
696
697 for value in where_and.members() {
698 db.where_and(
699 value[0].as_str().unwrap(),
700 value[1].as_str().unwrap(),
701 value[2].clone(),
702 );
703 }
704
705 let mut db_list = db.clone();
706
707 for item in order.members() {
708 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
709 }
710 let t = alls_field.join(",");
711 db_list.field(t.as_str());
712 if !table_field_json.is_empty() {
713 db_list.json(&table_field_json.join(","));
714 }
715 let mut data = db_list.select();
716
717 let mut table_datas = object! {};
718 let mut ids = HashMap::new();
719
720 for item in data.members_mut() {
721 for (field, _) in table_fields.entries() {
722 if table_datas[field].is_empty() {
723 table_datas[field] = array![];
724 }
725 let _ = table_datas[field].push(item[field].clone());
726 }
727 }
728 for (field, info) in table_fields.entries_mut() {
729 let _ = info["fields"].push("id");
730 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
731 let table_name = info["table"].clone();
732 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();
733
734 for item in data_list.members_mut() {
735 let id = item["id"].as_str().unwrap_or("").to_string();
736 item.remove("id");
737 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
738 ids.insert(
739 id.clone(),
740 object! {
741 value: id.clone(),
742 label:label.join(" | ").clone(),
743 },
744 );
745 }
746 }
747
748 let mut list = array![];
749 for item in data.members_mut() {
750 for (field, _) in table_fields.entries() {
751 if item[field].is_empty() {
752 continue;
753 }
754 item[field] = ids[item[field].as_str().unwrap()].clone();
755 }
756 let _ = list.push(object! {
757 id:item["id"].as_str().unwrap(),
758 label:item[label_field].as_str().unwrap(),
759 data:item.clone(),
760 });
761 }
762
763 object! {
764 data:list,
765 columns:columns,
766 search_name:search_name.join("/"),
767 filter_columns:filter_columns,
768 pid_field:pid_field,
769 btn_all:array![],
770 btn_api:array![]
771 }
772 }
773 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
775 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
776 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
777 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
778 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
779 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
780 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
781 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
782 params
783 }
784 #[allow(clippy::too_many_arguments)]
792 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
793 fn table_list(
794 &mut self,
795 request: JsonValue,
796 table_name: &str,
797 fields: JsonValue,
798 hidd_field: Vec<&str>,
799 show_field: Vec<&str>,
800 search_fields: Vec<&str>,
801 filter_fields: Vec<&str>,
802 ) -> JsonValue {
803 let page = request["page"].as_i32().unwrap_or(1);
804 let limit = request["limit"].as_i32().unwrap_or(10);
805 let search = request["search"].as_str().unwrap_or("");
806 let order = request["order"].clone();
807 let where_or = request["where_or"].clone();
808 let where_and = request["where_and"].clone();
809 let mut columns = array![];
810 let mut search_name = vec![];
811 let mut search_field = vec![];
812 let mut filter_columns = vec![];
813
814 let mut table_fields = object! {};
815
816 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
817 alls_field.retain(|x| !hidd_field.contains(x));
818 if !show_field.is_empty() {
819 alls_field.retain(|x| show_field.contains(x) || *x == "id");
820 }
821
822 for item in alls_field.iter() {
823 let key = item.to_string();
824 let field = fields[key.clone()]["field"].as_str().unwrap();
825 let title = fields[key.clone()]["title"].as_str().unwrap();
826 let mode = fields[key.clone()]["mode"].as_str().unwrap();
827
828 if search_fields.contains(&field) {
829 search_name.push(title);
830 search_field.push(field);
831 }
832 if filter_fields.contains(&field) {
833 filter_columns.push(self.filter_column(fields[key.clone()].clone()));
834 }
835 columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
836 let table_field_info = if mode == "table" {
837 fields[key.clone()].clone()
838 } else {
839 JsonValue::Null
840 };
841 if !table_field_info.is_empty() {
842 table_fields[field] = table_field_info;
843 }
844 }
845
846 let mut tools = self.tools();
847 let db = tools.db.table(table_name);
848
849 if !search.is_empty() {
850 db.where_and(
851 &search_field.join("|"),
852 "like",
853 format!("%{}%", search).into(),
854 );
855 }
856
857 for (key, value) in where_or.entries() {
858 if value.is_empty() {
859 continue;
860 }
861 if value.is_array() {
862 db.where_or(key, "in", value.clone());
864 } else if value.is_boolean() {
865 db.where_or(key, "=", value.clone());
866 } else {
867 db.where_or(key, "like", format!("%{}%", value).into());
868 }
869 }
870
871 for value in where_and.members() {
872 db.where_and(
873 value[0].as_str().unwrap(),
874 value[1].as_str().unwrap(),
875 value[2].clone(),
876 );
877 }
878
879 let total = db.clone().count().as_f64().unwrap();
880 let mut db_list = db.clone();
882
883 for item in order.members() {
884 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
885 }
886
887 let t = alls_field.join(",");
888 db_list.field(t.as_str());
889
890 let mut data = db_list.page(page, limit).select();
891
892 let mut table_datas = object! {};
893 let mut ids = HashMap::new();
894
895 for item in data.members_mut() {
896 if table_fields.is_empty() {
897 continue;
898 }
899 for (field, _) in table_fields.entries() {
900 if table_datas[field].is_empty() {
901 table_datas[field] = array![];
902 }
903 let _ = table_datas[field].push(item[field].clone());
904 }
905 }
906 for (field, info) in table_fields.entries_mut() {
907 let _ = info["fields"].push("id");
908 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
909 let table_name = info["table"].clone();
910 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();
911
912 for item in data_list.members_mut() {
913 let id = item["id"].as_str().unwrap_or("").to_string();
914 item.remove("id");
915 let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
916 ids.insert(
917 id.clone(),
918 object! {
919 value: id.clone(),
920 label:label.join(" | ").clone(),
921 },
922 );
923 }
924 }
925
926 for item in data.members_mut() {
927 if table_fields.is_empty() {
928 continue;
929 }
930 for (field, _) in table_fields.entries() {
931 if item[field].is_empty() {
932 continue;
933 }
934 let key = item[field].as_str().unwrap_or("");
935 if key.is_empty() {
936 continue;
937 }
938 if !ids.contains_key(key) {
939 continue;
940 }
941 item[field] = ids.get(key).unwrap().clone();
942 }
943 }
944
945 object! {
946 total:total,
947 data:data,
948 columns:columns,
949 search_name:search_name.join("/"),
950 filter_columns:filter_columns,
951 btn_all:array![],
952 btn_api:array![],
953 btn_ids:array![]
954 }
955 }
956 fn table_column(&mut self, field: JsonValue) -> JsonValue {
957 object! {
958 name:field["field"].clone(),
959 label:field["title"].clone(),
960 align:"center",
961 field:field["field"].clone(),
962 sortable:true,
963 mode:field["mode"].clone(),
964 dec:field["dec"].clone(),
965 fields:field["fields"].clone()
966 }
967 }
968 fn filter_column(&mut self, field: JsonValue) -> JsonValue {
969 object! {
970 name:field["field"].clone(),
971 label:field["title"].clone(),
972 mode:field["mode"].clone(),
973 option:field["option"].clone(),
974 api:field["api"].clone(),
975 fields:field["fields"].clone()
976 }
977 }
978 fn tools(&mut self) -> Tools {
980 let tools = PLUGIN_TOOLS.lock().unwrap();
981 let tools = tools.get("tools").unwrap().clone();
982 tools
983 }
984 fn config(&mut self, name: &str) -> JsonValue {
986 if CONFIG.lock().unwrap().get(name).is_none() {
987 object! {}
988 } else {
989 CONFIG.lock().unwrap().get(name).unwrap().clone()
990 }
991 }
992 fn btn(&mut self) -> Btn {
995 let mut btn = Btn::new(self.api().as_str());
996 btn.fields(self.params().clone());
997 btn.tags(self.tags());
998 btn.icon(self.icon());
999 btn.desc(self.description());
1000 btn.auth(self.auth());
1001 btn.public(self.public());
1002 btn.title(self.title());
1003 btn.btn_type(BtnType::Api);
1004 btn.btn_color(BtnColor::Primary);
1005 btn.path(self.api().clone().replace(".", "/").as_str());
1006 btn
1007 }
1008}
1009#[derive(Debug, Clone)]
1010pub struct Btn {
1011 api: String,
1012 title: String,
1013 desc: String,
1014 tags: &'static [&'static str],
1015 auth: bool,
1016 public: bool,
1017 btn_type: BtnType,
1018 color: BtnColor,
1019 icon: String,
1020 cnd: Vec<JsonValue>,
1021 url: String,
1022 path: String,
1023 fields: JsonValue,
1024}
1025impl Btn {
1026 pub fn new(api: &str) -> Self {
1027 Self {
1028 api: api.to_string(),
1029 title: "".to_string(),
1030 desc: "".to_string(),
1031 btn_type: BtnType::Api,
1032 color: BtnColor::Primary,
1033 icon: "".to_string(),
1034 auth: false,
1035 public: false,
1036 cnd: vec![],
1037 url: "".to_string(),
1038 path: "".to_string(),
1039 fields: object! {},
1040 tags: &[],
1041 }
1042 }
1043 pub fn path(&mut self, path: &str) -> &mut Self {
1044 self.path = path.to_string();
1045 self
1046 }
1047 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1048 self.cnd = cnd;
1049 self
1050 }
1051 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1052 self.btn_type = btn_type;
1053 self
1054 }
1055 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1056 self.color = btn_color;
1057 self
1058 }
1059 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1060 self.fields = fields;
1061 self
1062 }
1063 pub fn url(&mut self, url: &str) -> &mut Self {
1064 self.url = url.to_string();
1065 self
1066 }
1067 pub fn title(&mut self, title: &str) -> &mut Self {
1068 self.title = title.to_string();
1069 self
1070 }
1071 pub fn desc(&mut self, desc: &str) -> &mut Self {
1072 self.desc = desc.to_string();
1073 self
1074 }
1075 pub fn tags(&mut self, tags: &'static [&'static str]) -> &mut Self {
1076 self.tags = tags;
1077 self
1078 }
1079 pub fn public(&mut self, public: bool) -> &mut Self {
1080 self.public = public;
1081 self
1082 }
1083 pub fn auth(&mut self, auth: bool) -> &mut Self {
1084 self.auth = auth;
1085 self
1086 }
1087 pub fn icon(&mut self, icon: &str) -> &mut Self {
1088 self.icon = icon.to_string();
1089 self
1090 }
1091 pub fn json(&mut self) -> JsonValue {
1092 object! {
1093 api:self.api.clone(),
1094 title:self.title.clone(),
1095 desc:self.desc.clone(),
1096 auth:self.auth,
1097 public:self.public,
1098 btn_type:self.btn_type.clone().str(),
1099 color:self.color.clone().str(),
1100 icon:self.icon.clone(),
1101 cnd:self.cnd.clone(),
1102 url:self.url.clone(),
1103 path:self.path.clone(),
1104 fields:self.fields.clone(),
1105 tags:self.tags
1106 }
1107 }
1108}
1109
1110#[derive(Debug, Clone)]
1112pub enum InterfaceType {
1113 API,
1114 BTN,
1115 MENU,
1116}
1117
1118impl InterfaceType {
1119 pub fn str(self) -> &'static str {
1120 match self {
1121 InterfaceType::API => "api",
1122 InterfaceType::BTN => "btn",
1123 InterfaceType::MENU => "menu",
1124 }
1125 }
1126 pub fn types() -> Vec<&'static str> {
1127 vec!["api", "btn", "menu"]
1128 }
1129}
1130
1131#[derive(Debug, Clone)]
1133pub enum BtnType {
1134 Form,
1136 FormDownload,
1138 FormCustom,
1140 FormData,
1141 Url,
1143 Api,
1145 Download,
1147 Path,
1149 DialogCustom,
1151 FormApiDialogCustom,
1153 Preview,
1155}
1156
1157impl BtnType {
1158 fn str(self) -> &'static str {
1159 match self {
1160 BtnType::Form => "form",
1161 BtnType::FormDownload => "form_download",
1162 BtnType::FormCustom => "form_custom",
1163 BtnType::FormData => "form_data",
1164 BtnType::Api => "api",
1165 BtnType::Download => "download",
1166 BtnType::Url => "url",
1167 BtnType::Path => "path",
1168 BtnType::DialogCustom => "dialog_custom",
1169 BtnType::FormApiDialogCustom => "form_api_dialog_custom",
1170 BtnType::Preview => "preview",
1171 }
1172 }
1173}
1174#[derive(Debug, Clone)]
1176pub enum BtnColor {
1177 Primary,
1178 Red,
1179 Blue,
1180 Yellow,
1181 Green,
1182}
1183
1184impl BtnColor {
1185 fn str(self) -> &'static str {
1186 match self {
1187 BtnColor::Primary => "primary",
1188 BtnColor::Red => "negative",
1189 BtnColor::Blue => "info",
1190 BtnColor::Yellow => "warning",
1191 BtnColor::Green => "positive",
1192 }
1193 }
1194}