622 lines
18 KiB
Go
622 lines
18 KiB
Go
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
|
|
}
|