Files
yinjianm 8c130adcc9 feat(workspace): add cpu core status display and safer quick command actions
Expose `cpuCores` in backend status collection with multi-command fallback
and surface it in the status panel as a localized CPU core badge under the
CPU model.

Adjust terminal group UX by adding a server-level close-all control in the
SSH tab group header.

Reduce accidental quick command execution by switching list interaction to
single-click select + double-click execute, while preserving keyboard Enter
and context-menu execution paths.
2026-04-12 07:22:09 +08:00

6.8 KiB

变更提案: ssh-group-close-and-script-input-sanitize

元信息

类型: 功能增强
方案类型: implementation
优先级: P1
状态: 实施中
创建: 2026-04-12

1. 需求

背景

当前工作区顶部终端标签栏已经把 SSH 会话聚合为“服务器组头”,但组头本身只能切换,不能像单个终端标签那样直接关闭。用户希望在服务器组头上也能出现一个关闭入口,并且点击后一次关闭该服务器下的全部终端,避免逐个点子标签关闭。同时,“添加新连接”的脚本模式虽然已经支持空格、空行和 Markdown 围栏清洗,但脚本值仍只会去掉双引号,像 -p '$Moka1998A' 这样的单引号包裹密码会被原样保存,导致实际密码多出 '

目标

  • TerminalTabBar.vue 的 SSH 服务器组头中加入一个独立的关闭按钮,点击后关闭该服务器下全部终端。
  • 保持现有“组头切服务器、组内终端在次级标签条管理”的交互模式,不改后端协议和会话模型。
  • 修正脚本模式参数解析,对单引号和双引号包裹值统一去壳,让密码、代理名、标签、备注等字段都落成真实值。

约束条件

范围约束: 仅改前端工作区终端标签栏、脚本模式解析链路和相关文案,不改后端 API
交互约束: 服务器组头的主点击行为仍然是激活该服务器,不让新增关闭按钮抢占原有点击语义
兼容性约束: 非 SSH 的 RDP/VNC 顶层标签保持现状;脚本模式已有的空格、空行和 Markdown 围栏清洗继续保留
数据约束: 仅移除成对包裹值的外层引号,不修改值内部合法字符

验收标准

  • SSH 服务器组头出现可见的关闭按钮,点击后能关闭该服务器下全部终端
  • 组头关闭按钮不会误触发组头本身的激活切换,单个终端标签关闭行为保持不变
  • 脚本模式导入 -p '$Moka1998A' 时,实际保存的密码是 $Moka1998A 而不是带 '
  • packages/frontend 的构建校验通过

2. 方案

技术方案

沿用现有 TerminalTabBar.vue 对 SSH 会话按 connectionId 聚合的结果,在服务器组头按钮内部增加一个次级 X 按钮。该按钮通过本地分组会话列表拿到当前服务器的所有 sessionId,逐个复用已有的 session:close 事件链路关闭,避免引入新的后端或 store 协议。视觉上保持现有“服务器组头胶囊 + 终端子标签”的样式语言,只在 hover 和激活态补充关闭入口。

脚本模式解析继续保留在 useAddConnectionForm.ts 中处理,新增统一的“去掉成对包裹引号”辅助逻辑,并将参数切分从“只识别双引号”扩展为“同时识别单引号和双引号”。这样 -p '$Moka1998A'-proxy 'ssh 1'-note 'foo bar' 等值都能保留真实内容而不带外层引号。

影响范围

涉及模块:
  - frontend: TerminalTabBar.vue 的 SSH 组头按钮与关闭交互
  - frontend: useAddConnectionForm.ts 的脚本模式参数切分与值清洗
  - frontend: locales 文案(组头关闭提示)
预计变更文件: 5-6

风险评估

风险 等级 应对
组头关闭按钮触发冒泡,误切到服务器而不是关闭整组 在关闭按钮处理器中显式 stopPropagation() / preventDefault()
批量关闭同组终端时,本地分组列表在关闭过程中变化导致遗漏 先基于当前分组生成 sessionId 快照,再逐个发送关闭事件
单引号解析过宽,误删值内部字符 只去掉首尾成对且同类型的包裹引号,不处理内部字符

3. 核心场景

场景: 关闭某台服务器下的全部终端

模块: frontend / TerminalTabBar 条件: 当前连接类型为 SSH,且同一 connectionId 下存在 1 个或以上终端 行为: 用户点击服务器组头右侧的关闭按钮,组件基于当前分组会话快照逐个发出既有 session:close 事件 结果: 该服务器下的全部终端标签被关闭,其他服务器标签保持不变

场景: 脚本模式导入带单引号的密码

模块: frontend / useAddConnectionForm 条件: 用户在脚本模式中输入 -p '$Moka1998A' 这类带单引号包裹的参数值 行为: 解析阶段按单引号/双引号感知切分参数,并在取值时移除成对外层引号 结果: 提交给后端的密码值为 $Moka1998A,不会附带 '


4. 技术决策

本方案涉及的技术决策,归档后成为决策的唯一完整记录

ssh-group-close-and-script-input-sanitize#D001: 组头关闭复用现有单会话关闭链路,脚本值统一做外层引号去壳

日期: 2026-04-12 状态: 采纳 背景: 本次需求是现有前端交互增强,不需要改变后端会话协议,但要确保“整组关闭”和“脚本值去壳”都尽量复用既有链路,避免引入新的状态分叉。 选项分析:

选项 优点 缺点
A: 组头关闭复用现有 session:close 事件,脚本值统一做外层引号去壳 改动边界小,直接复用现有关闭和提交流程,风险低 组头关闭是逐个关闭,不是单事件批量关闭
B: 新增“按 connectionId 批量关闭”专用事件,并重写脚本解析器 语义更集中,理论上更便于后续扩展 需要扩展事件协议,改动面更大,超出这次需求边界
决策: 选择方案 A
理由: 当前需求聚焦前端交互与输入清洗,复用既有关闭链路与表单提交链路更符合“保守修改”和最小影响原则。
影响: 影响 TerminalTabBar.vueuseAddConnectionForm.ts 及相关 locale 文案。

5. 成果设计

设计方向

  • 美学基调: 延续现有终端标签栏的黑绿运维胶囊风格,不新增跳脱视觉体系的新按钮样式
  • 记忆点: 服务器组头在保持整块高亮的同时,hover 后能露出一个紧贴右侧的整组关闭入口
  • 参考: 现有 TerminalTabBar.vue 的服务器组头与子标签胶囊风格

视觉要素

  • 配色: 沿用组头当前 border-primary/60 + bg-primary/10 激活色系,关闭按钮 hover 时使用 bg-header / text-foreground
  • 字体: 延续当前标签栏字号体系,不引入额外字体变化
  • 布局: 关闭按钮嵌在服务器组头右侧,避免破坏左侧 server icon + 名称 + 计数的既有结构
  • 动效: 延续现有 150ms 渐隐渐显,关闭按钮默认隐藏,hover 组头时显现
  • 氛围: 保持当前运维面板风格,不追加新纹理或装饰

技术约束

  • 可访问性: 关闭按钮保留独立 title,避免只靠图标表达语义
  • 响应式: 继续兼容现有移动端/桌面端标签栏高度,不新增超出标签高度的控件