- 拆分 FileSystem.vue 为模块化组件架构 - 新增 Markdown Mermaid 图表渲染支持 - 新增 180+ 编程语言代码高亮 - 修复编辑/预览模式切换渲染问题 - 优化亮色/暗色模式主题适配 - 新增 TypeScript 类型定义
401 lines
9.0 KiB
Markdown
401 lines
9.0 KiB
Markdown
# 架构规范
|
||
|
||
**状态**:已确定
|
||
**最后更新**:2026-01-28
|
||
|
||
---
|
||
|
||
## 一、后端架构规范
|
||
|
||
### 1.1 分层架构
|
||
```
|
||
API层 (internal/api/)
|
||
↓
|
||
Service层 (internal/service/)
|
||
↓
|
||
Repository层 (internal/storage/repository/)
|
||
↓
|
||
Infrastructure层 (internal/dbclient/)
|
||
```
|
||
|
||
### 1.2 职责划分
|
||
|
||
#### API层
|
||
- **职责**:暴露给前端的接口
|
||
- **约束**:只负责参数验证和调用Service
|
||
- **文件命名**:`{功能}_api.go`
|
||
|
||
#### Service层
|
||
- **职责**:业务逻辑处理
|
||
- **约束**:不直接访问数据库,通过Repository
|
||
- **文件命名**:`{功能}_service.go`
|
||
|
||
#### Repository层
|
||
- **职责**:数据访问
|
||
- **约束**:只负责CRUD操作,不包含业务逻辑
|
||
- **文件命名**:`{模型}_repo.go`
|
||
|
||
#### Infrastructure层
|
||
- **职责**:基础设施(数据库客户端、连接池等)
|
||
- **约束**:提供统一的接口,隐藏实现细节
|
||
|
||
---
|
||
|
||
## 二、前端架构规范
|
||
|
||
### 2.1 组件结构
|
||
```
|
||
Views (views/db-cli/)
|
||
↓
|
||
Components (components/)
|
||
↓
|
||
Composables (composables/)
|
||
↓
|
||
Types (types/)
|
||
```
|
||
|
||
### 2.2 职责划分
|
||
|
||
#### Views
|
||
- **职责**:页面级组件,负责布局和状态协调
|
||
- **约束**:不包含具体业务逻辑
|
||
|
||
#### Components
|
||
- **职责**:可复用组件
|
||
- **约束**:组件应该是无状态的(通过props接收数据)
|
||
|
||
#### Composables
|
||
- **职责**:状态管理和业务逻辑
|
||
- **约束**:可复用的逻辑封装
|
||
|
||
#### Types
|
||
- **职责**:TypeScript类型定义
|
||
- **约束**:所有类型定义集中管理
|
||
|
||
---
|
||
|
||
## 三、事件系统规范
|
||
|
||
### 3.1 事件命名
|
||
- **格式**:`<组件>-<动作>` 或 `<功能>-<动作>`
|
||
- **示例**:`connection-select`、`table-structure`
|
||
|
||
### 3.2 事件参数
|
||
- **格式**:对象格式,不使用多个参数
|
||
- **类型**:所有事件都有TypeScript类型定义
|
||
- **位置**:`types/events.ts`
|
||
|
||
### 3.3 事件处理
|
||
- **位置**:在父组件中处理
|
||
- **职责**:调用相应的composable方法
|
||
|
||
---
|
||
|
||
## 四、架构设计美学原则
|
||
|
||
### 4.1 参数数量约束(最高优先级)
|
||
|
||
**原则**:方法参数不得超过 3 个,超过必须使用结构体/对象封装。
|
||
|
||
**违反示例**(不可接受):
|
||
```go
|
||
// ❌ 9个参数,完全不可接受
|
||
func SaveDbConnection(id uint, name, dbType, host string, port int, username, password, database, options string) error
|
||
```
|
||
|
||
**正确示例**:
|
||
```go
|
||
// ✅ 使用结构体封装
|
||
type SaveConnectionRequest struct {
|
||
ID uint
|
||
Name string
|
||
Type string
|
||
Host string
|
||
Port int
|
||
Username string
|
||
Password string
|
||
Database string
|
||
Options string
|
||
}
|
||
func SaveDbConnection(req SaveConnectionRequest) error
|
||
```
|
||
|
||
**前端同理**:
|
||
```typescript
|
||
// ❌ 参数过多
|
||
function saveConnection(id: number, name: string, type: string, host: string, port: number, username: string, password: string, database: string, options: string)
|
||
|
||
// ✅ 使用对象封装
|
||
interface SaveConnectionRequest {
|
||
id: number
|
||
name: string
|
||
type: string
|
||
host: string
|
||
port: number
|
||
username: string
|
||
password: string
|
||
database: string
|
||
options: string
|
||
}
|
||
function saveConnection(req: SaveConnectionRequest)
|
||
```
|
||
|
||
### 4.2 依赖注入美学
|
||
|
||
**原则**:减少手动依赖注入,优先使用自动依赖获取。
|
||
|
||
**当前问题**:
|
||
```typescript
|
||
// 需要手动注入依赖
|
||
const { executeSQL } = useSqlExecution(resultState, messageLog)
|
||
```
|
||
|
||
**优化方向**:
|
||
```typescript
|
||
// 内部自动获取依赖(通过 provide/inject 或全局状态)
|
||
const { executeSQL } = useSqlExecution()
|
||
```
|
||
|
||
### 4.3 代码简洁性
|
||
|
||
**原则**:代码应该简洁、直接、易于理解。
|
||
|
||
**要求**:
|
||
- 避免过度抽象
|
||
- 减少中间层
|
||
- 直接表达意图
|
||
- 移除不必要的包装
|
||
|
||
### 4.4 一致性原则
|
||
|
||
**原则**:相同功能在不同实现中保持一致的命名和结构。
|
||
|
||
**要求**:
|
||
- 统一的错误处理方式
|
||
- 统一的命名规范
|
||
- 统一的数据结构
|
||
- 统一的接口风格
|
||
|
||
### 4.5 可组合性
|
||
|
||
**原则**:Composables 应该可以独立使用,也可以组合使用。
|
||
|
||
**要求**:
|
||
- Composables 之间依赖关系清晰
|
||
- 支持按需组合
|
||
- 避免循环依赖
|
||
- 提供清晰的组合模式
|
||
|
||
---
|
||
|
||
## 五、架构优化建议
|
||
|
||
### 5.1 后端 API 层优化(高优先级)
|
||
|
||
**问题**:API 方法参数过多,违反设计美学。
|
||
|
||
**优化方案**:
|
||
1. 所有 API 方法参数超过 3 个时,必须使用请求结构体
|
||
2. 统一请求/响应结构体命名:`{Action}Request` / `{Action}Response`
|
||
3. 结构体定义放在对应的 API 文件中
|
||
|
||
**示例**:
|
||
```go
|
||
// connection_api.go
|
||
type SaveConnectionRequest struct {
|
||
ID uint `json:"id"`
|
||
Name string `json:"name"`
|
||
Type string `json:"type"`
|
||
Host string `json:"host"`
|
||
Port int `json:"port"`
|
||
Username string `json:"username"`
|
||
Password string `json:"password"`
|
||
Database string `json:"database"`
|
||
Options string `json:"options"`
|
||
}
|
||
|
||
func (api *ConnectionAPI) SaveDbConnection(req SaveConnectionRequest) error {
|
||
conn := &models.DbConnection{
|
||
ID: req.ID,
|
||
Name: req.Name,
|
||
Type: req.Type,
|
||
Host: req.Host,
|
||
Port: req.Port,
|
||
Username: req.Username,
|
||
Password: req.Password,
|
||
Database: req.Database,
|
||
Options: req.Options,
|
||
}
|
||
return api.connService.SaveConnection(conn)
|
||
}
|
||
```
|
||
|
||
### 5.2 前端 Composables 依赖优化(中优先级)
|
||
|
||
**问题**:需要手动注入依赖,使用不够优雅。
|
||
|
||
**优化方案**:
|
||
1. 使用 `provide/inject` 或全局状态管理依赖
|
||
2. Composables 内部自动获取依赖
|
||
3. 保持向后兼容,支持手动注入
|
||
|
||
**示例**:
|
||
```typescript
|
||
// 使用 provide/inject
|
||
const resultState = useResultState()
|
||
const messageLog = useMessageLog()
|
||
|
||
provide('resultState', resultState)
|
||
provide('messageLog', messageLog)
|
||
|
||
// useSqlExecution 内部自动获取
|
||
export function useSqlExecution() {
|
||
const resultState = inject<ReturnType<typeof useResultState>>('resultState')
|
||
const messageLog = inject<ReturnType<typeof useMessageLog>>('messageLog')
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### 5.3 Service 层验证逻辑提取(中优先级)
|
||
|
||
**问题**:验证逻辑分散在 Service 方法中,代码重复。
|
||
|
||
**优化方案**:
|
||
1. 创建独立的验证器(Validator)
|
||
2. 统一验证错误格式
|
||
3. 可复用的验证规则
|
||
|
||
**示例**:
|
||
```go
|
||
// validator/connection_validator.go
|
||
type ConnectionValidator struct{}
|
||
|
||
func (v *ConnectionValidator) ValidateSave(conn *models.DbConnection) error {
|
||
if conn.Name == "" {
|
||
return fmt.Errorf("连接名称不能为空")
|
||
}
|
||
if conn.Type == "" {
|
||
return fmt.Errorf("数据库类型不能为空")
|
||
}
|
||
if conn.Host == "" {
|
||
return fmt.Errorf("主机地址不能为空")
|
||
}
|
||
return nil
|
||
}
|
||
```
|
||
|
||
### 5.4 Composables 组合优化(低优先级)
|
||
|
||
**问题**:`index.vue` 中 composables 较多,可以进一步抽象。
|
||
|
||
**优化方案**:
|
||
1. 创建 `useDbCli` composable 作为统一入口
|
||
2. 内部组合所有相关 composables
|
||
3. 提供简洁的 API
|
||
|
||
**示例**:
|
||
```typescript
|
||
// composables/useDbCli.ts
|
||
export function useDbCli() {
|
||
const connection = useDbConnection()
|
||
const editor = useEditorState()
|
||
const result = useResultState()
|
||
const message = useMessageLog()
|
||
const sql = useSqlExecution(result, message)
|
||
const structure = useStructureState()
|
||
const structureEdit = useStructureEdit()
|
||
|
||
return {
|
||
connection,
|
||
editor,
|
||
result,
|
||
message,
|
||
sql,
|
||
structure,
|
||
structureEdit
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、架构检查清单
|
||
|
||
### 开发优先原则检查
|
||
- [ ] 是否使用了 Vue 的响应式系统管理状态?
|
||
- [ ] 是否使用了模板引用而非 DOM 查询?
|
||
- [ ] 是否在正确的时机执行操作(通过 `nextTick`、`requestAnimationFrame` 等)?
|
||
- [ ] 是否移除了不必要的重试循环?
|
||
- [ ] 是否移除了过多的条件检查和兜底逻辑?
|
||
- [ ] 代码是否简洁直接,易于理解?
|
||
- [ ] 是否避免了防御性编程模式?
|
||
|
||
### 后端检查
|
||
- [ ] API 方法参数不超过 3 个,超过使用结构体封装
|
||
- [ ] 所有请求/响应结构体命名统一
|
||
- [ ] Service 层验证逻辑清晰
|
||
- [ ] 错误处理统一
|
||
|
||
### 前端检查
|
||
- [ ] Composables 依赖关系清晰
|
||
- [ ] 减少手动依赖注入
|
||
- [ ] 代码简洁直接
|
||
- [ ] 类型定义完善
|
||
|
||
### 设计美学检查
|
||
- [ ] 参数数量符合约束(≤3)
|
||
- [ ] 代码简洁易读
|
||
- [ ] 命名一致统一
|
||
- [ ] 结构清晰优雅
|
||
|
||
---
|
||
|
||
## 四、数据流规范
|
||
|
||
### 4.1 数据流向
|
||
```
|
||
用户操作
|
||
↓
|
||
组件事件
|
||
↓
|
||
Composable方法
|
||
↓
|
||
API调用
|
||
↓
|
||
后端Service
|
||
↓
|
||
Repository
|
||
↓
|
||
数据库
|
||
```
|
||
|
||
### 4.2 状态管理
|
||
- **原则**:使用Composables管理状态
|
||
- **位置**:`composables/` 目录
|
||
- **命名**:`use{功能}State.ts`
|
||
|
||
---
|
||
|
||
## 五、约束条件
|
||
|
||
### 5.1 后端约束
|
||
- 方法参数不超过3个
|
||
- 不返回 `RetResult<Void>` 类型
|
||
- 使用分层架构,职责分离
|
||
|
||
### 5.2 前端约束
|
||
- 使用Arco基础样式
|
||
- 事件参数使用对象格式
|
||
- 所有事件有类型定义
|
||
|
||
---
|
||
|
||
## 六、检查清单
|
||
|
||
### 架构检查
|
||
- [ ] 分层架构清晰
|
||
- [ ] 职责分离明确
|
||
- [ ] 依赖方向正确
|
||
- [ ] 符合架构规范
|
||
|