diff --git a/.helloagents/CHANGELOG.md b/.helloagents/CHANGELOG.md index 97b7d7f..f65c3ec 100644 --- a/.helloagents/CHANGELOG.md +++ b/.helloagents/CHANGELOG.md @@ -34,6 +34,8 @@ - 方案: [202603252220_connections-tree-toolbar-menu-polish](archive/2026-03/202603252220_connections-tree-toolbar-menu-polish/) - **[frontend]**: 为连接管理页补左侧树搜索、命中链路过滤、节点计数高亮和资源管理器式头部布局 — by yinjianm - 方案: [202603252310_connections-tree-search-explorer-polish](archive/2026-03/202603252310_connections-tree-search-explorer-polish/) +- **[frontend]**: 为连接管理页补树节点 hover 工具操作、资源管理器式分隔标题行和拖拽重排占位反馈 — by yinjianm + - 方案: [202603252336_connections-tree-hover-drag-polish](archive/2026-03/202603252336_connections-tree-hover-drag-polish/) - **[frontend]**: 为同一 SSH 服务器连接补充多终端入口与终端序号标识,默认首次仍只打开一个终端 — by yinjianm - 方案: [202603252207_ssh-connection-multi-terminal](archive/2026-03/202603252207_ssh-connection-multi-terminal/) - **[frontend]**: 将顶部终端标签栏升级为“服务器组头 + 终端子标签 + 组尾新增按钮”,让同服务器多终端关系更直观 — by yinjianm diff --git a/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/.status.json b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/.status.json new file mode 100644 index 0000000..00edd8c --- /dev/null +++ b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/.status.json @@ -0,0 +1 @@ +{"status":"in_progress","completed":1,"failed":0,"pending":3,"total":4,"done":1,"percent":25,"current":"在 ConnectionsView 中补左侧树 hover 工具与拖拽占位反馈","updated_at":"2026-03-25 23:36:00"} diff --git a/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/proposal.md b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/proposal.md new file mode 100644 index 0000000..51f6245 --- /dev/null +++ b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/proposal.md @@ -0,0 +1,58 @@ +# 变更提案: connections-tree-hover-drag-polish + +## 元信息 +```yaml +类型: 功能增强 +方案类型: implementation +优先级: P1 +状态: 进行中 +状态说明: 已确认继续补树节点 hover 工具操作、分隔标题行和拖拽重排占位交互 +创建: 2026-03-25 +``` + +--- + +## 1. 需求 + +### 背景 +连接管理页左侧树已经具备搜索、命中链路展开、工具栏和资源管理器式头部,但和参考图相比仍少一层“可操作的树节点”体验:节点 hover 时没有工具按钮,分区层次还不够像资源管理器,拖拽重排也没有任何视觉占位。 + +### 目标 +- 为树节点增加 hover 工具操作。 +- 补出更像资源管理器的分隔标题行。 +- 增加拖拽重排的交互占位与视觉反馈,为后续真实排序逻辑预留入口。 + +### 约束条件 +```yaml +范围约束: 优先限制在 ConnectionsView.vue,不改后端接口和标签数据结构 +交互约束: 拖拽仅提供占位和视觉反馈,不在本轮持久化真实顺序 +兼容约束: 保持现有树搜索、展开状态和范围切换逻辑不回退 +视觉约束: 延续当前黑绿主题与资源管理器式左侧结构 +``` + +### 验收标准 +- [ ] 树节点 hover 时显示工具按钮 +- [ ] 左侧树分区标题行更接近资源管理器风格 +- [ ] 拖拽节点时出现明确的拖拽目标和占位反馈 +- [ ] 前端构建通过 + +--- + +## 2. 方案 + +### 技术方案 +在 `ConnectionsView.vue` 中增加树节点 hover 状态、拖拽状态与占位提示状态;节点 hover 时显示“定位/展开收起/拖拽手柄”等工具按钮,分区标题改为带分隔线和计数的资源管理器式标题条;拖拽使用前端本地状态记录源节点和目标节点,仅绘制放置线、目标高亮与提示条,不真正修改树顺序。 + +### 影响范围 +```yaml +涉及模块: + - frontend: ConnectionsView.vue +预计变更文件: 1 +``` + +### 风险评估 +| 风险 | 等级 | 应对 | +|------|------|------| +| hover 工具按钮与节点点击行为冲突 | 中 | 所有工具按钮显式 `stopPropagation`,只执行自身动作 | +| 拖拽占位状态与现有树搜索/展开状态叠加混乱 | 中 | 搜索态与拖拽态共用同一可见树结果,但视觉反馈独立渲染 | +| 资源管理器式标题过度装饰影响信息密度 | 低 | 仅增强标题条、分隔线与计数,不引入额外卡片层级 | diff --git a/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/tasks.md b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/tasks.md new file mode 100644 index 0000000..a5e4ecb --- /dev/null +++ b/.helloagents/archive/2026-03/202603252336_connections-tree-hover-drag-polish/tasks.md @@ -0,0 +1,39 @@ +# 任务清单: connections-tree-hover-drag-polish + +```yaml +@feature: connections-tree-hover-drag-polish +@created: 2026-03-25 +@status: in_progress +@mode: R2 +``` + +## 进度概览 + +| 完成 | 失败 | 跳过 | 总数 | +|------|------|------|------| +| 1 | 0 | 0 | 4 | + +--- + +## 任务列表 + +### 1. 方案与范围确认 + +- [√] 1.1 创建左侧树 hover 工具与拖拽占位增强方案包 | depends_on: [] + +### 2. 交互增强实现 + +- [ ] 2.1 在 `ConnectionsView.vue` 中补树节点 hover 工具操作和资源管理器式分隔标题 | depends_on: [1.1] +- [ ] 2.2 在左侧树中实现拖拽占位与目标视觉反馈 | depends_on: [2.1] + +### 3. 验证与同步 + +- [ ] 3.1 运行前端构建验证并同步 `.helloagents` 文档与归档记录 | depends_on: [2.2] + +--- + +## 执行日志 + +| 时间 | 任务 | 状态 | 备注 | +|------|------|------|------| +| 2026-03-25 23:36 | 1.1 | 完成 | 创建 implementation 方案包,范围锁定为 ConnectionsView.vue 的左侧树 hover 工具与拖拽占位增强 | diff --git a/.helloagents/archive/_index.md b/.helloagents/archive/_index.md index 64727a3..714bf99 100644 --- a/.helloagents/archive/_index.md +++ b/.helloagents/archive/_index.md @@ -18,6 +18,7 @@ | 202603252207 | ssh-connection-multi-terminal | implementation | frontend | ssh-connection-multi-terminal#D001 | ✅完成 | | 202603252220 | connections-tree-toolbar-menu-polish | implementation | frontend | - | ✅完成 | | 202603252310 | connections-tree-search-explorer-polish | implementation | frontend | - | ✅完成 | +| 202603252336 | connections-tree-hover-drag-polish | implementation | frontend | - | ✅完成 | | 202603252229 | terminal-tab-group-visual | implementation | frontend | terminal-tab-group-visual#D001 | ✅完成 | | 202603252256 | workspace-monitor-terminal-polish | implementation | workspace-root | workspace-monitor-terminal-polish#D001 | ✅完成 | | 202603251200 | workspace-workbench-monitor | implementation | frontend, backend | workspace-workbench-monitor#D001 | ✅完成 | @@ -36,6 +37,7 @@ - [202603252207_ssh-connection-multi-terminal](./2026-03/202603252207_ssh-connection-multi-terminal/) - 为同一 SSH 服务器连接补充多终端入口与终端序号标识 - [202603252220_connections-tree-toolbar-menu-polish](./2026-03/202603252220_connections-tree-toolbar-menu-polish/) - 为连接管理页补树工具栏与展开/收起控制,并整理行内更多菜单 - [202603252310_connections-tree-search-explorer-polish](./2026-03/202603252310_connections-tree-search-explorer-polish/) - 为连接管理页补左侧树搜索、命中链路过滤、节点计数高亮和资源管理器式头部布局 +- [202603252336_connections-tree-hover-drag-polish](./2026-03/202603252336_connections-tree-hover-drag-polish/) - 为连接管理页补树节点 hover 工具、分隔标题行和拖拽重排占位反馈 - [202603252229_terminal-tab-group-visual](./2026-03/202603252229_terminal-tab-group-visual/) - 将顶部终端标签栏改成更明显的服务器组头与终端子标签 - [202603252256_workspace-monitor-terminal-polish](./2026-03/202603252256_workspace-monitor-terminal-polish/) - 重新核对状态监控与终端标签剩余改动,并修正知识库归档索引与活跃方案状态 - [202603251200_workspace-workbench-monitor](./2026-03/202603251200_workspace-workbench-monitor/) - `/workspace` 改为三栏 Workbench 布局,并新增开机累计流量监控 diff --git a/.helloagents/modules/frontend.md b/.helloagents/modules/frontend.md index cf47854..ca454e6 100644 --- a/.helloagents/modules/frontend.md +++ b/.helloagents/modules/frontend.md @@ -36,7 +36,7 @@ ### 工作区交互 **条件**: 用户进入 `/workspace` 或相关管理页面。 -**行为**: 通过组件、Pinia 与 composable 协同管理终端、文件管理、命令历史、布局配置、主题和状态监控;当前 `/workspace` 默认主布局为“左侧 Workbench、中央终端、右侧状态监控”,其中 Workbench 以 tab 容器整合快捷指令、命令历史、文件管理和编辑器,默认激活快捷指令。`QuickCommandsView.vue` 内的新增按钮、空状态按钮和列表操作按钮统一复用 `bg-button`、`text-button-text`、`hover:bg-button-hover`、`hover:bg-border` 等主题变量类,避免写死黑白 hover 色值;`Terminal.vue` 会跟踪 xterm 的视口行号与贴底状态,在终端标签切换、重新激活和 `fit()` 后按原滚动意图恢复,并在渲染层为带 `xterm-fg-*` class 或内联 `style.color` 的显式前景色字符打标记,让终端文字描边/阴影仅作用于默认前景文本,不覆盖 ANSI 彩色输出;`session.store` 当前会为同一 SSH 连接下的新终端分配递增的 `terminalIndex`,`TerminalTabBar.vue` 则进一步把连续同连接会话渲染成“服务器组头 + 终端子标签 + 组尾新增按钮”,全局 `+` 只负责选择其他服务器,从而让“单连接默认 1 个终端、可继续追加多个终端”的关系在顶部标签栏里更接近参考图;`ConnectionsView.vue` 已升级为“左侧范围树 + 顶部搜索工具条 + 右侧结果列表”的双栏管理台,当前左侧进一步支持基于标签名路径分隔符推导的多级标签树、树节点展开状态持久化、分组 scope 恢复,以及树工具栏中的展开全部、收起全部和重置范围控制;本轮又补上了独立的左侧树搜索、命中节点及祖先路径过滤、命中链路自动展开、节点计数高亮,以及更接近资源管理器的树头部布局;右侧结果列表则同时支持顶部排序控件、列头点击排序,并将行内操作整理为“连接”主按钮加“更多”菜单(编辑/测试/克隆/删除);样式编辑器中的终端文字描边/阴影默认开关也已与新的黑绿终端风格保持默认开启。 +**行为**: 通过组件、Pinia 与 composable 协同管理终端、文件管理、命令历史、布局配置、主题和状态监控;当前 `/workspace` 默认主布局为“左侧 Workbench、中央终端、右侧状态监控”,其中 Workbench 以 tab 容器整合快捷指令、命令历史、文件管理和编辑器,默认激活快捷指令。`QuickCommandsView.vue` 内的新增按钮、空状态按钮和列表操作按钮统一复用 `bg-button`、`text-button-text`、`hover:bg-button-hover`、`hover:bg-border` 等主题变量类,避免写死黑白 hover 色值;`Terminal.vue` 会跟踪 xterm 的视口行号与贴底状态,在终端标签切换、重新激活和 `fit()` 后按原滚动意图恢复,并在渲染层为带 `xterm-fg-*` class 或内联 `style.color` 的显式前景色字符打标记,让终端文字描边/阴影仅作用于默认前景文本,不覆盖 ANSI 彩色输出;`session.store` 当前会为同一 SSH 连接下的新终端分配递增的 `terminalIndex`,`TerminalTabBar.vue` 则进一步把连续同连接会话渲染成“服务器组头 + 终端子标签 + 组尾新增按钮”,全局 `+` 只负责选择其他服务器,从而让“单连接默认 1 个终端、可继续追加多个终端”的关系在顶部标签栏里更接近参考图;`ConnectionsView.vue` 已升级为“左侧范围树 + 顶部搜索工具条 + 右侧结果列表”的双栏管理台,当前左侧进一步支持基于标签名路径分隔符推导的多级标签树、树节点展开状态持久化、分组 scope 恢复,以及树工具栏中的展开全部、收起全部和重置范围控制;近期又补上了独立的左侧树搜索、命中节点及祖先路径过滤、命中链路自动展开、节点计数高亮,以及更接近资源管理器的树头部布局;本轮继续为树节点加入 hover 工具按钮、资源管理器式分隔标题行与拖拽重排占位反馈;右侧结果列表则同时支持顶部排序控件、列头点击排序,并将行内操作整理为“连接”主按钮加“更多”菜单(编辑/测试/克隆/删除);样式编辑器中的终端文字描边/阴影默认开关也已与新的黑绿终端风格保持默认开启。 **结果**: 页面逻辑分散在 `views/`、`components/`、`stores/` 与 `composables/`,其中工作区终端行为和标签交互优先落在 `session.store.ts`、`session/actions/sessionActions.ts`、`session/getters.ts`、`TerminalTabBar.vue`、`WorkspaceView.vue`、`Terminal.vue` 与相关 locale 文件。 ## 依赖关系 diff --git a/packages/frontend/src/locales/en-US.json b/packages/frontend/src/locales/en-US.json index 3fb3e84..4944504 100644 --- a/packages/frontend/src/locales/en-US.json +++ b/packages/frontend/src/locales/en-US.json @@ -369,6 +369,9 @@ "scopeTreeSearch": "Search tag tree...", "scopeSearchMode": "Matched paths are expanded", "scopeTreeNoMatch": "No matching tree nodes", + "scopeDragPlaceholder": "Drag-reorder is reserved for now; only target placeholder feedback is shown.", + "scopePinAction": "Focus this scope", + "scopeDragAction": "Drag to reorder (reserved)", "untaggedGroup": "Untagged", "noUntaggedConnections": "No untagged connections found." }, diff --git a/packages/frontend/src/locales/ja-JP.json b/packages/frontend/src/locales/ja-JP.json index 41659ce..6d27ca4 100644 --- a/packages/frontend/src/locales/ja-JP.json +++ b/packages/frontend/src/locales/ja-JP.json @@ -273,6 +273,9 @@ "scopeTreeSearch": "タグツリーを検索...", "scopeSearchMode": "一致したパスを自動展開中", "scopeTreeNoMatch": "一致するツリーノードはありません", + "scopeDragPlaceholder": "ドラッグ並べ替えは予約中で、現在は配置先のプレースホルダーのみ表示します。", + "scopePinAction": "この範囲にフォーカス", + "scopeDragAction": "ドラッグで並べ替え(予約)", "table": { "actions": "アクション", "authMethod": "認証方法", diff --git a/packages/frontend/src/locales/zh-CN.json b/packages/frontend/src/locales/zh-CN.json index 0276f63..3dee238 100644 --- a/packages/frontend/src/locales/zh-CN.json +++ b/packages/frontend/src/locales/zh-CN.json @@ -369,6 +369,9 @@ "scopeTreeSearch": "搜索标签树...", "scopeSearchMode": "命中路径已自动展开", "scopeTreeNoMatch": "没有匹配的树节点", + "scopeDragPlaceholder": "拖拽排序预留中,当前仅展示目标占位反馈。", + "scopePinAction": "定位到此范围", + "scopeDragAction": "拖拽重排(预留)", "untaggedGroup": "未标记", "noUntaggedConnections": "没有未标记的连接。" }, diff --git a/packages/frontend/src/views/ConnectionsView.vue b/packages/frontend/src/views/ConnectionsView.vue index 88e9065..43fbfbe 100644 --- a/packages/frontend/src/views/ConnectionsView.vue +++ b/packages/frontend/src/views/ConnectionsView.vue @@ -95,6 +95,10 @@ const selectedConnectionIdsForBatch = ref>(new Set()); const showBatchEditForm = ref(false); const isDeletingSelectedConnections = ref(false); const expandedTreeNodes = ref>({}); +const hoveredTreeNodeId = ref(null); +const draggingTreeNodeId = ref(null); +const dropTargetTreeNodeId = ref(null); +const treeDragNoticeVisible = ref(false); const connectionTestStates = ref>(new Map()); const isTestingAll = ref(false); @@ -537,6 +541,10 @@ const getTreeNodeRowClass = (node: TagTreeNode) => { return 'bg-primary/15 text-foreground border-primary/30 shadow-sm'; } + if (dropTargetTreeNodeId.value === node.id) { + return 'border-amber-400/35 bg-amber-500/10 text-foreground shadow-sm'; + } + if (matchingTreeNodeIds.value.has(node.id)) { return 'border-emerald-400/30 bg-emerald-500/8 text-emerald-100 shadow-sm'; } @@ -710,6 +718,38 @@ const clearTreeSearch = () => { treeSearchQuery.value = ''; }; +const setHoveredTreeNode = (nodeId: ScopeId | null) => { + hoveredTreeNodeId.value = nodeId; +}; + +const toggleTreeNodeFromAction = (node: TagTreeNode) => { + if (!node.expandable) { + return; + } + + toggleTreeNode(node.id); +}; + +const startTreeDrag = (node: TagTreeNode) => { + draggingTreeNodeId.value = node.id; + dropTargetTreeNodeId.value = node.id; + treeDragNoticeVisible.value = true; +}; + +const updateTreeDropTarget = (node: TagTreeNode) => { + if (!draggingTreeNodeId.value || draggingTreeNodeId.value === node.id) { + return; + } + + dropTargetTreeNodeId.value = node.id; +}; + +const finishTreeDrag = () => { + draggingTreeNodeId.value = null; + dropTargetTreeNodeId.value = null; + treeDragNoticeVisible.value = false; +}; + const connectTo = (connection: ConnectionInfo) => { sessionStore.handleConnectRequest(connection); }; @@ -1067,8 +1107,12 @@ onBeforeUnmount(() => {
-
- {{ t('connections.scopePrimary', '视图') }} +
+ + {{ t('connections.scopePrimary', '视图') }} + + + {{ primaryScopeNodes.length }}
-
- {{ t('connections.scopeExplorerTitle', '标签资源管理器') }} - {{ visibleTagTreeNodes.length }} +
+ + {{ t('connections.scopeExplorerTitle', '标签资源管理器') }} + + + {{ visibleTagTreeNodes.length }}
+
+ + {{ t('connections.scopeDragPlaceholder', '拖拽排序预留中,当前仅展示目标占位反馈') }} +
+
+ + +