Private
Public Access
1
0
Files
u-desk/docs/04-功能迭代/GO-DESK-2.数据库客户端/设计文档/架构设计/事件系统设计.md

7.5 KiB
Raw Blame History

事件系统设计

设计日期2025-01-28
设计范围:数据库客户端全局事件系统
状态:设计阶段


一、设计概述

1.1 设计目标

  • 简洁统一:所有组件使用统一的事件命名和参数格式
  • 易于扩展:新增事件时,遵循统一规范,易于维护
  • 类型安全:使用 TypeScript 类型定义,确保类型安全
  • 功能强大:支持事件传递、事件拦截、事件日志等高级功能

1.2 设计原则

  1. 命名规范:事件名称使用 kebab-case语义清晰
  2. 参数统一:事件参数使用对象格式,包含必要上下文信息
  3. 类型定义:所有事件都有明确的 TypeScript 类型定义
  4. 文档完善:每个事件都有清晰的文档说明

二、事件分类

2.1 连接相关事件

// 连接选择
'connection-select': {
  connection: DbConnection
  database?: string  // 可选,选中的数据库
}

// 连接编辑
'connection-edit': {
  connectionId: number
}

// 连接删除
'connection-delete': {
  connectionId: number
}

// 连接刷新
'connection-refresh': {
  connectionId?: number  // 可选,不提供则刷新所有
}

2.2 表结构相关事件

// 查看表结构
'table-structure': {
  connectionId: number
  database: string
  tableName: string  // 表名/集合名/Key名
  dbType: 'mysql' | 'mongo' | 'redis'
  nodeType: 'table' | 'collection' | 'key' | 'database' | 'connection'
}

// 表选择生成SQL
'table-select': {
  connectionId: number
  database: string
  tableName: string
  sql?: string  // 可选预生成的SQL
}

2.3 SQL执行相关事件

// SQL执行
'sql-execute': {
  sql: string
  connectionId: number
  database?: string
}

// SQL执行完成
'sql-execute-complete': {
  result: SqlResult
  error?: string
}

2.4 编辑器相关事件

// SQL插入
'sql-insert': {
  sql: string
  tabKey?: string  // 可选指定Tab
}

// Tab切换
'tab-switch': {
  tabKey: string
}

// Tab关闭
'tab-close': {
  tabKey: string
}

三、事件系统架构

3.1 事件总线设计

// 事件总线接口
interface EventBus {
  // 注册事件监听器
  on<T = any>(event: string, handler: (data: T) => void): () => void
  
  // 注册一次性事件监听器
  once<T = any>(event: string, handler: (data: T) => void): void
  
  // 移除事件监听器
  off(event: string, handler?: Function): void
  
  // 触发事件
  emit<T = any>(event: string, data: T): void
  
  // 清除所有监听器
  clear(): void
}

// 全局事件总线实例
export const eventBus = createEventBus()

3.2 组件事件映射

// ConnectionTree 组件事件
interface ConnectionTreeEvents {
  'connection-select': { connection: DbConnection; database?: string }
  'connection-edit': { connectionId: number }
  'connection-delete': { connectionId: number }
  'table-select': { connectionId: number; database: string; tableName: string }
  'table-structure': { 
    connectionId: number
    database: string
    tableName: string
    dbType: 'mysql' | 'mongo' | 'redis'
    nodeType: string
  }
  'new-connection': void
  'show-bookmarks': void
  'show-templates': void
}

// SqlEditor 组件事件
interface SqlEditorEvents {
  'execute': { sql: string }
  'execute-selected': { sql: string }
  'sql-insert': { sql: string; tabKey?: string }
  'tab-switch': { tabKey: string }
  'tab-close': { tabKey: string }
  'toggle-editor': void
}

四、事件命名规范

4.1 命名规则

  • 格式<组件>-<动作><功能>-<动作>
  • 示例
    • connection-select:连接选择
    • table-structure:表结构查看
    • sql-executeSQL执行

4.2 动作词汇表

动作 说明 示例
select 选择 connection-select
edit 编辑 connection-edit
delete 删除 connection-delete
create 创建 tab-create
close 关闭 tab-close
switch 切换 tab-switch
execute 执行 sql-execute
insert 插入 sql-insert
refresh 刷新 connection-refresh

五、事件参数设计

5.1 参数原则

  1. 对象格式:所有事件参数使用对象,不使用多个参数
  2. 必要信息:包含事件处理所需的所有上下文信息
  3. 可选字段:使用可选字段(?)标记非必需信息
  4. 类型明确:所有字段都有明确的类型定义

5.2 参数示例

// ✅ 好的设计:对象格式,类型明确
emit('table-structure', {
  connectionId: 1,
  database: 'test',
  tableName: 'users',
  dbType: 'mysql',
  nodeType: 'table'
})

// ❌ 不好的设计:多个参数,类型不明确
emit('table-structure', 1, 'test', 'users', 'mysql', 'table')

六、事件处理流程

6.1 事件触发流程

组件内触发事件
    ↓
emit('event-name', data)
    ↓
父组件监听事件
    ↓
调用处理函数
    ↓
更新状态/执行操作

6.2 事件拦截机制(可选)

// 事件拦截器接口
interface EventInterceptor {
  beforeEmit?: (event: string, data: any) => boolean  // 返回false阻止事件
  afterEmit?: (event: string, data: any) => void      // 事件触发后执行
}

// 注册拦截器
eventBus.addInterceptor(interceptor)

七、实现细节

7.1 事件类型定义

// 事件类型定义文件types/events.ts
export interface ConnectionSelectEvent {
  connection: DbConnection
  database?: string
}

export interface TableStructureEvent {
  connectionId: number
  database: string
  tableName: string
  dbType: 'mysql' | 'mongo' | 'redis'
  nodeType: 'table' | 'collection' | 'key' | 'database' | 'connection'
}

// ... 其他事件类型

7.2 组件事件声明

// ConnectionTree.vue
const emit = defineEmits<{
  'connection-select': [data: ConnectionSelectEvent]
  'table-structure': [data: TableStructureEvent]
  'table-select': [data: TableSelectEvent]
  // ... 其他事件
}>()

7.3 事件处理

// index.vue
const handleTableStructure = (data: TableStructureEvent) => {
  // 加载表结构
  structureState.loadStructure(
    data.connectionId,
    data.database,
    data.tableName,
    data.dbType
  )
  // 切换到结构Tab
  resultTab.value = 'structure'
}

八、扩展性设计

8.1 事件日志(开发模式)

// 开发模式下记录所有事件
if (import.meta.env.DEV) {
  eventBus.on('*', (event, data) => {
    console.log(`[Event] ${event}`, data)
  })
}

8.2 事件统计(可选)

// 统计事件触发次数
const eventStats = new Map<string, number>()

eventBus.on('*', (event) => {
  eventStats.set(event, (eventStats.get(event) || 0) + 1)
})

九、实现优先级

P0必须实现

  1. 事件类型定义TypeScript
  2. 连接相关事件
  3. 表结构相关事件
  4. SQL执行相关事件

P1重要功能

  1. 事件参数验证
  2. 事件文档完善
  3. 事件处理错误处理

P2优化功能

  1. 事件拦截机制
  2. 事件日志(开发模式)
  3. 事件统计

十、总结

事件系统设计遵循以下原则:

  1. 简洁统一:统一的事件命名和参数格式
  2. 类型安全:完整的 TypeScript 类型定义
  3. 易于扩展:清晰的事件分类和命名规范
  4. 功能强大:支持事件拦截、日志等高级功能

通过以上设计,可以实现一个简洁、强大、易扩展的事件系统。