313 lines
12 KiB
Markdown
313 lines
12 KiB
Markdown
|
||
# 数据库客户端前端架构设计文档
|
||
|
||
**文档版本**:v2.0
|
||
**维护者**:JueChen
|
||
**更新日期**:2026-01-28
|
||
**源码路径**:`go-desk/frontend/src/views/db-cli/`
|
||
|
||
---
|
||
|
||
## 一、整体架构概览
|
||
|
||
### 1.1 分层架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 视图层(Views) │
|
||
│ ┌──────────────────────────────────────────────────────┐ │
|
||
│ │ index.vue (主页面 - 布局和协调) │ │
|
||
│ └──────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 组件层(Components) │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ConnectionTree│ │ SqlEditor │ │ ResultPanel │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ConnectionForm│ │ResourceManager│ │ │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 组合式函数层(Composables) │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │useDbConnection│ │useSqlExecution│ │useEditorState│ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
│ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │useResultState │ │useMessageLog │ │
|
||
│ └──────────────┘ └──────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ API 层(Wails Bridge) │
|
||
│ ┌──────────────────────────────────────────────────────┐ │
|
||
│ │ window.go.main.App.* │ │
|
||
│ └──────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 1.2 架构设计原则
|
||
|
||
1. **单一职责原则**:每个组件和 composable 只负责一个功能领域
|
||
2. **关注点分离**:视图、逻辑、状态分离
|
||
3. **可复用性**:通过 composables 抽取可复用逻辑
|
||
4. **可维护性**:清晰的目录结构和命名规范
|
||
5. **可测试性**:composables 可以独立测试
|
||
|
||
---
|
||
|
||
## 二、目录结构
|
||
|
||
```
|
||
db-cli/
|
||
├── index.vue # 主页面(布局和协调)
|
||
├── components/ # 组件目录
|
||
│ ├── ConnectionTree.vue # 连接树组件
|
||
│ ├── ConnectionForm.vue # 连接表单组件
|
||
│ ├── SqlEditor.vue # SQL编辑器组件
|
||
│ ├── ResultPanel.vue # 结果展示组件
|
||
│ ├── ResourceManager.vue # 资源管理组件
|
||
│ └── ~~BookmarkManager.vue~~ # ❌ 已删除(书签功能已删除)
|
||
│ └── ~~TemplateManager.vue~~ # ❌ 已删除(模板功能已删除)
|
||
└── composables/ # 组合式函数目录
|
||
├── useDbConnection.ts # 连接管理逻辑
|
||
├── useSqlExecution.ts # SQL执行逻辑
|
||
├── useEditorState.ts # 编辑器状态管理
|
||
├── useResultState.ts # 结果状态管理
|
||
└── useMessageLog.ts # 消息日志管理
|
||
```
|
||
|
||
---
|
||
|
||
## 三、Composables 设计
|
||
|
||
### 3.1 useDbConnection.ts
|
||
|
||
**职责**:管理数据库连接相关的状态和逻辑
|
||
|
||
**状态**:
|
||
- `currentConnection`: 当前选中的连接
|
||
- `selectedDatabase`: 当前选中的数据库(MySQL)
|
||
- `showConnectionForm`: 连接表单显示状态
|
||
- `editingConnectionId`: 正在编辑的连接ID
|
||
|
||
**方法**:
|
||
- `selectConnection(conn, database)`: 选择连接
|
||
- `editConnection(connectionId)`: 编辑连接
|
||
- `deleteConnection(connectionId)`: 删除连接
|
||
- `newConnection()`: 新建连接
|
||
- `onConnectionSuccess()`: 连接操作成功回调
|
||
|
||
### 3.2 useSqlExecution.ts
|
||
|
||
**职责**:管理SQL执行相关的逻辑
|
||
|
||
**方法**:
|
||
- `executeSQL(sql, connection, database)`: 执行SQL
|
||
- `handleQueryResult(result)`: 处理查询结果
|
||
- `handleUpdateResult(result)`: 处理更新结果
|
||
- `handleCommandResult(result)`: 处理命令结果(Redis)
|
||
|
||
### 3.3 useEditorState.ts
|
||
|
||
**职责**:管理编辑器显示/隐藏状态
|
||
|
||
**状态**:
|
||
- `editorVisible`: 编辑器是否可见
|
||
|
||
**方法**:
|
||
- `toggleEditor()`: 切换编辑器显示/隐藏
|
||
- `loadEditorVisible()`: 从localStorage加载状态
|
||
- `saveEditorVisible()`: 保存状态到localStorage
|
||
|
||
### 3.4 useResultState.ts
|
||
|
||
**职责**:管理执行结果相关的状态
|
||
|
||
**状态**:
|
||
- `resultLoading`: 加载状态
|
||
- `resultError`: 错误信息
|
||
- `resultData`: 结果数据
|
||
- `resultMode`: 展示模式(table/json)
|
||
- `resultStats`: 执行统计
|
||
- `resultColumns`: 表格列定义
|
||
|
||
**方法**:
|
||
- `clearResults()`: 清空结果
|
||
- `setQueryResult(data, stats)`: 设置查询结果
|
||
- `setUpdateResult(stats)`: 设置更新结果
|
||
- `setCommandResult(data, stats)`: 设置命令结果
|
||
- `setError(error)`: 设置错误
|
||
|
||
### 3.5 useMessageLog.ts
|
||
|
||
**职责**:管理消息日志
|
||
|
||
**状态**:
|
||
- `messages`: 消息列表
|
||
|
||
**方法**:
|
||
- `addMessage(type, content)`: 添加消息
|
||
- `clearMessages()`: 清空消息
|
||
- `getMessages(limit)`: 获取消息(带限制)
|
||
|
||
---
|
||
|
||
## 四、组件通信设计
|
||
|
||
### 4.1 Props 向下传递
|
||
|
||
```
|
||
index.vue
|
||
├─ ConnectionTree
|
||
│ └─ currentConnectionId (prop)
|
||
├─ SqlEditor
|
||
│ └─ currentConnection (prop)
|
||
└─ ResultPanel
|
||
├─ loading (prop)
|
||
├─ error (prop)
|
||
├─ data (prop)
|
||
├─ mode (prop)
|
||
├─ stats (prop)
|
||
├─ columns (prop)
|
||
└─ messages (prop)
|
||
```
|
||
|
||
### 4.2 Events 向上传递
|
||
|
||
```
|
||
ConnectionTree
|
||
├─ @connection-select → index.vue
|
||
├─ @connection-edit → index.vue
|
||
├─ @connection-delete → index.vue
|
||
├─ @table-select → index.vue
|
||
├─ @new-connection → index.vue
|
||
└─ ~~@show-bookmarks, @show-templates~~ ❌ 已删除(功能已删除)
|
||
|
||
SqlEditor
|
||
├─ @execute → index.vue
|
||
├─ @execute-selected → index.vue
|
||
└─ @toggle-editor → index.vue
|
||
|
||
ResultPanel
|
||
└─ @toggle-editor → index.vue
|
||
```
|
||
|
||
### 4.3 Provide/Inject(可选)
|
||
|
||
对于深层嵌套的组件,可以使用 provide/inject:
|
||
|
||
```typescript
|
||
// index.vue
|
||
provide('dbCliContext', {
|
||
currentConnection,
|
||
selectedDatabase,
|
||
executeSQL,
|
||
addMessage
|
||
})
|
||
|
||
// 深层组件
|
||
const { currentConnection, executeSQL } = inject('dbCliContext')
|
||
```
|
||
|
||
---
|
||
|
||
## 五、状态管理流程
|
||
|
||
### 5.1 连接选择流程
|
||
|
||
```
|
||
用户点击连接
|
||
→ ConnectionTree 触发 @connection-select
|
||
→ index.vue 调用 useDbConnection.selectConnection()
|
||
→ 更新 currentConnection 和 selectedDatabase
|
||
→ 清空结果(useResultState.clearResults())
|
||
→ 添加消息(useMessageLog.addMessage())
|
||
→ SqlEditor 接收新的 currentConnection prop
|
||
```
|
||
|
||
### 5.2 SQL执行流程
|
||
|
||
```
|
||
用户执行SQL
|
||
→ SqlEditor 触发 @execute
|
||
→ index.vue 调用 useSqlExecution.executeSQL()
|
||
→ 调用 window.go.main.App.ExecuteSQL()
|
||
→ 根据结果类型调用对应的处理方法
|
||
→ useResultState 更新结果状态
|
||
→ ResultPanel 接收新的 props 并展示
|
||
```
|
||
|
||
---
|
||
|
||
## 六、重构优势
|
||
|
||
### 6.1 代码组织
|
||
|
||
- **清晰的职责划分**:每个 composable 负责一个功能领域
|
||
- **易于维护**:修改某个功能只需修改对应的 composable
|
||
- **代码复用**:composables 可以在其他页面复用
|
||
|
||
### 6.2 可测试性
|
||
|
||
- **独立测试**:每个 composable 可以独立测试
|
||
- **Mock 简单**:可以轻松 mock window.go API
|
||
- **测试覆盖**:逻辑集中在 composables,测试更容易
|
||
|
||
### 6.3 可扩展性
|
||
|
||
- **新增功能**:只需添加新的 composable
|
||
- **功能组合**:可以组合多个 composables 实现复杂功能
|
||
- **向后兼容**:不影响现有组件结构
|
||
|
||
---
|
||
|
||
## 七、实施步骤
|
||
|
||
### 步骤1:创建 composables 目录结构 ✅
|
||
- [x] 创建 `composables/` 目录
|
||
- [x] 创建 `useDbConnection.ts`
|
||
- [x] 创建 `useSqlExecution.ts`
|
||
- [x] 创建 `useEditorState.ts`
|
||
- [x] 创建 `useResultState.ts`
|
||
- [x] 创建 `useMessageLog.ts`
|
||
|
||
### 步骤2:重构主页面 ✅
|
||
- [x] 将状态管理逻辑迁移到 composables
|
||
- [x] 将业务逻辑迁移到 composables
|
||
- [x] 简化 index.vue,只保留布局和协调逻辑
|
||
|
||
### 步骤3:优化组件通信 ✅
|
||
- [x] 评估是否需要使用 provide/inject(当前不需要)
|
||
- [x] 优化 props 传递
|
||
- [x] 优化事件处理
|
||
|
||
### 步骤4:测试和验证 ⚠️
|
||
- [x] 功能测试(基本完成)
|
||
- [ ] 性能测试(待完成)
|
||
- [x] 代码审查(已完成)
|
||
|
||
---
|
||
|
||
## 八、后续优化方向
|
||
|
||
1. **状态管理库**:如果状态管理变得复杂,可以考虑引入 Pinia
|
||
2. **类型安全**:为 composables 添加完整的 TypeScript 类型定义
|
||
3. **错误处理**:统一错误处理机制
|
||
4. **性能优化**:使用 computed 和 watch 优化响应式更新
|
||
5. **单元测试**:为 composables 编写单元测试
|
||
|
||
---
|
||
|
||
## 九、参考文档
|
||
|
||
- [Vue 3 Composition API](https://vuejs.org/guide/extras/composition-api-faq.html)
|
||
- [Vue 3 Provide/Inject](https://vuejs.org/guide/components/provide-inject.html)
|
||
- [组件拆分方案](./组件拆分方案.md)
|
||
|