|
|
@@ -9,9 +9,12 @@ const installStore = useInstallStore()
|
|
|
|
|
|
const isLaunching = ref(false)
|
|
|
const isInstalling = ref(false)
|
|
|
+const isUninstalling = ref(false)
|
|
|
const launchError = ref('')
|
|
|
const launchSuccess = ref(false)
|
|
|
const installError = ref('')
|
|
|
+const uninstallError = ref('')
|
|
|
+const uninstallSuccess = ref(false)
|
|
|
const isChecking = ref(false)
|
|
|
|
|
|
const nodejsInstalled = computed(() => installStore.isInstalled('nodejs'))
|
|
|
@@ -20,18 +23,24 @@ const claudeCodeInstalled = computed(() => installStore.isInstalled('claudeCode'
|
|
|
const claudeCodeVersion = computed(() => installStore.getInstalledVersion('claudeCode'))
|
|
|
|
|
|
// 启动按钮只有在 Claude Code 已安装时才可点击
|
|
|
-const canLaunch = computed(() => gitInstalled.value && claudeCodeInstalled.value && !isLaunching.value && !isChecking.value && !isInstalling.value)
|
|
|
+const canLaunch = computed(() => gitInstalled.value && claudeCodeInstalled.value && !isLaunching.value && !isChecking.value && !isInstalling.value && !isUninstalling.value)
|
|
|
|
|
|
// 安装按钮只有在 Node.js 已安装且 Claude Code 未安装时才可点击
|
|
|
-const canInstall = computed(() => nodejsInstalled.value && !claudeCodeInstalled.value && !isInstalling.value && !isChecking.value)
|
|
|
+const canInstall = computed(() => nodejsInstalled.value && !claudeCodeInstalled.value && !isInstalling.value && !isChecking.value && !isUninstalling.value)
|
|
|
+
|
|
|
+// 卸载按钮只有在 Claude Code 已安装时才可点击
|
|
|
+const canUninstall = computed(() => claudeCodeInstalled.value && !isUninstalling.value && !isChecking.value && !isInstalling.value)
|
|
|
|
|
|
const statusText = computed(() => {
|
|
|
if (isChecking.value) return t('common.loading')
|
|
|
if (isInstalling.value) return t('claudeCode.installing')
|
|
|
+ if (isUninstalling.value) return t('claudeCode.uninstalling')
|
|
|
if (isLaunching.value) return t('claudeCode.launching')
|
|
|
if (launchSuccess.value) return t('claudeCode.launchSuccess')
|
|
|
+ if (uninstallSuccess.value) return t('claudeCode.uninstallSuccess')
|
|
|
if (launchError.value) return launchError.value
|
|
|
if (installError.value) return installError.value
|
|
|
+ if (uninstallError.value) return uninstallError.value
|
|
|
if (!nodejsInstalled.value) return t('claudeCode.nodejsRequired')
|
|
|
if (!gitInstalled.value) return t('claudeCode.gitRequired')
|
|
|
if (!claudeCodeInstalled.value) return t('claudeCode.notInstalled')
|
|
|
@@ -82,6 +91,26 @@ async function handleLaunch() {
|
|
|
isLaunching.value = false
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+async function handleUninstall() {
|
|
|
+ if (!canUninstall.value) return
|
|
|
+
|
|
|
+ isUninstalling.value = true
|
|
|
+ uninstallError.value = ''
|
|
|
+ uninstallSuccess.value = false
|
|
|
+ launchSuccess.value = false
|
|
|
+
|
|
|
+ try {
|
|
|
+ await window.electronAPI.uninstall('claudeCode')
|
|
|
+ uninstallSuccess.value = true
|
|
|
+ // 卸载成功后刷新状态
|
|
|
+ await refreshStatus()
|
|
|
+ } catch (error) {
|
|
|
+ uninstallError.value = (error as Error).message || t('claudeCode.uninstallFailed')
|
|
|
+ } finally {
|
|
|
+ isUninstalling.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
@@ -94,12 +123,25 @@ async function handleLaunch() {
|
|
|
<span>{{ t('software.claudeCode.name') }}</span>
|
|
|
</h2>
|
|
|
<p>{{ t('software.claudeCode.description') }}</p>
|
|
|
- <el-tag v-if="claudeCodeInstalled && claudeCodeVersion" type="success" size="small">
|
|
|
- {{ t('common.installed') }} v{{ claudeCodeVersion }}
|
|
|
- </el-tag>
|
|
|
- <el-tag v-else-if="claudeCodeInstalled" type="success" size="small">
|
|
|
- {{ t('common.installed') }}
|
|
|
- </el-tag>
|
|
|
+ <div class="install-status">
|
|
|
+ <el-tag v-if="claudeCodeInstalled && claudeCodeVersion" type="success" size="small">
|
|
|
+ {{ t('common.installed') }} v{{ claudeCodeVersion }}
|
|
|
+ </el-tag>
|
|
|
+ <el-tag v-else-if="claudeCodeInstalled" type="success" size="small">
|
|
|
+ {{ t('common.installed') }}
|
|
|
+ </el-tag>
|
|
|
+ <el-button
|
|
|
+ v-if="claudeCodeInstalled"
|
|
|
+ type="danger"
|
|
|
+ size="small"
|
|
|
+ plain
|
|
|
+ :disabled="!canUninstall"
|
|
|
+ :loading="isUninstalling"
|
|
|
+ @click="handleUninstall"
|
|
|
+ >
|
|
|
+ {{ isUninstalling ? t('claudeCode.uninstalling') : t('claudeCode.uninstall') }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<div v-if="!nodejsInstalled" class="warning-card">
|
|
|
@@ -130,13 +172,13 @@ async function handleLaunch() {
|
|
|
>
|
|
|
{{ isInstalling ? t('claudeCode.installing') : t('claudeCode.install') }}
|
|
|
</el-button>
|
|
|
- <el-button :disabled="isChecking || isInstalling" @click="refreshStatus">
|
|
|
+ <el-button :disabled="isChecking || isInstalling || isUninstalling" @click="refreshStatus">
|
|
|
{{ t('claudeCode.refresh') }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
|
|
|
<div class="status-container">
|
|
|
- <p :class="['status-text', { success: launchSuccess, error: !!launchError || !!installError }]">
|
|
|
+ <p :class="['status-text', { success: launchSuccess || uninstallSuccess, error: !!launchError || !!installError || !!uninstallError }]">
|
|
|
{{ statusText }}
|
|
|
</p>
|
|
|
</div>
|
|
|
@@ -202,6 +244,13 @@ async function handleLaunch() {
|
|
|
font-size: 0.9em;
|
|
|
margin-top: var(--spacing-xs);
|
|
|
}
|
|
|
+
|
|
|
+ .install-status {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: var(--spacing-sm);
|
|
|
+ margin-top: var(--spacing-xs);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.info-card {
|