Ver código fonte

增加Claude Code的安装

黄中银 4 semanas atrás
pai
commit
543dd99b93

+ 47 - 1
ApqInstaller/electron/modules/ipc-handlers.ts

@@ -1,6 +1,7 @@
 // electron/modules/ipc-handlers.ts - IPC 处理模块
 
-import { ipcMain, dialog, BrowserWindow } from 'electron'
+import { ipcMain, dialog, BrowserWindow, shell } from 'electron'
+import * as path from 'path'
 import * as os from 'os'
 import { execa } from 'execa'
 import type { SoftwareType, SoftwareTypeWithAll, Platform } from './types'
@@ -255,6 +256,50 @@ export function registerHandlers(): void {
     return win?.isMaximized() ?? false
   })
 
+  // 启动 Claude Code (打开 Git Bash 并执行 claude 命令)
+  ipcMain.handle('launch-claude-code', async () => {
+    const platform = os.platform()
+
+    if (platform !== 'win32') {
+      throw new Error('此功能仅支持 Windows 系统')
+    }
+
+    // 查找 Git Bash 路径
+    const possiblePaths = [
+      'C:\\Program Files\\Git\\git-bash.exe',
+      'C:\\Program Files (x86)\\Git\\git-bash.exe',
+      path.join(os.homedir(), 'AppData', 'Local', 'Programs', 'Git', 'git-bash.exe')
+    ]
+
+    let gitBashPath = ''
+    for (const p of possiblePaths) {
+      try {
+        const fs = await import('fs')
+        if (fs.existsSync(p)) {
+          gitBashPath = p
+          break
+        }
+      } catch {
+        continue
+      }
+    }
+
+    if (!gitBashPath) {
+      throw new Error('未找到 Git Bash,请确保已安装 Git')
+    }
+
+    logger.info(`启动 Git Bash: ${gitBashPath}`)
+
+    // 使用 execa 启动 Git Bash 并执行 claude 命令
+    // -c 参数用于执行命令,exec bash 保持窗口打开
+    execa(gitBashPath, ['-c', 'claude; exec bash'], {
+      detached: true,
+      stdio: 'ignore'
+    }).unref()
+
+    return { success: true }
+  })
+
   // 统一安装入口
   ipcMain.handle('install', async (_event, software: SoftwareTypeWithAll, options = {}) => {
     const { version, installPnpm = true } = options
@@ -368,6 +413,7 @@ export function removeHandlers(): void {
     'window-maximize',
     'window-close',
     'window-is-maximized',
+    'launch-claude-code',
     'install'
   ]
 

+ 3 - 0
ApqInstaller/electron/modules/types.ts

@@ -119,6 +119,9 @@ export interface ElectronAPI {
   // 窗口操作
   setWindowTitle: (title: string) => Promise<void>
 
+  // Claude Code
+  launchClaudeCode: () => Promise<{ success: boolean }>
+
   // 事件监听
   onInstallStatus: (callback: (data: InstallStatus) => void) => void
   onInstallComplete: (callback: (data: InstallResult) => void) => void

+ 5 - 0
ApqInstaller/electron/preload.ts

@@ -63,6 +63,11 @@ const electronAPI: ElectronAPI = {
   // 设置窗口标题
   setWindowTitle: (title) => ipcRenderer.invoke('set-window-title', title),
 
+  // ==================== Claude Code ====================
+
+  // 启动 Claude Code (打开 Git Bash 并执行 claude 命令)
+  launchClaudeCode: () => ipcRenderer.invoke('launch-claude-code'),
+
   // 窗口最小化
   windowMinimize: () => ipcRenderer.invoke('window-minimize'),
 

+ 6 - 0
ApqInstaller/src/App.vue

@@ -7,6 +7,7 @@ import { useSettingsStore } from '@/stores/settings'
 import { useSystemStore } from '@/stores/system'
 import IntroView from '@/views/IntroView.vue'
 import BatchInstallView from '@/views/BatchInstallView.vue'
+import ClaudeCodeView from '@/views/ClaudeCodeView.vue'
 import SoftwarePane from '@/components/software/SoftwarePane.vue'
 import ProxySettings from '@/components/settings/ProxySettings.vue'
 import ThemeSwitch from '@/components/settings/ThemeSwitch.vue'
@@ -26,6 +27,7 @@ const tabs = [
   { id: 'nodejs', label: 'tabs.nodejs' },
   { id: 'vscode', label: 'tabs.vscode' },
   { id: 'git', label: 'tabs.git' },
+  { id: 'claudeCode', label: 'tabs.claudeCode' },
   { id: 'all', label: 'tabs.all' }
 ]
 
@@ -162,6 +164,10 @@ onUnmounted(() => {
           <SoftwarePane software="git" @install="handleInstall" @cancel="handleCancel" />
         </div>
 
+        <div :class="['tab-pane', { active: systemStore.activeTab === 'claudeCode' }]">
+          <ClaudeCodeView />
+        </div>
+
         <div :class="['tab-pane', { active: systemStore.activeTab === 'all' }]">
           <BatchInstallView />
         </div>

+ 15 - 0
ApqInstaller/src/i18n/en-US.ts

@@ -33,6 +33,7 @@ export default {
     nodejs: 'Node.js',
     vscode: 'VS Code',
     git: 'Git',
+    claudeCode: 'Claude Code',
     all: 'Install All'
   },
   intro: {
@@ -61,8 +62,22 @@ export default {
     all: {
       name: 'Install All',
       description: 'Customize installation of Node.js, VS Code, Git'
+    },
+    claudeCode: {
+      name: 'Claude Code',
+      description: 'Anthropic official AI programming assistant CLI tool'
     }
   },
+  claudeCode: {
+    launch: 'Launch Claude Code',
+    launching: 'Launching...',
+    launchSuccess: 'Git Bash launched, claude command executed',
+    launchFailed: 'Launch failed',
+    gitRequired: 'Git installation required',
+    gitRequiredDesc: 'Please install Git first in the Git tab before using Claude Code',
+    infoTitle: 'Instructions',
+    infoDesc: 'Click the button below to open Git Bash terminal and automatically execute the claude command. Make sure @anthropic-ai/claude-code is globally installed via npm.'
+  },
   install: {
     start: 'Install',
     startAll: 'Start Installation',

+ 15 - 0
ApqInstaller/src/i18n/zh-CN.ts

@@ -33,6 +33,7 @@ export default {
     nodejs: 'Node.js',
     vscode: 'VS Code',
     git: 'Git',
+    claudeCode: 'Claude Code',
     all: '一键全装'
   },
   intro: {
@@ -61,8 +62,22 @@ export default {
     all: {
       name: '一键安装全部',
       description: '自定义安装 Node.js、VS Code、Git'
+    },
+    claudeCode: {
+      name: 'Claude Code',
+      description: 'Anthropic 官方 AI 编程助手命令行工具'
     }
   },
+  claudeCode: {
+    launch: '启动 Claude Code',
+    launching: '正在启动...',
+    launchSuccess: 'Git Bash 已启动,claude 命令已执行',
+    launchFailed: '启动失败',
+    gitRequired: '需要先安装 Git',
+    gitRequiredDesc: '请先在 Git 标签页安装 Git,安装完成后才能使用 Claude Code',
+    infoTitle: '使用说明',
+    infoDesc: '点击下方按钮将打开 Git Bash 终端并自动执行 claude 命令。请确保已通过 npm 全局安装 @anthropic-ai/claude-code。'
+  },
   install: {
     start: '开始安装',
     startAll: '开始一键安装',

+ 105 - 0
ApqInstaller/src/views/ClaudeCodeView.vue

@@ -0,0 +1,105 @@
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { useInstallStore } from '@/stores/install'
+
+const { t } = useI18n()
+const installStore = useInstallStore()
+
+const isLaunching = ref(false)
+const launchError = ref('')
+const launchSuccess = ref(false)
+
+const gitInstalled = computed(() => installStore.isInstalled('git'))
+
+const statusText = computed(() => {
+  if (isLaunching.value) return t('claudeCode.launching')
+  if (launchSuccess.value) return t('claudeCode.launchSuccess')
+  if (launchError.value) return launchError.value
+  if (!gitInstalled.value) return t('claudeCode.gitRequired')
+  return t('common.ready')
+})
+
+async function handleLaunch() {
+  if (isLaunching.value || !gitInstalled.value) return
+
+  isLaunching.value = true
+  launchError.value = ''
+  launchSuccess.value = false
+
+  try {
+    await window.electronAPI.launchClaudeCode()
+    launchSuccess.value = true
+  } catch (error) {
+    launchError.value = (error as Error).message || t('claudeCode.launchFailed')
+  } finally {
+    isLaunching.value = false
+  }
+}
+</script>
+
+<template>
+  <div class="claude-code-install">
+    <div class="software-info">
+      <h2>{{ t('software.claudeCode.name') }}</h2>
+      <p>{{ t('software.claudeCode.description') }}</p>
+    </div>
+
+    <div class="info-card">
+      <el-alert type="info" :closable="false" show-icon>
+        <template #title>
+          {{ t('claudeCode.infoTitle') }}
+        </template>
+        <p>{{ t('claudeCode.infoDesc') }}</p>
+      </el-alert>
+    </div>
+
+    <div v-if="!gitInstalled" class="warning-card">
+      <el-alert type="warning" :closable="false" show-icon>
+        <template #title>
+          {{ t('claudeCode.gitRequired') }}
+        </template>
+        <p>{{ t('claudeCode.gitRequiredDesc') }}</p>
+      </el-alert>
+    </div>
+
+    <div class="button-group">
+      <el-button
+        type="primary"
+        :disabled="isLaunching || !gitInstalled"
+        :loading="isLaunching"
+        @click="handleLaunch"
+      >
+        {{ isLaunching ? t('claudeCode.launching') : t('claudeCode.launch') }}
+      </el-button>
+    </div>
+
+    <div class="status-container">
+      <p :class="['status-text', { success: launchSuccess, error: !!launchError }]">
+        {{ statusText }}
+      </p>
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.claude-code-install {
+  .info-card {
+    margin-bottom: var(--spacing-md);
+
+    p {
+      margin: var(--spacing-sm) 0 0 0;
+      color: var(--text-color-secondary);
+    }
+  }
+
+  .warning-card {
+    margin-bottom: var(--spacing-md);
+
+    p {
+      margin: var(--spacing-sm) 0 0 0;
+      color: var(--text-color-secondary);
+    }
+  }
+}
+</style>