Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
package prize_record_mod
import (
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type PrizeType int
type Location int
// 奖品类型 1-金币 2-游戏币 3-会员卡 4-vip 5-金币加赠券 6-金币观影券 7-实物
const (
PrizeTypeGold PrizeType = iota + 1 // 1、金币
PrizeTypeGameGold // 2、棋牌游戏币
PrizeTypeVIPCard // 3、会员卡
PrizeTypeVIP // 4、VIP
PrizeTypeGoldCoinBonus // 5、金币加赠券
PrizeTypeGoldWatch // 6、金币观影券
PrizeTypeInKind // 7、实物奖励
PrizeTypeAiUndress // 8、AI脱衣次数
PrizeTypeGoldDiscountCoupon // 9、AI金币抵扣券
)
const (
Turntable Location = iota + 1 // 大转盘
LuckPrize // 幸运奖
)
// AppUploadReq 优惠券上传请求
type AppUploadReq struct {
Count int64 `json:"count" bson:"count"` // 抽奖次数
Gold int64 `json:"gold" bson:"gold"` // 抽奖花费金币. 如果使用的是免费次数, 该值为0
Prizes []*Prize `json:"prizes" bson:"prizes"` // 奖品情况
}
// AppDeleteReq 优惠券删除请求
type AppDeleteReq struct {
ID primitive.ObjectID `json:"id" bson:"id"` // 优惠券删除
}
func (receiver *AppDeleteReq) Filter() bson.M {
return bson.M{"_id": receiver.ID}
}
type Prize struct {
ID primitive.ObjectID `json:"id" bson:"id,omitempty"` // 自增id
AppId int `json:"appId" bson:"appId"` // AppId
Name string `json:"name" bson:"name"` // 奖品名称
CursorLand int `json:"cursorLand" bson:"cursorLand"` // 光标落点
PrizeType PrizeType `json:"prizeType" bson:"prizeType"` // 奖品类型 1-金币 2-游戏币 3-会员卡 4-vip 5-金币加赠券 6-金币观影券 7-实物
Count int32 `json:"count" bson:"count"` // 奖品数量
Price int64 `json:"price" bson:"price"` // 奖品价值
Sort int32 `json:"sort" bson:"sort"` // 奖品排序
Weights int `json:"weights" bson:"weights"` // 中奖权重
WaterLevel int64 `json:"waterLevel" bson:"waterLevel"` // 水位
LowAttenuation int64 `json:"lowAttenuation" bson:"lowAttenuation"` // 低消
Cistern int64 `json:"cistern" bson:"cistern"` // 蓄水池
PrizeLocation Location `json:"prizeLocation" bson:"prizeLocation"` // 礼包位置 1-大转盘 2-幸运奖
Status bool `json:"status" bson:"status"` // 启用/禁用
Image string `json:"image" bson:"image"` // 图片地址
ValidDate int `json:"validDate" bson:"validDate"` // 过期天数
UpdateTime time.Time `json:"updateTime" bson:"updateTime"` // 修改时间
CreateTime time.Time `json:"createTime" bson:"createTime"` // 创建时间
Param1 string `json:"param1" json:"param1"` // 扩容字段
}
+404
View File
@@ -0,0 +1,404 @@
package prize_record_mod
import (
"91porn-server/common"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/models/v/backpackmod"
"91porn-server/models/v/coupon_record_mod"
"91porn-server/models/v/productmod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/walletmod"
"errors"
"fmt"
"sync"
"time"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var mu = sync.Mutex{}
type PrizeRecordHandler interface {
Run(t *db.MongoTool) error
GetTransactionLog() []txnmod.TransactionLog
}
func Run(u usermod.User, p Prize, transType txnmod.TransType) (PrizeRecordHandler, error) {
switch p.PrizeType {
case PrizeTypeGold:
// 1、金币
return newAddGold(u, p, transType), nil
case PrizeTypeVIPCard:
// 3、会员卡
return newAddVIPCard(u, p, transType), nil
case PrizeTypeVIP:
// 4、VIP
return newAddVIP(u, p, transType), nil
case PrizeTypeGoldWatch:
// 6、金币观影券
return newAddGoldWatch(u, p, transType), nil
case PrizeTypeGoldCoinBonus:
// 5、金币加赠券
return newAddGoldCoinBonus(u, p, transType), nil
case PrizeTypeInKind:
// 7、实物奖励
return newAddInKind(u, p, transType), nil
default:
return nil, errors.New("未知类型")
}
}
// addGold 新增用户金币
type addGold struct {
u usermod.User
p Prize
transType txnmod.TransType
wallet *walletmod.Wallet
}
// newAddGold 处理程序初始化
func newAddGold(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addGold{
u: u,
p: p,
transType: transType,
}
}
// Run 运行
func (h *addGold) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
walletInfo, err := walletmod.CreditAmount(t, h.p.Price, h.u.UID)
if err != nil {
return err
}
h.wallet = walletInfo
return nil
}
// GetTransactionLog 用户金币资金流水记录
func (h *addGold) GetTransactionLog() (out []txnmod.TransactionLog) {
out = append(out, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: h.u.UID,
Amount: h.p.Price,
ActualAmount: float64(h.p.Price),
TranType: h.transType.Key(),
TranTypeInt: int64(h.transType),
Desc: fmt.Sprintf("%s+金币[%d个]", h.transType.Key(), h.p.Price),
RealAmount: func() decimal.Decimal {
if h.wallet == nil {
return decimal.NewFromInt(0)
}
return h.wallet.RealAmount()
}(),
})
return
}
// addVIPDiscount 新增用户VIP折扣
type addVIPDiscount struct {
u usermod.User
p Prize
transType txnmod.TransType
wallet *walletmod.Wallet
}
// newAddVIPDiscount 处理程序初始化
func newAddVIPDiscount(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addVIPDiscount{
u: u,
p: p,
transType: transType,
}
}
// Run VIP折扣运行
func (h *addVIPDiscount) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
// 处理会员折扣
var (
goodsList []backpackmod.Backpack
now time.Time = time.Now()
)
for i := 0; i < int(h.p.Count); i++ {
goodsList = append(goodsList, backpackmod.Backpack{
UID: h.u.UID,
GoodsName: h.p.Name,
GoodsType: backpackmod.VIPDiscount,
GoodsValue: h.p.Price,
GoodsOrigin: h.transType.Key(),
GoodsDesc: h.p.Name,
Status: backpackmod.Unused,
ExpiredTime: now.AddDate(0, 0, int(h.p.ValidDate)),
CreateTime: now,
})
}
if len(goodsList) <= 0 {
return nil
}
if err := backpackmod.AddGoodsMany(t, h.u.UID, goodsList); err != nil {
return err
}
return nil
}
// GetTransactionLog 用户金币资金流水记录
func (h *addVIPDiscount) GetTransactionLog() (out []txnmod.TransactionLog) {
out = append(out, txnmod.TransactionLog{
TransNo: primitive.NewObjectID(),
UID: h.u.UID,
Money: decimal.NewFromInt(h.p.Price),
TranType: h.transType.Key(),
TranTypeInt: int64(h.transType),
Desc: fmt.Sprintf("%s-棋牌金币[%d个]", h.transType.Key(), h.p.Price),
})
return
}
// addVIP 新增用户VIP
type addVIP struct {
u usermod.User
p Prize
transType txnmod.TransType
wallet *walletmod.Wallet
}
// newAddVIP 处理程序初始化
func newAddVIP(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addVIP{
u: u,
p: p,
transType: transType,
}
}
// Run VIP运行
func (h *addVIP) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
// 处理会员
if _, err := usermod.Update(h.u.UID, usermod.UserSelector{VipExpireDate: &h.u.VipExpireDate, VipLevel: &h.u.VipLevel}); err != nil {
return err
}
return nil
}
// GetTransactionLog 用户VIP流水记录
func (h *addVIP) GetTransactionLog() (out []txnmod.TransactionLog) {
return
}
// addGoldCoinBonus 新增金币加赠券
type addGoldCoinBonus struct {
u usermod.User
p Prize
transType txnmod.TransType
wallet *walletmod.Wallet
}
// newAddGoldCoinBonus 处理程序初始化
func newAddGoldCoinBonus(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addGoldCoinBonus{
u: u,
p: p,
transType: transType,
}
}
// Run 金币加赠券运行
func (h *addGoldCoinBonus) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
time.Sleep(time.Duration(10) * time.Millisecond)
// 获取观影券是否存在
cId := HandleCId(h.p.ID)
c, err := coupon_record_mod.FindOneByCId(cId)
if err != nil {
return err
}
if !c.ID.IsZero() {
return stderr.New(400, "coupon_record is exist")
}
// 保存用户优惠券
now := time.Now()
newCo := coupon_record_mod.CouponRecord{
CID: cId,
PID: h.p.ID,
UID: h.u.UID,
UserName: h.u.Name,
Name: h.p.Name,
Count: h.p.Count,
Price: h.p.Price,
Type: coupon_record_mod.PrizeTypeGoldCoinBonus,
Used: false,
IsDelete: false,
ExpireTime: now.Add(time.Hour * 24 * time.Duration(h.p.ValidDate)),
}
err = coupon_record_mod.InsertOne(newCo)
if err != nil {
return err
}
return nil
}
// GetTransactionLog 金币观影券流水记录
func (h *addGoldCoinBonus) GetTransactionLog() (out []txnmod.TransactionLog) {
return
}
// addGoldWatch 新增金币观影券
type addGoldWatch struct {
u usermod.User
p Prize
transType txnmod.TransType
wallet *walletmod.Wallet
}
// newAddGoldWatch s处理程序初始化
func newAddGoldWatch(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addGoldWatch{
u: u,
p: p,
transType: transType,
}
}
// Run 金币观影券运行
func (h *addGoldWatch) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
cId := HandleCId(h.p.ID)
// 获取观影券是否存在
c, err := coupon_record_mod.FindOneByCId(cId)
if err != nil {
return err
}
if !c.ID.IsZero() {
return stderr.New(400, "coupon_record is exist")
}
// 保存用户优惠券
now := time.Now()
newCo := coupon_record_mod.CouponRecord{
CID: cId,
PID: h.p.ID,
UID: h.u.UID,
UserName: h.u.Name,
Name: h.p.Name,
Count: h.p.Count,
Price: h.p.Price,
Type: coupon_record_mod.PrizeTypeGoldWatch,
Used: false,
IsDelete: false,
ExpireTime: now.Add(time.Hour * 24 * time.Duration(h.p.ValidDate)),
}
err = coupon_record_mod.InsertOne(newCo)
if err != nil {
return err
}
return nil
}
// GetTransactionLog 金币观影券流水记录
func (h *addGoldWatch) GetTransactionLog() (out []txnmod.TransactionLog) {
return
}
// 会员卡处理
type addVIPCard struct {
u usermod.User
p Prize
transType txnmod.TransType
}
// 处理程序初始化
func newAddVIPCard(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addVIPCard{
u: u,
p: p,
transType: transType,
}
}
// Run VIP会员卡运行
func (h *addVIPCard) Run(t *db.MongoTool) error {
mu.Lock()
defer mu.Unlock()
set := usermod.UserSelector{VipExpireDate: &h.u.VipExpireDate, VipLevel: &h.u.VipLevel, PayVidDiscount: &h.u.PayVidDiscount}
if err := usermod.UpdateUserById(t, h.u.UID, set); err != nil {
return err
}
return nil
}
// GetTransactionLog 资金流水记录
func (h *addVIPCard) GetTransactionLog() (out []txnmod.TransactionLog) {
return
}
func CheckVipRenew(u *usermod.User, p *productmod.Product) (time.Time, int, int) {
now := time.Now()
end := time.Time{}
level := u.VipLevel
payVidDiscount := u.PayVidDiscount
d, _ := time.ParseDuration("24h")
d = d * time.Duration(p.Duration)
if u.VipExpireDate.After(now) { //renew
end = u.VipExpireDate.Add(d)
} else {
end = now.Add(time.Duration(d))
}
if p.VipLevel > level { //当前用户的vip等级比这次购买的大,使用用户的
level = p.VipLevel
}
if p.PayVidDiscount > 0 && payVidDiscount == 0 {
payVidDiscount = p.PayVidDiscount
}
if p.PayVidDiscount > 0 && p.PayVidDiscount < payVidDiscount {
payVidDiscount = p.PayVidDiscount
}
return end, level, payVidDiscount
}
// addInKinds 派发实物
type addInKinds struct {
u usermod.User
p Prize
transType txnmod.TransType
}
// 处理程序初始化
func newAddInKind(u usermod.User, p Prize, transType txnmod.TransType) PrizeRecordHandler {
return &addInKinds{
u: u,
p: p,
transType: transType,
}
}
// Run 具体派发流程
func (h *addInKinds) Run(t *db.MongoTool) error {
log.Info(fmt.Sprintf("用户ID:%d;奖品ID:%v;正在派发奖品", h.u.UID, h.p.ID))
log.Info(fmt.Sprintf("用户ID:%d;奖品ID:%v;派发奖品成功", h.u.UID, h.p.ID))
return nil
}
// GetTransactionLog 派发日志记录
func (h *addInKinds) GetTransactionLog() (out []txnmod.TransactionLog) {
return
}
func HandleCId(id primitive.ObjectID) string {
return id.Hex() + common.UUID()
}
+25
View File
@@ -0,0 +1,25 @@
package prize_record_mod
import (
"91porn-server/models/v/prizemod"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// PrizeRecord 用户抽奖记录
type PrizeRecord struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // 文档ID
ActivityID primitive.ObjectID `json:"activityId" bson:"activityId"` // 活动ID
VIPCardID primitive.ObjectID `json:"vipCardId" bson:"vipCardId"` // 会员卡ID
UID uint64 `json:"uid" bson:"uid"` // 用户ID
UserName string `json:"userName" bson:"userName"` // 用户名
Name string `json:"name" bson:"name"` // 奖品名称
Type prizemod.PrizeType `json:"type" bson:"type"` // 奖品类型
Count int32 `json:"count" bson:"count"` // 奖品数量
Price int64 `json:"price" bson:"price"` // 奖品价值
Value int64 `json:"value" bson:"value"` // 折扣率/活跃值
Level prizemod.PrizeLevel `json:"level" bson:"level"` // 奖品等级
DrawPrice int64 `json:"drawPrice" bson:"drawPrice"` // 单次抽奖价格(金币)
CreateTime time.Time `json:"createTime" bson:"createTime"` // 创建时间
}