package service import ( "blazing/common/utils" "blazing/cool" basemodel "blazing/modules/base/model" "blazing/modules/base/service" "blazing/modules/player/model" "context" "fmt" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" ) // 获取精灵信息 0是仓库,1是放生 func (s *PetService) PetInfo(flag int) []model.Pet { var tt []model.Pet err := s.dbm(s.Model).Where("free", flag).Scan(&tt) if err != nil { return []model.Pet{} } for i := 0; i < len(tt); i++ { tt[i].Data.CatchTime = tt[i].CatchTime } return tt } func (s *PetService) PetCount(flag int) int { ret, err := s.dbm(s.Model).Where("free", flag).Count() if err != nil { return 0 } return ret } func (s *PetService) UPdateFree(ctime uint32, free uint32) { s.dbm(s.Model).Where("catch_time", ctime).Data( "free", free, ).Update() } func (s *PetService) UPdatePrice(ctime uint32, Price uint32, is_sale uint32) error { if is_sale == 1 { t, _ := s.dbm(s.Model).Where("is_sale", 1).Count() if t > 3 { return fmt.Errorf("精灵数量已满") } } var p model.Pet s.dbm(s.Model).Where("catch_time", ctime).Scan(&p) if p.SalePrice != 0 && p.SalePrice != Price && utils.IsToday(p.UpdateTime) { //说明要修改价格 return fmt.Errorf("一天只允许改价一次") } res0, err := s.dbm(s.Model). Where("catch_time", ctime). // 限定 ctime,避免全表更新 Where("sale_price = ?", 0). // 只筛选 sale_price=0 的记录 Data(g.Map{ "sale_price": Price, "is_sale": is_sale, }).Update() if err != nil { return fmt.Errorf("修改 sale_price=0 的记录失败:%w", err) } affected0, _ := res0.RowsAffected() if affected0 == 0 { priceUpper := Price * 110 / 100 // 上限 = Price * 1.1(整数运算避免浮点误差) priceLower := Price * 90 / 100 // 下限 = Price * 0.9 res, _ := s.dbm(s.Model).Where("catch_time", ctime).WhereBetween("sale_price", priceLower, priceUpper).Data("sale_price", Price, "is_sale", is_sale).Update() t, _ := res.RowsAffected() if t < 0 { return fmt.Errorf("修改失败") } } return nil } func (s *PetService) BuyPet(pid uint32) error { tt := NewPetService(0).PetInfo_One_ID(pid) if tt == nil { return fmt.Errorf("没有此精灵") } if tt.IsVip != 0 { return fmt.Errorf("不允许交易") } if tt.IsSale == 0 { return fmt.Errorf("未上架") } if tt.Free == 0 { return fmt.Errorf("没有此精灵") } if tt.SalePrice == 0 { return fmt.Errorf("未设置价格") } if !tt.UpdateTime.AddDate(0, 0, 1).Before(gtime.Now()) { return fmt.Errorf("数据异常") } return g.DB().Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error { useglod := int64(tt.SalePrice)*102 + int64(tt.SaleCount)*5 var res1 basemodel.BaseSysUser err := tx.Model(basemodel.BaseSysUser{}).Where("id", s.userid).Fields("free_gold").Scan(&res1) if err != nil { return err } if res1.FreeGold < useglod { return fmt.Errorf("余额不足") } _, err = tx.Model(basemodel.BaseSysUser{}).Where("id", s.userid).Increment("free_gold", -useglod) if err != nil { return err } res, err := tx.Model(s.Model).Where("id", tt.ID).Delete() if err != nil { return err } cd, _ := res.RowsAffected() if cd == 0 { return fmt.Errorf("重复订单") } _, err = tx.Model(basemodel.BaseSysUser{}).Where("id", tt.PlayerID).Increment("free_gold", int64(tt.SalePrice)*98) if err != nil { return err } sql := fmt.Sprintf(` UPDATE %s SET max_ts = CASE WHEN max_ts < EXTRACT(EPOCH FROM NOW())::INT THEN EXTRACT(EPOCH FROM NOW())::INT ELSE max_ts + 1 END WHERE id = ? AND deleted_at IS NULL RETURNING max_ts; `, service.NewBaseSysUserService().Model.TableName()) // 执行 Raw SQL 并扫描返回值 ret, err := tx.Model(service.NewBaseSysUserService().Model).Raw(sql, s.userid).All() if err != nil { return err } //fmt.Println(ret, err) tt.CatchTime = ret.Array()[0].Uint32() var player model.Pet player.PlayerID = s.userid player.Data = tt.Data player.CatchTime = tt.CatchTime player.Free = 0 player.SalePrice = tt.SalePrice player.SaleCount = tt.SaleCount + 1 player.IsVip = cool.Config.ServerInfo.IsVip _, err = tx.Model(s.Model).Insert(player) if err != nil { return err } return nil }) } func (s *PetService) UPdate(t model.PetInfo) { m := s.dbm(s.Model).Where("catch_time", t.CatchTime) var tt *model.Pet m.Scan(&tt) if tt == nil { return } tt.Data = t _, err := m.OnConflict("catch_time").Update(tt) if err != nil { panic(err) } } func (s *PetService) PetInfo_One(cachetime uint32) *model.Pet { m := s.dbm(s.Model).Where("catch_time", cachetime) var tt *model.Pet m.Scan(&tt) if tt == nil { return nil } tt.Data.CatchTime = tt.CatchTime return tt } func (s *PetService) PetInfo_One_ID(Pid uint32) *model.Pet { m := s.dbm(s.Model).Where("id", Pid) var tt *model.Pet m.Scan(&tt) if tt == nil { return nil } tt.Data.CatchTime = tt.CatchTime return tt } func (s *PetService) PetInfo_One_ohter(userid, cachetime uint32) model.Pet { m := s.dbm(s.Model).Where("catch_time", cachetime) var tt model.Pet m.Scan(&tt) tt.Data.CatchTime = tt.CatchTime return tt } func (s *PetService) PetInfo_One_Unscoped(cachetime uint32) *model.Pet { m := s.dbm(s.Model).Where("catch_time", cachetime).Unscoped() var tt *model.Pet m.Scan(&tt) if tt == nil { return nil } tt.Data.CatchTime = tt.CatchTime return tt } func (s *PetService) Pet_del(cachetime uint32) { s.dbm(s.Model).Where("catch_time", cachetime).Delete() } func (s *PetService) Pet_LEVEL_all() []model.Pet { var tt []model.Pet s.dbm(s.Model).As("pp").Wheref(`(pp.data->>'Level')::INT > 100`).OrderDesc("(pp.data->>'Level')::INT").Scan(&tt) return tt } // 精灵真正添加后的捕捉时间才是真正的时间 func (s *PetService) PetAdd(y *model.PetInfo, salecount uint32) uint32 { if y == nil { return 0 } sql := fmt.Sprintf(` UPDATE %s SET max_ts = CASE WHEN max_ts < EXTRACT(EPOCH FROM NOW())::INT THEN EXTRACT(EPOCH FROM NOW())::INT ELSE max_ts + 1 END WHERE id = ? AND deleted_at IS NULL RETURNING max_ts; `, service.NewBaseSysUserService().Model.TableName()) // 执行 Raw SQL 并扫描返回值 ret, _ := cool.DBM(service.NewBaseSysUserService().Model).Raw(sql, s.userid).All() //fmt.Println(ret, err) y.CatchTime = ret.Array()[0].Uint32() m1 := cool.DBM(s.Model).Where("player_id", s.userid) var player model.Pet player.PlayerID = s.userid player.Data = *y player.CatchTime = y.CatchTime player.Free = 0 player.SaleCount = salecount player.IsVip = cool.Config.ServerInfo.IsVip _, err := m1.Insert(player) if err != nil { panic(err) } return y.CatchTime } // func (s *PetService) ModifyBefore(ctx context.Context, method string, param map[string]interface{}) (err error) { // admin := cool.GetAdmin(ctx) // userId := admin.UserId // s.userid = uint32(userId) // // if method == "Update" { // // if gconv.Uint(param["free"]) != 0 { // // err = fmt.Errorf("修改失败") // // } // // if userId != gconv.Uint(param["player_id"]) { // // err = fmt.Errorf("修改失败") // // } // // } // return // } type PetService struct { BaseService } func NewPetService(userid uint32) *PetService { return &PetService{ BaseService: BaseService{ userid: userid, Service: &cool.Service{ Model: model.NewPet(), ListQueryOp: &cool.QueryOp{ FieldEQ: []string{"player_id", "free", "is_sale"}, Where: func(ctx context.Context) [][]interface{} { return [][]interface{}{ // {"player_id", userId, true}, {"free", 1, true}, {"is_vip", 0, true}, } }, }, PageQueryOp: &cool.QueryOp{ FieldEQ: []string{"player_id", "free", "is_sale"}, Where: func(ctx context.Context) [][]interface{} { // var ( // admin = cool.GetAdmin(ctx) // // userId = admin.UserId // ) return [][]interface{}{ // {"player_id", userId, true}, {"free", 1, true}, {"is_vip", 0, true}, } }, }, }, }, } }