tyc-server/.cursor/rules/logic.mdc

271 lines
8.0 KiB
Plaintext
Raw Normal View History

2025-05-27 18:35:01 +08:00
# 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