package repository import ( "errors" "hyapp-admin-server/internal/model" "gorm.io/gorm" ) func (s *Store) MenusForPermissions(permissionCodes []string) ([]model.Menu, error) { var menus []model.Menu query := s.db.Where("visible = ?", true).Order("sort ASC, id ASC") if len(permissionCodes) > 0 { query = query.Where("permission_code = '' OR permission_code IN ?", permissionCodes) } else { // Empty permission sets may still see structural parent rows, but never rows bound to protected pages. query = query.Where("permission_code = ''") } err := query.Find(&menus).Error return menus, err } func (s *Store) ListMenus() ([]model.Menu, error) { var menus []model.Menu err := s.db.Order("sort ASC, id ASC").Find(&menus).Error return menus, err } func (s *Store) CreateMenu(menu *model.Menu) error { normalized, err := normalizeMenu(*menu) if err != nil { return err } *menu = normalized return s.db.Create(menu).Error } func (s *Store) UpdateMenu(id uint, patch model.Menu) (*model.Menu, error) { normalized, err := normalizeMenu(patch) if err != nil { return nil, err } var menu model.Menu if err := s.db.First(&menu, id).Error; err != nil { return nil, err } if normalized.ParentID != nil && *normalized.ParentID == id { return nil, errors.New("menu cannot be its own parent") } // 菜单字段直接影响前端路由和权限入口,更新时保持 code/path/permission_code 同步落库。 updates := map[string]any{ "parent_id": normalized.ParentID, "title": normalized.Title, "code": normalized.Code, "path": normalized.Path, "icon": normalized.Icon, "permission_code": normalized.PermissionCode, "sort": normalized.Sort, "visible": normalized.Visible, } if err := s.db.Model(&menu).Updates(updates).Error; err != nil { return nil, err } if err := s.db.First(&menu, id).Error; err != nil { return nil, err } return &menu, nil } func (s *Store) DeleteMenu(id uint) error { var children int64 if err := s.db.Model(&model.Menu{}).Where("parent_id = ?", id).Count(&children).Error; err != nil { return err } if children > 0 { return errors.New("menu has children") } return s.db.Delete(&model.Menu{}, id).Error } func (s *Store) UpdateMenuVisible(id uint, visible bool) (*model.Menu, error) { var menu model.Menu if err := s.db.First(&menu, id).Error; err != nil { return nil, err } if err := s.db.Model(&menu).Update("visible", visible).Error; err != nil { return nil, err } if err := s.db.First(&menu, id).Error; err != nil { return nil, err } return &menu, nil } func (s *Store) SortMenus(items []MenuSortItem) error { return s.db.Transaction(func(tx *gorm.DB) error { for _, item := range items { if item.ID == 0 { return errors.New("invalid menu id") } // 排序只更新 sort 字段,避免拖拽排序误改路由、权限码等关键入口字段。 if err := tx.Model(&model.Menu{}).Where("id = ?", item.ID).Update("sort", item.Sort).Error; err != nil { return err } } return nil }) }