package logic import ( "context" "errors" "fmt" "godemo/category/category" "godemo/category/internal/model" "godemo/category/internal/svc" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/sqlx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type DeleteCategoryLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewDeleteCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCategoryLogic { return &DeleteCategoryLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *DeleteCategoryLogic) DeleteCategory(in *category.DeleteCategoryRequest) (*category.DeleteResponse, error) { // 1. 参数校验 if in.Id == "" { return nil, status.Error(codes.InvalidArgument, "分类ID不能为空") } // 2. 检查分类是否存在 _, err := l.svcCtx.CategoryModel.FindOne(l.ctx, in.Id) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, status.Error(codes.NotFound, "分类不存在") } l.Logger.Errorf("查询分类失败: %v", err) return nil, status.Error(codes.Internal, "内部错误") } // 3. 开启事务执行删除 err = l.svcCtx.CategoryModel.Transact(l.ctx, func(ctx context.Context, session sqlx.Session) error { // 3.1 处理子分类(根据外键约束自动级联删除或设为NULL) if err := l.handleChildren(ctx, session, in.Id); err != nil { return err } // 3.2 删除主分类 if err := l.svcCtx.CategoryModel.WithSession(session).Delete(ctx, in.Id); err != nil { return fmt.Errorf("删除分类失败: %w", err) } return nil }) if err != nil { l.Logger.Errorf("删除分类事务失败: %v", err) return nil, status.Error(codes.Internal, "删除分类失败") } return &category.DeleteResponse{ Success: true, }, nil } // handleChildren 处理子分类(根据外键约束配置决定行为) func (l *DeleteCategoryLogic) handleChildren(ctx context.Context, session sqlx.Session, parentID string) error { // 如果外键是 ON DELETE SET NULL,需要显式更新子分类 if l.needUpdateChildren() { query := "UPDATE categories SET parent_id = NULL WHERE parent_id = $1" if _, err := session.ExecCtx(ctx, query, parentID); err != nil { return fmt.Errorf("更新子分类失败: %w", err) } } // 如果是 ON DELETE CASCADE 则无需额外处理 return nil } // needUpdateChildren 根据配置决定是否需要更新子分类 func (l *DeleteCategoryLogic) needUpdateChildren() bool { // 这里根据实际数据库外键约束配置返回 // 可以在 config 中添加配置项控制行为 return false // 默认假设是 ON DELETE CASCADE }