Files

390 lines
11 KiB
Go
Raw Permalink Normal View History

2025-08-03 00:11:15 +08:00
package user
import (
"context"
"errors"
"fmt"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"nl-video-api/internal/dao"
"nl-video-api/internal/model/entity"
"nl-video-api/utility/crypto"
)
// UserService 用户服务
type UserService struct{}
var User = &UserService{}
// UserCreateReq 创建用户请求
type UserCreateReq struct {
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
Phone string `json:"phone" v:"required|phone#手机号不能为空|手机号格式错误"`
Email string `json:"email" v:"email#邮箱格式错误"`
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
Nickname string `json:"nickname" v:"length:1,20#昵称长度为1-20位"`
Avatar string `json:"avatar"`
Gender int `json:"gender" v:"in:0,1,2#性别值错误"`
Birthday string `json:"birthday"`
VipLevel int `json:"vip_level" v:"min:1,max:10#VIP等级范围1-10"`
Status int `json:"status" v:"in:0,1#状态只能为0或1"`
}
// UserUpdateReq 更新用户请求
type UserUpdateReq struct {
Id int `json:"id" v:"required|min:1#用户ID不能为空"`
Username string `json:"username" v:"length:3,20#用户名长度为3-20位"`
Phone string `json:"phone" v:"phone#手机号格式错误"`
Email string `json:"email" v:"email#邮箱格式错误"`
Nickname string `json:"nickname" v:"length:1,20#昵称长度为1-20位"`
Avatar string `json:"avatar"`
Gender int `json:"gender" v:"in:0,1,2#性别值错误"`
Birthday string `json:"birthday"`
VipLevel int `json:"vip_level" v:"min:1,max:10#VIP等级范围1-10"`
Status int `json:"status" v:"in:0,1#状态只能为0或1"`
}
// UserPasswordReq 修改密码请求
type UserPasswordReq struct {
Id int `json:"id" v:"required|min:1#用户ID不能为空"`
OldPassword string `json:"old_password" v:"required#原密码不能为空"`
NewPassword string `json:"new_password" v:"required|length:6,20#新密码不能为空|新密码长度为6-20位"`
}
// VipUpgradeReq VIP升级请求
type VipUpgradeReq struct {
UserId int `json:"user_id" v:"required|min:1#用户ID不能为空"`
VipLevel int `json:"vip_level" v:"required|min:1,max:10#VIP等级不能为空|VIP等级范围1-10"`
Days int `json:"days" v:"required|min:1#天数不能为空"`
}
// Create 创建用户
func (s *UserService) Create(ctx context.Context, req *UserCreateReq) (int64, error) {
// 检查用户名是否存在
existUser, err := dao.User.GetByUsername(ctx, req.Username)
if err != nil {
return 0, fmt.Errorf("检查用户名失败: %v", err)
}
if existUser != nil {
return 0, errors.New("用户名已存在")
}
// 检查手机号是否存在
existPhone, err := dao.User.GetByPhone(ctx, req.Phone)
if err != nil {
return 0, fmt.Errorf("检查手机号失败: %v", err)
}
if existPhone != nil {
return 0, errors.New("手机号已存在")
}
// 检查邮箱是否存在
if req.Email != "" {
existEmail, err := dao.User.GetByEmail(ctx, req.Email)
if err != nil {
return 0, fmt.Errorf("检查邮箱失败: %v", err)
}
if existEmail != nil {
return 0, errors.New("邮箱已存在")
}
}
// 加密密码
hashedPassword, err := crypto.HashPassword(req.Password)
if err != nil {
return 0, fmt.Errorf("密码加密失败: %v", err)
}
// 设置默认值
if req.Nickname == "" {
req.Nickname = req.Username
}
if req.VipLevel == 0 {
req.VipLevel = 1 // 默认普通用户
}
if req.Status == 0 {
req.Status = 1 // 默认启用
}
// 解析生日
var birthday *time.Time
if req.Birthday != "" {
if parsedTime, err := time.Parse("2006-01-02", req.Birthday); err == nil {
birthday = &parsedTime
}
}
// 创建用户
user := &entity.NlUser{
Username: req.Username,
Phone: req.Phone,
Email: req.Email,
Password: hashedPassword,
NickName: req.Nickname,
Avatar: req.Avatar,
Gender: req.Gender,
Birthday: birthday,
VipLevel: req.VipLevel,
Status: req.Status,
}
return dao.User.Create(ctx, user)
}
// Update 更新用户
func (s *UserService) Update(ctx context.Context, req *UserUpdateReq) error {
// 检查用户是否存在
existUser, err := dao.User.GetById(ctx, req.Id)
if err != nil {
return fmt.Errorf("查询用户失败: %v", err)
}
if existUser == nil {
return errors.New("用户不存在")
}
updateData := g.Map{}
// 检查用户名是否重复
if req.Username != "" && req.Username != existUser.Username {
checkUser, err := dao.User.GetByUsername(ctx, req.Username)
if err != nil {
return fmt.Errorf("检查用户名失败: %v", err)
}
if checkUser != nil && int(checkUser.Id) != req.Id {
return errors.New("用户名已存在")
}
updateData["username"] = req.Username
}
// 检查手机号是否重复
if req.Phone != "" && req.Phone != existUser.Phone {
checkPhone, err := dao.User.GetByPhone(ctx, req.Phone)
if err != nil {
return fmt.Errorf("检查手机号失败: %v", err)
}
if checkPhone != nil && int(checkPhone.Id) != req.Id {
return errors.New("手机号已存在")
}
updateData["phone"] = req.Phone
}
// 检查邮箱是否重复
if req.Email != "" && req.Email != existUser.Email {
checkEmail, err := dao.User.GetByEmail(ctx, req.Email)
if err != nil {
return fmt.Errorf("检查邮箱失败: %v", err)
}
if checkEmail != nil && int(checkEmail.Id) != req.Id {
return errors.New("邮箱已存在")
}
updateData["email"] = req.Email
}
// 更新其他字段
if req.Nickname != "" {
updateData["nick_name"] = req.Nickname
}
if req.Avatar != "" {
updateData["avatar"] = req.Avatar
}
if req.Gender >= 0 {
updateData["gender"] = req.Gender
}
if req.Birthday != "" {
// 解析生日
if parsedTime, err := time.Parse("2006-01-02", req.Birthday); err == nil {
updateData["birthday"] = &parsedTime
}
}
if req.VipLevel > 0 {
updateData["vip_level"] = req.VipLevel
}
if req.Status >= 0 {
updateData["status"] = req.Status
}
if len(updateData) == 0 {
return errors.New("没有需要更新的数据")
}
return dao.User.Update(ctx, req.Id, updateData)
}
// GetById 根据ID获取用户
func (s *UserService) GetById(ctx context.Context, id int) (*entity.NlUser, error) {
user, err := dao.User.GetById(ctx, id)
if err != nil {
return nil, fmt.Errorf("查询用户失败: %v", err)
}
// 清除敏感信息
if user != nil {
user.Password = ""
}
return user, nil
}
// GetList 获取用户列表
func (s *UserService) GetList(ctx context.Context, req *dao.UserListReq) ([]*entity.NlUser, int, error) {
users, total, err := dao.User.GetList(ctx, req)
if err != nil {
return nil, 0, fmt.Errorf("查询用户列表失败: %v", err)
}
// 清除敏感信息
for _, user := range users {
user.Password = ""
}
return users, total, nil
}
// Delete 删除用户
func (s *UserService) Delete(ctx context.Context, id int) error {
// 检查用户是否存在
user, err := dao.User.GetById(ctx, id)
if err != nil {
return fmt.Errorf("查询用户失败: %v", err)
}
if user == nil {
return errors.New("用户不存在")
}
return dao.User.Delete(ctx, id)
}
// ChangePassword 修改密码
func (s *UserService) ChangePassword(ctx context.Context, req *UserPasswordReq) error {
// 获取用户信息
user, err := dao.User.GetById(ctx, req.Id)
if err != nil {
return fmt.Errorf("查询用户失败: %v", err)
}
if user == nil {
return errors.New("用户不存在")
}
// 验证原密码
if !crypto.CheckPassword(req.OldPassword, user.Password) {
return errors.New("原密码错误")
}
// 加密新密码
hashedPassword, err := crypto.HashPassword(req.NewPassword)
if err != nil {
return fmt.Errorf("密码加密失败: %v", err)
}
// 更新密码
return dao.User.Update(ctx, req.Id, g.Map{
"password": hashedPassword,
})
}
// BatchUpdateStatus 批量更新用户状态
func (s *UserService) BatchUpdateStatus(ctx context.Context, ids []int, status int) error {
if len(ids) == 0 {
return errors.New("请选择要操作的用户")
}
return dao.User.BatchUpdateStatus(ctx, ids, status)
}
// BatchDelete 批量删除用户
func (s *UserService) BatchDelete(ctx context.Context, ids []int) error {
if len(ids) == 0 {
return errors.New("请选择要删除的用户")
}
return dao.User.BatchDelete(ctx, ids)
}
// GetUserStats 获取用户统计信息
func (s *UserService) GetUserStats(ctx context.Context) (g.Map, error) {
return dao.User.GetUserStats(ctx)
}
// UpgradeVip 升级VIP
func (s *UserService) UpgradeVip(ctx context.Context, req *VipUpgradeReq) error {
// 检查用户是否存在
user, err := dao.User.GetById(ctx, req.UserId)
if err != nil {
return fmt.Errorf("查询用户失败: %v", err)
}
if user == nil {
return errors.New("用户不存在")
}
// 计算VIP到期时间
var expireAt int64
if int64(user.VipExpireTime) > gtime.Now().Unix() {
// 如果当前VIP未过期,在原基础上延长
expireAt = int64(user.VipExpireTime) + int64(req.Days*24*3600)
} else {
// 如果已过期或首次开通,从现在开始计算
expireAt = gtime.Now().Unix() + int64(req.Days*24*3600)
}
// 更新用户VIP信息
return dao.User.Update(ctx, req.UserId, g.Map{
"vip_level": req.VipLevel,
"vip_expire_time": int(expireAt),
})
}
// SearchUsers 搜索用户
func (s *UserService) SearchUsers(ctx context.Context, keyword string, page, pageSize int) ([]*entity.NlUser, int, error) {
if keyword == "" {
return nil, 0, errors.New("搜索关键词不能为空")
}
users, total, err := dao.User.SearchUsers(ctx, keyword, page, pageSize)
if err != nil {
return nil, 0, fmt.Errorf("搜索用户失败: %v", err)
}
// 清除敏感信息
for _, user := range users {
user.Password = ""
}
return users, total, nil
}
// GetVipUsers 获取VIP用户列表
func (s *UserService) GetVipUsers(ctx context.Context, page, pageSize int) ([]*entity.NlUser, int, error) {
users, total, err := dao.User.GetVipUsers(ctx, page, pageSize)
if err != nil {
return nil, 0, fmt.Errorf("查询VIP用户失败: %v", err)
}
// 清除敏感信息
for _, user := range users {
user.Password = ""
}
return users, total, nil
}
// GetExpiredVipUsers 获取VIP即将过期的用户
func (s *UserService) GetExpiredVipUsers(ctx context.Context, days int) ([]*entity.NlUser, error) {
users, err := dao.User.GetExpiredVipUsers(ctx, days)
if err != nil {
return nil, fmt.Errorf("查询即将过期VIP用户失败: %v", err)
}
// 清除敏感信息
for _, user := range users {
user.Password = ""
}
return users, nil
}
// UpdateLoginInfo 更新登录信息
func (s *UserService) UpdateLoginInfo(ctx context.Context, userId int, ip string) error {
return dao.User.UpdateLoginInfo(ctx, userId, ip)
}