diff --git a/admin/apps/game/domain/comm_resource.go b/admin/apps/game/domain/comm_resource.go
index f2f6ad9..5f14402 100644
--- a/admin/apps/game/domain/comm_resource.go
+++ b/admin/apps/game/domain/comm_resource.go
@@ -27,20 +27,20 @@ type CommonResourceService struct {
noticeRepo repo.INoticeRepo
}
-func initCommonResourcesRepo(db *gorm.DB) {
+func (svc *CommonResourceService) initCommonResourcesRepo(db *gorm.DB) {
r(consts.ResourcesName_Project, "项目管理", repo.NewCommonResourceRepo(db, &model.Project{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
{
serverRepo := r(consts.ResourcesName_Server, "服务器管理", repo.NewCommonResourceRepo(db, &model.Server{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
- serverRepo.GlobalBtns = []*api.ResourceBtnInfo{
- {Key: consts.BtnKeyGlobal_Server_DownAll, Name: "一键停服", BtnColorType: "info"},
- {Key: consts.BtnKeyGlobal_Server_UpAll, Name: "一键起服", BtnColorType: "warning"},
- {Key: consts.BtnKeyGlobal_Server_ExportCdn, Name: "一键导出cdn", BtnColorType: "danger"},
- {Key: consts.BtnKeyGlobal_Server_ExportCdn, Name: "预览导出cdn", BtnColorType: "default"},
+ serverRepo.GlobalBtns = []*ResourceBtnInfo{
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Server_DownAll, Name: "一键停服", BtnColorType: "info"}, svc.handleServerUpOrDown},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Server_UpAll, Name: "一键起服", BtnColorType: "warning"}, svc.handleServerUpOrDown},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Server_ExportCdn, Name: "一键导出cdn", BtnColorType: "danger"}, svc.handleServerExportCdn},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Server_ExportCdn, Name: "预览导出cdn", BtnColorType: "default"}, svc.handleServerExportCdn},
}
- serverRepo.RowBtns = []*api.ResourceBtnInfo{
- {Key: consts.BtnKeyRow_Server_Down, Name: "停服", BtnColorType: "info"},
- {Key: consts.BtnKeyRow_Server_Up, Name: "起服", BtnColorType: "warning"},
+ serverRepo.RowBtns = []*ResourceBtnInfo{
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyRow_Server_Down, Name: "停服", BtnColorType: "info"}, svc.handleServerUpOrDown},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyRow_Server_Up, Name: "起服", BtnColorType: "warning"}, svc.handleServerUpOrDown},
}
}
@@ -60,24 +60,25 @@ func initCommonResourcesRepo(db *gorm.DB) {
r(consts.ResourcesName_ItemBag, "道具礼包", repo.NewCommonResourceRepo(db, &model.ItemBag{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
{
noticeRepo := r(consts.ResourcesName_Notice, "公告", repo.NewCommonResourceRepo(db, &model.Notice{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
- noticeRepo.GlobalBtns = []*api.ResourceBtnInfo{
- {Key: consts.BtnKeyGlobal_Server_DownAll, Name: "一键禁用所有", BtnColorType: "info"},
+ noticeRepo.GlobalBtns = []*ResourceBtnInfo{
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Notice_DisableAll, Name: "一键禁用", BtnColorType: "info"}, svc.handleNoticeDisable},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Notice_EnableAll, Name: "一键启用", BtnColorType: "warning"}, svc.handleNoticeEnable},
}
- noticeRepo.RowBtns = []*api.ResourceBtnInfo{
- {Key: consts.BtnKeyRow_Server_Down, Name: "禁用", BtnColorType: "info"},
- {Key: consts.BtnKeyRow_Server_Up, Name: "启用", BtnColorType: "warning"},
+ noticeRepo.RowBtns = []*ResourceBtnInfo{
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Notice_Disable, Name: "禁用", BtnColorType: "info"}, svc.handleNoticeDisable},
+ {&api.ResourceBtnInfo{Key: consts.BtnKeyGlobal_Notice_Enable, Name: "启用", BtnColorType: "warning"}, svc.handleNoticeEnable},
}
}
r(consts.ResourcesName_DevicePush, "设备推送(暂无)", repo.NewCommonResourceRepo(db, &model.DevicePush{}), ShowMethod_Get)
}
func NewCommonResourceService(db *gorm.DB) *CommonResourceService {
- initCommonResourcesRepo(db)
svc := &CommonResourceService{
projectRepo: repo.NewProjectRepo(db),
serverRepo: repo.NewServerRepo(db),
noticeRepo: repo.NewNoticeRepo(db),
}
+ svc.initCommonResourcesRepo(db)
svc.startEventSubscriber()
svc.startLoadAllDelayInvokeDbData()
return svc
@@ -305,33 +306,14 @@ func (svc *CommonResourceService) RowsSelection(projectId int, resourceName stri
return projectEt, nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId)
}
- if params.BtnKey == consts.BtnKeyGlobal_Server_ExportCdn {
- // 导出cdn,聚合公告信息一起导
- serverList, err := svc.serverRepo.List(projectId)
- if err != nil {
- return projectEt, nil, err
- }
- noticeList, err := svc.noticeRepo.List(projectId)
- if err != nil {
- return projectEt, nil, err
- }
- content, err := genCdnServerListContent(serverList, noticeList)
- if err != nil {
- return projectEt, nil, err
- }
- return projectEt, &dto2.CommonRowsSelectionRsp{
- Msg: content,
- NeedRefresh: false,
- FileName: projectEt.GetProjectPo().Name + "-区服公告信息.txt",
- }, nil
- } else {
- if hook, ok := projects.GetProjectResourceHook(projectEt, resourceName).(projects.IPostResourceOpRowsHook); ok {
- rsp, err := hook.RowsSelection(projectEt, resourceName, params.BtnKey, params.Rows)
- return projectEt, rsp, err
- }
+ rRepo := findCommResourceRepo(resourceName)
+ btnInfo, find := rRepo.findRowsSelectionBtn(params.BtnKey)
+ if !find {
+ return projectEt, nil, errcode.New(errcode.ServerError, "not found project %v resource %v rows section btn:%v",
+ projectId, resourceName, params.BtnKey)
}
-
- return projectEt, nil, nil
+ rsp, err := btnInfo.RowsSelectionHandler(projectEt, resourceName, params)
+ return projectEt, rsp, err
}
func (svc *CommonResourceService) GetResourceKeyByDto(resource string, dtoObj []dto2.CommonDtoValues) (string, string) {
@@ -358,7 +340,7 @@ func (svc *CommonResourceService) GetResourceKeyByDto(resource string, dtoObj []
return desc, strings.Join(keyList, ",")
}
-func (svc *CommonResourceService) GetResourceSpecBtnKey(resource string, btnKey string) *api.ResourceBtnInfo {
+func (svc *CommonResourceService) GetResourceSpecBtnKey(resource string, btnKey string) *ResourceBtnInfo {
resourceInfo := findCommResourceRepo(resource)
for _, v := range resourceInfo.GlobalBtns {
if v.Key == btnKey {
@@ -376,13 +358,18 @@ func (svc *CommonResourceService) GetResourceSpecBtnKey(resource string, btnKey
func (svc *CommonResourceService) GetSupportResourcesList(permissions []string) []*api.ResourceInitInfo {
list := make([]*api.ResourceInitInfo, 0, len(commResourcesRepo))
for _, v := range commResourcesRepo {
- list = append(list, &api.ResourceInitInfo{
+ initInfo := &api.ResourceInitInfo{
Resource: v.Resource,
Desc: v.Desc,
ShowMethods: v.ShowMethods,
- GlobalBtns: v.GlobalBtns,
- RowBtns: v.RowBtns,
- })
+ }
+ for _, v := range v.GlobalBtns {
+ initInfo.GlobalBtns = append(initInfo.GlobalBtns, v.ResourceBtnInfo)
+ }
+ for _, v := range v.RowBtns {
+ initInfo.RowBtns = append(initInfo.RowBtns, v.ResourceBtnInfo)
+ }
+ list = append(list, initInfo)
}
return list
}
@@ -394,17 +381,36 @@ const (
ShowMethod_Delete = 1 << 3
)
+type ResourceBtnInfo struct {
+ *api.ResourceBtnInfo
+ RowsSelectionHandler func(projectEt *entity.Project, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error)
+}
+
type resourceRepoInfo struct {
Resource string
Desc string
Repo repo.ICommonResourceRepo
ShowMethods []string
showMethods int
- GlobalBtns []*api.ResourceBtnInfo
- RowBtns []*api.ResourceBtnInfo
+ GlobalBtns []*ResourceBtnInfo
+ RowBtns []*ResourceBtnInfo
HasDelayInvokeCreateHook bool
}
+func (repoInfo *resourceRepoInfo) findRowsSelectionBtn(clickedBtn string) (*ResourceBtnInfo, bool) {
+ for _, btn := range repoInfo.GlobalBtns {
+ if btn.Key == clickedBtn {
+ return btn, true
+ }
+ }
+ for _, btn := range repoInfo.RowBtns {
+ if btn.Key == clickedBtn {
+ return btn, true
+ }
+ }
+ return nil, false
+}
+
var commResourcesRepo = make([]*resourceRepoInfo, 0)
func r(resource, desc string, repo repo.ICommonResourceRepo, showMethods int) *resourceRepoInfo {
diff --git a/admin/apps/game/domain/comm_resource_selection.go b/admin/apps/game/domain/comm_resource_selection.go
new file mode 100644
index 0000000..4d81aac
--- /dev/null
+++ b/admin/apps/game/domain/comm_resource_selection.go
@@ -0,0 +1,78 @@
+package domain
+
+import (
+ "admin/apps/game/domain/entity"
+ "admin/apps/game/domain/projects"
+ dto2 "admin/internal/model/dto"
+)
+
+func (svc *CommonResourceService) handleServerUpOrDown(projectEt *entity.Project, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) {
+ if hook, ok := projects.GetProjectResourceHook(projectEt, resourceName).(projects.IPostResourceOpRowsHook); ok {
+ rsp, err := hook.RowsSelection(projectEt, resourceName, params.BtnKey, params.Rows)
+ return rsp, err
+ }
+ return nil, nil
+}
+
+func (svc *CommonResourceService) handleServerExportCdn(projectEt *entity.Project, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) {
+ // 导出cdn,聚合公告信息一起导
+ serverList, err := svc.serverRepo.List(projectEt.GetProjectPo().ID)
+ if err != nil {
+ return nil, err
+ }
+ noticeList, err := svc.noticeRepo.List(projectEt.GetProjectPo().ID)
+ if err != nil {
+ return nil, err
+ }
+ content, err := genCdnServerListContent(serverList, noticeList)
+ if err != nil {
+ return nil, err
+ }
+ return &dto2.CommonRowsSelectionRsp{
+ Msg: content,
+ NeedRefresh: false,
+ FileName: projectEt.GetProjectPo().Name + "-区服公告信息.txt",
+ }, nil
+}
+
+func (svc *CommonResourceService) handleNoticeDisable(projectEt *entity.Project, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) {
+ var err error
+ if len(params.Rows) == 0 {
+ // 禁用所有
+ err = svc.noticeRepo.DisableAll(projectEt.GetProjectID())
+ } else {
+ ids := make([]int, 0, len(params.Rows))
+ for _, v := range params.Rows {
+ ids = append(ids, int(v["ID"].(float64)))
+ }
+ err = svc.noticeRepo.DisableSome(projectEt.GetProjectID(), ids)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &dto2.CommonRowsSelectionRsp{
+ Msg: "禁用成功!",
+ NeedRefresh: true,
+ }, nil
+}
+
+func (svc *CommonResourceService) handleNoticeEnable(projectEt *entity.Project, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) {
+ var err error
+ if len(params.Rows) == 0 {
+ // 禁用所有
+ err = svc.noticeRepo.EnableAll(projectEt.GetProjectID())
+ } else {
+ ids := make([]int, 0, len(params.Rows))
+ for _, v := range params.Rows {
+ ids = append(ids, int(v["ID"].(float64)))
+ }
+ err = svc.noticeRepo.EnableSome(projectEt.GetProjectID(), ids)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &dto2.CommonRowsSelectionRsp{
+ Msg: "启用成功!",
+ NeedRefresh: true,
+ }, nil
+}
diff --git a/admin/apps/game/domain/entity/project.go b/admin/apps/game/domain/entity/project.go
index c12ddbf..76c0272 100644
--- a/admin/apps/game/domain/entity/project.go
+++ b/admin/apps/game/domain/entity/project.go
@@ -25,6 +25,10 @@ func (project *Project) ToCommonResource() *CommonResource {
return er.FromPo(project.Po)
}
+func (project *Project) GetProjectID() int {
+ return project.Po.ID
+}
+
func (project *Project) GetProjectPo() *model.Project {
return project.Po
}
diff --git a/admin/apps/game/domain/projects/smdl/server.go b/admin/apps/game/domain/projects/smdl/server.go
index ca1b1d6..137eebe 100644
--- a/admin/apps/game/domain/projects/smdl/server.go
+++ b/admin/apps/game/domain/projects/smdl/server.go
@@ -45,13 +45,13 @@ func (hook *ServerHook) List(projectInfo *entity.Project, resource string, param
row["TotalRoleCount"] = findRemoteServerInfo.TotalRoleCount
row["TotalAccountCount"] = findRemoteServerInfo.TotalAccountCount
if findRemoteServerInfo.IsServerDown {
- row["IsServerDown"] = "是"
+ row["IsServerDown"] = true
} else {
- row["IsServerDown"] = "否"
+ row["IsServerDown"] = false
}
} else {
- row["IsServerDown"] = "否"
- row["RunningStatus"] = "未知"
+ row["IsServerDown"] = false
+ row["RunningStatus"] = "失联"
row["Ccu"] = 0
row["TotalRoleCount"] = 0
row["TotalAccountCount"] = 0
diff --git a/admin/apps/game/domain/repo/notice.go b/admin/apps/game/domain/repo/notice.go
index 870cbd9..fb1a7f8 100644
--- a/admin/apps/game/domain/repo/notice.go
+++ b/admin/apps/game/domain/repo/notice.go
@@ -11,6 +11,10 @@ var NoticeRepoInstance INoticeRepo
type INoticeRepo interface {
List(projectId int) ([]*entity.CommonResource, error)
+ DisableAll(projectId int) error
+ EnableAll(projectId int) error
+ DisableSome(projectId int, ids []int) error
+ EnableSome(projectId int, ids []int) error
}
func NewNoticeRepo(db *gorm.DB) INoticeRepo {
@@ -23,7 +27,7 @@ type noticeRepoImpl struct {
func (impl *noticeRepoImpl) List(projectId int) ([]*entity.CommonResource, error) {
list := make([]*model.Notice, 0)
- err := impl.db.Where("project_id = ?", projectId).Find(&list).Error
+ err := impl.db.Where("project_id = ? and status = ?", projectId, true).Find(&list).Error
if err != nil {
return nil, errcode.New(errcode.DBError, "list server error:%v", err)
}
@@ -34,3 +38,32 @@ func (impl *noticeRepoImpl) List(projectId int) ([]*entity.CommonResource, error
}
return list1, nil
}
+
+func (impl *noticeRepoImpl) DisableAll(projectId int) error {
+ err := impl.db.Model(&model.Notice{}).Where("project_id = ?", projectId).Update("status", false).Error
+ if err != nil {
+ return errcode.New(errcode.DBError, "disable all error:%v", err)
+ }
+ return nil
+}
+func (impl *noticeRepoImpl) EnableAll(projectId int) error {
+ err := impl.db.Model(&model.Notice{}).Where("project_id = ?", projectId).Update("status", true).Error
+ if err != nil {
+ return errcode.New(errcode.DBError, "enable all error:%v", err)
+ }
+ return nil
+}
+func (impl *noticeRepoImpl) DisableSome(projectId int, ids []int) error {
+ err := impl.db.Model(&model.Notice{}).Where("project_id = ? and id in ?", projectId, ids).Update("status", false).Error
+ if err != nil {
+ return errcode.New(errcode.DBError, "disable all error:%v", err)
+ }
+ return nil
+}
+func (impl *noticeRepoImpl) EnableSome(projectId int, ids []int) error {
+ err := impl.db.Model(&model.Notice{}).Where("project_id = ? and id in ?", projectId, ids).Update("status", true).Error
+ if err != nil {
+ return errcode.New(errcode.DBError, "disable all error:%v", err)
+ }
+ return nil
+}
diff --git a/admin/apps/game/domain/server.go b/admin/apps/game/domain/server.go
index c5d9c75..1dfb15e 100644
--- a/admin/apps/game/domain/server.go
+++ b/admin/apps/game/domain/server.go
@@ -5,6 +5,7 @@ import (
"admin/apps/game/model"
"admin/internal/errcode"
"bytes"
+ "sort"
"strings"
"text/template"
"time"
@@ -68,6 +69,13 @@ func genCdnServerListContent(serverList, noticeList []*entity.CommonResource) (s
}
info.NoticeVersion = time.Now().Format("200601021504")
+
+ sort.SliceStable(noticeList, func(i, j int) bool {
+ infoI := noticeList[i].Po.(*model.Notice)
+ infoJ := noticeList[j].Po.(*model.Notice)
+ return infoI.SortWeight > infoJ.SortWeight
+ })
+
for i, notice := range noticeList {
noticeDbInfo := notice.Po.(*model.Notice)
noticeInfo := &CdnNoticeInfo{}
diff --git a/admin/apps/game/model/notice.go b/admin/apps/game/model/notice.go
index e2cd4cc..2f0b4e8 100644
--- a/admin/apps/game/model/notice.go
+++ b/admin/apps/game/model/notice.go
@@ -19,7 +19,8 @@ type Notice struct {
Content string `name:"公告内容" desc:"仅支持颜色标签和\\n换行标签" type:"text" required:"true"` // 公告内容
//StartAt time.Time `name:"开始时间" required:"true"`
//EndAt time.Time `name:"结束时间" required:"true"`
- Status bool `name:"是否启用" type:"tagStatus" choices:"GetStatusChoices" required:"true"`
+ Status bool `name:"是否启用" desc:"启用的公告才会导出到cdn被客户端显示" type:"tagStatus" choices:"GetStatusChoices" required:"true"`
+ SortWeight int `name:"排序" desc:"越大越靠前"`
CreatedAt time.Time `readonly:"true"`
UpdatedAt time.Time `readonly:"true"`
@@ -39,7 +40,7 @@ func (m *Notice) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice
func (m *Notice) GetStatusChoices(project *Project) []*dto.CommonDtoFieldChoice {
return []*dto.CommonDtoFieldChoice{
- {Desc: "禁用", Value: false},
- {Desc: "启动", Value: true},
+ {Desc: "禁用", Value: false, Type: 3}, // type: 0:plain 1:primary 2:success 3:info 4:warning 5:danger
+ {Desc: "启用", Value: true, Type: 2},
}
}
diff --git a/admin/apps/game/model/role.go b/admin/apps/game/model/role.go
index 53d705d..7fd5796 100644
--- a/admin/apps/game/model/role.go
+++ b/admin/apps/game/model/role.go
@@ -17,7 +17,7 @@ type Role struct {
Account string `name:"账号" json:"account" where:"eq"`
RoleId string `name:"角色ID" json:"roleId" where:"eq"`
Name string `name:"名称" json:"roleName" where:"eq"`
- Status string `name:"状态" desc:"离线|在线" type:"boolStatus" choices:"" json:"status"`
+ Status string `name:"状态" desc:"离线|在线" type:"tagStatus" choices:"GetStatusChoices"`
Level int `name:"等级" json:"roleLevel"`
Profession string `name:"职业" json:"profession"`
LatestLoginTime time.Time `name:"最近登录时间" json:"latestLoginAt"`
@@ -38,7 +38,7 @@ func (m *Role) GetServerConfIDChoices(project *Project) []*dto.CommonDtoFieldCho
func (m *Role) GetStatusChoices(project *Project) []*dto.CommonDtoFieldChoice {
return []*dto.CommonDtoFieldChoice{
- {Desc: "离线", Value: "离线"},
- {Desc: "在线", Value: "在线"},
+ {Desc: "离线", Value: "离线", Type: 3}, // type: 0:plain 1:primary 2:success 3:info 4:warning 5:danger
+ {Desc: "在线", Value: "在线", Type: 2},
}
}
diff --git a/admin/apps/game/model/server.go b/admin/apps/game/model/server.go
index 488243d..a720695 100644
--- a/admin/apps/game/model/server.go
+++ b/admin/apps/game/model/server.go
@@ -3,6 +3,7 @@ package model
import (
"admin/internal/db"
"admin/internal/global"
+ "admin/internal/model/dto"
"time"
)
@@ -17,11 +18,11 @@ type Server struct {
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" uneditable:"true"`
Desc string `name:"描述"`
ClientConnAddr string `name:"客户端连接地址" desc:"填 公网ip:公网端口" required:"true"`
- RunningStatus string `name:"进程运行状态" desc:"进程运行状态:未知、运行中、停止" readonly:"true" uneditable:"true"`
+ RunningStatus string `name:"进程运行状态" desc:"进程运行状态:未知、运行中、停止" readonly:"true" uneditable:"true" type:"tagStatus" choices:"GetRunningStatusChoices"`
Ccu int `name:"实时在线" desc:"ccu" readonly:"true" uneditable:"true"`
TotalRoleCount int `name:"总角色数" desc:"" readonly:"true" uneditable:"true"`
TotalAccountCount int `name:"总账号数" desc:"" readonly:"true" uneditable:"true"`
- IsServerDown bool `name:"停服维护中" desc:"" readonly:"true" uneditable:"true"`
+ IsServerDown bool `name:"停服维护中" desc:"" readonly:"true" uneditable:"true" type:"tagStatus" choices:"GetServerDownStatusChoices"`
// command_list接口服务器地址,为空代表由由项目统一提供command_list.
// 取决于每个项目改造难度:
// 为空就代表项目要实现一个自己统一对外暴露的gm调用服务对内聚合、分发指令执行,本后台执行指令只调用一次;
@@ -50,3 +51,17 @@ func (m *Server) ListByProjectId(projectId int) ([]*Server, error) {
err := global.GLOB_DB.Where("project_id=?", projectId).Find(&list).Error
return list, err
}
+
+func (m *Server) GetRunningStatusChoices(project *Project) []*dto.CommonDtoFieldChoice {
+ return []*dto.CommonDtoFieldChoice{
+ {Desc: "失联", Value: "失联", Type: 3}, // type: 0:plain 1:primary 2:success 3:info 4:warning 5:danger
+ {Desc: "运行中", Value: "运行中", Type: 2},
+ }
+}
+
+func (m *Server) GetServerDownStatusChoices(project *Project) []*dto.CommonDtoFieldChoice {
+ return []*dto.CommonDtoFieldChoice{
+ {Desc: "否", Value: false, Type: 3}, // type: 0:plain 1:primary 2:success 3:info 4:warning 5:danger
+ {Desc: "是", Value: true, Type: 2},
+ }
+}
diff --git a/admin/apps/game/server/middleware.go b/admin/apps/game/server/middleware.go
index 13993fd..2b6aad5 100644
--- a/admin/apps/game/server/middleware.go
+++ b/admin/apps/game/server/middleware.go
@@ -5,13 +5,12 @@ import (
"admin/internal/context"
"admin/internal/errcode"
"admin/internal/permission"
- "admin/lib/xlog"
"strings"
)
func (srv *Server) CheckToken(ctx *context.WebContext) {
reqPath := ctx.GinCtx().Request.URL.Path
- xlog.Tracef("请求路径:%v, 头:%+v", reqPath, ctx.GinCtx().Request.Header)
+ //xlog.Tracef("请求路径:%v, 头:%+v", reqPath, ctx.GinCtx().Request.Header)
if strings.Contains(reqPath, "/login") {
return
}
diff --git a/admin/apps/user/server/middleware.go b/admin/apps/user/server/middleware.go
index 627846f..3302a51 100644
--- a/admin/apps/user/server/middleware.go
+++ b/admin/apps/user/server/middleware.go
@@ -3,13 +3,12 @@ package server
import (
"admin/internal/context"
"admin/internal/errcode"
- "admin/lib/xlog"
"strings"
)
func (srv *Server) CheckToken(ctx *context.WebContext) {
reqPath := ctx.GinCtx().Request.URL.Path
- xlog.Tracef("请求路径:%v, 头:%+v", reqPath, ctx.GinCtx().Request.Header)
+ //xlog.Tracef("请求路径:%v, 头:%+v", reqPath, ctx.GinCtx().Request.Header)
if strings.Contains(reqPath, "/login") {
return
}
diff --git a/admin/internal/consts/consts.go b/admin/internal/consts/consts.go
index d0e2bed..fd5e42e 100644
--- a/admin/internal/consts/consts.go
+++ b/admin/internal/consts/consts.go
@@ -58,9 +58,13 @@ const (
)
const (
- BtnKeyGlobal_Server_DownAll = "server:down:all" // 一键维护
- BtnKeyGlobal_Server_UpAll = "server:up:all" // 一键维护结束
- BtnKeyGlobal_Server_ExportCdn = "server:export:cdn" // 一键导出cdn
+ BtnKeyGlobal_Server_DownAll = "server:down:all" // 一键维护
+ BtnKeyGlobal_Server_UpAll = "server:up:all" // 一键维护结束
+ BtnKeyGlobal_Server_ExportCdn = "server:export:cdn" // 一键导出cdn
+ BtnKeyGlobal_Notice_DisableAll = "notice:disable:all" // 一键禁用
+ BtnKeyGlobal_Notice_EnableAll = "notice:enable:all" // 一键启用
+ BtnKeyGlobal_Notice_Disable = "notice:disable" // 禁用
+ BtnKeyGlobal_Notice_Enable = "notice:enable" // 启用
)
diff --git a/admin/internal/context/ctx_web.go b/admin/internal/context/ctx_web.go
index 74c19df..a5ef827 100644
--- a/admin/internal/context/ctx_web.go
+++ b/admin/internal/context/ctx_web.go
@@ -37,7 +37,7 @@ func (ctx *WebContext) ExtractHeader() error {
if err != nil {
return err
}
- xlog.Debugf("提取请求头:%+v", ctx.GinCtx().Request.Header)
+ //xlog.Debugf("提取请求头:%+v", ctx.GinCtx().Request.Header)
ctx.Header = header
return nil
}
diff --git a/ui/src/components/game/cdkeyDetail.vue b/ui/src/components/game/cdkeyDetail.vue
new file mode 100644
index 0000000..fccdc80
--- /dev/null
+++ b/ui/src/components/game/cdkeyDetail.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/game/cdkeyUsedHistory.vue b/ui/src/components/game/cdkeyUsedHistory.vue
new file mode 100644
index 0000000..9203f7b
--- /dev/null
+++ b/ui/src/components/game/cdkeyUsedHistory.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+ 使用详情
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/game/userDetail.vue b/ui/src/components/game/userDetail.vue
index f4a40e0..dae6372 100644
--- a/ui/src/components/game/userDetail.vue
+++ b/ui/src/components/game/userDetail.vue
@@ -7,6 +7,7 @@ import LocalCache from "@/stores/localCache.js";
const props = defineProps({
rowInfo: {},
+ fieldsDescInfo: {},
})
const cachedResource = LocalCache.getCache("resource");
diff --git a/ui/src/components/restful/table.vue b/ui/src/components/restful/table.vue
index f8e4c27..17dbbff 100644
--- a/ui/src/components/restful/table.vue
+++ b/ui/src/components/restful/table.vue
@@ -46,7 +46,6 @@ const rowClickBtnSelectRow = ref(null)
const resource_url = cachedResource.meta.resource_url;
const fieldsDescInfo = ref([])
const whereFieldsDescInfo = ref([])
-const calcElColSpan = ref(0)
const rows = ref([])
const itemBags = ref([])
const rules = ref({})
@@ -63,6 +62,77 @@ const selectedItemBag = ref(null)
// console.log("enter table, resource:", cachedResource)
+const handleServerRowData = (fieldsDescInfoData, rowData) => {
+ for (let i = 0; i < fieldsDescInfoData.length; i++) {
+ var field = fieldsDescInfoData[i]
+ // dialogObjectForm.value[field.key] = ''
+
+ if (field.required === true) {
+ rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
+ }
+
+ if (field.type === "items") {
+ dialogObjectForm.value[field.key] = []
+ rowData.jsonValue = JSON.stringify(rowData[field.key])
+ if (field.required === true) {
+ rules.value[field.key] = [{
+ required: true,
+ validator: (rule, value, callback) => {
+ console.log("触发校验道具列表规则:", dialogObjectForm.value)
+ if (dialogObjectForm.value.Attach === undefined || dialogObjectForm.value.Attach.length === 0) {
+ callback(new Error("请至少填写一个奖励道具!"))
+ } else {
+ callback()
+ }
+ },
+ trigger: ["blur", "change"],
+ }]
+ }
+ }
+
+ const tagStatusColorArray = ["plain", "primary", "success", "info", "waring", "danger"]
+ if (field.type === "tagStatus") {
+ for (let k = 0; k < field.choices.length; k++) {
+ if (rowData[field.key] === field.choices[k].value) {
+ rowData.tagValue = field.choices[k].desc
+ rowData.tagColor = tagStatusColorArray[field.choices[k].type]
+ }
+ }
+ }
+
+ if (field.where !== "") {
+ field.value1 = ""
+ field.value2 = ""
+ field.whereDesc = getWhereConditionDesc(field.where)
+ let find = false
+ for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
+ let whereField = whereFieldsDescInfo.value[i]
+ if (whereField.key === field.key) {
+ whereFieldsDescInfo.value[i].type = field.type
+ whereFieldsDescInfo.value[i].where = field.where
+ whereFieldsDescInfo.value[i].whereDesc = getWhereConditionDesc(field.where)
+ find = true
+ break
+ }
+ }
+ if (!find) {
+ whereFieldsDescInfo.value.push(field)
+ }
+ }
+ }
+ return rowData
+}
+
+const handleServerRowsData = (fieldsDescInfoData, rowsData) => {
+ let newRowsData = []
+ rowsData.forEach((rowData) => {
+ const newRowData = handleServerRowData(fieldsDescInfoData, rowData)
+ // console.log("new data:", newRowData)
+ newRowsData.push(newRowData)
+ })
+ return newRowsData
+}
+
const listData = async () => {
try {
let listParams = {
@@ -93,74 +163,9 @@ const listData = async () => {
if (listRsp.value.code !== 200) throw new Error("请求失败,错误码:", listRsp.code);
fieldsDescInfo.value = listRsp.value.data.fields_desc
totalRowCount.value = listRsp.value.data.total_count
- rows.value = listRsp.value.data.rows
+ rows.value = handleServerRowsData(fieldsDescInfo.value, listRsp.value.data.rows)
itemBags.value = listRsp.value.data.item_bags
- for (let i = 0; i < fieldsDescInfo.value.length; i++) {
- var field = fieldsDescInfo.value[i]
- // dialogObjectForm.value[field.key] = ''
-
- if (field.required === true) {
- rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
- }
-
- if (field.type === "items") {
- dialogObjectForm.value[field.key] = []
- for (let j = 0; j < rows.value.length; j++) {
- rows.value[j].jsonValue = JSON.stringify(rows.value[j][field.key])
- }
- if (field.required === true) {
- rules.value[field.key] = [{
- required: true,
- validator: (rule, value, callback) => {
- console.log("触发校验道具列表规则:", dialogObjectForm.value)
- if (dialogObjectForm.value.Attach === undefined || dialogObjectForm.value.Attach.length === 0) {
- callback(new Error("请至少填写一个奖励道具!"))
- } else {
- callback()
- }
- },
- trigger: ["blur", "change"],
- }]
- }
- }
-
- if (field.where !== "") {
- field.value1 = ""
- field.value2 = ""
- field.whereDesc = getWhereConditionDesc(field.where)
- let find = false
- for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
- let whereField = whereFieldsDescInfo.value[i]
- if (whereField.key === field.key) {
- whereFieldsDescInfo.value[i].type = field.type
- whereFieldsDescInfo.value[i].where = field.where
- whereFieldsDescInfo.value[i].whereDesc = getWhereConditionDesc(field.where)
- find = true
- break
- }
- }
- if (!find) {
- whereFieldsDescInfo.value.push(field)
- }
- }
- }
-
- calcElColSpan.value = 0
- // 计算el-col占用24格子的span数量
- let calcElColSpanTmp = 2
- whereFieldsDescInfo.value.forEach((field) => {
- if (field.where === "range") {
- calcElColSpanTmp += 2
- } else {
- calcElColSpanTmp += 1
- }
- })
- calcElColSpan.value = 24 / calcElColSpanTmp
-
- // console.log("where fields:", whereFieldsDescInfo.value)
- // console.log('await list rsp:', listRsp.value, fieldsDescInfo.value, toRaw(rows.value), toRaw(rules.value))
-
listDataOK.value = true
} catch (err) {
console.log(err)
@@ -169,6 +174,29 @@ const listData = async () => {
}
}
+const calcFuncColumnBtnSize = () => {
+ let btnCount = 0;
+ if (resource_raw_node.meta.methods.put === true) {
+ btnCount += 1
+ }
+ if (resource_raw_node.meta.methods.delete === true) {
+ btnCount += 1
+ }
+
+ btnCount += rowClickBtns.length
+
+ if (btnCount >= 4) {
+ return "small"
+ }
+ if (btnCount >= 3) {
+ return "default"
+ }
+ return "large"
+}
+
+const funcBtnSize = ref("default")
+funcBtnSize.value = calcFuncColumnBtnSize()
+
onMounted(() => {
listData();
})
@@ -287,7 +315,9 @@ const submitAdd = async () => {
duration: 4000,
"show-close": true,
})
- rows.value.push(res.data.dto)
+ const newData = handleServerRowData(fieldsDescInfo.value, res.data.dto)
+ rows.value.unshift(newData)
+ // rows.value.push(res.data.dto)
dialogAddVisible.value = false
handleCloseDialog()
}, (err) => {
@@ -320,7 +350,7 @@ const submitEdit = async () => {
"show-close": true,
})
dialogEditVisible.value = false
- rows.value[oldIndex] = res.data.dto
+ rows.value[oldIndex] = handleServerRowData(fieldsDescInfo.value, res.data.dto)
handleCloseDialog()
}, (err) => {
console.log("添加报错:", err)
@@ -564,29 +594,39 @@ const handlePaginationCurChange = (val) => {
-
+
- {{ scope.row.Status }}
- {{ scope.row.Status }}
+ {{ scope.row.tagValue }}
+
+ v-else>
+
+
+ {{ fieldDescInfo.name }}
+
+ {{ fieldDescInfo.name }}
+
+
-
编辑
-
@@ -594,22 +634,22 @@ const handlePaginationCurChange = (val) => {
删除
-
-
+
{{ btn.name }}
-
-
+
{{ btn.name }}
-
-
+
{{ btn.name }}
@@ -639,7 +679,8 @@ const handlePaginationCurChange = (val) => {
-
+
diff --git a/ui/src/components/restful/tableCDKey.vue b/ui/src/components/restful/tableCDKey.vue
index 3f3fefd..2a52f30 100644
--- a/ui/src/components/restful/tableCDKey.vue
+++ b/ui/src/components/restful/tableCDKey.vue
@@ -35,6 +35,78 @@ const selectedItemBag = ref(null)
// console.log("enter table, resource:", cachedResource)
+
+const handleServerRowData = (fieldsDescInfoData, rowData) => {
+ for (let i = 0; i < fieldsDescInfoData.length; i++) {
+ var field = fieldsDescInfoData[i]
+ // dialogObjectForm.value[field.key] = ''
+
+ if (field.required === true) {
+ rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
+ }
+
+ if (field.type === "items") {
+ dialogObjectForm.value[field.key] = []
+ rowData.jsonValue = JSON.stringify(rowData[field.key])
+ if (field.required === true) {
+ rules.value[field.key] = [{
+ required: true,
+ validator: (rule, value, callback) => {
+ console.log("触发校验道具列表规则:", dialogObjectForm.value)
+ if (dialogObjectForm.value.Attach === undefined || dialogObjectForm.value.Attach.length === 0) {
+ callback(new Error("请至少填写一个奖励道具!"))
+ } else {
+ callback()
+ }
+ },
+ trigger: ["blur", "change"],
+ }]
+ }
+ }
+
+ const tagStatusColorArray = ["plain", "primary", "success", "info", "waring", "danger"]
+ if (field.type === "tagStatus") {
+ for (let k = 0; k < field.choices.length; k++) {
+ if (rowData[field.key] === field.choices[k].value) {
+ rowData.tagValue = field.choices[k].desc
+ rowData.tagColor = tagStatusColorArray[field.choices[k].type]
+ }
+ }
+ }
+
+ if (field.where !== "") {
+ field.value1 = ""
+ field.value2 = ""
+ field.whereDesc = getWhereConditionDesc(field.where)
+ let find = false
+ for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
+ let whereField = whereFieldsDescInfo.value[i]
+ if (whereField.key === field.key) {
+ whereFieldsDescInfo.value[i].type = field.type
+ whereFieldsDescInfo.value[i].where = field.where
+ whereFieldsDescInfo.value[i].whereDesc = getWhereConditionDesc(field.where)
+ find = true
+ break
+ }
+ }
+ if (!find) {
+ whereFieldsDescInfo.value.push(field)
+ }
+ }
+ }
+ return rowData
+}
+
+const handleServerRowsData = (fieldsDescInfoData, rowsData) => {
+ let newRowsData = []
+ rowsData.forEach((rowData) => {
+ const newRowData = handleServerRowData(fieldsDescInfoData, rowData)
+ // console.log("new data:", newRowData)
+ newRowsData.push(newRowData)
+ })
+ return newRowsData
+}
+
const listData = async () => {
try {
let listParams = {
@@ -65,72 +137,9 @@ const listData = async () => {
if (listRsp.value.code !== 200) throw new Error("请求失败,错误码:", listRsp.code);
fieldsDescInfo.value = listRsp.value.data.fields_desc
totalRowCount.value = listRsp.value.data.total_count
- rows.value = listRsp.value.data.rows
+ rows.value = handleServerRowsData(fieldsDescInfo.value, listRsp.value.data.rows)
itemBags.value = listRsp.value.data.item_bags
- for (let i = 0; i < fieldsDescInfo.value.length; i++) {
- var field = fieldsDescInfo.value[i]
- dialogObjectForm.value[field.key] = ''
-
- if (field.required == true) {
- rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: ["blur", "change"]}]
- }
-
- if (field.type == "items") {
- dialogObjectForm.value[field.key] = []
- for (let j = 0; j < rows.value.length; j++) {
- rows.value[j].jsonValue = JSON.stringify(rows.value[j][field.key])
- }
- rules.value[field.key] = [{
- required: true,
- validator: (rule, value, callback) => {
- console.log("触发校验道具列表规则:", dialogObjectForm.value)
- if (dialogObjectForm.value.Attach === undefined || dialogObjectForm.value.Attach.length === 0) {
- callback(new Error("请至少填写一个奖励道具!"))
- } else {
- callback()
- }
- },
- trigger: ["blur", "change"],
- }]
- }
-
- if (field.where !== "") {
- field.value1 = ""
- field.value2 = ""
- field.whereDesc = getWhereConditionDesc(field.where)
- let find = false
- for (let i = 0; i < whereFieldsDescInfo.value.length; i++) {
- let whereField = whereFieldsDescInfo.value[i]
- if (whereField.key === field.key) {
- whereFieldsDescInfo.value[i].type = field.type
- whereFieldsDescInfo.value[i].where = field.where
- whereFieldsDescInfo.value[i].whereDesc = getWhereConditionDesc(field.where)
- find = true
- break
- }
- }
- if (!find) {
- whereFieldsDescInfo.value.push(field)
- }
- }
- }
-
- calcElColSpan.value = 0
- // 计算el-col占用24格子的span数量
- let calcElColSpanTmp = 2
- whereFieldsDescInfo.value.forEach((field) => {
- if (field.where === "range") {
- calcElColSpanTmp += 2
- } else {
- calcElColSpanTmp += 1
- }
- })
- calcElColSpan.value = 24 / calcElColSpanTmp
-
- // console.log("where fields:", whereFieldsDescInfo.value)
- // console.log('await list rsp:', listRsp.value, fieldsDescInfo.value, toRaw(rows.value), toRaw(rules.value))
-
listDataOK.value = true
} catch (err) {
console.log(err)
@@ -169,7 +178,8 @@ const submitAdd = async () => {
duration: 4000,
"show-close": true,
})
- rows.value.push(res.data.dto)
+ const newData = handleServerRowData(fieldsDescInfo.value, res.data.dto)
+ rows.value.unshift(newData)
dialogAddVisible.value = false
handleCloseDialog()
}, (err) => {
@@ -202,7 +212,7 @@ const submitEdit = async () => {
"show-close": true,
})
dialogEditVisible.value = false
- rows.value[oldIndex] = res.data.dto
+ rows.value[oldIndex] = handleServerRowData(fieldsDescInfo.value, res.data.dto)
handleCloseDialog()
}, (err) => {
console.log("添加报错:", err)
diff --git a/ui/src/stores/user.js b/ui/src/stores/user.js
index e8f33a0..ab96620 100644
--- a/ui/src/stores/user.js
+++ b/ui/src/stores/user.js
@@ -119,9 +119,9 @@ const userStore = defineStore(
component: () => import('@/views/project/project_op.vue'),
props: true
}
- if (resource.resource === 'cdkey') {
- resourceRoute.component = () => import('@/views/project/project_cdkey.vue')
- }
+ // if (resource.resource === 'cdkey') {
+ // resourceRoute.component = () => import('@/views/project/project_cdkey.vue')
+ // }
resource.show_methods.forEach((method) => {
if (method == "get") {
projectHasAnyResourcePermission = true
diff --git a/ui/src/views/project/project_op.vue b/ui/src/views/project/project_op.vue
index 02ce486..5b435a7 100644
--- a/ui/src/views/project/project_op.vue
+++ b/ui/src/views/project/project_op.vue
@@ -3,8 +3,11 @@
import tableView from "@/components/restful/table.vue";
import LocalCache from "@/stores/localCache.js";
import userDetail from "@/components/game/userDetail.vue";
+import cdkeyDetail from "@/components/game/cdkeyDetail.vue";
+import cdkeyUsedHistory from "@/components/game/cdkeyUsedHistory.vue";
import router from '@/router/index.js'
import userStore from "@/stores/user.js";
+import {cdkeyExport} from "@/api/cdkey.js";
const cachedResource = LocalCache.getCache("resource");
const homeRoutes = userStore().dynamicRouteChildren
@@ -83,6 +86,57 @@ switch (cachedResource.meta.resource) {
}
},)
break
+ case "cdkey":
+ if (rowClickDialogBtns.length > 0) {
+ break
+ }
+ rowClickDialogBtns.push({
+ key: "cdkey:detail",
+ name: "查看",
+ btn_color_type: "primary",
+ btn_type: 1,
+ btn_callback_component: cdkeyDetail,
+ }, {
+ key: "cdkey:export",
+ name: "导出",
+ btn_color_type: "warning",
+ btn_type: 2,
+ click_handler: (row) => {
+ const cachedResource = LocalCache.getCache("resource");
+ const resource_url = cachedResource.meta.resource_url;
+ cdkeyExport(resource_url, {id: row.ID}).then((res) => {
+ console.log("导出cdkey返回:", res)
+
+ // 从响应头解析文件名
+ const contentDisposition = res.headers['content-disposition'];
+ let filename = 'default_filename.ext'; // 默认文件名
+
+ // 正则提取文件名(处理编码情况)
+ const filenameRegex = /filename\*?=(?:UTF-8'')?"?([^";]+)"?/i;
+ const matches = contentDisposition.match(filenameRegex);
+
+ if (matches && matches[1]) {
+ filename = decodeURIComponent(matches[1]); // 解码特殊字符
+ }
+
+ // 创建临时链接触发下载
+ const blob = new Blob([res.data]);
+ const link = document.createElement('a');
+ link.href = window.URL.createObjectURL(blob);
+ link.download = filename;
+ link.click();
+
+ // 释放内存
+ window.URL.revokeObjectURL(link.href);
+ })
+ },
+ }, {
+ key: "cdkey:used:history",
+ name: "礼包使用",
+ btn_color_type: "default",
+ btn_type: 1,
+ btn_callback_component: cdkeyUsedHistory,
+ },)
}