package admin import ( "context" "server/internal/db" "server/internal/db/sqlc" "server/internal/model/common" "server/internal/model/enum" "server/internal/model/request" "server/internal/pkg/cache" "server/internal/pkg/cache/cachekey" "server/internal/pkg/dberr" "server/internal/pkg/errs" ) type MenuService struct { store *db.Store cache *cache.Caches } func NewMenuService(store *db.Store, cache *cache.Caches) *MenuService { return &MenuService{ store: store, cache: cache, } } func (s *MenuService) Create(ctx context.Context, req request.CreateMenuRequest) error { err := s.store.WithTx(ctx, func(q *sqlc.Queries) error { menu := sqlc.CreateMenuParams{ Name: req.Name, Path: req.Path, Component: req.Component, Type: *req.Type, Status: *req.Status, Hidden: req.Hidden, Sort: req.Sort, Icon: req.Icon, ParentID: req.ParentID, } // 先创建权限 permissionId, err := q.CreatePermission(ctx, sqlc.CreatePermissionParams{ Type: int16(enum.PermissionTypeMenu), Code: &req.PermissionCode, }) // code重复性校验 if err != nil { return dberr.MapUniqueViolation(err, dberr.SysPermissionsCodeKey, errs.ErrPermissionCodeAlreadyExists) } // 创建菜单 menuId, err := q.CreateMenu(ctx, menu) if err != nil { return dberr.MapUniqueViolation(err, dberr.SysMenusPathUniqueIdx, errs.ErrMenusPathUniqueIdx) } // 绑定权限 if err = q.CreateMenuPermission(ctx, sqlc.CreateMenuPermissionParams{ MenuID: menuId, PermissionID: permissionId, }); err != nil { return err } return nil }) if err != nil { return err } // 清理缓存 这里不清理 超管用户的菜单不会刷新 _ = s.cache.DelByPrefix(ctx, cachekey.UserInfoPattern) return nil } func (s *MenuService) Update(ctx context.Context, id int32, req request.UpdateMenuRequest) error { err := s.store.WithTx(ctx, func(q *sqlc.Queries) error { // 构造 menu 参数 menu := sqlc.UpdateMenuParams{ ID: id, Name: req.Name, Path: req.Path, Component: req.Component, Hidden: req.Hidden, Sort: req.Sort, Type: req.Type, Status: req.Status, } if req.Icon.Set { menu.UpdateIcon = true if req.Icon.Valid { menu.Icon = &req.Icon.Value } } if req.ParentID.Set { menu.UpdateParentID = true if req.ParentID.Valid { menu.ParentID = &req.ParentID.Value } } // 执行更新 rows, err := q.UpdateMenu(ctx, menu) // 先判断数据是否存在 在判断path是否重复 if err = dberr.MapRowsAffected(rows, err, errs.ErrMenuNotFound); err != nil { return dberr.MapUniqueViolation(err, dberr.SysMenusPathUniqueIdx, errs.ErrMenusPathUniqueIdx) } permission := sqlc.UpdateMenuPermissionCodeParams{ MenuID: id, Code: req.PermissionCode, } if err = q.UpdateMenuPermissionCode(ctx, permission); err != nil { return dberr.MapUniqueViolation(err, dberr.SysPermissionsCodeKey, errs.ErrPermissionCodeAlreadyExists) } return nil }) if err != nil { return err } // 清理缓存 _ = s.cache.DelByPrefix(ctx, cachekey.UserInfoPattern) return nil } func (s *MenuService) List(ctx context.Context, p *common.Pagination) (*common.PageResult[sqlc.ListMenusRow], error) { params := sqlc.ListMenusParams{ Limit: p.PageSize, Offset: (p.Page - 1) * p.PageSize, } total, err := s.store.CountMenus(ctx) if err != nil { return nil, err } list, err := s.store.ListMenus(ctx, params) if err != nil { return nil, err } return &common.PageResult[sqlc.ListMenusRow]{ List: list, Total: total, }, nil } func (s *MenuService) ListAll(ctx context.Context) ([]sqlc.ListAllMenusRow, error) { return s.store.ListAllMenus(ctx) } func (s *MenuService) Delete(ctx context.Context, id int32) error { err := s.store.WithTx(ctx, func(q *sqlc.Queries) error { // 1. 根据菜单id, 找出对应的权限id permissionID, err := q.GetPermissionIDBySysMenuID(ctx, id) if err != nil { return dberr.MapNoRows(err, errs.ErrMenuNotFound) } // 2. 根据权限id 删除角色权限关联 if err = q.DeleteRolePermissionByPermissionID(ctx, permissionID); err != nil { return err } // 3. 根据菜单id 删除sys_menu_permission关联表数据 if err = q.DeleteMenuPermission(ctx, id); err != nil { return err } // 4. 根据权限id删除权限表数据 if err = q.DeletePermission(ctx, permissionID); err != nil { return err } // 5. 删除菜单 rows, err := q.DeleteMenu(ctx, id) if err = dberr.MapRowsAffected(rows, err, errs.ErrMenuNotFound); err != nil { return err } return nil }) if err != nil { return err } // 清理缓存 _ = s.cache.DelByPrefix(ctx, cachekey.UserInfoPattern) return nil }