# 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