- generic ContextMenu component (viewport flip, esc/outside close) - SchemaSidebar table right-click menu: preview data, generate SELECT/INSERT/UPDATE/DELETE templates with pk-aware WHERE, copy table name; double-click table runs preview SELECT; column right-click copy/insert; dialect-aware quoting; preview SELECT carries no LIMIT - SqlEditor selection-first execution (Mod-Enter runs selection else statement at cursor via quote/comment-aware splitter); pagination replays last executed statement - query history persisted server-side: drawer fetches query-histories with keyword/mine/favorites filters, star toggle (new PUT favorite + mine filter endpoints), insert and insert-and-run - custom templates in localStorage alongside built-ins - unit tests: genSql + statement splitter (28 tests green)
68 lines
6.2 KiB
Markdown
68 lines
6.2 KiB
Markdown
# OpsxSQL 查询体验与工单流程优化(借鉴 opsxdb / opsx-sec)
|
|
|
|
**用户已确认**:① 移除工单创建页死的「定时执行」字段 ② 全部四块都做。
|
|
**不做**(明确出界):多 tab 页签系统、草稿自动保存、批量审批、Redis Hash 值级 HSCAN 分页——后续迭代。
|
|
|
|
---
|
|
|
|
## Phase 1 — 后端 Redis 扫描服务化(借鉴 opsxdb server/internal/db/redis.go)
|
|
|
|
改造 `backend/internal/handler/redis.go`:
|
|
|
|
1. **SCAN 增量游标分页**(对标 opsxdb 的不透明游标设计):
|
|
- `keyScanPosition{Pattern, DB, Nodes, Index, Cursor}` JSON→base64 编码回传;下次请求带回,服务端校验 pattern/db/节点拓扑一致,不一致报「搜索位置已失效」
|
|
- 每页上限 200 键,单页最多 20 次 SCAN 调用,完整批次一起返回
|
|
- 响应:`{keys:[{name,type,ttl}], next_cursor, exact?}` — **无通配符输入时先 TYPE 精确探测,命中作为 exact 项置顶**
|
|
2. **pattern 规则**:`redisBrowsePattern` — 无 `*?[` 通配符自动包 `*关键词*`;有则按 glob 原样
|
|
3. **pipeline 批量 TYPE/TTL**:替换现逐 key 串行 N+1(大库必超时);type 筛选参数真正生效(pipeline 取到 type 后过滤)
|
|
4. **集群归一**:`ScanAllKeys` 改为 ForEachMaster 各分片**增量** SCAN 归并排序;cluster 模式只暴露 DB0;MOVED 错误追加「请将部署模式切为集群并填种子节点」提示
|
|
5. **CLI 修复**(现为必 403 的死功能):后端 `RedisExecuteCommand` 接受 `{db, command}` 整串——按空白拆 args(引号感知),白名单匹配首词;前端契约同步(api/datasource/redis.ts);危险命令清单二段确认在前端做
|
|
6. 更新 key 的 DEL+重写改为按类型的原子命令(Hash 用 HSET/HDEL 行级;保留整 key 重写兜底)
|
|
|
|
验证:go build/vet/test + curl 实测(单机 redis-server 本地起,若有;否则用实例 fixture 手测游标翻页)
|
|
|
|
## Phase 2 — 前端 Redis 键浏览重构
|
|
|
|
新建 `src/features/redis/keyBrowser/` 共享模块(详情页键管理 tab 与 QueriesPage 的 SchemaSidebar Redis 分支两处接入):
|
|
|
|
1. **hooks/useRedisKeyBrowser.ts**:游标加载状态机(首页/加载更多/重置)、请求序号防竞态(过期响应丢弃)、按键名 Map 增量合并、db/pattern/type 参数
|
|
2. **utils/keyTree.ts**(对标 opsxdb src/redis.ts):
|
|
- `buildRedisKeyTree` 按 `:` 分隔建 folder 树(文件夹计数徽标、numeric 排序、无分隔符留根层、exact 置顶)
|
|
- `formatRedisTtl`(-1 永久/-2 不存在/45s/5m30s/2d5h)、`redisTypeColor` 八类型色点、`removeRedisKeyFromTree` 本地移除(删键不重拉)
|
|
3. **搜索框交互**:回车/按钮触发 SCAN(不做防抖——SCAN 有成本,opsxdb 同款取舍);有关键字时显示「清除」;占位提示支持 `*` 通配
|
|
4. **树渲染**:叶子只显示末段(hover title 全名)、行尾淡显 `{type} · {ttl}`、底部「加载更多」按钮(title 提示游标扫描语义);DB 切换下拉 cluster 恒 DB0
|
|
5. **类型筛选**下拉接真实后端过滤(修死功能)
|
|
6. RedisDetailPage 键管理 tab 与 SchemaSidebar Redis 分支替换为新模块(保持各自布局壳)
|
|
|
|
## Phase 3 — MySQL/PG 查询便捷性(借鉴 opsxdb ObjectTree/SqlEditor)
|
|
|
|
1. **通用右键菜单组件** `src/components/ContextMenu.tsx`:视口边界翻转、Esc/外点关闭、菜单项分隔线
|
|
2. **SchemaSidebar 增强**:
|
|
- 表右键菜单:查看数据(生成方言化 SELECT 进编辑器并执行)/ 生成 SQL 子菜单(SELECT/INSERT/UPDATE/DELETE,全列展开+复合主键进 WHERE)/ 复制表名 / 复制建表 DDL(已有 DDL API 则接,无则隐藏)
|
|
- 双击表 = 生成 SELECT 预览;列右键:复制列名/复制 table.column
|
|
- 搜索框:本地已加载过滤保留
|
|
3. **SqlEditor 增强**:「执行选中优先」——Mod-Enter/执行按钮改为选区优先、否则光标所在语句(按分号切分,简单引号感知)
|
|
4. **查询历史持久化**(后端 API 已存在闲置):执行成功后自动 saveQueryHistory;历史抽屉改为后端数据源(分页拉取+关键字过滤),点击回填、▶ 回填并执行;收藏 id 集(localStorage)叠加在后端历史上
|
|
5. **自定义模板**:QueryTemplatePanel 支持用户自定义片段(localStorage,{name, sql}),与内置并列
|
|
|
|
## Phase 4 — 工单流程 step 优化(借鉴 opsx-sec)
|
|
|
|
1. **状态驱动步骤条**:`features/ticket/components/TicketStageSteps.tsx`——工单详情页(及详情弹窗)顶部步骤条:提交→初审→复审(按 workflow 实际 steps 动态生成)→执行→完成;active 由工单 status 推导(数据驱动,非可点击回跳);驳回/失败/回滚显示终态错误色;下方快捷入口按钮(查看 SQL/审批/执行日志)
|
|
2. **审批时间线修复**:DetailTimeline 的 ACTION_CONFIG 键改为后端实际 action 值(created/approve/reject/pending_review/executed/...),图标+颜色按事件类型分色(成功绿/警告琥珀/失败红)
|
|
3. **审批交互统一**(详情弹窗与详情页行为对齐):
|
|
- 通过/驳回:弹出行内评论输入(可选)→确认;列表页行内快捷通过保留但加轻量确认与评论入口;`alert()` 全部换 toast
|
|
- 执行:二次确认复述影响面「将对实例 X 库 Y 执行 N 条语句,确认执行?」(opsx-sec 带影响面摘要模式)
|
|
- 禁用按钮可解释:不可执行时 disabled+tooltip 原因(等待审批/非执行人/已执行等),`disabledReason()` 纯函数
|
|
4. **创建页修正**(TicketCreatePage):
|
|
- 移除死的「定时执行」字段;新增「回滚 SQL」采集(后端已支持 rollback_sql);priority 下拉真实可选
|
|
- **审批流预览**:选定实例后展示其 workflow 步骤与审批人名单(数据已有,创建前可见谁会审)
|
|
- SQL 检测通过才可提交的 gate 保留(已是两段式)
|
|
5. **空态引导**:暂无工单空态内嵌「创建变更工单」主按钮(EmptyState 引导动作)
|
|
|
|
## 实施与验证
|
|
|
|
- 每 Phase 独立 commit;前端每步过 `tsc --noEmit` + `npm run build` + `audit:pages`(页面不超 700 行),后端过 `go build/vet/test`
|
|
- Phase 1/2 完成后:本地起 Go 服务(独立端口+DB),curl 验证游标翻页/pattern/type 过滤/集群归一;浏览器实测 Redis 键浏览(搜索/分组树/加载更多/DB 切换)
|
|
- Phase 3/4 完成后:浏览器实测右键菜单/生成 SQL/历史持久化回填、工单步骤条/审批评论/禁用原因/创建页新字段
|
|
- 全部完成后跑全量门禁(vitest/tsc/build/go),收尾总结
|