feat: 积分质押功能

This commit is contained in:
2025-04-03 16:17:20 +08:00
parent 229f1d181b
commit 8119bcefdc
40 changed files with 2552 additions and 108 deletions

View File

@@ -13,10 +13,11 @@ import (
type Config struct {
rest.RestConf
MySql MySqlConf
Redis redis.RedisConf
Cache cache.CacheConf
Auth struct {
MySql MySqlConf
GameDB MySqlConf
Redis redis.RedisConf
Cache cache.CacheConf
Auth struct {
AccessSecret string
AccessExpire time.Duration `json:",default=168h"`
}
@@ -34,6 +35,7 @@ type Config struct {
PrivateKey string
IsTest bool `json:",default=false"`
} `json:",optional"`
NovaToken string `json:",default=JInj73uK5gK5BG7I53h5PaEJH41tWwBT"`
}
type Cron struct {

View File

@@ -0,0 +1,6 @@
package consts
const (
GameActionGetHomePointsState = "getStakeHomePointsState"
GameActionStakePoints = "stakeHomePoints"
)

View File

@@ -0,0 +1,30 @@
package admin
import (
"net/http"
"nova_task/internal/pkg/errs"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/admin"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// GameAction
func GameActionHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GameActionReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := admin.NewGameActionLogic(r.Context(), svcCtx)
resp, err := l.GameAction(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
errs.WriteHttpResponse(r.Context(), w, resp)
}
}
}

View File

@@ -10,6 +10,7 @@ import (
carv "nova_task/internal/handler/carv"
game7 "nova_task/internal/handler/game7"
kgen "nova_task/internal/handler/kgen"
stakepoint "nova_task/internal/handler/stakepoint"
task "nova_task/internal/handler/task"
"nova_task/internal/svc"
@@ -39,6 +40,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/fix_nft_staker",
Handler: admin.FixNftStakerHandler(serverCtx),
},
{
// GameAction
Method: http.MethodPost,
Path: "/game_action",
Handler: admin.GameActionHandler(serverCtx),
},
{
// NFT持有者更新
Method: http.MethodGet,
@@ -125,6 +132,25 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithPrefix("/gapi/kgen"),
)
server.AddRoutes(
[]rest.Route{
{
// 获取质押档位列表
Method: http.MethodGet,
Path: "/level",
Handler: stakepoint.GetStakeLevelListHandler(serverCtx),
},
{
// 质押积分操作
Method: http.MethodPost,
Path: "/stake",
Handler: stakepoint.StakePointHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
rest.WithPrefix("/gapi/stakepoint/v1"),
)
server.AddRoutes(
[]rest.Route{
{

View File

@@ -0,0 +1,29 @@
package stakepoint
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/stakepoint"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 获取质押档位列表
func GetStakeLevelListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetStakeLevelListReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := stakepoint.NewGetStakeLevelListLogic(r.Context(), svcCtx)
resp, err := l.GetStakeLevelList(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package stakepoint
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/stakepoint"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 质押积分操作
func StakePointHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.StakePointReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := stakepoint.NewStakePointLogic(r.Context(), svcCtx)
err := l.StakePoint(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.Ok(w)
}
}
}

View File

@@ -0,0 +1,69 @@
package check_points_stake
import (
"context"
"github.com/robfig/cron/v3"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"nova_task/internal/consts"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc"
"time"
)
type Cron struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCron(ctx context.Context, svcCtx *svc.ServiceContext) cron.Job {
return &Cron{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (c *Cron) Spec() string {
return "@every 30s"
}
func (c *Cron) Run() {
ns, err := c.svcCtx.StakePointsModel.FindOverdueList(c.ctx)
if err != nil {
logx.Errorw("find overdue list failed", logx.Field("err", err))
return
}
if len(ns) == 0 {
return
}
logx.Debugw("find overdue list", logx.Field("count", len(ns)))
for _, n := range ns {
err = c.svcCtx.DBConn.TransactCtx(c.ctx, func(ctx context.Context, session sqlx.Session) error {
err = c.svcCtx.StakePointsModel.WithSession(session).SetOverdue(ctx, n.Id)
if err != nil {
logx.Errorw("set overdue failed", logx.Field("err", err))
return err
}
err = c.svcCtx.AddUserAssetWithSession(c.ctx, session, n.Uid, int64(n.RoleId), consts.AssetType_Points, "", decimal.NewFromInt(int64(n.Points)), "stake point overdue return", 0, 0, false)
if err != nil {
return err
}
_, err = c.svcCtx.GameAction(c.ctx, int64(n.RoleId), consts.GameActionStakePoints, map[string]any{
"level": n.Level,
"operation": 4,
"start_time": time.Now().Unix(),
"end_time": 0,
"renew_times": 0,
})
if err != nil {
logx.Errorw("game action failed", logx.Field("err", err), logx.Field("uid", n.Uid), logx.Field("roleId", n.RoleId))
return errs.New(errs.ErrInternalServer, err)
}
return nil
})
if err != nil {
logx.Errorw("SetOverdue points stake", logx.Field("err", err), logx.Field("uid", n.Uid), logx.Field("roleId", n.RoleId))
}
}
}

View File

@@ -5,6 +5,7 @@ import (
"errors"
"github.com/robfig/cron/v3"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/job/check_points_stake"
"nova_task/internal/job/earn"
"nova_task/internal/job/holder"
"nova_task/internal/job/stake_settle"
@@ -16,6 +17,8 @@ var cronList = []func(context.Context, *svc.ServiceContext) cron.Job{
earn.NewCron,
holder.NewCron,
stake_settle.NewCron,
//game_notify.NewCron,
check_points_stake.NewCron,
}
type Corns struct {

View File

@@ -0,0 +1,81 @@
package game_notify
import (
"context"
"encoding/json"
"github.com/robfig/cron/v3"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/model"
"nova_task/internal/svc"
)
type Cron struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCron(ctx context.Context, svcCtx *svc.ServiceContext) cron.Job {
return &Cron{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (c *Cron) Spec() string {
return "@every 30s"
}
func (c *Cron) Run() {
c.Process(model.NTF_STATUS_WAITING_PROCESS)
c.Process(model.NTF_STATUS_FAILED)
}
func (c *Cron) Process(status int8) {
nfs, err := c.svcCtx.GameServerNotifyModel.FindNotifyList(c.ctx, status)
if err != nil {
logx.Errorw("find notify list failed", logx.Field("err", err))
return
}
if len(nfs) == 0 {
logx.Debug("no notify")
return
}
for _, nf := range nfs {
var arg = map[string]any{}
if nf.Data.Valid {
err = json.Unmarshal([]byte(nf.Data.String), &arg)
if err != nil {
logx.Errorw("unmarshal notify data failed", logx.Field("err", err), logx.Field("id", nf.Id))
continue
}
}
err := c.svcCtx.GameServerNotifyModel.UpdateNotifyStatus(c.ctx, nf.Id, model.NTF_STATUS_PROCESSING)
if err != nil {
logx.Errorw("update notify status failed", logx.Field("err", err), logx.Field("id", nf.Id))
continue
}
_, err = c.svcCtx.GameAction(c.ctx, int64(nf.RoleId), nf.Action, arg)
if err != nil {
c.svcCtx.GameServerNotifyModel.UpdateNotifyStatus(c.ctx, nf.Id, model.NTF_STATUS_FAILED)
} else {
c.svcCtx.GameServerNotifyModel.UpdateNotifyStatus(c.ctx, nf.Id, model.NTF_STATUS_SUCCESS)
}
}
}
/*
CREATE TABLE `nh_game_server_notify`
(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) unsigned NOT NULL COMMENT '角色id',
`action` varchar(128) NOT NULL COMMENT '事件类型',
`data` text NULL DEFAULT NULL COMMENT '事件数据',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态1=待处理2=处理中, 3=处理失败, 4=处理成功',
`retry_times` int NOT NULL DEFAULT 0 COMMENT '重试次数',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
INDEX (`status`)
) COMMENT ='游戏服通知事件';
*/

View File

@@ -0,0 +1,27 @@
package admin
import (
"context"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GameActionLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGameActionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GameActionLogic {
return &GameActionLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GameActionLogic) GameAction(req *types.GameActionReq) (any, error) {
return l.svcCtx.GameAction(l.ctx, req.RoleId, req.Action, nil)
}

View File

@@ -0,0 +1,147 @@
package stakepoint
import (
"context"
"errors"
"github.com/shopspring/decimal"
"github.com/spf13/cast"
"nova_task/internal/consts"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"time"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetStakeLevelListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetStakeLevelListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetStakeLevelListLogic {
return &GetStakeLevelListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetStakeLevelListLogic) GetStakeLevelList(req *types.GetStakeLevelListReq) (*types.GetStakeLevelListResp, error) {
resp, err := l.svcCtx.GameAction(l.ctx, req.RoleID, consts.GameActionGetHomePointsState, nil)
if err != nil {
l.Errorw("GetStakeLevelList", logx.Field("err", err))
return nil, errs.New(errs.GameServerError, err)
}
if !cast.ToBool(resp.(map[string]any)["data"]) {
l.Debugw("getStakeHomePointsState", logx.Field("role", req.RoleID), logx.Field("resp", resp))
return &types.GetStakeLevelListResp{
State: 0,
}, nil
}
lvs, err := l.svcCtx.StakePointConfigModel.All(l.ctx)
if err != nil {
l.Errorw("GetStakeLevelList", logx.Field("err", err))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
var ls []types.PointStakeLevel
for _, lv := range lvs {
ls = append(ls, types.PointStakeLevel{
Id: int(lv.Id),
Title: lv.Title,
Level: int(lv.Level),
Points: int(lv.Points),
Days: lv.Days.InexactFloat64(),
RenewDays: lv.RenewDays.InexactFloat64(),
})
}
stake, err := l.svcCtx.StakePointsModel.FindCurrentLevel(l.ctx, req.RoleID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
l.Errorw("GetStakeLevelList", logx.Field("err", err), logx.Field("role_id", req.RoleID))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
var staking *types.StakeLevel
var hasRenew bool
if stake != nil {
var (
title string
level int
points int
days float64
renewDays float64
canRenew bool
)
for _, lv := range lvs {
if lv.Id == stake.LevelId {
title = lv.Title
level = int(lv.Level)
points = int(lv.Points)
days = lv.Days.InexactFloat64()
renewDays = lv.RenewDays.InexactFloat64()
canRenew = stake.EndTime.Sub(time.Now()) <= time.Duration(lv.RenewDays.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) && stake.Status == model.PointsStakeStatusStaking
break
}
}
hasRenew = stake.Status == model.PointsStakeStatusRenew
staking = &types.StakeLevel{
Id: int(stake.LevelId),
Title: title,
Level: level,
Points: points,
Days: days,
RenewDays: renewDays,
StartTime: stake.StartTime.Format(time.DateTime),
EndTime: stake.EndTime.Format(time.DateTime),
CanRenew: canRenew,
}
}
var renewLevel *types.StakeLevel
if hasRenew {
stk, err := l.svcCtx.StakePointsModel.FindRenewLevel(l.ctx, req.RoleID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
l.Errorw("GetStakeLevelList", logx.Field("err", err), logx.Field("role_id", req.RoleID))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
if stk != nil {
var (
title string
level int
points int
days float64
renewDays float64
)
for _, lv := range lvs {
if lv.Id == stk.LevelId {
title = lv.Title
level = int(lv.Level)
points = int(lv.Points)
days = lv.Days.InexactFloat64()
renewDays = lv.RenewDays.InexactFloat64()
break
}
}
renewLevel = &types.StakeLevel{
Id: int(stk.LevelId),
Title: title,
Level: level,
Points: points,
Days: days,
RenewDays: renewDays,
StartTime: stk.StartTime.Format(time.DateTime),
EndTime: stk.EndTime.Format(time.DateTime),
CanRenew: false,
}
}
}
return &types.GetStakeLevelListResp{
State: 1,
Staking: staking,
RenewLevel: renewLevel,
Levels: ls,
}, nil
}

View File

@@ -0,0 +1,237 @@
package stakepoint
import (
"context"
"errors"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"nova_task/internal/consts"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"nova_task/internal/pkg/utils"
"time"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type StakePointLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 质押积分操作
func NewStakePointLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StakePointLogic {
return &StakePointLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *StakePointLogic) StakePoint(req *types.StakePointReq) error {
uid := utils.GetUid(l.ctx)
r, err := l.svcCtx.RoleModel.FindOneByRoleId(l.ctx, req.RoleID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrRoleNotFound, "role not exist")
}
l.Errorw("find role error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrDatabaseOperate, err)
}
u, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, r.Account)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrUserNotFound, "user not found")
}
l.Errorw("find user error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrDatabaseOperate, err)
}
if u.Id != uint(uid) {
return errs.New(errs.ErrRoleNotFound, "role not exist")
}
lv, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, uint(req.LevelId))
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrPointLevelConfigNotFound, "stake point level config not found")
}
return errs.New(errs.ErrDatabaseOperate, err)
}
clv, err := l.svcCtx.StakePointsModel.FindCurrentLevel(l.ctx, req.RoleID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
l.Errorw("find current level error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrDatabaseOperate, err)
}
start := time.Now()
end := start.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour * 24))).IntPart()))
switch req.Action {
case 1:
if err == nil {
return errs.New(errs.ErrPointsStakeExist, "stake points exist")
}
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-lv.Points)), "stake points", 0, 0, false)
if err != nil {
return err
}
_, err = l.svcCtx.StakePointsModel.WithSession(session).Insert(l.ctx, &model.NhStakePoints{
Uid: uint(uid),
RoleId: uint64(req.RoleID),
LevelId: lv.Id,
Level: lv.Level,
Points: lv.Points,
StartTime: start,
EndTime: end,
Status: model.PointsStakeStatusStaking,
})
if err != nil {
return errs.New(errs.ErrDatabaseOperate, err)
}
_, err := l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
"level": lv.Level,
"operation": req.Action,
"start_time": start.Unix(),
"end_time": end.Unix(),
"renew_times": 0,
})
return err
})
if err != nil {
l.Errorw("积分质押", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrInternalServer, err)
}
case 2:
if err != nil {
l.Errorw("用户在未质押的情况下进行升级", logx.Field("uid", uid), logx.Field("role_id", req.RoleID))
return errs.New(errs.ErrPointStakeNotExist, "stake points not exist")
}
clvConfig, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, clv.LevelId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrPointLevelConfigNotFound, "current stake point level config not found")
}
return errs.New(errs.ErrDatabaseOperate, err)
}
if lv.Level <= clvConfig.Level {
return errs.New(errs.ErrPointsStakeLevelNotAllow, "Upgraded pledge credit bracket must be higher than current bracket")
}
// 已续约,不可升级
if clv.Status != model.PointsStakeStatusStaking {
return errs.New(errs.ErrPointsStakeHasRenew, "Current stake has renew")
}
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
points := lv.Points - clvConfig.Points
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-points)), "stake points", 0, 0, false)
if err != nil {
return err
}
clv.Status = model.PointsStakeStatusUpgraded
clv.EndTime = start
spm := l.svcCtx.StakePointsModel.WithSession(session)
err := spm.Update(ctx, clv)
if err != nil {
return errs.New(errs.ErrDatabaseOperate, err)
}
end = start.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) - start.Sub(clv.StartTime))
_, err = spm.Insert(l.ctx, &model.NhStakePoints{
Uid: uint(uid),
RoleId: uint64(req.RoleID),
LevelId: lv.Id,
Level: lv.Level,
Points: lv.Points,
StartTime: start,
EndTime: end,
Status: model.PointsStakeStatusStaking,
})
if err != nil {
return errs.New(errs.ErrDatabaseOperate, err)
}
_, err = l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
"level": lv.Level,
"operation": req.Action,
"start_time": start.Unix(),
"end_time": end.Unix(),
"renew_times": 0,
})
return err
})
if err != nil {
l.Errorw("积分质押升级失败", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrInternalServer, err)
}
case 3:
if err != nil {
l.Errorw("用户在未质押的情况下进行续约", logx.Field("uid", uid), logx.Field("role_id", req.RoleID))
return errs.New(errs.ErrPointStakeNotExist, "stake points not exist")
}
clvConfig, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, clv.LevelId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrPointLevelConfigNotFound, "current stake point level config not found")
}
return errs.New(errs.ErrDatabaseOperate, err)
}
// 续约等级不能小于当前等级
if lv.Level < clvConfig.Level {
return errs.New(errs.ErrPointsStakeLevelNotAllow, "Renewal level cannot be lower than current level")
}
// 已续约,不可重复续约
if clv.Status != model.PointsStakeStatusStaking {
return errs.New(errs.ErrPointsStakeHasRenew, "Current stake has renew")
}
// 判断是否在可续约时间范围内
if clv.EndTime.Sub(time.Now()) > time.Duration(clvConfig.RenewDays.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) {
return errs.New(errs.ErrPointsStakeNotInRenewTime, "Not within the renewal time frame")
}
// 判断是否属于续约期内
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
points := lv.Points - clvConfig.Points
if points > 0 {
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-points)), "stake points", 0, 0, false)
if err != nil {
return err
}
}
clv.Status = model.PointsStakeStatusRenew
spm := l.svcCtx.StakePointsModel.WithSession(session)
err := spm.Update(ctx, clv)
if err != nil {
return errs.New(errs.ErrDatabaseOperate, err)
}
end = clv.EndTime.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour * 24))).IntPart()))
_, err = spm.Insert(l.ctx, &model.NhStakePoints{
Uid: uint(uid),
RoleId: uint64(req.RoleID),
LevelId: lv.Id,
Level: lv.Level,
Points: lv.Points,
StartTime: clv.EndTime,
EndTime: end,
Status: model.PointsStakeStatusStaking,
})
if err != nil {
return errs.New(errs.ErrDatabaseOperate, err)
}
_, err = l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
"level": lv.Level,
"operation": req.Action,
"start_time": start.Unix(),
"end_time": end.Unix(),
"renew_times": 0,
})
return err
})
if err != nil {
l.Errorw("积分质押续期失败", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
return errs.New(errs.ErrInternalServer, err)
}
default:
return errs.New(errs.ErrInvalidParam, "Invalid action")
}
return errs.Success()
}

View File

@@ -0,0 +1,57 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ MgServersModel = (*customMgServersModel)(nil)
type (
// MgServersModel is an interface to be customized, add more methods here,
// and implement the added methods in customMgServersModel.
MgServersModel interface {
mgServersModel
withSession(session sqlx.Session) MgServersModel
GetGameServer(ctx context.Context, agentId, serverId int64) (*GameServer, error)
}
customMgServersModel struct {
*defaultMgServersModel
}
GameServer struct {
AgentID int `db:"agent_id"` // 代理ID
ServerID int `db:"server_id"` // 服务器ID
WebPort int `db:"web_port"` // web访问端口
ServerIP string `db:"server_ip"` // 内网IP
PublicServerIP string `db:"public_server_ip"` // 公网IP
}
)
func (m *customMgServersModel) GetGameServer(ctx context.Context, agentId, serverId int64) (*GameServer, error) {
query := fmt.Sprintf("SELECT g.agent_id, g.server_id, g.web_port, s.ip AS server_ip, s.public_ip AS public_server_ip FROM ms_game_server AS g LEFT JOIN mg_servers AS s ON s.id = g.server_server_id WHERE g.server_id = ? AND g.agent_id = ?")
var result GameServer
err := m.conn.QueryRowCtx(ctx, &result, query, serverId, agentId)
switch {
case err == nil:
return &result, nil
case errors.Is(err, sqlx.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
// NewMgServersModel returns a model for the database table.
func NewMgServersModel(conn sqlx.SqlConn) MgServersModel {
return &customMgServersModel{
defaultMgServersModel: newMgServersModel(conn),
}
}
func (m *customMgServersModel) withSession(session sqlx.Session) MgServersModel {
return NewMgServersModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,92 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
mgServersFieldNames = builder.RawFieldNames(&MgServers{})
mgServersRows = strings.Join(mgServersFieldNames, ",")
mgServersRowsExpectAutoSet = strings.Join(stringx.Remove(mgServersFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
mgServersRowsWithPlaceHolder = strings.Join(stringx.Remove(mgServersFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
mgServersModel interface {
Insert(ctx context.Context, data *MgServers) (sql.Result, error)
FindOne(ctx context.Context, id int) (*MgServers, error)
Update(ctx context.Context, data *MgServers) error
Delete(ctx context.Context, id int) error
}
defaultMgServersModel struct {
conn sqlx.SqlConn
table string
}
MgServers struct {
Id int `db:"id"`
RegionId int `db:"region_id"` // 区域ID
Ip sql.NullString `db:"ip"` // 内网IP
PublicIp sql.NullString `db:"public_ip"` // 公网IP
Domain sql.NullString `db:"domain"` // 域名
ServerCategory sql.NullInt64 `db:"server_category"` // 服务器分类 1:游戏节点服, 2:游戏业务数据库服, 3:游戏日志数据库服,
ServerType sql.NullInt64 `db:"server_type"` // 服务器类型 1:本地开发;3:Android服;4:iOS服;
AdminId sql.NullInt64 `db:"admin_id"`
AddTime sql.NullTime `db:"add_time"`
}
)
func newMgServersModel(conn sqlx.SqlConn) *defaultMgServersModel {
return &defaultMgServersModel{
conn: conn,
table: "`mg_servers`",
}
}
func (m *defaultMgServersModel) Delete(ctx context.Context, id int) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultMgServersModel) FindOne(ctx context.Context, id int) (*MgServers, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", mgServersRows, m.table)
var resp MgServers
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultMgServersModel) Insert(ctx context.Context, data *MgServers) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, mgServersRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.RegionId, data.Ip, data.PublicIp, data.Domain, data.ServerCategory, data.ServerType, data.AdminId, data.AddTime)
return ret, err
}
func (m *defaultMgServersModel) Update(ctx context.Context, data *MgServers) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, mgServersRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.RegionId, data.Ip, data.PublicIp, data.Domain, data.ServerCategory, data.ServerType, data.AdminId, data.AddTime, data.Id)
return err
}
func (m *defaultMgServersModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ MsGameServerModel = (*customMsGameServerModel)(nil)
type (
// MsGameServerModel is an interface to be customized, add more methods here,
// and implement the added methods in customMsGameServerModel.
MsGameServerModel interface {
msGameServerModel
withSession(session sqlx.Session) MsGameServerModel
}
customMsGameServerModel struct {
*defaultMsGameServerModel
}
)
// NewMsGameServerModel returns a model for the database table.
func NewMsGameServerModel(conn sqlx.SqlConn) MsGameServerModel {
return &customMsGameServerModel{
defaultMsGameServerModel: newMsGameServerModel(conn),
}
}
func (m *customMsGameServerModel) withSession(session sqlx.Session) MsGameServerModel {
return NewMsGameServerModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,125 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
msGameServerFieldNames = builder.RawFieldNames(&MsGameServer{})
msGameServerRows = strings.Join(msGameServerFieldNames, ",")
msGameServerRowsExpectAutoSet = strings.Join(stringx.Remove(msGameServerFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
msGameServerRowsWithPlaceHolder = strings.Join(stringx.Remove(msGameServerFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
msGameServerModel interface {
Insert(ctx context.Context, data *MsGameServer) (sql.Result, error)
FindOne(ctx context.Context, id int) (*MsGameServer, error)
Update(ctx context.Context, data *MsGameServer) error
Delete(ctx context.Context, id int) error
}
defaultMsGameServerModel struct {
conn sqlx.SqlConn
table string
}
MsGameServer struct {
Id int `db:"id"` // ID
AgentId int `db:"agent_id"` // 代理ID
ServerId int `db:"server_id"` // 服务器ID
AgentServer sql.NullInt64 `db:"agent_server"` // agent_id 和 server_id的组合agent_id*10000000 + server_id
ServerName string `db:"server_name"` // 服名称
ServerServerId sql.NullInt64 `db:"server_server_id"` // 游戏节点服的物理服务器ID
MainNodes sql.NullString `db:"main_nodes"` // 主节点集合
Gateways sql.NullString `db:"gateways"` // 网关节点集合
GatewayPort int `db:"gateway_port"` // 游戏服端口
GameCode string `db:"game_code"` // 游戏名
AgentCode string `db:"agent_code"` // 代理
Branch string `db:"branch"` // 分支
ServerStartTime sql.NullTime `db:"server_start_time"` // 开服时间
WebPort int `db:"web_port"` // web访问端口
LogLevel int `db:"log_level"` // 日志等级
LogDir string `db:"log_dir"` // 日志地址
IsDebug string `db:"is_debug"` // debug是否开启,默认false
BackgroundLogOpen string `db:"background_log_open"` // 是否记录后台日志,默认开启
CenterId int `db:"center_id"` // 游戏中央服id
CenterIp string `db:"center_ip"` // 游戏中央服ip
ReplayId int `db:"replay_id"` // 重播日志服务器id
CrossId int `db:"cross_id"` // 跨服服务器id
DbServerId sql.NullInt64 `db:"db_server_id"` // 游戏业务数据库的物理服务器ID
DbPort int `db:"db_port"` // 游戏数据库port
RedisServerId sql.NullInt64 `db:"redis_server_id"` // redis的物理服务器ID
RedisPort sql.NullInt64 `db:"redis_port"` // redis端口
AdminServerId sql.NullInt64 `db:"admin_server_id"` // 游戏日志数据库的物理服务器ID
AdminPort int `db:"admin_port"` // 日志数据库端口
SdkVerifyUrl string `db:"sdk_verify_url"` // SDK验证地址
SdkVerifySandboxUrl string `db:"sdk_verify_sandbox_url"` // SDK验证地址(沙盒)
WebUrl string `db:"web_url"` // API接口域名
EsUrl string `db:"es_url"` // ES接口地址
IsMerge uint `db:"is_merge"` // 是否是合服后的新服
MergeTime sql.NullString `db:"merge_time"` // 合服时间
HbCheckClosed string `db:"hb_check_closed"` // 心跳包检查是否关闭,默认关闭
ItemBanList sql.NullString `db:"item_ban_list"` // 禁用道具
RegionIso string `db:"region_iso"` // 地区ISO
BytedanceLogOpen string `db:"bytedance_log_open"` // 字节跳动元宝日志,默认开启
IsFightLog string `db:"is_fight_log"` // 是否开启战斗日志默认false
CookieExtend string `db:"cookie_extend"` // 节点cookie
IsOverseas int8 `db:"is_overseas"` // 0国内 1国外
Status int8 `db:"status"` // 1:正常; 2:被合服了; 4:关服
}
)
func newMsGameServerModel(conn sqlx.SqlConn) *defaultMsGameServerModel {
return &defaultMsGameServerModel{
conn: conn,
table: "`ms_game_server`",
}
}
func (m *defaultMsGameServerModel) Delete(ctx context.Context, id int) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultMsGameServerModel) FindOne(ctx context.Context, id int) (*MsGameServer, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", msGameServerRows, m.table)
var resp MsGameServer
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultMsGameServerModel) Insert(ctx context.Context, data *MsGameServer) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, msGameServerRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.AgentId, data.ServerId, data.AgentServer, data.ServerName, data.ServerServerId, data.MainNodes, data.Gateways, data.GatewayPort, data.GameCode, data.AgentCode, data.Branch, data.ServerStartTime, data.WebPort, data.LogLevel, data.LogDir, data.IsDebug, data.BackgroundLogOpen, data.CenterId, data.CenterIp, data.ReplayId, data.CrossId, data.DbServerId, data.DbPort, data.RedisServerId, data.RedisPort, data.AdminServerId, data.AdminPort, data.SdkVerifyUrl, data.SdkVerifySandboxUrl, data.WebUrl, data.EsUrl, data.IsMerge, data.MergeTime, data.HbCheckClosed, data.ItemBanList, data.RegionIso, data.BytedanceLogOpen, data.IsFightLog, data.CookieExtend, data.IsOverseas, data.Status)
return ret, err
}
func (m *defaultMsGameServerModel) Update(ctx context.Context, data *MsGameServer) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, msGameServerRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.AgentId, data.ServerId, data.AgentServer, data.ServerName, data.ServerServerId, data.MainNodes, data.Gateways, data.GatewayPort, data.GameCode, data.AgentCode, data.Branch, data.ServerStartTime, data.WebPort, data.LogLevel, data.LogDir, data.IsDebug, data.BackgroundLogOpen, data.CenterId, data.CenterIp, data.ReplayId, data.CrossId, data.DbServerId, data.DbPort, data.RedisServerId, data.RedisPort, data.AdminServerId, data.AdminPort, data.SdkVerifyUrl, data.SdkVerifySandboxUrl, data.WebUrl, data.EsUrl, data.IsMerge, data.MergeTime, data.HbCheckClosed, data.ItemBanList, data.RegionIso, data.BytedanceLogOpen, data.IsFightLog, data.CookieExtend, data.IsOverseas, data.Status, data.Id)
return err
}
func (m *defaultMsGameServerModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,52 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ MsMergeServersModel = (*customMsMergeServersModel)(nil)
type (
// MsMergeServersModel is an interface to be customized, add more methods here,
// and implement the added methods in customMsMergeServersModel.
MsMergeServersModel interface {
msMergeServersModel
withSession(session sqlx.Session) MsMergeServersModel
FinalServer(ctx context.Context, childAgentId, childServerId int64) (FinalAgentId, FinalServerServerId int64, err error)
}
customMsMergeServersModel struct {
*defaultMsMergeServersModel
}
)
func (m *customMsMergeServersModel) FinalServer(ctx context.Context, childAgentId, childServerId int64) (FinalAgentId, FinalServerServerId int64, err error) {
query := fmt.Sprintf("select final_agent_id, final_server_id from %s where child_agent_id = ? and child_server_id = ?", m.table)
var result struct {
FinalServerServerId int64 `db:"final_server_server_id"` // 物理服务器ID来自mg_servers的自增ID
FinalAgentId int64 `db:"final_agent_id"` // 最终被合到了此agent_id下
}
err = m.conn.QueryRowCtx(ctx, &result, query, childAgentId, childServerId)
switch {
case err == nil:
return result.FinalAgentId, result.FinalServerServerId, nil
case errors.Is(err, sqlx.ErrNotFound):
return childAgentId, childServerId, nil
default:
return 0, 0, err
}
}
// NewMsMergeServersModel returns a model for the database table.
func NewMsMergeServersModel(conn sqlx.SqlConn) MsMergeServersModel {
return &customMsMergeServersModel{
defaultMsMergeServersModel: newMsMergeServersModel(conn),
}
}
func (m *customMsMergeServersModel) withSession(session sqlx.Session) MsMergeServersModel {
return NewMsMergeServersModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,96 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
msMergeServersFieldNames = builder.RawFieldNames(&MsMergeServers{})
msMergeServersRows = strings.Join(msMergeServersFieldNames, ",")
msMergeServersRowsExpectAutoSet = strings.Join(stringx.Remove(msMergeServersFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
msMergeServersRowsWithPlaceHolder = strings.Join(stringx.Remove(msMergeServersFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
msMergeServersModel interface {
Insert(ctx context.Context, data *MsMergeServers) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*MsMergeServers, error)
Update(ctx context.Context, data *MsMergeServers) error
Delete(ctx context.Context, id uint) error
}
defaultMsMergeServersModel struct {
conn sqlx.SqlConn
table string
}
MsMergeServers struct {
Id uint `db:"id"`
GsId sql.NullInt64 `db:"gs_id"` // 被合的服ms_game_server里的自增id
FinalServerServerId sql.NullInt64 `db:"final_server_server_id"` // 物理服务器ID来自mg_servers的自增ID
FinalAgentId sql.NullInt64 `db:"final_agent_id"` // 最终被合到了此agent_id下
FinalServerId sql.NullInt64 `db:"final_server_id"` // 最终被合到了此server_id下
FinalAgentServer sql.NullInt64 `db:"final_agent_server"` // 最终被合到了此agent_server下
ServerId sql.NullInt64 `db:"server_id"` // 合到此服
AgentServer sql.NullInt64 `db:"agent_server"` // agent_id 和 server_id的组合
ChildAgentId sql.NullInt64 `db:"child_agent_id"` // 被合服的agent_id
ChildServerId sql.NullInt64 `db:"child_server_id"` // 被合服的server_id
ChildAgentServer sql.NullInt64 `db:"child_agent_server"` // 被合服的server_id 和 server_id组合
AdminId sql.NullInt64 `db:"admin_id"` // 操作员
AddTime sql.NullInt64 `db:"add_time"` // 合服时间
}
)
func newMsMergeServersModel(conn sqlx.SqlConn) *defaultMsMergeServersModel {
return &defaultMsMergeServersModel{
conn: conn,
table: "`ms_merge_servers`",
}
}
func (m *defaultMsMergeServersModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultMsMergeServersModel) FindOne(ctx context.Context, id uint) (*MsMergeServers, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", msMergeServersRows, m.table)
var resp MsMergeServers
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultMsMergeServersModel) Insert(ctx context.Context, data *MsMergeServers) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, msMergeServersRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.GsId, data.FinalServerServerId, data.FinalAgentId, data.FinalServerId, data.FinalAgentServer, data.ServerId, data.AgentServer, data.ChildAgentId, data.ChildServerId, data.ChildAgentServer, data.AdminId, data.AddTime)
return ret, err
}
func (m *defaultMsMergeServersModel) Update(ctx context.Context, data *MsMergeServers) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, msMergeServersRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.GsId, data.FinalServerServerId, data.FinalAgentId, data.FinalServerId, data.FinalAgentServer, data.ServerId, data.AgentServer, data.ChildAgentId, data.ChildServerId, data.ChildAgentServer, data.AdminId, data.AddTime, data.Id)
return err
}
func (m *defaultMsMergeServersModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,80 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ NhGameServerNotifyModel = (*customNhGameServerNotifyModel)(nil)
type (
// NhGameServerNotifyModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhGameServerNotifyModel.
NhGameServerNotifyModel interface {
nhGameServerNotifyModel
withSession(session sqlx.Session) NhGameServerNotifyModel
FindNotifyList(ctx context.Context, status int8) ([]*NhGameServerNotify, error)
UpdateNotifyStatus(ctx context.Context, id uint, status int8) error
}
customNhGameServerNotifyModel struct {
*defaultNhGameServerNotifyModel
}
)
const (
NTF_STATUS_UNKNOWN = 0 // 未知
NTF_STATUS_WAITING_PROCESS = 1 // 待处理
NTF_STATUS_PROCESSING = 2 // 处理中
NTF_STATUS_FAILED = 3 // 处理失败
NTF_STATUS_SUCCESS = 4 // 处理成功
)
func (m *customNhGameServerNotifyModel) UpdateNotifyStatus(ctx context.Context, id uint, status int8) error {
var update string
switch status {
case NTF_STATUS_PROCESSING:
update = fmt.Sprintf("update %s set `status` = 2, `retry_times` = `retry_times` + 1 where `id` = ? and (`status` = 1 or `status` = 3)", m.table)
case NTF_STATUS_FAILED:
update = fmt.Sprintf("update %s set `status` = 3 where `id` = ? and `status` = 1", m.table)
case NTF_STATUS_SUCCESS:
update = fmt.Sprintf("update %s set `status` = 4 where `id` = ? and `status` = 1", m.table)
default:
return fmt.Errorf("unsupported status %d", status)
}
result, err := m.conn.ExecCtx(ctx, update, id)
if err != nil {
return err
}
rows, err := result.RowsAffected()
if err != nil {
return err
}
if rows == 0 {
return ErrNoRowUpdate
}
return nil
}
func (m *customNhGameServerNotifyModel) FindNotifyList(ctx context.Context, status int8) ([]*NhGameServerNotify, error) {
query := fmt.Sprintf("select %s from %s where `status` = ? and `retry_times` < 6 limit 10", nhGameServerNotifyRows, m.table)
var ntfs []*NhGameServerNotify
err := m.conn.QueryRowsCtx(ctx, &ntfs, query, status)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return ntfs, nil
}
// NewNhGameServerNotifyModel returns a model for the database table.
func NewNhGameServerNotifyModel(conn sqlx.SqlConn) NhGameServerNotifyModel {
return &customNhGameServerNotifyModel{
defaultNhGameServerNotifyModel: newNhGameServerNotifyModel(conn),
}
}
func (m *customNhGameServerNotifyModel) withSession(session sqlx.Session) NhGameServerNotifyModel {
return NewNhGameServerNotifyModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,92 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhGameServerNotifyFieldNames = builder.RawFieldNames(&NhGameServerNotify{})
nhGameServerNotifyRows = strings.Join(nhGameServerNotifyFieldNames, ",")
nhGameServerNotifyRowsExpectAutoSet = strings.Join(stringx.Remove(nhGameServerNotifyFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhGameServerNotifyRowsWithPlaceHolder = strings.Join(stringx.Remove(nhGameServerNotifyFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhGameServerNotifyModel interface {
Insert(ctx context.Context, data *NhGameServerNotify) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhGameServerNotify, error)
Update(ctx context.Context, data *NhGameServerNotify) error
Delete(ctx context.Context, id uint) error
}
defaultNhGameServerNotifyModel struct {
conn sqlx.SqlConn
table string
}
NhGameServerNotify struct {
Id uint `db:"id"`
RoleId uint64 `db:"role_id"` // 角色id
Action string `db:"action"` // 事件类型
Data sql.NullString `db:"data"` // 事件数据
Status int8 `db:"status"` // 状态1=待处理2=处理中, 3=处理失败, 4=处理成功
RetryTimes int `db:"retry_times"` // 重试次数
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
}
)
func newNhGameServerNotifyModel(conn sqlx.SqlConn) *defaultNhGameServerNotifyModel {
return &defaultNhGameServerNotifyModel{
conn: conn,
table: "`nh_game_server_notify`",
}
}
func (m *defaultNhGameServerNotifyModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhGameServerNotifyModel) FindOne(ctx context.Context, id uint) (*NhGameServerNotify, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhGameServerNotifyRows, m.table)
var resp NhGameServerNotify
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhGameServerNotifyModel) Insert(ctx context.Context, data *NhGameServerNotify) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, nhGameServerNotifyRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.RoleId, data.Action, data.Data, data.Status, data.RetryTimes)
return ret, err
}
func (m *defaultNhGameServerNotifyModel) Update(ctx context.Context, data *NhGameServerNotify) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhGameServerNotifyRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.RoleId, data.Action, data.Data, data.Status, data.RetryTimes, data.Id)
return err
}
func (m *defaultNhGameServerNotifyModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ NhRequestServerLogModel = (*customNhRequestServerLogModel)(nil)
type (
// NhRequestServerLogModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhRequestServerLogModel.
NhRequestServerLogModel interface {
nhRequestServerLogModel
withSession(session sqlx.Session) NhRequestServerLogModel
}
customNhRequestServerLogModel struct {
*defaultNhRequestServerLogModel
}
)
// NewNhRequestServerLogModel returns a model for the database table.
func NewNhRequestServerLogModel(conn sqlx.SqlConn) NhRequestServerLogModel {
return &customNhRequestServerLogModel{
defaultNhRequestServerLogModel: newNhRequestServerLogModel(conn),
}
}
func (m *customNhRequestServerLogModel) withSession(session sqlx.Session) NhRequestServerLogModel {
return NewNhRequestServerLogModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,90 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhRequestServerLogFieldNames = builder.RawFieldNames(&NhRequestServerLog{})
nhRequestServerLogRows = strings.Join(nhRequestServerLogFieldNames, ",")
nhRequestServerLogRowsExpectAutoSet = strings.Join(stringx.Remove(nhRequestServerLogFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhRequestServerLogRowsWithPlaceHolder = strings.Join(stringx.Remove(nhRequestServerLogFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhRequestServerLogModel interface {
Insert(ctx context.Context, data *NhRequestServerLog) (sql.Result, error)
FindOne(ctx context.Context, id int) (*NhRequestServerLog, error)
Update(ctx context.Context, data *NhRequestServerLog) error
Delete(ctx context.Context, id int) error
}
defaultNhRequestServerLogModel struct {
conn sqlx.SqlConn
table string
}
NhRequestServerLog struct {
Id int `db:"id"`
Action string `db:"action"` // 接口
Url string `db:"url"` // 推送地址
ServerInfo string `db:"server_info"`
ReqData string `db:"req_data"` // 请求数据
ResData string `db:"res_data"` // 响应数据
CreateTime sql.NullTime `db:"create_time"` // 创建时间
}
)
func newNhRequestServerLogModel(conn sqlx.SqlConn) *defaultNhRequestServerLogModel {
return &defaultNhRequestServerLogModel{
conn: conn,
table: "`nh_request_server_log`",
}
}
func (m *defaultNhRequestServerLogModel) Delete(ctx context.Context, id int) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhRequestServerLogModel) FindOne(ctx context.Context, id int) (*NhRequestServerLog, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhRequestServerLogRows, m.table)
var resp NhRequestServerLog
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhRequestServerLogModel) Insert(ctx context.Context, data *NhRequestServerLog) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, nhRequestServerLogRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Action, data.Url, data.ServerInfo, data.ReqData, data.ResData)
return ret, err
}
func (m *defaultNhRequestServerLogModel) Update(ctx context.Context, data *NhRequestServerLog) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhRequestServerLogRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Action, data.Url, data.ServerInfo, data.ReqData, data.ResData, data.Id)
return err
}
func (m *defaultNhRequestServerLogModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,45 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ NhStakeHomePointConfigModel = (*customNhStakeHomePointConfigModel)(nil)
type (
// NhStakeHomePointConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhStakeHomePointConfigModel.
NhStakeHomePointConfigModel interface {
nhStakeHomePointConfigModel
withSession(session sqlx.Session) NhStakeHomePointConfigModel
All(ctx context.Context) ([]*NhStakeHomePointConfig, error)
}
customNhStakeHomePointConfigModel struct {
*defaultNhStakeHomePointConfigModel
}
)
func (m *customNhStakeHomePointConfigModel) All(ctx context.Context) ([]*NhStakeHomePointConfig, error) {
query := fmt.Sprintf("select %s from %s", nhStakeHomePointConfigRows, m.table)
var resp []*NhStakeHomePointConfig
err := m.conn.QueryRowsCtx(ctx, &resp, query)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
// NewNhStakeHomePointConfigModel returns a model for the database table.
func NewNhStakeHomePointConfigModel(conn sqlx.SqlConn) NhStakeHomePointConfigModel {
return &customNhStakeHomePointConfigModel{
defaultNhStakeHomePointConfigModel: newNhStakeHomePointConfigModel(conn),
}
}
func (m *customNhStakeHomePointConfigModel) withSession(session sqlx.Session) NhStakeHomePointConfigModel {
return NewNhStakeHomePointConfigModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,95 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"github.com/shopspring/decimal"
)
var (
nhStakeHomePointConfigFieldNames = builder.RawFieldNames(&NhStakeHomePointConfig{})
nhStakeHomePointConfigRows = strings.Join(nhStakeHomePointConfigFieldNames, ",")
nhStakeHomePointConfigRowsExpectAutoSet = strings.Join(stringx.Remove(nhStakeHomePointConfigFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhStakeHomePointConfigRowsWithPlaceHolder = strings.Join(stringx.Remove(nhStakeHomePointConfigFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhStakeHomePointConfigModel interface {
Insert(ctx context.Context, data *NhStakeHomePointConfig) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhStakeHomePointConfig, error)
Update(ctx context.Context, data *NhStakeHomePointConfig) error
Delete(ctx context.Context, id uint) error
}
defaultNhStakeHomePointConfigModel struct {
conn sqlx.SqlConn
table string
}
NhStakeHomePointConfig struct {
Id uint `db:"id"`
Title string `db:"title"` // 名称
Level uint `db:"level"` // 精灵等级,必须为连续的数字
Points uint `db:"points"` // 积分数量
Days decimal.Decimal `db:"days"` // 天数,为了测试方便,增加小数
RenewDays decimal.Decimal `db:"renew_days"` // 续存倒数天数,为了测试方便,增加小数
Status int8 `db:"status"` // 状态0=正常1=停用
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
}
)
func newNhStakeHomePointConfigModel(conn sqlx.SqlConn) *defaultNhStakeHomePointConfigModel {
return &defaultNhStakeHomePointConfigModel{
conn: conn,
table: "`nh_stake_home_point_config`",
}
}
func (m *defaultNhStakeHomePointConfigModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhStakeHomePointConfigModel) FindOne(ctx context.Context, id uint) (*NhStakeHomePointConfig, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhStakeHomePointConfigRows, m.table)
var resp NhStakeHomePointConfig
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhStakeHomePointConfigModel) Insert(ctx context.Context, data *NhStakeHomePointConfig) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, nhStakeHomePointConfigRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Title, data.Level, data.Points, data.Days, data.RenewDays, data.Status)
return ret, err
}
func (m *defaultNhStakeHomePointConfigModel) Update(ctx context.Context, data *NhStakeHomePointConfig) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhStakeHomePointConfigRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Title, data.Level, data.Points, data.Days, data.RenewDays, data.Status, data.Id)
return err
}
func (m *defaultNhStakeHomePointConfigModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,103 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
)
var _ NhStakePointsModel = (*customNhStakePointsModel)(nil)
type (
// NhStakePointsModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhStakePointsModel.
NhStakePointsModel interface {
nhStakePointsModel
WithSession(session sqlx.Session) NhStakePointsModel
FindCurrentLevel(ctx context.Context, roleId int64) (*NhStakePoints, error)
FindRenewLevel(ctx context.Context, roleId int64) (*NhStakePoints, error)
FindOverdueList(ctx context.Context) ([]*NhStakePoints, error)
SetOverdue(ctx context.Context, id uint) error
}
customNhStakePointsModel struct {
*defaultNhStakePointsModel
}
)
const (
PointsStakeStatusUnknown = 0 // 未知状态
PointsStakeStatusStaking = 1 // 质押中
PointsStakeStatusUpgraded = 2 // 已升级
PointsStakeStatusRenew = 3 // 已续约
PointsStakeStatusOverdue = 4 // 已过期
)
func (m *customNhStakePointsModel) SetOverdue(ctx context.Context, id uint) error {
update := fmt.Sprintf("update %s set `status` = %d where `id` = ? and `status` = %d", m.table, PointsStakeStatusOverdue, PointsStakeStatusStaking)
result, err := m.conn.ExecCtx(ctx, update, id)
if err != nil {
return err
}
rows, err := result.RowsAffected()
if err != nil {
return err
}
if rows == 0 {
return ErrNoRowUpdate
}
return nil
}
func (m *customNhStakePointsModel) FindOverdueList(ctx context.Context) ([]*NhStakePoints, error) {
query := fmt.Sprintf("select %s from %s where end_time <= ? and `status` = %d limit 100", nhStakePointsRows, m.table, PointsStakeStatusStaking)
var resp []*NhStakePoints
err := m.conn.QueryRowsCtx(ctx, &resp, query, time.Now())
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
func (m *customNhStakePointsModel) FindRenewLevel(ctx context.Context, roleId int64) (*NhStakePoints, error) {
query := fmt.Sprintf("select %s from %s where `role_id` = ? and start_time > ? and `status` = %d limit 1", nhStakePointsRows, m.table, PointsStakeStatusStaking)
var resp NhStakePoints
now := time.Now()
err := m.conn.QueryRowCtx(ctx, &resp, query, roleId, now)
switch {
case err == nil:
return &resp, nil
case errors.Is(err, sqlx.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *customNhStakePointsModel) FindCurrentLevel(ctx context.Context, roleId int64) (*NhStakePoints, error) {
query := fmt.Sprintf("select %s from %s where `role_id` = ? and start_time <= ? and end_time >= ? and (`status` = %d or `status` = %d) limit 1", nhStakePointsRows, m.table, PointsStakeStatusStaking, PointsStakeStatusRenew)
var resp NhStakePoints
now := time.Now()
err := m.conn.QueryRowCtx(ctx, &resp, query, roleId, now, now)
switch {
case err == nil:
return &resp, nil
case errors.Is(err, sqlx.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
// NewNhStakePointsModel returns a model for the database table.
func NewNhStakePointsModel(conn sqlx.SqlConn) NhStakePointsModel {
return &customNhStakePointsModel{
defaultNhStakePointsModel: newNhStakePointsModel(conn),
}
}
func (m *customNhStakePointsModel) WithSession(session sqlx.Session) NhStakePointsModel {
return NewNhStakePointsModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,93 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.6
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhStakePointsFieldNames = builder.RawFieldNames(&NhStakePoints{})
nhStakePointsRows = strings.Join(nhStakePointsFieldNames, ",")
nhStakePointsRowsExpectAutoSet = strings.Join(stringx.Remove(nhStakePointsFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhStakePointsRowsWithPlaceHolder = strings.Join(stringx.Remove(nhStakePointsFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhStakePointsModel interface {
Insert(ctx context.Context, data *NhStakePoints) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhStakePoints, error)
Update(ctx context.Context, data *NhStakePoints) error
Delete(ctx context.Context, id uint) error
}
defaultNhStakePointsModel struct {
conn sqlx.SqlConn
table string
}
NhStakePoints struct {
Id uint `db:"id"`
Uid uint `db:"uid"` // 用户id
RoleId uint64 `db:"role_id"` // 角色id
LevelId uint `db:"level_id"` // 档位id
Level uint `db:"level"` // 档位
Points uint `db:"points"` // 积分数量
StartTime time.Time `db:"start_time"` // 开始时间戳
EndTime time.Time `db:"end_time"` // 结束时间戳
Status int8 `db:"status"` // 状态1=质押中2=已升级3=已续约4=已过期
}
)
func newNhStakePointsModel(conn sqlx.SqlConn) *defaultNhStakePointsModel {
return &defaultNhStakePointsModel{
conn: conn,
table: "`nh_stake_points`",
}
}
func (m *defaultNhStakePointsModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhStakePointsModel) FindOne(ctx context.Context, id uint) (*NhStakePoints, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhStakePointsRows, m.table)
var resp NhStakePoints
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhStakePointsModel) Insert(ctx context.Context, data *NhStakePoints) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhStakePointsRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.LevelId, data.Level, data.Points, data.StartTime, data.EndTime, data.Status)
return ret, err
}
func (m *defaultNhStakePointsModel) Update(ctx context.Context, data *NhStakePoints) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhStakePointsRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.LevelId, data.Level, data.Points, data.StartTime, data.EndTime, data.Status, data.Id)
return err
}
func (m *defaultNhStakePointsModel) tableName() string {
return m.table
}

View File

@@ -17,19 +17,31 @@ const (
ErrGenerateUUid Reason = 1004 // 生成uuid错误
ErrGenerateToken Reason = 1005 // 生成token错误
ErrSystemConfig Reason = 1006 // 系统配置错误
GameServerError Reason = 1007 // 游戏服务器错误
// ======= 业务层错误20000~29999 =======
ErrUnknownLogicError Reason = 20000 // 未知的业务错误
ErrTaskNotFound Reason = 20001 // 任务不存在
ErrTaskAlreadyReward Reason = 20002 // 任务已领取
ErrTaskNotFinished Reason = 20003 // 任务未完成
ErrNotBindWallet Reason = 20004 // 未绑定钱包
ErrTaskOpenDateNotSet Reason = 20005 // 任务开放时间未设置
ErrTaskConfNotSet Reason = 20006 // 任务配置未设置
ErrUserNotFound Reason = 20007 // 用户不存在
ErrNftNotBelongToUser Reason = 20008 // NFT不属于用户
ErrInvalidApiKey Reason = 20009 // 无效的api key
ErrRoleNotFound Reason = 20010 // 角色不存在
ErrInvalidParam Reason = 20011 // 无效的参数
ErrNotBindRole Reason = 20012 // 未绑定角色
ErrUnknownLogicError Reason = 20000 // 未知的业务错误
ErrTaskNotFound Reason = 20001 // 任务不存在
ErrTaskAlreadyReward Reason = 20002 // 任务已领取
ErrTaskNotFinished Reason = 20003 // 任务未完成
ErrNotBindWallet Reason = 20004 // 未绑定钱包
ErrTaskOpenDateNotSet Reason = 20005 // 任务开放时间未设置
ErrTaskConfNotSet Reason = 20006 // 任务配置未设置
ErrUserNotFound Reason = 20007 // 用户不存在
ErrNftNotBelongToUser Reason = 20008 // NFT不属于用户
ErrInvalidApiKey Reason = 20009 // 无效的api key
ErrRoleNotFound Reason = 20010 // 角色不存在
ErrInvalidParam Reason = 20011 // 无效的参数
ErrNotBindRole Reason = 20012 // 未绑定角色
ErrPointLevelConfigNotFound Reason = 20013 // 找不到质押积分档位配置
ErrPointsStakeExist Reason = 20014 // 质押积分已存在
ErrPointStakeNotExist Reason = 20015 // 质押积分不存在
ErrInsufficientPoints Reason = 20016 // 用户积分不足
ErrInsufficientCastile Reason = 20017 // 用户Castile不足
ErrInsufficientElitePoints Reason = 20018 // 用户精英积分不足
ErrInsufficientKeys Reason = 20019 // 用户钥匙不足
ErrPointsStakeLevelNotAllow Reason = 20020 // 质押积分档位不允许
ErrPointsStakeHasRenew Reason = 20021 // 质押积分已续期
ErrPointsStakeNotInRenewTime Reason = 20022 // 质押积分不在续期时间范围内
)

126
internal/svc/game_action.go Normal file
View File

@@ -0,0 +1,126 @@
package svc
import (
"bytes"
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"io"
"math"
"net/http"
"nova_task/internal/model"
"nova_task/internal/pkg/encrypt/md5"
"strconv"
"strings"
"time"
)
// GetGameServerAddress 获取游戏服地址
func (s *ServiceContext) GetGameServerAddress(ctx context.Context, roleID int64) (string, map[string]any, error) {
agentIDServerID := math.Floor(float64(roleID)/100000000) / 100000
splitStr := cast.ToString(agentIDServerID)
splitParts := []string{"0", "0"}
if parts := strings.Split(splitStr, "."); len(parts) == 2 {
splitParts = parts
}
serverInfo := map[string]any{}
originalAgentID, _ := strconv.ParseInt(splitParts[0], 10, 64)
originalServerID, _ := strconv.ParseInt(splitParts[1], 10, 64)
serverInfo["original_agent_id"] = originalAgentID
serverInfo["original_server_id"] = originalServerID
agentId, serverServerId, err := s.MergeServerModel.FinalServer(ctx, originalAgentID, originalServerID)
if err != nil {
return "", serverInfo, err
}
serverInfo["agent_id"] = agentId
serverInfo["server_id"] = serverServerId
gs, err := s.ServersModel.GetGameServer(ctx, agentId, serverServerId)
if err != nil {
return "", serverInfo, err
}
serverInfo["web_port"] = gs.WebPort
serverInfo["server_ip"] = gs.ServerIP
serverInfo["public_server_ip"] = gs.PublicServerIP
return fmt.Sprintf("http://%s:%d", gs.PublicServerIP, gs.WebPort), serverInfo, nil
}
func (s *ServiceContext) GameAction(ctx context.Context, roleId int64, action string, args map[string]any) (any, error) {
//return map[string]any{
// "data": 1,
// "ret": 1,
//}, nil
addr, serverInfo, err := s.GetGameServerAddress(ctx, roleId)
if err != nil {
return nil, err
}
now := time.Now().Unix()
request := map[string]any{
"nova_time": now,
"nova_token": md5.Md5str(fmt.Sprintf("%d%s", now, s.Config.NovaToken)),
"nova_action": action,
"role_id": roleId,
}
for k, v := range args {
if _, ok := request[k]; ok {
continue
}
request[k] = v
}
data, _ := json.Marshal(request)
httpReq, err := http.NewRequest(http.MethodPost, addr, bytes.NewReader(data))
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json")
httpResp, err := http.DefaultClient.Do(httpReq)
if err != nil {
s.ErrLog(ctx, action, addr, serverInfo, request, nil)
return nil, err
}
respData, _ := io.ReadAll(httpResp.Body)
resp := map[string]any{}
if err := json.Unmarshal(respData, &resp); err != nil {
s.ErrLog(ctx, action, addr, serverInfo, request, string(respData))
return nil, err
}
if cast.ToInt64(resp["ret"]) != 1 {
s.ErrLog(ctx, action, addr, serverInfo, request, resp)
return resp, fmt.Errorf("game action msg= %s, data=%v", cast.ToString(resp["msg"]), cast.ToString(resp["data"]))
}
return resp, nil
}
func (s *ServiceContext) ErrLog(ctx context.Context, action, url string, serverInfo, req, resp any) {
var marshal = func(v any) string {
if v == nil {
return ""
}
if vv, ok := v.(string); ok {
return vv
}
data, _ := json.Marshal(v)
return string(data)
}
_, err := s.RequestServerLogModel.Insert(ctx, &model.NhRequestServerLog{
Action: action,
Url: url,
ServerInfo: marshal(serverInfo),
ReqData: marshal(req),
ResData: marshal(resp),
CreateTime: sql.NullTime{Valid: true, Time: time.Now()},
})
if err != nil {
logx.Errorw("insert request server log error", logx.Field("err", err), logx.Field("action", action), logx.Field("url", url), logx.Field("server_info", serverInfo), logx.Field("req", req), logx.Field("resp", resp))
}
}

84
internal/svc/model.go Normal file
View File

@@ -0,0 +1,84 @@
package svc
import (
"github.com/zeromicro/go-zero/core/stores/sqlx"
"nova_task/internal/model"
)
type dbModel struct {
TaskModel model.NhTaskModel
taskAssetModel model.NhTaskAssetModel
taskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel
PromoteBindModel model.NhPromoteBindModel
TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
WalletModel model.NhWalletModel
ConfigModel model.NhSystemConfigModel
NftHolderModel model.NhNftHolderModel
NftHolderChangeLogModel model.NhNftHolderChangeLogModel
StakeNftModel model.NhTaskNftStakeModel
OldStakeNftModel model.NhNftStakeModel
StakeNftLogModel model.NhTaskNftStakeLogModel
StakeRewardModel model.NhTaskNftStakeRewardModel
GamePitModel model.NhGamePitModel
StakePropertyModel model.NhNftStakePropertyModel
EmailRewardModel model.NhEmailRewardModel
AmbassadorModel model.NhTaskAmbassadorModel
GameReportModel model.NhGameReportModel
RoleModel model.NhRoleModel
GamesPropertyModel model.NhGamesPropertyLogsModel
AirdropModel model.NhAirdropLogModel
PioneerRewardsModel model.NhPioneerRewardsModel
MergeServerModel model.MsMergeServersModel
GameServerModel model.MsGameServerModel
ServersModel model.MgServersModel
GameServerNotifyModel model.NhGameServerNotifyModel
RequestServerLogModel model.NhRequestServerLogModel
StakePointConfigModel model.NhStakeHomePointConfigModel
StakePointsModel model.NhStakePointsModel
}
func newDBModel(dbConn, gameConn sqlx.SqlConn, configModel model.NhSystemConfigModel) *dbModel {
return &dbModel{
TaskModel: model.NewNhTaskModel(dbConn),
taskAssetModel: model.NewNhTaskAssetModel(dbConn),
taskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn),
PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
TouristBindModel: model.NewNhTouristBindModel(dbConn),
WalletModel: model.NewNhWalletModel(dbConn),
ConfigModel: configModel,
NftHolderModel: model.NewNhNftHolderModel(dbConn),
NftHolderChangeLogModel: model.NewNhNftHolderChangeLogModel(dbConn),
StakeNftModel: model.NewNhTaskNftStakeModel(dbConn),
OldStakeNftModel: model.NewNhNftStakeModel(dbConn),
StakeRewardModel: model.NewNhTaskNftStakeRewardModel(dbConn),
GamePitModel: model.NewNhGamePitModel(dbConn),
StakePropertyModel: model.NewNhNftStakePropertyModel(dbConn),
EmailRewardModel: model.NewNhEmailRewardModel(dbConn),
AmbassadorModel: model.NewNhTaskAmbassadorModel(dbConn),
GameReportModel: model.NewNhGameReportModel(dbConn),
RoleModel: model.NewNhRoleModel(dbConn),
GamesPropertyModel: model.NewNhGamesPropertyLogsModel(dbConn),
AirdropModel: model.NewNhAirdropLogModel(dbConn),
PioneerRewardsModel: model.NewNhPioneerRewardsModel(dbConn),
StakePointConfigModel: model.NewNhStakeHomePointConfigModel(dbConn),
StakePointsModel: model.NewNhStakePointsModel(dbConn),
GameServerNotifyModel: model.NewNhGameServerNotifyModel(dbConn),
RequestServerLogModel: model.NewNhRequestServerLogModel(dbConn),
MergeServerModel: model.NewMsMergeServersModel(gameConn),
GameServerModel: model.NewMsGameServerModel(gameConn),
ServersModel: model.NewMgServersModel(gameConn),
}
}

View File

@@ -22,32 +22,7 @@ import (
type ServiceContext struct {
Config config.Config
TaskModel model.NhTaskModel
taskAssetModel model.NhTaskAssetModel
taskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel
PromoteBindModel model.NhPromoteBindModel
TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
WalletModel model.NhWalletModel
ConfigModel model.NhSystemConfigModel
NftHolderModel model.NhNftHolderModel
NftHolderChangeLogModel model.NhNftHolderChangeLogModel
StakeNftModel model.NhTaskNftStakeModel
OldStakeNftModel model.NhNftStakeModel
StakeNftLogModel model.NhTaskNftStakeLogModel
StakeRewardModel model.NhTaskNftStakeRewardModel
GamePitModel model.NhGamePitModel
StakePropertyModel model.NhNftStakePropertyModel
EmailRewardModel model.NhEmailRewardModel
AmbassadorModel model.NhTaskAmbassadorModel
GameReportModel model.NhGameReportModel
RoleModel model.NhRoleModel
GamesPropertyModel model.NhGamesPropertyLogsModel
AirdropModel model.NhAirdropLogModel
PioneerRewardsModel model.NhPioneerRewardsModel
*dbModel
ApiKeyCheck rest.Middleware
AdminSecretCheck rest.Middleware
@@ -61,44 +36,18 @@ type ServiceContext struct {
func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn()
gameConn := c.GameDB.Conn()
configModel := model.NewNhSystemConfigModel(dbConn, c.Cache)
return &ServiceContext{
Config: c,
TaskModel: model.NewNhTaskModel(dbConn),
taskAssetModel: model.NewNhTaskAssetModel(dbConn),
taskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn),
PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
TouristBindModel: model.NewNhTouristBindModel(dbConn),
WalletModel: model.NewNhWalletModel(dbConn),
ConfigModel: configModel,
NftHolderModel: model.NewNhNftHolderModel(dbConn),
NftHolderChangeLogModel: model.NewNhNftHolderChangeLogModel(dbConn),
StakeNftModel: model.NewNhTaskNftStakeModel(dbConn),
OldStakeNftModel: model.NewNhNftStakeModel(dbConn),
StakeRewardModel: model.NewNhTaskNftStakeRewardModel(dbConn),
GamePitModel: model.NewNhGamePitModel(dbConn),
StakePropertyModel: model.NewNhNftStakePropertyModel(dbConn),
EmailRewardModel: model.NewNhEmailRewardModel(dbConn),
AmbassadorModel: model.NewNhTaskAmbassadorModel(dbConn),
GameReportModel: model.NewNhGameReportModel(dbConn),
RoleModel: model.NewNhRoleModel(dbConn),
GamesPropertyModel: model.NewNhGamesPropertyLogsModel(dbConn),
AirdropModel: model.NewNhAirdropLogModel(dbConn),
PioneerRewardsModel: model.NewNhPioneerRewardsModel(dbConn),
Config: c,
dbModel: newDBModel(dbConn, gameConn, configModel),
ApiKeyCheck: middleware.NewApiKeyCheckMiddleware(configModel).Handle,
AdminSecretCheck: middleware.NewAdminSecretCheckMiddleware(configModel).Handle,
Game7ApiKeyCheck: middleware.NewGame7ApiKeyCheckMiddleware(configModel).Handle,
KGeNApiKeyCheck: middleware.NewKGeNApiKeyCheckMiddleware(configModel).Handle,
Earn: c.Earn.BuildEarnClient(),
DBConn: dbConn,
Redis: redis.MustNewRedis(c.Redis),
DBConn: dbConn,
Earn: c.Earn.BuildEarnClient(),
Redis: redis.MustNewRedis(c.Redis),
}
}
@@ -173,6 +122,35 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
recordModel = s.taskAssetRecordModel
gamesPropertyModel = s.GamesPropertyModel
}
if amount.LessThan(decimal.Zero) {
uAsset, err := assetModel.FindOneByUid(ctx, int(uid))
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errs.New(errs.ErrInsufficientPoints, "insufficient point")
}
return errs.New(errs.ErrDatabaseOperate, err)
}
switch asset {
case consts.AssetType_Points:
if uAsset.Points.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientPoints, "insufficient point")
}
case consts.AssetType_Castile:
if uAsset.Castile.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientCastile, "insufficient castile")
}
case consts.AssetType_Elite_Points:
if uAsset.ElitePoints.LessThan(amount.Abs()) {
return errs.New(errs.ErrInsufficientElitePoints, "insufficient elite points")
}
case consts.AssetType_Keys:
if uAsset.Keys < int(amount.IntPart()) {
return errs.New(errs.ErrInsufficientKeys, "insufficient keys")
}
default:
return errors.New("unknown asset type")
}
}
var err error
switch asset {
case consts.AssetType_Points:
@@ -186,7 +164,7 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
case consts.AssetType_Property:
_, err = gamesPropertyModel.Insert(ctx, &model.NhGamesPropertyLogs{
Uid: uid,
RoleId: int64(role),
RoleId: role,
PropertyId: assetId,
PropertyNum: uint(amount.IntPart()),
})
@@ -234,6 +212,7 @@ func (s *ServiceContext) AddUserAssetWithSession(ctx context.Context, session sq
return s.AddUserAssetWithSession(ctx, session, pb.ShareUid, 0, asset, assetId, rewardAmount, fmt.Sprintf("分享返利,比例%s", rated.String()), 7, uid, false)
}
// AddUserAsset 增加用户资产
func (s *ServiceContext) AddUserAsset(ctx context.Context, uid uint, role int64, asset consts.AssetType, assetId string, amount decimal.Decimal, remark string, eventId uint64, provideUid uint, referralReward bool) error {
return s.AddUserAssetWithSession(ctx, nil, uid, role, asset, assetId, amount, remark, eventId, provideUid, referralReward)
}

View File

@@ -55,6 +55,17 @@ type Game7TaskCheckReq struct {
Type int8 `form:"type"` // 1.是否在官网注册并链接钱包(是/否) 2.是否有超过两个以上的英雄(是/否) 3.是否消耗召唤券召唤了新英雄(是/否) 4. 是否在游戏内绑定了官网账号(是/否) 5. 是否有一个31级以上的英雄是/否) 6. 是否完成了主线第一章(是/否)
}
type GameActionReq struct {
RoleId int64 `json:"role_id"`
Action string `json:"action"`
}
type GameActionResp struct {
Ret int `json:"ret"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
type GetCommunityListResp struct {
CommunityList []Community `json:"community_list"` // 社区列表
}
@@ -63,6 +74,17 @@ type GetNftListReq struct {
WalletAddress string `form:"wallet_address"`
}
type GetStakeLevelListReq struct {
RoleID int64 `form:"role_id"` // 角色id
}
type GetStakeLevelListResp struct {
State int `json:"state"` // 状态1表示已开启可质押 0表示不可质押
Staking *StakeLevel `json:"staking,optional"` // 质押中的档位信息
RenewLevel *StakeLevel `json:"renew_level,optional"` // 已续约的档位信息
Levels []PointStakeLevel `json:"levels"` // 档位列表
}
type GetTaskListReq struct {
CommunityId uint `form:"community_id,optional"` // 所属社区ID
}
@@ -108,6 +130,15 @@ type PioneerReward struct {
Total float64 `json:"total"` // 总额
}
type PointStakeLevel struct {
Id int `json:"id"` // 档位id
Title string `json:"title"` // 档位标题
Level int `json:"level"` // 精灵等级
Points int `json:"points"` // 积分数量
Days float64 `json:"days"` // 质押天数
RenewDays float64 `json:"renew_days"` // 续期天数
}
type Result struct {
IsValid bool `json:"isValid"`
}
@@ -116,11 +147,29 @@ type StakeByAddressReq struct {
Address []string `json:"address"`
}
type StakeLevel struct {
Id int `json:"id"`
Title string `json:"title"` // 档位标题
Level int `json:"level"` // 精灵等级
Points int `json:"points"` // 积分数量
Days float64 `json:"days"` // 质押天数
RenewDays float64 `json:"renew_days"` // 续期天数
StartTime string `json:"start_time"` // 开始时间
EndTime string `json:"end_time"` // 结束时间
CanRenew bool `json:"can_renew"` // 是否可续约
}
type StakeNftList struct {
RoleId uint64 `json:"role_id,optional"` // 角色id
TokenIds []string `json:"token_ids"` // nft列表
}
type StakePointReq struct {
RoleID int64 `json:"role_id"` // 角色id
LevelId int `json:"level_id"` // 档位id
Action int `json:"action"` // 操作类型1表示质押2表示升级质押 3表示续约
}
type StakeReward struct {
Date string `json:"date"` // 日期
Reward float64 `json:"reward"` // 当日发放奖励