1use std::{env, fs};
2use std::fs::{create_dir_all, File};
3use std::io::Write;
4use std::path::{Path, PathBuf};
5use df_cache::Cache;
6use df_db::{Db, Mode, Table};
7use df_fields::Field;
8use df_kafka::Kafka;
9use json::{array, JsonValue, object};
10
11pub mod test;
12
13use lazy_static::lazy_static;
14use std::sync::Mutex;
15use std::collections::HashMap;
16use df_email::smtp::Smtp;
17use crate::test::Test;
18use crate::test::test::table::TestTestTable;
19use crate::test::test::TestTest;
20lazy_static! {
21 pub static ref TOOLS: Mutex<HashMap<String,Tools>> =Mutex::new(HashMap::new());
23}
24
25pub fn plugins(name: &str) -> Box<dyn Plugin> {
27 match name {
28 _ => Box::new(Test {})
29 }
30}
31
32pub fn models(name: &str) -> Box<dyn Model> {
34 match name {
35 _ => Box::new(TestTest {})
36 }
37}
38
39pub fn actions(name: &str) -> Box<dyn Action> {
41 match name {
42 _ => Box::new(TestTestTable { model: TestTest {} })
43 }
44}
45
46pub fn plugin_create(path: &str, plugin: &str, plugin_title: &str, model: &str, model_title: &str, action: &str, action_title: &str) {
48 let root_path = PathBuf::from(path);
49 let plugin_path = root_path.join("plugin");
50 let plugin_path = plugin_path.join(plugin);
51 create_dir_all(plugin_path.as_os_str()).expect("创建目录失败");
52
53 let plugin_mod_path = plugin_path.join("mod.rs");
54 if !plugin_mod_path.is_file() {
55 let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
56 let temp_plugin_mod_path = temp_plugin_mod_path.join("temp").join("plugin");
57 let temp_plugin_mod_data = fs::read_to_string(temp_plugin_mod_path).unwrap();
58 let plugin_1 = plugin[0..=0].to_uppercase();
59 let plugin_2 = plugin[1..].to_lowercase();
60 let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{plugin}}", &*format!("{}{}", plugin_1, plugin_2));
61 let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{title}}", plugin_title);
62 fs::write(plugin_mod_path, temp_plugin_mod_data).expect("写入插件mod错误");
63 }
64
65 if model != "" {
66 let model_path = plugin_path.join(model);
67 create_dir_all(model_path.as_os_str()).expect("创建模型目录失败");
68
69
70 let plugin_d = {
71 let t: Vec<String> = plugin.split("_").map(|x| {
72 let x1 = x[0..=0].to_uppercase();
73 let x2 = x[1..].to_lowercase();
74 format!("{}{}", x1.clone(), x2.clone())
75 }).collect();
76 t.join("")
77 };
78 let model_d = {
79 let t: Vec<String> = model.split("_").map(|x| {
80 let x1 = x[0..=0].to_uppercase();
81 let x2 = x[1..].to_lowercase();
82 format!("{}{}", x1.clone(), x2.clone())
83 }).collect();
84 t.join("")
85 };
86
87 let model_mod_path = model_path.join("mod.rs");
88 if !model_mod_path.is_file() {
89 let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
90 let temp_model_mod_path = temp_plugin_mod_path.join("temp").join("model");
91 let mut temp_model_mod_data = fs::read_to_string(temp_model_mod_path).unwrap();
92 temp_model_mod_data = temp_model_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
93 temp_model_mod_data = temp_model_mod_data.replace("{{plugin_model}}", &*format!("{}_{}", plugin, model));
94 let temp_model_mod_data = temp_model_mod_data.replace("{{title}}", model_title);
95 fs::write(model_mod_path, temp_model_mod_data).expect("写入模型mod错误");
96 }
97
98 if action != "" {
99 let action_path = model_path.join(format!("{}.rs", action));
100 if !action_path.is_file() {
101 let temp_action_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
102 let temp_action_mod_path = {
103 match action {
104 "table" => {
105 temp_action_mod_path.join("temp").join("action_table")
106 }
107 "add" => {
108 temp_action_mod_path.join("temp").join("action_add")
109 }
110 "delete" => {
111 temp_action_mod_path.join("temp").join("action_delete")
112 }
113 "put" => {
114 temp_action_mod_path.join("temp").join("action_put")
115 }
116 "select" => {
117 temp_action_mod_path.join("temp").join("action_select")
118 }
119 "get" => {
120 temp_action_mod_path.join("temp").join("action_get")
121 }
122 _ => {
123 temp_action_mod_path.join("temp").join("action")
124 }
125 }
126 };
127
128 let temp_action_mod_data = fs::read_to_string(temp_action_mod_path).unwrap();
129
130
131 let action_d = {
132 let t: Vec<String> = action.split("_").map(|x| {
133 let x1 = x[0..=0].to_uppercase();
134 let x2 = x[1..].to_lowercase();
135 format!("{}{}", x1.clone(), x2.clone())
136 }).collect();
137 t.join("")
138 };
139
140 let temp_action_mod_data = temp_action_mod_data.replace("{{action}}", &*format!("{}{}{}", plugin_d, model_d, action_d));
141 let temp_action_mod_data = temp_action_mod_data.replace("{{api}}", &*format!("{}.{}.{}", plugin, model, action));
142 let temp_action_mod_data = temp_action_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
143 let temp_action_mod_data = temp_action_mod_data.replace("{{model_a}}", &*format!("{}", model));
144 let temp_action_mod_data = temp_action_mod_data.replace("{{plugin}}", &*format!("{}", plugin));
145 let temp_action_mod_data = temp_action_mod_data.replace("{{title}}", action_title);
146 fs::write(action_path, temp_action_mod_data).expect("写入动作文件错误");
147 }
148 }
149 }
150}
151
152
153pub trait Plugin {
155 fn model(&mut self, name: &str) -> Box<dyn Model>;
156 fn title(&mut self) -> &'static str;
158 fn describe(&mut self) -> &'static str { return ""; }
160}
161
162pub trait Model {
164 fn version(&mut self) -> &'static str {
166 "0.0.1"
167 }
168 fn table(&mut self) -> &'static str;
170 fn title(&mut self) -> &'static str;
172 fn describe(&mut self) -> &'static str { return ""; }
174 fn fields(&mut self) -> JsonValue;
176
177 fn unique(&mut self) -> Vec<&'static str> {
179 return vec![];
180 }
181 fn index(&mut self) -> Vec<Vec<&'static str>> {
183 return vec![];
184 }
185 fn primary_key(&mut self) -> &'static str {
187 return "id";
188 }
189 fn auto(&mut self) -> bool {
191 return false;
192 }
193 fn json(&mut self) -> Table {
195 Table {
196 version: self.version().parse().unwrap(),
197 table: self.table().parse().unwrap(),
198 title: self.title().parse().unwrap(),
199 primary_key: self.primary_key().parse().unwrap(),
200 auto: self.auto(),
201 unique: self.unique().iter().map(|x| x.to_string()).collect(),
202 index: self.index().iter().map(|x| x.iter().map(|y| y.to_string()).collect()).collect(),
203 fields: self.fields(),
204 }
205 }
206 fn create_json_file(&mut self, path: &str) -> bool {
208 let json = self.json();
209 let o = Path::new(path);
210 if !o.is_dir() {
211 fs::create_dir(path).unwrap();
212 }
213 env::set_current_dir(path).unwrap();
214 let dir = env::current_dir().unwrap();
215 let version = self.version();
216 let version = version.replace(".", "_");
217 let dir = dir.join(format!("{}_{}.json", self.table(), version));
218 let mut f = File::create(dir.to_str().unwrap()).unwrap();
219 match f.write_all(json.to_string().as_bytes()) {
220 Ok(_) => true,
221 Err(_) => false
222 }
223 }
224 fn action(&mut self, name: &str) -> Box<dyn Action>;
226 fn table_fields(&mut self) -> JsonValue {
228 let mut params = object! {};
229 params["load"] = df_fields::select::Radio::new(false, "load", "加载内容", vec!["col", "data"], "data").field();
230 params["page"] = df_fields::int::Int::new(false, "page", "页数", 15, 1).field();
231 params["limit"] = df_fields::int::Int::new(false, "limit", "记录数", 10, 25).field();
232 params["where"] = df_fields::text::Json::new(false, "where", "条件", object! {}).field();
233 params["filter"] = df_fields::text::Text::new(false, "filter", "模糊搜索", "").field();
234 params["order"] = df_fields::text::Json::new(false, "order", "排序", array![]).field();
235 return params;
236 }
237
238 fn tools(&mut self) -> Tools {
239 let db = TOOLS.lock().unwrap();
240 let db = db.get("tools").unwrap().clone();
241 db
242 }
243 fn tables(&mut self, header: JsonValue, request: JsonValue, fields: Vec<&str>, query_fields: Vec<&str>, filter_fields: Vec<&str>) -> JsonValue {
245 let load = request["load"].as_str().unwrap();
246 let page = request["page"].as_i32().unwrap();
247 let limit = request["limit"].as_i32().unwrap();
248 let wheres = request["where"].clone();
249 let filter = request["filter"].to_string();
250 let order = request["order"].clone();
251 let columns = self.columns(fields.clone());
252 let mut data = {
254 let mut db = self.tools().db;
255 let db = db.table(self.table());
256 if filter_fields.len() > 0 && filter != "" {
258 db.where_or(filter_fields.join("|").as_str(), "like", format!("%{}%", filter).into());
259 }
260 if fields.len() > 0 {
261 db.field(fields.join(",").as_str().clone());
262 }
263 for item in wheres.members() {
264 db.where_and(item[0].as_str().unwrap(), item[1].as_str().unwrap(), item[2].clone());
265 }
266 if order.len() > 0 {
267 db.order(order[0].as_str().unwrap(), order[1].as_bool().unwrap());
268 }
269 db.page(page.clone(), limit.clone()).select()
270 };
271
272 let total = {
274 let mut db = self.tools().db;
275 let db = db.table(self.table());
276 if filter_fields.len() > 0 && filter != "" {
277 db.where_or(filter_fields.join("|").as_str(), "like", format!("%{}%", filter).into());
278 }
279 for item in wheres.members() {
280 db.where_and(item[0].as_str().unwrap(), item[1].as_str().unwrap(), item[2].clone());
281 }
282 db.count().as_i32().unwrap()
283 };
284
285
286 let mut fields_table = false;
287 let mut fields_list = object! {};
288 for field in columns.members() {
289 fields_list[field["field"].as_str().unwrap()] = field.clone();
290 match field["mode"].as_str().unwrap() {
291 "table" | "file" => {
292 fields_table = true;
293 }
294 _ => {}
295 }
296 }
297 if fields_table {
298 let mut fields_table_ids = object! {};
299 for item in data.members_mut() {
300 for (key, field) in fields_list.entries() {
301 match field["mode"].as_str().unwrap() {
302 "table" => {
303 let id = item[key].clone();
304 if id.is_empty() {
305 continue;
306 }
307 if fields_table_ids[id.as_str().unwrap()].is_null() {
308 let table = field["table"].as_str().unwrap();
309 let field: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
310 let find = self.tools().db.table(table)
311 .where_and("id", "=", id.clone())
312 .field(format!("id,{}", field.join(",")).as_str().clone())
313 .find();
314 let mut row = object! {};
315 if !find.is_empty() {
316 row["id"] = find["id"].clone();
317 for field in field.iter() {
318 if row["value"].is_null() {
319 row["value"] = format!("{}", find[field.clone()]).into();
320 } else {
321 row["value"] = format!("{} | {}", row["value"], find[field.clone()]).into();
322 }
323 }
324 fields_table_ids[id.as_str().unwrap()] = row;
325 } else {
326 fields_table_ids[id.as_str().unwrap()] = object! {};
327 }
328 }
329 item[key] = fields_table_ids[id.as_str().unwrap()].clone();
330 }
331 "file" => {
332 let id = item[key].clone();
333 if id.is_empty() {
334 item[key] = array![];
335 continue;
336 }
337 let mut files = self.tools().db.table("file_file")
338 .where_and("id", "in", id.clone())
339 .select();
340
341 let domain = header["domain"].clone();
342 for file in files.members_mut() {
343 file["url"] = format!("{}/file/{}/{}.{}", domain.clone(), file["mode"], file["id"], file["mode"]).into();
344 }
345 item[key] = files;
346 }
347 _ => {}
348 }
349 }
350 }
351 }
352
353 let mut table = object! {};
354 table["total_page"] = JsonValue::from((total as f64 / limit as f64).ceil() as i64);
355 table["total_data"] = total.into();
356 table["data"] = data.clone();
357 match load {
358 "col" => {
359 table["col"] = columns.clone();
360 table["query_fields"] = self.query_fields(query_fields.clone());
361 table["filter_title"] = self.filter_title(filter_fields.clone()).into();
362 }
363 _ => {}
364 }
365 table
366 }
367
368 fn columns(&mut self, fields: Vec<&str>) -> JsonValue {
370 let columns = self.fields();
371 let mut data = array![];
372 for (key, field) in columns.entries() {
373 if fields.contains(&key) || fields.len() == 0 {
374 let mut row = field.clone();
375 row["name"] = field["field"].clone();
376 row["label"] = field["title"].clone();
377 row["align"] = "center".into();
378 row["sortable"] = match field["mode"].as_str().unwrap() {
379 "int" | "float" => {
380 true.into()
381 }
382 _ => {
383 false.into()
384 }
385 };
386 data.push(row.clone()).unwrap();
387 }
388 }
389 data
390 }
391 fn query_fields(&mut self, fields: Vec<&str>) -> JsonValue {
393 let columns = self.fields();
394 let mut data = array![];
395 for (key, field) in columns.entries() {
396 if fields.contains(&key) {
397 let mut row = field.clone();
398 row["require"] = JsonValue::from(false);
399 data.push(row.clone()).unwrap();
400 }
401 }
402 data
403 }
404 fn filter_title(&mut self, fields: Vec<&str>) -> String {
406 let columns = self.fields();
407 let mut data = vec![];
408 for (key, field) in columns.entries() {
409 if fields.contains(&key) {
410 data.push(field["title"].as_str().unwrap());
411 }
412 }
413 format!("搜索 {}", data.join(" "))
414 }
415
416 fn btn_data(&mut self, title: &str, mut action: Box<dyn Action>, mode: BtnMode, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
418 let mut btn = object! {};
419 if title.is_empty() {
420 btn["title"] = action.title().into();
421 } else {
422 btn["title"] = title.into();
423 }
424 btn["api"] = action.name().into();
425 let mut params = array![];
426 for (_, item) in action.params().entries() {
427 params.push(item.clone()).unwrap();
428 }
429 btn["params"] = JsonValue::from(params);
430 btn["color"] = JsonValue::from(color.from());
431 btn["mode"] = JsonValue::from(mode.from());
432 btn["match_condition"] = match_condition.into();
433 return btn;
434 }
435
436
437 fn btn_path_data(&mut self, title: &str, path: &str, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
439 let mut btn = object! {};
440 btn["title"] = title.into();
441 btn["path"] = JsonValue::from(path);
442 btn["color"] = JsonValue::from(color.from());
443 btn["mode"] = JsonValue::from("path");
444 btn["match_condition"] = match_condition.into();
445 return btn;
446 }
447
448 fn table_select_fields(&mut self) -> JsonValue {
450 let mut fields = object! {};
451 fields[self.primary_key()] = df_fields::str::Key::new(true, self.primary_key(), "ID", 20).field();
452 fields["filter"] = df_fields::text::Text::new(true, "filter", "模糊搜索", "").field();
453 return fields;
454 }
455 fn table_select(&mut self, request: JsonValue, fields: Vec<&str>, filter: Vec<Vec<&str>>) -> JsonValue {
457 let id = request["id"].as_str().unwrap();
458 let wheres = request["filter"].as_str().unwrap();
459
460 let mut db = self.tools().db;
461 let db = db.table(self.table());
462
463 db.field(format!("id,{}", fields.join(",")).as_str().clone());
464
465 for item in filter.iter() {
466 db.where_and(item[0], item[1], item[2].into());
467 }
468 if wheres != "" {
469 if id != "" {
470 db.where_or("id", "=", id.into());
471 }
472 db.where_or(fields.join("|").as_str(), "like", format!("%{}%", wheres).into());
473 } else {
474 if id != "" {
475 db.where_or("id", "=", id.into()).where_or("id", "!=", id.into());
476 }
477 }
478
479 let data = db.select();
480 let mut list = array![];
481 for item in data.members() {
482 let mut row = object! {};
483 row["id"] = item["id"].clone();
484 for field in fields.iter() {
485 if row["value"].is_null() {
486 row["value"] = format!("{}", item[field.clone()]).into();
487 } else {
488 row["value"] = format!("{} | {}", row["value"], item[field.clone()]).into();
489 }
490 }
491 list.push(row).unwrap();
492 }
493 list
494 }
495}
496
497pub enum BtnColor {
499 Red,
500 Blue,
501 Yellow,
502}
503
504impl BtnColor {
505 fn from(self) -> &'static str {
506 match self {
507 BtnColor::Red => "red",
508 BtnColor::Blue => "blue",
509 BtnColor::Yellow => "yellow",
510 }
511 }
512}
513
514pub enum BtnMode {
516 Form,
517 Url,
518 Api,
519 Download,
520 Path,
521}
522
523impl BtnMode {
524 fn from(self) -> &'static str {
525 match self {
526 BtnMode::Form => "form",
527 BtnMode::Url => "url",
528 BtnMode::Api => "api",
529 BtnMode::Download => "download",
530 BtnMode::Path => "path",
531 }
532 }
533}
534
535pub trait Action {
537 fn title(&mut self) -> &'static str;
539 fn name(&mut self) -> &'static str;
541 fn token(&mut self) -> bool { true }
543 fn describe(&mut self) -> &'static str { return ""; }
545 fn public(&mut self) -> bool { true }
547 fn interface_type(&mut self) -> &'static str {
549 ""
550 }
551 fn dependent(&mut self) -> Vec<&'static str> {
553 return vec![];
554 }
555 fn params(&mut self) -> JsonValue { object! {} }
557 fn _check(&mut self, mut request: JsonValue) -> (bool, String, JsonValue) {
559 let params = self.params();
560 let mut new_request = object! {};
561 for (key, field) in params.entries() {
562 if request[key].is_null() && field["require"].as_bool().unwrap() {
563 return (false, format!("缺少参数 {}:{}", key, field["title"]), request);
564 }
565 if request[key].is_empty() && field["require"].as_bool().unwrap() {
566 request[key] = field["def"].clone().into();
567 }
568 if request[key].is_null() && !field["require"].as_bool().unwrap() {
569 request[key] = field["def"].clone().into();
570 }
571 if request[key] == JsonValue::from("null") {
572 request[key] = field["def"].clone().into();
573 }
574 new_request[key] = request[key].clone();
575 }
576 return (true, "验证通过".to_string(), new_request);
577 }
578 fn run(&mut self, header: JsonValue, request: JsonValue) -> Response {
580 let (state, msg, request) = self._check(request.clone());
581 if !state {
582 return self.fail(&*msg);
583 }
584 return self.index(header.clone(), request.clone());
585 }
586 fn index(&mut self, header: JsonValue, request: JsonValue) -> Response;
587 fn success(&mut self, data: JsonValue, msg: &str) -> Response {
588 Response::success(data, msg)
589 }
590 fn fail(&mut self, msg: &str) -> Response {
591 Response::fail(msg)
592 }
593 fn login(&mut self, msg: &str) -> Response {
594 Response::login(msg)
595 }
596 fn download(&mut self, filename: &str) -> Response {
597 Response::download(filename)
598 }
599 fn redirect(&mut self, url: &str) -> Response {
600 Response::redirect(url)
601 }
602 fn tools(&mut self) -> Tools {
604 TOOLS.lock().unwrap().get("tools").unwrap().clone()
605 }
606}
607
608#[derive(Clone)]
610pub struct Tools {
611 pub db: Db,
612 pub cache: Cache,
613 pub kafka: Kafka,
614 pub email: Smtp,
615}
616
617#[derive(Clone, Debug)]
618pub struct Response(i32, &'static str, JsonValue);
619
620impl Response {
621 pub fn into(self) -> (i32, &'static str, JsonValue) {
622 return (self.0, self.1, self.2);
623 }
624 pub fn success(data: JsonValue, msg: &str) -> Self {
626 let data = object! {code: 0,data:data,msg: msg.to_string()};
627 Self(200, "json", data)
628 }
629 pub fn fail(msg: &str) -> Self {
631 let data = object! {
632 code: -1,
633 msg: msg.to_string()
634 };
635 Self(200, "json", data)
636 }
637 pub fn login(msg: &str) -> Self {
639 let data = object! {code: 1000,msg: msg.to_string(),};
640 Self(200, "json", data)
641 }
642 pub fn download(filename: &str) -> Self {
644 Self(200, "download", filename.into())
645 }
646 pub fn redirect(url: &str) -> Self {
648 Self(301, "url", url.into())
649 }
650}
651
652pub struct ApiModel {}
653
654impl ApiModel {
655 pub fn run(args_new: Vec<String>) -> (bool, String, String, String, String, JsonValue) {
656 let mut args: Vec<String> = env::args().collect();
657 if args_new.len() > 0 {
658 args = args_new.clone();
659 }
660 if args.len() <= 1 {
661 return (false, "参数错误".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
662 }
663 let mode = args[1].as_str();
664 let api = args[2].as_str();
665 if api.is_empty() {
666 return (false, "无API参数".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
667 }
668 let api: Vec<&str> = api.split(".").collect();
669 if api.len() != 3 {
670 return (false, "API参数错误".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
671 }
672 let data = args[3].as_str();
673 if data.is_empty() {
674 return (false, "请求参数无效".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
675 }
676 let data = json::parse(data).unwrap();
677 return (true, mode.to_string(), api[0].to_string(), api[1].to_string(), api[2].to_string(), data);
678 }
679 pub fn fail(msg: &str) -> JsonValue {
680 let data = object! {code:-1,msg:msg};
681 return data;
682 }
683}
684
685