@@ -0,0 +1,192 @@
|
||||
package sys_config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/app/proto"
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/constant/redisconst"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models/v/sysconfmod"
|
||||
"91porn-server/models/v/usermod"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
// mapUserPaymentStatusPopup 用户付费状态分层 → 需要拉取的配置项集合
|
||||
var mapUserPaymentStatusPopup = map[string]map[sysconfmod.VCode]bool{
|
||||
usermod.UserPaymentStatusPopupNewUnpay: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserPopup: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserFloating: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserPlayPage: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserMeTab: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserVipCardID: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupNewUserCountdown: true,
|
||||
},
|
||||
usermod.UserPaymentStatusPopupUnder7DayUnpay: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPopup: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayFloating: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPlayPage: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayMeTab: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayVipCardID: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayCountdown: true,
|
||||
},
|
||||
usermod.UserPaymentStatusPopupUnder7DayUnpayNoCountdown: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPopupNoCountdown: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayFloatingNoCountdown: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPlayPageNoCountdown: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayMeTabNoCountdown: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayVipCardID: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayCountdown: true,
|
||||
},
|
||||
usermod.UserPaymentStatusPopupOver7DayUnpay: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayPopup: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayFloating: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayPlayPage: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayMeTab: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayVipCardID: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayCountdown: true,
|
||||
},
|
||||
usermod.UserPaymentStatusPopupOver7DayNeedUpgrade: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradePopup: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeFloating: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradePlayPage: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeMeTab: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeVipCardID: true,
|
||||
sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeCountdown: true,
|
||||
},
|
||||
usermod.UserPaymentStatusPopupMaxVIPLevel: {
|
||||
sysconfmod.VCodeUserPaymentStatusPopupMaxVIPLevel: true,
|
||||
},
|
||||
}
|
||||
|
||||
// SysConfUserPaymentStatusPopup 根据用户付费状态分层,返回对应的分层弹窗配置与分层标识。
|
||||
// 结果按分层做 1-3 分钟随机时长的 Redis 缓存。
|
||||
func SysConfUserPaymentStatusPopup(user *usermod.User) (res proto.PaymentStatusPopupConfig, userType string, err error) {
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
userType = user.GetPaymentStatusPopup()
|
||||
userCreateTime := user.CreatedAt
|
||||
vCodes, ok := mapUserPaymentStatusPopup[userType]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// 缓存键使用原始分层标识:有倒计时/无倒计时两个分层的配置项不同,必须分开缓存,
|
||||
// 否则会互相覆盖,导致下发错误的图片源。
|
||||
cacheKey := fmt.Sprintf("%s:%s", redisconst.UserPaymentStatusPopupCache, userType)
|
||||
|
||||
// 读缓存
|
||||
str, err := appg.Redis.Get(cacheKey)
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("获取用户分层弹窗缓存数据异常:%v", err))
|
||||
}
|
||||
if str != nil {
|
||||
if err = msgpack.Unmarshal([]byte(*str), &res); err == nil {
|
||||
// 缓存按分层(userType)共享、不含 uid,图片配置可共享;但 LastDiscountTime
|
||||
// 是 per-user 动态值(依赖当前用户注册时间),必须基于当前用户重算,
|
||||
// 否则会串用到同分层其他用户的时刻。
|
||||
if !res.LastDiscountTime.IsZero() {
|
||||
res.LastDiscountTime = userCreateTime.AddDate(0, 0, countdownDaysOf(userType)).Local()
|
||||
}
|
||||
userType = normalizePaymentStatusPopupType(userType)
|
||||
return
|
||||
}
|
||||
log.Warn(fmt.Sprintf("解析用户分层弹窗缓存数据异常:%v", err))
|
||||
}
|
||||
|
||||
vCodesKey := make([]sysconfmod.VCode, 0, len(vCodes))
|
||||
for vCode := range vCodes {
|
||||
vCodesKey = append(vCodesKey, vCode)
|
||||
}
|
||||
data, err := sysconfmod.BatchGetInfoByVCode(vCodesKey)
|
||||
if err != nil {
|
||||
log.Error("获取用户分层弹窗数据失败!", log.E(err))
|
||||
res = proto.PaymentStatusPopupConfig{} // 兜底:返回空配置
|
||||
} else { // 使用两层 else 是为了让兜底方案也能被缓存,避免故障时每次请求都访问数据库
|
||||
for _, d := range data {
|
||||
switch d.VCode {
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserPopup),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPopup),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPopupNoCountdown),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayPopup),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradePopup):
|
||||
res.Homepage = d.Value
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserFloating),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayFloating),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayFloatingNoCountdown),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayFloating),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeFloating):
|
||||
res.HomepageFlot = d.Value
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserPlayPage),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPlayPage),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayPlayPageNoCountdown),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayPlayPage),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradePlayPage):
|
||||
res.PlayPage = d.Value
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserMeTab),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayMeTab),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayMeTabNoCountdown),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayMeTab),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeMeTab),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupMaxVIPLevel):
|
||||
res.MeTab = d.Value
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserVipCardID),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayVipCardID),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayOver7dayVipCardID),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupPayNeedUpgradeVipCardID):
|
||||
res.VipCard = d.Value
|
||||
case string(sysconfmod.VCodeUserPaymentStatusPopupNewUserCountdown),
|
||||
string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayCountdown):
|
||||
if d.VCode == string(sysconfmod.VCodeUserPaymentStatusPopupNewUserCountdown) && d.Value == "1" {
|
||||
res.LastDiscountTime = userCreateTime.AddDate(0, 0, 1).Local()
|
||||
}
|
||||
if d.VCode == string(sysconfmod.VCodeUserPaymentStatusPopupUnpayUnder7dayCountdown) && d.Value == "1" {
|
||||
res.LastDiscountTime = userCreateTime.AddDate(0, 0, 2).Local()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
common.Go(func() {
|
||||
// 加入缓存,随机 60-180 秒,避免缓存集中失效
|
||||
random := rand.Intn(120) + 60
|
||||
b, mErr := msgpack.Marshal(res)
|
||||
if mErr != nil {
|
||||
return
|
||||
}
|
||||
if sErr := appg.Redis.Set(cacheKey, b, time.Duration(random)*time.Second); sErr != nil {
|
||||
log.Warn(fmt.Sprintf("设置用户分层弹窗缓存数据异常:%v", sErr))
|
||||
}
|
||||
})
|
||||
|
||||
userType = normalizePaymentStatusPopupType(userType)
|
||||
return
|
||||
}
|
||||
|
||||
// normalizePaymentStatusPopupType 统一对外的分层标识:无倒计时仅作内部区分,对外并入 under_7_day_unpay。
|
||||
// 前端通过 LastDiscountTime 是否为零值来判断是否展示倒计时。
|
||||
func normalizePaymentStatusPopupType(userType string) string {
|
||||
if userType == usermod.UserPaymentStatusPopupUnder7DayUnpayNoCountdown {
|
||||
return usermod.UserPaymentStatusPopupUnder7DayUnpay
|
||||
}
|
||||
return userType
|
||||
}
|
||||
|
||||
// countdownDaysOf 返回该分层倒计时天数(用于命中缓存时按当前用户重算 LastDiscountTime):
|
||||
// 新用户 1 天,7天内未付款(含无倒计时变体) 2 天,其余分层无倒计时。
|
||||
// 需与生成路径 AddDate 的天数保持一致。
|
||||
func countdownDaysOf(userType string) int {
|
||||
switch userType {
|
||||
case usermod.UserPaymentStatusPopupNewUnpay:
|
||||
return 1
|
||||
case usermod.UserPaymentStatusPopupUnder7DayUnpay,
|
||||
usermod.UserPaymentStatusPopupUnder7DayUnpayNoCountdown:
|
||||
return 2
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user