From 809448a1619dc4efdb3a6e0dfac82084f94a9814 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 13 May 2026 16:08:00 +0800 Subject: [PATCH] feat: multi-JRE support, Oracle 10g driver profile, and JRE uninstall - Support multiple JRE versions per agent driver (jre-8/, jre-17/) - Auto-migrate legacy jre/ directory to jre-17/ - Detect macOS Adoptium JRE 8 Contents/Home/ layout - Route Oracle 10g connections to oracle-10g agent via driver_profile - Add Oracle 10g option in connection dialog - Add JRE uninstall with dependency check - Show per-JRE status and controls in driver management UI --- src-tauri/src/commands/agents.rs | 19 +++++ src-tauri/src/lib.rs | 1 + src/components/config/DriverStoreDialog.vue | 84 +++++++++++++------ .../connection/ConnectionDialog.vue | 2 + 4 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src-tauri/src/commands/agents.rs b/src-tauri/src/commands/agents.rs index 66cf4f534..2d50eb449 100644 --- a/src-tauri/src/commands/agents.rs +++ b/src-tauri/src/commands/agents.rs @@ -161,6 +161,25 @@ pub async fn check_jre_installed(state: State<'_, Arc>, jre_key: Optio Ok(state.agent_manager.is_jre_installed(key)) } +#[tauri::command] +pub async fn uninstall_jre(state: State<'_, Arc>, jre_key: String) -> Result<(), String> { + let am = &state.agent_manager; + let local_state = am.load_state(); + let dependents: Vec<&str> = + local_state.installed_drivers.iter().filter(|(_, d)| d.jre == jre_key).map(|(k, _)| k.as_str()).collect(); + if !dependents.is_empty() { + return Err(format!("JRE {} 正在被以下驱动使用: {},请先卸载这些驱动", jre_key, dependents.join(", "))); + } + let jre_dir = am.jre_dir(&jre_key); + if jre_dir.exists() { + std::fs::remove_dir_all(&jre_dir).map_err(|e| format!("Failed to remove JRE: {e}"))?; + } + let mut local_state = am.load_state(); + local_state.jre_versions.remove(&jre_key); + am.save_state(&local_state)?; + Ok(()) +} + #[tauri::command] pub async fn invalidate_agent_registry_cache() -> Result<(), String> { *REGISTRY_CACHE.lock().await = None; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index fb7f735ec..1c6c2a588 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -149,6 +149,7 @@ pub fn run() { commands::agents::install_agent, commands::agents::uninstall_agent, commands::agents::check_jre_installed, + commands::agents::uninstall_jre, commands::agents::reinstall_jre, commands::agents::invalidate_agent_registry_cache, ]) diff --git a/src/components/config/DriverStoreDialog.vue b/src/components/config/DriverStoreDialog.vue index fa42ae9fe..8f0745c0d 100644 --- a/src/components/config/DriverStoreDialog.vue +++ b/src/components/config/DriverStoreDialog.vue @@ -29,6 +29,8 @@ interface AgentDriverInfo { installed: boolean; installed_version: string | null; update_available: boolean; + jre: string; + jre_installed: boolean; } interface InstallProgress { @@ -38,14 +40,25 @@ interface InstallProgress { } const drivers = ref([]); -const jreInstalled = ref(false); const installing = ref(null); -const reinstallingJre = ref(false); +const reinstallingJre = ref(null); const refreshing = ref(false); const progress = ref(null); let unlisten: UnlistenFn | null = null; +const installedJres = computed(() => { + const jreMap = new Map(); + for (const d of drivers.value) { + if (!jreMap.has(d.jre)) { + jreMap.set(d.jre, d.jre_installed); + } + } + return [...jreMap.entries()] + .map(([key, installed]) => ({ key, installed })) + .sort((a, b) => b.key.localeCompare(a.key)); +}); + const progressText = computed(() => { const p = progress.value; if (!p) return ""; @@ -65,7 +78,6 @@ const progressPercent = computed(() => { }); async function refreshAgents() { - jreInstalled.value = await invoke("check_jre_installed"); drivers.value = await invoke("list_installed_agents"); } @@ -106,21 +118,31 @@ async function uninstallDriver(dbType: string) { } } -async function reinstallJre() { - reinstallingJre.value = true; +async function reinstallJre(jreKey: string) { + reinstallingJre.value = jreKey; progress.value = null; try { - await invoke("reinstall_jre"); + await invoke("reinstall_jre", { jreKey }); await refreshAgents(); - toast("JRE 重新安装成功"); + toast(`JRE ${jreKey} 重新安装成功`); } catch (e: any) { - toast(`JRE 重新安装失败: ${e}`); + toast(`JRE ${jreKey} 重新安装失败: ${e}`); } finally { - reinstallingJre.value = false; + reinstallingJre.value = null; progress.value = null; } } +async function uninstallJre(jreKey: string) { + try { + await invoke("uninstall_jre", { jreKey }); + await refreshAgents(); + toast(`JRE ${jreKey} 已卸载`); + } catch (e: any) { + toast(String(e)); + } +} + function formatSize(bytes: number): string { if (!bytes) return ""; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`; @@ -238,12 +260,7 @@ async function deleteJdbcDriver(path: string) { // ──────────── Lifecycle ──────────── onMounted(async () => { - const [jre, localDrivers] = await Promise.all([ - invoke("check_jre_installed"), - invoke("list_installed_agents_local"), - ]); - jreInstalled.value = jre; - drivers.value = localDrivers; + drivers.value = await invoke("list_installed_agents_local"); invoke("list_installed_agents").then((result) => { drivers.value = result; @@ -290,29 +307,43 @@ onUnmounted(() => { -
-
+
+
-
JRE 运行时
-

首次安装驱动时自动下载

+
JRE {{ jre.key }} 运行时
- 已安装 + 已安装 未安装 +
+
+
JRE 运行时
+

首次安装驱动时自动下载

+
@@ -340,6 +371,11 @@ onUnmounted(() => {
{{ driver.label }}
+ JRE {{ driver.jre }}