修复好多
This commit is contained in:
parent
5f9156137f
commit
6ece507c90
@ -9,10 +9,15 @@ import (
|
||||
"admin/apps/game/model/dto"
|
||||
"admin/internal/consts"
|
||||
"admin/internal/errcode"
|
||||
"admin/internal/event"
|
||||
"admin/lib/xlog"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CommonResourceService struct {
|
||||
@ -39,8 +44,13 @@ func initCommonResourcesRepo(db *gorm.DB) {
|
||||
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_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_MailGlobal, "全服邮件", repo.NewCommonResourceRepo(db, &model.GlobalMail{}), ShowMethod_Get|ShowMethod_Post) // 直接删除,别修改了,玩家收到的更乱
|
||||
r(consts.ResourcesName_MailRole, "个人邮件", repo.NewCommonResourceRepo(db, &model.RoleMail{}), ShowMethod_Get|ShowMethod_Post) // 个人邮件发放就没法撤回?
|
||||
|
||||
{
|
||||
globalMailRepo := r(consts.ResourcesName_MailGlobal, "全服邮件", repo.NewCommonResourceRepo(db, &model.GlobalMail{}), ShowMethod_Get|ShowMethod_Post)
|
||||
globalMailRepo.HasDelayInvokeCreateHook = true
|
||||
} // 直接删除,别修改了,玩家收到的更乱
|
||||
|
||||
r(consts.ResourcesName_CDKey, "礼包码", repo.NewCommonResourceRepo(db, &model.CDKey{}), ShowMethod_Get|ShowMethod_Post|ShowMethod_Put|ShowMethod_Delete)
|
||||
r(consts.ResourcesName_ItemBag, "道具礼包", repo.NewCommonResourceRepo(db, &model.ItemBag{}), 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)
|
||||
@ -52,9 +62,48 @@ func NewCommonResourceService(db *gorm.DB) *CommonResourceService {
|
||||
svc := &CommonResourceService{
|
||||
projectRepo: repo.NewProjectRepo(db),
|
||||
}
|
||||
svc.startEventSubscriber()
|
||||
svc.startLoadAllDelayInvokeDbData()
|
||||
return svc
|
||||
}
|
||||
|
||||
func (svc *CommonResourceService) startLoadAllDelayInvokeDbData() {
|
||||
for _, repo := range commResourcesRepo {
|
||||
if repo.HasDelayInvokeCreateHook {
|
||||
repo.Repo.ListPagination("`delay_invoke_create_hook` is not NULL and `delay_invoke_create_hook` > ?", []any{time.Now()}, func(po model.IModel) {
|
||||
var projectId int
|
||||
var resource string = repo.Resource
|
||||
var delayAt time.Time
|
||||
//xlog.Infof("过滤数据:%+v", po)
|
||||
switch repo.Resource {
|
||||
case consts.ResourcesName_MailGlobal:
|
||||
dbData := po.(*model.GlobalMail)
|
||||
projectId = dbData.ProjectId
|
||||
if !dbData.DelayInvokeCreateHook.Valid || dbData.DelayInvokeCreateHook.Time.Before(time.Now()) {
|
||||
return
|
||||
}
|
||||
delayAt = dbData.DelayInvokeCreateHook.Time
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// 延迟执行钩子调用
|
||||
xlog.Infof("起服查看全局邮件:%+v延迟到%v发送,添加到全局定时器。。", po, delayAt.Format(time.DateTime))
|
||||
objBin, _ := json.Marshal(po)
|
||||
payload := &event.EventPayload_DelayInvokeCreateHook{
|
||||
ProjectId: projectId,
|
||||
Resource: resource,
|
||||
DelayAt: delayAt,
|
||||
Obj: objBin,
|
||||
}
|
||||
event.GetMgrInstance().Publish(event.EventTopic_DelayInvokeCreateHook, payload)
|
||||
return
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *CommonResourceService) List(projectId int, resource string, listParams *dto.CommonListReq) (int, []*dto.CommonDtoFieldDesc, []dto.CommonDtoValues, error) {
|
||||
_, projectEt, find, err := svc.projectRepo.GetById(projectId)
|
||||
if err != nil {
|
||||
@ -65,7 +114,7 @@ func (svc *CommonResourceService) List(projectId int, resource string, listParam
|
||||
}
|
||||
|
||||
rRepo := findCommResourceRepo(resource)
|
||||
totalCount, fieldsDescInfo, etList, err := rRepo.List(projectEt, listParams)
|
||||
totalCount, fieldsDescInfo, etList, err := rRepo.Repo.List(projectEt, listParams)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
@ -96,7 +145,7 @@ func (svc *CommonResourceService) GetById(projectId int, resource string, id int
|
||||
return nil, nil, nil, false, errcode.New(errcode.ServerError, "not found project %v db data", projectId)
|
||||
}
|
||||
|
||||
fieldsDescInfo, et, find, err := findCommResourceRepo(resource).GetById(projectEt, id)
|
||||
fieldsDescInfo, et, find, err := findCommResourceRepo(resource).Repo.GetById(projectEt, id)
|
||||
if err != nil {
|
||||
return nil, nil, nil, false, err
|
||||
}
|
||||
@ -114,7 +163,8 @@ func (svc *CommonResourceService) Create(projectId int, resource string, dtoObj
|
||||
}
|
||||
|
||||
createOne := func(obj dto.CommonDtoValues) (dto.CommonDtoValues, error) {
|
||||
et, err := findCommResourceRepo(resource).Create(projectEt, resource, obj)
|
||||
resourceRepo := findCommResourceRepo(resource)
|
||||
et, err := resourceRepo.Repo.Create(projectEt, resource, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -124,6 +174,23 @@ func (svc *CommonResourceService) Create(projectId int, resource string, dtoObj
|
||||
newObj := et.ToCommonDto()
|
||||
|
||||
// 执行各个项目特定的钩子方法
|
||||
if resourceRepo.HasDelayInvokeCreateHook {
|
||||
field := reflect.ValueOf(et.Po).Elem().FieldByName("DelayInvokeCreateHook")
|
||||
delayAt := field.Interface().(sql.NullTime)
|
||||
if delayAt.Valid && delayAt.Time.After(time.Now()) {
|
||||
// 延迟执行钩子调用
|
||||
objBin, _ := json.Marshal(et.Po)
|
||||
payload := &event.EventPayload_DelayInvokeCreateHook{
|
||||
ProjectId: projectId,
|
||||
Resource: resource,
|
||||
DelayAt: delayAt.Time,
|
||||
Obj: objBin,
|
||||
}
|
||||
event.GetMgrInstance().Publish(event.EventTopic_DelayInvokeCreateHook, payload)
|
||||
return newObj, nil
|
||||
}
|
||||
}
|
||||
|
||||
if hook, ok := projects.GetProjectResourceHook(projectEt, resource).(projects.IPostResourceOpCreateHook); ok {
|
||||
err = hook.Create(projectEt, resource, newObj)
|
||||
if err != nil {
|
||||
@ -168,7 +235,7 @@ func (svc *CommonResourceService) Edit(projectId int, resource string, dtoObj dt
|
||||
return errcode.New(errcode.ServerError, "not found project %v db data", projectId)
|
||||
}
|
||||
|
||||
err = findCommResourceRepo(resource).Edit(projectEt, dtoObj)
|
||||
err = findCommResourceRepo(resource).Repo.Edit(projectEt, dtoObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -194,7 +261,7 @@ func (svc *CommonResourceService) Delete(projectId int, resource string, id int)
|
||||
return nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId)
|
||||
}
|
||||
|
||||
oldEt, find, err := findCommResourceRepo(resource).Delete(projectEt, id)
|
||||
oldEt, find, err := findCommResourceRepo(resource).Repo.Delete(projectEt, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -249,13 +316,14 @@ const (
|
||||
)
|
||||
|
||||
type resourceRepoInfo struct {
|
||||
Resource string
|
||||
Desc string
|
||||
Repo repo.ICommonResourceRepo
|
||||
ShowMethods []string
|
||||
showMethods int
|
||||
GlobalBtns []*api.ResourceBtnInfo
|
||||
RowBtns []*api.ResourceBtnInfo
|
||||
Resource string
|
||||
Desc string
|
||||
Repo repo.ICommonResourceRepo
|
||||
ShowMethods []string
|
||||
showMethods int
|
||||
GlobalBtns []*api.ResourceBtnInfo
|
||||
RowBtns []*api.ResourceBtnInfo
|
||||
HasDelayInvokeCreateHook bool
|
||||
}
|
||||
|
||||
var commResourcesRepo = make([]*resourceRepoInfo, 0)
|
||||
@ -286,10 +354,10 @@ func r(resource, desc string, repo repo.ICommonResourceRepo, showMethods int) *r
|
||||
return curRepo
|
||||
}
|
||||
|
||||
func findCommResourceRepo(resource string) repo.ICommonResourceRepo {
|
||||
func findCommResourceRepo(resource string) *resourceRepoInfo {
|
||||
for _, v := range commResourcesRepo {
|
||||
if v.Resource == resource {
|
||||
return v.Repo
|
||||
return v
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("not found Resource:%v", resource))
|
||||
|
@ -67,6 +67,10 @@ func getFieldTypeDtoDescInfo(project *Project, poValue reflect.Value, fieldType
|
||||
f1.Name = "创建时间"
|
||||
}
|
||||
|
||||
if f1.Key == "UpdatedAt" {
|
||||
f1.Name = "更新时间"
|
||||
}
|
||||
|
||||
if tagType := fieldType.Tag.Get("type"); tagType != "" {
|
||||
f1.Type = tagType
|
||||
}
|
||||
|
71
admin/apps/game/domain/event.go
Normal file
71
admin/apps/game/domain/event.go
Normal file
@ -0,0 +1,71 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"admin/apps/game/domain/entity"
|
||||
"admin/apps/game/domain/projects"
|
||||
"admin/apps/game/model"
|
||||
"admin/internal/consts"
|
||||
"admin/internal/event"
|
||||
"admin/internal/global"
|
||||
"admin/lib/dtimer"
|
||||
"admin/lib/xlog"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (svc *CommonResourceService) startEventSubscriber() {
|
||||
event.GetMgrInstance().Subscribe("resource.create", event.EventTopic_DelayInvokeCreateHook, svc.handleResourceDelayInvokeCreateHook)
|
||||
}
|
||||
|
||||
func (svc *CommonResourceService) handleResourceDelayInvokeCreateHook(msg *event.Msg) {
|
||||
payload := &event.EventPayload_DelayInvokeCreateHook{}
|
||||
err := json.Unmarshal(msg.Payload, payload)
|
||||
if err != nil {
|
||||
xlog.Warnf("unmarshal EventPayload_DelayInvokeCreateHook(%+v) error:%v", string(msg.Payload), err)
|
||||
return
|
||||
}
|
||||
|
||||
if payload.Resource == consts.ResourcesName_MailGlobal {
|
||||
mailInfo := &model.GlobalMail{}
|
||||
err = json.Unmarshal(payload.Obj, mailInfo)
|
||||
if err != nil {
|
||||
xlog.Warnf("unmarshal mail(%+v) error:%v", string(payload.Obj), err)
|
||||
return
|
||||
}
|
||||
delayAt := payload.DelayAt
|
||||
if delayAt.After(time.Now()) {
|
||||
xlog.Infof("全服邮件[%+v]延迟到%v发送,添加到全局定时器。。。", mailInfo, delayAt.Format(time.DateTime))
|
||||
global.GLOB_TIMER.Add(&dtimer.Timer{
|
||||
Key: fmt.Sprintf("create.global.mail.%v", mailInfo.ID),
|
||||
Duration: delayAt.Sub(time.Now()),
|
||||
Callback: func() {
|
||||
_, projectEt, _, err := svc.projectRepo.GetById(payload.ProjectId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
obj := new(entity.CommonResource).FromPo(mailInfo).ToCommonDto()
|
||||
hook, ok := projects.GetProjectResourceHook(projectEt, payload.Resource).(projects.IPostResourceOpCreateHook)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err = hook.Create(projectEt, payload.Resource, obj)
|
||||
if err != nil {
|
||||
xlog.Errorf("invoke hook create resource:%v obj:%+v error:%v", payload.Resource, obj)
|
||||
return
|
||||
}
|
||||
xlog.Infof("delay send global mail ok, mail info:%+v", mailInfo)
|
||||
|
||||
// 更新数据库延迟时间为NULL
|
||||
resourceRepo := findCommResourceRepo(payload.Resource)
|
||||
err = resourceRepo.Repo.UpdateClearDelayInvokeCreateHookFieldN(mailInfo.ID)
|
||||
if err != nil {
|
||||
xlog.Errorf("UpdateClearDelayInvokeCreateHookFieldN id:%v error:%v", mailInfo.ID)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"admin/apps/game/domain/entity"
|
||||
"admin/apps/game/domain/projects"
|
||||
"admin/apps/game/domain/repo"
|
||||
"admin/apps/game/model"
|
||||
"admin/apps/game/model/dto"
|
||||
"admin/internal/errcode"
|
||||
"gorm.io/gorm"
|
||||
@ -87,3 +88,26 @@ func (svc *ProjectService) GetAllItems(projectId int) ([]*dto.CommonDtoFieldChoi
|
||||
|
||||
return handler.GetItems(projectEt)
|
||||
}
|
||||
|
||||
func (svc *ProjectService) GetAllItemBag(projectId int) ([]*dto.ItemBagInfo, error) {
|
||||
dbList, err := new(model.ItemBag).List(projectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retList := make([]*dto.ItemBagInfo, 0, len(dbList))
|
||||
for _, v := range dbList {
|
||||
info := &dto.ItemBagInfo{
|
||||
Name: v.Name,
|
||||
}
|
||||
for _, item := range v.Attach {
|
||||
info.Items = append(info.Items, &dto.ItemInfo{
|
||||
ItemID: int(item.ID),
|
||||
ItemNum: item.Num,
|
||||
ItemType: item.ItemType,
|
||||
Desc: item.Desc,
|
||||
})
|
||||
}
|
||||
retList = append(retList, info)
|
||||
}
|
||||
return retList, nil
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MailGlobalHook struct {
|
||||
@ -68,6 +69,19 @@ func (hook *MailGlobalHook) Create(projectInfo *entity.Project, resource string,
|
||||
params.Add("mailtitle", mailInfo.Title)
|
||||
params.Add("mailcontent", mailInfo.Content)
|
||||
|
||||
if mailInfo.ExpireAt.Valid {
|
||||
params.Add("expiretime", mailInfo.ExpireAt.Time.Format(time.DateTime))
|
||||
}
|
||||
if mailInfo.CreateRoleTimeBefore.Valid {
|
||||
params.Add("createrole", mailInfo.CreateRoleTimeBefore.Time.Format(time.DateTime))
|
||||
}
|
||||
if mailInfo.TotalPayMoney > 0 {
|
||||
params.Add("cash", strconv.Itoa(mailInfo.TotalPayMoney))
|
||||
}
|
||||
if mailInfo.RoleLevel > 0 {
|
||||
params.Add("playerlevel", strconv.Itoa(mailInfo.RoleLevel))
|
||||
}
|
||||
|
||||
// 通知对应服务器
|
||||
for _, serverId := range serverIds {
|
||||
serverIdInt, _ := strconv.Atoi(serverId)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"admin/lib/httpclient"
|
||||
"admin/lib/utils"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -94,5 +95,9 @@ func (hook *RoleHook) List(projectInfo *entity.Project, resource string, params
|
||||
}
|
||||
}
|
||||
|
||||
sort.SliceStable(rows, func(i, j int) bool {
|
||||
return rows[i]["Status"].(string) < rows[j]["Status"].(string)
|
||||
})
|
||||
|
||||
return totalCount, fields, rows, nil
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"admin/internal/consts"
|
||||
"admin/internal/errcode"
|
||||
"admin/lib/xlog"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
@ -26,6 +27,8 @@ type ICommonResourceRepo interface {
|
||||
Create(projectEt *entity.Project, resource string, et dto.CommonDtoValues) (*entity.CommonResource, error)
|
||||
Edit(projectEt *entity.Project, et dto.CommonDtoValues) error
|
||||
Delete(projectEt *entity.Project, id int) (*entity.CommonResource, bool, error)
|
||||
ListPagination(whereSql string, whereArgs []any, f func(po model.IModel)) error
|
||||
UpdateClearDelayInvokeCreateHookFieldN(id int) error
|
||||
}
|
||||
|
||||
func NewCommonResourceRepo(db *gorm.DB, poTemplate model.IModel) ICommonResourceRepo {
|
||||
@ -96,11 +99,11 @@ func (repo *commonResourceRepoImpl) List(projectEt *entity.Project, params *dto.
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) GetById(projectEt *entity.Project, id int) ([]*dto.CommonDtoFieldDesc, *entity.CommonResource, bool, error) {
|
||||
po := repo.newEmptyPo()
|
||||
po := repo.makeEmptyPo()
|
||||
err := repo.db.Where("id = ?", id).First(po).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return repo.fieldsDescInfoFun(projectEt), (&entity.CommonResource{}).FromPo(repo.newEmptyPo()), false, nil
|
||||
return repo.fieldsDescInfoFun(projectEt), (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()), false, nil
|
||||
}
|
||||
return nil, nil, false, errcode.New(errcode.DBError, "get resource:%v by id:%v error:%v", repo.poTemplate.TableName(), id, err)
|
||||
}
|
||||
@ -108,7 +111,7 @@ func (repo *commonResourceRepoImpl) GetById(projectEt *entity.Project, id int) (
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) Create(projectEt *entity.Project, resource string, dtoObj dto.CommonDtoValues) (*entity.CommonResource, error) {
|
||||
et := (&entity.CommonResource{}).FromPo(repo.newEmptyPo()).FromDto(dtoObj)
|
||||
et := (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()).FromDto(dtoObj)
|
||||
if handler, find := createHooks[resource]; find {
|
||||
if err := handler(projectEt, dtoObj); err != nil {
|
||||
return et, err
|
||||
@ -127,7 +130,7 @@ func (repo *commonResourceRepoImpl) Create(projectEt *entity.Project, resource s
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) Edit(projectEt *entity.Project, dtoObj dto.CommonDtoValues) error {
|
||||
et := (&entity.CommonResource{}).FromPo(repo.newEmptyPo()).FromDto(dtoObj)
|
||||
et := (&entity.CommonResource{}).FromPo(repo.makeEmptyPo()).FromDto(dtoObj)
|
||||
err := repo.db.Where("id=?", et.Po.GetId()).Save(et.Po).Error
|
||||
if err != nil {
|
||||
return errcode.New(errcode.DBError, "edit resource:%v obj:%+v error:%v", repo.poTemplate.TableName(), et, err)
|
||||
@ -151,7 +154,52 @@ func (repo *commonResourceRepoImpl) Delete(projectEt *entity.Project, id int) (*
|
||||
return et, true, nil
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) newEmptyPo() model.IModel {
|
||||
func (repo *commonResourceRepoImpl) ListPagination(whereSql string, whereArgs []any, f func(po model.IModel)) error {
|
||||
pageNo := 0
|
||||
pageLen := 100
|
||||
for {
|
||||
limitStart := pageNo * pageLen
|
||||
limitLen := pageLen
|
||||
listType := reflect.New(reflect.SliceOf(reflect.TypeOf(repo.poTemplate)))
|
||||
var txFind *gorm.DB
|
||||
var err error
|
||||
if len(whereSql) <= 0 {
|
||||
txFind = repo.db.Offset(limitStart).Limit(limitLen).Order("created_at desc")
|
||||
} else {
|
||||
txFind = repo.db.Where(whereSql, whereArgs...).Offset(limitStart).Limit(limitLen)
|
||||
}
|
||||
err = txFind.Find(listType.Interface()).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
listType1 := listType.Elem()
|
||||
listLen := listType1.Len()
|
||||
|
||||
for i := 0; i < listType1.Len(); i++ {
|
||||
po := listType1.Index(i).Interface().(model.IModel)
|
||||
f(po)
|
||||
}
|
||||
|
||||
if listLen < limitLen {
|
||||
// 遍历完了
|
||||
return nil
|
||||
}
|
||||
|
||||
pageNo++
|
||||
}
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) UpdateClearDelayInvokeCreateHookFieldN(id int) error {
|
||||
repo.makeEmptyPo()
|
||||
err := repo.db.Model(repo.makeEmptyPo()).Where("id = ?", id).UpdateColumn("delay_invoke_create_hook", sql.NullTime{}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *commonResourceRepoImpl) makeEmptyPo() model.IModel {
|
||||
return reflect.New(reflect.TypeOf(repo.poTemplate).Elem()).Interface().(model.IModel)
|
||||
}
|
||||
|
||||
@ -168,13 +216,28 @@ func (repo *commonResourceRepoImpl) parseWhereConditions2Sql(conditions []*dto.G
|
||||
}
|
||||
dbFieldName := namer.ColumnName("", field.Name)
|
||||
if field.Type.Name() == "Time" {
|
||||
cond.Value1, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value1.(string), time.Local)
|
||||
cond.Value2, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value2.(string), time.Local)
|
||||
if cond.Value1 == nil {
|
||||
cond.Value1 = time.Time{}
|
||||
} else {
|
||||
cond.Value1, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value1.(string), time.Local)
|
||||
}
|
||||
if cond.Value2 == nil {
|
||||
cond.Value2 = time.Time{}
|
||||
} else {
|
||||
cond.Value2, _ = time.ParseInLocation("2006/01/02 15:04:05", cond.Value2.(string), time.Local)
|
||||
}
|
||||
|
||||
}
|
||||
switch field.Tag.Get("where") {
|
||||
case "eq":
|
||||
whereClause = append(whereClause, fmt.Sprintf("`%v` = ?", dbFieldName))
|
||||
whereArgs = append(whereArgs, cond.Value1)
|
||||
if field.Tag.Get("type") == "[]string" && field.Tag.Get("multi_choice") == "true" {
|
||||
// eq也要查出来为空的
|
||||
whereClause = append(whereClause, fmt.Sprintf("JSON_CONTAINS( `%v`, '\"%v\"', '$' ) or `%v` IS NULL",
|
||||
dbFieldName, cond.Value1, dbFieldName))
|
||||
} else {
|
||||
whereClause = append(whereClause, fmt.Sprintf("`%v` = ?", dbFieldName))
|
||||
whereArgs = append(whereArgs, cond.Value1)
|
||||
}
|
||||
case "gt":
|
||||
whereClause = append(whereClause, fmt.Sprintf("`%v` > ?", dbFieldName))
|
||||
whereArgs = append(whereArgs, cond.Value1)
|
||||
@ -191,10 +254,10 @@ func (repo *commonResourceRepoImpl) parseWhereConditions2Sql(conditions []*dto.G
|
||||
whereClause = append(whereClause, fmt.Sprintf("`%v` like ?", dbFieldName))
|
||||
whereArgs = append(whereArgs, cond.Value1)
|
||||
case "range":
|
||||
|
||||
if t1, ok1 := cond.Value1.(time.Time); ok1 {
|
||||
t2, _ := cond.Value2.(time.Time)
|
||||
if t1.IsZero() && t2.IsZero() {
|
||||
t1, ok1 := cond.Value1.(time.Time)
|
||||
t2, ok2 := cond.Value2.(time.Time)
|
||||
if ok1 || ok2 {
|
||||
if !t1.IsZero() && !t2.IsZero() {
|
||||
whereClause = append(whereClause, fmt.Sprintf("`%v` >= ? and `%v` <= ?", dbFieldName, dbFieldName))
|
||||
whereArgs = append(whereArgs, cond.Value1, cond.Value2)
|
||||
} else if !t1.IsZero() {
|
||||
|
@ -23,6 +23,7 @@ type Ban struct {
|
||||
ExpireAt sql.NullTime `name:"封禁到期时间" desc:"封禁到期时间,0表示永久封禁"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *Ban) TableName() string {
|
||||
|
@ -14,9 +14,9 @@ func init() {
|
||||
|
||||
type CDKey struct {
|
||||
ID int `gorm:"primarykey" readonly:"true"`
|
||||
ProjectId int `gorm:"index:idx_project_id"`
|
||||
ProjectId int `gorm:"uniqueIndex:idx_project_cdkey"`
|
||||
ServerIDs []string `gorm:"type:json;serializer:json" name:"区服" desc:"不选就是全服通用" type:"[]string" choices:"GetChoiceServers" multi_choice:"true" uneditable:"true""`
|
||||
Name string `gorm:"type:varchar(100);unique" name:"礼包说明" required:"true" uneditable:"true"`
|
||||
Name string `gorm:"type:varchar(100);uniqueIndex:idx_project_cdkey" name:"礼包说明" required:"true" uneditable:"true"`
|
||||
CodeType int `name:"礼包类型" required:"true" choices:"GetCodeTypeChoices" uneditable:"true"`
|
||||
Code string `gorm:"type:VARCHAR(50);index" name:"礼包码" desc:"一码通用才配置" uneditable:"true"`
|
||||
CodeNum int `name:"礼包数量" desc:"一码一用才配置"`
|
||||
@ -25,6 +25,7 @@ type CDKey struct {
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"礼包码奖励道具" type:"items" desc:"搜索道具并点击添加"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *CDKey) TableName() string {
|
||||
|
@ -21,6 +21,7 @@ type CDKeyUsed struct {
|
||||
IP string `gorm:"type:varchar(20)"`
|
||||
DeviceId string `gorm:"type:varchar(50)"`
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *CDKeyUsed) TableName() string {
|
||||
|
@ -39,7 +39,8 @@ type CommonDtoValues map[string]any
|
||||
type CommonDtoList struct {
|
||||
FieldsDesc []*CommonDtoFieldDesc `json:"fields_desc"` // 数据字段描述信息
|
||||
TotalCount int `json:"total_count"`
|
||||
Rows []CommonDtoValues `json:"rows"` // 数据行
|
||||
Rows []CommonDtoValues `json:"rows"` // 数据行
|
||||
ItemBags []*ItemBagInfo `json:"item_bags"` // 礼包,用来给道具添加功能选择用
|
||||
}
|
||||
|
||||
type PathInfo struct {
|
||||
@ -61,6 +62,11 @@ type ItemInfo struct {
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
type ItemBagInfo struct {
|
||||
Name string `json:"name"`
|
||||
Items []*ItemInfo `json:"items"`
|
||||
}
|
||||
|
||||
type AccountDetailOrderInfo struct {
|
||||
ServerId string `json:"server_id"`
|
||||
AccountId string `json:"account_id"`
|
||||
|
@ -3,6 +3,7 @@ package model
|
||||
import (
|
||||
"admin/apps/game/model/dto"
|
||||
"admin/internal/db"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -11,14 +12,20 @@ func init() {
|
||||
}
|
||||
|
||||
type GlobalMail struct {
|
||||
ID int `gorm:"primarykey" readonly:"true"`
|
||||
ProjectId int `gorm:"index:idx_project_id"`
|
||||
ServerIDs []string `gorm:"type:json;serializer:json" desc:"不选就是默认所有区服" name:"区服" type:"[]string" choices:"GetChoiceServers" multi_choice:"true"`
|
||||
Title string `name:"邮件标题" required:"true"`
|
||||
Content string `name:"邮件内容" required:"true"`
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
|
||||
ID int `gorm:"primarykey" readonly:"true"`
|
||||
ProjectId int `gorm:"index:idx_project_id"`
|
||||
ServerIDs []string `gorm:"type:json;serializer:json" desc:"不选就是默认所有区服" name:"区服" type:"[]string" choices:"GetChoiceServers" multi_choice:"true"`
|
||||
Title string `name:"邮件标题" required:"true"`
|
||||
Content string `name:"邮件内容" required:"true"`
|
||||
DelayInvokeCreateHook sql.NullTime `name:"邮件定时发送时间" desc:"不填或者无效就立即发送"`
|
||||
ExpireAt sql.NullTime `name:"邮件到期时间" desc:"不填就是永久有效"`
|
||||
CreateRoleTimeBefore sql.NullTime `name:"创角时间" desc:"在这时间之前创建的角色才能收到邮件,不填就是都生效"`
|
||||
TotalPayMoney int `name:"充值金额大于" desc:"充值金额大于的才能收到邮件,不填就是没有要求"`
|
||||
RoleLevel int `name:"角色等级大于" desc:"角色等级大于的才能收到邮件,不填就是没有要求"`
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *GlobalMail) TableName() string {
|
||||
|
@ -3,6 +3,8 @@ package model
|
||||
import (
|
||||
"admin/apps/game/model/dto"
|
||||
"admin/internal/db"
|
||||
"admin/internal/errcode"
|
||||
"admin/internal/global"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -13,11 +15,12 @@ func init() {
|
||||
// 道具包,配置一系列道具,供邮件、礼包码填写使用
|
||||
type ItemBag struct {
|
||||
ID int `gorm:"primarykey" readonly:"true"`
|
||||
ProjectId int `gorm:"uniqueIndex:idx_whitelist"`
|
||||
Name string `gorm:"type:varchar(255);uniqu" name:"礼包名称" desc:"请输入礼包名称,全项目唯一" required:"true" where:"eq"`
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
|
||||
ProjectId int `gorm:"uniqueIndex:idx_bag"`
|
||||
Name string `gorm:"type:varchar(255);uniqueIndex:idx_bag" name:"礼包名称" desc:"请输入礼包名称,全项目唯一" required:"true" where:"eq"`
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加" required:"true"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *ItemBag) TableName() string {
|
||||
@ -38,3 +41,12 @@ func (m *ItemBag) GetWhitelistTypeChoices(project *Project) []*dto.CommonDtoFiel
|
||||
{Desc: "账号", Value: "account"},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ItemBag) List(projectId int) ([]*ItemBag, error) {
|
||||
list := make([]*ItemBag, 0)
|
||||
err := global.GLOB_DB.Where("project_id = ?", projectId).Order("created_at desc").Find(&list).Error
|
||||
if err != nil {
|
||||
return list, errcode.New(errcode.DBError, "list all item bag error:%v", err)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ type Notice struct {
|
||||
EndAt time.Time `name:"结束时间" required:"true"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *Notice) TableName() string {
|
||||
|
@ -28,6 +28,7 @@ type Project struct {
|
||||
ApiAddr string `name:"游戏api地址" desc:"api服务器地址,例如神魔大陆就是alisrv服务器地址,用于后台调用gm"`
|
||||
SortWeight int `name:"菜单排序" desc:"越大越靠前"`
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *Project) TableName() string {
|
||||
|
@ -27,6 +27,7 @@ type RoleMail struct {
|
||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *RoleMail) TableName() string {
|
||||
|
@ -29,6 +29,7 @@ type Server struct {
|
||||
//ApiAddr string
|
||||
|
||||
CreatedAt time.Time `readonly:"true"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *Server) TableName() string {
|
||||
|
@ -17,6 +17,7 @@ type SupportAccount struct {
|
||||
Account string `gorm:"type:varchar(200);uniqueIndex:idx_account;" name:"账号" desc:"用逗号标记多个" required:"true"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *SupportAccount) TableName() string {
|
||||
|
@ -18,6 +18,7 @@ type WhiteList struct {
|
||||
Value string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账号或者ip等值" required:"true"`
|
||||
|
||||
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||
UpdatedAt time.Time `readonly:"true"`
|
||||
}
|
||||
|
||||
func (lm *WhiteList) TableName() string {
|
||||
|
@ -58,7 +58,11 @@ func (svc *Service) CommonList(ctx context.Context, projectId int, resourceName
|
||||
}}, params.ParsedWhereConditions.Conditions...)
|
||||
}
|
||||
totalCount, fieldsDescInfo, rows, err := svc.resourceSvc.List(projectId, resourceName, params)
|
||||
return &dto.CommonDtoList{FieldsDesc: fieldsDescInfo, TotalCount: totalCount, Rows: rows}, err
|
||||
itemBags, err := svc.projectSvc.GetAllItemBag(projectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.CommonDtoList{FieldsDesc: fieldsDescInfo, TotalCount: totalCount, Rows: rows, ItemBags: itemBags}, err
|
||||
}
|
||||
|
||||
func (svc *Service) CommonPost(ctx context.Context, projectId int, resourceName string, params dto.CommonDtoValues) (dto.CommonDtoValues, error) {
|
||||
|
@ -1,7 +1,10 @@
|
||||
package event
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
EventTopic_UserExecute = "user.execute"
|
||||
EventTopic_UserExecute = "user.execute"
|
||||
EventTopic_DelayInvokeCreateHook = "resource.create.delay"
|
||||
)
|
||||
|
||||
type EventPayload_UserExecute struct {
|
||||
@ -14,3 +17,10 @@ type EventPayload_UserExecute struct {
|
||||
NewData any `json:"new_data"`
|
||||
Any any `json:"any"`
|
||||
}
|
||||
|
||||
type EventPayload_DelayInvokeCreateHook struct {
|
||||
ProjectId int
|
||||
Resource string
|
||||
DelayAt time.Time
|
||||
Obj []byte
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package global
|
||||
import (
|
||||
"admin/internal/config"
|
||||
"admin/lib/cache"
|
||||
"admin/lib/dtimer"
|
||||
"admin/lib/web"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -12,4 +13,5 @@ var (
|
||||
GLOB_DB *gorm.DB // 数据库
|
||||
GLOB_API_ENGINE *web.Engine // 全局api服务器
|
||||
GLOB_LOCAL_CACHER = cache.NewLocalCache() // 全局本地内存缓存器
|
||||
GLOB_TIMER = dtimer.NewDTimerMgr() // 全局定时器
|
||||
)
|
||||
|
@ -1,9 +1,100 @@
|
||||
package dtimer
|
||||
|
||||
import (
|
||||
"admin/lib/xlog"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
分布式定时器,用于解决比如多个进程启动后,只有一个进程触发定时器事件执行,
|
||||
目标不影响架构复杂性,做个能用的出来。思路是用mysql做分布式锁,多个进程抢占单例执行
|
||||
*/
|
||||
|
||||
type DTimer struct {
|
||||
type Timer struct {
|
||||
Key string
|
||||
Duration time.Duration
|
||||
IsInterval bool
|
||||
Callback func()
|
||||
expireAt time.Time
|
||||
timerMgr *DTimerMgr
|
||||
}
|
||||
|
||||
// todo 先实现一个本地数据库单例版本的
|
||||
type DTimerMgr struct {
|
||||
locker *sync.Mutex
|
||||
timers map[string]*Timer
|
||||
taskQueue chan *Timer
|
||||
}
|
||||
|
||||
func NewDTimerMgr() *DTimerMgr {
|
||||
mgr := new(DTimerMgr)
|
||||
mgr.locker = new(sync.Mutex)
|
||||
mgr.timers = make(map[string]*Timer)
|
||||
mgr.taskQueue = make(chan *Timer, 1024)
|
||||
go mgr.start()
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (mgr *DTimerMgr) Add(task *Timer) (*Timer, bool) {
|
||||
mgr.locker.Lock()
|
||||
defer mgr.locker.Unlock()
|
||||
|
||||
old, find := mgr.timers[task.Key]
|
||||
task.expireAt = time.Now().Add(task.Duration)
|
||||
mgr.timers[task.Key] = task
|
||||
return old, find
|
||||
}
|
||||
|
||||
func (mgr *DTimerMgr) Del(key string) {
|
||||
mgr.locker.Lock()
|
||||
defer mgr.locker.Unlock()
|
||||
delete(mgr.timers, key)
|
||||
}
|
||||
|
||||
func (mgr *DTimerMgr) start() {
|
||||
for i := 0; i < runtime.NumCPU(); i++ {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case t := <-mgr.taskQueue:
|
||||
func() {
|
||||
defer xlog.CatchWithInfo(fmt.Sprintf("handle timer %v panic", t.Key))
|
||||
t.Callback()
|
||||
}()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
tk := time.NewTicker(time.Second)
|
||||
defer tk.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-tk.C:
|
||||
mgr.locker.Lock()
|
||||
mgr.checkExpire()
|
||||
mgr.locker.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mgr *DTimerMgr) checkExpire() {
|
||||
timeNow := time.Now()
|
||||
for k, v := range mgr.timers {
|
||||
if v.expireAt.Before(timeNow) {
|
||||
if !v.IsInterval {
|
||||
delete(mgr.timers, k)
|
||||
} else {
|
||||
v.expireAt = timeNow.Add(v.Duration)
|
||||
}
|
||||
select {
|
||||
case mgr.taskQueue <- v:
|
||||
default:
|
||||
xlog.Warnf("timer channel full!!!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
admin/lib/dtimer/timer_test.go
Normal file
21
admin/lib/dtimer/timer_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package dtimer
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTimer(t *testing.T) {
|
||||
mgr := NewDTimerMgr()
|
||||
log.Printf("start ...")
|
||||
mgr.Add(&Timer{
|
||||
Key: "test1",
|
||||
Duration: time.Second * 5,
|
||||
Callback: func() {
|
||||
log.Printf("trigger timer")
|
||||
},
|
||||
})
|
||||
|
||||
select {}
|
||||
}
|
@ -40,6 +40,7 @@ const fieldsDescInfo = ref([])
|
||||
const whereFieldsDescInfo = ref([])
|
||||
const calcElColSpan = ref(0)
|
||||
const rows = ref([])
|
||||
const itemBags = ref([])
|
||||
const rules = ref({})
|
||||
|
||||
const current_page = ref(1)
|
||||
@ -47,10 +48,10 @@ const page_size = ref(10)
|
||||
const pageSizes = [10, 20, 50, 100]
|
||||
const totalRowCount = ref(0)
|
||||
|
||||
const item = ref({
|
||||
id: '',
|
||||
number: 1,
|
||||
})
|
||||
const selectedItem = ref(null)
|
||||
const selectedItemNum = ref(0)
|
||||
|
||||
const selectedItemBag = ref(null)
|
||||
|
||||
// console.log("enter table, resource:", cachedResource)
|
||||
|
||||
@ -68,7 +69,7 @@ const listData = async () => {
|
||||
conditions: []
|
||||
}
|
||||
whereFieldsDescInfo.value.forEach((field) => {
|
||||
if (field.value1) {
|
||||
if (field.value1 || field.value2) {
|
||||
whereReqConditions.conditions.push({
|
||||
key: field.key,
|
||||
op: field.where,
|
||||
@ -85,20 +86,35 @@ const listData = async () => {
|
||||
fieldsDescInfo.value = listRsp.value.data.fields_desc
|
||||
totalRowCount.value = listRsp.value.data.total_count
|
||||
rows.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) {
|
||||
if (field.required === true) {
|
||||
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
|
||||
}
|
||||
|
||||
if (field.type == "items") {
|
||||
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 !== "") {
|
||||
@ -313,29 +329,64 @@ const handleDelete = (index, row) => {
|
||||
}
|
||||
|
||||
function addItem(fieldDescInfo) {
|
||||
if (item.value.id == null || item.value.id == '' || item.value.id < 0) {
|
||||
ElMessage('请选择道具!')
|
||||
return;
|
||||
let hasValidInput = false;
|
||||
if (selectedItemBag.value != null && selectedItemBag.value.name !== undefined && selectedItemBag.value.name !== '') {
|
||||
selectedItemBag.value.items.forEach((bagItem) => {
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
}
|
||||
let d = {id: bagItem.item_id, num: bagItem.item_num, desc: bagItem.desc, item_type: bagItem.item_type};
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
})
|
||||
console.log("添加礼包:", selectedItemBag.value)
|
||||
hasValidInput = true;
|
||||
}
|
||||
if (item.value.num == null || item.value.num == '' || item.value.num <= 0) {
|
||||
ElMessage('请输入有效道具数量!')
|
||||
return;
|
||||
if (selectedItem.value !== null && selectedItem.value.value !== undefined && selectedItem.value.value !== '') {
|
||||
if (selectedItemNum.value <= 0) {
|
||||
ElMessage('请输入有效道具数量!')
|
||||
return;
|
||||
}
|
||||
let d = {
|
||||
id: selectedItem.value.value,
|
||||
num: Number(selectedItemNum.value),
|
||||
desc: selectedItem.value.desc,
|
||||
item_type: selectedItem.value.type
|
||||
};
|
||||
|
||||
console.log("add item:", d)
|
||||
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
}
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
hasValidInput = true;
|
||||
}
|
||||
if (!hasValidInput) {
|
||||
console.log("道具:", selectedItem.value)
|
||||
console.log("礼包:", selectedItemBag.value)
|
||||
ElMessage('请选择道具或者礼包!')
|
||||
}
|
||||
|
||||
let d = {id: item.value.id, num: Number(item.value.num), desc: item.value.desc, item_type: item.value.item_type};
|
||||
|
||||
console.log("add item:", d)
|
||||
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
if (dialogAddVisible.value) {
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
} else if (dialogEditVisible.value) {
|
||||
// console.log("删除道具,准备校验表单规则", rules.value)
|
||||
// console.log("删除道具,准备校验表单规则", dialogEditFormRef.value)
|
||||
dialogEditFormRef.value.validateField("Attach");
|
||||
}
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
}
|
||||
|
||||
function deleteItem(row) {
|
||||
// 移除该对象
|
||||
let number = dialogObjectForm.value.Attach.findIndex(item => item === row);
|
||||
dialogObjectForm.value.Attach.splice(number, 1);
|
||||
|
||||
if (dialogAddVisible.value) {
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
} else if (dialogEditVisible.value) {
|
||||
// console.log("删除道具,准备校验表单规则", rules.value)
|
||||
dialogEditFormRef.value.validateField("Attach");
|
||||
}
|
||||
}
|
||||
|
||||
const handleCloseDialog = () => {
|
||||
@ -345,18 +396,14 @@ const handleCloseDialog = () => {
|
||||
dialogObjectForm.value = {
|
||||
Attach: [],
|
||||
}
|
||||
item.value.desc = ''
|
||||
selectedItem.value = null
|
||||
selectedItemNum.value = 0
|
||||
selectedItemBag.value = null
|
||||
}
|
||||
|
||||
const loadingRemoteItems = ref(false)
|
||||
const itemChoices = ref({})
|
||||
|
||||
const handleItemOnSelect = (itemOption) => {
|
||||
console.log("选中:", itemOption)
|
||||
item.value.id = itemOption.value
|
||||
item.value.desc = itemOption.desc
|
||||
}
|
||||
|
||||
const handleQueryItem = (itemQueryStr) => {
|
||||
if (!itemQueryStr) {
|
||||
itemChoices.value = []
|
||||
@ -465,13 +512,24 @@ const handlePaginationCurChange = (val) => {
|
||||
<el-main>
|
||||
<el-table :data="rows" style="width: 100%" table-layout="auto" stripe
|
||||
@selection-change="handleTableSelectChange">
|
||||
<el-table-column type="selection" v-if="globalClickBtns.length > 0 || rowClickBtns.length > 0">
|
||||
<el-table-column type="selection" v-if="globalClickBtns.length > 0">
|
||||
|
||||
</el-table-column>
|
||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||
<!-- 道具列表 -->
|
||||
<el-table-column prop="jsonValue" :label="fieldDescInfo.name" show-overflow-tooltip
|
||||
v-if="(fieldDescInfo.type === 'items')"></el-table-column>
|
||||
<!-- 角色状态 -->
|
||||
<el-table-column prop="jsonValue" :label="fieldDescInfo.name"
|
||||
v-else-if="(fieldDescInfo.key === 'Status' && cachedResource.meta.resource === 'role' )">
|
||||
<template #default="scope">
|
||||
<el-tag type="info" v-if="scope.row.Status === '离线'">离线</el-tag>
|
||||
<el-tag type="success" v-else-if="scope.row.Status === '在线'">在线</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 其它普通字段 -->
|
||||
<el-table-column :prop="fieldDescInfo.key" :label="fieldDescInfo.name"
|
||||
:show-overflow-tooltip="(fieldDescInfo.key === 'Title' || fieldDescInfo.key === 'Content')"
|
||||
v-else></el-table-column>
|
||||
</template>
|
||||
<el-table-column prop="func" label="功 能">
|
||||
@ -547,15 +605,14 @@ const handlePaginationCurChange = (val) => {
|
||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||
<!--如何是items类型,就是物品下拉框+道具组合-->
|
||||
<template v-if="(fieldDescInfo.type === 'items')">
|
||||
<el-form :inline="true" :model="item" label-position="right">
|
||||
<el-form :inline="true" :model="selectedItem" 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 v-model="item" placeholder="--搜索道具--" style="width: 150px"
|
||||
filterable remote
|
||||
<el-select v-model="selectedItem" placeholder="--搜索道具--" style="width: 150px"
|
||||
filterable remote clearable
|
||||
:remote-method="handleQueryItem"
|
||||
:loading="loadingRemoteItems"
|
||||
value-key="value"
|
||||
@change="handleItemOnSelect"
|
||||
>
|
||||
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc"
|
||||
:value="info"></el-option>
|
||||
@ -563,7 +620,16 @@ const handlePaginationCurChange = (val) => {
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="num">
|
||||
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
|
||||
<el-input type="number" v-model="selectedItemNum" placeholder="请输入数量" style="width: 150px"/>
|
||||
</el-form-item>
|
||||
<!-- 选择礼包 -->
|
||||
<el-form-item v-if="cachedResource.meta.resource !== 'item_bag'">
|
||||
<el-tooltip effect="light" content="选择礼包,点击添加到奖励列表">
|
||||
<el-select placeholder="--礼包--" v-model="selectedItemBag" clearable style="width: 150px"
|
||||
value-key="name">
|
||||
<el-option v-for="bag in itemBags" :key="bag.name" :label="bag.name" :value="bag"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="addItem(fieldDescInfo)">添加</el-button>
|
||||
@ -633,11 +699,11 @@ const handlePaginationCurChange = (val) => {
|
||||
|
||||
<!--如果是items类型,就是物品下拉框+道具组合-->
|
||||
<template v-if="(fieldDescInfo.type === 'items')">
|
||||
<el-form :inline="true" :model="item" label-position="right"
|
||||
<el-form :inline="true" :model="selectedItem" 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" style="width: 150px"
|
||||
<el-select placeholder="--搜索道具--" v-model="selectedItem" style="width: 150px"
|
||||
filterable remote :remote-method="handleQueryItem"
|
||||
:loading="loadingRemoteItems"
|
||||
value-key="value"
|
||||
@ -648,13 +714,22 @@ const handlePaginationCurChange = (val) => {
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="number">
|
||||
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
|
||||
<el-input type="number" v-model="selectedItemNum" placeholder="请输入数量" style="width: 150px"/>
|
||||
</el-form-item>
|
||||
<!-- 选择礼包 -->
|
||||
<el-form-item v-if="cachedResource.meta.resource !== 'item_bag'">
|
||||
<el-tooltip effect="light" content="选择礼包,点击添加到奖励列表">
|
||||
<el-select placeholder="--礼包--" v-model="selectedItemBag" clearable style="width: 150px"
|
||||
value-key="name">
|
||||
<el-option v-for="bag in itemBags" :key="bag.name" :label="bag.name" :value="bag"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</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="attachmentsList">
|
||||
<el-form-item label="奖励列表" prop="Attach">
|
||||
<el-table :data="dialogObjectForm.Attach" border>
|
||||
<el-table-column label="道具id" prop="id"/>
|
||||
<el-table-column label="数量" prop="num"/>
|
||||
|
@ -21,6 +21,7 @@ const fieldsDescInfo = ref([])
|
||||
const whereFieldsDescInfo = ref([])
|
||||
const calcElColSpan = ref(0)
|
||||
const rows = ref([])
|
||||
const itemBags = ref([])
|
||||
const rules = ref({})
|
||||
|
||||
const current_page = ref(1)
|
||||
@ -28,11 +29,9 @@ const page_size = ref(10)
|
||||
const pageSizes = [10, 20, 50, 100]
|
||||
const totalRowCount = ref(0)
|
||||
|
||||
const item = ref({
|
||||
id: '',
|
||||
number: 1,
|
||||
desc: '',
|
||||
})
|
||||
const selectedItem = ref(null)
|
||||
const selectedItemNum = ref(0)
|
||||
const selectedItemBag = ref(null)
|
||||
|
||||
// console.log("enter table, resource:", cachedResource)
|
||||
|
||||
@ -67,13 +66,14 @@ const listData = async () => {
|
||||
fieldsDescInfo.value = listRsp.value.data.fields_desc
|
||||
totalRowCount.value = listRsp.value.data.total_count
|
||||
rows.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"}]
|
||||
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: ["blur", "change"]}]
|
||||
}
|
||||
|
||||
if (field.type == "items") {
|
||||
@ -91,7 +91,7 @@ const listData = async () => {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: "blur",
|
||||
trigger: ["blur", "change"],
|
||||
}]
|
||||
}
|
||||
|
||||
@ -160,8 +160,7 @@ const submitAdd = async () => {
|
||||
try {
|
||||
await dialogAddFormRef.value.validate(valid => {
|
||||
if (valid) {
|
||||
console.log("commit add form:", dialogObjectForm.value)
|
||||
return
|
||||
// console.log("commit add form:", dialogObjectForm.value)
|
||||
resourcePost(resource_url, dialogObjectForm.value).then((res) => {
|
||||
ElNotification({
|
||||
title: "添加结果通知",
|
||||
@ -253,11 +252,19 @@ const handleLook = (index, row) => {
|
||||
}
|
||||
|
||||
const handleEdit = (index, row) => {
|
||||
dialogObjectForm.value = row
|
||||
dialogObjectForm.value.oldData = row
|
||||
console.log("点击行:", row)
|
||||
const rawRow = JSON.parse(JSON.stringify(row))
|
||||
dialogObjectForm.value = rawRow
|
||||
dialogObjectForm.value.oldData = rawRow
|
||||
dialogObjectForm.value.oldIndex = index
|
||||
rules.value["Code"] = []
|
||||
rules.value["CodeNum"] = []
|
||||
if (row.CodeType === 0) {
|
||||
cdkeyCodeInputDisabled.value = true
|
||||
cdkeyCodeNumInputDisabled.value = true
|
||||
} else {
|
||||
cdkeyCodeInputDisabled.value = true
|
||||
cdkeyCodeNumInputDisabled.value = false
|
||||
}
|
||||
handleCodeTypeOnSelect(row.CodeType)
|
||||
console.log("edit data:", row)
|
||||
dialogEditVisible.value = true
|
||||
}
|
||||
@ -282,36 +289,74 @@ const handleDelete = (index, row) => {
|
||||
}
|
||||
|
||||
function addItem() {
|
||||
if (item.value.id == null || item.value.id == '' || item.value.id < 0) {
|
||||
ElMessage('请选择道具!')
|
||||
return;
|
||||
}
|
||||
if (item.value.num == null || item.value.num == '' || item.value.num <= 0) {
|
||||
ElMessage('请输入有效道具数量!')
|
||||
return;
|
||||
let hasValidInput = false;
|
||||
if (selectedItemBag.value != null && selectedItemBag.value.name !== undefined && selectedItemBag.value.name !== '') {
|
||||
selectedItemBag.value.items.forEach((bagItem) => {
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
}
|
||||
let d = {id: bagItem.item_id, num: bagItem.item_num, desc: bagItem.desc, item_type: bagItem.item_type};
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
})
|
||||
console.log("添加礼包:", selectedItemBag.value)
|
||||
hasValidInput = true;
|
||||
}
|
||||
|
||||
let d = {id: item.value.id, num: Number(item.value.num), desc: item.value.desc, item_type: item.value.item_type};
|
||||
if (selectedItem.value !== null && selectedItem.value.value !== undefined && selectedItem.value.value !== '') {
|
||||
if (selectedItemNum.value <= 0) {
|
||||
ElMessage('请输入有效道具数量!')
|
||||
return;
|
||||
}
|
||||
let d = {
|
||||
id: selectedItem.value.value,
|
||||
num: Number(selectedItemNum.value),
|
||||
desc: selectedItem.value.desc,
|
||||
item_type: selectedItem.value.type
|
||||
};
|
||||
|
||||
console.log("add item:", d)
|
||||
console.log("add item:", d)
|
||||
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
if (typeof dialogObjectForm.value.Attach === typeof "") {
|
||||
dialogObjectForm.value.Attach = [];
|
||||
}
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
hasValidInput = true;
|
||||
}
|
||||
|
||||
if (!hasValidInput) {
|
||||
console.log("道具:", selectedItem.value)
|
||||
console.log("礼包:", selectedItemBag.value)
|
||||
ElMessage('请选择道具或者礼包!')
|
||||
return
|
||||
}
|
||||
|
||||
// console.log("校验规则:", rules.value)
|
||||
// 道具变动了,重新校验一下表单规则
|
||||
if (dialogAddVisible.value) {
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
} else if (dialogEditVisible.value) {
|
||||
// console.log("删除道具,准备校验表单规则", rules.value)
|
||||
// console.log("删除道具,准备校验表单规则", dialogEditFormRef.value)
|
||||
dialogEditFormRef.value.validateField("Attach");
|
||||
}
|
||||
dialogObjectForm.value.Attach.push(d);
|
||||
console.log("校验规则:", rules.value)
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
}
|
||||
|
||||
function deleteItem(row) {
|
||||
// 移除该对象
|
||||
let number = dialogObjectForm.value.Attach.findIndex(item => item === row);
|
||||
dialogObjectForm.value.Attach.splice(number, 1);
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
if (dialogAddVisible.value) {
|
||||
dialogAddFormRef.value.validateField("Attach");
|
||||
} else if (dialogEditVisible.value) {
|
||||
// console.log("删除道具,准备校验表单规则", rules.value)
|
||||
dialogEditFormRef.value.validateField("Attach");
|
||||
}
|
||||
}
|
||||
|
||||
const handleCloseDialog = () => {
|
||||
console.log("关闭添加/编辑弹窗")
|
||||
if (dialogEditVisible.value) {
|
||||
}
|
||||
dialogAddVisible.value = false
|
||||
dialogLookVisible.value = false
|
||||
dialogEditVisible.value = false
|
||||
@ -319,7 +364,9 @@ const handleCloseDialog = () => {
|
||||
dialogObjectForm.value = {
|
||||
Attach: [],
|
||||
}
|
||||
item.value.desc = ''
|
||||
selectedItem.value = null
|
||||
selectedItemNum.value = 0
|
||||
selectedItemBag.value = null
|
||||
}
|
||||
|
||||
const loadingRemoteItems = ref(false)
|
||||
@ -343,7 +390,20 @@ const handleCodeTypeOnSelect = (codeType) => {
|
||||
cdkeyCodeInputDisabled.value = true
|
||||
cdkeyCodeNumInputDisabled.value = false
|
||||
rules.value["Code"] = []
|
||||
rules.value["CodeNum"] = [{required: true, message: "礼包数量不能为空", trigger: "blur"}]
|
||||
rules.value["CodeNum"] = [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
const codeNum = dialogObjectForm.value['CodeNum']
|
||||
console.log("校验礼包数量:", dialogObjectForm.value)
|
||||
console.log("校验礼包数量:", codeNum)
|
||||
if (dialogObjectForm.value['CodeType'] === 1 && codeNum <= 0) {
|
||||
callback(new Error("请至少大于0的奖励码数量!"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ["blur", "change"],
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
@ -485,6 +545,7 @@ const handlePaginationCurChange = (val) => {
|
||||
<span>礼包使用</span>
|
||||
</el-button>
|
||||
<el-button size="default" type="danger" @click="handleDelete( scope.$index, scope.row)"
|
||||
style="margin-top: 5px"
|
||||
v-if="(resource_raw_node.meta.methods.delete === true)">
|
||||
<span>删除</span>
|
||||
</el-button>
|
||||
@ -513,15 +574,14 @@ const handlePaginationCurChange = (val) => {
|
||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||
<!--如何是items类型,就是物品下拉框+道具组合-->
|
||||
<template v-if="(fieldDescInfo.type === 'items')">
|
||||
<el-form :inline="true" :model="item" label-position="right">
|
||||
<el-form :inline="true" :model="selectedItem" 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 v-model="item" placeholder="--搜索道具--" style="width: 150px"
|
||||
filterable remote
|
||||
<el-select v-model="selectedItem" placeholder="--搜索道具--" style="width: 150px"
|
||||
filterable remote clearable
|
||||
:remote-method="handleQueryItem"
|
||||
:loading="loadingRemoteItems"
|
||||
value-key="value"
|
||||
@change="handleItemOnSelect"
|
||||
>
|
||||
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc"
|
||||
:value="info"></el-option>
|
||||
@ -529,7 +589,17 @@ const handlePaginationCurChange = (val) => {
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="num">
|
||||
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
|
||||
<el-input type="number" v-model="selectedItemNum" placeholder="请输入大于0的道具数量"
|
||||
style="width: 150px"/>
|
||||
</el-form-item>
|
||||
<!-- 选择礼包 -->
|
||||
<el-form-item>
|
||||
<el-tooltip effect="light" content="选择礼包,点击添加到奖励列表">
|
||||
<el-select placeholder="--礼包--" v-model="selectedItemBag" clearable style="width: 150px"
|
||||
value-key="name">
|
||||
<el-option v-for="bag in itemBags" :key="bag.name" :label="bag.name" :value="bag"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="addItem()">添加</el-button>
|
||||
@ -609,15 +679,15 @@ const handlePaginationCurChange = (val) => {
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="dialogLookVisible" :mask="true" title="编辑" :modal="true" :before-close="handleCloseDialog"
|
||||
<el-dialog v-model="dialogLookVisible" :mask="true" title="查看" :modal="true" :before-close="handleCloseDialog"
|
||||
destroy-on-close>
|
||||
<el-form ref="dialogEditFormRef" :model="dialogObjectForm" :rules="rules" class="operation_form"
|
||||
<el-form ref="dialogLookFormRef" :model="dialogObjectForm" :rules="rules" class="operation_form"
|
||||
label-width="130px">
|
||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||
|
||||
<!--如果是items类型,就是物品下拉框+道具组合-->
|
||||
<template v-if="(fieldDescInfo.type === 'items')">
|
||||
<el-form-item label="奖励列表" prop="attachmentsList">
|
||||
<el-form-item label="奖励列表" prop="Attach">
|
||||
<el-table :data="dialogObjectForm.Attach" border>
|
||||
<el-table-column label="道具id" prop="id"/>
|
||||
<el-table-column label="数量" prop="num"/>
|
||||
@ -665,10 +735,6 @@ const handlePaginationCurChange = (val) => {
|
||||
<!-- <el-input v-model="dialogEditForm[fieldDescInfo.key]"></el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
</template>
|
||||
|
||||
<el-form-item>
|
||||
<el-button @click="submitEdit(dialogEditFormRef)" size="large" type="primary">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
@ -680,30 +746,38 @@ const handlePaginationCurChange = (val) => {
|
||||
|
||||
<!--如果是items类型,就是物品下拉框+道具组合-->
|
||||
<template v-if="(fieldDescInfo.type === 'items')">
|
||||
<el-form :inline="true" :model="item" label-position="right"
|
||||
<el-form :inline="true" :model="selectedItem" 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" style="width: 150px"
|
||||
filterable remote
|
||||
<el-select placeholder="--搜索道具--" v-model="selectedItem" style="width: 150px"
|
||||
filterable remote clearable
|
||||
:remote-method="handleQueryItem"
|
||||
:loading="loadingRemoteItems"
|
||||
value-key="value"
|
||||
@change="handleItemOnSelect"
|
||||
>
|
||||
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc"
|
||||
:value="info"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="number">
|
||||
<el-input type="number" v-model="item.num" placeholder="请输入数量" style="width: 150px"/>
|
||||
<el-form-item label="数量" prop="num" label-width="40px">
|
||||
<el-input type="number" v-model="selectedItemNum" placeholder="请输入数量" style="width: 150px"/>
|
||||
</el-form-item>
|
||||
<!-- 选择礼包 -->
|
||||
<el-form-item>
|
||||
<el-tooltip effect="light" content="选择礼包,点击添加到奖励列表">
|
||||
<el-select placeholder="--礼包--" v-model="selectedItemBag" clearable style="width: 150px"
|
||||
value-key="name">
|
||||
<el-option v-for="bag in itemBags" :key="bag.name" :label="bag.name" :value="bag"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</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="attachmentsList">
|
||||
<el-form-item label="奖励列表" prop="Attach">
|
||||
<el-table :data="dialogObjectForm.Attach" border>
|
||||
<el-table-column label="道具id" prop="id"/>
|
||||
<el-table-column label="数量" prop="num"/>
|
||||
@ -745,8 +819,13 @@ const handlePaginationCurChange = (val) => {
|
||||
<!-- 否则就是普通字段 -->
|
||||
<template v-else>
|
||||
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||
<el-input v-model="dialogObjectForm[fieldDescInfo.key]" :disabled="cdkeyCodeInputDisabled"
|
||||
:placeholder="fieldDescInfo.help_text" v-if="fieldDescInfo.key === 'Code'"></el-input>
|
||||
<el-input v-model="dialogObjectForm[fieldDescInfo.key]"
|
||||
:placeholder="fieldDescInfo.help_text"></el-input>
|
||||
:placeholder="fieldDescInfo.help_text" :disabled="cdkeyCodeNumInputDisabled"
|
||||
v-else-if="fieldDescInfo.key === 'CodeNum'" type="number"></el-input>
|
||||
<el-input v-model="dialogObjectForm[fieldDescInfo.key]"
|
||||
:placeholder="fieldDescInfo.help_text" v-else></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
Loading…
x
Reference in New Issue
Block a user