120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"soul-api/internal/database"
|
|
"soul-api/internal/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AdminWithdrawalsList GET /api/admin/withdrawals
|
|
func AdminWithdrawalsList(c *gin.Context) {
|
|
statusFilter := c.Query("status")
|
|
var list []model.Withdrawal
|
|
q := database.DB().Order("created_at DESC").Limit(100)
|
|
if statusFilter != "" {
|
|
q = q.Where("status = ?", statusFilter)
|
|
}
|
|
if err := q.Find(&list).Error; err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error(), "withdrawals": []interface{}{}, "stats": gin.H{"total": 0}})
|
|
return
|
|
}
|
|
userIds := make([]string, 0, len(list))
|
|
seen := make(map[string]bool)
|
|
for _, w := range list {
|
|
if !seen[w.UserID] {
|
|
seen[w.UserID] = true
|
|
userIds = append(userIds, w.UserID)
|
|
}
|
|
}
|
|
var users []model.User
|
|
if len(userIds) > 0 {
|
|
database.DB().Where("id IN ?", userIds).Find(&users)
|
|
}
|
|
userMap := make(map[string]*model.User)
|
|
for i := range users {
|
|
userMap[users[i].ID] = &users[i]
|
|
}
|
|
withdrawals := make([]gin.H, 0, len(list))
|
|
for _, w := range list {
|
|
u := userMap[w.UserID]
|
|
userName := "未知用户"
|
|
var userAvatar *string
|
|
account := "未绑定微信号"
|
|
if w.WechatID != nil && *w.WechatID != "" {
|
|
account = *w.WechatID
|
|
}
|
|
if u != nil {
|
|
if u.Nickname != nil {
|
|
userName = *u.Nickname
|
|
}
|
|
userAvatar = u.Avatar
|
|
if u.WechatID != nil && *u.WechatID != "" {
|
|
account = *u.WechatID
|
|
}
|
|
}
|
|
st := "pending"
|
|
if w.Status != nil {
|
|
st = *w.Status
|
|
if st == "success" {
|
|
st = "completed"
|
|
} else if st == "failed" {
|
|
st = "rejected"
|
|
} else if st == "pending_confirm" {
|
|
st = "pending_confirm"
|
|
}
|
|
}
|
|
withdrawals = append(withdrawals, gin.H{
|
|
"id": w.ID, "userId": w.UserID, "userName": userName, "userAvatar": userAvatar,
|
|
"amount": w.Amount, "status": st, "createdAt": w.CreatedAt,
|
|
"method": "wechat", "account": account,
|
|
})
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"success": true, "withdrawals": withdrawals, "stats": gin.H{"total": len(withdrawals)}})
|
|
}
|
|
|
|
// AdminWithdrawalsAction PUT /api/admin/withdrawals 审核/打款
|
|
func AdminWithdrawalsAction(c *gin.Context) {
|
|
var body struct {
|
|
ID string `json:"id"`
|
|
Action string `json:"action"`
|
|
ErrorMessage string `json:"errorMessage"`
|
|
Reason string `json:"reason"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil || body.ID == "" {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 id 或请求体无效"})
|
|
return
|
|
}
|
|
reason := body.ErrorMessage
|
|
if reason == "" {
|
|
reason = body.Reason
|
|
}
|
|
if reason == "" && body.Action == "reject" {
|
|
reason = "管理员拒绝"
|
|
}
|
|
var newStatus string
|
|
switch body.Action {
|
|
case "approve":
|
|
newStatus = "success"
|
|
case "reject":
|
|
newStatus = "failed"
|
|
default:
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "action 须为 approve 或 reject"})
|
|
return
|
|
}
|
|
now := time.Now()
|
|
err := database.DB().Model(&model.Withdrawal{}).Where("id = ?", body.ID).Updates(map[string]interface{}{
|
|
"status": newStatus,
|
|
"error_message": reason,
|
|
"processed_at": now,
|
|
}).Error
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"success": true, "message": "操作成功"})
|
|
}
|