Skip to content

Commit fedcf94

Browse files
authored
Merge pull request #13 from qianmoQ/dev-25.0.0
feat (core): 日志根据 level 拆分独立文件
2 parents ae83887 + 7f47912 commit fedcf94

9 files changed

Lines changed: 104 additions & 61 deletions

File tree

src-tauri/src/logger.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,35 @@ use tauri::{AppHandle, Manager};
88
static LOG_DIRECTORY: Mutex<Option<PathBuf>> = Mutex::new(None);
99

1010
pub fn setup_logger(app: &AppHandle) -> Result<(), fern::InitError> {
11-
// 获取日志目录(可能是自定义的,也可能是默认的)
11+
// 获取日志目录
1212
let log_dir = get_effective_log_directory(app);
1313

1414
// 创建日志目录
1515
if let Err(e) = fs::create_dir_all(&log_dir) {
1616
eprintln!("Failed to create log directory: {}", e);
17-
// 如果自定义目录创建失败,回退到默认目录
1817
let default_dir = get_default_log_directory(app);
1918
fs::create_dir_all(&default_dir).expect("Failed to create default log directory");
2019

21-
// 更新为默认目录
2220
{
2321
let mut guard = LOG_DIRECTORY.lock().unwrap();
24-
*guard = None; // 清除自定义设置
22+
*guard = None;
2523
}
2624

2725
warn!("日志目录创建失败,使用默认目录: {:?}", default_dir);
28-
} else {
29-
info!("日志目录: {:?}", log_dir);
3026
}
3127

3228
// 生成当天的日志文件名
3329
let today = Local::now().format("%Y-%m-%d").to_string();
34-
let log_file = log_dir.join(format!("codeforge-{}.log", today));
3530

36-
// 配置日志
37-
fern::Dispatch::new()
31+
// 不同级别的日志文件
32+
let all_log_file = log_dir.join(format!("codeforge-{}.log", today));
33+
let error_log_file = log_dir.join(format!("codeforge-error-{}.log", today));
34+
let warn_log_file = log_dir.join(format!("codeforge-warn-{}.log", today));
35+
let info_log_file = log_dir.join(format!("codeforge-info-{}.log", today));
36+
let debug_log_file = log_dir.join(format!("codeforge-debug-{}.log", today));
37+
38+
// 基础配置
39+
let base_config = fern::Dispatch::new()
3840
.format(|out, message, record| {
3941
out.finish(format_args!(
4042
"[{}] [{}] [{}:{}] {}",
@@ -45,17 +47,40 @@ pub fn setup_logger(app: &AppHandle) -> Result<(), fern::InitError> {
4547
message
4648
))
4749
})
48-
.level(LevelFilter::Debug) // 设置日志级别
49-
.level_for("hyper", LevelFilter::Warn) // 减少第三方库的日志
50+
.level(LevelFilter::Debug)
51+
.level_for("hyper", LevelFilter::Warn)
5052
.level_for("reqwest", LevelFilter::Warn)
51-
.level_for("tauri", LevelFilter::Info) // Tauri 框架日志
52-
.chain(std::io::stdout()) // 同时输出到控制台
53-
.chain(fern::log_file(&log_file)?) // 输出到文件
53+
.level_for("tauri", LevelFilter::Info);
54+
55+
// 配置不同级别的日志输出
56+
base_config
57+
.chain(std::io::stdout()) // 控制台输出
58+
.chain(fern::log_file(&all_log_file)?) // 所有级别写入总文件
59+
.chain(
60+
fern::Dispatch::new()
61+
.filter(|metadata| metadata.level() == log::Level::Error)
62+
.chain(fern::log_file(&error_log_file)?),
63+
)
64+
.chain(
65+
fern::Dispatch::new()
66+
.filter(|metadata| metadata.level() == log::Level::Warn)
67+
.chain(fern::log_file(&warn_log_file)?),
68+
)
69+
.chain(
70+
fern::Dispatch::new()
71+
.filter(|metadata| metadata.level() == log::Level::Info)
72+
.chain(fern::log_file(&info_log_file)?),
73+
)
74+
.chain(
75+
fern::Dispatch::new()
76+
.filter(|metadata| metadata.level() == log::Level::Debug)
77+
.chain(fern::log_file(&debug_log_file)?),
78+
)
5479
.apply()?;
5580

5681
info!("CodeForge 应用启动");
5782
info!("应用版本: {}", env!("CARGO_PKG_VERSION"));
58-
info!("日志文件: {:?}", log_file);
83+
info!("日志文件目录 {}", log_dir.display());
5984

6085
Ok(())
6186
}

src-tauri/src/main.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async fn execute_code(
6464
let start_time = std::time::Instant::now();
6565
let mut _last_error: String = String::new();
6666

67-
let cmd = plugin.get_command();
67+
let cmd = plugin.get_command(None);
6868
let args = plugin.get_execute_args(file_path.to_str().unwrap());
6969
info!(
7070
"执行代码 -> 调用插件 [ {} ] 执行命令 {} 携带参数 {}",
@@ -74,7 +74,7 @@ async fn execute_code(
7474
);
7575

7676
let output = Command::new(&cmd)
77-
.args(&args)
77+
.args(args)
7878
.stdout(Stdio::piped())
7979
.stderr(Stdio::piped())
8080
.output();
@@ -142,7 +142,9 @@ async fn execute_code(
142142
request.language,
143143
request.language,
144144
_last_error,
145-
plugin.get_command().to_string()
145+
plugin
146+
.get_command(Some(file_path.to_str().unwrap()))
147+
.to_string()
146148
),
147149
execution_time,
148150
timestamp,
@@ -172,7 +174,7 @@ async fn get_info(
172174
format!("Pre-execution hook failed: {}", e)
173175
})?;
174176

175-
let cmd = plugin.get_command();
177+
let cmd = plugin.get_command(None);
176178
debug!("获取环境 -> 插件 [ {} ] 命令 {}", language, cmd);
177179

178180
let version_output = Command::new(&cmd).args(plugin.get_version_args()).output();
@@ -211,7 +213,7 @@ async fn get_info(
211213
Ok(LanguageInfo {
212214
installed: false,
213215
version: "Not found".to_string(),
214-
path: format!("Not found - tried: {:?}", plugin.get_command()),
216+
path: format!("Not found - tried: {:?}", plugin.get_command(None)),
215217
language: plugin.get_language_name().to_string(),
216218
})
217219
}

src-tauri/src/plugins/manager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl PluginManager {
5454
self.get_plugin(language).map(|plugin| PluginInfo {
5555
name: plugin.get_language_name().to_string(),
5656
file_extension: plugin.get_file_extension(),
57-
available_commands: vec![plugin.get_command().to_string()],
57+
available_commands: vec![plugin.get_command(None).to_string()],
5858
})
5959
}
6060

@@ -65,7 +65,7 @@ impl PluginManager {
6565
.map(|plugin| PluginInfo {
6666
name: plugin.get_language_name().to_string(),
6767
file_extension: plugin.get_file_extension(),
68-
available_commands: vec![plugin.get_command().to_string()],
68+
available_commands: vec![plugin.get_command(None).to_string()],
6969
})
7070
.collect()
7171
}

src-tauri/src/plugins/mod.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,23 @@ pub trait LanguagePlugin: Send + Sync {
6363
fn get_execute_home(&self) -> Option<PathBuf> {
6464
self.get_config()
6565
.and_then(|config| config.execute_home.clone())
66+
.filter(|path| !path.trim().is_empty()) // 过滤掉空字符串和只有空白字符的字符串
6667
.map(PathBuf::from)
6768
}
6869

6970
// 获取插件支持的命令
70-
fn get_command(&self) -> String {
71+
fn get_command(&self, file_path: Option<&str>) -> String {
7172
if let Some(config) = self.get_config() {
7273
if let Some(run_cmd) = &config.run_command {
73-
return run_cmd
74-
.split_whitespace()
75-
.next()
76-
.unwrap_or(&config.language)
77-
.to_string();
74+
if let Some(path) = file_path {
75+
return run_cmd.replace("$filename", path);
76+
} else {
77+
return run_cmd
78+
.split_whitespace()
79+
.next()
80+
.unwrap_or(&config.language)
81+
.to_string();
82+
}
7883
}
7984
}
8085
self.get_default_command()
@@ -120,7 +125,23 @@ pub trait LanguagePlugin: Send + Sync {
120125
}
121126

122127
fn get_version_args(&self) -> Vec<&'static str>;
123-
fn get_execute_args(&self, file_path: &str) -> Vec<String>;
128+
129+
fn get_execute_args(&self, file_path: &str) -> Vec<String> {
130+
if let Some(config) = self.get_config() {
131+
if let Some(run_cmd) = &config.run_command {
132+
// 替换 $filename 后分割,跳过第一个元素(命令本身)
133+
let full_cmd = run_cmd.replace("$filename", file_path);
134+
return full_cmd
135+
.split_whitespace()
136+
.skip(1) // 跳过命令部分,只返回参数
137+
.map(|s| s.to_string())
138+
.collect();
139+
}
140+
}
141+
// 默认情况下,文件路径就是唯一的参数
142+
vec![file_path.to_string()]
143+
}
144+
124145
fn get_path_command(&self) -> String;
125146

126147
// 构建默认配置
@@ -193,7 +214,11 @@ pub trait LanguagePlugin: Send + Sync {
193214
}
194215

195216
// 后执行钩子
196-
fn post_execute_hook(&self, _result: &mut ExecutionResult) -> Result<(), String> {
217+
fn post_execute_hook(&self, result: &mut ExecutionResult) -> Result<(), String> {
218+
if result.success && result.stdout.is_empty() && result.stderr.is_empty() {
219+
result.stdout = "代码执行成功 (无输出)".to_string();
220+
}
221+
197222
Ok(())
198223
}
199224
}

src-tauri/src/plugins/python2.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ impl LanguagePlugin for Python2Plugin {
2020
vec!["--version"]
2121
}
2222

23-
fn get_execute_args(&self, file_path: &str) -> Vec<String> {
24-
vec![file_path.to_string()]
25-
}
26-
2723
fn get_path_command(&self) -> String {
2824
"import sys; print(sys.executable)".to_string()
2925
}

src-tauri/src/plugins/python3.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{ExecutionResult, LanguagePlugin, PluginConfig};
1+
use super::{LanguagePlugin, PluginConfig};
22

33
pub struct Python3Plugin;
44

@@ -19,10 +19,6 @@ impl LanguagePlugin for Python3Plugin {
1919
vec!["--version"]
2020
}
2121

22-
fn get_execute_args(&self, file_path: &str) -> Vec<String> {
23-
vec![file_path.to_string()]
24-
}
25-
2622
fn get_path_command(&self) -> String {
2723
"import sys; print(sys.executable)".to_string()
2824
}
@@ -43,20 +39,4 @@ impl LanguagePlugin for Python3Plugin {
4339
fn get_default_command(&self) -> String {
4440
self.get_config().unwrap().run_command.unwrap()
4541
}
46-
47-
fn post_execute_hook(&self, result: &mut ExecutionResult) -> Result<(), String> {
48-
// Python 特定的后处理
49-
if result.success && result.stdout.is_empty() && result.stderr.is_empty() {
50-
result.stdout = "代码执行成功 (无输出)".to_string();
51-
}
52-
53-
// 清理 Python 特定的错误信息
54-
if !result.stderr.is_empty() {
55-
result.stderr = result
56-
.stderr
57-
.replace("Traceback (most recent call last):", "Error:");
58-
}
59-
60-
Ok(())
61-
}
6242
}

src/components/Settings.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<!-- 语言配置 -->
1010
<template #language>
11-
<Language/>
11+
<Language v-if="activeTab === 'language'"/>
1212
</template>
1313
</Tabs>
1414
</Modal>

src/components/setting/Language.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="-mt-2">
3-
<Tabs v-model="activeTab" type="card" size="md" position="left" :tabs="tabsData" @change="handleTabChange">
3+
<Tabs v-model="activeTab" type="card" size="md" position="left" :tab-button-class="['w-36']" :tabs="tabsData" @change="handleTabChange">
44
<template #[activeTab]="{ tab }">
55
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
66
<Settings2 class="w-5 h-5 mr-2"/>

src/ui/Tabs.vue

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,14 @@ const getTabButtonClasses = (tab: Tab, _index: number) => {
244244
'transition-all', 'duration-200', 'cursor-pointer', 'whitespace-nowrap'
245245
]
246246
247+
// 位置相关
248+
if (props.position === 'left' || props.position === 'right') {
249+
baseClasses.push('my-0.5')
250+
}
251+
else {
252+
baseClasses.push('mx-0.5')
253+
}
254+
247255
// 尺寸
248256
if (props.size === 'sm') {
249257
baseClasses.push('px-3', 'py-1.5', 'text-xs')
@@ -270,7 +278,7 @@ const getTabButtonClasses = (tab: Tab, _index: number) => {
270278
baseClasses.push('text-blue-600', 'dark:text-blue-400', 'border-blue-600', 'dark:border-blue-400')
271279
}
272280
else {
273-
baseClasses.push('text-gray-600', 'hover:text-gray-900', 'dark:text-gray-400', 'dark:hover:text-gray-100', 'hover:border-gray-300', 'dark:hover:border-gray-600')
281+
baseClasses.push('text-gray-600', 'hover:text-blue-500', 'dark:text-gray-400', 'dark:hover:text-blue-300', 'hover:border-blue-300', 'dark:hover:border-blue-500')
274282
}
275283
break
276284
@@ -281,7 +289,7 @@ const getTabButtonClasses = (tab: Tab, _index: number) => {
281289
baseClasses.push('bg-white', 'dark:bg-gray-700', 'shadow-sm', 'text-blue-600', 'dark:text-blue-400')
282290
}
283291
else {
284-
baseClasses.push('text-gray-600', 'hover:text-gray-900', 'dark:text-gray-400', 'dark:hover:text-gray-100')
292+
baseClasses.push('text-gray-600', 'hover:text-blue-500', 'dark:text-gray-400', 'dark:hover:text-blue-300', 'hover:bg-gray-100', 'dark:hover:bg-gray-600')
285293
}
286294
break
287295
@@ -291,7 +299,14 @@ const getTabButtonClasses = (tab: Tab, _index: number) => {
291299
baseClasses.push('bg-blue-600', 'text-white', 'border-blue-600', 'z-10')
292300
}
293301
else {
294-
baseClasses.push('bg-white', 'dark:bg-gray-800', 'text-gray-600', 'hover:text-gray-900', 'dark:text-gray-400', 'dark:hover:text-gray-100')
302+
baseClasses.push('bg-white',
303+
'dark:bg-gray-800',
304+
'text-gray-600',
305+
'hover:text-blue-500',
306+
'dark:text-gray-400',
307+
'dark:hover:text-blue-300',
308+
'hover:bg-blue-50',
309+
'dark:hover:bg-blue-900/20')
295310
}
296311
break
297312
@@ -300,7 +315,7 @@ const getTabButtonClasses = (tab: Tab, _index: number) => {
300315
baseClasses.push('text-blue-600', 'dark:text-blue-400')
301316
}
302317
else {
303-
baseClasses.push('text-gray-600', 'hover:text-gray-900', 'dark:text-gray-400', 'dark:hover:text-gray-100')
318+
baseClasses.push('text-gray-600', 'hover:text-blue-500', 'dark:text-gray-400', 'dark:hover:text-blue-300')
304319
}
305320
}
306321

0 commit comments

Comments
 (0)