This commit is contained in:
likun 2025-08-18 17:49:05 +08:00
parent 4237a3bf89
commit aeecf8b8b0
15 changed files with 347 additions and 17 deletions

View File

@ -81,6 +81,17 @@ func (svc *AccountService) GetWhiteListAll(projectId int) ([]*dto.WhiteListInfo,
})
}
}
// 扶持号也用的白名单功能标记
scList, err := svc.accountRepo.GetSCListAll(projectEt)
if err != nil {
return nil, err
}
for _, sc := range scList {
list = append(list, &dto.WhiteListInfo{
WType: "support",
Value: sc.Account,
})
}
}
return list, nil

View File

@ -294,7 +294,8 @@ func (svc *CommonResourceService) Create(ctx context.Context, projectId int, res
tmpObj, err := createOne(dtoObj)
if err != nil {
xlog.Errorf("create support account %v db error:%v", ac, err)
err = nil // 忽略多个插入的报错
return projectEt, tmpObj, err
//err = nil // 忽略多个插入的报错
} else {
newDtoObj = tmpObj
}

View File

@ -6,9 +6,12 @@ import (
"admin/apps/game/domain/repo"
"admin/apps/game/model"
"admin/internal/errcode"
"admin/internal/event"
"admin/internal/model/dto"
"admin/lib/xlog"
"context"
"gorm.io/gorm"
"strconv"
)
type ProjectService struct {
@ -91,6 +94,53 @@ func (svc *ProjectService) GetAllItems(projectId int) ([]*dto.CommonDtoFieldChoi
return handler.GetItems(projectEt)
}
func (svc *ProjectService) ChangeRoleItem(ctx context.Context, projectId int, serverId, roleId string, itemId int32, itemNum int64) error {
_, projectEt, find, err := svc.repo.GetById(projectId)
if err != nil {
return err
}
if !find {
return errcode.New(errcode.ServerError, "not found project %v db data", projectId)
}
handler := projects.GetProjectValueChoicesGetHook(projectEt.Po.ProjectType)
if handler == nil {
xlog.Warnf("project %+v not found choices hook", projectEt.Po)
return nil
}
err = handler.ChangeRoleItem(projectEt, serverId, roleId, itemId, itemNum)
if err != nil {
return err
}
userId := ctx.Value("user_id").(int)
//userName := ctx.Value("user_name").(string)
evPayload := &event.EventPayload_UserGameExecute{
UserId: userId,
ProjectId: projectId,
ProjectName: projectEt.Po.Name,
OpResourceType: "变动道具",
OpResourceGroup: "变动道具",
OpResourceKey: strconv.Itoa(int(itemId)),
Method: "新增",
SrcDataList: []any{map[string]any{
"server_id": serverId,
"role_id": roleId,
"item_id": itemId,
"item_num": itemNum,
}},
}
if itemNum <= 0 {
evPayload.Method = "扣除"
}
event.GetMgrInstance().Publish(event.EventTopic_UserGameExecute, evPayload)
return err
}
func (svc *ProjectService) GetAllItemBag(projectId int) ([]*dto.ItemBagInfo, error) {
dbList, err := new(model.ItemBag).List(projectId)
if err != nil {

View File

@ -39,6 +39,7 @@ type IGetRoleDetailHook interface {
type IGetAllValueChoiceHook interface {
// 获取所有道具,可以用于前端页面做下拉选择等
GetItems(projectInfo *entity.Project) ([]*dto2.CommonDtoFieldChoice, error)
ChangeRoleItem(projectInfo *entity.Project, serverId, roleId string, itemId int32, itemNum int64) error
}
type IServerInfoHook interface {

View File

@ -13,15 +13,16 @@ var debugDisableAllHook = false // 调试用,关闭所有项目钩子调用,
var projectsResourceHookMgr = map[string]map[string]any{
// 神魔大陆项目注册的资源钩子回调
consts.RegisteredProjectId_shenmodalu: {
consts.ResourcesName_Server: &smdl.ServerHook{}, // 查看了数据库所有数据之后还要连alisrv获取所有进程运行情况
consts.ResourcesName_Role: &smdl.RoleHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_Account: &smdl.AccountHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_Ban: &smdl.BanHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_MailGlobal: &smdl.MailGlobalHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_MailRole: &smdl.MailRoleHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_WhiteList: &smdl.WhitelistHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_GenAccount: &smdl.GenAccountHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_GameLog: &smdl.GameLogHook{},
consts.ResourcesName_Server: &smdl.ServerHook{}, // 查看了数据库所有数据之后还要连alisrv获取所有进程运行情况
consts.ResourcesName_Role: &smdl.RoleHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_Account: &smdl.AccountHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_Ban: &smdl.BanHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_MailGlobal: &smdl.MailGlobalHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_MailRole: &smdl.MailRoleHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_WhiteList: &smdl.WhitelistHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_GenAccount: &smdl.GenAccountHook{}, // 所有角色走神魔大陆api直接获取
consts.ResourcesName_GameLog: &smdl.GameLogHook{},
consts.ResourcesName_SupportAccount: &smdl.SupportAccountHook{},
},
}
@ -59,3 +60,7 @@ func (items *debugItemsHook) GetItems(projectInfo *entity.Project) ([]*dto.Commo
{Desc: "法杖", Value: 3456456},
}, nil
}
func (items *debugItemsHook) ChangeRoleItem(projectInfo *entity.Project, serverId, roleId string, itemId int32, itemNum int64) error {
return nil
}

View File

@ -5,6 +5,10 @@ import (
"admin/internal/errcode"
"admin/internal/model/dto"
"admin/lib/httpclient"
"admin/lib/xlog"
"math"
"net/url"
"strconv"
"time"
)
@ -67,3 +71,35 @@ func (items *Items) GetItems(projectInfo *entity.Project) ([]*dto.CommonDtoField
return rsp.Data.List, nil
}
func (items *Items) ChangeRoleItem(projectInfo *entity.Project, serverId, roleId string, itemId int32, itemNum int64) error {
alisrvAddr := projectInfo.GetApiAddr()
if alisrvAddr == "" {
return errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name)
}
if itemNum == 0 {
xlog.Warnf("change role item:%v,%v,%v,%v num invalid", serverId, roleId, itemId, itemNum)
return nil
}
// http://127.0.0.1:12007/GM?cmd_data=addItem&roleid=20007000171&itemsn=14201093&itemnum=1&isbind=true
params := &url.Values{}
params.Set("cmd_data", "addItem")
params.Add("roleid", roleId)
params.Add("server", serverId)
params.Set("itemsn", strconv.Itoa(int(itemId)))
params.Set("itemnum", strconv.FormatInt(int64(math.Abs(float64(itemNum))), 10))
params.Set("isbind", "true")
if itemNum < 0 {
params.Set("deduct", "true")
}
rsp := make(map[string]any)
err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
if err != nil {
}
return nil
}

View File

@ -29,10 +29,18 @@ func (hook *SupportAccountHook) Create(projectInfo *entity.Project, resource str
params.Add("op", "add")
//params.Add("server", info.ServerConfID)
rsp := make(map[string]any)
err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
// 所有区服
serverList, err := getAllRunningServers(projectInfo)
if err != nil {
return errcode.New(errcode.ServerError, "发送新增白名单请求:%+v错误:%v", info, err)
return err
}
for _, v := range serverList {
params.Set("server", v.ServerId)
rsp := make(map[string]any)
err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
if err != nil {
return errcode.New(errcode.ServerError, "发送新增扶持号请求:%+v错误:%v", info, err)
}
}
return nil
@ -54,10 +62,18 @@ func (hook *SupportAccountHook) Delete(projectInfo *entity.Project, resource str
params.Add("op", "remove")
//params.Add("server", info.ServerConfID)
rsp := make(map[string]any)
err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
// 所有区服
serverList, err := getAllRunningServers(projectInfo)
if err != nil {
return errcode.New(errcode.ServerError, "发送删除白名单请求:%+v错误:%v", info, err)
return err
}
for _, v := range serverList {
params.Set("server", v.ServerId)
rsp := make(map[string]any)
err := httpclient.Request(alisrvAddr+"/gm", "get", params, &rsp)
if err != nil {
return errcode.New(errcode.ServerError, "发送删除扶持号请求:%+v错误:%v", info, err)
}
}
return nil

View File

@ -11,6 +11,7 @@ import (
type IAccountRepo interface {
GetWhiteListAll(projectEt *entity.Project) ([]*dto.WhiteListInfo, error)
GetBanListAll(projectEt *entity.Project) ([]*model.Ban, error)
GetSCListAll(projectEt *entity.Project) ([]*model.SupportAccount, error)
}
type accountRepoImpl struct {
@ -46,3 +47,13 @@ func (impl *accountRepoImpl) GetBanListAll(projectEt *entity.Project) ([]*model.
return list, nil
}
func (impl *accountRepoImpl) GetSCListAll(projectEt *entity.Project) ([]*model.SupportAccount, error) {
list := make([]*model.SupportAccount, 0)
err := impl.db.Where("project_id = ?", projectEt.Po.ID).Find(&list).Error
if err != nil {
return nil, errcode.New(errcode.DBError, "list project %v sc list error:%v", projectEt.Po.ID, err)
}
return list, nil
}

View File

@ -3,6 +3,7 @@ package server
import (
"admin/internal/context"
"admin/internal/model/dto"
"admin/lib/xlog"
stdContext "context"
)
@ -92,3 +93,15 @@ func (ctl *controller) GetProjectAllItems(ctx *context.WebContext, params *dto.N
rsp.Items = items
return nil
}
func (ctl *controller) ChangeProjectItem(ctx *context.WebContext, params *dto.ChangeProjectItemReq, rsp *dto.ChangeProjectItemRes) error {
ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId)
ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserName)
projectId := getCtxURIProjectId(ctx)
xlog.Debugf("receive change item:%v,%v,%v,%v,%v", projectId, params.ServerId, params.RoleId, params.ItemId, params.ItemNum)
err := ctl.svc.ChangeItem(ctx1, projectId, params.ServerId, params.RoleId, params.ItemId, params.ItemNum)
if err != nil {
return err
}
return nil
}

View File

@ -31,6 +31,7 @@ func (srv *Server) Route(engine *web.Engine, sdkEngine *web.Engine) {
}
projectGroup.Get("/:projectId/items", "获取项目所有道具列表", consts.WebPathPermit_Read, srv.ctl.GetProjectAllItems)
projectGroup.Get("/:projectId/change_item", "改变道具数量", consts.WebPathPermit_Read, srv.ctl.ChangeProjectItem)
{
// 礼包码特殊接口

View File

@ -6,6 +6,7 @@ import (
"admin/internal/consts"
"admin/internal/model/dto"
"admin/internal/permission"
"context"
"sort"
)
@ -81,3 +82,8 @@ func (svc *Service) GetProjectInvokeApiAddr(projectId int, serverIds []int) ([]s
func (svc *Service) GetAllItems(projectId int) ([]*dto.CommonDtoFieldChoice, error) {
return svc.projectSvc.GetAllItems(projectId)
}
func (svc *Service) ChangeItem(ctx context.Context, projectId int, serverId string, roleId string, itemId int32, itemNum int64) error {
err := svc.projectSvc.ChangeRoleItem(ctx, projectId, serverId, roleId, itemId, itemNum)
return err
}

View File

@ -152,3 +152,13 @@ type GameLogEventListRsp struct {
FieldsDescInfo []*GameLogFieldInfo `json:"fieldsDescInfo"`
Rows [][]any `json:"rows"`
}
type ChangeProjectItemReq struct {
ServerId string `json:"server_id"`
RoleId string `json:"role_id"`
ItemId int32 `json:"item_id"`
ItemNum int64 `json:"item_num"`
}
type ChangeProjectItemRes struct {
}

View File

@ -47,4 +47,17 @@ export function resourceGetAllItems(projectId) {
url: '/project/' + projectId.toString() + "/items",
method: 'get',
})
}
export function resourceChangeRoleItem(projectId, serverId, roleId, itemId, itemNum) {
return request({
url: '/project/' + projectId.toString() + "/change_item",
method: 'get',
params: {
server_id: serverId,
role_id: roleId,
item_id: itemId,
item_num: itemNum
}
})
}

View File

@ -62,7 +62,7 @@ const handleClick = (tab, event) => {
<div>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick" v-if="loadAccountOk">
<el-tab-pane label="道具列表" name="detail">
<roleDetailItems :items="roleInfo.items"/>
<roleDetailItems :serverId="serverId" :roleId="roleId" :items="roleInfo.items"/>
</el-tab-pane>
<!-- <el-tab-pane label="货币记录" name="currency" v-if="accountInfo !== null">货币记录子页面</el-tab-pane>-->
<el-tab-pane key="tab-chat" label="聊天记录" name="chat">

View File

@ -1,16 +1,172 @@
<script setup>
import {ref} from "vue";
import {resourceChangeRoleItem, resourceGetAllItems} from "@/api/resource.js";
import LocalCache from "@/stores/localCache.js";
import {ElNotification} from "element-plus";
const props = defineProps({
serverId: '',
roleId: '',
items: {},
})
const cachedResource = LocalCache.getCache("resource");
const projectId = cachedResource.meta.projectId
const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogOpObj = ref({})
const selectItemId = ref(null)
const oldItemNum = ref(0)
const selectItemNum = ref(null)
const onClickDialogButton = (title, row) => {
console.log("点击行:", row)
dialogTitle.value = title
selectItemId.value = row.item_id
selectItemNum.value = row.item_num
oldItemNum.value = row.item_num
dialogOpObj.value = row
dialogVisible.value = true
}
const loadingRemoteItems = ref(false)
const itemChoices = ref({})
const handleQueryItem = (itemQueryStr) => {
if (!itemQueryStr) {
itemChoices.value = []
return
}
loadingRemoteItems.value = true
itemQueryStr = itemQueryStr.replace(/[\s\u3000]/g, "")
resourceGetAllItems(projectId).then((res) => {
console.log("获取所有道具返回:", res.data)
console.log("查询字符串:[" + itemQueryStr + "]")
let curQueryCount = 0
itemChoices.value = res.data.items.filter((item) => {
if (curQueryCount > 1000) {
//
return false
}
const idFind = (item.value.toString()).includes(itemQueryStr)
if (idFind) {
curQueryCount++
return idFind
}
const descFind = item.desc.includes(itemQueryStr)
if (descFind) {
curQueryCount++
}
return descFind
})
loadingRemoteItems.value = false
}, (err) => {
itemChoices.value = []
})
}
const onCloseDialog = () => {
dialogTitle.value = ''
dialogOpObj.value = {}
dialogVisible.value = false
selectItemId.value = null
selectItemNum.value = null
}
const submitOpItem = (opTitle) => {
console.log("选中道具:", selectItemId.value)
console.log("选中道具数量:", selectItemNum.value)
if (selectItemId.value === null || selectItemId.value === undefined || selectItemId.value === '') {
alert('请选择道具!')
return
}
if (selectItemNum.value === null || selectItemNum.value === undefined || selectItemNum.value === '0') {
alert('请输入有效数量!')
return
}
if (opTitle === '扣除') {
selectItemNum.value = -Number(selectItemNum.value)
}
console.log("选中道具:", selectItemId.value)
console.log("选中道具数量:", selectItemNum.value)
resourceChangeRoleItem(projectId, props.serverId, props.roleId, selectItemId.value, selectItemNum.value).then((res) => {
ElNotification({
title: "修改道具数量成功!",
message: h('i', {style: 'color: teal'}, 'ok'),
duration: 900,
onClose(vm) {
}
})
dialogVisible.value = false
}, (err) => {
})
}
</script>
<template>
<div>
<div style="margin-bottom: 10px">
<el-button type="primary" @click="onClickDialogButton('添加道具', {})">添加道具</el-button>
</div>
<el-table :data="items" style="width: 100%" max-height="500px" table-layout="auto" border :show-header="true">
<el-table-column prop="item_id" label="道具id"/>
<el-table-column prop="desc" label="道具名"/>
<el-table-column prop="item_num" label="道具数量"/>
<el-table-column prop="func" label="功 能">
<template #default="scope">
<el-button type="warning" @click="onClickDialogButton('扣除', scope.row)">扣除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog
v-model="dialogVisible"
width="40%"
:title="dialogTitle"
append-to-body
style="height: 300px"
@close="onCloseDialog"
destroy-on-close
>
<el-form label-width="120px">
<el-form-item label="道具" label-width="120px" required style="width: 400px">
<el-select v-model="selectItemId" placeholder="--搜索道具--"
filterable remote clearable
:remote-method="handleQueryItem"
:loading="loadingRemoteItems"
v-if="dialogTitle!=='扣除'"
>
<el-option v-for="info in itemChoices" :key="info.value" :label="info.desc+'('+info.value+')'"
:value="info.value"></el-option>
</el-select>
<el-input type="number" v-model="selectItemId" disabled v-else></el-input>
</el-form-item>
<el-form-item label="当前数量" label-width="120px" required
style="width: 400px" v-if="dialogTitle==='扣除'">
<el-input type="number" v-model="oldItemNum" disabled></el-input>
</el-form-item>
<el-form-item :label="dialogTitle==='扣除'?'扣除数量':'添加数量'" label-width="120px" required
style="width: 400px">
<el-input type="number" v-model="selectItemNum"
:placeholder="dialogTitle==='扣除'?'输入扣除数量':'输入添加数量'"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitOpItem(dialogTitle)">提交</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>