first commit
This commit is contained in:
270
.cursor/rules/logic.mdc
Normal file
270
.cursor/rules/logic.mdc
Normal file
@@ -0,0 +1,270 @@
|
||||
# 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"
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-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
|
||||
Reference in New Issue
Block a user