1use crate::module::Module;
2use crate::Tools;
3use crate::PLUGIN_TOOLS;
4use std::any::type_name;
5use std::fs;
6use std::fs::create_dir_all;
7use std::path::PathBuf;
8
9#[must_use]
10pub fn to_pascal_case(s: &str) -> String {
11 s.split('_')
12 .filter(|part| !part.is_empty())
13 .map(|part| {
14 let mut chars = part.chars();
15 match chars.next() {
16 Some(first) => first
17 .to_uppercase()
18 .chain(chars.flat_map(|c| c.to_lowercase()))
19 .collect(),
20 None => String::new(),
21 }
22 })
23 .collect()
24}
25
26pub trait Addon: Send + Sync + 'static {
28 fn name(&self) -> &'static str {
31 let name = type_name::<Self>()
32 .split("::")
33 .last()
34 .unwrap_or_default()
35 .to_lowercase();
36 Box::leak(name.into_boxed_str())
37 }
38 fn title(&self) -> &'static str;
40 fn icon(&self) -> &'static str {
42 ""
43 }
44 fn description(&self) -> &'static str {
46 ""
47 }
48 fn pages(&self) -> &'static str {
50 ""
51 }
52 fn sort(&self) -> usize {
54 99
55 }
56 fn category(&self) -> &'static str {
58 ""
59 }
60 fn module(&mut self, name: &str) -> Result<Box<dyn Module>, String>;
62 fn tools(&mut self) -> Tools {
64 PLUGIN_TOOLS.get().expect("tools not initialized").clone()
65 }
66 fn handle(&mut self) {}
68}
69
70pub fn addon_create(
71 path: &str,
72 plugin: &str,
73 plugin_title: &str,
74 model: &str,
75 model_title: &str,
76 action: &str,
77 action_title: &str,
78) {
79 let root_path = PathBuf::from(path);
80 let plugin_path = root_path.join("plugin");
81 let plugin_path = plugin_path.join(plugin);
82 create_dir_all(plugin_path.as_os_str()).expect("创建目录失败");
83
84 let plugin_mod_path = plugin_path.join("mod.rs");
85 if !plugin_mod_path.is_file() {
86 let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
87 let temp_plugin_mod_path = temp_plugin_mod_path.join("temp").join("plugin");
88 let temp_plugin_mod_data =
89 fs::read_to_string(temp_plugin_mod_path).expect("读取插件模板失败");
90 let addon_1 = plugin.to_lowercase();
91 let plugin_1 = plugin[0..=0].to_uppercase();
92 let plugin_2 = plugin[1..].to_lowercase();
93 let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{addon}}", &addon_1.to_string());
94 let temp_plugin_mod_data =
95 temp_plugin_mod_data.replace("{{plugin}}", &format!("{plugin_1}{plugin_2}"));
96 let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{title}}", plugin_title);
97 fs::write(plugin_mod_path, temp_plugin_mod_data).expect("写入插件mod错误");
98 }
99
100 if !model.is_empty() {
101 let model_path = plugin_path.join(model);
102 create_dir_all(model_path.as_os_str()).expect("创建模型目录失败");
103
104 let plugin_d = to_pascal_case(plugin);
105 let model_d = to_pascal_case(model);
106
107 let model_mod_path = model_path.join("mod.rs");
108 if !model_mod_path.is_file() {
109 let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
110 let temp_model_mod_path = temp_plugin_mod_path.join("temp").join("model");
111 let mut temp_model_mod_data =
112 fs::read_to_string(temp_model_mod_path).expect("读取模型模板失败");
113 temp_model_mod_data = temp_model_mod_data.replace("{{addon}}", &plugin_d.to_string());
114 temp_model_mod_data =
115 temp_model_mod_data.replace("{{model}}", &format!("{plugin_d}{model_d}"));
116 temp_model_mod_data =
117 temp_model_mod_data.replace("{{addon::model}}", &format!("{plugin}::{model}"));
118 temp_model_mod_data =
119 temp_model_mod_data.replace("{{plugin_model}}", &format!("{plugin}_{model}"));
120 temp_model_mod_data = temp_model_mod_data.replace("{{model_name}}", model);
121 let temp_model_mod_data = temp_model_mod_data.replace("{{title}}", model_title);
122 fs::write(model_mod_path, temp_model_mod_data).expect("写入模型mod错误");
123 }
124
125 if !action.is_empty() {
126 let action_path = model_path.join(format!("{action}.rs"));
127 if !action_path.is_file() {
128 let temp_action_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
129 let temp_action_mod_path = {
130 if action.contains("table") {
131 temp_action_mod_path.join("temp").join("action_table")
132 } else if action.contains("add") {
133 temp_action_mod_path.join("temp").join("action_add")
134 } else if action.contains("del") {
135 temp_action_mod_path.join("temp").join("action_del")
136 } else if action.contains("put") {
137 temp_action_mod_path.join("temp").join("action_put")
138 } else if action.contains("select_tree") {
139 temp_action_mod_path.join("temp").join("action_select_tree")
140 } else if action.contains("select") {
141 temp_action_mod_path.join("temp").join("action_select")
142 } else if action.contains("get") {
143 temp_action_mod_path.join("temp").join("action_get")
144 } else if action.contains("menu") {
145 temp_action_mod_path.join("temp").join("action_menu")
146 } else if action.contains("down") {
147 temp_action_mod_path.join("temp").join("action_down")
148 } else if action.contains("tree") {
149 temp_action_mod_path.join("temp").join("action_tree")
150 } else if action.contains("import") {
151 temp_action_mod_path.join("temp").join("action_import")
152 } else {
153 temp_action_mod_path.join("temp").join("action")
154 }
155 };
156
157 let temp_action_mod_data =
158 fs::read_to_string(temp_action_mod_path).expect("读取动作模板失败");
159
160 let action_d = to_pascal_case(action);
161
162 let temp_action_mod_data = temp_action_mod_data
163 .replace("{{action}}", &format!("{plugin_d}{model_d}{action_d}"));
164 let temp_action_mod_data =
165 temp_action_mod_data.replace("{{api}}", &format!("{plugin}.{model}.{action}"));
166 let temp_action_mod_data =
167 temp_action_mod_data.replace("{{model}}", &format!("{plugin_d}{model_d}"));
168 let temp_action_mod_data =
169 temp_action_mod_data.replace("{{addon::model}}", &format!("{plugin}::{model}"));
170 let temp_action_mod_data = temp_action_mod_data.replace("{{model_a}}", model);
171 let temp_action_mod_data = temp_action_mod_data.replace("{{plugin}}", plugin);
172 let temp_action_mod_data = temp_action_mod_data.replace("{{title}}", action_title);
173 fs::write(action_path, temp_action_mod_data).expect("写入动作文件错误");
174 }
175 }
176 }
177}