1use crate::request::{ContentType, Method, Request};
2use crate::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" => {
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 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
454 fn table_menu(
455 &mut self,
456 request: JsonValue,
457 table_name: &str,
458 label_field: &str,
459 fields: JsonValue,
460
461 hidd_field: Vec<&str>,
462 show_field: Vec<&str>,
463
464 search_fields: Vec<&str>,
465 _filter_fields: Vec<&str>,
466 ) -> JsonValue {
467 let search = request["search"].as_str().unwrap_or("");
468
469 let order = request["order"].clone();
470 let where_or = request["where_or"].clone();
471 let where_and = request["where_and"].clone();
472 let mut columns = array![];
473 let mut search_name = vec![];
474 let mut search_field = vec![];
475 let mut filter_columns = vec![];
476 let mut table_fields = object! {};
477 let mut table_field_json = vec![];
478
479 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
480 alls_field.retain(|x| !hidd_field.contains(x));
481 if !show_field.is_empty() {
482 alls_field.retain(|x| show_field.contains(x) || *x == "id");
483 }
484
485 for item in alls_field.iter() {
486 let row = &fields[item.to_string()];
487 let field = row["field"].to_string();
488 let title = row["title"].to_string();
489 let mode = row["mode"].to_string();
490
491 if search_fields.contains(&field.as_str()) {
492 search_name.push(title);
493 search_field.push(field.clone());
494 }
495 filter_columns.push(self.filter_column(row.clone()));
496 columns.push(self.table_column(row.clone())).unwrap();
497 let mut table_field_info = object! {};
498 match mode.as_str() {
499 "table" => table_field_info = row.clone(),
500 "array" => table_field_json.push(field.clone()),
501 _ => {}
502 }
503 if !table_field_info.is_empty() {
504 table_fields[field.as_str()] = table_field_info;
505 }
506 }
507
508 let mut tools = self.tools();
509 let db = tools.db.table(table_name);
510
511 if !search.is_empty() {
512 db.where_and(
513 &search_field.join("|"),
514 "like",
515 format!("%{}%", search).into(),
516 );
517 }
518
519 for (key, value) in where_or.entries() {
520 if value.is_empty() {
521 continue;
522 }
523 if value.is_array() {
524 db.where_or(key, "between", value.clone());
525 db.where_or(key, "in", value.clone());
526 } else if value.is_boolean() {
527 db.where_or(key, "=", value.clone());
528 } else {
529 db.where_or(key, "like", format!("%{}%", value).into());
530 }
531 }
532
533 for value in where_and.members() {
534 db.where_and(
535 value[0].as_str().unwrap(),
536 value[1].as_str().unwrap(),
537 value[2].clone(),
538 );
539 }
540
541 let mut db_list = db.clone();
542
543 for item in order.members() {
544 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
545 }
546
547 let t = alls_field.join(",");
548 db_list.field(t.as_str());
549
550 if !table_field_json.is_empty() {
551 db_list.json(&table_field_json.join(","));
552 }
553
554 let mut data = db_list.select();
555
556 let mut table_datas = object! {};
557 let mut ids = HashMap::new();
558
559 for item in data.members_mut() {
560 for (field, _) in table_fields.entries() {
561 if table_datas[field].is_empty() {
562 table_datas[field] = array![];
563 }
564 let _ = table_datas[field].push(item[field].clone());
565 }
566 }
567 for (field, info) in table_fields.entries_mut() {
568 let _ = info["fields"].push("id");
569 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
570 let table_name = info["table"].clone();
571 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();
572
573 for item in data_list.members_mut() {
574 let id = item["id"].as_str().unwrap_or("").to_string();
575 item.remove("id");
576 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
577 ids.insert(
578 id.clone(),
579 object! {
580 value: id.clone(),
581 label:label.join(" | ").clone(),
582 },
583 );
584 }
585 }
586
587 for item in data.members_mut() {
588 for (field, _) in table_fields.entries() {
589 if item[field].is_empty() {
590 continue;
591 }
592 item[field] = ids[item[field].as_str().unwrap()].clone();
593 }
594 }
595
596 object! {
597 data:data,
598 columns:columns,
599 search_name:search_name.join("/"),
600 filter_columns:filter_columns,
601 label_field:label_field,
602 btn_all:array![],
603 btn_api:array![]
604 }
605 }
606 fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
608 params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "").example("".into()).field();
609 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
610 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
611 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
612 params
613 }
614 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
615 fn table_tree(
616 &mut self,
617 request: JsonValue,
618 table_name: &str,
619 pid_field: &str,
620 label_field: &str,
621 fields: JsonValue,
622 hidd_field: Vec<&str>,
623 show_field: Vec<&str>,
624 search_fields: Vec<&str>,
625 _filter_fields: Vec<&str>,
626 ) -> JsonValue {
627 let search = request["search"].as_str().unwrap_or("");
628
629 let pid = request["pid"].clone();
630
631 let order = request["order"].clone();
632 let where_or = request["where_or"].clone();
633 let where_and = request["where_and"].clone();
634 let mut columns = array![];
635 let mut search_name = vec![];
636 let mut search_field = vec![];
637 let mut filter_columns = vec![];
638 let mut table_field_json = vec![];
639 let mut table_fields = object! {};
640
641 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
642 alls_field.retain(|x| !hidd_field.contains(x));
643 if !show_field.is_empty() {
644 alls_field.retain(|x| show_field.contains(x) || *x == "id");
645 }
646
647 for item in alls_field.iter() {
648 let row = fields[item.to_string()].clone();
649 let field = row["field"].to_string();
650 let title = row["title"].to_string();
651 let mode = row["mode"].to_string();
652
653 if search_fields.contains(&field.as_str()) {
654 search_name.push(title);
655 search_field.push(field.clone());
656 }
657 filter_columns.push(self.filter_column(row.clone()));
658 columns.push(self.table_column(row.clone())).unwrap();
659 let mut table_field_info = object! {};
660 match mode.as_str() {
661 "table" => table_field_info = row.clone(),
662 "array" => table_field_json.push(field.clone()),
663 _ => {}
664 }
665 if !table_field_info.is_empty() {
666 table_fields[field.as_str()] = table_field_info;
667 }
668 }
669
670 let mut tools = self.tools();
671 let db = tools.db.table(table_name);
672 db.where_and(pid_field, "=", pid);
673 if !search.is_empty() {
674 db.where_and(
675 &search_field.join("|"),
676 "like",
677 format!("%{}%", search).into(),
678 );
679 }
680
681 for (key, value) in where_or.entries() {
682 if value.is_empty() {
683 continue;
684 }
685 if value.is_array() {
686 db.where_or(key, "in", value.clone());
688 } else if value.is_boolean() {
689 db.where_or(key, "=", value.clone());
690 } else {
691 db.where_or(key, "like", format!("%{}%", value).into());
692 }
693 }
694
695 for value in where_and.members() {
696 db.where_and(
697 value[0].as_str().unwrap(),
698 value[1].as_str().unwrap(),
699 value[2].clone(),
700 );
701 }
702
703 let mut db_list = db.clone();
704
705 for item in order.members() {
706 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
707 }
708 let t = alls_field.join(",");
709 db_list.field(t.as_str());
710 if !table_field_json.is_empty() {
711 db_list.json(&table_field_json.join(","));
712 }
713 let mut data = db_list.select();
714
715 let mut table_datas = object! {};
716 let mut ids = HashMap::new();
717
718 for item in data.members_mut() {
719 for (field, _) in table_fields.entries() {
720 if table_datas[field].is_empty() {
721 table_datas[field] = array![];
722 }
723 let _ = table_datas[field].push(item[field].clone());
724 }
725 }
726 for (field, info) in table_fields.entries_mut() {
727 let _ = info["fields"].push("id");
728 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
729 let table_name = info["table"].clone();
730 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();
731
732 for item in data_list.members_mut() {
733 let id = item["id"].as_str().unwrap_or("").to_string();
734 item.remove("id");
735 let label = item.entries().map(|(_, v)| v.as_str().unwrap()).collect::<Vec<&str>>();
736 ids.insert(
737 id.clone(),
738 object! {
739 value: id.clone(),
740 label:label.join(" | ").clone(),
741 },
742 );
743 }
744 }
745
746 let mut list = array![];
747 for item in data.members_mut() {
748 for (field, _) in table_fields.entries() {
749 if item[field].is_empty() {
750 continue;
751 }
752 item[field] = ids[item[field].as_str().unwrap()].clone();
753 }
754 let _ = list.push(object! {
755 id:item["id"].as_str().unwrap(),
756 label:item[label_field].as_str().unwrap(),
757 data:item.clone(),
758 });
759 }
760
761 object! {
762 data:list,
763 columns:columns,
764 search_name:search_name.join("/"),
765 filter_columns:filter_columns,
766 pid_field:pid_field,
767 btn_all:array![],
768 btn_api:array![]
769 }
770 }
771 fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
773 params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1).example(1.into()).field();
774 params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10).example(10.into()).field();
775 params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "").example("".into()).field();
776 params["order"] = br_fields::text::Array::new(false, "order", "排序", array![]).example(array![array!["id", false]]).field();
777 params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![]).example(array![]).field();
778 params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![]).example(array![]).field();
779 params["field"] = br_fields::str::Str::new(false, "field", "显示字段", 20, "id").example("id".into()).field();
780 params
781 }
782 #[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
790 fn table_list(
791 &mut self,
792 request: JsonValue,
793 table_name: &str,
794 fields: JsonValue,
795 hidd_field: Vec<&str>,
796 show_field: Vec<&str>,
797 search_fields: Vec<&str>,
798 filter_fields: Vec<&str>,
799 ) -> JsonValue {
800 let page = request["page"].as_i32().unwrap_or(1);
801 let limit = request["limit"].as_i32().unwrap_or(10);
802 let search = request["search"].as_str().unwrap_or("");
803 let order = request["order"].clone();
804 let where_or = request["where_or"].clone();
805 let where_and = request["where_and"].clone();
806 let mut columns = array![];
807 let mut search_name = vec![];
808 let mut search_field = vec![];
809 let mut filter_columns = vec![];
810
811 let mut table_fields = object! {};
812
813 let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
814 alls_field.retain(|x| !hidd_field.contains(x));
815 if !show_field.is_empty() {
816 alls_field.retain(|x| show_field.contains(x) || *x == "id");
817 }
818
819 for item in alls_field.iter() {
820 let key = item.to_string();
821 let field = fields[key.clone()]["field"].as_str().unwrap();
822 let title = fields[key.clone()]["title"].as_str().unwrap();
823 let mode = fields[key.clone()]["mode"].as_str().unwrap();
824
825 if search_fields.contains(&field) {
826 search_name.push(title);
827 search_field.push(field);
828 }
829 if filter_fields.contains(&field) {
830 filter_columns.push(self.filter_column(fields[key.clone()].clone()));
831 }
832 columns.push(self.table_column(fields[key.clone()].clone())).unwrap();
833 let table_field_info = if mode == "table" {
834 fields[key.clone()].clone()
835 } else {
836 JsonValue::Null
837 };
838 if !table_field_info.is_empty() {
839 table_fields[field] = table_field_info;
840 }
841 }
842
843 let mut tools = self.tools();
844 let db = tools.db.table(table_name);
845
846 if !search.is_empty() {
847 db.where_and(
848 &search_field.join("|"),
849 "like",
850 format!("%{}%", search).into(),
851 );
852 }
853
854 for (key, value) in where_or.entries() {
855 if value.is_empty() {
856 continue;
857 }
858 if value.is_array() {
859 db.where_or(key, "in", value.clone());
861 } else if value.is_boolean() {
862 db.where_or(key, "=", value.clone());
863 } else {
864 db.where_or(key, "like", format!("%{}%", value).into());
865 }
866 }
867
868 for value in where_and.members() {
869 db.where_and(
870 value[0].as_str().unwrap(),
871 value[1].as_str().unwrap(),
872 value[2].clone(),
873 );
874 }
875
876 let total = db.clone().count().as_f64().unwrap();
877 let mut db_list = db.clone();
879
880 for item in order.members() {
881 db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
882 }
883
884 let t = alls_field.join(",");
885 db_list.field(t.as_str());
886
887 let mut data = db_list.page(page, limit).select();
888
889 let mut table_datas = object! {};
890 let mut ids = HashMap::new();
891
892 for item in data.members_mut() {
893 if table_fields.is_empty() {
894 continue;
895 }
896 for (field, _) in table_fields.entries() {
897 if table_datas[field].is_empty() {
898 table_datas[field] = array![];
899 }
900 let _ = table_datas[field].push(item[field].clone());
901 }
902 }
903 for (field, info) in table_fields.entries_mut() {
904 let _ = info["fields"].push("id");
905 let fields_k = info["fields"].members().map(|x| x.as_str().unwrap()).collect::<Vec<&str>>();
906 let table_name = info["table"].clone();
907 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();
908
909 for item in data_list.members_mut() {
910 let id = item["id"].as_str().unwrap_or("").to_string();
911 item.remove("id");
912 let label = item.entries().map(|(_, v)| v.to_string()).collect::<Vec<String>>();
913 ids.insert(
914 id.clone(),
915 object! {
916 value: id.clone(),
917 label:label.join(" | ").clone(),
918 },
919 );
920 }
921 }
922
923 for item in data.members_mut() {
924 if table_fields.is_empty() {
925 continue;
926 }
927 for (field, _) in table_fields.entries() {
928 if item[field].is_empty() {
929 continue;
930 }
931 let key = item[field].as_str().unwrap_or("");
932 if key.is_empty() {
933 continue;
934 }
935 if !ids.contains_key(key) {
936 continue;
937 }
938 item[field] = ids.get(key).unwrap().clone();
939 }
940 }
941
942 object! {
943 total:total,
944 data:data,
945 columns:columns,
946 search_name:search_name.join("/"),
947 filter_columns:filter_columns,
948 btn_all:array![],
949 btn_api:array![],
950 btn_ids:array![]
951 }
952 }
953 fn table_column(&mut self, field: JsonValue) -> JsonValue {
954 object! {
955 name:field["field"].clone(),
956 label:field["title"].clone(),
957 align:"center",
958 field:field["field"].clone(),
959 sortable:true,
960 mode:field["mode"].clone(),
961 dec:field["dec"].clone(),
962 fields:field["fields"].clone()
963 }
964 }
965 fn filter_column(&mut self, field: JsonValue) -> JsonValue {
966 object! {
967 name:field["field"].clone(),
968 label:field["title"].clone(),
969 mode:field["mode"].clone(),
970 option:field["option"].clone(),
971 api:field["api"].clone(),
972 fields:field["fields"].clone()
973 }
974 }
975 fn tools(&mut self) -> Tools {
977 let tools = PLUGIN_TOOLS.lock().unwrap();
978 let tools = tools.get("tools").unwrap().clone();
979 tools
980 }
981 fn btn(&mut self) -> Btn {
984 let mut btn = Btn::new(self.api().as_str());
985 btn.fields(self.params().clone());
986 btn.icon(self.icon());
987 btn.desc(self.description());
988 btn.auth(self.auth());
989 btn.public(self.public());
990 btn.title(self.title());
991 btn.btn_type(BtnType::Api);
992 btn.btn_color(BtnColor::Primary);
993 btn.path(self.api().clone().replace(".", "/").as_str());
994 btn
995 }
996}
997#[derive(Debug, Clone)]
998pub struct Btn {
999 api: String,
1000 title: String,
1001 desc: String,
1002 auth: bool,
1003 public: bool,
1004 btn_type: BtnType,
1005 color: BtnColor,
1006 icon: String,
1007 cnd: Vec<JsonValue>,
1008 url: String,
1009 path: String,
1010 fields: JsonValue,
1011}
1012impl Btn {
1013 pub fn new(api: &str) -> Self {
1014 Self {
1015 api: api.to_string(),
1016 title: "".to_string(),
1017 desc: "".to_string(),
1018 btn_type: BtnType::Api,
1019 color: BtnColor::Primary,
1020 icon: "".to_string(),
1021 auth: false,
1022 public: false,
1023 cnd: vec![],
1024 url: "".to_string(),
1025 path: "".to_string(),
1026 fields: object! {},
1027 }
1028 }
1029 pub fn path(&mut self, path: &str) -> &mut Self {
1030 self.path = path.to_string();
1031 self
1032 }
1033 pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
1034 self.cnd = cnd;
1035 self
1036 }
1037 pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
1038 self.btn_type = btn_type;
1039 self
1040 }
1041 pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
1042 self.color = btn_color;
1043 self
1044 }
1045 pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
1046 self.fields = fields;
1047 self
1048 }
1049 pub fn url(&mut self, url: &str) -> &mut Self {
1050 self.url = url.to_string();
1051 self
1052 }
1053 pub fn title(&mut self, title: &str) -> &mut Self {
1054 self.title = title.to_string();
1055 self
1056 }
1057 pub fn desc(&mut self, desc: &str) -> &mut Self {
1058 self.desc = desc.to_string();
1059 self
1060 }
1061 pub fn public(&mut self, public: bool) -> &mut Self {
1062 self.public = public;
1063 self
1064 }
1065 pub fn auth(&mut self, auth: bool) -> &mut Self {
1066 self.auth = auth;
1067 self
1068 }
1069 pub fn icon(&mut self, icon: &str) -> &mut Self {
1070 self.icon = icon.to_string();
1071 self
1072 }
1073 pub fn json(&mut self) -> JsonValue {
1074 object! {
1075 api:self.api.clone(),
1076 title:self.title.clone(),
1077 desc:self.desc.clone(),
1078 auth:self.auth,
1079 public:self.public,
1080 btn_type:self.btn_type.clone().str(),
1081 color:self.color.clone().str(),
1082 icon:self.icon.clone(),
1083 cnd:self.cnd.clone(),
1084 url:self.url.clone(),
1085 path:self.path.clone(),
1086 fields:self.fields.clone()
1087 }
1088 }
1089}
1090
1091#[derive(Debug, Clone)]
1093pub enum InterfaceType {
1094 API,
1095 BTN,
1096 MENU,
1097}
1098
1099impl InterfaceType {
1100 pub fn str(self) -> &'static str {
1101 match self {
1102 InterfaceType::API => "api",
1103 InterfaceType::BTN => "btn",
1104 InterfaceType::MENU => "menu",
1105 }
1106 }
1107 pub fn types() -> Vec<&'static str> {
1108 vec!["api", "btn", "menu"]
1109 }
1110}
1111
1112#[derive(Debug, Clone)]
1114pub enum BtnType {
1115 Form,
1117 FormDownload,
1119 FormCustom,
1121 FormData,
1122 Url,
1124 Api,
1126 Download,
1128 Path,
1130 DialogCustom,
1132}
1133
1134impl BtnType {
1135 fn str(self) -> &'static str {
1136 match self {
1137 BtnType::Form => "form",
1138 BtnType::FormDownload => "form_download",
1139 BtnType::FormCustom => "form_custom",
1140 BtnType::FormData => "form_data",
1141 BtnType::Api => "api",
1142 BtnType::Download => "download",
1143 BtnType::Url => "url",
1144 BtnType::Path => "path",
1145 BtnType::DialogCustom => "dialog_custom",
1146 }
1147 }
1148}
1149#[derive(Debug, Clone)]
1151pub enum BtnColor {
1152 Primary,
1153 Red,
1154 Blue,
1155 Yellow,
1156 Green,
1157}
1158
1159impl BtnColor {
1160 fn str(self) -> &'static str {
1161 match self {
1162 BtnColor::Primary => "primary",
1163 BtnColor::Red => "negative",
1164 BtnColor::Blue => "info",
1165 BtnColor::Yellow => "warning",
1166 BtnColor::Green => "positive",
1167 }
1168 }
1169}