20251209
This commit is contained in:
621
archive/bbs-go-active/server/internal/services/user_service.go
Normal file
621
archive/bbs-go-active/server/internal/services/user_service.go
Normal file
@@ -0,0 +1,621 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bbs-go/internal/models/constants"
|
||||
"bbs-go/internal/pkg/bbsurls"
|
||||
"bbs-go/internal/pkg/email"
|
||||
"bbs-go/internal/pkg/errs"
|
||||
"bbs-go/internal/pkg/validate"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mlogclub/simple/common/dates"
|
||||
"github.com/mlogclub/simple/common/passwd"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"bbs-go/internal/cache"
|
||||
|
||||
"bbs-go/internal/models"
|
||||
"bbs-go/internal/repositories"
|
||||
)
|
||||
|
||||
// 邮箱验证邮件有效期(小时)
|
||||
const emailVerifyExpireHour = 24
|
||||
|
||||
var UserService = newUserService()
|
||||
|
||||
func newUserService() *userService {
|
||||
return &userService{}
|
||||
}
|
||||
|
||||
type userService struct {
|
||||
}
|
||||
|
||||
func (s *userService) Get(id int64) *models.User {
|
||||
return repositories.UserRepository.Get(sqls.DB(), id)
|
||||
}
|
||||
|
||||
func (s *userService) Take(where ...interface{}) *models.User {
|
||||
return repositories.UserRepository.Take(sqls.DB(), where...)
|
||||
}
|
||||
|
||||
func (s *userService) Find(cnd *sqls.Cnd) []models.User {
|
||||
return repositories.UserRepository.Find(sqls.DB(), cnd)
|
||||
}
|
||||
|
||||
func (s *userService) FindOne(cnd *sqls.Cnd) *models.User {
|
||||
return repositories.UserRepository.FindOne(sqls.DB(), cnd)
|
||||
}
|
||||
|
||||
func (s *userService) FindPageByParams(params *params.QueryParams) (list []models.User, paging *sqls.Paging) {
|
||||
return repositories.UserRepository.FindPageByParams(sqls.DB(), params)
|
||||
}
|
||||
|
||||
func (s *userService) FindPageByCnd(cnd *sqls.Cnd) (list []models.User, paging *sqls.Paging) {
|
||||
return repositories.UserRepository.FindPageByCnd(sqls.DB(), cnd)
|
||||
}
|
||||
|
||||
func (s *userService) Create(t *models.User) error {
|
||||
err := repositories.UserRepository.Create(sqls.DB(), t)
|
||||
if err == nil {
|
||||
cache.UserCache.Invalidate(t.Id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *userService) Update(t *models.User) error {
|
||||
err := repositories.UserRepository.Update(sqls.DB(), t)
|
||||
cache.UserCache.Invalidate(t.Id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *userService) Updates(id int64, columns map[string]interface{}) error {
|
||||
err := repositories.UserRepository.Updates(sqls.DB(), id, columns)
|
||||
cache.UserCache.Invalidate(id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *userService) UpdateColumn(id int64, name string, value interface{}) error {
|
||||
err := repositories.UserRepository.UpdateColumn(sqls.DB(), id, name, value)
|
||||
cache.UserCache.Invalidate(id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *userService) Delete(id int64) {
|
||||
repositories.UserRepository.Delete(sqls.DB(), id)
|
||||
cache.UserCache.Invalidate(id)
|
||||
}
|
||||
|
||||
// Scan 扫描
|
||||
func (s *userService) Scan(callback func(users []models.User)) {
|
||||
var cursor int64
|
||||
for {
|
||||
list := repositories.UserRepository.Find(sqls.DB(), sqls.NewCnd().Where("id > ?", cursor).Asc("id").Limit(100))
|
||||
if len(list) == 0 {
|
||||
break
|
||||
}
|
||||
cursor = list[len(list)-1].Id
|
||||
callback(list)
|
||||
}
|
||||
}
|
||||
|
||||
// Forbidden 禁言
|
||||
func (s *userService) Forbidden(operatorId, userId int64, days int, reason string, r *http.Request) error {
|
||||
var forbiddenEndTime int64
|
||||
if days == -1 { // 永久禁言
|
||||
forbiddenEndTime = -1
|
||||
} else if days > 0 {
|
||||
forbiddenEndTime = dates.Timestamp(time.Now().Add(time.Hour * 24 * time.Duration(days)))
|
||||
} else {
|
||||
return errors.New("禁言时间错误")
|
||||
}
|
||||
if repositories.UserRepository.UpdateColumn(sqls.DB(), userId, "forbidden_end_time", forbiddenEndTime) == nil {
|
||||
cache.UserCache.Invalidate(userId)
|
||||
description := ""
|
||||
if strs.IsNotBlank(reason) {
|
||||
description = "禁言原因:" + reason
|
||||
}
|
||||
OperateLogService.AddOperateLog(operatorId, constants.OpTypeForbidden, constants.EntityUser, userId,
|
||||
description, r)
|
||||
|
||||
// 永久禁言
|
||||
if days == -1 {
|
||||
user := cache.UserCache.Get(userId)
|
||||
_ = s.DecrScore(userId, user.Score, constants.EntityUser, strconv.FormatInt(operatorId, 10), "永久禁言")
|
||||
go func() {
|
||||
// 删除话题
|
||||
TopicService.ScanByUser(userId, func(topics []models.Topic) {
|
||||
for _, topic := range topics {
|
||||
if topic.Status != constants.StatusDeleted {
|
||||
_ = TopicService.Delete(topic.Id, operatorId, nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 删除文章
|
||||
ArticleService.ScanByUser(userId, func(articles []models.Article) {
|
||||
for _, article := range articles {
|
||||
if article.Status != constants.StatusDeleted {
|
||||
_ = ArticleService.Delete(article.Id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 删除评论
|
||||
CommentService.ScanByUser(userId, func(comments []models.Comment) {
|
||||
for _, comment := range comments {
|
||||
if comment.Status != constants.StatusDeleted {
|
||||
_ = CommentService.Delete(comment.Id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveForbidden 移除禁言
|
||||
func (s *userService) RemoveForbidden(operatorId, userId int64, r *http.Request) {
|
||||
user := s.Get(userId)
|
||||
if user == nil || !user.IsForbidden() {
|
||||
return
|
||||
}
|
||||
if repositories.UserRepository.UpdateColumn(sqls.DB(), userId, "forbidden_end_time", 0) == nil {
|
||||
cache.UserCache.Invalidate(user.Id)
|
||||
OperateLogService.AddOperateLog(operatorId, constants.OpTypeRemoveForbidden, constants.EntityUser, userId, "", r)
|
||||
}
|
||||
}
|
||||
|
||||
// GetByEmail 根据邮箱查找
|
||||
func (s *userService) GetByEmail(email string) *models.User {
|
||||
return repositories.UserRepository.GetByEmail(sqls.DB(), email)
|
||||
}
|
||||
|
||||
// GetByUsername 根据用户名查找
|
||||
func (s *userService) GetByUsername(username string) *models.User {
|
||||
return repositories.UserRepository.GetByUsername(sqls.DB(), username)
|
||||
}
|
||||
|
||||
// SignUp 注册
|
||||
func (s *userService) SignUp(username, email, nickname, password, rePassword string) (*models.User, error) {
|
||||
username = strings.TrimSpace(username)
|
||||
email = strings.TrimSpace(email)
|
||||
nickname = strings.TrimSpace(nickname)
|
||||
|
||||
// 验证昵称
|
||||
if len(nickname) == 0 {
|
||||
return nil, errors.New("昵称不能为空")
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
err := validate.IsValidPassword(password, rePassword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 验证邮箱
|
||||
if len(email) > 0 {
|
||||
if err := validate.IsEmail(email); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.GetByEmail(email) != nil {
|
||||
return nil, errors.New("邮箱:" + email + " 已被占用")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("请输入邮箱")
|
||||
}
|
||||
|
||||
// 验证用户名
|
||||
if len(username) > 0 {
|
||||
if err := validate.IsUsername(username); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.isUsernameExists(username) {
|
||||
return nil, errors.New("用户名:" + username + " 已被占用")
|
||||
}
|
||||
}
|
||||
|
||||
user := &models.User{
|
||||
Username: sqls.SqlNullString(username),
|
||||
Email: sqls.SqlNullString(email),
|
||||
Nickname: nickname,
|
||||
Password: passwd.EncodePassword(password),
|
||||
Status: constants.StatusOk,
|
||||
CreateTime: dates.NowTimestamp(),
|
||||
UpdateTime: dates.NowTimestamp(),
|
||||
}
|
||||
|
||||
err = repositories.UserRepository.Create(sqls.DB(), user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// SignIn 登录
|
||||
func (s *userService) SignIn(username, password string) (*models.User, error) {
|
||||
if strs.IsBlank(username) {
|
||||
return nil, errors.New("用户名/邮箱不能为空")
|
||||
}
|
||||
if strs.IsBlank(password) {
|
||||
return nil, errors.New("密码不能为空")
|
||||
}
|
||||
if err := validate.IsPassword(password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var user *models.User = nil
|
||||
if err := validate.IsEmail(username); err == nil { // 如果用户输入的是邮箱
|
||||
user = s.GetByEmail(username)
|
||||
} else {
|
||||
user = s.GetByUsername(username)
|
||||
}
|
||||
if user == nil || user.Status != constants.StatusOk {
|
||||
return nil, errors.New("用户名或密码错误")
|
||||
}
|
||||
if !passwd.ValidatePassword(user.Password, password) {
|
||||
return nil, errors.New("用户名或密码错误")
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// isEmailExists 邮箱是否存在
|
||||
func (s *userService) isEmailExists(email string) bool {
|
||||
if len(email) == 0 { // 如果邮箱为空,那么就认为是不存在
|
||||
return false
|
||||
}
|
||||
return s.GetByEmail(email) != nil
|
||||
}
|
||||
|
||||
// isUsernameExists 用户名是否存在
|
||||
func (s *userService) isUsernameExists(username string) bool {
|
||||
return s.GetByUsername(username) != nil
|
||||
}
|
||||
|
||||
// UpdateAvatar 更新头像
|
||||
func (s *userService) UpdateAvatar(userId int64, avatar string) error {
|
||||
return s.UpdateColumn(userId, "avatar", avatar)
|
||||
}
|
||||
|
||||
// UpdateNickname 更新昵称
|
||||
func (s *userService) UpdateNickname(userId int64, nickname string) error {
|
||||
return s.UpdateColumn(userId, "nickname", nickname)
|
||||
}
|
||||
|
||||
// UpdateDescription 更新简介
|
||||
func (s *userService) UpdateDescription(userId int64, description string) error {
|
||||
return s.UpdateColumn(userId, "description", description)
|
||||
}
|
||||
|
||||
// UpdateGender 修改性别
|
||||
func (s *userService) UpdateGender(userId int64, gender string) error {
|
||||
if strs.IsBlank(gender) {
|
||||
return s.UpdateColumn(userId, "gender", "")
|
||||
} else {
|
||||
if gender != string(constants.GenderMale) && gender != string(constants.GenderFemale) {
|
||||
return errors.New("invalidate gender value")
|
||||
}
|
||||
return s.UpdateColumn(userId, "gender", gender)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateBirthday 修改生日
|
||||
func (s *userService) UpdateBirthday(userId int64, birthdayStr string) error {
|
||||
if strs.IsBlank(birthdayStr) {
|
||||
return s.UpdateColumn(userId, "birthday", "")
|
||||
} else {
|
||||
birthday, err := dates.Parse(birthdayStr, dates.FmtDate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.UpdateColumn(userId, "birthday", birthday)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateBackgroundImage 修改背景图
|
||||
func (s *userService) UpdateBackgroundImage(userId int64, backgroundImage string) error {
|
||||
return s.UpdateColumn(userId, "background_image", backgroundImage)
|
||||
}
|
||||
|
||||
// SetUsername 设置用户名
|
||||
func (s *userService) SetUsername(userId int64, username string) error {
|
||||
username = strings.TrimSpace(username)
|
||||
if err := validate.IsUsername(username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := s.Get(userId)
|
||||
if len(user.Username.String) > 0 {
|
||||
return errors.New("你已设置了用户名,无法重复设置。")
|
||||
}
|
||||
if s.isUsernameExists(username) {
|
||||
return errors.New("用户名:" + username + " 已被占用")
|
||||
}
|
||||
return s.UpdateColumn(userId, "username", username)
|
||||
}
|
||||
|
||||
// SetEmail 设置密码
|
||||
func (s *userService) SetEmail(userId int64, email string) error {
|
||||
email = strings.TrimSpace(email)
|
||||
if err := validate.IsEmail(email); err != nil {
|
||||
return err
|
||||
}
|
||||
user := s.Get(userId)
|
||||
if user == nil {
|
||||
return errors.New("用户不存在")
|
||||
}
|
||||
if user.Email.String == email {
|
||||
// 用户邮箱没做变更
|
||||
return nil
|
||||
}
|
||||
if s.isEmailExists(email) {
|
||||
return errors.New("邮箱:" + email + " 已被占用")
|
||||
}
|
||||
return s.Updates(userId, map[string]interface{}{
|
||||
"email": email,
|
||||
"email_verified": false,
|
||||
})
|
||||
}
|
||||
|
||||
// SetPassword 设置密码
|
||||
func (s *userService) SetPassword(userId int64, password, rePassword string) error {
|
||||
if err := validate.IsValidPassword(password, rePassword); err != nil {
|
||||
return err
|
||||
}
|
||||
user := s.Get(userId)
|
||||
if len(user.Password) > 0 {
|
||||
return errors.New("你已设置了密码,如需修改请前往修改页面。")
|
||||
}
|
||||
password = passwd.EncodePassword(password)
|
||||
return s.UpdateColumn(userId, "password", password)
|
||||
}
|
||||
|
||||
// UpdatePassword 修改密码
|
||||
func (s *userService) UpdatePassword(userId int64, oldPassword, password, rePassword string) error {
|
||||
if err := validate.IsValidPassword(password, rePassword); err != nil {
|
||||
return err
|
||||
}
|
||||
user := s.Get(userId)
|
||||
|
||||
if len(user.Password) == 0 {
|
||||
return errors.New("你没设置密码,请先设置密码")
|
||||
}
|
||||
|
||||
if !passwd.ValidatePassword(user.Password, oldPassword) {
|
||||
return errors.New("旧密码验证失败")
|
||||
}
|
||||
|
||||
return s.UpdateColumn(userId, "password", passwd.EncodePassword(password))
|
||||
}
|
||||
|
||||
// IncrTopicCount topic_count + 1
|
||||
func (s *userService) IncrTopicCount(tx *gorm.DB, userId int64) error {
|
||||
if err := repositories.UserRepository.UpdateColumn(sqls.DB(), userId, "topic_count", gorm.Expr("topic_count + 1")); err != nil {
|
||||
slog.Error(err.Error(), slog.Any("err", err))
|
||||
return err
|
||||
}
|
||||
cache.UserCache.Invalidate(userId)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IncrCommentCount comment_count + 1
|
||||
func (s *userService) IncrCommentCount(userId int64) int {
|
||||
t := repositories.UserRepository.Get(sqls.DB(), userId)
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
commentCount := t.CommentCount + 1
|
||||
if err := repositories.UserRepository.UpdateColumn(sqls.DB(), userId, "comment_count", commentCount); err != nil {
|
||||
slog.Error(err.Error(), slog.Any("err", err))
|
||||
} else {
|
||||
cache.UserCache.Invalidate(userId)
|
||||
}
|
||||
return commentCount
|
||||
}
|
||||
|
||||
// SyncUserCount 同步用户计数
|
||||
func (s *userService) SyncUserCount() {
|
||||
s.Scan(func(users []models.User) {
|
||||
for _, user := range users {
|
||||
topicCount := repositories.TopicRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).Eq("status", constants.StatusOk))
|
||||
commentCount := repositories.CommentRepository.Count(sqls.DB(), sqls.NewCnd().Eq("user_id", user.Id).Eq("status", constants.StatusOk))
|
||||
_ = repositories.UserRepository.UpdateColumn(sqls.DB(), user.Id, "topic_count", topicCount)
|
||||
_ = repositories.UserRepository.UpdateColumn(sqls.DB(), user.Id, "comment_count", commentCount)
|
||||
cache.UserCache.Invalidate(user.Id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// SendEmailVerifyEmail 发送邮箱验证邮件
|
||||
func (s *userService) SendEmailVerifyEmail(userId int64) error {
|
||||
user := s.Get(userId)
|
||||
if user == nil {
|
||||
return errors.New("用户不存在")
|
||||
}
|
||||
if user.EmailVerified {
|
||||
return errors.New("用户邮箱已验证")
|
||||
}
|
||||
if err := validate.IsEmail(user.Email.String); err != nil {
|
||||
return err
|
||||
}
|
||||
// 如果设置了邮箱白名单
|
||||
if emailWhitelist := SysConfigService.GetEmailWhitelist(); len(emailWhitelist) > 0 {
|
||||
isInWhitelist := false
|
||||
for _, whitelist := range emailWhitelist {
|
||||
if strings.Contains(strings.ToLower(user.Email.String), strings.ToLower(whitelist)) {
|
||||
isInWhitelist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isInWhitelist {
|
||||
// 直接返回,也不抛出异常了,就是不发邮件
|
||||
slog.Error("不支持使用该邮箱进行验证.", slog.String("email", user.Email.String))
|
||||
return errors.New("不支持该类型邮箱")
|
||||
}
|
||||
}
|
||||
var (
|
||||
token = strs.UUID()
|
||||
url = bbsurls.AbsUrl("/user/email/verify?token=" + token)
|
||||
link = &models.ActionLink{Title: "点击这里验证邮箱>>", Url: url}
|
||||
siteTitle = cache.SysConfigCache.GetValue(constants.SysConfigSiteTitle)
|
||||
subject = "邮箱验证 - " + siteTitle
|
||||
title = "邮箱验证 - " + siteTitle
|
||||
content = "该邮件用于验证你在 " + siteTitle + " 中设置邮箱的正确性,请在" + strconv.Itoa(emailVerifyExpireHour) + "小时内完成验证。验证链接:" + url
|
||||
)
|
||||
return sqls.DB().Transaction(func(tx *gorm.DB) error {
|
||||
if err := repositories.EmailCodeRepository.Create(tx, &models.EmailCode{
|
||||
Model: models.Model{},
|
||||
UserId: userId,
|
||||
Email: user.Email.String,
|
||||
Code: "",
|
||||
Token: token,
|
||||
Title: title,
|
||||
Content: content,
|
||||
Used: false,
|
||||
CreateTime: dates.NowTimestamp(),
|
||||
}); err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := email.SendTemplateEmail(nil, user.Email.String, subject, title, content, "", link); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// VerifyEmail 验证邮箱
|
||||
func (s *userService) VerifyEmail(token string) (string, error) {
|
||||
emailCode := EmailCodeService.FindOne(sqls.NewCnd().Eq("token", token))
|
||||
if emailCode == nil || emailCode.Used {
|
||||
return "", errors.New("非法请求")
|
||||
}
|
||||
|
||||
user := s.Get(emailCode.UserId)
|
||||
if user == nil || emailCode.Email != user.Email.String {
|
||||
return "", errors.New("验证码过期")
|
||||
}
|
||||
if dates.FromTimestamp(emailCode.CreateTime).Add(time.Hour * time.Duration(emailVerifyExpireHour)).Before(time.Now()) {
|
||||
return "", errors.New("验证邮件已过期")
|
||||
}
|
||||
err := sqls.DB().Transaction(func(tx *gorm.DB) error {
|
||||
if err := repositories.UserRepository.UpdateColumn(tx, emailCode.UserId, "email_verified", true); err != nil {
|
||||
return err
|
||||
}
|
||||
cache.UserCache.Invalidate(emailCode.UserId)
|
||||
return repositories.EmailCodeRepository.UpdateColumn(tx, emailCode.Id, "used", true)
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return emailCode.Email, nil
|
||||
}
|
||||
|
||||
// CheckPostStatus 用于在发表内容时检查用户状态
|
||||
func (s *userService) CheckPostStatus(user *models.User) error {
|
||||
if user == nil {
|
||||
return errs.NotLogin
|
||||
}
|
||||
if user.Status != constants.StatusOk {
|
||||
return errs.UserDisabled
|
||||
}
|
||||
if user.IsForbidden() {
|
||||
return errs.ForbiddenError
|
||||
}
|
||||
observeSeconds := SysConfigService.GetInt(constants.SysConfigUserObserveSeconds, 0)
|
||||
if user.InObservationPeriod(observeSeconds) {
|
||||
return web.NewError(errs.InObservationPeriod.Code, "账号尚在观察期,观察期时长:"+strconv.Itoa(observeSeconds)+"秒,请稍后再试")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IncrScoreForPostTopic 发帖获积分
|
||||
func (s *userService) IncrScoreForPostTopic(topic *models.Topic) {
|
||||
config := SysConfigService.GetConfig()
|
||||
if config.ScoreConfig.PostTopicScore <= 0 {
|
||||
slog.Info("请配置发帖积分")
|
||||
return
|
||||
}
|
||||
err := s.addScore(topic.UserId, config.ScoreConfig.PostTopicScore, constants.EntityTopic,
|
||||
strconv.FormatInt(topic.Id, 10), "发表话题")
|
||||
if err != nil {
|
||||
slog.Error(err.Error(), slog.Any("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
// IncrScoreForPostComment 跟帖获积分
|
||||
func (s *userService) IncrScoreForPostComment(comment *models.Comment) {
|
||||
// 非话题跟帖,跳过
|
||||
if comment.EntityType != constants.EntityTopic {
|
||||
return
|
||||
}
|
||||
config := SysConfigService.GetConfig()
|
||||
if config.ScoreConfig.PostCommentScore <= 0 {
|
||||
slog.Info("请配置跟帖积分")
|
||||
return
|
||||
}
|
||||
err := s.addScore(comment.UserId, config.ScoreConfig.PostCommentScore, constants.EntityComment,
|
||||
strconv.FormatInt(comment.Id, 10), "发表跟帖")
|
||||
if err != nil {
|
||||
slog.Error(err.Error(), slog.Any("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
// IncrScore 增加分数
|
||||
func (s *userService) IncrScore(userId int64, score int, sourceType, sourceId, description string) error {
|
||||
if score <= 0 {
|
||||
return errors.New("分数必须为正数")
|
||||
}
|
||||
return s.addScore(userId, score, sourceType, sourceId, description)
|
||||
}
|
||||
|
||||
// DecrScore 减少分数
|
||||
func (s *userService) DecrScore(userId int64, score int, sourceType, sourceId, description string) error {
|
||||
if score <= 0 {
|
||||
return errors.New("分数必须为正数")
|
||||
}
|
||||
return s.addScore(userId, -score, sourceType, sourceId, description)
|
||||
}
|
||||
|
||||
// addScore 加分数,也可以加负数
|
||||
func (s *userService) addScore(userId int64, score int, sourceType, sourceId, description string) error {
|
||||
if score == 0 {
|
||||
return errors.New("分数不能为0")
|
||||
}
|
||||
user := s.Get(userId)
|
||||
if user == nil {
|
||||
return errors.New("用户不存在")
|
||||
}
|
||||
if err := s.Updates(userId, map[string]interface{}{
|
||||
"score": gorm.Expr("score + ?", score),
|
||||
"update_time": dates.NowTimestamp(),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scoreType := constants.ScoreTypeIncr
|
||||
if score < 0 {
|
||||
scoreType = constants.ScoreTypeDecr
|
||||
}
|
||||
err := UserScoreLogService.Create(&models.UserScoreLog{
|
||||
UserId: userId,
|
||||
SourceType: sourceType,
|
||||
SourceId: sourceId,
|
||||
Description: description,
|
||||
Type: scoreType,
|
||||
Score: score,
|
||||
CreateTime: dates.NowTimestamp(),
|
||||
})
|
||||
if err == nil {
|
||||
cache.UserCache.Invalidate(userId)
|
||||
}
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user