package system import ( "context" "encoding/json" "errors" "kra/internal/biz/system" "kra/internal/data/model" "kra/internal/data/query" "github.com/google/uuid" "gorm.io/gorm" ) type userRepo struct { db *gorm.DB } // NewUserRepo 创建用户仓储 func NewUserRepo(db *gorm.DB) system.UserRepo { query.SetDefault(db) return &userRepo{db: db} } func (r *userRepo) Create(ctx context.Context, user *system.User) error { m := toBizUser(user) return query.SysUser.WithContext(ctx).Create(m) } func (r *userRepo) Update(ctx context.Context, user *system.User) error { _, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(user.ID))).Updates(map[string]any{ "nick_name": user.NickName, "header_img": user.HeaderImg, "phone": user.Phone, "email": user.Email, "enable": user.Enable, }) return err } func (r *userRepo) UpdateSelf(ctx context.Context, user *system.User) error { updates := map[string]any{} if user.NickName != "" { updates["nick_name"] = user.NickName } if user.HeaderImg != "" { updates["header_img"] = user.HeaderImg } if user.Phone != "" { updates["phone"] = user.Phone } if user.Email != "" { updates["email"] = user.Email } if user.SideMode != "" { updates["side_mode"] = user.SideMode } if user.BaseColor != "" { updates["base_color"] = user.BaseColor } if len(updates) == 0 { return nil } _, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(user.ID))).Updates(updates) return err } func (r *userRepo) UpdateSelfSetting(ctx context.Context, id uint, setting json.RawMessage) error { _, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(id))).Update(query.SysUser.OriginSetting, string(setting)) return err } func (r *userRepo) Delete(ctx context.Context, id uint) error { return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Where("id = ?", id).Delete(&model.SysUser{}).Error; err != nil { return err } if err := tx.Where("sys_user_id = ?", id).Delete(&model.SysUserAuthority{}).Error; err != nil { return err } return nil }) } func (r *userRepo) FindByID(ctx context.Context, id uint) (*system.User, error) { m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.ID.Eq(int64(id))).First() if err != nil { return nil, err } return toModelUser(m), nil } func (r *userRepo) FindByIDWithAuthorities(ctx context.Context, id uint) (*system.User, error) { m, err := query.SysUser.WithContext(ctx). Preload(query.SysUser.Authority). Preload(query.SysUser.Authorities). Where(query.SysUser.ID.Eq(int64(id))). First() if err != nil { return nil, err } return toModelUserWithAuthorities(m), nil } func (r *userRepo) FindByUUID(ctx context.Context, uuidStr string) (*system.User, error) { m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.UUID.Eq(uuidStr)).First() if err != nil { return nil, err } return toModelUser(m), nil } func (r *userRepo) FindByUUIDWithAuthorities(ctx context.Context, uuidStr string) (*system.User, error) { m, err := query.SysUser.WithContext(ctx). Preload(query.SysUser.Authority). Preload(query.SysUser.Authorities). Where(query.SysUser.UUID.Eq(uuidStr)). First() if err != nil { return nil, err } return toModelUserWithAuthorities(m), nil } func (r *userRepo) FindByUsername(ctx context.Context, username string) (*system.User, error) { m, err := query.SysUser.WithContext(ctx).Where(query.SysUser.Username.Eq(username)).First() if err != nil { return nil, err } return toModelUser(m), nil } func (r *userRepo) FindByUsernameWithAuthorities(ctx context.Context, username string) (*system.User, error) { m, err := query.SysUser.WithContext(ctx). Preload(query.SysUser.Authority). Preload(query.SysUser.Authorities). Where(query.SysUser.Username.Eq(username)). First() if err != nil { return nil, err } return toModelUserWithAuthorities(m), nil } func (r *userRepo) List(ctx context.Context, page, pageSize int, filters map[string]string) ([]*system.User, int64, error) { u := query.SysUser q := u.WithContext(ctx) if v, ok := filters["username"]; ok && v != "" { q = q.Where(u.Username.Like("%" + v + "%")) } if v, ok := filters["nick_name"]; ok && v != "" { q = q.Where(u.NickName.Like("%" + v + "%")) } if v, ok := filters["phone"]; ok && v != "" { q = q.Where(u.Phone.Like("%" + v + "%")) } if v, ok := filters["email"]; ok && v != "" { q = q.Where(u.Email.Like("%" + v + "%")) } total, err := q.Count() if err != nil { return nil, 0, err } offset := (page - 1) * pageSize list, err := q.Preload(u.Authority).Preload(u.Authorities).Offset(offset).Limit(pageSize).Find() if err != nil { return nil, 0, err } users := make([]*system.User, len(list)) for i := range list { users[i] = toModelUserWithAuthorities(list[i]) } return users, total, nil } func (r *userRepo) UpdatePassword(ctx context.Context, id uint, password string) error { return r.db.WithContext(ctx).Model(&model.SysUser{}).Where("id = ?", id).Update("password", password).Error } func (r *userRepo) UpdateAuthorityID(ctx context.Context, id uint, authorityId uint) error { return r.db.WithContext(ctx).Model(&model.SysUser{}).Where("id = ?", id).Update("authority_id", authorityId).Error } func (r *userRepo) SetUserAuthorities(ctx context.Context, adminAuthorityID, userId uint, authorityIds []uint) error { return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { var user model.SysUser if err := tx.Where("id = ?", userId).First(&user).Error; err != nil { return errors.New("查询用户数据失败") } if err := tx.Where("sys_user_id = ?", userId).Delete(&model.SysUserAuthority{}).Error; err != nil { return err } for _, aid := range authorityIds { if err := checkAuthorityIDAuth(tx, adminAuthorityID, aid); err != nil { return err } ua := &model.SysUserAuthority{ SysUserID: int64(userId), SysAuthorityAuthorityID: int64(aid), } if err := tx.Create(ua).Error; err != nil { return err } } if len(authorityIds) > 0 { if err := tx.Model(&model.SysUser{}).Where("id = ?", userId).Update("authority_id", authorityIds[0]).Error; err != nil { return err } } return nil }) } func checkAuthorityIDAuth(tx *gorm.DB, adminAuthorityID, targetAuthorityID uint) error { // 超级管理员(888)直接通过 if adminAuthorityID == 888 { return nil } // 获取管理员角色的所有子角色ID(递归) authIDs, err := getStructAuthorityList(tx, adminAuthorityID) if err != nil { return err } // 检查目标角色是否在权限列表中 for _, id := range authIDs { if id == targetAuthorityID { return nil } } return errors.New("您没有权限分配该角色") } // getStructAuthorityList 递归获取角色ID列表(包含子角色) func getStructAuthorityList(tx *gorm.DB, authorityID uint) ([]uint, error) { var auth model.SysAuthority if err := tx.First(&auth, "authority_id = ?", authorityID).Error; err != nil { return nil, err } var list []uint var children []model.SysAuthority if err := tx.Where("parent_id = ?", authorityID).Find(&children).Error; err != nil { return nil, err } for _, child := range children { list = append(list, uint(child.AuthorityID)) childList, err := getStructAuthorityList(tx, uint(child.AuthorityID)) if err == nil { list = append(list, childList...) } } // 如果是顶级角色,包含自己 if auth.ParentID == 0 { list = append(list, authorityID) } return list, nil } func (r *userRepo) CheckUserHasAuthority(ctx context.Context, userId, authorityId uint) (bool, error) { var count int64 err := r.db.WithContext(ctx).Model(&model.SysUserAuthority{}). Where("sys_user_id = ? AND sys_authority_authority_id = ?", userId, authorityId). Count(&count).Error return count > 0, err } func (r *userRepo) GetAuthorityMenuRouters(ctx context.Context, authorityId uint) ([]string, error) { var authorityMenus []model.SysAuthorityMenu if err := r.db.WithContext(ctx).Where("sys_authority_authority_id = ?", authorityId).Find(&authorityMenus).Error; err != nil { return nil, err } if len(authorityMenus) == 0 { return []string{}, nil } menuIDs := make([]int64, len(authorityMenus)) for i, am := range authorityMenus { menuIDs[i] = am.SysBaseMenuID } var menus []model.SysBaseMenu if err := r.db.WithContext(ctx).Where("id IN ?", menuIDs).Find(&menus).Error; err != nil { return nil, err } routers := make([]string, len(menus)) for i, m := range menus { routers[i] = m.Name } return routers, nil } func (r *userRepo) GetAuthorityDefaultRouter(ctx context.Context, authorityId uint) (string, error) { var authority model.SysAuthority if err := r.db.WithContext(ctx).Where("authority_id = ?", authorityId).First(&authority).Error; err != nil { return "", err } return authority.DefaultRouter, nil } // 转换函数 func toBizUser(u *system.User) *model.SysUser { return &model.SysUser{ ID: int64(u.ID), UUID: u.UUID.String(), Username: u.Username, Password: u.Password, NickName: u.NickName, HeaderImg: u.HeaderImg, AuthorityID: int64(u.AuthorityId), Phone: u.Phone, Email: u.Email, Enable: int64(u.Enable), } } func toModelUser(m *model.SysUser) *system.User { u := &system.User{ ID: uint(m.ID), Username: m.Username, Password: m.Password, NickName: m.NickName, HeaderImg: m.HeaderImg, AuthorityId: uint(m.AuthorityID), Phone: m.Phone, Email: m.Email, Enable: int(m.Enable), OriginSetting: json.RawMessage(m.OriginSetting), CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } u.UUID, _ = uuid.Parse(m.UUID) return u } func toModelUserWithAuthorities(m *model.SysUser) *system.User { u := toModelUser(m) // 转换Authority u.Authority = &system.Authority{ AuthorityId: uint(m.Authority.AuthorityID), AuthorityName: m.Authority.AuthorityName, DefaultRouter: m.Authority.DefaultRouter, } if m.Authority.ParentID != 0 { pid := uint(m.Authority.ParentID) u.Authority.ParentId = &pid } // 转换Authorities if len(m.Authorities) > 0 { u.Authorities = make([]*system.Authority, len(m.Authorities)) for i, a := range m.Authorities { u.Authorities[i] = &system.Authority{ AuthorityId: uint(a.AuthorityID), AuthorityName: a.AuthorityName, DefaultRouter: a.DefaultRouter, } if a.ParentID != 0 { pid := uint(a.ParentID) u.Authorities[i].ParentId = &pid } } } return u }