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": "操作成功"}) }