337 lines
8.4 KiB
Markdown
337 lines
8.4 KiB
Markdown
# 快速开发指南
|
||
|
||
## 添加新配置模块的5分钟快速步骤
|
||
|
||
假设要添加 `PaymentConfig` (支付配置) 模块。
|
||
|
||
### 步骤 1: 创建模型 (30秒)
|
||
**文件**: `internal/models/payment_config.go`
|
||
|
||
复制 `user_level_config.go`,替换类名和字段即可。
|
||
|
||
### 步骤 2: 创建存储层 (1分钟)
|
||
**文件**: `internal/storage/payment_config_storage.go`
|
||
|
||
复制 `user_level_config_storage.go`,改成新的模型名称。
|
||
|
||
### 步骤 3: 创建服务层 (1分钟)
|
||
**文件**: `internal/services/payment_config_service.go`
|
||
|
||
复制 `user_level_config_service.go`,改成新的存储和模型名称。
|
||
|
||
### 步骤 4: 创建 Handler (1分钟)
|
||
**文件**: `internal/api/handlers/payment_config_handler.go`
|
||
|
||
复制 `user_level_config_handler.go`,改成新的服务名称。
|
||
|
||
### 步骤 5: 注册路由 (1分钟)
|
||
在 `internal/api/routes/routes.go` 中的 `SetupRoutes` 函数中添加:
|
||
|
||
```go
|
||
paymentConfigHandler := handlers.NewPaymentConfigHandler(paymentConfigService, logger)
|
||
|
||
paymentConfigs := admin.Group("/payment-configs")
|
||
{
|
||
paymentConfigs.GET("", paymentConfigHandler.List)
|
||
paymentConfigs.POST("", paymentConfigHandler.Create)
|
||
paymentConfigs.GET("/:id", paymentConfigHandler.GetByID)
|
||
paymentConfigs.PUT("/:id", paymentConfigHandler.Update)
|
||
paymentConfigs.DELETE("/:id", paymentConfigHandler.Delete)
|
||
}
|
||
```
|
||
|
||
### 步骤 6: 在 main.go 中注册服务 (30秒)
|
||
|
||
```go
|
||
paymentConfigService := services.NewPaymentConfigService(
|
||
storage.NewPaymentConfigStorage(),
|
||
logger,
|
||
)
|
||
|
||
router := routes.SetupRoutes(
|
||
// ... 其他服务
|
||
paymentConfigService,
|
||
// ...
|
||
)
|
||
```
|
||
|
||
### 步骤 7: 添加数据库迁移 (30秒)
|
||
|
||
在 `internal/storage/database.go` 的 `AutoMigrate` 中:
|
||
|
||
```go
|
||
err := DB.AutoMigrate(
|
||
&models.UserLevelConfig{},
|
||
&models.PaymentConfig{}, // 新增
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## 文件复制清单
|
||
|
||
使用这个检查清单确保没有遗漏:
|
||
|
||
```
|
||
[ ] 创建模型文件 internal/models/payment_config.go
|
||
[ ] 定义主模型结构体
|
||
[ ] 定义 CreateRequest 结构体
|
||
[ ] 定义 UpdateRequest 结构体
|
||
[ ] 定义 ListRequest 结构体
|
||
[ ] 设置 TableName()
|
||
|
||
[ ] 创建存储文件 internal/storage/payment_config_storage.go
|
||
[ ] 定义接口
|
||
[ ] 实现 Create
|
||
[ ] 实现 GetByID
|
||
[ ] 实现 Update
|
||
[ ] 实现 Delete
|
||
[ ] 实现 List
|
||
|
||
[ ] 创建服务文件 internal/services/payment_config_service.go
|
||
[ ] 定义接口
|
||
[ ] 实现 Create(包含验证)
|
||
[ ] 实现 GetByID
|
||
[ ] 实现 Update
|
||
[ ] 实现 Delete
|
||
[ ] 实现 List
|
||
|
||
[ ] 创建处理器 internal/api/handlers/payment_config_handler.go
|
||
[ ] 实现 Create
|
||
[ ] 实现 GetByID
|
||
[ ] 实现 Update
|
||
[ ] 实现 Delete
|
||
[ ] 实现 List
|
||
|
||
[ ] 在 routes.go 中注册路由
|
||
[ ] 在 SetupRoutes 函数签名中添加参数
|
||
[ ] 创建 Handler 实例
|
||
[ ] 定义路由组
|
||
[ ] 添加所有 CRUD 路由
|
||
|
||
[ ] 在 main.go 中注册服务
|
||
[ ] 创建 Storage 实例
|
||
[ ] 创建 Service 实例
|
||
[ ] 在 SetupRoutes 调用中传入 Service
|
||
|
||
[ ] 在 database.go 中添加迁移
|
||
[ ] 在 AutoMigrate 中添加模型
|
||
```
|
||
|
||
---
|
||
|
||
## API 端点快速查询
|
||
|
||
### 用户等级配置模块已有端点
|
||
|
||
```
|
||
GET /api/admin/user-level-configs 列表(分页)
|
||
GET /api/admin/user-level-configs/all 列表(不分页)
|
||
POST /api/admin/user-level-configs 创建
|
||
GET /api/admin/user-level-configs/:id 详情
|
||
PUT /api/admin/user-level-configs/:id 更新
|
||
DELETE /api/admin/user-level-configs/:id 删除
|
||
PUT /api/admin/user-level-configs/:id/status 更新状态
|
||
```
|
||
|
||
### 新模块应该实现
|
||
|
||
```
|
||
GET /api/admin/[resource-name] 列表(分页)
|
||
POST /api/admin/[resource-name] 创建
|
||
GET /api/admin/[resource-name]/:id 详情
|
||
PUT /api/admin/[resource-name]/:id 更新
|
||
DELETE /api/admin/[resource-name]/:id 删除
|
||
```
|
||
|
||
---
|
||
|
||
## 常见错误排查
|
||
|
||
### 1. 导包错误
|
||
确保在每个文件顶部都有正确的导入:
|
||
|
||
```go
|
||
import (
|
||
"goalfymax-admin/internal/models"
|
||
"goalfymax-admin/internal/storage"
|
||
"goalfymax-admin/internal/services"
|
||
"goalfymax-admin/pkg/utils"
|
||
)
|
||
```
|
||
|
||
### 2. Handler 没有注册
|
||
- 在 `SetupRoutes` 中创建了 Handler 实例吗?
|
||
- Handler 实例是否传给了路由组?
|
||
|
||
### 3. Service 没有注册
|
||
- 在 `main.go` 中创建了 Service 实例吗?
|
||
- Service 实例是否传给了 `SetupRoutes`?
|
||
|
||
### 4. 迁移失败
|
||
- 模型定义中是否有 `TableName()` 方法?
|
||
- 是否在 `database.go` 的 `AutoMigrate` 中添加了模型?
|
||
|
||
### 5. 字段验证不生效
|
||
检查请求模型中的 `binding` tag:
|
||
- `required` - 必填
|
||
- `min=1,max=100` - 长度限制
|
||
- `email` - 邮箱格式
|
||
|
||
---
|
||
|
||
## 测试新模块
|
||
|
||
### 使用 curl 测试
|
||
|
||
```bash
|
||
# 创建
|
||
curl -X POST http://localhost:8087/api/admin/payment-configs \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"key":"stripe_key","value":"sk_test_xxx","type":"string"}'
|
||
|
||
# 列表
|
||
curl http://localhost:8087/api/admin/payment-configs
|
||
|
||
# 详情
|
||
curl http://localhost:8087/api/admin/payment-configs/1
|
||
|
||
# 更新
|
||
curl -X PUT http://localhost:8087/api/admin/payment-configs/1 \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"key":"stripe_key","value":"sk_test_yyy"}'
|
||
|
||
# 删除
|
||
curl -X DELETE http://localhost:8087/api/admin/payment-configs/1
|
||
```
|
||
|
||
---
|
||
|
||
## 关键对比表
|
||
|
||
### Models 文件
|
||
|
||
| 用户等级配置 | 新模块 |
|
||
|-----------|--------|
|
||
| `user_level_config.go` | `payment_config.go` |
|
||
| `UserLevelConfig` | `PaymentConfig` |
|
||
| `UserLevelConfigCreateRequest` | `PaymentConfigCreateRequest` |
|
||
| `admin_user_level_configs` | `admin_payment_configs` |
|
||
|
||
### Storage 文件
|
||
|
||
| 用户等级配置 | 新模块 |
|
||
|-----------|--------|
|
||
| `user_level_config_storage.go` | `payment_config_storage.go` |
|
||
| `UserLevelConfigStorage` | `PaymentConfigStorage` |
|
||
| `NewUserLevelConfigStorage()` | `NewPaymentConfigStorage()` |
|
||
|
||
### Service 文件
|
||
|
||
| 用户等级配置 | 新模块 |
|
||
|-----------|--------|
|
||
| `user_level_config_service.go` | `payment_config_service.go` |
|
||
| `UserLevelConfigService` | `PaymentConfigService` |
|
||
| `NewUserLevelConfigService()` | `NewPaymentConfigService()` |
|
||
|
||
### Handler 文件
|
||
|
||
| 用户等级配置 | 新模块 |
|
||
|-----------|--------|
|
||
| `user_level_config_handler.go` | `payment_config_handler.go` |
|
||
| `UserLevelConfigHandler` | `PaymentConfigHandler` |
|
||
| `NewUserLevelConfigHandler()` | `NewPaymentConfigHandler()` |
|
||
|
||
### Routes 注册
|
||
|
||
| 用户等级配置 | 新模块 |
|
||
|-----------|--------|
|
||
| `/user-level-configs` | `/payment-configs` |
|
||
| `userLevelConfigHandler` | `paymentConfigHandler` |
|
||
| `userLevelConfigService` | `paymentConfigService` |
|
||
|
||
---
|
||
|
||
## 模板代码片段
|
||
|
||
### 最小模型
|
||
|
||
```go
|
||
package models
|
||
|
||
import "time"
|
||
|
||
type PaymentConfig struct {
|
||
ID uint `json:"id" gorm:"primaryKey;autoIncrement"`
|
||
Key string `json:"key" gorm:"uniqueIndex;not null"`
|
||
Value string `json:"value" gorm:"type:longtext"`
|
||
CreatedAt time.Time `json:"created_at"`
|
||
UpdatedAt time.Time `json:"updated_at"`
|
||
}
|
||
|
||
func (PaymentConfig) TableName() string {
|
||
return "admin_payment_configs"
|
||
}
|
||
```
|
||
|
||
### 最小 Handler 方法
|
||
|
||
```go
|
||
func (h *PaymentConfigHandler) Create(c *gin.Context) {
|
||
var req models.PaymentConfigCreateRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
h.response.ValidateError(c, err)
|
||
return
|
||
}
|
||
|
||
result, err := h.service.Create(&req)
|
||
if err != nil {
|
||
h.response.InternalServerError(c, err.Error())
|
||
return
|
||
}
|
||
|
||
h.response.Success(c, result)
|
||
}
|
||
```
|
||
|
||
### 最小 Service 方法
|
||
|
||
```go
|
||
func (s *paymentConfigService) Create(req *models.PaymentConfigCreateRequest) (*models.PaymentConfig, error) {
|
||
config := &models.PaymentConfig{
|
||
Key: req.Key,
|
||
Value: req.Value,
|
||
}
|
||
|
||
if err := s.storage.Create(config); err != nil {
|
||
s.logger.Error("创建支付配置失败", zap.Error(err))
|
||
return nil, errors.New("创建失败")
|
||
}
|
||
|
||
return config, nil
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 内存关键点
|
||
|
||
1. **三层架构**: Handler -> Service -> Storage
|
||
2. **接口优先**: Service 和 Storage 都是接口
|
||
3. **命名规范**: `admin_[resource]s` 表名
|
||
4. **错误处理**: Service 返回有意义的错误,Handler 返回 HTTP 响应
|
||
5. **日志**: 每个操作都要记录日志
|
||
6. **验证**: Binding tag + Service 层验证
|
||
|
||
---
|
||
|
||
## 下一步
|
||
|
||
如需添加新的配置模块,只需:
|
||
1. 复制现有配置模块(如 `user_level_config`)
|
||
2. 全量替换类名和结构
|
||
3. 调整业务逻辑验证(如果有的话)
|
||
4. 完成!
|
||
|
||
预计耗时:5-10分钟
|