Files
bl/modules/player/service/pet.go
昔念 5657f1e673
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
fix(pet): 修复宠物数量检查逻辑错误

当free参数为2时,应该查询free字段值为2的记录数量,
而不是查询free字段值为1的记录数量,确保精灵数量限制检查正确。
```
2026-03-19 22:25:10 +08:00

341 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"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) bool {
res, _ := s.dbm(s.Model).Where("catch_time", ctime).Data(
"free", free,
).Update()
r, _ := res.RowsAffected()
return r > 0
}
func (s *PetService) UPdatePrice(ctime uint32, Price uint32, free uint32) error {
var item1 model.Pet
var feeRate float64
var err1 error
if free == 2 {
t, _ := s.dbm(s.Model).Where("free", 2).Count()
if t > 3 {
return fmt.Errorf("精灵数量已满")
}
} else {
s.dbm(s.Model).Where("catch_time", ctime).Scan(&item1)
_, feeRate, err1 = item1.GetOffShelfFee()
if err1 != nil {
return err1
}
}
res, _ := s.dbm(s.Model).
Where("catch_time", ctime). // 限定 ctime避免全表更新
//Where("sale_price = ?", 0). // 只筛选 sale_price=0 的记录
Data(g.Map{
"sale_price": Price,
"free": free,
}).Update()
g, _ := res.RowsAffected()
if g > 0 && free != 2 && feeRate != 0 {
amount1 := item1.CalculateOffShelfAmount(feeRate)
service.NewBaseSysUserService().UpdateFreeGold(s.userid, -int64(amount1*100))
}
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.Free != 2 {
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.Data.OldCatchTime = 0
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) error {
m := s.dbm(s.Model).Where("catch_time", t.CatchTime)
var tt *model.Pet
m.Scan(&tt)
if tt == nil {
return fmt.Errorf("没有此精灵")
}
tt.Data = t
_, err := m.OnConflict("catch_time").Update(tt)
if err != nil {
return err
}
return nil
}
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{
AddOrderby: g.MapStrStr{"updateTime": "asc"},
FieldEQ: []string{"player_id", "free"},
Where: func(ctx context.Context) [][]interface{} {
return [][]interface{}{
{"free", 0, false},
{"is_vip", 0, true},
}
},
},
PageQueryOp: &cool.QueryOp{
FieldEQ: []string{"player_id", "free"},
Where: func(ctx context.Context) [][]interface{} {
// var (
// admin = cool.GetAdmin(ctx)
// // userId = admin.UserId
// )
return [][]interface{}{
// {"player_id", userId, true},
{"free", 0, false},
{"is_vip", 0, true},
}
},
},
},
},
}
}