# 变更提案: terminal-group-and-broadcast-dedupe ## 元信息 ```yaml 类型: 功能增强 方案类型: implementation 优先级: P1 状态: 实施中 状态说明: 代码改动已完成,前端全量构建被现有 ConnectionsView.vue 重复属性错误阻塞 创建: 2026-03-25 ``` --- ## 1. 需求 ### 背景 当前顶部终端标签栏已经有“服务器组头 + 终端子标签”的雏形,但同一服务器新增终端后仍会按全局尾部插入,导致不同服务器之间组关系错乱。另外,`快捷指令` 和 `命令历史` 的“发送到全部会话”仍按终端实例广播,同一服务器有多个终端时会重复执行。 ### 目标 - 把服务器组头做成更稳定的胶囊式 tab group,组头固定、子标签更紧凑、激活组整块高亮。 - 修复多服务器并行使用时的“新增终端乱插组”问题,确保新终端始终插入到所属服务器组尾部。 - 将 `快捷指令` 与 `命令历史` 的“发送到全部会话”统一改成“每台服务器只执行一次”。 ### 约束条件 ```yaml 范围约束: 只改前端终端标签栏、session 顺序维护和两处广播入口,不改后端协议 排序约束: 继续复用 localStorage 中的 sessionOrder,但允许在新增同组终端时做定向插入 广播约束: 每个 connectionId 最多选择一个已连接 SSH 终端,避免重复执行 兼容约束: RDP/VNC 不参与组内新增终端,也不参与 SSH 广播去重逻辑 ``` ### 验收标准 - [ ] 多台服务器并行打开时,为某台服务器新增终端会稳定插入到该服务器组尾部 - [ ] 顶部标签栏具备更明显的“胶囊分组”视觉,激活组有整块高亮关系 - [ ] `快捷指令` 与 `命令历史` 的“发送到全部会话”都按服务器去重,只执行一次 - [ ] 前端构建通过 --- ## 2. 方案 ### 技术方案 在 `sessionActions.ts` 中新增针对 `sessionOrder` 的组内插入逻辑:为某连接创建新终端时,优先把新 `sessionId` 插到同连接最后一个 session 的后面,而不是简单追加到尾部。`TerminalTabBar.vue` 则继续利用连续同 `connectionId` 的会话数组,在组头、子标签和组尾按钮三层上补更强的胶囊边界和激活组高亮。`QuickCommandsView.vue` 与 `CommandHistoryView.vue` 共享一套“按 connectionId 选取代表会话”的广播去重策略,只对每台服务器选择一个已连接 SSH 终端发送指令。 ### 影响范围 ```yaml 涉及模块: - frontend: session/actions/sessionActions.ts, TerminalTabBar.vue, QuickCommandsView.vue, CommandHistoryView.vue, locales 预计变更文件: 5-7 ``` ### 风险评估 | 风险 | 等级 | 应对 | |------|------|------| | sessionOrder 定向插入与拖拽排序持久化冲突 | 中 | 只在“新增同组终端”时做最小插入,不改已有排序语义 | | 广播去重选错终端,导致发到非激活或异常会话 | 低 | 只从已连接 SSH 会话中选择每个 connectionId 的首个代表 | | 胶囊分组视觉过重影响移动端 | 低 | 保持结构复用,移动端沿用同逻辑但不额外堆复杂控件 | --- ## 3. 技术决策 ### terminal-group-and-broadcast-dedupe#D001: 新终端按 connectionId 插回组尾,广播按 connectionId 去重 **日期**: 2026-03-25 **状态**: ✅采纳 **决策**: 会话仍保持独立 `sessionId`,但新增同服务器终端时要把其 `sessionId` 插入到该连接组尾部;批量发送场景统一按 `connectionId` 选择代表会话。 **理由**: 问题本质是展示顺序和广播粒度,而不是底层 SSH 能力。按连接做最小排序修正和广播去重,能解决“乱加”和“重复执行”两个核心问题,而且改动边界清晰。 **影响**: 影响 `sessionOrder` 维护逻辑、顶部标签栏分组样式,以及 `快捷指令` / `命令历史` 两个广播入口。