10 KiB
10 KiB
右键菜单系统设计
设计日期:2025-01-28
设计范围:数据库客户端全局右键菜单系统
状态:设计阶段
一、设计概述
1.1 设计目标
- 统一体验:所有区域的右键菜单使用统一的设计和交互方式
- 易于扩展:新增菜单项和功能区域时,可以快速集成
- 上下文感知:根据点击位置和对象类型,显示相应的菜单项
- 简洁强大:菜单项精简,但功能完整
1.2 适用范围
- 连接树区域:连接、数据库、表/集合/Key节点的右键菜单
- SQL编辑器区域:编辑器内容、Tab标签的右键菜单(未来扩展)
- 结果区域:表格、JSON内容的右键菜单(未来扩展)
1.3 设计原则
- 按需显示:根据节点类型和上下文,只显示相关的菜单项
- 分组清晰:相关功能分组,使用分隔线区分
- 操作明确:菜单项名称清晰,避免歧义
- 快捷操作:常用功能提供快捷键提示
二、连接树右键菜单设计
2.1 连接节点右键菜单
触发条件:右键点击连接节点
菜单项:
┌─────────────────────────┐
│ 查看结构 │
│ 编辑连接 │
│ 删除连接 │
├─────────────────────────┤
│ 刷新 │
│ 测试连接 │
└─────────────────────────┘
菜单项说明:
- 查看结构:查看连接的数据库列表结构(如果支持)
- 编辑连接:编辑连接配置
- 删除连接:删除连接(需确认)
- 刷新:刷新连接状态和数据库列表
- 测试连接:测试连接是否可用
2.2 数据库节点右键菜单
触发条件:右键点击数据库节点
菜单项(MySQL/MongoDB):
┌─────────────────────────┐
│ 查看结构 │
│ 生成SELECT语句 │
├─────────────────────────┤
│ 刷新 │
└─────────────────────────┘
菜单项(Redis DB):
┌─────────────────────────┐
│ 查看结构 │
│ 生成KEYS命令 │
├─────────────────────────┤
│ 刷新 │
└─────────────────────────┘
菜单项说明:
- 查看结构:查看数据库的表/集合列表结构
- 生成SELECT语句:生成
SELECT * FROM database.table LIMIT 100; - 生成KEYS命令:生成
KEYS *命令(Redis) - 刷新:刷新表/集合列表
2.3 表/集合节点右键菜单
触发条件:右键点击表/集合节点
菜单项(MySQL):
┌─────────────────────────┐
│ 查看结构 │
│ 生成SELECT语句 │
│ 复制表名 │
├─────────────────────────┤
│ 刷新 │
└─────────────────────────┘
菜单项(MongoDB):
┌─────────────────────────┐
│ 查看结构 │
│ 生成find语句 │
│ 复制集合名 │
├─────────────────────────┤
│ 刷新 │
└─────────────────────────┘
菜单项说明:
- 查看结构:查看表/集合的结构信息(字段、索引等)
- 生成SELECT语句:生成
SELECT * FROM database.table LIMIT 100; - 生成find语句:生成
db.collection.find({})(MongoDB) - 复制表名/集合名:复制到剪贴板
- 刷新:刷新表结构
2.4 Key节点右键菜单(Redis)
触发条件:右键点击Key节点
菜单项:
┌─────────────────────────┐
│ 查看结构 │
│ 生成GET命令 │
│ 复制Key名 │
├─────────────────────────┤
│ 刷新 │
└─────────────────────────┘
菜单项说明:
- 查看结构:查看Key的详细信息(类型、TTL、值预览)
- 生成GET命令:根据Key类型生成相应命令(GET、HGETALL等)
- 复制Key名:复制Key名称到剪贴板
- 刷新:刷新Key信息
三、技术实现设计
3.1 组件结构
ContextMenu.vue (全局右键菜单组件)
├── 菜单项配置(根据节点类型动态生成)
├── 菜单项渲染(使用 Arco Design Dropdown)
└── 事件处理(触发相应操作)
ConnectionTree.vue
└── 集成 ContextMenu 组件
└── 根据节点类型传递菜单配置
3.2 菜单配置数据结构
interface MenuItem {
key: string // 唯一标识
label: string // 显示文本
icon?: string // 图标(可选)
disabled?: boolean // 是否禁用
divider?: boolean // 是否为分隔线
children?: MenuItem[] // 子菜单(可选)
}
interface MenuConfig {
items: MenuItem[] // 菜单项列表
position: { // 菜单位置
x: number
y: number
}
}
3.3 菜单项注册机制
// 菜单项注册表
const menuRegistry = {
'connection': [
{ key: 'view-structure', label: '查看结构', icon: 'icon-eye' },
{ key: 'edit', label: '编辑连接', icon: 'icon-edit' },
{ key: 'delete', label: '删除连接', icon: 'icon-delete' },
{ key: 'divider-1', divider: true },
{ key: 'refresh', label: '刷新', icon: 'icon-refresh' },
{ key: 'test', label: '测试连接', icon: 'icon-check' }
],
'database': [
{ key: 'view-structure', label: '查看结构', icon: 'icon-eye' },
{ key: 'generate-sql', label: '生成SELECT语句', icon: 'icon-code' },
{ key: 'divider-1', divider: true },
{ key: 'refresh', label: '刷新', icon: 'icon-refresh' }
],
'table': [
{ key: 'view-structure', label: '查看结构', icon: 'icon-eye' },
{ key: 'generate-sql', label: '生成SELECT语句', icon: 'icon-code' },
{ key: 'copy-name', label: '复制表名', icon: 'icon-copy' },
{ key: 'divider-1', divider: true },
{ key: 'refresh', label: '刷新', icon: 'icon-refresh' }
],
// ... 其他节点类型
}
3.4 事件处理机制
// 统一的事件处理接口
interface MenuEventHandler {
(nodeData: TreeNodeData, menuKey: string): void | Promise<void>
}
// 事件映射表
const eventHandlers: Record<string, MenuEventHandler> = {
'view-structure': (nodeData) => {
// 触发查看结构事件
emit('table-structure', {
connectionId: nodeData.connectionId,
database: nodeData.database,
tableName: nodeData.tableName || nodeData.title,
dbType: nodeData.dbType,
nodeType: nodeData.type
})
},
'edit': (nodeData) => {
emit('connection-edit', nodeData.connectionId)
},
'delete': (nodeData) => {
emit('connection-delete', nodeData.connectionId)
},
'generate-sql': (nodeData) => {
// 生成SQL语句
const sql = generateSQL(nodeData)
emit('table-select', { ...nodeData, sql })
},
'copy-name': (nodeData) => {
// 复制名称到剪贴板
copyToClipboard(nodeData.tableName || nodeData.title)
},
'refresh': (nodeData) => {
// 刷新节点数据
refreshNode(nodeData)
}
}
四、实现细节
4.1 菜单显示位置
- 定位方式:使用鼠标事件坐标定位
- 边界处理:菜单超出视口时自动调整位置
- 层级管理:使用 z-index 确保菜单在最上层
4.2 菜单交互
- 点击外部关闭:点击菜单外部区域自动关闭
- ESC键关闭:按ESC键关闭菜单
- 键盘导航:支持方向键导航菜单项(可选,P2)
4.3 菜单样式
- 使用 Arco Design Dropdown:保持与系统风格一致
- 图标支持:菜单项支持图标显示
- 禁用状态:禁用项显示为灰色,不可点击
- 分隔线:使用分隔线区分功能组
五、扩展性设计
5.1 插件化菜单项
// 菜单项插件接口
interface MenuItemPlugin {
name: string
condition: (nodeData: TreeNodeData) => boolean // 显示条件
getMenuItem: (nodeData: TreeNodeData) => MenuItem // 生成菜单项
handler: (nodeData: TreeNodeData) => void // 处理函数
}
// 注册插件
function registerMenuItemPlugin(plugin: MenuItemPlugin) {
// 注册逻辑
}
5.2 动态菜单项
- 权限控制:根据用户权限动态显示/隐藏菜单项
- 上下文感知:根据当前状态动态调整菜单项
- 条件显示:某些菜单项只在特定条件下显示
六、实现优先级
P0(必须实现)
- ✅ 连接节点右键菜单(查看结构、编辑、删除、刷新)
- ✅ 数据库节点右键菜单(查看结构、生成SQL、刷新)
- ✅ 表节点右键菜单(查看结构、生成SQL、复制表名、刷新)
- ✅ Key节点右键菜单(查看结构、生成命令、复制Key名、刷新)
P1(重要功能)
- 菜单定位和边界处理
- 菜单项图标支持
- 复制功能实现
P2(优化功能)
- 键盘导航支持
- 菜单项插件化
- 权限控制
七、总结
右键菜单系统设计遵循以下原则:
- 统一设计:所有区域的右键菜单使用统一的设计和交互
- 易于扩展:通过配置和插件机制,易于添加新功能
- 上下文感知:根据节点类型和状态,显示相关菜单项
- 简洁强大:菜单项精简但功能完整
通过以上设计,可以实现一个统一、易用、易扩展的右键菜单系统。