Files
2025-07-29 12:45:07 +08:00

311 lines
7.4 KiB
Go

package service
import (
"context"
"cms-api/internal/dao"
"cms-api/internal/model"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
type sUser struct{}
func User() *sUser {
return &sUser{}
}
// Login 用户登录
func (s *sUser) Login(ctx context.Context, req *model.UserLoginRequest) (*model.UserLoginResponse, error) {
// 查询用户
user, err := dao.User.GetByAccount(ctx, req.Account)
if err != nil {
return nil, err
}
if user == nil {
return nil, gerror.New("用户名或密码错误")
}
// 验证密码
if !s.VerifyPassword(req.Password, user.Password) {
return nil, gerror.New("用户名或密码错误")
}
// 检查状态
if user.Status != 0 {
statusText := map[int]string{
1: "账号已被冻结",
2: "账号已被封号",
3: "账号已注销",
}
return nil, gerror.New(statusText[user.Status])
}
// 更新登录信息
err = dao.User.Update(ctx, user.Id, g.Map{
"ip": g.RequestFromCtx(ctx).GetClientIp(),
"updated_at": gtime.Now(),
})
if err != nil {
g.Log().Error(ctx, "更新用户登录信息失败:", err)
}
// 生成token (暂时使用简单的token生成)
token := gmd5.MustEncrypt(gconv.String(user.Id) + "_" + gconv.String(gtime.Now().Unix()))
// 清除密码字段
user.Password = ""
return &model.UserLoginResponse{
Token: token,
ExpiresIn: 7200, // 2小时
User: user,
}, nil
}
// GetById 根据ID获取用户信息
func (s *sUser) GetById(ctx context.Context, id int) (*model.User, error) {
user, err := dao.User.GetById(ctx, id)
if err != nil {
return nil, err
}
if user == nil {
return nil, nil
}
// 清除密码字段
user.Password = ""
return user, nil
}
// List 获取用户列表
func (s *sUser) List(ctx context.Context, req *model.UserListRequest) (*model.PageResponse, error) {
var (
page = req.Page
pageSize = req.PageSize
)
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = 10
}
// 设置分页参数
req.Page = page
req.PageSize = pageSize
// 获取列表
users, total, err := dao.User.List(ctx, req)
if err != nil {
return nil, err
}
// 清除密码字段
for _, user := range users {
user.Password = ""
}
return &model.PageResponse{
List: users,
Total: total,
Page: page,
PageSize: pageSize,
TotalPages: (total + pageSize - 1) / pageSize,
}, nil
}
// Create 创建用户
func (s *sUser) Create(ctx context.Context, req *model.CreateUserRequest) error {
// 检查账号是否存在
existUser, err := dao.User.GetByAccount(ctx, req.Account)
if err != nil {
return err
}
if existUser != nil {
return gerror.New("账号已存在")
}
// 检查邮箱是否存在
existUser, err = dao.User.GetByEmail(ctx, req.Email)
if err != nil {
return err
}
if existUser != nil {
return gerror.New("邮箱已存在")
}
// 加密密码
hashedPassword := s.HashPassword(req.Password)
// 创建用户
user := &model.User{
Account: req.Account,
NickName: req.NickName,
Avatar: req.Avatar,
Email: req.Email,
Password: hashedPassword,
Balance: req.Balance,
RoleId: req.RoleId,
IsSysNotifications: req.IsSysNotifications,
IsCollectionNotifications: req.IsCollectionNotifications,
IsMarketingNotifications: req.IsMarketingNotifications,
Status: 0, // 默认正常状态
CreatedAt: gtime.Now(),
UpdatedAt: gtime.Now(),
}
_, err = dao.User.Create(ctx, user)
return err
}
// Update 更新用户
func (s *sUser) Update(ctx context.Context, id int, req *model.UpdateUserRequest) error {
// 检查用户是否存在
user, err := s.GetById(ctx, id)
if err != nil {
return err
}
if user == nil {
return gerror.New("用户不存在")
}
// 检查邮箱是否被其他用户使用
existUser, err := dao.User.GetByEmail(ctx, req.Email)
if err != nil {
return err
}
if existUser != nil && existUser.Id != id {
return gerror.New("邮箱已被使用")
}
// 更新用户
updateData := g.Map{
"nick_name": req.NickName,
"email": req.Email,
"avatar": req.Avatar,
"balance": req.Balance,
"role_id": req.RoleId,
"status": req.Status,
"is_sys_notifications": req.IsSysNotifications,
"is_collection_notifications": req.IsCollectionNotifications,
"is_marketing_notifications": req.IsMarketingNotifications,
"updated_at": gtime.Now(),
}
return dao.User.Update(ctx, id, updateData)
}
// Delete 删除用户
func (s *sUser) Delete(ctx context.Context, id int) error {
// 检查用户是否存在
user, err := s.GetById(ctx, id)
if err != nil {
return err
}
if user == nil {
return gerror.New("用户不存在")
}
return dao.User.Delete(ctx, id)
}
// ChangePassword 修改密码
func (s *sUser) ChangePassword(ctx context.Context, id int, req *model.ChangePasswordRequest) error {
// 获取用户信息
user, err := dao.User.GetById(ctx, id)
if err != nil {
return err
}
if user == nil {
return gerror.New("用户不存在")
}
// 验证原密码
if !s.VerifyPassword(req.OldPassword, user.Password) {
return gerror.New("原密码错误")
}
// 加密新密码
hashedPassword := s.HashPassword(req.NewPassword)
// 更新密码
updateData := g.Map{
"password": hashedPassword,
"last_reset_password_at": gtime.Now().Unix(),
"updated_at": gtime.Now(),
}
return dao.User.Update(ctx, id, updateData)
}
// UpdateStatus 更新用户状态
func (s *sUser) UpdateStatus(ctx context.Context, id int, status int) error {
// 检查用户是否存在
user, err := s.GetById(ctx, id)
if err != nil {
return err
}
if user == nil {
return gerror.New("用户不存在")
}
return dao.User.UpdateStatus(ctx, id, status)
}
// HashPassword 加密密码
func (s *sUser) HashPassword(password string) string {
return gmd5.MustEncrypt(password + "cms_user_salt_2024")
}
// VerifyPassword 验证密码
func (s *sUser) VerifyPassword(password, hashedPassword string) bool {
return gmd5.MustEncrypt(password+"cms_user_salt_2024") == hashedPassword
}
// Profile 获取当前用户信息
func (s *sUser) Profile(ctx context.Context) (*model.User, error) {
userId := gconv.Int(g.RequestFromCtx(ctx).GetCtxVar("user_id"))
return s.GetById(ctx, userId)
}
// UpdateProfile 更新当前用户信息
func (s *sUser) UpdateProfile(ctx context.Context, req *model.UpdateUserRequest) error {
userId := gconv.Int(g.RequestFromCtx(ctx).GetCtxVar("user_id"))
return s.Update(ctx, userId, req)
}
// GetStats 获取用户统计信息
func (s *sUser) GetStats(ctx context.Context) (map[string]interface{}, error) {
// 获取总用户数
totalCount, err := dao.User.GetCount(ctx)
if err != nil {
return nil, err
}
// 获取各状态用户数
normalCount, err := dao.User.GetCountByStatus(ctx, 0)
if err != nil {
return nil, err
}
frozenCount, err := dao.User.GetCountByStatus(ctx, 1)
if err != nil {
return nil, err
}
bannedCount, err := dao.User.GetCountByStatus(ctx, 2)
if err != nil {
return nil, err
}
return map[string]interface{}{
"total_count": totalCount,
"normal_count": normalCount,
"frozen_count": frozenCount,
"banned_count": bannedCount,
}, nil
}