From 808da76bd020e3cc2093e250400c3206d951790d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 21 Apr 2026 01:56:06 +0800 Subject: [PATCH] 1 --- modules/player/controller/admin/gold_list.go | 19 +-- modules/player/service/gold_list.go | 138 ++++++++++++++++++- 2 files changed, 132 insertions(+), 25 deletions(-) diff --git a/modules/player/controller/admin/gold_list.go b/modules/player/controller/admin/gold_list.go index 709d2546..b272fca2 100644 --- a/modules/player/controller/admin/gold_list.go +++ b/modules/player/controller/admin/gold_list.go @@ -2,14 +2,10 @@ package admin import ( "blazing/cool" - base "blazing/modules/base/service" "blazing/modules/player/service" "context" - "fmt" - "time" "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" ) type GoldListController struct { @@ -38,23 +34,10 @@ type DuihuanGoldAddReq struct { func (c *GoldListController) DuihuanGold(ctx context.Context, req *DuihuanGoldAddReq) (res *cool.BaseRes, err error) { t := cool.GetAdmin(ctx) - r, err := service.NewGoldListService(0).Done(req.ID) + _, err = service.NewGoldListService(0).Trade(ctx, req.ID, t.UserId) if err != nil { return } - - costfree := r.Rate * float64(r.ExchangeNum) - - if base.NewBaseSysUserService().GetFreeGold(t.UserId) < int64(costfree*100) { - err = fmt.Errorf("余额不足") - return - } - if !r.UpdateTime.Add(1 * time.Hour).Before(gtime.Now()) { - err = fmt.Errorf("未到购买时间") - return - } - base.NewBaseSysUserService().DuihuanFreeGold(uint32(r.PlayerID), int64(r.ExchangeNum*100), int64(costfree*95)) - base.NewBaseSysUserService().DuihuanGold(uint32(t.UserId), int64(r.ExchangeNum*95), int64(costfree*100)) res = cool.Ok(nil) return } diff --git a/modules/player/service/gold_list.go b/modules/player/service/gold_list.go index 5f4e06c8..0b1a5245 100644 --- a/modules/player/service/gold_list.go +++ b/modules/player/service/gold_list.go @@ -2,20 +2,48 @@ package service import ( "blazing/cool" + basemodel "blazing/modules/base/model" "blazing/modules/base/service" "blazing/modules/player/model" "context" "fmt" + "math" + "time" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" - "github.com/gogf/gf/v2/util/grand" ) type GoldListService struct { BaseService } +func (s *GoldListService) getPrevDayAvgRate() float64 { + var ( + now = gtime.Now() + yesterday = now.AddDate(0, 0, -1) + dayStart = gtime.NewFromStr(yesterday.Format("Y-m-d") + " 00:00:00") + nextDay = dayStart.AddDate(0, 0, 1) + result struct { + AvgRate float64 `json:"avg_rate"` + } + ) + + err := s.dbm_fix(s.Model). + Fields("COALESCE(AVG(rate), 0) AS avg_rate"). + Where("status", 1). + WhereGTE("createTime", dayStart). + WhereLT("createTime", nextDay). + Scan(&result) + if err != nil || result.AvgRate <= 0 { + return 1 + } + + return result.AvgRate +} + func (s *GoldListService) ModifyBefore(ctx context.Context, method string, param map[string]interface{}) (err error) { admin := cool.GetAdmin(ctx) userId := admin.UserId @@ -29,14 +57,16 @@ func (s *GoldListService) ModifyBefore(ctx context.Context, method string, param if t > 0 { return fmt.Errorf("不允许多挂单") } - if gconv.Float64(param["rate"]) > 2 { - r := g.List{} - for i := 0; i < grand.N(1, 3); i++ { - r = append(r, g.Map{"rate": param["rate"], "exchange_num": param["exchange_num"], "player_id": 10001}) - } - s.dbm_fix(s.Model).Data(r).Insert() + var ( + rate = gconv.Float64(param["rate"]) + prevAvg = s.getPrevDayAvgRate() + minRate = math.Round(prevAvg*0.9*10000) / 10000 + maxRate = math.Round(prevAvg*1.1*10000) / 10000 + ) + if rate < minRate || rate > maxRate { + return fmt.Errorf("当前价格涨跌幅超限,需在昨日均价 %.4f 的上下10%%范围内(%.4f - %.4f)", prevAvg, minRate, maxRate) } } else { var items []model.GoldBeanOrder @@ -70,6 +100,100 @@ func (s *GoldListService) Done(listid uint32) (*model.GoldBeanOrder, error) { } return &rr, nil } + +func (s *GoldListService) Trade(ctx context.Context, listid uint32, buyerID uint32) (*model.GoldBeanOrder, error) { + var result *model.GoldBeanOrder + + err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + var ( + order model.GoldBeanOrder + buyer basemodel.BaseSysUser + seller basemodel.BaseSysUser + ) + + if err := tx.Model(s.Model).Where("id", listid).Where("status", 0).Scan(&order); err != nil { + return err + } + if order.ID == 0 { + return fmt.Errorf("重复订单") + } + + if !order.UpdateTime.Add(1 * time.Hour).Before(gtime.Now()) { + return fmt.Errorf("未到购买时间") + } + + costFree := int64(math.Round(order.Rate * float64(order.ExchangeNum) * 100)) + sellerGold := int64(order.ExchangeNum) * 100 + sellerIncome := int64(math.Round(order.Rate * float64(order.ExchangeNum) * 95)) + buyerGold := int64(order.ExchangeNum * 95) + + if err := tx.Model(basemodel.BaseSysUser{}).Where("id", buyerID).Fields("free_gold").Scan(&buyer); err != nil { + return err + } + if buyer.FreeGold < costFree { + return fmt.Errorf("余额不足") + } + + if err := tx.Model(basemodel.BaseSysUser{}).Where("id", order.PlayerID).Fields("goldbean").Scan(&seller); err != nil { + return err + } + if seller.GoldBean < sellerGold { + return fmt.Errorf("卖家余额不足") + } + + res, err := tx.Model(basemodel.BaseSysUser{}). + Where("id", buyerID). + WhereGTE("free_gold", costFree). + Increment("free_gold", -costFree) + if err != nil { + return err + } + rows, _ := res.RowsAffected() + if rows == 0 { + return fmt.Errorf("余额不足") + } + + res, err = tx.Model(basemodel.BaseSysUser{}). + Where("id", order.PlayerID). + WhereGTE("goldbean", sellerGold). + Increment("goldbean", -sellerGold) + if err != nil { + return err + } + rows, _ = res.RowsAffected() + if rows == 0 { + return fmt.Errorf("卖家余额不足") + } + + if _, err = tx.Model(basemodel.BaseSysUser{}).Where("id", order.PlayerID).Increment("free_gold", sellerIncome); err != nil { + return err + } + if _, err = tx.Model(basemodel.BaseSysUser{}).Where("id", buyerID).Increment("goldbean", buyerGold); err != nil { + return err + } + + res, err = tx.Model(s.Model). + Data("status", 1). + Where("id", listid). + Where("status", 0). + Update() + if err != nil { + return err + } + rows, _ = res.RowsAffected() + if rows == 0 { + return fmt.Errorf("重复订单") + } + + result = &order + return nil + }) + if err != nil { + return nil, err + } + + return result, nil +} func (s *GoldListService) Get() []model.GoldBeanOrder { var rr []model.GoldBeanOrder s.dbm_fix(s.Model).Where("status", 0).Order("rate", "asc").Scan(&rr)