feat(status-monitor): add websocket process manager and runtime metadata

extend server status payload with timezone, uptime, and process summary so
the monitor sidebar can show richer at-a-glance host context.

introduce process:list and process:signal websocket flows on active SSH
sessions, enabling on-demand process querying and terminate/kill actions
without adding new HTTP endpoints.

add a dedicated process manager modal in the frontend with search, refresh,
auto-refresh, and per-process actions, and wire localized labels for both
english and chinese.

enhance global connection fuzzy search scoring to include tag names as
secondary-weight fields while preserving primary host/name relevance.
This commit is contained in:
yinjianm
2026-04-15 22:21:26 +08:00
parent 154bb7ee60
commit 9b45ad77e5
21 changed files with 1701 additions and 16 deletions
+8
View File
@@ -2,6 +2,14 @@
## [Unreleased]
- **[frontend]**: 将右侧状态监控继续收紧为更贴近服务器小屏的默认概览,并新增时区、运行时间、进程概览与“查看全部”独立进程管理弹窗 — by yinjianm
- 方案: [202604152147_status-monitor-process-manager-modal](archive/2026-04/202604152147_status-monitor-process-manager-modal/)
- **[backend]**: 扩展状态监控采集时区、运行时间和轻量进程摘要,并为当前 SSH 会话新增 `process:list` / `process:signal` WebSocket 进程管理消息 — by yinjianm
- 方案: [202604152147_status-monitor-process-manager-modal](archive/2026-04/202604152147_status-monitor-process-manager-modal/)
- **[frontend]**: 让全局服务器检索将标签名纳入本地模糊搜索评分,并保持标签匹配权重低于名称和主机、高于类型 - by yinjianm
- 方案: [202604152139_workspace-global-search-tag-fuzzy-search](archive/2026-04/202604152139_workspace-global-search-tag-fuzzy-search/)
- **[frontend]**: 将工作区状态监控重构为更接近服务器监控小屏的深色响应式面板,统一头部信息条、资源监控条、内存/网络/磁盘卡片及 CPU/网络趋势图风格 — by yinjianm
- 方案: [202604152109_status-monitor-responsive-remodel](archive/2026-04/202604152109_status-monitor-responsive-remodel/)
@@ -0,0 +1 @@
{"status":"completed","completed":4,"failed":0,"pending":0,"total":4,"done":4,"percent":100,"current":"Completed - tag names now participate in global connection fuzzy search","updated_at":"2026-04-15 21:44:00"}
@@ -0,0 +1,117 @@
# 变更提案: workspace-global-search-tag-fuzzy-search
## 元信息
```yaml
类型: 优化
方案类型: implementation
优先级: P2
状态: 草稿
创建: 2026-04-15
```
---
## 1. 需求
### 背景
“全局服务器检索”已经支持在结果卡片中显示服务器标签,但当前模糊搜索只对连接名称、主机、用户名和类型做评分,用户通过标签组织环境或用途时,仍然无法直接按标签词搜索到目标服务器。
### 目标
- 让服务器标签名也参与全局模糊搜索。
- 保持当前排序主次关系,其中标签匹配权重低于服务器名称和主机,高于类型。
- 尽量局部改动,只影响全局服务器检索及其搜索工具函数。
### 约束条件
```yaml
时间约束: 本轮内完成搜索权重调整与基础验证
性能约束: 保持当前本地评分模型,不引入额外远程请求
兼容性约束: 不改变空搜索时的默认排序,不影响现有结果卡片渲染
业务约束: 标签只作为附加搜索字段,不替代名称和主机的主排序地位
```
### 验收标准
- [ ] 在全局服务器检索中输入标签名时,能命中绑定该标签的服务器。
- [ ] 当名称/主机与标签同时参与匹配时,名称和主机仍优先于标签字段排序。
- [ ] 空搜索场景仍按最近连接和显示名排序,不受新增标签字段影响。
- [ ] 至少完成一次前端可执行校验,确认本次改动未引入新的打包错误。
---
## 2. 方案
### 技术方案
扩展 `packages/frontend/src/utils/connectionSearch.ts`,为搜索函数增加可选的附加搜索字段提供器,由调用方传入标签名数组。`GlobalConnectionQuickSearch.vue` 继续复用当前标签映射逻辑,把每条连接的标签名作为附加字段传给 `searchConnections()`。评分权重设置为低于 `host`、高于 `type` 的中低档位,只影响有查询词时的匹配分数。
### 影响范围
```yaml
涉及模块:
- frontend: 全局服务器检索的本地模糊搜索评分
- knowledge-base: 新增方案包并记录本次搜索能力优化
预计变更文件: 5
```
### 风险评估
| 风险 | 等级 | 应对 |
|------|------|------|
| 标签权重过高,导致标签命中结果压过名称或主机匹配 | 中 | 将标签字段权重明确控制在 `host` 之下,并保留现有主字段排序 |
| 搜索工具函数签名调整影响其他调用点 | 低 | 当前仓库仅 `GlobalConnectionQuickSearch.vue` 使用该函数,保持参数向后兼容 |
| 标签缺失或标签缓存未加载时搜索结果不稳定 | 低 | 附加字段回调默认返回空数组,缺失时静默降级为现有搜索行为 |
---
## 3. 技术设计(可选)
> 本次不涉及架构、API 或数据模型变更,N/A。
---
## 4. 核心场景
### 场景: 按标签检索服务器
**模块**: frontend
**条件**: 用户打开全局服务器检索,并输入某个服务器标签名
**行为**: 搜索工具函数把标签名作为附加字段参与模糊匹配与排序
**结果**: 绑定该标签的服务器能出现在搜索结果中
### 场景: 主字段保持更高优先级
**模块**: frontend
**条件**: 查询词同时可能命中名称、主机和标签
**行为**: 名称和主机匹配继续获得更高分值,标签只作为次级加权字段
**结果**: 结果排序仍符合“先服务器标识、后标签补充”的预期
---
## 5. 技术决策
### workspace-global-search-tag-fuzzy-search#D001: 用可选附加字段扩展搜索函数,而不是把标签逻辑硬编码进工具函数
**日期**: 2026-04-15
**状态**: ✅采纳
**背景**: 需要让标签参与全局搜索,但又不想让工具函数只为一个组件写死标签依赖。
**选项分析**:
| 选项 | 优点 | 缺点 |
|------|------|------|
| A: 在 `connectionSearch.ts` 内直接读取标签 store | 调用方最简单 | 工具函数耦合 UI store,不利于复用和测试 |
| B: 为 `searchConnections()` 增加可选附加字段回调 | 依赖边界清晰,调用方按需提供标签名 | 函数签名略有扩展 |
**决策**: 选择方案 B
**理由**: 既能满足当前需求,又能把工具函数保持为纯评分逻辑,不直接依赖 Vue/Pinia。
**影响**: frontend
---
## 6. 成果设计
### 设计方向
- **美学基调**: 不改视觉布局,搜索能力增强应保持“无感升级”。
- **记忆点**: 用户可以直接输入环境标签词并立即定位服务器。
- **参考**: 继续沿用现有 `GlobalConnectionQuickSearch.vue` 结果卡片展示。
### 视觉要素
- **配色**: N/A
- **字体**: N/A
- **布局**: 不新增额外布局变化,保持现有结果卡片结构。
- **动效**: N/A
- **氛围**: N/A
### 技术约束
- **可访问性**: 搜索行为增强不应改变现有键盘上下选择与回车连接流程。
- **响应式**: N/A
@@ -0,0 +1,49 @@
# 任务清单: workspace-global-search-tag-fuzzy-search
> **@status:** completed | 2026-04-15 21:51
```yaml
@feature: workspace-global-search-tag-fuzzy-search
@created: 2026-04-15
@status: completed
@mode: R2
```
## 进度概览
| 完成 | 失败 | 跳过 | 总数 |
|------|------|------|------|
| 4 | 0 | 0 | 4 |
---
## 任务列表
### 1. 方案设计
- [√] 1.1 确认标签搜索权重策略为“低于名称和主机,高于类型”,并收敛到全局搜索工具与调用组件 | depends_on: []
### 2. 前端实现
- [√] 2.1 在 `packages/frontend/src/utils/connectionSearch.ts` 中为搜索函数增加附加搜索字段能力,并设置标签字段权重 | depends_on: [1.1]
- [√] 2.2 在 `packages/frontend/src/components/GlobalConnectionQuickSearch.vue` 中将连接标签名传入搜索函数,接通按标签模糊搜索 | depends_on: [2.1]
### 3. 验证与知识同步
- [√] 3.1 执行前端构建或等价校验,确认标签加入模糊搜索后未引入新的打包错误 | depends_on: [2.2]
---
## 执行日志
| 时间 | 任务 | 状态 | 备注 |
|------|------|------|------|
| 2026-04-15 21:39 | DESIGN | completed | 已确认本次为现有全局检索的搜索增强,标签匹配权重低于名称与主机、高于类型 |
| 2026-04-15 21:42 | 2.1-2.2 | completed | 已扩展 `searchConnections()` 的附加搜索字段能力,并在 `GlobalConnectionQuickSearch.vue` 中接通标签名搜索 |
| 2026-04-15 21:44 | 3.1 | completed | `npm --workspace @nexus-terminal/frontend exec vite build` 通过,确认标签搜索接入未引入新的打包错误 |
---
## 执行备注
> 本次只增强“标签参与搜索”,不调整空搜索排序,不扩展到其他连接列表或筛选器。
@@ -0,0 +1,167 @@
# 变更提案: status-monitor-process-manager-modal
## 元信息
```yaml
类型: 新功能/重构/优化
方案类型: implementation
优先级: P1
状态: 已确认
创建: 2026-04-15
```
---
## 1. 需求
### 背景
上一轮状态监控已经完成基础视觉重构,但用户明确反馈“不够好看,要更贴近参考图”,同时新增了明确需求:默认状态视图中需要补上时区、运行时间和进程管理概览;点击“查看全部”后,应弹出一个更完整的独立进程管理页面,风格接近用户提供的深色表格化管理截图。
### 目标
- 将默认状态视图继续收紧为更接近“服务器监控小屏”的布局节奏与视觉密度
- 在默认状态视图中新增时区、运行时间和进程管理概览
- 提供“查看全部”入口,打开独立 modal 形式的进程管理页面,支持搜索、刷新、自动刷新和结束/强制结束进程
### 约束条件
```yaml
时间约束: 当前回合内完成设计、实现、验证和知识库同步
性能约束: 进程列表查询与自动刷新不能影响现有 SSH 会话稳定性;默认视图仅展示摘要,避免持续渲染超长列表
兼容性约束: 复用现有 SSH 会话 WebSocket 链路,不破坏状态轮询、终端、Docker 和现有 modal 行为
业务约束: 默认视图是轻量概览;完整进程管理通过“查看全部” modal 打开,不直接把整张管理表挤进侧栏
```
### 验收标准
- [ ] `StatusMonitor.vue` 默认视图补齐时区、运行时间和进程概览,并整体更贴近用户给出的服务器小屏参考图
- [ ] 新增独立进程管理 modal,支持搜索、刷新、自动刷新、结束进程、强制结束进程
- [ ] 后端通过现有 WebSocket 会话返回时区、运行时间、进程列表和进程操作结果,前端构建通过
---
## 2. 方案
### 技术方案
本次改动分为三层:
1. 扩展状态监控后端采集:
-`status-monitor.service.ts` 中新增服务器时区和运行时间采集
- 保持 `status_update` 主链路用于基础状态字段
2. 新增进程管理 WebSocket 能力:
- 在现有 SSH 会话 WebSocket 连接上扩展 `process:list``process:signal` 消息类型
- 后端通过当前活动 SSH 会话执行 `ps``kill` 指令,返回结构化进程列表与操作结果
3. 前端双层展示:
- `StatusMonitor.vue` 默认视图继续向监控小屏靠拢,新增时区、运行时间和进程概览卡片
- “查看全部” 打开新的 `ProcessManagerModal.vue`,其中嵌入完整进程管理表格视图
- 表格风格尽量贴近用户截图,采用紧凑列、搜索栏、自动刷新开关和右侧操作列
### 影响范围
```yaml
涉及模块:
- packages/backend/src/services/status-monitor.service.ts: 扩展时区和运行时间采集
- packages/backend/src/websocket/connection.ts: 新增进程查询与信号操作消息分发
- packages/backend/src/websocket/types.ts: 扩展进程管理消息类型
- packages/frontend/src/types/server.types.ts: 增加时区/运行时间字段
- packages/frontend/src/components/StatusMonitor.vue: 默认状态视图继续贴近参考图并增加进程概览
- packages/frontend/src/components/ProcessManagerModal.vue: 独立进程管理 modal
- packages/frontend/src/locales/*.json: 新增进程管理与状态监控文案
- .helloagents/modules/frontend.md / modules/backend.md / CHANGELOG.md: 同步知识库
预计变更文件: 8-10
```
### 风险评估
| 风险 | 等级 | 应对 |
|------|------|------|
| `ps` 输出格式在不同 Linux 发行版上存在差异 | 中 | 使用明确字段顺序与受控 awk/tab 分隔格式,后端集中解析并做回退 |
| 进程操作误伤系统进程 | 中 | 默认仅提供单行显式操作按钮,不做批量;强制结束作为二级危险动作高亮展示 |
| modal 自动刷新与会话切换叠加导致订阅混乱 | 中 | 前端对 active session / isVisible 建立显式注册与清理逻辑,关闭 modal 时停止自动刷新 |
---
## 3. 技术设计(可选)
> 本次以现有 SSH 会话 WebSocket 为主,不新增独立 HTTP 管理接口。
### 架构设计
```mermaid
flowchart TD
A[StatusMonitorService] --> B[status_update]
C[WebSocket connection.ts] --> D[process:list / process:signal]
B --> E[StatusMonitor.vue 默认概览]
D --> E
E --> F[ProcessManagerModal.vue]
```
### API设计
#### WebSocket `process:list`
- **请求**: `{ type: 'process:list', sessionId, payload: { limit?: number } }`
- **响应**: `{ type: 'process:list:response', sessionId, payload: { processes, total, running, sleeping } }`
#### WebSocket `process:signal`
- **请求**: `{ type: 'process:signal', sessionId, payload: { pid, signal: 'TERM' | 'KILL' } }`
- **响应**: `{ type: 'process:signal:response', sessionId, payload: { pid, signal, success, error? } }`
### 数据模型
| 字段 | 类型 | 说明 |
|------|------|------|
| `timezone` | `string` | 服务器当前时区显示文本 |
| `uptimeSeconds` | `number` | 服务器已运行秒数 |
| `ProcessListItem.pid` | `number` | 进程 ID |
| `ProcessListItem.user` | `string` | 所属用户 |
| `ProcessListItem.state` | `string` | 进程状态 |
| `ProcessListItem.cpu` | `number` | CPU 占比 |
| `ProcessListItem.memMb` | `number` | 内存占用,MB |
| `ProcessListItem.startedAt` | `string` | 启动时间文本 |
| `ProcessListItem.command` | `string` | 完整命令 |
---
## 4. 核心场景
### 场景: 默认状态视图查看进程概览
**模块**: `packages/frontend/src/components/StatusMonitor.vue`
**条件**: 用户已有活动 SSH 会话,状态监控面板正常显示
**行为**: 面板以更接近服务器监控小屏的密度展示系统、时区、运行时间和资源状态,并在底部显示进程概览和“查看全部”入口
**结果**: 用户无需离开侧栏即可快速判断机器运行情况,并知道是否需要打开完整进程管理
### 场景: 查看全部进程管理
**模块**: `packages/frontend/src/components/ProcessManagerModal.vue`
**条件**: 用户点击状态监控中的“查看全部”
**行为**: 打开独立 modal,显示可搜索的进程表格,并支持刷新、自动刷新、结束进程和强制结束
**结果**: 用户获得接近参考图的独立进程管理页面,同时仍保留在当前工作区上下文中
---
## 5. 技术决策
### status-monitor-process-manager-modal#D001: 进程管理沿当前 SSH 会话 WebSocket 链路实现
**日期**: 2026-04-15
**状态**: ✅采纳
**背景**: 进程列表和进程操作都依赖当前活动 SSH 会话上下文,若改走独立 HTTP 接口,需要额外解决会话绑定和 SSH 复用问题。
**选项分析**:
| 选项 | 优点 | 缺点 |
|------|------|------|
| A: 新增 HTTP 接口直连后台查询进程 | 前端调用方式统一 | 很难绑定当前 SSH 会话,需额外管理远端执行上下文 |
| B: 复用现有 SSH 会话 WebSocket 消息 | 与当前终端/状态监控链路一致,复用现有 sessionId 和 wsManager | 需要扩展消息类型和前端订阅 |
**决策**: 选择方案 B
**理由**: 与现有架构最一致,能自然绑定活动 SSH 会话,也更适合 modal 内的即时刷新和进程操作回执。
**影响**: 影响 `packages/backend/src/websocket/*``StatusMonitor.vue` 以及新的进程管理 modal 组件
---
## 6. 成果设计
### 设计方向
- **美学基调**: 更贴近运维监控终端的小屏控制台风格,默认视图强调紧凑、层级分明、状态色克制,弹窗则偏运维后台表格台面
- **记忆点**: 默认视图像“服务器小屏仪表”,而点击“查看全部”后立刻切到一张近似真实进程控制台的深色表格
- **参考**: 用户给出的服务器状态小屏截图 + 进程管理独立弹窗截图
### 视觉要素
- **配色**: 延续炭黑监控底色,默认视图用绿色/蓝色/琥珀色状态高亮;进程表格中的危险操作使用明显红色
- **字体**: 继续使用项目现有字体体系,强调等宽数字和紧凑列头,避免引入额外字体依赖
- **布局**: 默认视图尽量纵向、像小屏;进程管理 modal 采用顶栏搜索 + 表格主体 + 右侧操作列的后台结构
- **动效**: 仅保留轻量 hover、刷新和 modal 开合过渡,不增加大幅动画
- **氛围**: 深色渐变、薄边框、表格网格线、低饱和荧光状态色和危险动作红色高亮
### 技术约束
- **可访问性**: 表头、搜索框、按钮和危险操作需要明确可见状态;危险动作文字不能只靠颜色表达
- **响应式**: 默认视图继续兼容窄侧栏;modal 在桌面优先按参考图宽表格布局,小屏允许横向滚动
@@ -0,0 +1,63 @@
# 任务清单: status-monitor-process-manager-modal
> **@status:** completed | 2026-04-15 22:12
```yaml
@feature: status-monitor-process-manager-modal
@created: 2026-04-15
@status: completed
@mode: R2
```
## 进度概览
| 完成 | 失败 | 跳过 | 总数 |
|------|------|------|------|
| 7 | 0 | 0 | 7 |
---
## 任务列表
### 1. 需求与链路确认
- [√] 1.1 确认时区、运行时间和进程管理应分别挂载到状态轮询链路与 SSH 会话 WebSocket 链路 | depends_on: []
### 2. 后端能力补充
- [√] 2.1 在 `packages/backend/src/services/status-monitor.service.ts` 中新增时区与运行时间采集并扩展状态返回结构 | depends_on: [1.1]
- [√] 2.2 在 `packages/backend/src/websocket/types.ts``packages/backend/src/websocket/connection.ts` 中新增进程列表和进程信号操作消息 | depends_on: [1.1]
### 3. 前端类型与默认视图
- [√] 3.1 在 `packages/frontend/src/types/server.types.ts` 中补充时区/运行时间/进程相关类型 | depends_on: [2.1, 2.2]
- [√] 3.2 在 `packages/frontend/src/components/StatusMonitor.vue` 中继续收紧默认视图,并新增时区、运行时间和进程概览区 | depends_on: [3.1]
### 4. 独立进程管理页面
- [√] 4.1 新增进程管理 modal 组件,支持搜索、刷新、自动刷新和结束/强制结束操作 | depends_on: [2.2, 3.1]
### 5. 文案、验证与同步
- [√] 5.1 更新中英文状态监控和进程管理文案 | depends_on: [3.2, 4.1]
- [√] 5.2 执行前后端相关构建验证并同步知识库、CHANGELOG、方案包 | depends_on: [2.1, 2.2, 3.2, 4.1, 5.1]
---
## 执行日志
| 时间 | 任务 | 状态 | 备注 |
|------|------|------|------|
| 2026-04-15 21:47 | 1.1 | completed | 已确认默认视图和完整进程管理页分层交付,后端需补状态字段与进程 WebSocket 消息 |
| 2026-04-15 21:56 | 2.1 / 2.2 | completed | 后端状态监控已补时区、运行时间、进程摘要,并新增进程列表 / 信号操作 WebSocket handler |
| 2026-04-15 22:02 | 3.1 / 3.2 | completed | 前端状态类型已扩展,默认状态视图已新增时区、运行时间和进程概览入口 |
| 2026-04-15 22:06 | 4.1 | completed | 已新增独立 `ProcessManagerModal.vue`,支持搜索、自动刷新、刷新和结束/强制结束进程 |
| 2026-04-15 22:08 | 5.1 / 5.2 | completed | `packages/backend``packages/frontend` 构建通过;文案和知识库已同步 |
---
## 执行备注
- 默认视图继续贴近监控小屏,不直接承载完整进程表格
- 完整进程管理通过 modal 打开,避免破坏右侧状态监控的侧栏职责
- 前端构建仍保留仓库既有的 Vite 动态导入与大 chunk 警告,但本次改动未引入新的阻断性错误
+2
View File
@@ -7,6 +7,8 @@
| 时间戳 | 名称 | 类型 | 涉及模块 | 决策 | 结果 |
|--------|------|------|---------|------|------|
| 202604152147 | status-monitor-process-manager-modal | - | - | - | ✅完成 |
| 202604152139 | workspace-global-search-tag-fuzzy-search | - | - | - | ✅完成 |
| 202604152110 | workspace-global-search-show-connection-tags | - | - | - | ✅完成 |
| 202604152109 | status-monitor-responsive-remodel | - | - | - | ✅完成 |
| 202604122248 | connections-tag-batch-management | implementation | frontend, backend | connections-tag-batch-management#D001 | ✅完成 |
+4 -4
View File
@@ -66,8 +66,8 @@
### 状态监控
**条件**: 前端工作区通过 WebSocket 订阅服务器状态。
**行为**: `StatusMonitorService` 通过 SSH 读取 `free``df``/proc/stat``/proc/net/dev`,同时计算瞬时网速与默认网卡自开机以来的累计上下行字节数
**结果**: 前端状态监控既能展示实时速率,也能展示“开机累计流量”,后续扩展监控字段时应优先复用现有 SSH 采集链路
**行为**: `StatusMonitorService` 通过 SSH 读取 `free``df``/proc/stat``/proc/net/dev``date``/proc/uptime`,同时计算瞬时网速与默认网卡自开机以来的累计上下行字节数,并在常规 `status_update` 中附带服务器时区、运行秒数和轻量级进程摘要(总数、运行中、休眠中、Top 进程预览)
**结果**: 前端状态监控既能展示实时资源状态,也能直接展示服务器时区、运行时间和默认进程概览,而无需再为这些基础信息单独请求后端
## 依赖关系
@@ -78,5 +78,5 @@
### 状态监控字段扩展
**条件**: `StatusMonitorService` 为前端工作区持续轮询服务器状态。
**行为**: 当前状态采集链路除 `free``df``/proc/stat``/proc/net/dev` 外,还会补充解析 `memFree``memCached``diskAvailable``diskMountPoint``diskFsType``diskDevice`,并基于 `/proc/diskstats` 计算根设备的磁盘读写速率;CPU 规格信息则会先读取 CPU 型号,再通过 `nproc``getconf _NPROCESSORS_ONLN``grep -c '^processor' /proc/cpuinfo``lscpu` 多级回退获取 `cpuCores`无法获取的字段均按 `undefined` 降级
**结果**: 前端状态监控可以直接展示参考图风格的内存/磁盘卡片,并额外展示 CPU 核心数,而不需要再自行推导缓存、空闲、磁盘元信息或服务器 CPU 规格
**行为**: 当前状态采集链路除 `free``df``/proc/stat``/proc/net/dev` 外,还会补充解析 `memFree``memCached``diskAvailable``diskMountPoint``diskFsType``diskDevice`,并基于 `/proc/diskstats` 计算根设备的磁盘读写速率;CPU 规格信息则会先读取 CPU 型号,再通过 `nproc``getconf _NPROCESSORS_ONLN``grep -c '^processor' /proc/cpuinfo``lscpu` 多级回退获取 `cpuCores`本轮还新增服务器时区、运行时间和默认进程摘要采集。与此同时,`websocket/connection.ts` 新增 `process:list``process:signal` 消息分发,后端会在当前活动 SSH 会话上下文中执行 `ps``kill` 指令,返回完整进程列表及结束/强制结束结果
**结果**: 前端默认状态监控可以展示更完整的小屏监控信息,而“查看全部”进程管理 modal 也能沿同一 SSH 会话上下文安全复用进程查询与操作能力
File diff suppressed because one or more lines are too long