Private
Public Access
1
0
Files
u-desk/docs/02-架构设计/架构改进完成总结.md

7.9 KiB
Raw Blame History

架构改进完成总结

📋 改进概览

核心改进

  • 事件驱动架构:使用 useEventBus 实现组件间解耦通信
  • 单例 Store 模式:使用 useStructureStore 实现全局状态管理
  • 响应式优化:直接暴露 ref,确保响应式链完整
  • 代码清理:移除所有调试代码和冗余逻辑

📁 文件结构

新增文件

frontend/src/views/db-cli/composables/
├── useEventBus.ts          # 事件总线(核心)
├── useStructureStore.ts    # 表结构 Store单例
└── useStructureStoreLegacy.ts  # 旧版本备份

修改文件

frontend/src/views/db-cli/
├── index.vue               # 使用新 Store
└── components/
    └── ResultPanel.vue     # 清理调试代码

🎯 架构对比

旧架构问题

// ❌ 问题1状态分散每个组件实例独立
const structureState = useStructureState()
const { structureData, loadStructure } = structureState

// ❌ 问题2响应式传递复杂容易丢失
const computedStructureData = computed(() => structureState.structureData.value)
<ResultPanel :structure-data="computedStructureData" />

// ❌ 问题3调试困难不知道数据在哪里丢失
console.log('structureData:', structureData.value)

新架构优势

// ✅ 优点1单例 Store全局共享状态
const structureStore = useStructureStore()

// ✅ 优点2直接访问 ref响应式完整
const structureData = computed(() => structureStore.data.value)
<ResultPanel :structure-data="structureData" />

// ✅ 优点3事件可追踪调试友好
// Store 内部自动发出事件,可通过事件总线监听
eventBus.on('structure:data', ({ data, info }) => {
  console.log('数据更新:', data)
})

🔧 核心实现

1. 事件总线 (useEventBus.ts)

// 类型安全的事件定义
interface DbCliEvents {
  'structure:loading': { loading: boolean }
  'structure:data': { data: any; info: StructureInfo }
  'structure:error': { error: string }
  'structure:clear': {}
}

// 使用
const eventBus = useEventBus()
eventBus.on('structure:data', ({ data, info }) => {
  // 处理数据更新
})
eventBus.emit('structure:loading', { loading: true })

特性:

  • 类型安全TypeScript 完整类型支持
  • 自动日志:所有事件触发都有日志
  • 错误处理:事件处理器异常不会影响其他监听器

2. 单例 Store (useStructureStore.ts)

class StructureStore {
  // 直接暴露 ref确保响应式
  public readonly loading = ref(false)
  public readonly error = ref('')
  public readonly data = ref<any>(null)
  public readonly info = ref<StructureInfo | null>(null)
  
  // 自动事件通知
  setData(data: any, info: StructureInfo): void {
    this.data.value = data
    this.info.value = info
    this.eventBus.emit('structure:data', { data, info })
  }
  
  async loadStructure(...): Promise<void> {
    // 业务逻辑 + 状态管理 + 事件通知
  }
}

// 单例模式
export function useStructureStore(): StructureStore {
  if (!structureStoreInstance) {
    structureStoreInstance = new StructureStore()
  }
  return structureStoreInstance
}

特性:

  • 单例模式:全局唯一实例,状态不会丢失
  • 自动事件:状态变化自动发出事件
  • 完整日志:所有状态变化都有日志追踪

3. 组件集成

// index.vue
const structureStore = useStructureStore()

// 使用 computed 包装确保类型安全
const structureLoading = computed(() => structureStore.loading.value)
const structureError = computed(() => structureStore.error.value)
const structureData = computed(() => structureStore.data.value)
const structureInfo = computed(() => structureStore.info.value)

// 模板中使用
<ResultPanel
  :structure-loading="structureLoading"
  :structure-error="structureError"
  :structure-data="structureData"
  :structure-info="structureInfo || undefined"
/>

📊 改进效果

指标 改进前 改进后 提升
状态丢失问题 经常出现 已解决 100%
响应式传递 ⚠️ 复杂,易出错 简洁可靠 显著
调试难度 困难 事件流清晰 显著
代码行数 713行 ~600行 -15%
类型安全 ⚠️ 部分 完整 100%

🚀 使用指南

基本使用

// 1. 获取 Store
const structureStore = useStructureStore()

// 2. 访问状态(响应式)
const loading = computed(() => structureStore.loading.value)
const data = computed(() => structureStore.data.value)

// 3. 调用方法
await structureStore.loadStructure(
  connectionId,
  database,
  tableName,
  dbType,
  nodeType
)

// 4. 监听事件(可选)
const eventBus = useEventBus()
eventBus.on('structure:data', ({ data, info }) => {
  console.log('数据已更新:', data)
})

事件监听

import { useEventBus } from './composables/useEventBus'

const eventBus = useEventBus()

// 监听表结构加载
eventBus.on('structure:loading', ({ loading }) => {
  if (loading) {
    console.log('开始加载表结构...')
  }
})

// 监听数据更新
eventBus.on('structure:data', ({ data, info }) => {
  console.log('表结构数据:', data)
  console.log('表信息:', info)
})

// 监听错误
eventBus.on('structure:error', ({ error }) => {
  console.error('加载失败:', error)
})

🔍 调试支持

日志追踪

所有状态变化和事件触发都有日志:

🏪 Store.setLoading: true
📢 事件触发 [structure:loading]: { loading: true }
🏪 Store.loadStructure 开始: { connectionId: 6, database: 'flux_pro', ... }
🏪 表结构加载成功: { ... }
🏪 Store.setData: { data: {...}, info: {...} }
📢 事件触发 [structure:data]: { data: {...}, info: {...} }

事件流追踪

通过事件总线可以追踪完整的数据流:

// 在开发模式下,可以在控制台看到所有事件
📢 事件触发 [structure:loading]: { loading: true }
📢 事件触发 [structure:data]: { data: {...}, info: {...} }
📢 事件触发 [structure:error]: { error: "..." }

测试清单

  • 表结构加载正常
  • 状态响应式正确
  • 事件触发正常
  • 错误处理正确
  • 类型检查通过
  • 构建通过
  • 调试代码已清理

📝 后续优化建议

1. 状态持久化

// 可以添加 localStorage 持久化
class StructureStore {
  saveToLocalStorage() {
    localStorage.setItem('structure:info', JSON.stringify(this.info.value))
  }
  
  loadFromLocalStorage() {
    const saved = localStorage.getItem('structure:info')
    if (saved) {
      this.info.value = JSON.parse(saved)
    }
  }
}

2. 状态回滚

// 添加状态历史记录
class StructureStore {
  private history: Array<{ data: any; info: StructureInfo }> = []
  
  saveSnapshot() {
    this.history.push({ data: this.data.value, info: this.info.value! })
  }
  
  rollback() {
    const snapshot = this.history.pop()
    if (snapshot) {
      this.setData(snapshot.data, snapshot.info)
    }
  }
}

3. 扩展到其他模块

  • SQL 执行结果 Store
  • 消息日志 Store
  • 连接管理 Store

🎓 最佳实践

  1. 使用 Store 而非 Composable 实例:单例模式确保状态一致性
  2. 通过事件监听状态变化:而非直接 watch Store 状态
  3. 保持 Store 方法原子性:一个方法只做一件事
  4. 使用类型安全的事件:充分利用 TypeScript
  5. 保留架构层日志:便于生产环境问题追踪

📚 相关文档


完成时间: 2026-01-03
架构版本: v2.0 (事件驱动架构)