optimize and add cdkey
This commit is contained in:
		
							parent
							
								
									a2897f288e
								
							
						
					
					
						commit
						bc368e96cf
					
				@ -27,7 +27,7 @@ func initCommonResourcesRepo(db *gorm.DB) {
 | 
			
		||||
	r(consts.ResourcesName_MailRole, "个人邮件", repo.NewCommonResourceRepo(db, &model.RoleMail{}), ShowMethod_Get|ShowMethod_Post)     // 个人邮件发放就没法撤回?
 | 
			
		||||
	r(consts.ResourcesName_MailGlobal, "全服邮件", repo.NewCommonResourceRepo(db, &model.GlobalMail{}), ShowMethod_Get|ShowMethod_Post) // 直接删除,别修改了,玩家收到的更乱
 | 
			
		||||
	r(consts.ResourcesName_Notice, "公告", repo.NewCommonResourceRepo(db, &model.Notice{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
 | 
			
		||||
	r(consts.ResourcesName_RewardCode, "奖励码", repo.NewCommonResourceRepo(db, &model.RewardCode{}), ShowMethod_Get)
 | 
			
		||||
	r(consts.ResourcesName_RewardCode, "奖励码", repo.NewCommonResourceRepo(db, &model.CDKey{}), ShowMethod_Get)
 | 
			
		||||
	r(consts.ResourcesName_DevicePush, "设备推送", repo.NewCommonResourceRepo(db, &model.DevicePush{}), ShowMethod_Get)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								admin/apps/game/domain/entity/cdkey.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								admin/apps/game/domain/entity/cdkey.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
package entity
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"admin/apps/game/model"
 | 
			
		||||
	"admin/lib/cdkey"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var MaxKeyNum = 100000 // 每个批次直接搞10w个,不然运营想补加码,算法又要一开始定好数量
 | 
			
		||||
 | 
			
		||||
type CDKey struct {
 | 
			
		||||
	Po *model.CDKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewCDKey(po *model.CDKey) *CDKey {
 | 
			
		||||
	return &CDKey{
 | 
			
		||||
		Po: po,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *CDKey) GenerateKeys() []string {
 | 
			
		||||
	return cdkey.GenerateAll(c.Po.ID, MaxKeyNum)[:c.Po.CodeNum]
 | 
			
		||||
}
 | 
			
		||||
@ -16,6 +16,7 @@ var projectsResourceHookMgr = map[string]map[string]any{
 | 
			
		||||
		consts.ResourcesName_Ban:        &smdl.BanHook{},        // 所有角色走神魔大陆api直接获取
 | 
			
		||||
		consts.ResourcesName_MailGlobal: &smdl.MailGlobalHook{}, // 所有角色走神魔大陆api直接获取
 | 
			
		||||
		consts.ResourcesName_MailRole:   &smdl.MailRoleHook{},   // 所有角色走神魔大陆api直接获取
 | 
			
		||||
		consts.ResourcesName_WhiteList:  &smdl.WhitelistHook{},  // 所有角色走神魔大陆api直接获取
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,12 +11,12 @@ type Items struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (items *Items) GetItems(projectInfo *entity.Project) ([]*dto.CommonDtoFieldChoice, error) {
 | 
			
		||||
	return []*dto.CommonDtoFieldChoice{
 | 
			
		||||
		{Desc: "黄金战甲", Value: 123, Type: 1},
 | 
			
		||||
		{Desc: "黄金头盔", Value: 234, Type: 1},
 | 
			
		||||
		{Desc: "黄金大刀", Value: 346, Type: 1},
 | 
			
		||||
		{Desc: "白银大刀", Value: 346, Type: 1},
 | 
			
		||||
	}, nil
 | 
			
		||||
	//return []*dto.CommonDtoFieldChoice{
 | 
			
		||||
	//	{Desc: "黄金战甲", Value: 123, Type: 1},
 | 
			
		||||
	//	{Desc: "黄金头盔", Value: 234, Type: 1},
 | 
			
		||||
	//	{Desc: "黄金大刀", Value: 346, Type: 1},
 | 
			
		||||
	//	{Desc: "白银大刀", Value: 346, Type: 1},
 | 
			
		||||
	//}, nil
 | 
			
		||||
	alisrvAddr := projectInfo.GetApiAddr()
 | 
			
		||||
	if alisrvAddr == "" {
 | 
			
		||||
		return nil, errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								admin/apps/game/domain/projects/smdl/whitelist.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								admin/apps/game/domain/projects/smdl/whitelist.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
package smdl
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"admin/apps/game/domain/entity"
 | 
			
		||||
	"admin/apps/game/model"
 | 
			
		||||
	"admin/apps/game/model/dto"
 | 
			
		||||
	"admin/internal/errcode"
 | 
			
		||||
	"admin/lib/httpclient"
 | 
			
		||||
	"net/url"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WhitelistHook struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *WhitelistHook) Create(projectInfo *entity.Project, resource string, dtoObj dto.CommonDtoValues) error {
 | 
			
		||||
	alisrvAddr := projectInfo.GetApiAddr()
 | 
			
		||||
	if alisrvAddr == "" {
 | 
			
		||||
		return errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	et := (&entity.CommonResource{}).FromPo(&model.RoleMail{}).FromDto(dtoObj)
 | 
			
		||||
	whiteInfo := et.ToPo().(*model.WhiteList)
 | 
			
		||||
 | 
			
		||||
	params := &url.Values{}
 | 
			
		||||
	params.Add("cmd_data", "OpWhitelist")
 | 
			
		||||
	params.Add("type", whiteInfo.WType)
 | 
			
		||||
	params.Add("value", whiteInfo.Value)
 | 
			
		||||
	params.Add("op", "add")
 | 
			
		||||
	params.Add("server", whiteInfo.ServerConfID)
 | 
			
		||||
 | 
			
		||||
	rsp := make(map[string]any)
 | 
			
		||||
	err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errcode.New(errcode.ServerError, "发送新增白名单请求:%+v错误:%v", whiteInfo, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hook *WhitelistHook) Delete(projectInfo *entity.Project, resource string, dtoObj dto.CommonDtoValues) error {
 | 
			
		||||
	alisrvAddr := projectInfo.GetApiAddr()
 | 
			
		||||
	if alisrvAddr == "" {
 | 
			
		||||
		return errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	et := (&entity.CommonResource{}).FromPo(&model.RoleMail{}).FromDto(dtoObj)
 | 
			
		||||
	whiteInfo := et.ToPo().(*model.WhiteList)
 | 
			
		||||
 | 
			
		||||
	params := &url.Values{}
 | 
			
		||||
	params.Add("cmd_data", "OpWhitelist")
 | 
			
		||||
	params.Add("type", whiteInfo.WType)
 | 
			
		||||
	params.Add("value", whiteInfo.Value)
 | 
			
		||||
	params.Add("op", "remove")
 | 
			
		||||
	params.Add("server", whiteInfo.ServerConfID)
 | 
			
		||||
 | 
			
		||||
	rsp := make(map[string]any)
 | 
			
		||||
	err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errcode.New(errcode.ServerError, "发送删除白名单请求:%+v错误:%v", whiteInfo, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -11,7 +11,7 @@ func init() {
 | 
			
		||||
 | 
			
		||||
// Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
 | 
			
		||||
type Account struct {
 | 
			
		||||
	ProjectId       int
 | 
			
		||||
	ProjectId       int       `gorm:"index:idx_project_id"`
 | 
			
		||||
	Account         string    `name:"账号" json:"account" where:"eq"`
 | 
			
		||||
	ServerConfId    string    `name:"区服id" json:"serveId" where:"eq"`
 | 
			
		||||
	RoleIds         []string  `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								admin/apps/game/model/cdkey.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								admin/apps/game/model/cdkey.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
package model
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"admin/apps/game/model/dto"
 | 
			
		||||
	"admin/internal/db"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	db.RegisterTableModels(CDKey{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CDKey struct {
 | 
			
		||||
	ID             int               `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId      int               `gorm:"index:idx_project_id"`
 | 
			
		||||
	Desc           string            `name:"礼包说明" required:"true"`
 | 
			
		||||
	ServerIDs      []string          `gorm:"type:json;serializer:json" name:"区服" type:"[]string" choices:"GetChoiceServers" multi_choice:"true"`
 | 
			
		||||
	CodeType       int               `name:"礼包类型" required:"true" choices:"GetCodeTypeChoices"`
 | 
			
		||||
	Code           string            `name:"礼包码" desc:"一码通用才配置"`
 | 
			
		||||
	CodeNum        int               `name:"礼包数量" desc:"一码一用才配置"`
 | 
			
		||||
	ValidStartTime time.Time         `name:"生效起始时间"`
 | 
			
		||||
	ValidEndTime   time.Time         `name:"生效结束时间"`
 | 
			
		||||
	RewardList     []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
 | 
			
		||||
 | 
			
		||||
	CreatedAt time.Time `readonly:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lm *CDKey) TableName() string {
 | 
			
		||||
	return "cdkey"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *CDKey) GetId() int {
 | 
			
		||||
	return m.ID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *CDKey) GetCodeTypeChoices() []*dto.CommonDtoFieldChoice {
 | 
			
		||||
	return []*dto.CommonDtoFieldChoice{
 | 
			
		||||
		{Desc: "一码通用", Value: 0},
 | 
			
		||||
		{Desc: "一码一用", Value: 1},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								admin/apps/game/model/cdkey_used.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								admin/apps/game/model/cdkey_used.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
package model
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"admin/internal/db"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	db.RegisterTableModels(CDKeyUsed{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CDKeyUsed struct {
 | 
			
		||||
	ID        int       `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int       `gorm:"index:idx_project_id"`
 | 
			
		||||
	ServerID  string    `name:"所属区服" choices:"GetChoiceServers" required:"true" where:"eq"`
 | 
			
		||||
	Account   string    `gorm:"type:varchar(255);index:idx_account"`
 | 
			
		||||
	RoleID    string    `gorm:"type:varchar(255);index:idx_role_id"`
 | 
			
		||||
	RoleName  string    `gorm:"type:varchar(255)"`
 | 
			
		||||
	Key       string    `gorm:"type:varchar(255);index:idx_key"`
 | 
			
		||||
	CreatedAt time.Time `readonly:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lm *CDKeyUsed) TableName() string {
 | 
			
		||||
	return "cdkey_used"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *CDKeyUsed) GetId() int {
 | 
			
		||||
	return m.ID
 | 
			
		||||
}
 | 
			
		||||
@ -11,8 +11,8 @@ func init() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GlobalMail struct {
 | 
			
		||||
	ID        int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int
 | 
			
		||||
	ID        int               `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int               `gorm:"index:idx_project_id"`
 | 
			
		||||
	ServerIDs []string          `gorm:"type:json;serializer:json" name:"区服" type:"[]string" choices:"GetChoiceServers" multi_choice:"true"`
 | 
			
		||||
	Title     string            `name:"邮件标题" required:"true"`
 | 
			
		||||
	Content   string            `name:"邮件内容" required:"true"`
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,8 @@ func init() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Notice struct {
 | 
			
		||||
	ID        int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int
 | 
			
		||||
	ID        int       `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int       `gorm:"index:idx_project_id"`
 | 
			
		||||
	ServerIDs []int     `gorm:"type:json;serializer:json" name:"公告生效服务器" desc:"为空表示所有服" choices:"GetChoiceServers"`
 | 
			
		||||
	Content   string    `name:"公告内容" required:"true"`
 | 
			
		||||
	StartAt   time.Time `name:"开始时间" required:"true"`
 | 
			
		||||
 | 
			
		||||
@ -1,27 +0,0 @@
 | 
			
		||||
package model
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"admin/internal/db"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	db.RegisterTableModels(RewardCode{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RewardCode struct {
 | 
			
		||||
	ID        int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int
 | 
			
		||||
	Group     int `name:"奖励码组"`
 | 
			
		||||
	Code      int `name:"奖励码"`
 | 
			
		||||
 | 
			
		||||
	CreatedAt time.Time `readonly:"true"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lm *RewardCode) TableName() string {
 | 
			
		||||
	return "reward_code"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *RewardCode) GetId() int {
 | 
			
		||||
	return m.ID
 | 
			
		||||
}
 | 
			
		||||
@ -17,8 +17,8 @@ type MailAttachItem struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RoleMail struct {
 | 
			
		||||
	ID        int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int
 | 
			
		||||
	ID        int               `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId int               `gorm:"index:idx_project_id"`
 | 
			
		||||
	RoleIDs   []string          `gorm:"type:json;serializer:json" name:"生效的角色id" desc:"生效的角色id,逗号分隔多个" required:"true"`
 | 
			
		||||
	ServerID  string            `name:"所属区服" choices:"GetChoiceServers" required:"true" where:"eq"`
 | 
			
		||||
	Title     string            `name:"邮件标题" required:"true"`
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,9 @@ func init() {
 | 
			
		||||
type WhiteList struct {
 | 
			
		||||
	ID           int    `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	ProjectId    int    `gorm:"uniqueIndex:idx_whitelist"`
 | 
			
		||||
	ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" choices:"GetChoiceServers" where:"eq"`
 | 
			
		||||
	Account      string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账户" required:"true"`
 | 
			
		||||
	Desc         string `name:"描述"`
 | 
			
		||||
	ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_whitelist;index:idx_server" name:"区服id" required:"true" choices:"GetChoiceServers" where:"eq"`
 | 
			
		||||
	WType        string `name:"白名单类型" desc:"账号或者ip" required:"true" choices:"GetWhitelistTypeChoices"`
 | 
			
		||||
	Value        string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账户" required:"true"`
 | 
			
		||||
 | 
			
		||||
	CreatedAt time.Time `readonly:"true" where:"range"`
 | 
			
		||||
}
 | 
			
		||||
@ -31,3 +31,10 @@ func (m *WhiteList) GetId() int {
 | 
			
		||||
func (m *WhiteList) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice {
 | 
			
		||||
	return getChoiceServers(project)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *WhiteList) GetWhitelistTypeChoices(project *Project) []*dto.CommonDtoFieldChoice {
 | 
			
		||||
	return []*dto.CommonDtoFieldChoice{
 | 
			
		||||
		{Desc: "IP", Value: "ip"},
 | 
			
		||||
		{Desc: "账号", Value: "account"},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,11 @@ import (
 | 
			
		||||
 | 
			
		||||
func (ctl *controller) CommonList(ctx *context.WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error {
 | 
			
		||||
	projectId, resource := getCtxURIProjectIdAndResource(ctx)
 | 
			
		||||
	list, err := ctl.svc.CommonList(ctx, projectId, resource, params)
 | 
			
		||||
 | 
			
		||||
	ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId)
 | 
			
		||||
	ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserName)
 | 
			
		||||
 | 
			
		||||
	list, err := ctl.svc.CommonList(ctx1, projectId, resource, params)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -20,7 +24,7 @@ func (ctl *controller) CommonPost(ctx *context.WebContext, params *dto.CommonPos
 | 
			
		||||
	projectId, resource := getCtxURIProjectIdAndResource(ctx)
 | 
			
		||||
 | 
			
		||||
	ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId)
 | 
			
		||||
	ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserId)
 | 
			
		||||
	ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserName)
 | 
			
		||||
 | 
			
		||||
	newObj, err := ctl.svc.CommonPost(ctx1, projectId, resource, *params.Dto)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -32,7 +36,11 @@ func (ctl *controller) CommonPost(ctx *context.WebContext, params *dto.CommonPos
 | 
			
		||||
 | 
			
		||||
func (ctl *controller) CommonPut(ctx *context.WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error {
 | 
			
		||||
	projectId, resource := getCtxURIProjectIdAndResource(ctx)
 | 
			
		||||
	err := ctl.svc.CommonPut(ctx, projectId, resource, *params.Dto)
 | 
			
		||||
 | 
			
		||||
	ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId)
 | 
			
		||||
	ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserName)
 | 
			
		||||
 | 
			
		||||
	err := ctl.svc.CommonPut(ctx1, projectId, resource, *params.Dto)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -42,7 +50,11 @@ func (ctl *controller) CommonPut(ctx *context.WebContext, params *dto.CommonPutR
 | 
			
		||||
 | 
			
		||||
func (ctl *controller) CommonDelete(ctx *context.WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error {
 | 
			
		||||
	projectId, resource := getCtxURIProjectIdAndResource(ctx)
 | 
			
		||||
	err := ctl.svc.CommonDelete(ctx, projectId, resource, params.Id)
 | 
			
		||||
 | 
			
		||||
	ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId)
 | 
			
		||||
	ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserName)
 | 
			
		||||
 | 
			
		||||
	err := ctl.svc.CommonDelete(ctx1, projectId, resource, params.Id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -12,14 +12,14 @@ func init() {
 | 
			
		||||
 | 
			
		||||
// History 用户执行历史
 | 
			
		||||
type History struct {
 | 
			
		||||
	ID         int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	UserId     int
 | 
			
		||||
	UserName   string
 | 
			
		||||
	ProjectId  int
 | 
			
		||||
	Resource   string
 | 
			
		||||
	Method     string
 | 
			
		||||
	Data       string `gorm:"type:longtext"`
 | 
			
		||||
	CreateTime time.Time
 | 
			
		||||
	ID        int `gorm:"primarykey" readonly:"true"`
 | 
			
		||||
	UserId    int
 | 
			
		||||
	UserName  string
 | 
			
		||||
	ProjectId int
 | 
			
		||||
	Resource  string
 | 
			
		||||
	Method    string
 | 
			
		||||
	Data      string `gorm:"type:longtext"`
 | 
			
		||||
	CreatedAt time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *History) TableName() string {
 | 
			
		||||
 | 
			
		||||
@ -14,10 +14,12 @@ type Server struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(svc *service.Service) *Server {
 | 
			
		||||
	return &Server{
 | 
			
		||||
	srv := &Server{
 | 
			
		||||
		svc: svc,
 | 
			
		||||
		ctl: newController(svc),
 | 
			
		||||
	}
 | 
			
		||||
	srv.jobsSubscribe()
 | 
			
		||||
	return srv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (srv *Server) jobsSubscribe() {
 | 
			
		||||
@ -30,6 +32,7 @@ func (srv *Server) subscriberHandlerUserExecute(msg *event.Msg) {
 | 
			
		||||
	err := json.Unmarshal(msg.Payload, msgHistory)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		xlog.Errorf("unmarshal msg(%+v) err:%v", string(msg.Payload), err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	po.UserId = msgHistory.UserId
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ type WebContext struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWebContext(rawCtx *gin.Context) web.IContext {
 | 
			
		||||
	return &WebContext{rawCtx: rawCtx}
 | 
			
		||||
	return &WebContext{Context: context.Background(), rawCtx: rawCtx}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *WebContext) ExtractHeader() error {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								admin/lib/cdkey/bitmap.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								admin/lib/cdkey/bitmap.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
package cdkey
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type bitmap struct {
 | 
			
		||||
	size int
 | 
			
		||||
	set  int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newBitmap(size int, set int64) *bitmap {
 | 
			
		||||
	if size < 0 || size > 63 {
 | 
			
		||||
		panic("size must be between 0 and 63")
 | 
			
		||||
	}
 | 
			
		||||
	if size == 0 {
 | 
			
		||||
		size = 32
 | 
			
		||||
	}
 | 
			
		||||
	m := &bitmap{size: size, set: set}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) Get(index int) bool {
 | 
			
		||||
	return m.GetInt(index) != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) GetInt(index int) int64 {
 | 
			
		||||
	if index < 0 || index >= m.size {
 | 
			
		||||
		panic(fmt.Errorf("index out of range:%v", index))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if m.set&(1<<uint(index)) != 0 {
 | 
			
		||||
		return 1
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) Set(index int, value bool) {
 | 
			
		||||
	if index < 0 || index >= m.size {
 | 
			
		||||
		panic(fmt.Errorf("index out of range:%v", index))
 | 
			
		||||
	}
 | 
			
		||||
	if value {
 | 
			
		||||
		m.set |= 1 << uint(index)
 | 
			
		||||
	} else {
 | 
			
		||||
		m.set &^= 1 << uint(index)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) Clear() {
 | 
			
		||||
	m.set = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) toInt64() int64 {
 | 
			
		||||
	return m.set
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *bitmap) GetSize() int {
 | 
			
		||||
	return m.size
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								admin/lib/cdkey/cdkey.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								admin/lib/cdkey/cdkey.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,124 @@
 | 
			
		||||
package cdkey
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 奖励码模块,从神魔大陆java代码移植过来的
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
func GenerateAll(batch int, totalCount int) []string {
 | 
			
		||||
	keyList := make([]string, 0, totalCount)
 | 
			
		||||
	for i := 0; i < totalCount; i++ {
 | 
			
		||||
		codeKey := GenerateOne(batch, totalCount, i)
 | 
			
		||||
		keyList = append(keyList, codeKey)
 | 
			
		||||
	}
 | 
			
		||||
	return keyList
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GenerateOne(batch int, totalCount int, curNo int) string {
 | 
			
		||||
	base := MAXNUM / totalCount
 | 
			
		||||
	numId := curNo
 | 
			
		||||
	num := base + numId*base
 | 
			
		||||
	mainKeyBitSet := newBitmap(MAIN_KEY_LENGTH, 0)
 | 
			
		||||
	numKeyIndex := int((num + batch) % NUM_KEY_LENGTH_BINARY)
 | 
			
		||||
	temp := newEncode(int64(num), numKeyIndex)
 | 
			
		||||
	for i := 0; i < MAIN_KEY_NUM_LENGTH; i++ {
 | 
			
		||||
		mainKeyBitSet.Set(i, (temp&1) == 1)
 | 
			
		||||
		temp >>= 1
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < NUM_KEY_LENGTH; i++ {
 | 
			
		||||
		mainKeyBitSet.Set(i+MAIN_KEY_NUM_LENGTH, toNumBitSet[numKeyIndex].Get(i))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var beCheckNum int64
 | 
			
		||||
	if mainKeyBitSet.toInt64() > 0 {
 | 
			
		||||
		beCheckNum = mainKeyBitSet.toInt64()
 | 
			
		||||
	} else {
 | 
			
		||||
		beCheckNum = -mainKeyBitSet.toInt64()
 | 
			
		||||
	}
 | 
			
		||||
	checkNum := int32(beCheckNum % 32)
 | 
			
		||||
	checkNumBitSet := toBitSet32[checkNum]
 | 
			
		||||
	for i := 0; i < CHECK_LENGTH; i++ {
 | 
			
		||||
		mainKeyBitSet.Set(i+MAIN_KEY_NUM_LENGTH+NUM_KEY_LENGTH, checkNumBitSet.Get(i))
 | 
			
		||||
	}
 | 
			
		||||
	batchBitSet := newBitmap(BATCH_LENGTH, 0)
 | 
			
		||||
	temp = int64(batch)
 | 
			
		||||
	for i := 0; i < BATCH_LENGTH; i++ {
 | 
			
		||||
		batchBitSet.Set(i, (temp&1) == 1)
 | 
			
		||||
		temp >>= 1
 | 
			
		||||
	}
 | 
			
		||||
	batchKeyIndex := (num + batch) % BATCH_KEY_LENGTH_BINARY
 | 
			
		||||
	batchStr := base32Encode(fakeRC4Encode(batchBitSet, batchKey[batchKeyIndex]))
 | 
			
		||||
	temp1 := fakeRC4Encode(mainKeyBitSet, getMainKey(batchBitSet))
 | 
			
		||||
	mainKeyStr := base32Encode(temp1)
 | 
			
		||||
 | 
			
		||||
	cdKeyType := 1
 | 
			
		||||
	typeIndex := (num + cdKeyType) % TYPE_LENGTH_BINARY
 | 
			
		||||
 | 
			
		||||
	codeKey := mainKeyStr + batchStr + string(toBase32[batchKeyIndex]) + string(toBase32[typeIndex])
 | 
			
		||||
	return shuffleCDKey(codeKey, batchKeyIndex)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CDKeyInfo struct {
 | 
			
		||||
	Batch int
 | 
			
		||||
	Num   int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeCDKey(cdKey string) (*CDKeyInfo, bool) {
 | 
			
		||||
	if len(cdKey) != CDKEY_LENGTH {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	index := toBase32CToI[rune(cdKey[SHUFFLE_INDEX])]
 | 
			
		||||
	cdKey1 := recoverCDKey(cdKey[0:SHUFFLE_INDEX], index)
 | 
			
		||||
	if cdKey1 == "" {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	typeCheck, find := toBase32CToI[rune(cdKey1[TYPE_INDEX])]
 | 
			
		||||
	if !find {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	batchKeyIndex, find := toBase32CToI[rune(cdKey1[BATCH_NUM_BEGIN])]
 | 
			
		||||
	if !find {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	if !(batchKeyIndex == index) {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	batch := base32Decode(cdKey1[BATCH_BEGIN:BATCH_END])
 | 
			
		||||
	if batch == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	batchBitSet := fakeRC4Encode(batch, batchKey[batchKeyIndex])
 | 
			
		||||
	if batchBitSet == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	mainKey := base32Decode(cdKey1[MAIN_KEY_BEGIN:MAIN_KEY_END])
 | 
			
		||||
	if mainKey == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	mainKey2 := getMainKey(batchBitSet)
 | 
			
		||||
	if mainKey2 == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	mainKeyBitSet := fakeRC4Encode(mainKey, mainKey2)
 | 
			
		||||
	if mainKeyBitSet == nil {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	if !(check(mainKeyBitSet)) {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
	numKeyIndex := getNumKeyIndex(mainKeyBitSet)
 | 
			
		||||
	numInt := numEncode(mainKeyBitSet.toInt64()&intFormat, numKeyIndex)
 | 
			
		||||
	batchInt := int(batchBitSet.toInt64() & intFormat)
 | 
			
		||||
	if !(checkIndex(numInt, batchInt, batchKeyIndex, numKeyIndex)) {
 | 
			
		||||
		return nil, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cdkeyInfo := &CDKeyInfo{
 | 
			
		||||
		Batch: batchInt,
 | 
			
		||||
		Num:   numInt,
 | 
			
		||||
		// Type: typeCheck,
 | 
			
		||||
	}
 | 
			
		||||
	if typeCheck > 0 {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return cdkeyInfo, true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								admin/lib/cdkey/cdkey_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								admin/lib/cdkey/cdkey_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
package cdkey
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestCDKey(t *testing.T) {
 | 
			
		||||
	for i, key := range GenerateAll(2, 100000) {
 | 
			
		||||
		if i > 10 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		info, ok := DecodeCDKey(key)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			panic(key)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Printf("%s, info:%+v\n", key, info)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										311
									
								
								admin/lib/cdkey/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								admin/lib/cdkey/utils.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,311 @@
 | 
			
		||||
package cdkey
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MAXNUM                             = math.MaxInt32 - 20000000
 | 
			
		||||
	CDKEY_LENGTH                       = 15
 | 
			
		||||
	MAIN_KEY_LENGTH                    = 40
 | 
			
		||||
	NUM_KEY_LENGTH_BINARY              = 8
 | 
			
		||||
	MAIN_KEY_NUM_LENGTH                = 32
 | 
			
		||||
	NUM_KEY_LENGTH                     = 3
 | 
			
		||||
	CHECK_LENGTH                       = 5
 | 
			
		||||
	BATCH_LENGTH                       = 20
 | 
			
		||||
	BATCH_KEY_LENGTH_BINARY            = 32
 | 
			
		||||
	TYPE_LENGTH_BINARY                 = 32
 | 
			
		||||
	shuffleLength                      = 32
 | 
			
		||||
	exceptShuffleSeedTotalLength       = 70
 | 
			
		||||
	SHUFFLE_INDEX                      = 14
 | 
			
		||||
	TYPE_INDEX                         = 13
 | 
			
		||||
	BATCH_NUM_BEGIN                    = 12
 | 
			
		||||
	BATCH_BEGIN                        = 8
 | 
			
		||||
	BATCH_END                          = 12
 | 
			
		||||
	MAIN_KEY_BEGIN                     = 0
 | 
			
		||||
	MAIN_KEY_END                       = 8
 | 
			
		||||
	mainKeyFormat                int64 = 34359738367
 | 
			
		||||
	checkNumFormat               int64 = 1065151889408
 | 
			
		||||
	CHECK_LENGTH_BINARY                = 32
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var toBase32 = []rune{'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
 | 
			
		||||
var toBase32CToI map[rune]int
 | 
			
		||||
 | 
			
		||||
var mainKeyBatchKey = newBitmap(20, 1918215104086)
 | 
			
		||||
 | 
			
		||||
var intFormat int64 = 4294967295
 | 
			
		||||
var key = newBitmap(20, 1209617303503)
 | 
			
		||||
var shuffleMap = make(map[int][]int)
 | 
			
		||||
 | 
			
		||||
var numKey = []int64{
 | 
			
		||||
	3000669867,
 | 
			
		||||
	3671239387,
 | 
			
		||||
	2526368469,
 | 
			
		||||
	2493864681,
 | 
			
		||||
	3604110165,
 | 
			
		||||
	3567998377,
 | 
			
		||||
	2763216037,
 | 
			
		||||
	2863360677,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var batchKey = []*bitmap{
 | 
			
		||||
	newBitmap(20, 31511741981182095),
 | 
			
		||||
	newBitmap(20, 3664122353341979125),
 | 
			
		||||
	newBitmap(20, 3024789513220408272),
 | 
			
		||||
	newBitmap(20, 7614911559402769357),
 | 
			
		||||
	newBitmap(20, 2108459002177461007),
 | 
			
		||||
	newBitmap(20, -3779584974404014377),
 | 
			
		||||
	newBitmap(20, -4708816669881919040),
 | 
			
		||||
	newBitmap(20, -6362362468306307184),
 | 
			
		||||
	newBitmap(20, 5237470582631498811),
 | 
			
		||||
	newBitmap(20, 5507680150663927504),
 | 
			
		||||
	newBitmap(20, -533592023685287698),
 | 
			
		||||
	newBitmap(20, 5175063634818869382),
 | 
			
		||||
	newBitmap(20, -8744795741519816883),
 | 
			
		||||
	newBitmap(20, -4080090257317771786),
 | 
			
		||||
	newBitmap(20, -8036132546007449313),
 | 
			
		||||
	newBitmap(20, 202953352259602475),
 | 
			
		||||
	newBitmap(20, 1095317292689077154),
 | 
			
		||||
	newBitmap(20, 2991873574004670411),
 | 
			
		||||
	newBitmap(20, -6707239314758981218),
 | 
			
		||||
	newBitmap(20, 7712241472074747715),
 | 
			
		||||
	newBitmap(20, -8133590642362246474),
 | 
			
		||||
	newBitmap(20, -4968343163714505661),
 | 
			
		||||
	newBitmap(20, -6905628074578549760),
 | 
			
		||||
	newBitmap(20, 5195681389062354029),
 | 
			
		||||
	newBitmap(20, -5910830154906229288),
 | 
			
		||||
	newBitmap(20, -1676518468791541432),
 | 
			
		||||
	newBitmap(20, -7994149653806568719),
 | 
			
		||||
	newBitmap(20, -7378005837432330374),
 | 
			
		||||
	newBitmap(20, 1068884024847281324),
 | 
			
		||||
	newBitmap(20, 1945505497196485942),
 | 
			
		||||
	newBitmap(20, -3492268017556027220),
 | 
			
		||||
	newBitmap(20, 7364928014934311923),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var toNumBitSet [NUM_KEY_LENGTH_BINARY]*bitmap
 | 
			
		||||
var toBitSet32 [32]*bitmap
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	for i := 0; i < 32; i++ {
 | 
			
		||||
		temp := i
 | 
			
		||||
		toBitSet32[i] = newBitmap(5, 0)
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			toBitSet32[i].Set(j, (temp&1) == 1)
 | 
			
		||||
			temp >>= 1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < NUM_KEY_LENGTH_BINARY; i++ {
 | 
			
		||||
		temp := i
 | 
			
		||||
		toNumBitSet[i] = newBitmap(NUM_KEY_LENGTH, 0)
 | 
			
		||||
		for j := 0; j < NUM_KEY_LENGTH; j++ {
 | 
			
		||||
			toNumBitSet[i].Set(j, (temp&1) == 1)
 | 
			
		||||
			temp >>= 1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	toBase32CToI = make(map[rune]int)
 | 
			
		||||
	for i := 0; i < len(toBitSet32); i++ {
 | 
			
		||||
		toBase32CToI[toBase32[i]] = i
 | 
			
		||||
	}
 | 
			
		||||
	for seed := 0; seed < shuffleLength; seed++ {
 | 
			
		||||
		array := make([]int, exceptShuffleSeedTotalLength)
 | 
			
		||||
		for i := 0; i < exceptShuffleSeedTotalLength; i++ {
 | 
			
		||||
			array[i] = i
 | 
			
		||||
		}
 | 
			
		||||
		shuffle(array, rand.New(rand.NewSource(int64(seed))))
 | 
			
		||||
		shuffleMap[seed] = array
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkIndex(num int64, batch int, batchKeyIndex int, numKeyIndex int) bool {
 | 
			
		||||
	return (num+int64(batch))%BATCH_KEY_LENGTH_BINARY == int64(batchKeyIndex) && (num+int64(batch))%NUM_KEY_LENGTH_BINARY == int64(numKeyIndex)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func numEncode(num int64, index int) int64 {
 | 
			
		||||
	return numKey[index] ^ num
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getNumKeyIndex(mainKeyBitSet *bitmap) int {
 | 
			
		||||
	bitset := newBitmap(NUM_KEY_LENGTH, 0)
 | 
			
		||||
	for i := 0; i < bitset.GetSize(); i++ {
 | 
			
		||||
		bitset.Set(i, mainKeyBitSet.Get(MAIN_KEY_NUM_LENGTH+i))
 | 
			
		||||
	}
 | 
			
		||||
	return int(bitset.toInt64())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func check(mainkeyBitSet *bitmap) bool {
 | 
			
		||||
	mainkey := mainkeyBitSet.toInt64()
 | 
			
		||||
	if mainkey <= 0 {
 | 
			
		||||
		mainkey = -mainkey
 | 
			
		||||
	}
 | 
			
		||||
	beCheckNum := mainkey & mainKeyFormat
 | 
			
		||||
	checkNum := mainkey & checkNumFormat
 | 
			
		||||
	checkNum >>= (MAIN_KEY_NUM_LENGTH + NUM_KEY_LENGTH)
 | 
			
		||||
	return beCheckNum%CHECK_LENGTH_BINARY == checkNum
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func base32Decode(data string) *bitmap {
 | 
			
		||||
	if len(data) > 63/5 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	bitset := newBitmap(len(data)*5, 0)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for _, c := range data {
 | 
			
		||||
		if _, find := toBase32CToI[c]; !find {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		index := toBase32CToI[c]
 | 
			
		||||
		letterBitSet := toBitSet32[index]
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			bitset.Set(i, letterBitSet.Get(j))
 | 
			
		||||
			i++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return bitset
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func recoverCDKey(cdKey string, index int) string {
 | 
			
		||||
	array := shuffleMap[index]
 | 
			
		||||
	if array == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	bytes := base32DecodeReturnByteArray(cdKey)
 | 
			
		||||
	if bytes == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	if len(array) != len(bytes) {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	resultByte := make([]byte, len(bytes))
 | 
			
		||||
	for i := 0; i < len(array); i++ {
 | 
			
		||||
		resultByte[array[i]] = bytes[i]
 | 
			
		||||
	}
 | 
			
		||||
	return base32Encode1(resultByte)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func shuffleCDKey(key string, index int) string {
 | 
			
		||||
	array := shuffleMap[index]
 | 
			
		||||
	bytes := base32DecodeReturnByteArray(key)
 | 
			
		||||
	resultByte := make([]byte, len(bytes))
 | 
			
		||||
	for i := 0; i < len(array); i++ {
 | 
			
		||||
		resultByte[i] = bytes[array[i]]
 | 
			
		||||
	}
 | 
			
		||||
	return base32Encode1(resultByte) + string(toBase32[index])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func shuffle(array []int, rander *rand.Rand) {
 | 
			
		||||
	for i := len(array); i > 1; i-- {
 | 
			
		||||
		swap(array, i-1, rander.Intn(i))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func swap(array []int, i, j int) {
 | 
			
		||||
	array[i], array[j] = array[j], array[i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newEncode(num int64, index int) int64 {
 | 
			
		||||
	return numKey[index] ^ num
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func base32Encode(m *bitmap) string {
 | 
			
		||||
	if m.GetSize()%5 != 0 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stringBuilder := ""
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < m.GetSize(); i += 5 {
 | 
			
		||||
		bitset1 := newBitmap(5, 0)
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			bitset1.Set(j, m.Get(i+j))
 | 
			
		||||
		}
 | 
			
		||||
		if bitset1.toInt64() >= int64(len(toBase32)) {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
		letter := toBase32[int(bitset1.toInt64())]
 | 
			
		||||
		stringBuilder += string(letter)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stringBuilder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func base32Encode1(bytes []byte) string {
 | 
			
		||||
	if len(bytes)%5 != 0 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stringBuilder := ""
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < len(bytes); i += 5 {
 | 
			
		||||
		bitset1 := newBitmap(5, 0)
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			bitset1.Set(j, bytes[i+j] > 0)
 | 
			
		||||
		}
 | 
			
		||||
		if bitset1.toInt64() >= int64(len(toBase32)) {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
		letter := toBase32[int(bitset1.toInt64())]
 | 
			
		||||
		stringBuilder += string(letter)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stringBuilder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fakeRC4Encode(data, key *bitmap) *bitmap {
 | 
			
		||||
	if data.GetSize() != key.GetSize() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	bitSet := newBitmap(data.GetSize(), 0)
 | 
			
		||||
	for i := 0; i < data.GetSize(); i++ {
 | 
			
		||||
		bitSet.Set(i, data.GetInt(i)^key.GetInt(i) == 1)
 | 
			
		||||
	}
 | 
			
		||||
	return bitSet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getMainKey(batch *bitmap) *bitmap {
 | 
			
		||||
	bitSet := newBitmap(MAIN_KEY_LENGTH, 0)
 | 
			
		||||
	batchKey := fakeRC4Encode(batch, mainKeyBatchKey)
 | 
			
		||||
	if batchKey == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	index := (int)(batchKey.toInt64()&intFormat) % key.GetSize()
 | 
			
		||||
	count := 0
 | 
			
		||||
	for i := 0; i < index; i++ {
 | 
			
		||||
		bitSet.Set(count, key.Get(i))
 | 
			
		||||
		count++
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < batchKey.GetSize(); i++ {
 | 
			
		||||
		bitSet.Set(count, batchKey.Get(i))
 | 
			
		||||
		count++
 | 
			
		||||
	}
 | 
			
		||||
	for i := index; i < key.GetSize(); i++ {
 | 
			
		||||
		bitSet.Set(count, key.Get(i))
 | 
			
		||||
		count++
 | 
			
		||||
	}
 | 
			
		||||
	return bitSet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func base32DecodeReturnByteArray(data string) []byte {
 | 
			
		||||
	bytes := make([]byte, len(data)*5)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for _, c := range data {
 | 
			
		||||
		if _, find := toBase32CToI[c]; !find {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		index := toBase32CToI[c]
 | 
			
		||||
		letterBitSet := toBitSet32[index]
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			bitValue := letterBitSet.Get(j)
 | 
			
		||||
			if bitValue {
 | 
			
		||||
				bytes[i] = 1
 | 
			
		||||
			} else {
 | 
			
		||||
				bytes[i] = 0
 | 
			
		||||
			}
 | 
			
		||||
			i++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return bytes
 | 
			
		||||
}
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
VITE_APP_BASE_API = '/api'
 | 
			
		||||
VITE_APP_BASE_URL = 'http://localhost:8080/api'
 | 
			
		||||
VITE_APP_BASE_URL = 'http://192.168.78.128:8080/api'
 | 
			
		||||
@ -98,7 +98,7 @@ const listData = async () => {
 | 
			
		||||
 | 
			
		||||
    calcElColSpan.value = 0
 | 
			
		||||
    // 计算el-col占用24格子的span数量
 | 
			
		||||
    let calcElColSpanTmp = 1
 | 
			
		||||
    let calcElColSpanTmp = 2
 | 
			
		||||
    whereFieldsDescInfo.value.forEach((field) => {
 | 
			
		||||
      if (field.where === "range") {
 | 
			
		||||
        calcElColSpanTmp += 2
 | 
			
		||||
@ -106,9 +106,9 @@ const listData = async () => {
 | 
			
		||||
        calcElColSpanTmp += 1
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    calcElColSpan.value = 24/calcElColSpanTmp
 | 
			
		||||
    calcElColSpan.value = 24 / calcElColSpanTmp
 | 
			
		||||
 | 
			
		||||
    console.log("where fields:", whereFieldsDescInfo.value)
 | 
			
		||||
    // console.log("where fields:", whereFieldsDescInfo.value)
 | 
			
		||||
    // console.log('await list  rsp:', listRsp.value, fieldsDescInfo.value, toRaw(rows.value), toRaw(rules.value))
 | 
			
		||||
 | 
			
		||||
    listDataOK.value = true
 | 
			
		||||
@ -270,7 +270,7 @@ const handleQueryItem = (itemQueryStr) => {
 | 
			
		||||
  itemQueryStr = itemQueryStr.replace(/[\s\u3000]/g, "")
 | 
			
		||||
  resourceGetAllItems(projectId).then((res) => {
 | 
			
		||||
    console.log("获取所有道具返回:", res.data)
 | 
			
		||||
    console.log("查询字符串:[" +  itemQueryStr + "]")
 | 
			
		||||
    console.log("查询字符串:[" + itemQueryStr + "]")
 | 
			
		||||
    itemChoices.value = res.data.items.filter((item) => {
 | 
			
		||||
      return item.desc.includes(itemQueryStr)
 | 
			
		||||
    })
 | 
			
		||||
@ -280,6 +280,14 @@ const handleQueryItem = (itemQueryStr) => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const resetConditionSearch = () => {
 | 
			
		||||
  for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
 | 
			
		||||
    let field = whereFieldsDescInfo.value[i]
 | 
			
		||||
    field.value1 = null
 | 
			
		||||
    field.value2 = null
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@ -299,13 +307,14 @@ const handleQueryItem = (itemQueryStr) => {
 | 
			
		||||
              </el-col>
 | 
			
		||||
              <el-col :span="calcElColSpan">
 | 
			
		||||
                <el-date-picker v-model="fieldDescInfo.value2" type="datetime"
 | 
			
		||||
                               :placeholder="(fieldDescInfo.name + '结束')" format="YYYY/MM/DD HH:mm:ss"
 | 
			
		||||
                               value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
 | 
			
		||||
                                :placeholder="(fieldDescInfo.name + '结束')" format="YYYY/MM/DD HH:mm:ss"
 | 
			
		||||
                                value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
 | 
			
		||||
              </el-col>
 | 
			
		||||
            </template>
 | 
			
		||||
            <template v-else>
 | 
			
		||||
              <el-col :span="calcElColSpan">
 | 
			
		||||
                <el-select v-model="fieldDescInfo.value1" :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
 | 
			
		||||
                <el-select v-model="fieldDescInfo.value1"
 | 
			
		||||
                           :placeholder="(fieldDescInfo.multi_choice === true ? '--' + fieldDescInfo.name + '--' : '--' + fieldDescInfo.name + '--')"
 | 
			
		||||
                           style="width: 150px"
 | 
			
		||||
                           filterable v-if="(fieldDescInfo.choices.length > 0)">
 | 
			
		||||
                  <el-option v-for="choice in fieldDescInfo.choices" :key="choice.value" :label="choice.desc"
 | 
			
		||||
@ -320,6 +329,9 @@ const handleQueryItem = (itemQueryStr) => {
 | 
			
		||||
          <el-col :span="calcElColSpan">
 | 
			
		||||
            <el-button @click="listData" type="primary">条件搜索</el-button>
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :span="calcElColSpan">
 | 
			
		||||
            <el-button @click="resetConditionSearch">清空条件</el-button>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
 | 
			
		||||
        <el-row style="margin-top: 10px">
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@ router.beforeEach((to, from, next) => {
 | 
			
		||||
                LocalCache.deleteCache("projectsRoute")
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
            // console.log("访问页面" + to.path + "已经请求过用户数据,跳过获取")
 | 
			
		||||
            console.log("访问页面" + to.path + "已经请求过用户数据,跳过获取")
 | 
			
		||||
            // console.log("op tree routes length valid:", projectOpTreeRoutes.value.length)
 | 
			
		||||
            next()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ const activeMenu = computed(() => route.path)
 | 
			
		||||
 | 
			
		||||
const hasClickedMenu = ref(false)
 | 
			
		||||
 | 
			
		||||
router.push("/welcome")
 | 
			
		||||
// router.push("/welcome")
 | 
			
		||||
 | 
			
		||||
const handleEnterIndex = () => {
 | 
			
		||||
  router.push("/welcome")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								ui/todo.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								ui/todo.md
									
									
									
									
									
								
							@ -1,7 +1,11 @@
 | 
			
		||||
# todo列表
 | 
			
		||||
 | 
			
		||||
- [x] 道具列表选择支持远程搜索(避免道具列表太长卡顿)
 | 
			
		||||
- [ ] 表格各种项目支持分页(难点是账户、角色、订单如何分)
 | 
			
		||||
- [ ] 表格各种项目支持分页(难点是账户、角色、订单这种来自各个游戏区服数据如何分)
 | 
			
		||||
- [ ] 表格字段排序
 | 
			
		||||
- [ ] 表格字段搜索
 | 
			
		||||
- [x] 表格字段搜索
 | 
			
		||||
- [ ] 表格定制化按钮,比如服务器列表支持单个服务器维护、一键维护(难点是带页面跳转的比如角色列表快速封禁)
 | 
			
		||||
- [ ] 执行历史记录
 | 
			
		||||
- [x] 执行历史记录
 | 
			
		||||
- [ ] 执行历史查看和条件检索
 | 
			
		||||
- [ ] 公告发送游戏
 | 
			
		||||
- [ ] 奖励码接入
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user