黄中银 2 недель назад
Родитель
Сommit
a34cd5bfbb
7 измененных файлов с 77 добавлено и 47 удалено
  1. 1 1
      package.json
  2. 15 2
      scripts/release.cjs
  3. 1 1
      src-tauri/Cargo.toml
  4. 57 40
      src-tauri/src/commands/install.rs
  5. 1 1
      src-tauri/tauri.conf.json
  6. 1 1
      src/i18n/en-US.ts
  7. 1 1
      src/i18n/zh-CN.ts

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "claude-ai-installer",
-  "version": "0.0.5",
+  "version": "0.0.6",
   "description": "Claude AI安装器 - Claude AI Installer",
   "type": "module",
   "scripts": {

+ 15 - 2
scripts/release.cjs

@@ -403,7 +403,7 @@ ${colors.bright}╔════════════════════
   if (fs.existsSync(releaseDir)) {
     const files = fs.readdirSync(releaseDir).filter(f => {
       const ext = path.extname(f).toLowerCase();
-      return ['.exe', '.dmg', '.appimage', '.deb', '.rpm', '.zip'].includes(ext);
+      return ['.exe', '.msi', '.dmg', '.appimage', '.deb', '.rpm', '.zip'].includes(ext);
     });
 
     if (files.length > 0) {
@@ -412,7 +412,20 @@ ${colors.bright}╔════════════════════
         const filePath = path.join(releaseDir, file);
         const stats = fs.statSync(filePath);
         const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
-        console.log(`  ${colors.green}•${colors.reset} ${file} (${sizeMB} MB)`);
+        // 根据文件名添加描述
+        let desc = '';
+        if (file.includes('-setup.exe')) {
+          desc = ' - NSIS 安装程序';
+        } else if (file.endsWith('.msi')) {
+          desc = ' - MSI 安装程序';
+        } else if (file.includes('-portable.exe')) {
+          desc = ' - 便携版';
+        } else if (file.endsWith('.dmg')) {
+          desc = ' - macOS 安装镜像';
+        } else if (file.endsWith('.AppImage')) {
+          desc = ' - Linux 可执行程序';
+        }
+        console.log(`  ${colors.green}•${colors.reset} ${file} (${sizeMB} MB)${desc}`);
       }
     }
   }

+ 1 - 1
src-tauri/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "claude-ai-installer"
-version = "0.0.5"
+version = "0.0.6"
 description = "Claude AI安装器 - Claude AI Installer"
 authors = ["Claude AI"]
 edition = "2021"

+ 57 - 40
src-tauri/src/commands/install.rs

@@ -197,13 +197,14 @@ pub async fn install_software(
     }
 
     // 发送安装状态事件
-    let emit_status = |message: &str, progress: f64, i18n_key: Option<&str>, skip_log: bool| {
+    let emit_status = |message: &str, progress: f64, i18n_key: Option<&str>, skip_log: bool, i18n_params: Option<serde_json::Value>| {
         let _ = app.emit("install-status", serde_json::json!({
             "software": software,
             "message": message,
             "progress": progress,
             "i18nKey": i18n_key,
             "skipLog": skip_log,
+            "i18nParams": i18n_params,
         }));
     };
 
@@ -305,10 +306,10 @@ async fn install_nodejs<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool),
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
     C: Fn() -> bool,
 {
-    emit_status("Preparing to install Node.js...", 0.0, Some("install.preparing"), false);
+    emit_status("Preparing to install Node.js...", 0.0, Some("install.preparing"), false, None);
 
     if is_cancelled() {
         return Ok(InstallResult {
@@ -322,7 +323,7 @@ where
 
     #[cfg(target_os = "windows")]
     {
-        emit_status("Downloading Node.js...", 10.0, Some("install.downloading"), false);
+        emit_status("Downloading Node.js...", 10.0, Some("install.downloading"), false, None);
 
         // 构建下载 URL
         let download_url = format!(
@@ -349,7 +350,11 @@ where
                 last_logged_percent = (current_percent / 10) * 10;
             }
             let message = format!("下载中... {:.0}% ({:.1}MB / {:.1}MB)", percent, downloaded_mb, total_mb);
-            emit_status(&message, progress, Some("install.downloading"), !should_log);
+            emit_status(&message, progress, Some("install.downloading"), !should_log, Some(serde_json::json!({
+                "percent": format!("{:.0}", percent),
+                "downloaded": format!("{:.1}MB", downloaded_mb),
+                "total": format!("{:.1}MB", total_mb)
+            })));
         }).await?;
 
         if is_cancelled() {
@@ -361,7 +366,7 @@ where
             });
         }
 
-        emit_status("安装中...", 55.0, Some("install.installing"), false);
+        emit_status("安装中...", 55.0, Some("install.installing"), false, None);
 
         // 执行安装
         let mut args = vec!["/i", msi_path.to_str().unwrap(), "/qn"];
@@ -379,7 +384,7 @@ where
         let _ = std::fs::remove_file(&msi_path);
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Node.js installed successfully".to_string(),
@@ -392,7 +397,7 @@ where
 
     #[cfg(target_os = "macos")]
     {
-        emit_status("Installing Node.js via Homebrew...", 10.0, Some("install.installing"), false);
+        emit_status("Installing Node.js via Homebrew...", 10.0, Some("install.installing"), false, None);
 
         // 使用 shell 执行以获取最新的 PATH(包括 Homebrew 路径)
         let major_version = version.trim_start_matches('v').split('.').next().unwrap_or("22");
@@ -401,7 +406,7 @@ where
             .map_err(|e| e.to_string())?;
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Node.js installed successfully".to_string(),
@@ -414,7 +419,7 @@ where
 
     #[cfg(target_os = "linux")]
     {
-        emit_status("Installing Node.js...", 10.0, Some("install.installing"), false);
+        emit_status("Installing Node.js...", 10.0, Some("install.installing"), false, None);
 
         // 使用 NodeSource 安装
         let major_version = version.trim_start_matches('v').split('.').next().unwrap_or("22");
@@ -432,7 +437,7 @@ where
             .map_err(|e| e.to_string())?;
 
         if install_output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Node.js installed successfully".to_string(),
@@ -452,10 +457,10 @@ async fn install_pnpm<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool),
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
     C: Fn() -> bool,
 {
-    emit_status("安装中...", 10.0, Some("install.installing"), false);
+    emit_status("安装中...", 10.0, Some("install.installing"), false, None);
 
     if is_cancelled() {
         return Ok(InstallResult {
@@ -470,7 +475,7 @@ where
         .map_err(|e| e.to_string())?;
 
     if output.status.success() {
-        emit_status("安装成功", 100.0, Some("install.success"), false);
+        emit_status("安装成功", 100.0, Some("install.success"), false, None);
         Ok(InstallResult {
             success: true,
             message: "pnpm installed successfully".to_string(),
@@ -490,10 +495,10 @@ async fn install_vscode<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool),
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
     C: Fn() -> bool,
 {
-    emit_status("正在准备安装...", 0.0, Some("install.preparing"), false);
+    emit_status("正在准备安装...", 0.0, Some("install.preparing"), false, None);
 
     if is_cancelled() {
         return Ok(InstallResult {
@@ -505,7 +510,7 @@ where
 
     #[cfg(target_os = "windows")]
     {
-        emit_status("正在下载...", 10.0, Some("install.downloading"), false);
+        emit_status("正在下载...", 10.0, Some("install.downloading"), false, None);
 
         let download_url = "https://code.visualstudio.com/sha/download?build=stable&os=win32-x64";
 
@@ -527,10 +532,14 @@ where
                 last_logged_percent = (current_percent / 10) * 10;
             }
             let message = format!("下载中... {:.0}% ({:.1}MB / {:.1}MB)", percent, downloaded_mb, total_mb);
-            emit_status(&message, progress, Some("install.downloading"), !should_log);
+            emit_status(&message, progress, Some("install.downloading"), !should_log, Some(serde_json::json!({
+                "percent": format!("{:.0}", percent),
+                "downloaded": format!("{:.1}MB", downloaded_mb),
+                "total": format!("{:.1}MB", total_mb)
+            })));
         }).await?;
 
-        emit_status("安装中...", 65.0, Some("install.installing"), false);
+        emit_status("安装中...", 65.0, Some("install.installing"), false, None);
 
         let mut args = vec!["/VERYSILENT", "/NORESTART", "/MERGETASKS=!runcode"];
 
@@ -545,7 +554,7 @@ where
         let _ = std::fs::remove_file(&exe_path);
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "VS Code installed successfully".to_string(),
@@ -558,14 +567,14 @@ where
 
     #[cfg(target_os = "macos")]
     {
-        emit_status("Installing VS Code via Homebrew...", 10.0, Some("install.installing"), false);
+        emit_status("Installing VS Code via Homebrew...", 10.0, Some("install.installing"), false, None);
 
         // 使用 shell 执行以获取最新的 PATH(包括 Homebrew 路径)
         let output = run_shell_hidden("brew install --cask visual-studio-code")
             .map_err(|e| e.to_string())?;
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "VS Code installed successfully".to_string(),
@@ -578,7 +587,7 @@ where
 
     #[cfg(target_os = "linux")]
     {
-        emit_status("正在下载...", 10.0, Some("install.downloading"), false);
+        emit_status("正在下载...", 10.0, Some("install.downloading"), false, None);
 
         // 下载并安装 .deb 包
         let download_url = "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64";
@@ -599,10 +608,14 @@ where
                 last_logged_percent = (current_percent / 10) * 10;
             }
             let message = format!("下载中... {:.0}% ({:.1}MB / {:.1}MB)", percent, downloaded_mb, total_mb);
-            emit_status(&message, progress, Some("install.downloading"), !should_log);
+            emit_status(&message, progress, Some("install.downloading"), !should_log, Some(serde_json::json!({
+                "percent": format!("{:.0}", percent),
+                "downloaded": format!("{:.1}MB", downloaded_mb),
+                "total": format!("{:.1}MB", total_mb)
+            })));
         }).await?;
 
-        emit_status("安装中...", 65.0, Some("install.installing"), false);
+        emit_status("安装中...", 65.0, Some("install.installing"), false, None);
 
         // 使用 shell 执行以获取最新的 PATH
         let cmd = format!("sudo dpkg -i {}", deb_path.to_str().unwrap());
@@ -612,7 +625,7 @@ where
         let _ = std::fs::remove_file(&deb_path);
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "VS Code installed successfully".to_string(),
@@ -633,10 +646,10 @@ async fn install_git<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool),
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
     C: Fn() -> bool,
 {
-    emit_status("正在准备安装...", 0.0, Some("install.preparing"), false);
+    emit_status("正在准备安装...", 0.0, Some("install.preparing"), false, None);
 
     if is_cancelled() {
         return Ok(InstallResult {
@@ -648,7 +661,7 @@ where
 
     #[cfg(target_os = "windows")]
     {
-        emit_status("正在下载...", 10.0, Some("install.downloading"), false);
+        emit_status("正在下载...", 10.0, Some("install.downloading"), false, None);
 
         // 获取最新版本
         let client = reqwest::Client::new();
@@ -693,10 +706,14 @@ where
                 last_logged_percent = (current_percent / 10) * 10;
             }
             let message = format!("下载中... {:.0}% ({:.1}MB / {:.1}MB)", percent, downloaded_mb, total_mb);
-            emit_status(&message, progress, Some("install.downloading"), !should_log);
+            emit_status(&message, progress, Some("install.downloading"), !should_log, Some(serde_json::json!({
+                "percent": format!("{:.0}", percent),
+                "downloaded": format!("{:.1}MB", downloaded_mb),
+                "total": format!("{:.1}MB", total_mb)
+            })));
         }).await?;
 
-        emit_status("安装中...", 65.0, Some("install.installing"), false);
+        emit_status("安装中...", 65.0, Some("install.installing"), false, None);
 
         let mut args = vec!["/VERYSILENT", "/NORESTART"];
 
@@ -711,7 +728,7 @@ where
         let _ = std::fs::remove_file(&exe_path);
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Git installed successfully".to_string(),
@@ -724,14 +741,14 @@ where
 
     #[cfg(target_os = "macos")]
     {
-        emit_status("Installing Git via Homebrew...", 10.0, Some("install.installing"), false);
+        emit_status("Installing Git via Homebrew...", 10.0, Some("install.installing"), false, None);
 
         // 使用 shell 执行以获取最新的 PATH(包括 Homebrew 路径)
         let output = run_shell_hidden("brew install git")
             .map_err(|e| e.to_string())?;
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Git installed successfully".to_string(),
@@ -744,14 +761,14 @@ where
 
     #[cfg(target_os = "linux")]
     {
-        emit_status("Installing Git...", 10.0, Some("install.installing"), false);
+        emit_status("Installing Git...", 10.0, Some("install.installing"), false, None);
 
         // 使用 shell 执行以获取最新的 PATH
         let output = run_shell_hidden("sudo apt-get install -y git")
             .map_err(|e| e.to_string())?;
 
         if output.status.success() {
-            emit_status("安装成功", 100.0, Some("install.success"), false);
+            emit_status("安装成功", 100.0, Some("install.success"), false, None);
             Ok(InstallResult {
                 success: true,
                 message: "Git installed successfully".to_string(),
@@ -771,10 +788,10 @@ async fn install_claude_code_software<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool),
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
     C: Fn() -> bool,
 {
-    emit_status("安装中...", 10.0, Some("install.installing"), false);
+    emit_status("安装中...", 10.0, Some("install.installing"), false, None);
 
     if is_cancelled() {
         return Ok(InstallResult {
@@ -789,7 +806,7 @@ where
         .map_err(|e| e.to_string())?;
 
     if output.status.success() {
-        emit_status("安装成功", 100.0, Some("install.success"), false);
+        emit_status("安装成功", 100.0, Some("install.success"), false, None);
         Ok(InstallResult {
             success: true,
             message: "Claude Code installed successfully".to_string(),
@@ -809,7 +826,7 @@ async fn install_all<F, C>(
     is_cancelled: C,
 ) -> Result<InstallResult, String>
 where
-    F: Fn(&str, f64, Option<&str>, bool) + Copy,
+    F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>) + Copy,
     C: Fn() -> bool + Copy,
 {
     let mut results = Vec::new();

+ 1 - 1
src-tauri/tauri.conf.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://schema.tauri.app/config/2",
   "productName": "Claude AI Installer",
-  "version": "0.0.5",
+  "version": "0.0.6",
   "identifier": "com.claude.ai.installer",
   "build": {
     "beforeDevCommand": "npm run dev:frontend",

+ 1 - 1
src/i18n/en-US.ts

@@ -113,7 +113,7 @@ export default {
     start: 'Install',
     startAll: 'Start Installation',
     installing: 'Installing...',
-    downloading: 'Downloading...',
+    downloading: 'Downloading... {percent}% ({downloaded} / {total})',
     complete: 'Installation Complete',
     failed: 'Installation Failed',
     cancelled: 'Installation Cancelled',

+ 1 - 1
src/i18n/zh-CN.ts

@@ -113,7 +113,7 @@ export default {
     start: '开始安装',
     startAll: '开始一键安装',
     installing: '安装中...',
-    downloading: '正在下载...',
+    downloading: '下载... {percent}% ({downloaded} / {total})',
     complete: '安装完成',
     failed: '安装失败',
     cancelled: '安装已取消',