save
This commit is contained in:
parent
7fb270308d
commit
e9d01aa19f
@ -22,7 +22,7 @@ func initCommonResourcesRepo(db *gorm.DB) {
|
|||||||
r(consts.ResourcesName_Account, "账号管理", repo.NewCommonResourceRepo(db, &model.Account{}), ShowMethod_Get) // 账号管理不需要在后台读写数据,都是通过项目api拉
|
r(consts.ResourcesName_Account, "账号管理", repo.NewCommonResourceRepo(db, &model.Account{}), ShowMethod_Get) // 账号管理不需要在后台读写数据,都是通过项目api拉
|
||||||
r(consts.ResourcesName_Role, "角色管理", repo.NewCommonResourceRepo(db, &model.Role{}), ShowMethod_Get) // 角色管理不需要在后台读写数据,都是通过项目api拉
|
r(consts.ResourcesName_Role, "角色管理", repo.NewCommonResourceRepo(db, &model.Role{}), ShowMethod_Get) // 角色管理不需要在后台读写数据,都是通过项目api拉
|
||||||
r(consts.ResourcesName_WhiteList, "白名单", repo.NewCommonResourceRepo(db, &model.WhiteList{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Delete)
|
r(consts.ResourcesName_WhiteList, "白名单", repo.NewCommonResourceRepo(db, &model.WhiteList{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Delete)
|
||||||
r(consts.ResourcesName_Ban, "封禁管理", repo.NewCommonResourceRepo(db, &model.Ban{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Delete)
|
r(consts.ResourcesName_Ban, "封禁管理", repo.NewCommonResourceRepo(db, &model.Ban{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
|
||||||
r(consts.ResourcesName_MailRole, "个人邮件", repo.NewCommonResourceRepo(db, &model.RoleMail{}), ShowMethod_Get|ShowMethod_Post) // 个人邮件发放就没法撤回?
|
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|ShowMethod_Delete) // 直接删除,别修改了,玩家收到的更乱
|
r(consts.ResourcesName_MailGlobal, "全服邮件", repo.NewCommonResourceRepo(db, &model.GlobalMail{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Delete) // 直接删除,别修改了,玩家收到的更乱
|
||||||
r(consts.ResourcesName_Notice, "公告", repo.NewCommonResourceRepo(db, &model.Notice{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
|
r(consts.ResourcesName_Notice, "公告", repo.NewCommonResourceRepo(db, &model.Notice{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,6 +28,10 @@ func poToCommonDtoNo(po any) dto.CommonDtoValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj[ft.Name] = fo.Interface()
|
obj[ft.Name] = fo.Interface()
|
||||||
|
|
||||||
|
if ft.Type.Name() == "Time" && ft.Type.PkgPath() == "time" {
|
||||||
|
obj[ft.Name] = fo.Interface().(time.Time).Format(time.DateTime)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
@ -46,6 +51,11 @@ func getFieldTypeDtoDescInfo(projectId string, poValue reflect.Value, fieldType
|
|||||||
Required: fieldType.Tag.Get("required") == "true",
|
Required: fieldType.Tag.Get("required") == "true",
|
||||||
Choices: make([]*dto.CommonDtoFieldChoice, 0),
|
Choices: make([]*dto.CommonDtoFieldChoice, 0),
|
||||||
MultiChoice: fieldType.Tag.Get("multi_choice") == "true",
|
MultiChoice: fieldType.Tag.Get("multi_choice") == "true",
|
||||||
|
Uneditable: fieldType.Tag.Get("uneditable") == "true",
|
||||||
|
}
|
||||||
|
|
||||||
|
if f1.Key == "CreatedAt" {
|
||||||
|
f1.Name = "创建时间"
|
||||||
}
|
}
|
||||||
|
|
||||||
if tagType := fieldType.Tag.Get("type"); tagType != "" {
|
if tagType := fieldType.Tag.Get("type"); tagType != "" {
|
||||||
@ -114,7 +124,9 @@ func parseStr2FieldValue(field reflect.StructField, rawValue any) (realSetValue
|
|||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
typeName := field.Type.Name()
|
typeName := field.Type.Name()
|
||||||
if typeName == "Time" {
|
if typeName == "Time" {
|
||||||
return reflect.ValueOf(time.Now())
|
xlog.Debugf("time content:%v", setValue)
|
||||||
|
t, _ := time.ParseInLocation("2006/01/02 15:04:05", setValue, time.Local)
|
||||||
|
return reflect.ValueOf(t)
|
||||||
}
|
}
|
||||||
if typeName == "DeletedAt" {
|
if typeName == "DeletedAt" {
|
||||||
return reflect.ValueOf(gorm.DeletedAt{})
|
return reflect.ValueOf(gorm.DeletedAt{})
|
||||||
@ -124,29 +136,43 @@ func parseStr2FieldValue(field reflect.StructField, rawValue any) (realSetValue
|
|||||||
typeName := field.Type.String()
|
typeName := field.Type.String()
|
||||||
if typeName == "[]string" {
|
if typeName == "[]string" {
|
||||||
list := make([]string, 0)
|
list := make([]string, 0)
|
||||||
if _, ok := rawValue.(string); ok {
|
if rawValueStr, ok := rawValue.(string); ok {
|
||||||
|
elems := strings.Split(rawValueStr, ",")
|
||||||
|
list = append(list, elems...)
|
||||||
// 空的字符串
|
// 空的字符串
|
||||||
} else {
|
} else {
|
||||||
for _, v := range rawValue.([]interface{}) {
|
if rawValueList, ok := rawValue.([]string); ok {
|
||||||
list = append(list, v.(string))
|
for _, v := range rawValueList {
|
||||||
|
list = append(list, v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, v := range rawValue.([]interface{}) {
|
||||||
|
list = append(list, v.(string))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parsedValue = list
|
parsedValue = list
|
||||||
} else if typeName == "[]*model.MailAttachItem" {
|
} else if typeName == "[]*model.MailAttachItem" {
|
||||||
items := make([]*model.MailAttachItem, 0)
|
items := make([]*model.MailAttachItem, 0)
|
||||||
for _, itemI := range rawValue.([]interface{}) {
|
if rawValueList, ok := rawValue.([]*model.MailAttachItem); ok {
|
||||||
item := &model.MailAttachItem{}
|
for _, item := range rawValueList {
|
||||||
for k, vI := range itemI.(map[string]any) {
|
items = append(items, item)
|
||||||
v := vI.(float64)
|
}
|
||||||
if k == "id" {
|
} else {
|
||||||
item.ID = int32(v)
|
for _, itemI := range rawValue.([]interface{}) {
|
||||||
} else if k == "num" {
|
item := &model.MailAttachItem{}
|
||||||
item.Num = int64(v)
|
for k, vI := range itemI.(map[string]any) {
|
||||||
} else if k == "item_type" {
|
v := vI.(float64)
|
||||||
item.ItemType = int(v)
|
if k == "id" {
|
||||||
}
|
item.ID = int32(v)
|
||||||
|
} else if k == "num" {
|
||||||
|
item.Num = int64(v)
|
||||||
|
} else if k == "item_type" {
|
||||||
|
item.ItemType = int(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
items = append(items, item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedValue = items
|
parsedValue = items
|
||||||
|
@ -15,6 +15,7 @@ type ProjectService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewProjectService(db *gorm.DB) *ProjectService {
|
func NewProjectService(db *gorm.DB) *ProjectService {
|
||||||
|
repo.ServerRepoInstance = repo.NewServerRepo(db)
|
||||||
return &ProjectService{repo: repo.NewProjectRepo(db)}
|
return &ProjectService{repo: repo.NewProjectRepo(db)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +9,12 @@ import (
|
|||||||
var projectsResourceHookMgr = map[string]map[string]any{
|
var projectsResourceHookMgr = map[string]map[string]any{
|
||||||
// 神魔大陆项目注册的资源钩子回调
|
// 神魔大陆项目注册的资源钩子回调
|
||||||
consts.RegisteredProjectId_shenmodalu: {
|
consts.RegisteredProjectId_shenmodalu: {
|
||||||
consts.ResourcesName_Server: &smdl.ServerHook{}, // 查看了数据库所有数据之后,还要连alisrv获取所有进程运行情况
|
consts.ResourcesName_Server: &smdl.ServerHook{}, // 查看了数据库所有数据之后,还要连alisrv获取所有进程运行情况
|
||||||
consts.ResourcesName_Role: &smdl.RoleHook{}, // 所有角色走神魔大陆api直接获取
|
consts.ResourcesName_Role: &smdl.RoleHook{}, // 所有角色走神魔大陆api直接获取
|
||||||
consts.ResourcesName_Account: &smdl.AccountHook{}, // 所有角色走神魔大陆api直接获取
|
consts.ResourcesName_Account: &smdl.AccountHook{}, // 所有角色走神魔大陆api直接获取
|
||||||
consts.ResourcesName_Ban: &smdl.BanHook{}, // 所有角色走神魔大陆api直接获取
|
consts.ResourcesName_Ban: &smdl.BanHook{}, // 所有角色走神魔大陆api直接获取
|
||||||
|
consts.ResourcesName_MailGlobal: &smdl.MailGlobalHook{}, // 所有角色走神魔大陆api直接获取
|
||||||
|
consts.ResourcesName_MailRole: &smdl.MailRoleHook{}, // 所有角色走神魔大陆api直接获取
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
"admin/lib/httpclient"
|
"admin/lib/httpclient"
|
||||||
|
"admin/lib/utils"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,9 +26,9 @@ func (hook *AccountHook) List(projectInfo *entity.Project, resource string, page
|
|||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data struct {
|
Data struct {
|
||||||
Data []struct {
|
Data []struct {
|
||||||
Account string `json:"account"`
|
Account string `json:"account"`
|
||||||
ServerId int `json:"serverId"`
|
ServerId int `json:"serverId"`
|
||||||
RoleList []*model.Role `json:"roleList"`
|
RoleList []*Role `json:"roleList"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
@ -43,9 +45,19 @@ func (hook *AccountHook) List(projectInfo *entity.Project, resource string, page
|
|||||||
Account: user.Account,
|
Account: user.Account,
|
||||||
ServerConfId: strconv.Itoa(user.ServerId),
|
ServerConfId: strconv.Itoa(user.ServerId),
|
||||||
}
|
}
|
||||||
|
latestLoginTime := int64(0)
|
||||||
|
earliestCreateTime := int64(math.MaxInt64)
|
||||||
for _, v := range user.RoleList {
|
for _, v := range user.RoleList {
|
||||||
userPo.RoleIds = append(userPo.RoleIds, v.RoleId)
|
userPo.RoleIds = append(userPo.RoleIds, v.RoleId)
|
||||||
|
if latestLoginTime < v.LatestLoginTime {
|
||||||
|
latestLoginTime = v.LatestLoginTime
|
||||||
|
}
|
||||||
|
if earliestCreateTime > v.CreateTime {
|
||||||
|
earliestCreateTime = v.CreateTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
userPo.LatestLoginTime = utils.ParseUnixTimestamp2LocalTime(latestLoginTime)
|
||||||
|
userPo.CreateTime = utils.ParseUnixTimestamp2LocalTime(earliestCreateTime)
|
||||||
et := (&entity.CommonResource{}).FromPo(userPo)
|
et := (&entity.CommonResource{}).FromPo(userPo)
|
||||||
rows = append(rows, et.ToCommonDto())
|
rows = append(rows, et.ToCommonDto())
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,15 @@ func (hook *BanHook) Create(projectInfo *entity.Project, resource string, dtoObj
|
|||||||
params.Add("server", banInfo.ServerConfID)
|
params.Add("server", banInfo.ServerConfID)
|
||||||
params.Add("roleid", roleId)
|
params.Add("roleid", roleId)
|
||||||
|
|
||||||
if banInfo.ExpireAt <= 0 {
|
expireAt := banInfo.ExpireAt.Unix()
|
||||||
|
|
||||||
|
if expireAt <= 0 {
|
||||||
// 解封
|
// 解封
|
||||||
params.Add("forbidtime", "0")
|
params.Add("forbidtime", "0")
|
||||||
params.Add("desc", "待写原因")
|
params.Add("desc", "待写原因")
|
||||||
params.Add("desc", "你被永久封禁了")
|
params.Add("desc", "你被永久封禁了")
|
||||||
} else {
|
} else {
|
||||||
dura := banInfo.ExpireAt - time.Now().Unix()
|
dura := expireAt - time.Now().Unix()
|
||||||
if dura <= 0 {
|
if dura <= 0 {
|
||||||
// 解封
|
// 解封
|
||||||
params.Add("forbidtime", "0")
|
params.Add("forbidtime", "0")
|
||||||
|
@ -2,10 +2,12 @@ package smdl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/apps/game/domain/entity"
|
"admin/apps/game/domain/entity"
|
||||||
|
"admin/apps/game/domain/repo"
|
||||||
"admin/apps/game/model"
|
"admin/apps/game/model"
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
"admin/lib/httpclient"
|
"admin/lib/httpclient"
|
||||||
|
"admin/lib/xlog"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -45,7 +47,15 @@ func (hook *MailGlobalHook) Create(projectInfo *entity.Project, resource string,
|
|||||||
serverIdsLen := len(mailInfo.ServerIDs)
|
serverIdsLen := len(mailInfo.ServerIDs)
|
||||||
switch {
|
switch {
|
||||||
case serverIdsLen == 0:
|
case serverIdsLen == 0:
|
||||||
// todo 所有服
|
// 为空就发给所有服
|
||||||
|
serverList, err := repo.ServerRepoInstance.List(projectInfo.ProjectPo.ProjectId)
|
||||||
|
if err != nil {
|
||||||
|
xlog.Errorf("list all server by project:%v error:%v", projectInfo.ProjectPo.ProjectId, err)
|
||||||
|
return errcode.New(errcode.ServerError, "list all server by project:%v error:%v", projectInfo.ProjectPo.ProjectId, err)
|
||||||
|
}
|
||||||
|
for _, v := range serverList {
|
||||||
|
serverIds = append(serverIds, v.ToPo().(*model.Server).ServerConfID)
|
||||||
|
}
|
||||||
case serverIdsLen > 0:
|
case serverIdsLen > 0:
|
||||||
for _, v := range mailInfo.ServerIDs {
|
for _, v := range mailInfo.ServerIDs {
|
||||||
serverIds = append(serverIds, v)
|
serverIds = append(serverIds, v)
|
||||||
@ -60,8 +70,16 @@ func (hook *MailGlobalHook) Create(projectInfo *entity.Project, resource string,
|
|||||||
|
|
||||||
// 通知对应服务器
|
// 通知对应服务器
|
||||||
for _, serverId := range serverIds {
|
for _, serverId := range serverIds {
|
||||||
|
serverIdInt, _ := strconv.Atoi(serverId)
|
||||||
|
if serverIdInt == 0 || serverIdInt%10000 > 500 {
|
||||||
|
// 过滤掉20801 28802这些跨服
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
params.Set("server", serverId)
|
params.Set("server", serverId)
|
||||||
|
|
||||||
|
xlog.Debugf("通知神魔大陆区服%v添加邮件:%v", serverId, params.Encode())
|
||||||
|
|
||||||
rsp := make(map[string]any)
|
rsp := make(map[string]any)
|
||||||
err := httpclient.Request(alisrvAddr+"/mail_global", "get", params, &rsp)
|
err := httpclient.Request(alisrvAddr+"/mail_global", "get", params, &rsp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
"admin/lib/httpclient"
|
"admin/lib/httpclient"
|
||||||
|
"admin/lib/xlog"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -49,6 +50,8 @@ func (hook *MailRoleHook) Create(projectInfo *entity.Project, resource string, d
|
|||||||
|
|
||||||
// 通知对应服务器
|
// 通知对应服务器
|
||||||
for _, roleId := range mailInfo.RoleIDs {
|
for _, roleId := range mailInfo.RoleIDs {
|
||||||
|
params.Set("playerid", roleId)
|
||||||
|
xlog.Debugf("发送神魔大陆个人邮件给角色:%v, 内容:%v", roleId, params.Encode())
|
||||||
rsp := make(map[string]any)
|
rsp := make(map[string]any)
|
||||||
err := httpclient.Request(alisrvAddr+"/mail_role", "get", params, &rsp)
|
err := httpclient.Request(alisrvAddr+"/mail_role", "get", params, &rsp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -6,8 +6,21 @@ import (
|
|||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
"admin/lib/httpclient"
|
"admin/lib/httpclient"
|
||||||
|
"admin/lib/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
RoleId string `json:"roleId"`
|
||||||
|
Account string `json:"account"`
|
||||||
|
ServerConfId string `json:"serverId"`
|
||||||
|
Name string `json:"roleName"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Level int `json:"roleLevel"`
|
||||||
|
Profession string `json:"profession"`
|
||||||
|
LatestLoginTime int64 `json:"latestLoginAt"`
|
||||||
|
CreateTime int64 `json:"createAt"`
|
||||||
|
}
|
||||||
|
|
||||||
type RoleHook struct {
|
type RoleHook struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +35,7 @@ func (hook *RoleHook) List(projectInfo *entity.Project, resource string, pageNo,
|
|||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data struct {
|
Data struct {
|
||||||
Data []*model.Role `json:"data"`
|
Data []*Role `json:"data"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +46,18 @@ func (hook *RoleHook) List(projectInfo *entity.Project, resource string, pageNo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, role := range rsp.Data.Data {
|
for _, role := range rsp.Data.Data {
|
||||||
et := (&entity.CommonResource{}).FromPo(role)
|
rolePo := &model.Role{
|
||||||
|
RoleId: role.RoleId,
|
||||||
|
Account: role.Account,
|
||||||
|
ServerConfId: role.ServerConfId,
|
||||||
|
Name: role.Name,
|
||||||
|
Status: role.Status,
|
||||||
|
Level: role.Level,
|
||||||
|
Profession: role.Profession,
|
||||||
|
LatestLoginTime: utils.ParseUnixTimestamp2LocalTime(role.LatestLoginTime),
|
||||||
|
CreateTime: utils.ParseUnixTimestamp2LocalTime(role.CreateTime),
|
||||||
|
}
|
||||||
|
et := (&entity.CommonResource{}).FromPo(rolePo)
|
||||||
rows = append(rows, et.ToCommonDto())
|
rows = append(rows, et.ToCommonDto())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,9 @@ func (hook *ServerHook) List(projectInfo *entity.Project, resource string, pageN
|
|||||||
HelpText: "进程运行状态:未知、运行中、停止",
|
HelpText: "进程运行状态:未知、运行中、停止",
|
||||||
Readonly: false,
|
Readonly: false,
|
||||||
Required: false,
|
Required: false,
|
||||||
Choices: nil,
|
Choices: make([]*dto.CommonDtoFieldChoice, 0),
|
||||||
MultiChoice: false,
|
MultiChoice: false,
|
||||||
|
Uneditable: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
type ServerInfo struct {
|
type ServerInfo struct {
|
||||||
|
36
admin/apps/game/domain/repo/server.go
Normal file
36
admin/apps/game/domain/repo/server.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"admin/apps/game/domain/entity"
|
||||||
|
"admin/apps/game/model"
|
||||||
|
"admin/internal/errcode"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ServerRepoInstance IServerRepo
|
||||||
|
|
||||||
|
type IServerRepo interface {
|
||||||
|
List(projectId string) ([]*entity.CommonResource, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServerRepo(db *gorm.DB) IServerRepo {
|
||||||
|
return &serverRepoImpl{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverRepoImpl struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *serverRepoImpl) List(projectId string) ([]*entity.CommonResource, error) {
|
||||||
|
list := make([]*model.Server, 0)
|
||||||
|
err := impl.db.Where("project_id = ?", projectId).Find(&list).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, errcode.New(errcode.DBError, "list server error:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
list1 := make([]*entity.CommonResource, 0, len(list))
|
||||||
|
for _, v := range list {
|
||||||
|
list1 = append(list1, (&entity.CommonResource{}).FromPo(v))
|
||||||
|
}
|
||||||
|
return list1, nil
|
||||||
|
}
|
@ -2,6 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -10,11 +11,11 @@ func init() {
|
|||||||
|
|
||||||
// Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
// Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
||||||
type Account struct {
|
type Account struct {
|
||||||
Account string `name:"账号" json:"account"`
|
Account string `name:"账号" json:"account"`
|
||||||
ServerConfId string `name:"区服id" json:"serveId"`
|
ServerConfId string `name:"区服id" json:"serveId"`
|
||||||
RoleIds []string `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"`
|
RoleIds []string `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"`
|
||||||
LatestLoginTime int64 `name:"最近登录时间" json:"latest_login_time"`
|
LatestLoginTime time.Time `name:"最近登录时间" json:"latest_login_time"`
|
||||||
CreateTime int64 `name:"创建时间" json:"create_time"`
|
CreateTime time.Time `name:"创建时间" json:"create_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Account) TableName() string {
|
func (lm *Account) TableName() string {
|
||||||
|
@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,16 +11,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Ban struct {
|
type Ban struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string `gorm:"type:varchar(255);uniqueIndex:idx_ban"`
|
ProjectId string `gorm:"type:varchar(255);uniqueIndex:idx_ban"`
|
||||||
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" required:"true"`
|
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" choices:"GetServerConfIDChoices" uneditable:"true"`
|
||||||
BanType string `name:"封禁类型" required:"true" choices:"GetBanTypeChoices" multi_choice:"true"`
|
BanType string `name:"封禁类型" required:"true" choices:"GetBanTypeChoices" uneditable:"true"`
|
||||||
Value string `gorm:"type:varchar(128);uniqueIndex:idx_ban" name:"封禁账号" required:"true" desc:"填账号"`
|
Value string `gorm:"type:varchar(128);uniqueIndex:idx_ban" name:"封禁值" required:"true" desc:"根据封禁类型填对应值,例如ip就填ip地址" uneditable:"true"`
|
||||||
ExpireAt int64 `name:"封禁到期时间" desc:"封禁到期时间,0表示永久封禁"`
|
BanReason string `name:"封禁理由" desc:"封禁理由,会推送给客户端弹窗" required:"true"`
|
||||||
|
ExpireAt time.Time `name:"封禁到期时间" desc:"封禁到期时间,0表示永久封禁"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Ban) TableName() string {
|
func (lm *Ban) TableName() string {
|
||||||
@ -32,15 +30,35 @@ func (m *Ban) GetId() int {
|
|||||||
return m.ID
|
return m.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Ban) GetServerConfIDChoices(projectId string) []*dto.CommonDtoFieldChoice {
|
||||||
|
return getChoiceServers(projectId)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Ban) GetBanTypeChoices(projectId string) []*dto.CommonDtoFieldChoice {
|
func (m *Ban) GetBanTypeChoices(projectId string) []*dto.CommonDtoFieldChoice {
|
||||||
return []*dto.CommonDtoFieldChoice{
|
return []*dto.CommonDtoFieldChoice{
|
||||||
{
|
{
|
||||||
Desc: "作弊",
|
Desc: "账号",
|
||||||
Value: "作弊",
|
Value: "account",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Desc: "广告",
|
Desc: "角色",
|
||||||
Value: "广告",
|
Value: "role",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Desc: "IP",
|
||||||
|
Value: "ip",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Desc: "账号发言",
|
||||||
|
Value: "account_chat",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Desc: "角色发言",
|
||||||
|
Value: "role_chat",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Desc: "设备号",
|
||||||
|
Value: "device_id",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,9 +16,7 @@ type DevicePush struct {
|
|||||||
Title string `name:"通知标题" desc:""`
|
Title string `name:"通知标题" desc:""`
|
||||||
Content string `name:"通知内容"`
|
Content string `name:"通知内容"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *DevicePush) TableName() string {
|
func (lm *DevicePush) TableName() string {
|
||||||
|
@ -36,6 +36,7 @@ type CommonDtoFieldDesc struct {
|
|||||||
Required bool `json:"required"` // 是否必填,不能为空
|
Required bool `json:"required"` // 是否必填,不能为空
|
||||||
Choices []*CommonDtoFieldChoice `json:"choices"` // 可选项,用于字段做下拉框
|
Choices []*CommonDtoFieldChoice `json:"choices"` // 可选项,用于字段做下拉框
|
||||||
MultiChoice bool `json:"multi_choice"` // 是否多选
|
MultiChoice bool `json:"multi_choice"` // 是否多选
|
||||||
|
Uneditable bool `json:"uneditable"` // 不可编辑,某些数据一旦新增之后不能修改,例如封禁的值、服务器的id等
|
||||||
}
|
}
|
||||||
|
|
||||||
//type CommonDtoValue struct {
|
//type CommonDtoValue struct {
|
||||||
|
@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,9 +20,7 @@ type GlobalMail struct {
|
|||||||
Content string `name:"邮件内容" required:"true"`
|
Content string `name:"邮件内容" required:"true"`
|
||||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" choices:"GetChoiceItems"`
|
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" choices:"GetChoiceItems"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *GlobalMail) TableName() string {
|
func (lm *GlobalMail) TableName() string {
|
||||||
|
@ -11,8 +11,8 @@ type IModel interface {
|
|||||||
|
|
||||||
var GetProjectServersHandler func(projectId string) ([]*Server, error)
|
var GetProjectServersHandler func(projectId string) ([]*Server, error)
|
||||||
|
|
||||||
func getChoiceServers(args ...any) []*dto.CommonDtoFieldChoice {
|
func getChoiceServers(projectId string) []*dto.CommonDtoFieldChoice {
|
||||||
servers, err := GetProjectServersHandler(args[0].(string))
|
servers, err := GetProjectServersHandler(projectId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,14 +13,12 @@ func init() {
|
|||||||
type Notice struct {
|
type Notice struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string
|
ProjectId string
|
||||||
ServerIDs []int `gorm:"type:json;serializer:json" name:"公告生效服务器" desc:"为空表示所有服" choices:"GetChoiceServers"`
|
ServerIDs []int `gorm:"type:json;serializer:json" name:"公告生效服务器" desc:"为空表示所有服" choices:"GetChoiceServers"`
|
||||||
Content string `name:"公告内容" required:"true"`
|
Content string `name:"公告内容" required:"true"`
|
||||||
StartAt int64 `name:"开始时间" required:"true"`
|
StartAt time.Time `name:"开始时间" required:"true"`
|
||||||
EndAt int64 `name:"结束时间" required:"true"`
|
EndAt time.Time `name:"结束时间" required:"true"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Notice) TableName() string {
|
func (lm *Notice) TableName() string {
|
||||||
|
@ -2,7 +2,6 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ func init() {
|
|||||||
type Project struct {
|
type Project struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string `gorm:"type:varchar(255);unique" name:"项目id" readonly:"true"`
|
ProjectId string `gorm:"type:varchar(255);unique" name:"项目id" readonly:"true"`
|
||||||
Name string `gorm:"primarykey" required:"true" name:"项目名" readonly:"true"`
|
Name string `gorm:"primarykey" required:"true" name:"项目名" readonly:"true" uneditable:"true"`
|
||||||
Desc string `name:"项目描述"`
|
Desc string `name:"项目描述"`
|
||||||
// command_list接口服务器地址,为空代表由由项目下各个逻辑服提供command_list.
|
// command_list接口服务器地址,为空代表由由项目下各个逻辑服提供command_list.
|
||||||
// 取决于每个项目改造难度:
|
// 取决于每个项目改造难度:
|
||||||
@ -23,9 +22,7 @@ type Project struct {
|
|||||||
// 调用各个逻辑服执行,本后台执行指令需要根据逻辑服数量调用;
|
// 调用各个逻辑服执行,本后台执行指令需要根据逻辑服数量调用;
|
||||||
ApiAddr string `name:"游戏api地址" desc:"api服务器地址,例如神魔大陆就是alisrv服务器地址,用于后台调用gm"`
|
ApiAddr string `name:"游戏api地址" desc:"api服务器地址,例如神魔大陆就是alisrv服务器地址,用于后台调用gm"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Project) TableName() string {
|
func (lm *Project) TableName() string {
|
||||||
|
@ -2,7 +2,6 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,9 +15,7 @@ type RewardCode struct {
|
|||||||
Group int `name:"奖励码组"`
|
Group int `name:"奖励码组"`
|
||||||
Code int `name:"奖励码"`
|
Code int `name:"奖励码"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *RewardCode) TableName() string {
|
func (lm *RewardCode) TableName() string {
|
||||||
|
@ -2,6 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -10,15 +11,15 @@ func init() {
|
|||||||
|
|
||||||
// Role 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
// Role 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
||||||
type Role struct {
|
type Role struct {
|
||||||
RoleId string `name:"账号" json:"roleId"`
|
RoleId string `name:"角色ID" json:"roleId"`
|
||||||
Account string `name:"账号" json:"account"`
|
Account string `name:"账号" json:"account"`
|
||||||
ServerConfId string `name:"区服id" json:"serverId"`
|
ServerConfId string `name:"区服id" json:"serverId"`
|
||||||
Name string `name:"名称" json:"roleName"`
|
Name string `name:"名称" json:"roleName"`
|
||||||
Status string `name:"状态" desc:"离线|在线" json:"status"`
|
Status string `name:"状态" desc:"离线|在线" json:"status"`
|
||||||
Level int `name:"等级" json:"roleLevel"`
|
Level int `name:"等级" json:"roleLevel"`
|
||||||
Profession string `name:"职业" json:"profession"`
|
Profession string `name:"职业" json:"profession"`
|
||||||
LatestLoginTime int64 `name:"最近登录时间" json:"latestLoginAt"`
|
LatestLoginTime time.Time `name:"最近登录时间" json:"latestLoginAt"`
|
||||||
CreateTime int64 `name:"创建时间" json:"createAt"`
|
CreateTime time.Time `name:"创建时间" json:"createAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Role) TableName() string {
|
func (lm *Role) TableName() string {
|
||||||
|
@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,15 +19,13 @@ type MailAttachItem struct {
|
|||||||
type RoleMail struct {
|
type RoleMail struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string
|
ProjectId string
|
||||||
RoleIDs []string `gorm:"type:json;serializer:json" name:"生效的角色id" required:"true"`
|
RoleIDs []string `gorm:"type:json;serializer:json" name:"生效的角色id" desc:"生效的角色id,逗号分隔多个" required:"true"`
|
||||||
ServerID string `name:"所属区服" choices:"GetChoiceServers" multi_choice:"false"`
|
ServerID string `name:"所属区服" choices:"GetChoiceServers" required:"true"`
|
||||||
Title string `name:"邮件标题" required:"true"`
|
Title string `name:"邮件标题" required:"true"`
|
||||||
Content string `name:"邮件内容" required:"true"`
|
Content string `name:"邮件内容" required:"true"`
|
||||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" choices:"GetChoiceItems"`
|
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" choices:"GetChoiceItems"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *RoleMail) TableName() string {
|
func (lm *RoleMail) TableName() string {
|
||||||
|
@ -2,7 +2,6 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,18 +13,16 @@ func init() {
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string `gorm:"type:varchar(200);uniqueIndex:idx_server"`
|
ProjectId string `gorm:"type:varchar(200);uniqueIndex:idx_server"`
|
||||||
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" required:"true"`
|
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" uneditable:"true"`
|
||||||
Desc string
|
Desc string `name:"描述"`
|
||||||
// command_list接口服务器地址,为空代表由由项目统一提供command_list.
|
// command_list接口服务器地址,为空代表由由项目统一提供command_list.
|
||||||
// 取决于每个项目改造难度:
|
// 取决于每个项目改造难度:
|
||||||
// 为空就代表项目要实现一个自己统一对外暴露的gm调用服务对内聚合、分发指令执行,本后台执行指令只调用一次;
|
// 为空就代表项目要实现一个自己统一对外暴露的gm调用服务对内聚合、分发指令执行,本后台执行指令只调用一次;
|
||||||
// 不为空就代表command_list实现在各个逻辑服,由本后台系统在执行指令时聚合、分发指令
|
// 不为空就代表command_list实现在各个逻辑服,由本后台系统在执行指令时聚合、分发指令
|
||||||
// 调用各个逻辑服执行,本后台执行指令需要根据逻辑服数量调用;
|
// 调用各个逻辑服执行,本后台执行指令需要根据逻辑服数量调用;
|
||||||
ApiAddr string
|
//ApiAddr string
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Server) TableName() string {
|
func (lm *Server) TableName() string {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/db"
|
"admin/internal/db"
|
||||||
"gorm.io/gorm"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,14 +13,11 @@ func init() {
|
|||||||
type WhiteList struct {
|
type WhiteList struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId string `gorm:"type:varchar(256);uniqueIndex:idx_whitelist"`
|
ProjectId string `gorm:"type:varchar(256);uniqueIndex:idx_whitelist"`
|
||||||
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" required:"true"`
|
ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" choices:"GetChoiceServers"`
|
||||||
Account string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist"`
|
Account string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账户" required:"true"`
|
||||||
AccountType int `gorm:"uniqueIndex:idx_whitelist"`
|
Desc string `name:"描述"`
|
||||||
Desc string
|
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true"`
|
||||||
UpdatedAt time.Time `readonly:"true"`
|
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" readonly:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *WhiteList) TableName() string {
|
func (lm *WhiteList) TableName() string {
|
||||||
@ -30,3 +27,7 @@ func (lm *WhiteList) TableName() string {
|
|||||||
func (m *WhiteList) GetId() int {
|
func (m *WhiteList) GetId() int {
|
||||||
return m.ID
|
return m.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *WhiteList) GetChoiceServers(projectId string) []*dto.CommonDtoFieldChoice {
|
||||||
|
return getChoiceServers(projectId)
|
||||||
|
}
|
||||||
|
44
admin/lib/utils/time.go
Normal file
44
admin/lib/utils/time.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseUnixTimestamp2LocalTime(ts int64) (local time.Time) {
|
||||||
|
sec := int64(0)
|
||||||
|
nsec := int64(0)
|
||||||
|
switch {
|
||||||
|
case ts >= 1e18: // 纳秒
|
||||||
|
sec = ts / int64(1e9)
|
||||||
|
nsec = ts % int64(1e9)
|
||||||
|
case ts >= 1e15: // 微妙
|
||||||
|
sec = ts / int64(1e6)
|
||||||
|
nsec = ts % int64(1e6)
|
||||||
|
case ts >= 1e12: // 毫秒
|
||||||
|
sec = ts / int64(1e3)
|
||||||
|
nsec = ts % int64(1e3)
|
||||||
|
case ts >= 1e9: // 秒
|
||||||
|
sec = ts
|
||||||
|
nsec = 0
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("ts:%v invalid parse to local time"))
|
||||||
|
}
|
||||||
|
|
||||||
|
t := time.Unix(sec, nsec)
|
||||||
|
ts2str := t.Format("2006-01-02 15:04:05.000000000")
|
||||||
|
local, _ = time.ParseInLocation("2006-01-02 15:04:05.000000000", ts2str, time.Local)
|
||||||
|
return local
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTimeZoneLocalTime 获取指定时区的当地时间
|
||||||
|
func GetTimeZoneLocalTime(timeZone int) time.Time {
|
||||||
|
offsetZone := time.FixedZone(time.Local.String(), timeZone*60*60)
|
||||||
|
return time.Now().In(offsetZone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTimeZoneLocalTimeByTimestamp 获取指定时间戳与时区的当地时间
|
||||||
|
func GetTimeZoneLocalTimeByTimestamp(ts int64, timeZone int) time.Time {
|
||||||
|
offsetZone := time.FixedZone(time.Local.String(), timeZone*60*60)
|
||||||
|
return time.Unix(ts, 0).Local().In(offsetZone)
|
||||||
|
}
|
@ -1,4 +1,29 @@
|
|||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
color: var(--color-text);
|
||||||
|
background: var(--color-background);
|
||||||
|
transition: color 0.5s,
|
||||||
|
background-color 0.5s;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-family: Inter,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
Oxygen,
|
||||||
|
Ubuntu,
|
||||||
|
Cantarell,
|
||||||
|
'Fira Sans',
|
||||||
|
'Droid Sans',
|
||||||
|
'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
.el-table {
|
.el-table {
|
||||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||||
th {
|
th {
|
||||||
@ -32,4 +57,4 @@
|
|||||||
|
|
||||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,13 @@ const listData = async () => {
|
|||||||
for (let i = 0; i < fieldsDescInfo.value.length; i++) {
|
for (let i = 0; i < fieldsDescInfo.value.length; i++) {
|
||||||
var field = fieldsDescInfo.value[i]
|
var field = fieldsDescInfo.value[i]
|
||||||
dialogAddForm.value[field.key] = ''
|
dialogAddForm.value[field.key] = ''
|
||||||
|
|
||||||
if (field.required == true) {
|
if (field.required == true) {
|
||||||
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
|
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field.type == "items") {
|
if (field.type == "items") {
|
||||||
|
dialogAddForm.value[field.key] = []
|
||||||
for (let j = 0; j < rows.value.length; j++) {
|
for (let j = 0; j < rows.value.length; j++) {
|
||||||
rows.value[j].jsonValue = JSON.stringify(rows.value[j][field.key])
|
rows.value[j].jsonValue = JSON.stringify(rows.value[j][field.key])
|
||||||
}
|
}
|
||||||
@ -71,6 +73,7 @@ const dialogEditFormRef = ref(null)
|
|||||||
|
|
||||||
const dialogAddForm = ref({
|
const dialogAddForm = ref({
|
||||||
ServerIDs: [],
|
ServerIDs: [],
|
||||||
|
Attach: [],
|
||||||
})
|
})
|
||||||
const dialogEditForm = ref({})
|
const dialogEditForm = ref({})
|
||||||
|
|
||||||
@ -90,6 +93,7 @@ const submitAdd = async () => {
|
|||||||
})
|
})
|
||||||
rows.value.push(res.data.dto)
|
rows.value.push(res.data.dto)
|
||||||
dialogAddVisible.value = false
|
dialogAddVisible.value = false
|
||||||
|
handleCloseDialog()
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
console.log("添加报错:", err)
|
console.log("添加报错:", err)
|
||||||
})
|
})
|
||||||
@ -115,6 +119,7 @@ const submitEdit = async () => {
|
|||||||
})
|
})
|
||||||
dialogEditVisible.value = false
|
dialogEditVisible.value = false
|
||||||
rows.value[dialogEditForm.value.oldIndex] = res.data.dto
|
rows.value[dialogEditForm.value.oldIndex] = res.data.dto
|
||||||
|
handleCloseDialog()
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
console.log("添加报错:", err)
|
console.log("添加报错:", err)
|
||||||
})
|
})
|
||||||
@ -135,18 +140,22 @@ const handleEdit = (index, row) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleDelete = (index, row) => {
|
const handleDelete = (index, row) => {
|
||||||
resourceDelete(resource_url, {id: row.ID}).then((res) => {
|
ElMessageBox.confirm("确定要删除吗?").then(() => {
|
||||||
ElNotification({
|
resourceDelete(resource_url, {id: row.ID}).then((res) => {
|
||||||
title: "删除结果通知",
|
ElNotification({
|
||||||
message: "删除指令服务器[" + row.name + "]成功!",
|
title: "删除结果通知",
|
||||||
type: 'success',
|
message: "删除数据[" + row.ID + "]成功!",
|
||||||
duration: 4000,
|
type: 'success',
|
||||||
"show-close": true,
|
duration: 4000,
|
||||||
|
"show-close": true,
|
||||||
|
})
|
||||||
|
rows.value.splice(index, 1)
|
||||||
|
}, (err) => {
|
||||||
|
console.log("delet error:", err)
|
||||||
})
|
})
|
||||||
rows.value.splice(index, 1)
|
}).catch(() => {
|
||||||
}, (err) => {
|
|
||||||
console.log("delet error:", err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addItem(fieldDescInfo) {
|
function addItem(fieldDescInfo) {
|
||||||
@ -184,6 +193,7 @@ function deleteItem(row) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleCloseDialog = () => {
|
const handleCloseDialog = () => {
|
||||||
|
console.log("关闭添加/编辑弹窗")
|
||||||
dialogAddVisible.value = false
|
dialogAddVisible.value = false
|
||||||
dialogEditVisible.value = false
|
dialogEditVisible.value = false
|
||||||
dialogAddForm.value = {
|
dialogAddForm.value = {
|
||||||
@ -213,24 +223,6 @@ const handleCloseDialog = () => {
|
|||||||
<el-table-column prop="func" label="功 能">
|
<el-table-column prop="func" label="功 能">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|
||||||
<!-- <el-button size="default" type="primary"-->
|
|
||||||
<!-- @click="tableRowClick(row_click_btn1, scope.$index, scope.row)"-->
|
|
||||||
<!-- v-if="(row_click_btn1.text !== '')">-->
|
|
||||||
<!-- <el-icon style="vertical-align: middle">-->
|
|
||||||
<!-- <component :is="row_click_btn1.icon"></component>-->
|
|
||||||
<!-- </el-icon>-->
|
|
||||||
<!-- <span>{{ row_click_btn1.text }}</span>-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
|
|
||||||
<!-- <el-button size="default" type="primary"-->
|
|
||||||
<!-- @click="tableRowClick(row_click_btn2, scope.$index, scope.row)"-->
|
|
||||||
<!-- v-if="(row_click_btn2.text !== '')">-->
|
|
||||||
<!-- <el-icon style="vertical-align: middle">-->
|
|
||||||
<!-- <component :is="row_click_btn2.icon"></component>-->
|
|
||||||
<!-- </el-icon>-->
|
|
||||||
<!-- <span>{{ row_click_btn2.text }}</span>-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
|
|
||||||
<el-button size="default" type="success" @click="handleEdit( scope.$index, scope.row)"
|
<el-button size="default" type="success" @click="handleEdit( scope.$index, scope.row)"
|
||||||
v-if="(resource_raw_node.meta.methods.put === true)">
|
v-if="(resource_raw_node.meta.methods.put === true)">
|
||||||
<el-icon style="vertical-align: middle">
|
<el-icon style="vertical-align: middle">
|
||||||
@ -251,15 +243,97 @@ const handleCloseDialog = () => {
|
|||||||
|
|
||||||
<el-dialog v-model="dialogAddVisible" :mask="true" title="添加" :modal="true" :before-close="handleCloseDialog"
|
<el-dialog v-model="dialogAddVisible" :mask="true" title="添加" :modal="true" :before-close="handleCloseDialog"
|
||||||
destroy-on-close>
|
destroy-on-close>
|
||||||
<el-form ref="dialogAddFormRef" :model="dialogAddForm" :rules="rules">
|
<el-form ref="dialogAddFormRef" :model="dialogAddForm" :rules="rules" label-position="right"
|
||||||
|
label-width="130px">
|
||||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||||
<!--如何是items类型,就是物品下拉框+道具组合-->
|
<!--如何是items类型,就是物品下拉框+道具组合-->
|
||||||
<!--如何是[]string类型,就是下拉框或多选框-->
|
|
||||||
<template v-if="(fieldDescInfo.type === 'items')">
|
<template v-if="(fieldDescInfo.type === 'items')">
|
||||||
<el-form :inline="true" :model="item">
|
<el-form :inline="true" :model="item" label-position="right">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key" label-width="130px">
|
||||||
|
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
||||||
|
<el-select placeholder="--选择道具后填数量点击添加--" v-model="item.id" style="width: 150px"
|
||||||
|
filterable>
|
||||||
|
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
||||||
|
:value="info.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数量" prop="num">
|
||||||
|
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="addItem(fieldDescInfo)">添加</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form-item label="奖励列表" prop="Attach">
|
||||||
|
<el-table :data="dialogAddForm.Attach" border>
|
||||||
|
<el-table-column label="道具id" prop="id"/>
|
||||||
|
<el-table-column label="数量" prop="num"/>
|
||||||
|
<el-table-column label="操作">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="danger" size="small" @click="deleteItem(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="(fieldDescInfo.readonly !== true)">
|
||||||
|
<!-- 有可选项的字段,走下拉框或者多选框 -->
|
||||||
|
<template v-if="(fieldDescInfo.choices !== undefined && fieldDescInfo.choices.length > 0)">
|
||||||
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
||||||
<el-select placeholder="可选项" v-model="item.id" style="width: 150px">
|
<el-select :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
|
||||||
|
v-model="dialogAddForm[fieldDescInfo.key]" style="width: 150px"
|
||||||
|
:multiple="(fieldDescInfo.multi_choice === true)">
|
||||||
|
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
||||||
|
:value="info.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 时间戳字段,展示时间选择器 -->
|
||||||
|
<template v-else-if="(fieldDescInfo.type === 'Time')">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-date-picker v-model="dialogAddForm[fieldDescInfo.key]" type="datetime"
|
||||||
|
placeholder="选个时间" format="YYYY/MM/DD HH:mm:ss"
|
||||||
|
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 否则就是普通字段 -->
|
||||||
|
<template v-else>
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-input v-model="dialogAddForm[fieldDescInfo.key]"
|
||||||
|
:placeholder="fieldDescInfo.help_text"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="submitAdd(dialogAddFormRef)" size="large" type="primary">提交</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog v-model="dialogEditVisible" :mask="true" title="编辑" :modal="true" :before-close="handleCloseDialog"
|
||||||
|
destroy-on-close>
|
||||||
|
<el-form ref="dialogEditFormRef" :model="dialogEditForm" :rules="rules" class="operation_form"
|
||||||
|
label-width="130px">
|
||||||
|
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||||
|
|
||||||
|
<!--如果是items类型,就是物品下拉框+道具组合-->
|
||||||
|
<template v-if="(fieldDescInfo.type === 'items')">
|
||||||
|
<el-form :inline="true" :model="item" label-position="right"
|
||||||
|
label-width="130px">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
||||||
|
<el-select placeholder="--选择道具后填数量点击添加--" v-model="item.id" style="width: 150px"
|
||||||
|
filterable>
|
||||||
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
||||||
:value="info.value"></el-option>
|
:value="info.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@ -273,7 +347,7 @@ const handleCloseDialog = () => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-form-item label="奖励列表" prop="attachmentsList">
|
<el-form-item label="奖励列表" prop="attachmentsList">
|
||||||
<el-table :data="dialogAddForm.Attach" border>
|
<el-table :data="dialogEditForm.Attach" border>
|
||||||
<el-table-column label="道具id" prop="id"/>
|
<el-table-column label="道具id" prop="id"/>
|
||||||
<el-table-column label="数量" prop="num"/>
|
<el-table-column label="数量" prop="num"/>
|
||||||
<el-table-column label="操作">
|
<el-table-column label="操作">
|
||||||
@ -285,50 +359,54 @@ const handleCloseDialog = () => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="(fieldDescInfo.type === '[]string')">
|
|
||||||
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
|
||||||
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
|
||||||
<el-select placeholder="可选项" v-model="dialogAddForm.ServerIDs" style="width: 150px"
|
|
||||||
:multiple="(fieldDescInfo.multi_choice === true)">
|
|
||||||
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
|
||||||
:value="info.value"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-tooltip>
|
|
||||||
</el-form-item>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else-if="(fieldDescInfo.readonly !== true)">
|
<template v-else-if="(fieldDescInfo.readonly !== true)">
|
||||||
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
<template v-if="(fieldDescInfo.uneditable !== true)">
|
||||||
<el-input v-model="dialogAddForm[fieldDescInfo.key]" :placeholder="fieldDescInfo.name"></el-input>
|
<!-- 有可选项的字段,走下拉框或者多选框 -->
|
||||||
</el-form-item>
|
<template v-if="(fieldDescInfo.choices !== undefined && fieldDescInfo.choices.length > 0)">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start">
|
||||||
|
<el-select :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
|
||||||
|
v-model="dialogEditForm[fieldDescInfo.key]" style="width: 150px"
|
||||||
|
:multiple="(fieldDescInfo.multi_choice === true)">
|
||||||
|
<el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"
|
||||||
|
:value="info.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 时间戳字段,展示时间选择器 -->
|
||||||
|
<template v-else-if="(fieldDescInfo.type === 'Time')">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-date-picker v-model="dialogEditForm[fieldDescInfo.key]" type="datetime"
|
||||||
|
placeholder="选个时间" format="YYYY/MM/DD HH:mm:ss"
|
||||||
|
value-format="YYYY/MM/DD HH:mm:ss"></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 否则就是普通字段 -->
|
||||||
|
<template v-else>
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-input v-model="dialogEditForm[fieldDescInfo.key]"
|
||||||
|
:placeholder="fieldDescInfo.help_text"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-input v-model="dialogEditForm[fieldDescInfo.key]"
|
||||||
|
:placeholder="fieldDescInfo.help_text" disabled></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- <el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">-->
|
<!-- <el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">-->
|
||||||
<!-- <el-tooltip effect="light" :content="fieldDescInfo.help_text" placement="bottom-start"-->
|
<!-- <el-input v-model="dialogEditForm[fieldDescInfo.key]"></el-input>-->
|
||||||
<!-- v-if="(fieldDescInfo.type === 'items')">-->
|
|
||||||
<!-- <el-select placeholder="可选项">-->
|
|
||||||
<!-- <el-option v-for="info in fieldDescInfo.choices" :key="info.desc" :label="info.desc"-->
|
|
||||||
<!-- :value="info.value"></el-option>-->
|
|
||||||
<!-- </el-select>-->
|
|
||||||
<!-- </el-tooltip>-->
|
|
||||||
<!-- <el-input v-model="dialogAddForm[fieldDescInfo.key]" :placeholder="fieldDescInfo.name" v-else></el-input>-->
|
|
||||||
<!-- </el-form-item>-->
|
<!-- </el-form-item>-->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-button @click="submitAdd(dialogAddFormRef)" size="large" type="primary">提交</el-button>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog v-model="dialogEditVisible" :mask="true" title="编辑" :modal="true" :before-close="handleCloseDialog"
|
|
||||||
destroy-on-close>
|
|
||||||
<el-form ref="dialogEditFormRef" :model="dialogEditForm" :rules="rules">
|
|
||||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
|
||||||
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
|
||||||
<el-input v-model="dialogEditForm[fieldDescInfo.key]"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button @click="submitEdit(dialogEditFormRef)" size="large" type="primary">提交</el-button>
|
<el-button @click="submitEdit(dialogEditFormRef)" size="large" type="primary">提交</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import './assets/main.css'
|
// import './assets/main.css'
|
||||||
|
|
||||||
import {createApp} from 'vue'
|
import {createApp} from 'vue'
|
||||||
import {createPinia} from 'pinia'
|
import {createPinia} from 'pinia'
|
||||||
|
@ -28,11 +28,12 @@ router.beforeEach((to, from, next) => {
|
|||||||
projectList.value = res.data.projects
|
projectList.value = res.data.projects
|
||||||
setProjectOperationRoutes(projectList.value)
|
setProjectOperationRoutes(projectList.value)
|
||||||
// console.log("all routes:", router.getRoutes())
|
// console.log("all routes:", router.getRoutes())
|
||||||
next()
|
next({...to, replace: true}); // 在已有页面里查找
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
console.log("跳转路径:", to.path, " 报错:", err)
|
console.log("跳转路径:", to.path, " 报错:", err)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
console.log("op tree routes length valid:", projectOpTreeRoutes.value.length)
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import LocalCache from "@/stores/project.js";
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|
||||||
// 计算当前激活的菜单项
|
// 计算当前激活的菜单项
|
||||||
const activeMenu = computed(() => route.path)
|
const activeMenu = computed(() => route.path)
|
||||||
|
|
||||||
@ -22,49 +23,76 @@ const handleMenuSelect = (clickResource) => {
|
|||||||
<template>
|
<template>
|
||||||
<main>
|
<main>
|
||||||
<div>
|
<div>
|
||||||
<el-container style="height: 100vh;">
|
<el-container class="layout-container">
|
||||||
<el-aside class="el-aside-demo" width="200px">
|
<el-aside class="el-aside-demo">
|
||||||
<!-- <el-avatar shape="square" :size="100" :src="avatarUrl"></el-avatar>-->
|
<div class="sidebar-content">
|
||||||
<div class="sidebar-logo">
|
<!-- <el-avatar shape="square" :size="100" :src="avatarUrl"></el-avatar>-->
|
||||||
<img src="@/assets/logo.svg" class="logo" alt="Logo">
|
<div class="sidebar-logo">
|
||||||
<span class="system-name">游戏后台管理系统</span>
|
<img src="@/assets/logo.svg" class="logo" alt="Logo">
|
||||||
|
<span class="system-name">游戏后台管理系统</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-menu :default-active="activeMenu" class="el-menu-vertical-demo" :collapse="false">
|
||||||
|
|
||||||
|
<!-- 静态菜单 -->
|
||||||
|
<el-menu-item index="/user" @click="$router.push('/user')">
|
||||||
|
<span>用户管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/project" @click="$router.push('/project')">
|
||||||
|
<span>项目管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
|
<!-- 分割条 -->
|
||||||
|
<el-divider></el-divider>
|
||||||
|
|
||||||
|
<!-- 动态菜单:每个项目操作 -->
|
||||||
|
<template v-for="project in projectOpTreeRoutes">
|
||||||
|
<el-sub-menu :index="project.path">
|
||||||
|
<!-- 设置菜单栏标题 -->
|
||||||
|
<template #title>
|
||||||
|
<span>{{ project.meta.projectName }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 添加项目资源操作点击菜单 -->
|
||||||
|
<el-menu-item v-for="resource in project.children" :key="resource.path" :index="resource.path"
|
||||||
|
@click="handleMenuSelect(resource)">
|
||||||
|
{{ resource.meta.desc }}
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
|
</el-sub-menu>
|
||||||
|
</template>
|
||||||
|
</el-menu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-menu :default-active="activeMenu" class="el-menu-vertical-demo" :collapse="isCollapse">
|
|
||||||
|
|
||||||
<!-- 静态菜单 -->
|
|
||||||
<el-menu-item index="/user" @click="$router.push('/user')">
|
|
||||||
<span>用户管理</span>
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/project" @click="$router.push('/project')">
|
|
||||||
<span>项目管理</span>
|
|
||||||
</el-menu-item>
|
|
||||||
|
|
||||||
<!-- 分割条 -->
|
|
||||||
<el-divider></el-divider>
|
|
||||||
|
|
||||||
<!-- 动态菜单:每个项目操作 -->
|
|
||||||
<template v-for="project in projectOpTreeRoutes">
|
|
||||||
<el-sub-menu :index="project.path">
|
|
||||||
<!-- 设置菜单栏标题 -->
|
|
||||||
<template #title>
|
|
||||||
<span>{{ project.meta.projectName }}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 添加项目资源操作点击菜单 -->
|
|
||||||
<el-menu-item v-for="resource in project.children" :key="resource.path" :index="resource.path"
|
|
||||||
@click="handleMenuSelect(resource)">
|
|
||||||
{{ resource.meta.desc }}
|
|
||||||
</el-menu-item>
|
|
||||||
|
|
||||||
</el-sub-menu>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</el-menu>
|
|
||||||
</el-aside>
|
</el-aside>
|
||||||
|
|
||||||
<el-container class="el-container-right">
|
<el-container class="el-container-right">
|
||||||
<el-header style="border-bottom: #1f2d3d 1px solid">游戏后台管理系统</el-header>
|
<el-header class="el-header-demo">
|
||||||
<el-main>
|
<div class="header-content">
|
||||||
|
<div class="avatar-container">
|
||||||
|
<el-dropdown class="right-menu-item hover-effect" trigger="click">
|
||||||
|
|
||||||
|
<!-- 头像 -->
|
||||||
|
<div class="avatar-wrapper">
|
||||||
|
<img :src="avatarUrl" class="user-avatar"/>
|
||||||
|
<el-icon color="black" size="20">
|
||||||
|
<ArrowDownBold/>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 头像操作下拉菜单 -->
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||||
|
<el-dropdown-item>退出登录</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <el-avatar shape="square" :size="100" :src="avatarUrl"></el-avatar>-->
|
||||||
|
</el-header>
|
||||||
|
<el-main class="el-main-demo">
|
||||||
<router-view :key="$route.fullPath"></router-view>
|
<router-view :key="$route.fullPath"></router-view>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
@ -73,22 +101,7 @@ const handleMenuSelect = (clickResource) => {
|
|||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
.dashboard-container {
|
|
||||||
display: flex;
|
|
||||||
/* 使用flex布局 */
|
|
||||||
justify-content: space-between;
|
|
||||||
/* 子元素之间的间隔 */
|
|
||||||
align-items: flex-start;
|
|
||||||
/* 子元素垂直方向顶部对齐 */
|
|
||||||
padding: 20px;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: #71e4ae;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #333;
|
color: #333;
|
||||||
@ -96,80 +109,46 @@ h1 {
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-list {
|
.layout-container {
|
||||||
list-style-type: none;
|
height: 100vh;
|
||||||
/* 移除列表项前的标记 */
|
overflow: hidden;
|
||||||
padding: 0;
|
|
||||||
|
.el-aside-demo {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 1000;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: 2px 0 6px rgba(0, 0, 0, 0.1);
|
||||||
|
background-color: #4d4f52;
|
||||||
|
|
||||||
|
.sidebar-content {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-container-right {
|
||||||
|
min-height: 100vh;
|
||||||
|
margin-left: 200px;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.el-header-demo {
|
||||||
|
height: 60px;
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1px solid #e6e6e6;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-main-demo {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-list li {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 200px;
|
|
||||||
/* 侧边栏宽度 */
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
/* 侧边栏背景色 */
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar li {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a {
|
|
||||||
color: #333;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 16px;
|
|
||||||
display: block;
|
|
||||||
/* 使链接占据整行 */
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
/* 平滑过渡效果 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a:hover {
|
|
||||||
background-color: #c6ec97;
|
|
||||||
/* 鼠标悬停时的背景色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-container {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
flex: 1;
|
|
||||||
/* 剩余空间 */
|
|
||||||
padding: 20px;
|
|
||||||
/* 内容区域的内边距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 200px;
|
|
||||||
min-height: 100vh;
|
|
||||||
background-color: #545c64;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-button {
|
|
||||||
margin: 10px;
|
|
||||||
align-self: flex-end;
|
|
||||||
background-color: #545c64;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-logo {
|
.sidebar-logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -179,40 +158,24 @@ h1 {
|
|||||||
background: transparent; /* 关键:透明背景 */
|
background: transparent; /* 关键:透明背景 */
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.5)); /* 添加微光效果 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-name {
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); /* 文字阴影增强可读性 */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.5)); /* 添加微光效果 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.system-name {
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
margin: 0;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); /* 文字阴影增强可读性 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-aside-demo {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 200px;
|
|
||||||
z-index: 1000;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: #4d4f52;
|
|
||||||
border-right: 1px solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-container-right {
|
|
||||||
margin-left: 0;
|
|
||||||
width: calc(100vw - 220px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-menu-vertical-demo {
|
.el-menu-vertical-demo {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -244,8 +207,35 @@ h1 {
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.router-link-active {
|
.avatar-container {
|
||||||
color: #ffd04b;
|
height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
|
|
||||||
|
margin-right: 40px;
|
||||||
|
|
||||||
|
.avatar-wrapper {
|
||||||
|
margin-top: 5px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: -20px;
|
||||||
|
top: 25px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user