refactor: update match configuration and user matching logic
- Changed the daily free match limit to a lifetime limit, aligning with backend configurations. - Updated the match price display to include original pricing for better user clarity. - Refactored match quota handling to sync with the server, ensuring accurate match counts and purchase statuses. - Enhanced UI messages to reflect changes in match availability and pricing. - Removed deprecated logic related to daily match counts, streamlining the matching process.
This commit is contained in:
@@ -14,18 +14,30 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const defaultFreeMatchLimit = 3
|
||||
const defaultFreeMatchLimit = 1
|
||||
|
||||
const completeProfileSQL = "((phone IS NOT NULL AND phone != '') AND (nickname IS NOT NULL AND nickname != '' AND nickname != '微信用户') AND (avatar IS NOT NULL AND avatar != ''))"
|
||||
|
||||
// MatchQuota 匹配次数配额(纯计算:订单 + match_records)
|
||||
// 免费次数为「终身」额度,不按自然日重置;RemainToday JSON 字段名历史遗留,语义为「当前剩余可匹配次数」。
|
||||
type MatchQuota struct {
|
||||
PurchasedTotal int64 `json:"purchasedTotal"`
|
||||
PurchasedUsed int64 `json:"purchasedUsed"`
|
||||
MatchesUsedToday int64 `json:"matchesUsedToday"`
|
||||
FreeRemainToday int64 `json:"freeRemainToday"`
|
||||
MatchesUsedToday int64 `json:"matchesUsedToday"` // 今日已匹配次数(统计用)
|
||||
FreeRemainToday int64 `json:"freeRemainToday"` // 终身免费剩余次数(字段名保留)
|
||||
PurchasedRemain int64 `json:"purchasedRemain"`
|
||||
RemainToday int64 `json:"remainToday"` // 今日剩余可匹配次数
|
||||
RemainToday int64 `json:"remainToday"` // 当前剩余可匹配次数(免费剩余 + 已购剩余)
|
||||
}
|
||||
|
||||
// normalizeFreeMatchLimit 产品规则:终身免费匹配仅 1 次(不按日重置);配置大于 1 时按 1 生效
|
||||
func normalizeFreeMatchLimit(n int) int {
|
||||
if n <= 0 {
|
||||
return defaultFreeMatchLimit
|
||||
}
|
||||
if n > 1 {
|
||||
return 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func getFreeMatchLimit(db *gorm.DB) int {
|
||||
@@ -38,35 +50,31 @@ func getFreeMatchLimit(db *gorm.DB) int {
|
||||
return defaultFreeMatchLimit
|
||||
}
|
||||
if v, ok := config["freeMatchLimit"].(float64); ok && v > 0 {
|
||||
return int(v)
|
||||
return normalizeFreeMatchLimit(int(v))
|
||||
}
|
||||
return defaultFreeMatchLimit
|
||||
}
|
||||
|
||||
// GetMatchQuota 根据订单和 match_records 纯计算用户匹配配额
|
||||
// GetMatchQuota 根据订单和 match_records 纯计算用户匹配配额(免费次数为终身额度,不按日重置)
|
||||
func GetMatchQuota(db *gorm.DB, userID string, freeLimit int) MatchQuota {
|
||||
if freeLimit <= 0 {
|
||||
freeLimit = defaultFreeMatchLimit
|
||||
}
|
||||
freeLimit = normalizeFreeMatchLimit(freeLimit)
|
||||
var purchasedTotal int64
|
||||
db.Model(&model.Order{}).Where("user_id = ? AND product_type = ? AND status = ?", userID, "match", "paid").Count(&purchasedTotal)
|
||||
var matchesToday int64
|
||||
db.Model(&model.MatchRecord{}).Where("user_id = ? AND created_at >= CURDATE()", userID).Count(&matchesToday)
|
||||
// 历史每日超出免费部分之和 = 已消耗的购买次数
|
||||
var purchasedUsed int64
|
||||
db.Raw(`
|
||||
SELECT COALESCE(SUM(cnt - ?), 0) FROM (
|
||||
SELECT DATE(created_at) AS d, COUNT(*) AS cnt
|
||||
FROM match_records WHERE user_id = ?
|
||||
GROUP BY DATE(created_at)
|
||||
HAVING cnt > ?
|
||||
) t
|
||||
`, freeLimit, userID, freeLimit).Scan(&purchasedUsed)
|
||||
freeUsed := matchesToday
|
||||
if freeUsed > int64(freeLimit) {
|
||||
freeUsed = int64(freeLimit)
|
||||
var lifetimeMatches int64
|
||||
db.Model(&model.MatchRecord{}).Where("user_id = ?", userID).Count(&lifetimeMatches)
|
||||
|
||||
fl := int64(freeLimit)
|
||||
beyondFree := lifetimeMatches - fl
|
||||
if beyondFree < 0 {
|
||||
beyondFree = 0
|
||||
}
|
||||
freeRemain := int64(freeLimit) - freeUsed
|
||||
purchasedUsed := beyondFree
|
||||
if purchasedUsed > purchasedTotal {
|
||||
purchasedUsed = purchasedTotal
|
||||
}
|
||||
freeRemain := fl - lifetimeMatches
|
||||
if freeRemain < 0 {
|
||||
freeRemain = 0
|
||||
}
|
||||
@@ -74,14 +82,17 @@ func GetMatchQuota(db *gorm.DB, userID string, freeLimit int) MatchQuota {
|
||||
if purchasedRemain < 0 {
|
||||
purchasedRemain = 0
|
||||
}
|
||||
remainToday := freeRemain + purchasedRemain
|
||||
remainTotal := freeRemain + purchasedRemain
|
||||
if remainTotal < 0 {
|
||||
remainTotal = 0
|
||||
}
|
||||
return MatchQuota{
|
||||
PurchasedTotal: purchasedTotal,
|
||||
PurchasedUsed: purchasedUsed,
|
||||
MatchesUsedToday: matchesToday,
|
||||
FreeRemainToday: freeRemain,
|
||||
PurchasedRemain: purchasedRemain,
|
||||
RemainToday: remainToday,
|
||||
RemainToday: remainTotal,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,10 +111,11 @@ func MatchConfigGet(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": gin.H{
|
||||
"matchTypes": defaultMatchTypes,
|
||||
"freeMatchLimit": 3,
|
||||
"matchPrice": 1,
|
||||
"settings": gin.H{"enableFreeMatches": true, "enablePaidMatches": true, "maxMatchesPerDay": 10},
|
||||
"matchTypes": defaultMatchTypes,
|
||||
"freeMatchLimit": 1,
|
||||
"matchPrice": 1,
|
||||
"matchPriceOriginal": 9.9,
|
||||
"settings": gin.H{"enableFreeMatches": true, "enablePaidMatches": true, "maxMatchesPerDay": 10},
|
||||
},
|
||||
"source": "default",
|
||||
})
|
||||
@@ -129,14 +141,18 @@ func MatchConfigGet(c *gin.Context) {
|
||||
matchTypes = defaultMatchTypes
|
||||
}
|
||||
}
|
||||
freeMatchLimit := 3
|
||||
if v, ok := config["freeMatchLimit"].(float64); ok {
|
||||
freeMatchLimit = int(v)
|
||||
freeMatchLimit := defaultFreeMatchLimit
|
||||
if v, ok := config["freeMatchLimit"].(float64); ok && int(v) > 0 {
|
||||
freeMatchLimit = normalizeFreeMatchLimit(int(v))
|
||||
}
|
||||
matchPrice := 1
|
||||
if v, ok := config["matchPrice"].(float64); ok {
|
||||
matchPrice = int(v)
|
||||
}
|
||||
matchPriceOriginal := 9.9
|
||||
if v, ok := config["matchPriceOriginal"].(float64); ok && v > 0 {
|
||||
matchPriceOriginal = v
|
||||
}
|
||||
settings := gin.H{"enableFreeMatches": true, "enablePaidMatches": true, "maxMatchesPerDay": 10}
|
||||
if s, ok := config["settings"].(map[string]interface{}); ok {
|
||||
for k, v := range s {
|
||||
@@ -144,7 +160,11 @@ func MatchConfigGet(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": gin.H{
|
||||
"matchTypes": matchTypes, "freeMatchLimit": freeMatchLimit, "matchPrice": matchPrice, "settings": settings,
|
||||
"matchTypes": matchTypes,
|
||||
"freeMatchLimit": freeMatchLimit,
|
||||
"matchPrice": matchPrice,
|
||||
"matchPriceOriginal": matchPriceOriginal,
|
||||
"settings": settings,
|
||||
}, "source": "database"})
|
||||
}
|
||||
|
||||
@@ -188,7 +208,7 @@ func MatchUsers(c *gin.Context) {
|
||||
if quota.RemainToday <= 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "今日匹配次数已用完,请购买更多次数",
|
||||
"message": "免费次数已用完,请购买匹配次数后再试",
|
||||
"code": "QUOTA_EXCEEDED",
|
||||
})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user