package service import ( "context" "errors" "fmt" "photography-backend/internal/models" "photography-backend/internal/utils" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type UserService struct { db *gorm.DB logger *zap.Logger } func NewUserService(db *gorm.DB, logger *zap.Logger) *UserService { return &UserService{ db: db, logger: logger, } } // UserListParams 用户列表查询参数 type UserListParams struct { Page int `json:"page" form:"page"` Limit int `json:"limit" form:"limit"` Search string `json:"search" form:"search"` Role string `json:"role" form:"role"` IsActive *bool `json:"is_active" form:"is_active"` } // UserListResponse 用户列表响应 type UserListResponse struct { Users []models.User `json:"users"` Total int64 `json:"total"` Page int `json:"page"` Limit int `json:"limit"` Pages int `json:"pages"` } // GetUsers 获取用户列表 func (s *UserService) GetUsers(ctx context.Context, params UserListParams) (*UserListResponse, error) { // 设置默认值 if params.Page <= 0 { params.Page = 1 } if params.Limit <= 0 { params.Limit = 20 } if params.Limit > 100 { params.Limit = 100 } // 构建查询 query := s.db.WithContext(ctx) // 搜索过滤 if params.Search != "" { searchPattern := "%" + params.Search + "%" query = query.Where("username ILIKE ? OR email ILIKE ?", searchPattern, searchPattern) } // 角色过滤 if params.Role != "" { query = query.Where("role = ?", params.Role) } // 状态过滤 if params.IsActive != nil { query = query.Where("is_active = ?", *params.IsActive) } // 计算总数 var total int64 countQuery := query if err := countQuery.Model(&models.User{}).Count(&total).Error; err != nil { s.logger.Error("Failed to count users", zap.Error(err)) return nil, err } // 分页查询 offset := (params.Page - 1) * params.Limit var users []models.User if err := query. Order("created_at DESC"). Offset(offset). Limit(params.Limit). Find(&users).Error; err != nil { s.logger.Error("Failed to get users", zap.Error(err)) return nil, err } // 计算总页数 pages := int((total + int64(params.Limit) - 1) / int64(params.Limit)) return &UserListResponse{ Users: users, Total: total, Page: params.Page, Limit: params.Limit, Pages: pages, }, nil } // GetUserByID 根据ID获取用户 func (s *UserService) GetUserByID(ctx context.Context, id uint) (*models.User, error) { var user models.User if err := s.db.WithContext(ctx).First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } s.logger.Error("Failed to get user by ID", zap.Error(err), zap.Uint("id", id)) return nil, err } return &user, nil } // GetUserByUsername 根据用户名获取用户 func (s *UserService) GetUserByUsername(ctx context.Context, username string) (*models.User, error) { var user models.User if err := s.db.WithContext(ctx).Where("username = ?", username).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } s.logger.Error("Failed to get user by username", zap.Error(err), zap.String("username", username)) return nil, err } return &user, nil } // GetUserByEmail 根据邮箱获取用户 func (s *UserService) GetUserByEmail(ctx context.Context, email string) (*models.User, error) { var user models.User if err := s.db.WithContext(ctx).Where("email = ?", email).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } s.logger.Error("Failed to get user by email", zap.Error(err), zap.String("email", email)) return nil, err } return &user, nil } // CreateUser 创建用户 func (s *UserService) CreateUser(ctx context.Context, req *models.CreateUserRequest) (*models.User, error) { // 验证用户名唯一性 var existingUser models.User if err := s.db.WithContext(ctx).Where("username = ?", req.Username).First(&existingUser).Error; err == nil { return nil, errors.New("username already exists") } // 验证邮箱唯一性 if err := s.db.WithContext(ctx).Where("email = ?", req.Email).First(&existingUser).Error; err == nil { return nil, errors.New("email already exists") } // 加密密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { s.logger.Error("Failed to hash password", zap.Error(err)) return nil, err } user := &models.User{ Username: req.Username, Email: req.Email, Password: string(hashedPassword), Role: req.Role, IsActive: true, } if err := s.db.WithContext(ctx).Create(user).Error; err != nil { s.logger.Error("Failed to create user", zap.Error(err)) return nil, err } s.logger.Info("User created successfully", zap.Uint("id", user.ID)) return user, nil } // UpdateUser 更新用户 func (s *UserService) UpdateUser(ctx context.Context, id uint, req *models.UpdateUserRequest) (*models.User, error) { // 检查用户是否存在 var user models.User if err := s.db.WithContext(ctx).First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } return nil, err } // 构建更新数据 updates := map[string]interface{}{} if req.Username != nil { // 验证用户名唯一性 var existingUser models.User if err := s.db.WithContext(ctx).Where("username = ? AND id != ?", *req.Username, id).First(&existingUser).Error; err == nil { return nil, errors.New("username already exists") } updates["username"] = *req.Username } if req.Email != nil { // 验证邮箱唯一性 var existingUser models.User if err := s.db.WithContext(ctx).Where("email = ? AND id != ?", *req.Email, id).First(&existingUser).Error; err == nil { return nil, errors.New("email already exists") } updates["email"] = *req.Email } if req.Role != nil { updates["role"] = *req.Role } if req.IsActive != nil { updates["is_active"] = *req.IsActive } if len(updates) > 0 { if err := s.db.WithContext(ctx).Model(&user).Updates(updates).Error; err != nil { s.logger.Error("Failed to update user", zap.Error(err)) return nil, err } } s.logger.Info("User updated successfully", zap.Uint("id", id)) return &user, nil } // UpdateCurrentUser 更新当前用户信息 func (s *UserService) UpdateCurrentUser(ctx context.Context, id uint, req *models.UpdateCurrentUserRequest) (*models.User, error) { // 检查用户是否存在 var user models.User if err := s.db.WithContext(ctx).First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("user not found") } return nil, err } // 构建更新数据 updates := map[string]interface{}{} if req.Username != nil { // 验证用户名唯一性 var existingUser models.User if err := s.db.WithContext(ctx).Where("username = ? AND id != ?", *req.Username, id).First(&existingUser).Error; err == nil { return nil, errors.New("username already exists") } updates["username"] = *req.Username } if req.Email != nil { // 验证邮箱唯一性 var existingUser models.User if err := s.db.WithContext(ctx).Where("email = ? AND id != ?", *req.Email, id).First(&existingUser).Error; err == nil { return nil, errors.New("email already exists") } updates["email"] = *req.Email } if len(updates) > 0 { if err := s.db.WithContext(ctx).Model(&user).Updates(updates).Error; err != nil { s.logger.Error("Failed to update current user", zap.Error(err)) return nil, err } } s.logger.Info("Current user updated successfully", zap.Uint("id", id)) return &user, nil } // DeleteUser 删除用户 func (s *UserService) DeleteUser(ctx context.Context, id uint) error { // 检查用户是否存在 var user models.User if err := s.db.WithContext(ctx).First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return errors.New("user not found") } return err } // 删除用户 if err := s.db.WithContext(ctx).Delete(&user).Error; err != nil { s.logger.Error("Failed to delete user", zap.Error(err)) return err } s.logger.Info("User deleted successfully", zap.Uint("id", id)) return nil } // ChangePassword 修改密码 func (s *UserService) ChangePassword(ctx context.Context, id uint, req *models.ChangePasswordRequest) error { // 检查用户是否存在 var user models.User if err := s.db.WithContext(ctx).First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return errors.New("user not found") } return err } // 验证旧密码 if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)); err != nil { return errors.New("old password is incorrect") } // 加密新密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { s.logger.Error("Failed to hash new password", zap.Error(err)) return err } // 更新密码 if err := s.db.WithContext(ctx).Model(&user).Update("password", string(hashedPassword)).Error; err != nil { s.logger.Error("Failed to update password", zap.Error(err)) return err } s.logger.Info("Password changed successfully", zap.Uint("id", id)) return nil } // ValidateCredentials 验证用户凭据 func (s *UserService) ValidateCredentials(ctx context.Context, username, password string) (*models.User, error) { var user models.User // 根据用户名或邮箱查找用户 if err := s.db.WithContext(ctx).Where("username = ? OR email = ?", username, username).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("invalid credentials") } s.logger.Error("Failed to find user", zap.Error(err)) return nil, err } // 检查用户是否激活 if !user.IsActive { return nil, errors.New("user account is disabled") } // 验证密码 if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { return nil, errors.New("invalid credentials") } return &user, nil } // GetUserStats 获取用户统计信息 func (s *UserService) GetUserStats(ctx context.Context) (*models.UserStats, error) { var stats models.UserStats // 总用户数 if err := s.db.WithContext(ctx).Model(&models.User{}).Count(&stats.Total).Error; err != nil { return nil, err } // 活跃用户数 if err := s.db.WithContext(ctx).Model(&models.User{}). Where("is_active = ?", true).Count(&stats.Active).Error; err != nil { return nil, err } // 按角色统计 var roleStats []struct { Role string `json:"role"` Count int64 `json:"count"` } if err := s.db.WithContext(ctx).Model(&models.User{}). Select("role, COUNT(*) as count"). Where("is_active = ?", true). Group("role"). Find(&roleStats).Error; err != nil { return nil, err } stats.RoleStats = make(map[string]int64) for _, stat := range roleStats { stats.RoleStats[stat.Role] = stat.Count } // 本月新增用户 startOfMonth := time.Now().AddDate(0, 0, -time.Now().Day()+1) if err := s.db.WithContext(ctx).Model(&models.User{}). Where("created_at >= ?", startOfMonth). Count(&stats.ThisMonth).Error; err != nil { return nil, err } // 今日新增用户 startOfDay := time.Now().Truncate(24 * time.Hour) if err := s.db.WithContext(ctx).Model(&models.User{}). Where("created_at >= ?", startOfDay). Count(&stats.Today).Error; err != nil { return nil, err } return &stats, nil } // IsUsernameAvailable 检查用户名是否可用 func (s *UserService) IsUsernameAvailable(ctx context.Context, username string) (bool, error) { var count int64 if err := s.db.WithContext(ctx).Model(&models.User{}). Where("username = ?", username).Count(&count).Error; err != nil { return false, err } return count == 0, nil } // IsEmailAvailable 检查邮箱是否可用 func (s *UserService) IsEmailAvailable(ctx context.Context, email string) (bool, error) { var count int64 if err := s.db.WithContext(ctx).Model(&models.User{}). Where("email = ?", email).Count(&count).Error; err != nil { return false, err } return count == 0, nil }