同步完整源码至远程:扁平化重构现状 + 未入库源文件
- 补入库:server/internal/db/dump.go、redis 分页/扫描预算测试、opsxdb-mcp main_test、 packages/opsxdb-mcp package-lock、docs 审计与对比文档等 37 个新文件 - 含结构扁平化进行中的 80 处修改与 155 处旧结构删除(server/ src/ src-tauri/ 为当前有效源) - 构建产物(bin/target/dist)与签名私钥仍按规则排除
This commit is contained in:
1 parent
5c0be49217
commit
2c0bfafd8d
269 files changed
+10372
-16435
No files matched your search
+60
-52
@@ -1,10 +1,12 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { closeSession } from "./api";
|
||||
import { closeSession, openSession } from "./api";
|
||||
import { driverById } from "./catalog";
|
||||
import { askInput } from "./dialogs";
|
||||
import { DriverIcon } from "./DriverIcon";
|
||||
import { ObjectTree } from "./ObjectTree";
|
||||
import { ContextMenu } from "./ContextMenu";
|
||||
import { TreeChevron } from "./TreeChevron";
|
||||
import { connectionEndpoint, connectionUri } from "./contextActions";
|
||||
import {
|
||||
DEFAULT_CONN_GROUP,
|
||||
useWorkspaceStore,
|
||||
@@ -34,7 +36,10 @@ export function ConnectionSidebar({
|
||||
const moveConnection = useWorkspaceStore((s) => s.moveConnection);
|
||||
const toggleConnGroup = useWorkspaceStore((s) => s.toggleConnGroup);
|
||||
const notify = useWorkspaceStore((s) => s.notify);
|
||||
const notifyError = useWorkspaceStore((s) => s.notifyError);
|
||||
const editConnection = useWorkspaceStore((s) => s.editConnection);
|
||||
const connState = useWorkspaceStore((s) => s.connState);
|
||||
const set = useWorkspaceStore((s) => s.set);
|
||||
|
||||
const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number; conn: SavedConnection } | null>(null);
|
||||
/** 断开连接:关会话 + 清树 + 清激活 */
|
||||
@@ -51,6 +56,26 @@ export function ConnectionSidebar({
|
||||
st.set("connState", "down");
|
||||
st.set("status", `已断开 ${c.name}`);
|
||||
}
|
||||
notify({ kind: "warning", title: "已断开", message: c.name, mode: "toast", durationMs: 1800 });
|
||||
};
|
||||
|
||||
const reconnect = async (c: SavedConnection) => {
|
||||
set("connState", "reconnecting");
|
||||
set("status", "重连中…");
|
||||
try {
|
||||
useWorkspaceStore.getState().setSession(c.id, null);
|
||||
const { sessionId } = await openSession(c);
|
||||
useWorkspaceStore.getState().setSession(c.id, sessionId);
|
||||
useWorkspaceStore.getState().selectConnection(c.id);
|
||||
set("connState", "ok");
|
||||
set("status", `已重连 ${c.name}` + (c.database ? ` · ${c.database}` : ""));
|
||||
notify({ kind: "success", title: "重连成功", message: c.name, mode: "toast", durationMs: 1600 });
|
||||
} catch (e) {
|
||||
set("connState", "down");
|
||||
const msg = e instanceof Error ? e.message : String(e);
|
||||
set("status", `重连失败:${msg}`);
|
||||
notifyError(e, "modal");
|
||||
}
|
||||
};
|
||||
|
||||
const [dragId, setDragId] = useState<string | null>(null);
|
||||
@@ -122,7 +147,7 @@ export function ConnectionSidebar({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex shrink-0 flex-col">
|
||||
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="flex items-center justify-between px-1.5 py-1 text-[11px]" style={{ color: "var(--ops-muted)" }}>
|
||||
<span>连接</span>
|
||||
<button type="button" className="hover:underline" style={{ color: "var(--ops-accent)" }} onClick={onAddGroup} title="新建分组">
|
||||
@@ -255,16 +280,36 @@ export function ConnectionSidebar({
|
||||
<span className="h-3 w-1 shrink-0 rounded-sm" style={{ background: c.color }} />
|
||||
)}
|
||||
<DriverIcon driver={c.driver} size={14} />
|
||||
<span className="min-w-0 truncate" title={`${driverById(c.driver)?.name ?? c.driver} · ${c.name}`}>
|
||||
{c.name}
|
||||
<span className="min-w-0 flex-1 truncate" title={`${driverById(c.driver)?.name ?? c.driver} · ${c.name} · ${connectionEndpoint(c)}`}>
|
||||
<span className="truncate">{c.name}</span>
|
||||
{(c.host || c.redisNodes || c.database) && (
|
||||
<span className="ml-1 text-[10px] opacity-45">
|
||||
{c.host || c.redisNodes ? connectionEndpoint(c) : c.database}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span
|
||||
className="ml-1 h-1.5 w-1.5 shrink-0 rounded-full"
|
||||
style={{
|
||||
background: activeId === c.id ? '#22c55e' : 'var(--ops-muted)',
|
||||
background:
|
||||
activeId === c.id
|
||||
? connState === "down"
|
||||
? "var(--ops-danger)"
|
||||
: connState === "reconnecting"
|
||||
? "var(--ops-warning)"
|
||||
: "#22c55e"
|
||||
: "var(--ops-muted)",
|
||||
opacity: activeId === c.id ? 1 : 0.4,
|
||||
}}
|
||||
title={activeId === c.id ? '已连接' : '未激活'}
|
||||
title={
|
||||
activeId === c.id
|
||||
? connState === "down"
|
||||
? "已断开"
|
||||
: connState === "reconnecting"
|
||||
? "重连中…"
|
||||
: "已连接"
|
||||
: "未激活"
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
@@ -298,52 +343,15 @@ export function ConnectionSidebar({
|
||||
})}
|
||||
</div>
|
||||
|
||||
{ctxMenu && (
|
||||
<div
|
||||
className="ops-ctx"
|
||||
style={{ position: "fixed", left: ctxMenu.x, top: ctxMenu.y, zIndex: 1000 }}
|
||||
>
|
||||
{activeId === ctxMenu.conn.id && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
disconnect(ctxMenu.conn);
|
||||
setCtxMenu(null);
|
||||
}}
|
||||
>
|
||||
断开连接
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onSelect(ctxMenu.conn.id);
|
||||
setCtxMenu(null);
|
||||
}}
|
||||
>
|
||||
连接
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
editConnection(ctxMenu.conn);
|
||||
setCtxMenu(null);
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
style={{ color: "var(--ops-danger)" }}
|
||||
onClick={() => {
|
||||
onDelete(ctxMenu.conn.id);
|
||||
setCtxMenu(null);
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{ctxMenu && <ContextMenu x={ctxMenu.x} y={ctxMenu.y} title={ctxMenu.conn.name} onClose={() => setCtxMenu(null)} items={[
|
||||
{ label: "连接", hidden: activeId === ctxMenu.conn.id, action: () => onSelect(ctxMenu.conn.id) },
|
||||
{ label: "断开连接", hidden: activeId !== ctxMenu.conn.id, action: () => disconnect(ctxMenu.conn) },
|
||||
{ label: "重新连接", action: () => void reconnect(ctxMenu.conn) },
|
||||
{ label: "编辑连接…", action: () => editConnection(ctxMenu.conn) },
|
||||
{ label: "复制连接地址(无凭据)", separator: true, action: () => { void navigator.clipboard.writeText(connectionUri(ctxMenu.conn)).catch((e) => notifyError(e, "toast")); } },
|
||||
{ label: "复制主机端口", action: () => { void navigator.clipboard.writeText(connectionEndpoint(ctxMenu.conn)).catch((e) => notifyError(e, "toast")); } },
|
||||
{ label: "删除连接…", separator: true, danger: true, action: () => onDelete(ctxMenu.conn.id) },
|
||||
]} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user