Files
soul-yongping/soul-api/internal/handler/vip.go

190 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"net/http"
"time"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// VipStatus GET /api/miniprogram/vip/status 小程序-查询用户 VIP 状态
func VipStatus(c *gin.Context) {
userID := c.Query("userId")
if userID == "" {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 userId"})
return
}
db := database.DB()
// 查是否有 fullbook 或 vip 的已支付订单
var order model.Order
err := db.Where("user_id = ? AND status = ? AND (product_type = ? OR product_type = ?)",
userID, "paid", "fullbook", "vip").
Order("pay_time DESC").First(&order).Error
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"isVip": false,
"daysRemaining": 0,
"expireDate": "",
"price": float64(1980),
},
})
return
}
expireDate := time.Now().AddDate(0, 0, 365)
daysRemaining := 365
if order.PayTime != nil {
expireDate = order.PayTime.AddDate(0, 0, 365)
if expireDate.After(time.Now()) {
daysRemaining = int(expireDate.Sub(time.Now()).Hours() / 24)
} else {
daysRemaining = 0
}
}
expStr := expireDate.Format("2006-01-02")
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"isVip": true,
"daysRemaining": daysRemaining,
"expireDate": expStr,
"price": float64(1980),
},
})
}
// VipProfileGet GET /api/miniprogram/vip/profile 小程序-获取 VIP 资料
func VipProfileGet(c *gin.Context) {
userID := c.Query("userId")
if userID == "" {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 userId"})
return
}
db := database.DB()
var user model.User
if err := db.Where("id = ?", userID).First(&user).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": true, "data": gin.H{"name": "", "project": "", "contact": "", "bio": ""}})
return
}
name := ""
if user.Nickname != nil {
name = *user.Nickname
}
contact := ""
if user.Phone != nil {
contact = *user.Phone
}
if user.WechatID != nil && contact == "" {
contact = *user.WechatID
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"name": name,
"project": "",
"contact": contact,
"bio": "",
},
})
}
// VipProfilePost POST /api/miniprogram/vip/profile 小程序-更新 VIP 资料
func VipProfilePost(c *gin.Context) {
var req struct {
UserID string `json:"userId" binding:"required"`
Name string `json:"name"`
Project string `json:"project"`
Contact string `json:"contact"`
Bio string `json:"bio"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "请求体无效"})
return
}
db := database.DB()
updates := map[string]interface{}{}
if req.Name != "" {
updates["nickname"] = req.Name
}
if req.Contact != "" {
updates["phone"] = req.Contact
}
if len(updates) > 0 {
db.Model(&model.User{}).Where("id = ?", req.UserID).Updates(updates)
}
c.JSON(http.StatusOK, gin.H{"success": true})
}
// VipMembers GET /api/miniprogram/vip/members 小程序-VIP 会员列表(无 id 返回列表;有 id 返回单个)
func VipMembers(c *gin.Context) {
id := c.Query("id")
db := database.DB()
// 有 id 时查单个:优先从已购 fullbook/vip 的用户中找
if id != "" {
var user model.User
if err := db.Where("id = ?", id).First(&user).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": true, "data": nil})
return
}
// 检查是否 VIP有 fullbook 或 vip 订单)
var cnt int64
db.Model(&model.Order{}).Where("user_id = ? AND status = ? AND (product_type = ? OR product_type = ?)",
id, "paid", "fullbook", "vip").Count(&cnt)
item := formatVipMember(&user, cnt > 0)
c.JSON(http.StatusOK, gin.H{"success": true, "data": item})
return
}
// 无 id返回 VIP 会员列表(有 fullbook 或 vip 订单的用户)
var userIDs []string
db.Model(&model.Order{}).Select("DISTINCT user_id").
Where("status = ? AND (product_type = ? OR product_type = ?)", "paid", "fullbook", "vip").
Pluck("user_id", &userIDs)
if len(userIDs) == 0 {
c.JSON(http.StatusOK, gin.H{"success": true, "data": []interface{}{}})
return
}
var users []model.User
db.Where("id IN ?", userIDs).Find(&users)
list := make([]gin.H, 0, len(users))
for i := range users {
list = append(list, formatVipMember(&users[i], true))
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": list})
}
func formatVipMember(u *model.User, isVip bool) gin.H {
name := ""
if u.Nickname != nil {
name = *u.Nickname
}
avatar := ""
if u.Avatar != nil {
avatar = *u.Avatar
}
contact := ""
if u.Phone != nil {
contact = *u.Phone
}
if u.WechatID != nil && contact == "" {
contact = *u.WechatID
}
return gin.H{
"id": u.ID,
"nickname": name,
"avatar": avatar,
"vip_name": name,
"vip_avatar": avatar,
"vip_contact": contact,
"is_vip": isVip,
}
}