mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-08 18:23:45 +08:00
add redeem code function
This commit is contained in:
@@ -60,13 +60,6 @@ func (h *DashboardHandler) Stats(c *gin.Context) {
|
||||
stats.Tokens += item.Tokens
|
||||
}
|
||||
|
||||
// 众筹收入
|
||||
var rewards []model.Reward
|
||||
res = h.DB.Where("created_at > ?", zeroTime).Find(&rewards)
|
||||
for _, item := range rewards {
|
||||
stats.Income += item.Amount
|
||||
}
|
||||
|
||||
// 订单收入
|
||||
var orders []model.Order
|
||||
res = h.DB.Where("status = ?", types.OrderPaidSuccess).Where("created_at > ?", zeroTime).Find(&orders)
|
||||
@@ -101,13 +94,6 @@ func (h *DashboardHandler) Stats(c *gin.Context) {
|
||||
historyMessagesStatistic[item.CreatedAt.Format("2006-01-02")] += float64(item.Tokens)
|
||||
}
|
||||
|
||||
// 浮点数相加?
|
||||
// 统计最近7天的众筹
|
||||
res = h.DB.Where("created_at > ?", startDate).Find(&rewards)
|
||||
for _, item := range rewards {
|
||||
incomeStatistic[item.CreatedAt.Format("2006-01-02")], _ = decimal.NewFromFloat(incomeStatistic[item.CreatedAt.Format("2006-01-02")]).Add(decimal.NewFromFloat(item.Amount)).Float64()
|
||||
}
|
||||
|
||||
// 统计最近7天的订单
|
||||
res = h.DB.Where("status = ?", types.OrderPaidSuccess).Where("created_at > ?", startDate).Find(&orders)
|
||||
for _, item := range orders {
|
||||
|
||||
164
api/handler/admin/redeem_handler.go
Normal file
164
api/handler/admin/redeem_handler.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package admin
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RedeemHandler struct {
|
||||
handler.BaseHandler
|
||||
}
|
||||
|
||||
func NewRedeemHandler(app *core.AppServer, db *gorm.DB) *RedeemHandler {
|
||||
return &RedeemHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
|
||||
}
|
||||
|
||||
func (h *RedeemHandler) List(c *gin.Context) {
|
||||
page := h.GetInt(c, "page", 1)
|
||||
pageSize := h.GetInt(c, "page_size", 20)
|
||||
code := c.Query("code")
|
||||
status := h.GetInt(c, "status", -1)
|
||||
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
if code != "" {
|
||||
session.Where("code LIKE ?", "%"+code+"%")
|
||||
}
|
||||
if status == 0 {
|
||||
session.Where("redeem_at = ?", 0)
|
||||
} else if status == 1 {
|
||||
session.Where("redeem_at > ?", 0)
|
||||
}
|
||||
|
||||
var total int64
|
||||
session.Model(&model.Redeem{}).Count(&total)
|
||||
var redeems []model.Redeem
|
||||
offset := (page - 1) * pageSize
|
||||
err := session.Order("id DESC").Offset(offset).Limit(pageSize).Find(&redeems).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
var items = make([]vo.Redeem, 0)
|
||||
userIds := make([]uint, 0)
|
||||
for _, v := range redeems {
|
||||
userIds = append(userIds, v.UserId)
|
||||
}
|
||||
var users []model.User
|
||||
h.DB.Where("id IN ?", userIds).Find(&users)
|
||||
var userMap = make(map[uint]model.User)
|
||||
for _, u := range users {
|
||||
userMap[u.Id] = u
|
||||
}
|
||||
|
||||
for _, v := range redeems {
|
||||
var r vo.Redeem
|
||||
err = utils.CopyObject(v, &r)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
r.Id = v.Id
|
||||
r.Username = userMap[v.UserId].Username
|
||||
r.CreatedAt = v.CreatedAt.Unix()
|
||||
items = append(items, r)
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, page, pageSize, items))
|
||||
}
|
||||
|
||||
func (h *RedeemHandler) Create(c *gin.Context) {
|
||||
var data struct {
|
||||
Name string `json:"name"`
|
||||
Power int `json:"power"`
|
||||
Num int `json:"num"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
counter := 0
|
||||
codes := make([]string, 0)
|
||||
var errMsg = ""
|
||||
if data.Num > 0 {
|
||||
for i := 0; i < data.Num; i++ {
|
||||
code, err := utils.GenRedeemCode(32)
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
continue
|
||||
}
|
||||
err = h.DB.Create(&model.Redeem{
|
||||
Code: code,
|
||||
Name: data.Name,
|
||||
Power: data.Power,
|
||||
Enabled: true,
|
||||
}).Error
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
continue
|
||||
}
|
||||
codes = append(codes, code)
|
||||
counter++
|
||||
}
|
||||
}
|
||||
if counter == 0 {
|
||||
resp.ERROR(c, errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, gin.H{
|
||||
"counter": counter,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *RedeemHandler) Set(c *gin.Context) {
|
||||
var data struct {
|
||||
Id uint `json:"id"`
|
||||
Filed string `json:"filed"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.DB.Model(&model.Redeem{}).Where("id = ?", data.Id).Update(data.Filed, data.Value).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
|
||||
func (h *RedeemHandler) Remove(c *gin.Context) {
|
||||
var data struct {
|
||||
Id uint
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
if data.Id > 0 {
|
||||
err := h.DB.Where("id", data.Id).Delete(&model.Redeem{}).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package admin
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RewardHandler struct {
|
||||
handler.BaseHandler
|
||||
}
|
||||
|
||||
func NewRewardHandler(app *core.AppServer, db *gorm.DB) *RewardHandler {
|
||||
return &RewardHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
|
||||
}
|
||||
|
||||
func (h *RewardHandler) List(c *gin.Context) {
|
||||
var items []model.Reward
|
||||
res := h.DB.Order("id DESC").Find(&items)
|
||||
var rewards = make([]vo.Reward, 0)
|
||||
if res.Error == nil {
|
||||
userIds := make([]uint, 0)
|
||||
for _, v := range items {
|
||||
userIds = append(userIds, v.UserId)
|
||||
}
|
||||
var users []model.User
|
||||
h.DB.Where("id IN ?", userIds).Find(&users)
|
||||
var userMap = make(map[uint]model.User)
|
||||
for _, u := range users {
|
||||
userMap[u.Id] = u
|
||||
}
|
||||
|
||||
for _, v := range items {
|
||||
var r vo.Reward
|
||||
err := utils.CopyObject(v, &r)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
r.Id = v.Id
|
||||
r.Username = userMap[v.UserId].Username
|
||||
r.CreatedAt = v.CreatedAt.Unix()
|
||||
r.UpdatedAt = v.UpdatedAt.Unix()
|
||||
rewards = append(rewards, r)
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, rewards)
|
||||
}
|
||||
|
||||
func (h *RewardHandler) Remove(c *gin.Context) {
|
||||
var data struct {
|
||||
Id uint
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
if data.Id > 0 {
|
||||
err := h.DB.Where("id = ?", data.Id).Delete(&model.Reward{}).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func (h *UserHandler) Remove(c *gin.Context) {
|
||||
// 删除算力日志
|
||||
h.DB.Where("user_id = ?", id).Delete(&model.PowerLog{})
|
||||
// 删除众筹日志
|
||||
h.DB.Where("user_id = ?", id).Delete(&model.Reward{})
|
||||
h.DB.Where("user_id = ?", id).Delete(&model.Redeem{})
|
||||
// 删除绘图任务
|
||||
h.DB.Where("user_id = ?", id).Delete(&model.MidJourneyJob{})
|
||||
h.DB.Where("user_id = ?", id).Delete(&model.SdJob{})
|
||||
|
||||
102
api/handler/redeem_handler.go
Normal file
102
api/handler/redeem_handler.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package handler
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"geekai/utils/resp"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RedeemHandler struct {
|
||||
BaseHandler
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func NewRedeemHandler(app *core.AppServer, db *gorm.DB) *RedeemHandler {
|
||||
return &RedeemHandler{BaseHandler: BaseHandler{App: app, DB: db}}
|
||||
}
|
||||
|
||||
func (h *RedeemHandler) Verify(c *gin.Context) {
|
||||
var data struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
userId := h.GetLoginUserId(c)
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
|
||||
var item model.Redeem
|
||||
res := h.DB.Where("code", data.Code).First(&item)
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "无效的兑换码!")
|
||||
return
|
||||
}
|
||||
|
||||
if !item.Enabled {
|
||||
resp.ERROR(c, "当前兑换码已被禁用!")
|
||||
return
|
||||
}
|
||||
|
||||
if item.RedeemedAt > 0 {
|
||||
resp.ERROR(c, "当前兑换码已使用,请勿重复使用!")
|
||||
return
|
||||
}
|
||||
|
||||
tx := h.DB.Begin()
|
||||
err := tx.Model(&model.User{}).Where("id", userId).UpdateColumn("power", gorm.Expr("power + ?", item.Power)).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 更新核销状态
|
||||
item.RedeemedAt = time.Now().Unix()
|
||||
item.UserId = userId
|
||||
err = tx.Updates(&item).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 记录算力充值日志
|
||||
var user model.User
|
||||
err = h.DB.Where("id", userId).First(&user).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.DB.Create(&model.PowerLog{
|
||||
UserId: userId,
|
||||
Username: user.Username,
|
||||
Type: types.PowerReward,
|
||||
Amount: item.Power,
|
||||
Balance: user.Power,
|
||||
Mark: types.PowerAdd,
|
||||
Model: "兑换码",
|
||||
Remark: fmt.Sprintf("兑换码核销,算力:%d,兑换码:%s...", item.Power, item.Code[:10]),
|
||||
CreatedAt: time.Now(),
|
||||
})
|
||||
tx.Commit()
|
||||
resp.SUCCESS(c)
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package handler
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RewardHandler struct {
|
||||
BaseHandler
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func NewRewardHandler(app *core.AppServer, db *gorm.DB) *RewardHandler {
|
||||
return &RewardHandler{BaseHandler: BaseHandler{App: app, DB: db}}
|
||||
}
|
||||
|
||||
// Verify 打赏码核销
|
||||
func (h *RewardHandler) Verify(c *gin.Context) {
|
||||
var data struct {
|
||||
TxId string `json:"tx_id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.GetLoginUser(c)
|
||||
if err != nil {
|
||||
resp.HACKER(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 移除转账单号中间的空格,防止有人复制的时候多复制了空格
|
||||
data.TxId = strings.ReplaceAll(data.TxId, " ", "")
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
|
||||
var item model.Reward
|
||||
res := h.DB.Where("tx_id = ?", data.TxId).First(&item)
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "无效的众筹交易流水号!")
|
||||
return
|
||||
}
|
||||
|
||||
if item.Status {
|
||||
resp.ERROR(c, "当前众筹交易流水号已经被核销,请不要重复核销!")
|
||||
return
|
||||
}
|
||||
|
||||
tx := h.DB.Begin()
|
||||
exchange := vo.RewardExchange{}
|
||||
power := math.Ceil(item.Amount / h.App.SysConfig.PowerPrice)
|
||||
exchange.Power = int(power)
|
||||
err = tx.Model(&user).UpdateColumn("power", gorm.Expr("power + ?", exchange.Power)).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 更新核销状态
|
||||
item.Status = true
|
||||
item.UserId = user.Id
|
||||
item.Exchange = utils.JsonEncode(exchange)
|
||||
err = tx.Updates(&item).Error
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 记录算力充值日志
|
||||
h.DB.Create(&model.PowerLog{
|
||||
UserId: user.Id,
|
||||
Username: user.Username,
|
||||
Type: types.PowerReward,
|
||||
Amount: exchange.Power,
|
||||
Balance: user.Power + exchange.Power,
|
||||
Mark: types.PowerAdd,
|
||||
Model: "众筹支付",
|
||||
Remark: fmt.Sprintf("众筹充值算力,金额:%f,价格:%f", item.Amount, h.App.SysConfig.PowerPrice),
|
||||
CreatedAt: time.Now(),
|
||||
})
|
||||
tx.Commit()
|
||||
resp.SUCCESS(c)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user