import { useEffect, useRef, useState } from "react"; import { driverImportOffline, driverInstall, driverStatus, type DriverStatusItem } from "./api"; import { driverById } from "./catalog"; import { DriverIcon } from "./DriverIcon"; import { OpsModal } from "./OpsModal"; import { useWorkspaceStore } from "./store"; const LABELS: Record = { mongodb: "MongoDB", zookeeper: "ZooKeeper", dameng: "达梦 DM8", }; function fmtSize(n: number): string { if (n >= 1 << 20) return `${(n / (1 << 20)).toFixed(1)} MB`; if (n >= 1 << 10) return `${(n / (1 << 10)).toFixed(0)} KB`; return `${n} B`; } /** * 驱动管理弹框:agent 驱动(MongoDB / ZooKeeper / 达梦)的运行时状态与维护入口。 * 在线环境首次连接会自动下载;这里提供预装、离线包导入与商用 jar 指引。 */ export function DriverManager({ onClose }: { onClose: () => void }) { const notify = useWorkspaceStore((s) => s.notify); const notifyError = useWorkspaceStore((s) => s.notifyError); const [items, setItems] = useState(null); const [busy, setBusy] = useState(null); const fileRef = useRef(null); const reload = async () => { try { setItems(await driverStatus()); } catch (e) { notifyError(e, "toast"); } }; useEffect(() => { void reload(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const install = async (id: string) => { setBusy(id); try { const r = await driverInstall(id); if (r.drivers) setItems(r.drivers); if (r.ok) { notify({ kind: "success", title: "安装完成", message: `${LABELS[id] ?? id} 驱动已就绪`, mode: "toast" }); } else { notify({ kind: "error", title: "安装失败", message: r.error ?? "未知错误", mode: "modal" }); } } catch (e) { notifyError(e, "modal"); } finally { setBusy(null); } }; const importZip = async (f: File) => { setBusy("import"); try { const r = await driverImportOffline(f); if (r.drivers) setItems(r.drivers); if (r.ok) { notify({ kind: "success", title: "导入完成", message: `已导入 ${r.imported} 个文件`, mode: "toast" }); } else { notify({ kind: "error", title: "导入失败", message: r.error ?? "包校验失败", mode: "modal" }); } } catch (e) { notifyError(e, "modal"); } finally { setBusy(null); if (fileRef.current) fileRef.current.value = ""; } }; const jdk = items?.find((x) => x.jdkRequired); return (
{/* 环境状态行 */}
JVM: {jdk?.jdkOk ? ( 已检测到 Java {jdk.javaVersion} ) : ( 未找到 Java(agent 驱动需 JDK 17+) )} · agent: {items?.[0]?.agentInstalled ? "已安装" : "缺失(连接时自动下载)"}
{/* 驱动行 */} {items === null &&
加载中…
} {items?.map((d) => { const done = d.allInstalled; const badge = !d.jdkOk ? { t: "缺 JDK", c: "var(--ops-danger)" } : done ? { t: "已安装", c: "var(--ops-accent)" } : d.license === "proprietary" ? { t: "需自备 jar", c: "var(--ops-warning)" } : { t: "未安装", c: "var(--ops-muted)" }; const total = d.jars.reduce((s, j) => s + (j.size || 0), 0); const got = d.jars.filter((j) => j.installed).length; return (
{LABELS[d.id] ?? d.label} {badge.t}
{d.license === "proprietary" ? "商用许可不代下载:把官方 DmJdbcDriver jar 放到 ~/.opsxdb/drivers/dameng/" : d.jars.length > 0 ? `驱动 jar ${got}/${d.jars.length}${total > 0 ? ` · ${fmtSize(total)}` : ""}${d.autoFetch ? " · 连接时自动下载" : ""}` : "—"}
{d.autoFetch && !done && d.jdkOk && ( )}
); })} {/* 离线包导入 */}
内网/离线: (opsxdb-driver 仓库 pack.sh 产物 .zip) { const f = e.target.files?.[0]; if (f) void importZip(f); }} />
); }