package admin_role import ( "context" "tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/types" "tydata-server/app/main/model" "tydata-server/common/xerr" "github.com/pkg/errors" "github.com/samber/lo" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/sqlx" ) type UpdateRoleLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewUpdateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateRoleLogic { return &UpdateRoleLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *UpdateRoleLogic) UpdateRole(req *types.UpdateRoleReq) (resp *types.UpdateRoleResp, err error) { // 检查角色是否存在 role, err := l.svcCtx.AdminRoleModel.FindOne(l.ctx, req.Id) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, errors.Wrapf(xerr.NewErrMsg("角色不存在"), "更新角色失败, 角色不存在err: %v", err) } return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新角色失败err: %v", err) } // 检查角色编码是否重复 if req.RoleCode != nil && *req.RoleCode != role.RoleCode { roleModel, err := l.svcCtx.AdminRoleModel.FindOneByRoleCode(l.ctx, *req.RoleCode) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新角色失败err: %v", err) } if roleModel != nil { return nil, errors.Wrapf(xerr.NewErrMsg("角色编码已存在"), "更新角色失败, 角色编码已存在err: %v", err) } } // 更新角色信息 if req.RoleName != nil { role.RoleName = *req.RoleName } if req.RoleCode != nil { role.RoleCode = *req.RoleCode } if req.Description != nil { role.Description = *req.Description } if req.Status != nil { role.Status = *req.Status } if req.Sort != nil { role.Sort = *req.Sort } // 使用事务更新角色和关联菜单 err = l.svcCtx.AdminRoleModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { // 更新角色 _, err = l.svcCtx.AdminRoleModel.Update(ctx, session, role) if err != nil { return err } if req.MenuIds != nil { // 1. 获取当前关联的菜单ID builder := l.svcCtx.AdminRoleMenuModel.SelectBuilder(). Where("role_id = ?", req.Id) currentMenus, err := l.svcCtx.AdminRoleMenuModel.FindAll(ctx, builder, "id ASC") if err != nil { return err } // 2. 转换为map便于查找 currentMenuMap := make(map[int64]*model.AdminRoleMenu) for _, menu := range currentMenus { currentMenuMap[menu.MenuId] = menu } // 3. 检查新的菜单ID是否存在 for _, menuId := range req.MenuIds { exists, err := l.svcCtx.AdminMenuModel.FindOne(ctx, menuId) if err != nil || exists == nil { return errors.Wrapf(xerr.NewErrMsg("菜单不存在"), "菜单ID: %d", menuId) } } // 4. 找出需要删除和新增的关联 var toDelete []*model.AdminRoleMenu var toInsert []int64 // 需要删除的:当前存在但新列表中没有的 for menuId, roleMenu := range currentMenuMap { if !lo.Contains(req.MenuIds, menuId) { toDelete = append(toDelete, roleMenu) } } // 需要新增的:新列表中有但当前不存在的 for _, menuId := range req.MenuIds { if _, exists := currentMenuMap[menuId]; !exists { toInsert = append(toInsert, menuId) } } // 5. 删除需要移除的关联 for _, roleMenu := range toDelete { err = l.svcCtx.AdminRoleMenuModel.Delete(ctx, session, roleMenu.Id) if err != nil { return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除角色菜单关联失败: %v", err) } } // 6. 添加新的关联 for _, menuId := range toInsert { roleMenu := &model.AdminRoleMenu{ RoleId: req.Id, MenuId: menuId, } _, err = l.svcCtx.AdminRoleMenuModel.Insert(ctx, session, roleMenu) if err != nil { return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "添加角色菜单关联失败: %v", err) } } } return nil }) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新角色失败err: %v", err) } return &types.UpdateRoleResp{ Success: true, }, nil }