diff --git a/index.html b/index.html index 71404bf..259f98a 100644 --- a/index.html +++ b/index.html @@ -5,10 +5,157 @@ CodeForge + + +
+ +

CodeForge

+

轻量级代码执行器

+
+
+
+
+
+
+ +
+ + diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 27a3ff4..a85cfa1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,7 +14,7 @@ tauri-build = { version = "2", features = [] } chrono = { version = "0.4.41", features = ["serde"] } [dependencies] -tauri = { version = "2", features = [] } +tauri = { version = "2", features = ["devtools"] } tauri-plugin-opener = "2" tauri-plugin-shell = "2.0" tauri-plugin-dialog = "2.0" diff --git a/src-tauri/src/execution.rs b/src-tauri/src/execution.rs index 831445a..3e6178f 100644 --- a/src-tauri/src/execution.rs +++ b/src-tauri/src/execution.rs @@ -343,6 +343,20 @@ pub async fn execute_code( let _ = plugin.post_execute_hook(&mut result); + if result.success + && result.stdout == *"END-NO-OUTPUT" + && result.stderr == *"END-NO-OUTPUT" + { + let _ = app.emit( + "code-output", + serde_json::json!({ + "type": "stdout", + "content": "代码执行成功 (无输出)", + "language": request.language + }), + ); + } + let _ = app.emit( "code-execution-complete", serde_json::json!({ diff --git a/src-tauri/src/plugins/mod.rs b/src-tauri/src/plugins/mod.rs index f003504..a1ff9de 100644 --- a/src-tauri/src/plugins/mod.rs +++ b/src-tauri/src/plugins/mod.rs @@ -295,10 +295,20 @@ pub trait LanguagePlugin: Send + Sync { // 后执行钩子 fn post_execute_hook(&self, result: &mut ExecutionResult) -> Result<(), String> { + info!( + "执行代码 -> 插件 [ {} ] 处理 post_execute_hook 开始", + self.get_language_key() + ); + if result.success && result.stdout.is_empty() && result.stderr.is_empty() { - result.stdout = "代码执行成功 (无输出)".to_string(); + result.stdout = String::from("END-NO-OUTPUT"); + result.stderr = String::from("END-NO-OUTPUT"); } + info!( + "执行代码 -> 插件 [ {} ] 处理 post_execute_hook 结束", + self.get_language_key() + ); Ok(()) } } diff --git a/src-tauri/src/setup/menu.rs b/src-tauri/src/setup/menu.rs index 85ad74a..0327d6d 100644 --- a/src-tauri/src/setup/menu.rs +++ b/src-tauri/src/setup/menu.rs @@ -12,8 +12,11 @@ pub fn create_menu(app: &AppHandle) -> tauri::Result> { // 编辑菜单 let edit_submenu = menus::edit::create_edit_submenu(app)?; + // 开发者菜单 + let developer_submenu = menus::developer::create_developer_submenu(app)?; + let menu = MenuBuilder::new(app) - .items(&[&app_submenu, &edit_submenu]) + .items(&[&app_submenu, &edit_submenu, &developer_submenu]) .build()?; Ok(menu) @@ -23,5 +26,6 @@ pub fn setup_menu_handler(app: &AppHandle) { app.on_menu_event(move |app, event| { menus::app::handle_app_menu_event(app, event.id().as_ref()); menus::edit::handle_edit_menu_event(app, event.id().as_ref()); + menus::developer::handle_developer_menu_event(app, event.id().as_ref()); }); } diff --git a/src-tauri/src/setup/menus/app.rs b/src-tauri/src/setup/menus/app.rs index 55b3923..92efcd5 100644 --- a/src-tauri/src/setup/menus/app.rs +++ b/src-tauri/src/setup/menus/app.rs @@ -9,21 +9,27 @@ pub fn create_app_submenu(app: &AppHandle) -> tauri::Result> .id("about") .build(app)?; - let quit_item = MenuItemBuilder::new("退出 CodeForge") - .id("quit") - .accelerator("CmdOrCtrl+Q") - .build(app)?; - let settings_item = MenuItemBuilder::new("设置") .id("settings") .accelerator("CmdOrCtrl+,") .build(app)?; + let restart_item = MenuItemBuilder::new("重启 CodeForge") + .id("restart") + .accelerator("CmdOrCtrl+R") + .build(app)?; + + let quit_item = MenuItemBuilder::new("退出 CodeForge") + .id("quit") + .accelerator("CmdOrCtrl+Q") + .build(app)?; + let app_submenu = SubmenuBuilder::new(app, "CodeForge") .item(&about_item) .separator() .item(&settings_item) .separator() + .item(&restart_item) .item(&quit_item) .build()?; @@ -38,6 +44,10 @@ pub fn handle_app_menu_event(app: &AppHandle, event_id: &str) { "settings" => { let _event = app.emit("show-settings", ()); } + "restart" => { + info!("CodeForge 应用重启"); + app.restart(); + } "quit" => { info!("CodeForge 应用关闭"); app.exit(0); diff --git a/src-tauri/src/setup/menus/developer.rs b/src-tauri/src/setup/menus/developer.rs new file mode 100644 index 0000000..a930162 --- /dev/null +++ b/src-tauri/src/setup/menus/developer.rs @@ -0,0 +1,42 @@ +use log::info; +use tauri::{ + AppHandle, Manager, + menu::{MenuItemBuilder, Submenu, SubmenuBuilder}, +}; + +pub fn create_developer_submenu(app: &AppHandle) -> tauri::Result> { + let reload_item = MenuItemBuilder::new("重新加载") + .id("reload-window") + .accelerator("CmdOrCtrl+Shift+R") + .build(app)?; + + let devtools_item = MenuItemBuilder::new("打开调试器") + .id("open-devtools") + .accelerator("CmdOrCtrl+Shift+I") + .build(app)?; + + let developer_submenu = SubmenuBuilder::new(app, "开发者模式") + .item(&reload_item) + .item(&devtools_item) + .build()?; + + Ok(developer_submenu) +} + +pub fn handle_developer_menu_event(app: &AppHandle, event_id: &str) { + match event_id { + "reload-window" => { + info!("开发者 -> 重新加载"); + if let Some(window) = app.get_webview_window("main") { + let _ = window.reload(); + } + } + "open-devtools" => { + info!("开发者 -> 打开调试器"); + if let Some(window) = app.get_webview_window("main") { + window.open_devtools(); + } + } + _ => {} + } +} diff --git a/src-tauri/src/setup/menus/mod.rs b/src-tauri/src/setup/menus/mod.rs index fe00cba..816ce03 100644 --- a/src-tauri/src/setup/menus/mod.rs +++ b/src-tauri/src/setup/menus/mod.rs @@ -1,2 +1,3 @@ pub mod app; +pub mod developer; pub mod edit; diff --git a/src-tauri/src/utils/logger.rs b/src-tauri/src/utils/logger.rs index 8888d70..230ab15 100644 --- a/src-tauri/src/utils/logger.rs +++ b/src-tauri/src/utils/logger.rs @@ -95,7 +95,7 @@ pub async fn reset_log_directory(_app: AppHandle) -> Result<(), String> { } // 获取日志文件列表 -#[command] +#[tauri::command] pub async fn get_log_files(app: AppHandle) -> Result, String> { let log_dir = { let guard = LOG_DIRECTORY.lock().unwrap(); @@ -106,22 +106,49 @@ pub async fn get_log_files(app: AppHandle) -> Result, String> { }; info!("获取日志 -> 日志目录为: {}", log_dir.display()); + // 获取今天的日期字符串 + let today = chrono::Local::now().format("%Y-%m-%d").to_string(); + info!("获取日志 -> 查找今天({})的日志文件", today); + let mut log_files = Vec::new(); if let Ok(entries) = std::fs::read_dir(&log_dir) { for entry in entries.flatten() { if let Some(filename) = entry.file_name().to_str() { - if filename.ends_with(".log") && filename.starts_with("codeforge-") { + if filename.ends_with(".log") + && filename.starts_with("codeforge-") + && filename.contains(&today) + { log_files.push(filename.to_string()); - info!("获取日志 -> 发现日志文件: {}", filename); + info!("获取日志 -> 发现今天的日志文件: {}", filename); } } } } - info!("获取日志 -> 找到 {} 个日志文件", log_files.len()); - log_files.sort(); - log_files.reverse(); // 最新的在前面 + info!("获取日志 -> 找到 {} 个今天的日志文件", log_files.len()); + + // 按日志级别排序:error -> warn -> info -> debug -> 普通日志 + log_files.sort_by(|a, b| { + let get_priority = |filename: &str| -> u8 { + if filename.contains("-info-") { + 1 + } else if filename.contains("-warn-") { + 2 + } else if filename.contains("-error-") { + 3 + } else if filename.contains("-debug-") { + 4 + } else { + 0 + } + }; + + let priority_a = get_priority(a); + let priority_b = get_priority(b); + + priority_a.cmp(&priority_b).then_with(|| a.cmp(b)) + }); Ok(log_files) } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 29de561..ee9eaac 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -17,6 +17,8 @@ "minHeight": 600, "width": 1800, "height": 1200, + "center": true, + "devtools": true, "additionalBrowserArgs": "--disable-context-menu" } ], diff --git a/src/App.vue b/src/App.vue index 9cae388..927f772 100644 --- a/src/App.vue +++ b/src/App.vue @@ -338,6 +338,7 @@ const clearOutput = () => { // 处理实时输出 const handleRealtimeOutput = (event: any) => { const data: CodeOutputEvent = event.payload + console.log('实时输出:', data) // 只处理当前语言的输出 if (data.language !== currentLanguage.value) { @@ -448,6 +449,9 @@ onMounted(async () => { unlistenExecutionStoppedFn = await listen('code-execution-stopped', handleExecutionStopped) unlistenExecutionTimeoutFn = await listen('code-execution-timeout', handleExecutionTimeout) unlistenExecutionErrorFn = await listen('code-execution-error', handleExecutionError) + + // 触发 app-ready 事件,通知主进程 + window.dispatchEvent(new CustomEvent('app-ready')) }) onUnmounted(() => {