271 lines
8.0 KiB
Plaintext
271 lines
8.0 KiB
Plaintext
# Your rule content
|
||
|
||
- You can @ files here
|
||
- You can use markdown but dont have to
|
||
|
||
# Logic 实现规范
|
||
|
||
## 目录结构
|
||
```
|
||
app/main/api/internal/logic/
|
||
├── admin_notification/ # 通知管理模块
|
||
│ ├── admincreatenotificationlogic.go # 创建通知
|
||
│ ├── admindeletnotificationlogic.go # 删除通知
|
||
│ ├── admingetnotificationdetaillogic.go # 获取通知详情
|
||
│ ├── admingetnotificationlistlogic.go # 获取通知列表
|
||
│ └── adminupdatenotificationlogic.go # 更新通知
|
||
└── [其他模块]/
|
||
```
|
||
|
||
## Logic 实现规范
|
||
|
||
### 1. 基础结构
|
||
每个 Logic 文件都应包含以下基础结构:
|
||
```go
|
||
package [模块名]
|
||
|
||
import (
|
||
"context"
|
||
"tyc-server/app/main/api/internal/svc"
|
||
"tyc-server/app/main/api/internal/types"
|
||
"tyc-server/common/xerr"
|
||
"github.com/pkg/errors"
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
)
|
||
|
||
type [操作名]Logic struct {
|
||
logx.Logger
|
||
ctx context.Context
|
||
svcCtx *svc.ServiceContext
|
||
}
|
||
|
||
func New[操作名]Logic(ctx context.Context, svcCtx *svc.ServiceContext) *[操作名]Logic {
|
||
return &[操作名]Logic{
|
||
Logger: logx.WithContext(ctx),
|
||
ctx: ctx,
|
||
svcCtx: svcCtx,
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 增删改查实现规范
|
||
|
||
#### 2.1 创建操作(Create)
|
||
```go
|
||
func (l *[操作名]Logic) [操作名](req *types.[操作名]Req) (resp *types.[操作名]Resp, err error) {
|
||
// 1. 数据转换和验证
|
||
data := &model.[表名]{
|
||
Field1: req.Field1,
|
||
Field2: req.Field2,
|
||
// ... 其他字段映射
|
||
}
|
||
|
||
// 2. 数据库操作
|
||
result, err := l.svcCtx.[表名]Model.Insert(l.ctx, nil, data)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"创建[操作对象]失败, err: %v, req: %+v", err, req)
|
||
}
|
||
|
||
// 3. 返回结果
|
||
id, _ := result.LastInsertId()
|
||
return &types.[操作名]Resp{Id: id}, nil
|
||
}
|
||
```
|
||
|
||
#### 2.2 删除操作(Delete)
|
||
```go
|
||
func (l *[操作名]Logic) [操作名](req *types.[操作名]Req) (resp *types.[操作名]Resp, err error) {
|
||
// 1. 查询记录是否存在
|
||
record, err := l.svcCtx.[表名]Model.FindOne(l.ctx, req.Id)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"查找[操作对象]失败, err: %v, id: %d", err, req.Id)
|
||
}
|
||
|
||
// 2. 执行删除操作(软删除)
|
||
err = l.svcCtx.[表名]Model.DeleteSoft(l.ctx, nil, record)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"删除[操作对象]失败, err: %v, id: %d", err, req.Id)
|
||
}
|
||
|
||
// 3. 返回结果
|
||
return &types.[操作名]Resp{Success: true}, nil
|
||
}
|
||
```
|
||
|
||
#### 2.3 更新操作(Update)
|
||
```go
|
||
func (l *[操作名]Logic) [操作名](req *types.[操作名]Req) (resp *types.[操作名]Resp, err error) {
|
||
// 1. 查询记录是否存在
|
||
record, err := l.svcCtx.[表名]Model.FindOne(l.ctx, req.Id)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"查找[操作对象]失败, err: %v, id: %d", err, req.Id)
|
||
}
|
||
|
||
// 2. 更新字段(使用指针判断是否更新)
|
||
if req.Field1 != nil {
|
||
record.Field1 = *req.Field1
|
||
}
|
||
if req.Field2 != nil {
|
||
record.Field2 = *req.Field2
|
||
}
|
||
// ... 其他字段更新
|
||
|
||
// 3. 执行更新操作
|
||
_, err = l.svcCtx.[表名]Model.Update(l.ctx, nil, record)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"更新[操作对象]失败, err: %v, req: %+v", err, req)
|
||
}
|
||
|
||
// 4. 返回结果
|
||
return &types.[操作名]Resp{Success: true}, nil
|
||
}
|
||
```
|
||
|
||
#### 2.4 查询详情(GetDetail)
|
||
```go
|
||
func (l *[操作名]Logic) [操作名](req *types.[操作名]Req) (resp *types.[操作名]Resp, err error) {
|
||
// 1. 查询记录
|
||
record, err := l.svcCtx.[表名]Model.FindOne(l.ctx, req.Id)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"查找[操作对象]失败, err: %v, id: %d", err, req.Id)
|
||
}
|
||
|
||
// 2. 构建响应
|
||
resp = &types.[操作名]Resp{
|
||
Id: record.Id,
|
||
Field1: record.Field1,
|
||
Field2: record.Field2,
|
||
CreateTime: record.CreateTime.Format("2006-01-02 15:04:05"),
|
||
UpdateTime: record.UpdateTime.Format("2006-01-02 15:04:05"),
|
||
}
|
||
|
||
// 3. 处理可选字段(如时间字段)
|
||
if record.OptionalField.Valid {
|
||
resp.OptionalField = record.OptionalField.Time.Format("2006-01-02")
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
```
|
||
|
||
#### 2.5 查询列表(GetList)
|
||
```go
|
||
func (l *[操作名]Logic) [操作名](req *types.[操作名]Req) (resp *types.[操作名]Resp, err error) {
|
||
// 1. 构建查询条件
|
||
builder := l.svcCtx.[表名]Model.SelectBuilder()
|
||
|
||
// 2. 添加查询条件(使用指针判断是否添加条件)
|
||
if req.Field1 != nil {
|
||
builder = builder.Where("field1 LIKE ?", "%"+*req.Field1+"%")
|
||
}
|
||
if req.Field2 != nil {
|
||
builder = builder.Where("field2 = ?", *req.Field2)
|
||
}
|
||
// ... 其他查询条件
|
||
|
||
// 3. 执行分页查询
|
||
list, total, err := l.svcCtx.[表名]Model.FindPageListByPageWithTotal(
|
||
l.ctx, builder, req.Page, req.PageSize, "id DESC")
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||
"查询[操作对象]列表失败, err: %v, req: %+v", err, req)
|
||
}
|
||
|
||
// 4. 构建响应列表
|
||
items := make([]types.[列表项类型], 0, len(list))
|
||
for _, item := range list {
|
||
listItem := types.[列表项类型]{
|
||
Id: item.Id,
|
||
Field1: item.Field1,
|
||
Field2: item.Field2,
|
||
CreateTime: item.CreateTime.Format("2006-01-02 15:04:05"),
|
||
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
|
||
}
|
||
// 处理可选字段
|
||
if item.OptionalField.Valid {
|
||
listItem.OptionalField = item.OptionalField.Time.Format("2006-01-02")
|
||
}
|
||
items = append(items, listItem)
|
||
}
|
||
|
||
// 5. 返回结果
|
||
return &types.[操作名]Resp{
|
||
Total: total,
|
||
Items: items,
|
||
}, nil
|
||
}
|
||
```
|
||
|
||
### 3. 错误处理规范
|
||
1. 使用 `errors.Wrapf` 包装错误
|
||
2. 使用 `xerr.NewErrCode` 创建业务错误
|
||
3. 错误信息应包含:
|
||
- 操作类型(创建/更新/删除/查询)
|
||
- 具体错误描述
|
||
- 相关参数信息(ID、请求参数等)
|
||
|
||
### 4. 时间处理规范
|
||
1. 时间格式化:
|
||
- 日期时间:`"2006-01-02 15:04:05"`
|
||
- 仅日期:`"2006-01-02"`
|
||
2. 可选时间字段处理:
|
||
```go
|
||
if field.Valid {
|
||
resp.Field = field.Time.Format("2006-01-02")
|
||
}
|
||
```
|
||
|
||
### 5. 数据库操作规范
|
||
1. 查询条件构建:
|
||
```go
|
||
builder := l.svcCtx.[表名]Model.SelectBuilder()
|
||
builder = builder.Where("field = ?", value)
|
||
```
|
||
2. 分页查询:
|
||
```go
|
||
list, total, err := l.svcCtx.[表名]Model.FindPageListByPageWithTotal(
|
||
ctx, builder, page, pageSize, "id DESC")
|
||
```
|
||
3. 事务处理:
|
||
```go
|
||
err = l.svcCtx.[表名]Model.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||
// 事务操作
|
||
return nil
|
||
})
|
||
```
|
||
|
||
### 6. 并发处理规范
|
||
```go
|
||
var mu sync.Mutex
|
||
err = mr.MapReduceVoid(func(source chan<- interface{}) {
|
||
// 并发处理
|
||
}, func(item interface{}, writer mr.Writer[struct{}], cancel func(error)) {
|
||
// 处理单个项目
|
||
}, func(pipe <-chan struct{}, cancel func(error)) {
|
||
// 完成处理
|
||
})
|
||
```
|
||
|
||
### 7. 注意事项
|
||
1. 所有数据库操作必须进行错误处理
|
||
2. 更新操作必须使用指针类型判断字段是否更新
|
||
3. 查询列表必须支持分页
|
||
4. 时间字段必须统一格式化
|
||
5. 可选字段必须进行空值判断
|
||
6. 保持代码风格统一,添加必要的注释
|
||
7. 涉及多表操作时使用事务
|
||
8. 并发操作时注意使用互斥锁保护共享资源
|
||
9. 错误处理必须使用 errors.Wrapf 和 xerr 包
|
||
10. 时间类型统一使用 "2006-01-02 15:04:05" 格式
|
||
|
||
# Your rule content
|
||
|
||
- You can @ files here
|
||
- You can use markdown but dont have to
|