Files
huangguo_server/app/service/taskser/sign.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

434 lines
12 KiB
Go

package taskser
import (
"91porn-server/app/appg"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/common/timeutil"
"91porn-server/models/v/prizemod"
"91porn-server/models/v/signtaskmod"
"91porn-server/models/v/taskrecordmod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/usermod"
"encoding/json"
"sort"
"strconv"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// 签到
func Sign(uid uint64, configID string) (code stderr.Code) {
now := time.Now()
id, err := primitive.ObjectIDFromHex(configID)
if err != nil {
return stderr.ErrParamError
}
// 获取用户信息
u, err := usermod.FindUserByUID(uid)
if err != nil || u == nil {
code = stderr.UserIsNotExists
return
}
// 获取配置列表
signConfig, err := signtaskmod.GetConfigList()
if err != nil {
return stderr.ErrDbQueryError
}
// 查询当前签到配置
configInfo, err := signtaskmod.GetConfigByID(id)
if err != nil {
return stderr.ErrDbQueryError
}
// 异常判定 未配置签到福利/签到福利类型不正确
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
log.Info("未配置签到福利")
return stderr.ErrInvalidRequest
}
// 查询签到信息
signRecordMap := make(map[string]bool, 0)
taskInfo, err := taskrecordmod.GetSignRecord(uid)
if err != nil {
return stderr.ErrDbQueryError
}
if taskInfo == nil {
log.Info("未查询到签到任务")
return stderr.ErrDbQueryError
}
for _, taskId := range taskInfo.SignRecord {
signRecordMap[taskId.Hex()] = true
}
// 判断是否重复签到
if _, ok := signRecordMap[configID]; ok {
log.Info("已签到")
return stderr.HasSigned
}
// 计算相差多少天
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
diffDays := int64(duration.Hours() / 24)
// 判断此签到是否是当天签到
if configInfo.FinishCondition-1 != diffDays {
log.Info("条件不匹配")
return stderr.ErrInvalidRequest
}
// 获取奖品列表
prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes)
if err != nil {
return stderr.ErrDbQueryError
}
// 获取额外奖品列表
signCount := len(signRecordMap)
for _, item := range signConfig {
if item.FinishCondition == int64(signCount)+1 {
extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes)
if e != nil {
continue
}
prizes = append(prizes, extraPrizeIds...)
}
}
// 更新签到记录(事务)
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil {
return err
}
return nil
}); err != nil {
return stderr.ErrDbTransError
}
// 发放奖励
for _, v := range prizes {
for i := 0; i < int(v.Count); i++ {
handler, err := prizemod.Run(uid, *v, txnmod.SignBoon)
if err != nil {
log.Error("签到发放奖励handler失败:", log.Any("err", err))
continue
}
err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
err = handler.Run(t)
if err != nil {
return err
}
err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog())
if err != nil {
return err
}
return nil
})
if err != nil {
log.Error("签到发放奖励事务失败:", log.Any("err", err))
continue
}
}
}
return stderr.Success
}
// 补签
func ReSign(uid uint64, configID string) (code stderr.Code) {
now := time.Now()
redisKey := "task::resign::" + strconv.FormatUint(uid, 10)
if appg.Redis.Exists(redisKey) {
return stderr.ExceededTimes
}
id, err := primitive.ObjectIDFromHex(configID)
if err != nil {
return stderr.ErrParamError
}
// 获取用户信息
u, err := usermod.FindUserByUID(uid)
if err != nil || u == nil {
code = stderr.UserIsNotExists
return
}
// 获取配置列表
signConfig, err := signtaskmod.GetConfigList()
if err != nil {
return stderr.ErrDbQueryError
}
// 查询当前签到配置
configInfo, err := signtaskmod.GetConfigByID(id)
if err != nil {
return stderr.ErrDbQueryError
}
// 异常判定 未配置签到福利/签到福利类型不正确
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
log.Info("未配置签到福利")
return stderr.ErrInvalidRequest
}
//查询签到信息
signRecordMap := make(map[string]bool, 0)
taskInfo, err := taskrecordmod.GetSignRecord(uid)
if err != nil {
return stderr.ErrDbQueryError
}
if taskInfo == nil {
log.Info("未查询到签到任务")
return stderr.ErrDbQueryError
}
for _, taskId := range taskInfo.SignRecord {
signRecordMap[taskId.Hex()] = true
}
// 判断是否重复签到
if _, ok := signRecordMap[configID]; ok {
log.Info("已签到")
return stderr.HasSigned
}
// 计算相差多少天
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
diffDays := int64(duration.Hours() / 24)
// 判断是否在补签范围
if configInfo.FinishCondition > diffDays {
log.Info("条件不匹配")
return stderr.ErrInvalidRequest
}
// redis作为倒计时(一天只能补签一次)
seconds := int64(timeutil.BeginningOfTomorrow(now).Sub(now).Seconds())
err = appg.Redis.Set(redisKey, configID, time.Duration(seconds)*time.Second)
if err != nil {
log.Error(err.Error())
}
return stderr.Success
}
// 补签回调
func ReSignCallBack(uid uint64) (code stderr.Code) {
now := time.Now()
redisKey := "task::resign::" + strconv.FormatUint(uid, 10)
if !appg.Redis.Exists(redisKey) {
return stderr.ErrParamError
}
configID, err := appg.Redis.Get(redisKey)
if err != nil {
log.Error("redis缓存不存在!")
return stderr.ErrParamError
}
if configID == nil {
log.Error("签到配置不存在!")
return stderr.ErrParamError
}
id, err := primitive.ObjectIDFromHex(*configID)
if err != nil {
return stderr.ErrParamError
}
// 获取用户信息
u, err := usermod.FindUserByUID(uid)
if err != nil || u == nil {
code = stderr.UserIsNotExists
return
}
// 获取配置列表
signConfig, err := signtaskmod.GetConfigList()
if err != nil {
return stderr.ErrDbQueryError
}
// 查询当前签到配置
configInfo, err := signtaskmod.GetConfigByID(id)
if err != nil {
return stderr.ErrDbQueryError
}
// 异常判定 未配置签到福利/签到福利类型不正确
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
log.Info("未配置签到福利")
return stderr.ErrInvalidRequest
}
//查询签到信息
signRecordMap := make(map[string]bool, 0)
taskInfo, err := taskrecordmod.GetSignRecord(uid)
if err != nil {
return stderr.ErrDbQueryError
}
if taskInfo == nil {
log.Info("未查询到签到任务")
return stderr.ErrDbQueryError
}
for _, taskId := range taskInfo.SignRecord {
signRecordMap[taskId.Hex()] = true
}
// 判断是否重复签到
if _, ok := signRecordMap[*configID]; ok {
log.Info("已签到")
return stderr.HasSigned
}
// 计算相差多少天
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
diffDays := int64(duration.Hours() / 24)
// 判断是否在补签范围
if configInfo.FinishCondition > diffDays {
log.Info("条件不匹配")
return stderr.ErrInvalidRequest
}
// 获取奖品列表
prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes)
if err != nil {
return stderr.ErrDbQueryError
}
// 获取额外奖品列表
signCount := len(signRecordMap)
for _, item := range signConfig {
if item.FinishCondition == int64(signCount) {
extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes)
if e != nil {
continue
}
prizes = append(prizes, extraPrizeIds...)
}
}
// 更新签到记录(事务)
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil {
return err
}
return nil
}); err != nil {
return stderr.ErrDbTransError
}
// 发放奖励
for _, v := range prizes {
for i := 0; i < int(v.Count); i++ {
handler, err := prizemod.Run(uid, *v, txnmod.SignBoon)
if err != nil {
log.Error("签到发放奖励handler失败:", log.Any("err", err))
continue
}
err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
err = handler.Run(t)
if err != nil {
return err
}
err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog())
if err != nil {
return err
}
return nil
})
if err != nil {
log.Error("签到发放奖励事务失败:", log.Any("err", err))
continue
}
}
}
return stderr.Success
}
// 获取签到额外奖励
func SignExtraPrizes(uid uint64) (out []map[string]interface{}, code stderr.Code) {
out = make([]map[string]interface{}, 0)
taskInfo, err := taskrecordmod.GetSignRecord(uid)
if err != nil {
return out, stderr.ErrDbQueryError
}
signRecords := make([]primitive.ObjectID, 0)
if taskInfo != nil {
signRecords = taskInfo.SignRecord
}
signConfig, err := signtaskmod.GetConfigList()
if err != nil {
return out, stderr.ErrDbQueryError
}
// 获取奖品列表
prizes, err := prizemod.GetPrizeList()
for _, item := range signConfig {
if len(item.ExtraPrizes) == 0 {
continue
}
extraPrizes := getPrizeList(item.ExtraPrizes, prizes)
for _, prize := range extraPrizes {
b, _ := json.Marshal(&prize)
var extraPrizeMap map[string]interface{}
_ = json.Unmarshal(b, &extraPrizeMap)
days := item.FinishCondition - int64(len(signRecords))
if days < 0 {
days = 0
}
extraPrizeMap["finishCondition"] = days
// 设置额外奖励领取状态
if len(signRecords) >= int(item.FinishCondition) {
extraPrizeMap["extraPrizeStatus"] = true
} else {
extraPrizeMap["extraPrizeStatus"] = false
}
out = append(out, extraPrizeMap)
}
}
sort.Slice(out, func(i, j int) bool {
valI := out[i]["extraPrizeStatus"].(bool)
valJ := out[j]["extraPrizeStatus"].(bool)
return !valI && valJ
})
return out, stderr.Success
}
// 获取签到详情
func GetSignDetails(uid uint64) (out SignDetailsResponse, code stderr.Code) {
now := time.Now()
// 获取配置列表
signConfig, err := signtaskmod.GetConfigList()
if err != nil {
return out, stderr.ErrDbQueryError
}
// 查询用户签到信息
signRecordMap := make(map[string]bool, 0)
taskInfo, err := taskrecordmod.GetSignRecord(uid)
if err != nil {
return out, stderr.ErrDbQueryError
}
// 新增用户任务记录
if taskInfo == nil {
taskInfo, err = taskrecordmod.TaskSignInit(uid)
if err != nil {
return out, stderr.ErrDbQueryError
}
}
// 计算相差多少天
diffDays := int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24)
// 判断是否重置数据
if diffDays >= len(signConfig) {
taskInfo, err = taskrecordmod.TaskSignReset(uid)
if err != nil {
return out, stderr.ErrDbQueryError
}
}
// 构建签到记录map
for _, item := range taskInfo.SignRecord {
signRecordMap[item.String()] = true
}
// 获取奖品列表
prizes, err := prizemod.GetPrizeList()
if err != nil {
return out, stderr.ErrDbQueryError
}
out.Value = int64(len(taskInfo.SignRecord))
out.List = make([]Config, len(signConfig))
for i, v := range signConfig {
taskConfig := Config{
ID: v.ID,
Prizes: getPrizeList(v.Prizes, prizes),
FinishCondition: v.FinishCondition,
Title: v.Title,
Desc: v.Desc,
Status: UnDone,
}
// 存在表示已经签到,不存在则需要判断是否是补签
if _, ok := signRecordMap[v.ID.String()]; ok {
// 如果存在,标记为已完成
taskConfig.Status = Finish
} else {
diffDays = int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24)
if i < diffDays {
taskConfig.Status = ReDo
}
}
out.List[i] = taskConfig
}
// 当日任务标识
if diffDays >= 0 && diffDays < len(out.List) {
out.List[diffDays].IsToday = true
}
return out, stderr.Success
}