190 lines
5.3 KiB
Markdown
190 lines
5.3 KiB
Markdown
# API 命名规范统一修复总结
|
||
|
||
## 📋 问题描述
|
||
|
||
前后端 API 字段命名风格不一致,导致前后端交互失败:
|
||
|
||
- **后端 Go JSON tags**: 使用 `snake_case` (如 `cluster_id`, `ca_data`)
|
||
- **OpenAPI 规范**: 使用 `camelCase` (如 `clusterId`, `caData`)
|
||
- **前端生成代码**: 使用 `camelCase`,与后端实际返回的JSON不匹配
|
||
- **前端手写代码**: 为了临时修复,手动使用 `snake_case`
|
||
|
||
## ✅ 解决方案
|
||
|
||
**选择方案B**: 统一使用 `snake_case` 作为业务数据字段命名规范
|
||
|
||
### 命名规范标准
|
||
|
||
1. **OpenAPI 自身规范字段**: 保持 `camelCase` (如 `operationId`, `requestBody`)
|
||
2. **业务数据字段**: 统一使用 `snake_case` (与后端 Go JSON tags 一致)
|
||
|
||
### 优势
|
||
|
||
- ✅ 保持后端代码不变,降低改动成本
|
||
- ✅ Go 的 JSON 序列化默认就是字段名,使用 snake_case 更符合 Go 生态
|
||
- ✅ 前端自动生成的代码与后端完全匹配
|
||
- ✅ 无需手动维护类型定义
|
||
|
||
## 🔧 修改内容
|
||
|
||
### 1. 后端 DTO (保持不变)
|
||
|
||
```go
|
||
// backend/internal/adapter/input/http/dto/cluster_dto.go
|
||
type CreateClusterRequest struct {
|
||
Name string `json:"name" binding:"required"`
|
||
Host string `json:"host" binding:"required"`
|
||
CAData string `json:"ca_data"` // ✅ snake_case
|
||
CertData string `json:"cert_data"` // ✅ snake_case
|
||
KeyData string `json:"key_data"` // ✅ snake_case
|
||
Token string `json:"token"`
|
||
Description string `json:"description"`
|
||
}
|
||
|
||
type ClusterResponse struct {
|
||
ID string `json:"id"`
|
||
Name string `json:"name"`
|
||
// ...
|
||
CreatedAt string `json:"created_at"` // ✅ snake_case
|
||
UpdatedAt string `json:"updated_at"` // ✅ snake_case
|
||
}
|
||
```
|
||
|
||
### 2. OpenAPI 规范修改
|
||
|
||
**修改文件**: `backend/docs/openapi.yaml`
|
||
|
||
#### 修改的 Schema:
|
||
|
||
1. **CreateClusterRequest**
|
||
- `caData` → `ca_data`
|
||
- `certData` → `cert_data`
|
||
- `keyData` → `key_data`
|
||
|
||
2. **UpdateClusterRequest**
|
||
- `caData` → `ca_data`
|
||
- `certData` → `cert_data`
|
||
- `keyData` → `key_data`
|
||
|
||
3. **ClusterResponse**
|
||
- `createdAt` → `created_at`
|
||
- `updatedAt` → `updated_at`
|
||
|
||
4. **RegistryResponse**
|
||
- `createdAt` → `created_at`
|
||
- `updatedAt` → `updated_at`
|
||
|
||
5. **UserResponse**
|
||
- `createdAt` → `created_at`
|
||
- `updatedAt` → `updated_at`
|
||
|
||
6. **InstanceResponse**
|
||
- `clusterId` → `cluster_id` ✅
|
||
- `registryId` → `registry_id` ✅ (新增字段)
|
||
- `repository` ✅ (新增字段)
|
||
|
||
### 3. 前端生成代码
|
||
|
||
重新生成前端 TypeScript API 客户端:
|
||
|
||
```bash
|
||
bash scripts/sync-openapi-frontend.sh
|
||
```
|
||
|
||
**生成结果**:
|
||
- ✅ 7 个 API 文件
|
||
- ✅ 25 个 Model 文件
|
||
- ✅ 完全匹配后端 JSON 字段命名
|
||
|
||
**示例生成代码**:
|
||
|
||
```typescript
|
||
// frontend/src/api/generated/models/create-cluster-request.ts
|
||
export interface CreateClusterRequest {
|
||
'name': string;
|
||
'host': string;
|
||
'ca_data'?: string; // ✅ snake_case
|
||
'cert_data'?: string; // ✅ snake_case
|
||
'key_data'?: string; // ✅ snake_case
|
||
'token'?: string;
|
||
}
|
||
|
||
// frontend/src/api/generated/models/instance-response.ts
|
||
export interface InstanceResponse {
|
||
'id'?: string;
|
||
'name'?: string;
|
||
'namespace'?: string;
|
||
'cluster_id'?: string; // ✅ snake_case
|
||
'registry_id'?: string; // ✅ snake_case
|
||
'repository'?: string;
|
||
// ...
|
||
}
|
||
```
|
||
|
||
## 📊 影响范围
|
||
|
||
### 已修改
|
||
|
||
1. ✅ `backend/docs/openapi.yaml` - OpenAPI 规范
|
||
2. ✅ `frontend/src/api/generated/*` - 自动生成的 TypeScript 代码
|
||
|
||
### 无需修改
|
||
|
||
1. ✅ 后端 Go DTO 代码 - 保持原有 snake_case
|
||
2. ✅ 前端手写的临时修复代码 - 现在可以使用生成的代码替换
|
||
|
||
## 🎯 后续工作
|
||
|
||
### 可选优化(前端)
|
||
|
||
前端中手写的类型定义现在可以删除,直接使用生成的代码:
|
||
|
||
**需要清理的文件**:
|
||
- `frontend/src/core/types/index.ts` - 包含手写的 snake_case 类型
|
||
- `frontend/src/core/api/instance.api.ts` - 包含手写的接口定义
|
||
- `frontend/src/core/api/unified-api.ts` - 包含手写的接口定义
|
||
|
||
**推荐做法**:
|
||
直接导入并使用自动生成的类型:
|
||
```typescript
|
||
import {
|
||
ClusterResponse,
|
||
CreateClusterRequest,
|
||
InstanceResponse
|
||
} from '@/api/generated';
|
||
```
|
||
|
||
## ✅ 验证
|
||
|
||
### 字段命名一致性检查
|
||
|
||
| 字段 | 后端 JSON | OpenAPI | 前端生成 | 状态 |
|
||
|------|-----------|---------|----------|------|
|
||
| `ca_data` | ✅ | ✅ | ✅ | 一致 |
|
||
| `cert_data` | ✅ | ✅ | ✅ | 一致 |
|
||
| `key_data` | ✅ | ✅ | ✅ | 一致 |
|
||
| `cluster_id` | ✅ | ✅ | ✅ | 一致 |
|
||
| `registry_id` | ✅ | ✅ | ✅ | 一致 |
|
||
| `created_at` | ✅ | ✅ | ✅ | 一致 |
|
||
| `updated_at` | ✅ | ✅ | ✅ | 一致 |
|
||
|
||
## 📝 注意事项
|
||
|
||
1. **OpenAPI 规范字段仍使用 camelCase**: 如 `operationId`, `requestBody` 等元字段
|
||
2. **业务数据字段统一 snake_case**: 所有 schemas 中的属性
|
||
3. **前端需更新代码**: 如果有直接使用手写类型的地方,需要切换到生成的类型
|
||
|
||
## 🔗 相关文件
|
||
|
||
- OpenAPI 规范: `backend/docs/openapi.yaml`
|
||
- 生成脚本: `scripts/sync-openapi-frontend.sh`
|
||
- 前端生成代码: `frontend/src/api/generated/`
|
||
- 后端 DTO: `backend/internal/adapter/input/http/dto/`
|
||
|
||
---
|
||
|
||
**修复日期**: 2025-11-10
|
||
**修复人**: AI Assistant
|
||
**影响版本**: OCDP v1.0.0
|
||
|