fix:1,修改

main
YuanJian 2025-09-04 09:20:44 +08:00
parent 250e3125c6
commit 9b7344e595
63 changed files with 6362 additions and 263 deletions

View File

@ -6,4 +6,4 @@ VITE_APP_TITLE = 超管系统
VITE_APP_ENV = 'development'
# 代理管理系统/开发环境
VITE_APP_BASE_API = '/ff-api'
VITE_APP_BASE_API = '/dev-api'

BIN
dist.rar

Binary file not shown.

View File

@ -32,6 +32,7 @@
"jsencrypt": "3.3.2",
"nprogress": "0.2.0",
"sortablejs": "^1.15.3",
"html2canvas": "^1.4.1",
"pinia": "2.1.7",
"vue": "3.4.31",
"vue-cropper": "1.1.1",

View File

@ -0,0 +1,183 @@
import request from '@/utils/request'
// 活动中心列表
export function listActivityInfo(query) {
return request({
url: '/discounts/activityInfo/list',
method: 'get',
params: query
})
}
//活动分类下拉框列表
export function getActivityCategory(query) {
return request({
url: '/discounts/activityCategory/categorySelectList',
method: 'get',
params: query
})
}
// 新增活动
export function addActivity(data) {
return request({
url: '/discounts/activityInfo/addActivity',
method: 'post',
data: data
})
}
// 修改活动
export function updateActivity(data) {
return request({
url: '/discounts/activityInfo/updateActivity',
method: 'put',
data: data
})
}
// 获取活动详情
export function getActivityInfo({id}) {
return request({
url: `/discounts/activityInfo/getActivityInfo/${id}`,
method: 'get'
})
}
//活动列表指定
export function activityInfoSetTop({ id, sortNo }) {
return request({
url: `/discounts/activityInfo/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 删除活动列表
export function deleteActivityInfo(id) {
return request({
url: `/discounts/activityInfo/delete/${id}`,
method: 'delete'
})
}
// 发布活动
export function activityInfoPublishActivity(id) {
return request({
url: `/discounts/activityInfo/publishActivity/${id}`,
method: 'put'
})
}
// 关闭活动
export function activityInfoCloseActivity(id) {
return request({
url: `/discounts/activityInfo/closeActivity/${id}`,
method: 'put'
})
}
// 活动分类列表
export function getDiscountsActivityCategory(query) {
return request({
url: '/discounts/activityCategory/list',
method: 'get',
params: query
})
}
//分类管理是否启用
export function activityCategorySetOnOrOff(data) {
return request({
url: '/discounts/activityCategory/setOnOrOff',
method: 'put',
data: data
})
}
// 分类管理排序
export function activityCategorySetTop({ id, sortNo }) {
return request({
url: `/discounts/activityCategory/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 新增分类
export function addActivityCategory(data) {
return request({
url: '/discounts/activityCategory/addActivityCategory',
method: 'post',
data: data
})
}
// 修改分类
export function editActivityCategory(data) {
return request({
url: '/discounts/activityCategory/editActivityCategory',
method: 'put',
data: data
})
}
// 删除分类
export function deleteActivityCategory(id) {
return request({
url: `/discounts/activityCategory/${id}`,
method: 'delete'
})
}
// 获取分类详情
export function getActivityCategoryInfo({id}) {
return request({
url: `/discounts/activityCategory/${id}`,
method: 'get'
})
}
// 活动优惠统计列表
export function getActivityDiscountReceiveList(query) {
return request({
url: '/discounts/receive/activityDiscountReceiveList',
method: 'get',
params: query
})
}
// 派发奖励
export function editDistributeReward(data) {
return request({
url: '/discounts/activityInfo/distributeReward',
method: 'put',
data: data
})
}
// 推广记录列表
export function getExtensionList(query) {
return request({
url: '/discounts/activityInfo/getExtensionList',
method: 'get',
params: query
})
}
// 指定代理账号
export function getChannelLists(query) {
return request({
url: '/operation/channel/list',
method: 'get',
params: query
})
}
// 集字活动资源
export function getActivityCombinationCharacter(query) {
return request({
url: 'discounts/activityCombinationCharacter/list',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,149 @@
import request from '@/utils/request'
// 查询实时返水列表
export function listRealtimeRebate(query) {
return request({
url: '/discounts/realtimeRebate/list',
method: 'get',
params: query
})
}
// 查询基本游戏信息
export function getGameTypes(query) {
return request({
url: '/discounts/realtimeRebate/getGameTypes',
method: 'get',
params: query
})
}
// 查询基本平台信息
export function getGameTypesSimp(query) {
return request({
url: '/discounts/realtimeRebate/getGameTypesSimp',
method: 'get',
params: query
})
}
// 查询游戏
export function getGameTypesGame(data = {}) {
return request({
url: '/discounts/realtimeRebate/getGameTypesGame',
method: 'post',
data: data
})
}
// 查询基本游戏信息
export function getPlatformTree(query) {
return request({
url: '/game/platform/tree',
method: 'get',
params: query
})
}
// 查询实时返水币种已绑定的会员层级
export function getBoundMemberLevel(query) {
return request({
url: '/discounts/realtimeRebate/getBoundMemberLevel',
method: 'get',
params: query
})
}
// 查询实时返水详细
export function getRealtimeRebate(id) {
return request({
url: '/discounts/realtimeRebate/' + id,
method: 'get'
})
}
// 新增实时返水
export function addRealtimeRebate(data) {
return request({
url: '/discounts/realtimeRebate/addRebate',
method: 'post',
data: data
})
}
// 启停实时返水
export function setOnOrOff(data) {
return request({
url: '/discounts/realtimeRebate/setOnOrOff',
method: 'put',
data: data
})
}
// 修改实时返水
export function updateRealtimeRebate(data) {
return request({
url: '/discounts/realtimeRebate',
method: 'put',
data: data
})
}
// 删除实时返水
export function delRealtimeRebate(id) {
return request({
url: '/discounts/realtimeRebate/' + id,
method: 'delete'
})
}
// 查询可设定返水的VIP等级
export function getVipLevels(query) {
return request({
url: '/discounts/realtimeRebate/vip/list',
method: 'get',
params: query
})
}
// 返水设置查询
export function getRealtimeRebateConfig(query) {
return request({
url: '/discounts/discountRealtimeRebateSetting/getRebateSetting',
method: 'get',
params: query
})
}
// 返水设置
export function setRealtimeRebateConfig(data) {
return request({
url: '/discounts/discountRealtimeRebateSetting',
method: 'put',
data: data
})
}
// 返水开关状态查询
export function getRealtimeRebateStatus(query) {
return request({
url: '/discounts/discountRealtimeRebateSetting/getSettingStatus',
method: 'get',
params: query
})
}
// 返水开关状态设置
export function setRealtimeRebateStatus(data) {
return request({
url: '/discounts/discountRealtimeRebateSetting/setOnOrOff',
method: 'put',
data: data
})
}
// 查询返水设置历史记录
export function getRealtimeRebateHistory(query) {
return request({
url: '/discounts/discountRealtimeRebateSetting/historyList',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,125 @@
import request from '@/utils/request'
// 会员申请审核列表
export function activityRewardAuditList(query) {
return request({
url: '/discounts/activityRewardAudit/list',
method: 'get',
params: query
})
}
// 会员申请审核通过审核
export function activityRewardAuditPass(data) {
return request({
url: '/discounts/activityRewardAudit/auditAdopt',
method: 'post',
data: data
})
}
// 会员申请审核拒绝
export function activityRewardAuditRefuse(data) {
return request({
url: '/discounts/activityRewardAudit/auditRefuse',
method: 'post',
data: data
})
}
// 全部记录列表
export function getReceiveInfoList(query) {
return request({
url: '/discounts/receive/receiveInfoList',
method: 'get',
params: query
})
}
// 优惠明细
export function getDiscountDetailList(query) {
return request({
url: '/discounts/receive/discountDetailList',
method: 'get',
params: query
})
}
// 待领取列表
export function getReceivePendingList(query) {
return request({
url: '/discounts/receive/receivePendingList',
method: 'get',
params: query
})
}
// 已领取列表
export function getReceiveReceivedList(query) {
return request({
url: '/discounts/receive/receiveReceivedList',
method: 'get',
params: query
})
}
// 被拒绝列表
export function getReceiveRejectedList(query) {
return request({
url: '/discounts/receive/receiveRejectedList',
method: 'get',
params: query
})
}
// 已过期列表
export function getReceiveExpiredList(query) {
return request({
url: '/discounts/receive/receiveExpiredList',
method: 'get',
params: query
})
}
// 修改优惠领取记录
export function updateReceiveInfo(data) {
return request({
url: '/discounts/receive/updateReceiveInfo',
method: 'post',
data: data
})
}
// 立即派发优惠领取
export function dispatchReceive(data) {
return request({
url: '/discounts/receive/dispatchReceive',
method: 'post',
data: data
})
}
// 强制取消优惠领取
export function cancleReceive(data) {
return request({
url: '/discounts/receive/cancleReceive',
method: 'post',
data: data
})
}
// 待领取列表
export function getDistributeAuditList(query) {
return request({
url: '/discounts/activityRewardAudit/distributeAuditList',
method: 'get',
params: query
})
}
// 已审核列表
export function getActivityRewardAuditList(query) {
return request({
url: '/discounts/activityRewardAudit/auditedList',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,370 @@
import request from '@/utils/request'
// 根据任务id查询任务详情
export function getTaskInfo(id) {
return request({
url: `/discounts/taskCenter/${id}`,
method: 'get'
})
}
// 批量修改任务
export function batchUpdateTask(data) {
return request({
url: '/discounts/taskCenter/batchUpdate',
method: 'put',
data: data
})
}
// ---------------------------新人福利----------------------------------- //
// 查询新人福利列表
export function getNewcomerListInfo(query) {
return request({
url: '/discounts/newCome/getNewComeListInfo',
method: 'get',
params: query
})
}
// 新人福利任务是否开启
export function newcomerSetOnOrOff(data) {
return request({
url: '/discounts/newCome/setOnOrOff',
method: 'put',
data: data
})
}
// 提示气泡是否开启
export function newcomerSetTipPop(data) {
return request({
url: '/discounts/newCome/setTipPop',
method: 'put',
data: data
})
}
// 设置新人福利列表置顶
export function newcomerSetTop({ id, sortNo }) {
return request({
url: `/discounts/newCome/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 修改新人福利
export function editNewcomer(data) {
return request({
url: '/discounts/newCome',
method: 'put',
data: data
})
}
// 查询新人福利设置
export function getNewcomerSetting(query) {
return request({
url: '/discounts/newCome/getTaskSetting',
method: 'get',
params: query
})
}
// 新人福利设置
export function setNewcomerSetting(data) {
return request({
url: '/discounts/newCome/setTaskSetting',
method: 'put',
data: data
})
}
// ---------------------------每日任务----------------------------------- //
// 每日任务列表查询
export function getDailyTaskListInfo(query) {
return request({
url: '/discounts/taskCenter/daily/list',
method: 'get',
params: query
})
}
// 每日任务开关
export function dailyTaskSetOnOrOff(data) {
return request({
url: '/discounts/taskCenter/daily/setOnOrOff',
method: 'put',
data: data
})
}
// 每日任务置顶
export function dailyTaskSetTop({ id, sortNo }) {
return request({
url: `/discounts/taskCenter/daily/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 新增每日任务
export function addDailyTask(data) {
return request({
url: '/discounts/taskCenter/daily/add',
method: 'post',
data: data
})
}
// 修改每日任务
export function editDailyTask(data) {
return request({
url: '/discounts/taskCenter/daily/update',
method: 'put',
data: data
})
}
// 查询每日任务设置
export function getDailyTaskSetting(query) {
return request({
url: '/discounts/taskSetting/daily/getTaskSetting',
method: 'get',
params: query
})
}
// 保存每日任务设置
export function setDailyTaskSetting(data) {
return request({
url: '/discounts/taskSetting/daily/setTaskSetting',
method: 'put',
data: data
})
}
// 删除每日任务
export function deleteDailyTask(id) {
return request({
url: `/discounts/taskCenter/daily/${id}`,
method: 'delete'
})
}
// ---------------------------每周任务----------------------------------- //
// 查询每周任务列表
export function getWeeklyTaskListInfo(query) {
return request({
url: '/discounts/taskCenter/weekly/list',
method: 'get',
params: query
})
}
// 每周任务开关
export function weeklyTaskSetOnOrOff(data) {
return request({
url: '/discounts/taskCenter/weekly/setOnOrOff',
method: 'put',
data: data
})
}
// 每周任务置顶
export function weeklyTaskSetTop({ id, sortNo }) {
return request({
url: `/discounts/taskCenter/weekly/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 新增每周任务
export function addWeeklyTask(data) {
return request({
url: '/discounts/taskCenter/weekly/add',
method: 'post',
data: data
})
}
// 修改每周任务
export function editWeeklyTask(data) {
return request({
url: '/discounts/taskCenter/weekly/update',
method: 'put',
data: data
})
}
// 查询每周任务设置
export function getWeeklyTaskSetting(query) {
return request({
url: '/discounts/taskSetting/weekly/getTaskSetting',
method: 'get',
params: query
})
}
// 保存每周任务设置
export function setWeeklyTaskSetting(data) {
return request({
url: '/discounts/taskSetting/weekly/setTaskSetting',
method: 'put',
data: data
})
}
// 删除每周任务
export function deleteWeeklyTask(id) {
return request({
url: `/discounts/taskCenter/weekly/${id}`,
method: 'delete'
})
}
// ---------------------------三日神秘任务----------------------------------- //
// 查询神秘任务列表
export function getMysteryTaskListInfo(query) {
return request({
url: '/discounts/taskCenter/mysteryTask/list',
method: 'get',
params: query
})
}
// 神秘任务开关
export function mysteryTaskSetOnOrOff(data) {
return request({
url: '/discounts/taskCenter/mysteryTask/setOnOrOff',
method: 'put',
data: data
})
}
// 神秘任务置顶
export function mysteryTaskSetTop({ id, sortNo }) {
return request({
url: `/discounts/taskCenter/mysteryTask/setTop/${id}/${sortNo}`,
method: 'put'
})
}
// 新增神秘任务
export function addMysteryTask(data) {
return request({
url: '/discounts/taskCenter/mysteryTask/add',
method: 'post',
data: data
})
}
// 修改神秘任务
export function editMysteryTask(data) {
return request({
url: '/discounts/taskCenter/mysteryTask/update',
method: 'put',
data: data
})
}
// 查询神秘任务设置
export function getMysteryTaskSetting(query) {
return request({
url: '/discounts/taskSetting/mysteryTask/getTaskSetting',
method: 'get',
params: query
})
}
// 保存神秘任务设置
export function setMysteryTaskSetting(data) {
return request({
url: '/discounts/taskSetting/mysteryTask/setTaskSetting',
method: 'put',
data: data
})
}
// 删除神秘任务
export function deleteMysteryTask(id) {
return request({
url: `/discounts/taskCenter/mysteryTask/${id}`,
method: 'delete'
})
}
// 神秘任务总开关状态
export function mysteryTaskGetAllOnOrOff() {
return request({
url: '/discounts/taskSetting/mysteryTask/getSettingStatus',
method: 'get'
})
}
// 神秘任务总开关设置
export function mysteryTaskSetAllOnOrOff(data) {
return request({
url: '/discounts/taskSetting/mysteryTask/setOnOrOff',
method: 'put',
data: data
})
}
// ---------------------------活跃度设置----------------------------------- //
// 活跃度设置列表
export function getActivityList(query) {
return request({
url: '/discounts/activityBox/list',
method: 'get',
params: query
})
}
// 活跃度设置开关状态
export function getActivityStatus() {
return request({
url: '/discounts/activitySetting/getStatus',
method: 'get'
})
}
// 活跃度开关设置
export function setActivityStatus(data) {
return request({
url: '/discounts/activitySetting/setOnOrOff',
method: 'put',
data: data
})
}
// 查询活跃度设置
export function getActivitySetting(query) {
return request({
url: '/discounts/activitySetting/getActivitySetting',
method: 'get',
params: query
})
}
// 保存活跃度设置
export function setActivitySetting(data) {
return request({
url: '/discounts/activitySetting/setActivitySetting',
method: 'put',
data: data
})
}
// 修改活跃度设置
export function editActivitySetting(data) {
return request({
url: '/discounts/activityBox',
method: 'put',
data: data
})
}

View File

@ -0,0 +1,92 @@
import request from '@/utils/request'
// 查询会员投注细目列表
export function listDetails(query) {
return request({
url: '/game/details/list',
method: 'get',
params: query
})
}
// 查询会员投注细目详细
export function getDetails(id) {
return request({
url: '/game/details/' + id,
method: 'get'
})
}
// 新增会员投注细目
export function addDetails(data) {
return request({
url: '/game/details',
method: 'post',
data: data
})
}
// 修改会员投注细目
export function updateDetails(data) {
return request({
url: '/game/details',
method: 'put',
data: data
})
}
// 删除会员投注细目
export function delDetails(id) {
return request({
url: '/game/details/' + id,
method: 'delete'
})
}
/* ------------------------------- 投注记录start ------------------------------- */
/**
* 投注统计列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226082399e0
* @param {*} query
* @returns
*/
export function listStatistics(query) {
return request({
url: '/game/details/statistics',
method: 'get',
params: query
})
}
/* ------------------------------- 投注记录end ------------------------------- */
/* ------------------------------- 会员投注细目start ------------------------------- */
/**
* 投注明细列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289
* @param {*} query
* @returns
*/
export function listSummary(query) {
return request({
url: '/game/details/summary/list',
method: 'get',
params: query
})
}
/**
* 投注明细列表汇总
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226018011e0
* @param {*} query
* @returns
*/
export function totalSummary(query) {
return request({
url: '/game/details/summary',
method: 'get',
params: query
})
}
/* ------------------------------- 会员投注细目end ------------------------------- */

View File

@ -0,0 +1,269 @@
import request from '@/utils/request'
// 查询平台子游戏管理列表
export function listGame(query) {
return request({
url: '/game/game/list',
method: 'get',
params: query
})
}
// 查询平台子游戏管理详细
export function getGame(id) {
return request({
url: '/game/game/' + id,
method: 'get'
})
}
// 新增平台子游戏管理
export function addGame(data) {
return request({
url: '/game/game',
method: 'post',
data: data
})
}
// 修改平台子游戏管理
export function updateGame(data) {
return request({
url: '/game/game',
method: 'put',
data: data
})
}
// 删除平台子游戏管理
export function delGame(id) {
return request({
url: '/game/game/' + id,
method: 'delete'
})
}
// 游戏图片同步
export function gameGameSync({id}) {
return request({
url: `/game/game/sync/${id}`,
method: 'get'
})
}
/**
* 列表开关
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226766867e0
* @param {*} data
* @returns
*/
export function updateGameSwitch(data) {
return request({
url: '/game/game/switch',
method: 'put',
data: data
})
}
/**
* 子游戏置顶和列表交换
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226760893e0
* @param {*} id
* @param {*} sortNo
* @returns
*/
export function gameSort({ id, sortNo }) {
return request({
url: `/game/game/sort/top/${id}/${sortNo}`,
method: 'get'
})
}
/* ------------------------------- 热门管理start ------------------------------- */
/**
* 热门管理列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/230502710e0
* @param {*} query
* @returns
*/
export function listPopular(query) {
return request({
url: '/game/popular/list',
method: 'get',
params: query
})
}
/**
* 热门管理置顶和列表交换
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/230512091e0
* @param {*} id
* @param {*} sortNo
* @returns
*/
export function popularSort({ id, sortNo }) {
return request({
url: `/game/popular/sort/top/${id}/${sortNo}`,
method: 'get'
})
}
/**
* 移除热门管理
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/230543317e0
* @param {*} id
* @returns
*/
export function delPopular(id) {
return request({
url: '/game/popular/' + id,
method: 'delete'
})
}
/* ------------------------------- 热门管理end ------------------------------- */
/* ------------------------------- 系统热门模块start ------------------------------- */
/**
* 系统热门模板列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226847441e0
* @param {*} query
* @returns
*/
export function listSystem(query) {
return request({
url: '/game/details/popular/list',
method: 'get',
params: query
})
}
/* ------------------------------- 系统热门模块end ------------------------------- */
/* ------------------------------- 类型管理start ------------------------------- */
/**
* 游戏类型管理列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226897775e0
* @param {*} query
* @returns
*/
export function listCategory(query) {
return request({
url: '/game/category/list',
method: 'get',
params: query
})
}
/**
* 类型管理置顶和列表交换
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226940195e0
* @param {*} id
* @param {*} sortNo
* @returns
*/
export function categorySort({ id, sortNo }) {
return request({
url: `/game/category/sort/top/${id}/${sortNo}`,
method: 'get'
})
}
/**
* 查询类型管理详情
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226948669e0
* @param {*} id
* @returns
*/
export function getCategory(id) {
return request({
url: '/game/category/' + id,
method: 'get'
})
}
/**
* 修改类型管理行数设置
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226951731e0
* @param {*} data
* @returns
*/
export function updateCategory(data) {
return request({
url: '/game/category',
method: 'put',
data: data
})
}
/**
* 新增外部链接
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226955535e0
* @param {*} data
* @returns
*/
export function addLinks(data) {
return request({
url: '/game/category/add/external/links',
method: 'post',
data: data
})
}
/**
* 修改外部链接
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226993828e0
* @param {*} data
* @returns
*/
export function updateLinks(data) {
return request({
url: '/game/category/update/external/links',
method: 'put',
data: data
})
}
/**
* 删除外部链接
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226994734e0
* @param {*} id
* @returns
*/
export function delCategory(id) {
return request({
url: '/game/category/' + id,
method: 'delete'
})
}
/**
* 类型管理列表开关
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/230951868e0
* @param {*} data
* @returns
*/
export function updateCategorySwitch(data) {
return request({
url: '/game/category/switch',
method: 'put',
data: data
})
}
/* ------------------------------- 类型管理end ------------------------------- */
/* ------------------------------- 游戏全网排名start ------------------------------- */
/**
* 游戏全网排名列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/227024433e0
* @param {*} query
* @returns
*/
export function listRanking(query) {
return request({
url: '/game/details/ranking/list',
method: 'get',
params: query
})
}
/* ------------------------------- 游戏全网排名end ------------------------------- */

View File

@ -0,0 +1,24 @@
import request from '@/utils/request'
/* ------------------------------- 游戏杀率管理start ------------------------------- */
// 查询原生游戏杀率列表
export function listKill(query) {
return request({
url: '/game/rate/list',
method: 'get',
params: query
})
}
// 修改原生游戏杀率
export function updateKill(data) {
return request({
url: '/game/rate',
method: 'put',
data: data
})
}
/* ------------------------------- 游戏杀率管理end ------------------------------- */

View File

@ -0,0 +1,175 @@
import request from '@/utils/request'
// 查询平台管理列表
export function listPlatform(query) {
return request({
url: '/game/platform/list',
method: 'get',
params: query
})
}
// 获取游戏配置详细信息
export function gameConfig(query) {
return request({
url: '/game/config',
method: 'get',
params: query
})
}
// 新增游戏配置
export function postGameConfig(data) {
return request({
url: '/game/config',
method: 'post',
data: data
})
}
// 获取游戏周转配置详细信息
export function gameTurnoverConfig(query) {
return request({
url: '/game/turnover/config',
method: 'get',
params: query
})
}
// 新增游戏周转配置
export function postGameTurnoverConfig(data) {
return request({
url: '/game/turnover/config',
method: 'post',
data: data
})
}
// 查询平台管理详细
export function getPlatform(id) {
return request({
url: '/game/platform/' + id,
method: 'get'
})
}
// 新增平台管理
export function addPlatform(data) {
return request({
url: '/game/platform',
method: 'post',
data: data
})
}
// 修改平台管理
export function updatePlatform(data) {
return request({
url: '/game/platform',
method: 'put',
data: data
})
}
// 删除平台管理
export function delPlatform(id) {
return request({
url: '/game/platform/' + id,
method: 'delete'
})
}
// 平台图片同步
export function gamePlatformSync({id}) {
return request({
url: `/game/platform/sync/${id}`,
method: 'get'
})
}
/**
* 置顶和列表交换
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226604932e0
* @param {*} id
* @param {*} sortNo
* @returns
*/
export function platformSort({id, sortNo}) {
return request({
url: `/game/platform/sort/top/${id}/${sortNo}`,
method: 'get'
})
}
/**
* 获取进入游戏限制初始值
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226590282e0
* @returns
*/
export function getGameConfig() {
return request({
url: '/game/platform/configKey/batch',
headers: {
repeatSubmit: false
},
method: 'post'
})
}
/**
* 修改进入游戏限制
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/227838119e0
* @param {*} data
* @returns
*/
export function updateGameConfig(data) {
return request({
url: '/game/platform/configKey/batch',
method: 'put',
data: data
})
}
/**
* 游戏下拉列表
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226738498e0
* @param {*} query
* @returns
*/
export function platformSelect(query) {
return request({
url: '/game/platform/select',
method: 'get',
params: query
})
}
/**
* 列表开关
* https://apifox.com/apidoc/shared-e7cce3ff-8932-4a55-9381-e9d3d1649289/226750300e0
* @param {*} data
* @returns
*/
export function updatePlatformSwitch(data) {
return request({
url: '/game/platform/switch',
method: 'put',
data: data
})
}
//同步api游戏
export function getGamePlatformApiSync(query) {
return request({
url: '/game/platform/api/sync',
method: 'get',
params: query
})
}
//同步游戏到租户
export function getGamePlatformTenantSync(query) {
return request({
url: '/game/platform/tenant/sync',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询虚拟彩金池列表
export function listPool(query) {
return request({
url: '/game/pool/list',
method: 'get',
params: query
})
}
// 查询虚拟彩金池详细
export function getPool(id) {
return request({
url: '/game/pool/' + id,
method: 'get'
})
}
// 新增虚拟彩金池
export function addPool(data) {
return request({
url: '/game/pool',
method: 'post',
data: data
})
}
// 修改虚拟彩金池
export function updatePool(data) {
return request({
url: '/game/pool',
method: 'put',
data: data
})
}
// 删除虚拟彩金池
export function delPool(id) {
return request({
url: '/game/pool/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 游戏统计列表
export function listStatistics(query) {
return request({
url: '/game/details/statistics/list',
method: 'get',
params: query
})
}

View File

@ -128,14 +128,7 @@ export function postSiteQuotaChange(data) {
})
}
//绑定api租户
export function postSiteBindApiGame(data) {
return request({
url: '/site/bind/api/game',
method: 'post',
data: data
})
}
//登录方法
export function tenantLogin(data) {
return request({
@ -143,4 +136,38 @@ export function tenantLogin(data) {
method: 'post',
data: data
})
}
}
//更新api租户
export function postSiteUpdateApiGame(data) {
return request({
url: '/site/update/api/game',
method: 'post',
data: data
})
}
//新增api租户
export function postSiteBindApiGame(data) {
return request({
url: '/site/bind/api/game',
method: 'post',
data: data
})
}
//查询绑定api租户信息
export function getSiteBindApiGameInfo(query) {
return request({
url: '/site/bind/api/game/info',
method: 'get',
params: query
})
}
//删除api游戏信息
export function postSiteDeleteApiGame(data) {
return request({
url: '/site/delete/api/game/info',
method: 'post',
data: data
})
}

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735116008146" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2379" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M508.025406 655.446718c-14.45307 0-28.183486-5.781228-39.023289-15.898376l-231.249118-231.249118c-10.117149-10.117149-10.117149-26.015526 0-36.132675s26.015526-10.117149 36.132675 0l231.249118 231.249118c2.16796 2.16796 4.335921 2.16796 5.781228 0l231.971771-231.971771c10.117149-10.117149 26.015526-10.117149 35.410021 0 10.117149 10.117149 10.117149 26.015526 0 36.132674l-231.971771 231.971772c-9.394495 10.117149-23.124912 15.898377-38.300635 15.898376z" fill="#0090FF" p-id="2380"></path></svg>

After

Width:  |  Height:  |  Size: 832 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735116860559" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8265" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M832.522014 669.951405c0-8.782014-3.235694-17.565051-9.708106-24.26873L535.638373 348.198354c-12.932544-13.408381-33.9226-13.408381-46.855144 0l-287.172465 297.485345c-12.9438 13.408381-12.9438 35.130102 0 48.53746 12.932544 13.408381 33.9226 13.408381 46.855144 0l263.744893-273.215592 263.747963 273.215592c12.932544 13.408381 33.9226 13.408381 46.855144 0C829.28632 687.516456 832.522014 678.734442 832.522014 669.951405z" fill="#1296db" p-id="8266"></path></svg>

After

Width:  |  Height:  |  Size: 799 B

View File

@ -0,0 +1,224 @@
<template >
<!-- 背景图颜色 -->
<div class="borderOverflow" :style="isExpand?'height: 200px;':'height: 162px;'">
<el-tabs
v-model="activeName"
type="card"
class="demo-tabs"
>
<el-tab-pane v-for="item in list" :key="item.id" :name="item.label">
<template #label>
<el-badge :is-dot="activeName == item.label" class="item"><span style="padding: 0 10px;">{{ item.label }}</span></el-badge>
</template>
<div class="tab-content">
<div :class="disabled==true?'disable-click contents':'contents'">
<div v-for="(items, index) in item.gameMaterialDatas" :key="index" @click="clickSelect(items,'not')" :class="selectType ==items.url?'colorcon select':'colorcon Uncheck' ">
<!-- <div class="colorback" :style="{ background: `#${items.mainColor}` }" ></div> -->
<img class="colorback" :src="fileHost+items.url" alt="" >
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane :label="t('自定义')" name="自定义">
<div :class="disabled==true? 'disable-click tab-content':'tab-content'">
<div class="contents contentsIcon" style="display: flex;">
<upload-icon @updateIcon="updateIcons" :typeUpImg="101" :limit="1" :fileType="['jpg', 'png', 'jpeg']"
:fileSize="1"></upload-icon>
<div style="width: 290px;text-wrap: wrap;margin-left: 5px;">
<span style="color: red;">*</span>{{ t('只能上传png,jpeg,jpg,gif格式图片且不超过1mb图片尺寸710px*320px') }}</div>
<div class="buttonClass" style="cursor: pointer;" @click="delectClick">{{ t('') }}</div>
</div>
<div class="contents" style="margin-top: 10px;">
<div v-for="item2 in listFale" @click="clickSelect(item2,'its')" :class="selectType ==item2.url?'contentsBorder select':'contentsBorder Uncheck' ">
<img :src="fileHost+item2.url" style="width: 100%;" alt="" >
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div class="imgArrow" @click="clickAwor">
<img v-if="!isExpand" src="@/assets/icons/svg/arrow1.svg" style="width: 25;height: 23px;"/>
<img v-else src="@/assets/icons/svg/arrow2.svg" style="width: 25;height: 23px;"/>
<span v-if="!isExpand"></span>
<span v-else></span>
</div>
</template>
<script setup>
import { getSelectData } from '@/api/common.js';
import UploadIcon from "@/components/UploadIcon"; // BannerBannerImg
import { getLocalStorage } from "@/utils/auth";
const { proxy } = getCurrentInstance();
const props = defineProps({
url: {
type: String,
default: ''
},
query: {
type: Object
},
method: {
type: String,
default: 'get'
},
backgroundColor:{ //
type: String,
default: ''
},
disabled:{ //
type: Boolean,
default: false
}
});
const emits = defineEmits(['clickSelect']) //
const fileHost = getLocalStorage('fileUrl') || ''; // host
const list = ref([]); //
const activeName = ref(''); //
const listFale = ref([]); //
const delectItem = ref({});
const selectType = ref(''); //
//isExpand
const isExpand = ref(false); //
//
const delectClick = () =>{
if (!delectItem.value || Object.keys(delectItem.value).length === 0){
proxy.$modal.msgError(proxy.t('请选择需要删除的内容'));
return
}
const index = listFale.value.findIndex(item => item.url === delectItem.value);
if (index !== -1) {
listFale.value.splice(index, 1)
emits('clickSelect', '');
}
}
//
const getList = async () => {
const { query, method, url } = props
try {
const parmas = { pageNumber: 1, pageSize: 1000, ...query }
await getSelectData(url, parmas, method).then(res => {
//
res.data.map((item,index) => {
list.value.push(item);
if (index == 0){
activeName.value = item.label
}
item.gameMaterialDatas.map((items,indexs)=>{
if (props.backgroundColor){
selectType.value = props.backgroundColor
}else{
if (index == 0 && indexs == 0){
selectType.value = items.url;
emits('clickSelect', items);
}
}
})
})
res.data.map(item => {
item.gameMaterialDatas.map(item2 => {
if (item2.url == props.backgroundColor){
activeName.value = item.label;
}
})
})
})
} catch (e) {
}
}
getList();
const updateIcons = (file) => {
listFale.value=file;
}
//
const clickAwor = () => {
isExpand.value = !isExpand.value;
}
//
const clickSelect = (item,type) => {
delectItem.value = item.url;
selectType.value = item.url
item.type = type;
emits('clickSelect', item);
}
</script>
<style lang="scss" scoped>
.banner-color{
width: 400px;
display: flex;
flex-wrap: wrap;
overflow: hidden;
}
.tab-content{
// width: 462px;
height: 180px;
overflow-y: auto;
}
.contents{
display: flex;
flex-wrap: wrap;
.contentsBorder{
width: 70px;
height: 70px;
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
.Uncheck{
border: 1px solid #d1d5db;
}
.select{
border: 1px solid #409EFF;
}
}
.colorcon{
width: 60px;
height: 30px;
border-radius: 2px;
padding: 1px;
margin-left: 4px;
margin-top: 4px;
cursor: pointer;
.colorback{
width: 56px;
height: 26px;
}
}
.imgArrow{
display: flex;
align-items: center;
// width: 500px;
justify-content: right;
padding-right: 0px;
color: #409EFF;
cursor: pointer;
}
.buttonClass{
width: 70px;
text-align: center;
height: 40px;
line-height: 40px;
border: 1px solid #409EFF;
color: #fff;
background: #409EFF;
border-radius: 5px;
}
.Uncheck{
border: 1px solid #d1d5db;
}
.select{
border: 1px solid #409EFF;
}
.borderOverflow{
border: 1px solid #d1d5db;
overflow: hidden;
}
.disable-click {
pointer-events: none;
}
</style>

View File

@ -0,0 +1,242 @@
<template >
<!-- 图标选择 -->
<div class="tab-container borderOverflow" >
<!-- el-tabs 组件的容器 -->
<div class="tab-scroll-content" ref="tabScrollContent">
<el-tabs
v-model="activeName"
type="card"
class="demo-tabs"
@tab-click="handleClick"
>
<el-tab-pane v-for="item in list" :key="item.id" :name="item.label">
<template #label>
<el-badge :is-dot="activeName == item.label" class="item"><span style="padding: 0 10px;">{{ item.label }}</span></el-badge>
</template>
<div class="tab-content" :style="isExpand?'height: 500px;':'height: 180px;'">
<div :class="disabled==true?'disable-click contents':'contents'">
<div v-for="items in item.gameMaterialDatas" :key="items.label" @click="clickSelect(items,'not')" :class="selectType ==items.url?'contentsBorder select':'contentsBorder Uncheck' ">
<img :src="fileHost+items.url" style="width: 100%;" alt="" >
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane :label="t('自定义')" name="自定义">
<div :class="disabled==true? 'disable-click tab-content':'tab-content'" :style="isExpand?'height: 500px;':'height: 180px;'">
<div class="contents contentsIcon" style="display: flex;">
<upload-icon @updateIcon="updateIcons" :typeUpImg="101" :limit="1" :fileType="['jpg', 'png', 'jpeg']"
:fileSize="1"></upload-icon>
<div style="width: 290px;text-wrap: wrap;margin-left: 5px;">
<span style="color: red;">*</span>{{ t('只能上传文件且不超过1MB图片尺寸为343px*300px') }}</div>
<div class="buttonClass" style="cursor: pointer;" @click="delectClick">{{ t('') }}</div>
</div>
<div class="contents" style="margin-top: 10px;">
<div v-for="item2 in listFale" @click="clickSelect(item2,'its')" :class="selectType ==item2.url?'contentsBorder select':'contentsBorder Uncheck' ">
<img :src="fileHost+item2.url" style="width: 100%;" alt="" >
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
<div class="imgArrow" @click="clickAwor">
<img v-if="!isExpand" src="@/assets/icons/svg/arrow1.svg" style="width: 25;height: 23px;"/>
<img v-else src="@/assets/icons/svg/arrow2.svg" style="width: 25;height: 23px;"/>
<span v-if="!isExpand"></span>
<span v-else></span>
</div>
</template>
<script setup>
import { getSelectData } from '@/api/common.js';
import { getLocalStorage } from "@/utils/auth";
import UploadIcon from "@/components/UploadIcon"; // BannerBannerImg
const props = defineProps({
url: {
type: String,
default: ''
},
query: {
type: Object
},
method: {
type: String,
default: 'get'
},
imageUrl: {
type: String, //Banner
default: ''
},
disabled:{ //
type: Boolean,
default: false
}
});
const emits = defineEmits(['clickSelect']) //
const fileHost = getLocalStorage('fileUrl') || ''; // host
const tabScrollContent = ref(null); // tab-scroll-content
const list = ref([]); //
const delectItem = ref({});
const listFale = ref([]); //
const activeName = ref(''); //
const selectType = ref(''); //
const isExpand = ref(false); //
//
const clickSelect = (item,type) => {
selectType.value = item.url
item.type = type;
delectItem.value = item.url;
emits('clickSelect', item);
}
const delectClick = () =>{
if (!delectItem.value || Object.keys(delectItem.value).length === 0){
proxy.$modal.msgError(proxy.t('请选择需要删除的内容'));
return
}
const index = listFale.value.findIndex(item => item.url === delectItem.value);
if (index !== -1) {
listFale.value.splice(index, 1)
emits('clickSelect', '');
}
}
const clickAwor = () => {
isExpand.value = !isExpand.value;
}
//
const getList = async () => {
const { query, method, url } = props
try {
const parmas = { pageNumber: 1, pageSize: 1000, ...query }
await getSelectData(url, parmas, method).then(res => {
//
res.data.map((item,index) => {
if (index == 0){
activeName.value = item.label
}
if (props.imageUrl){
selectType.value = props.imageUrl
}else{
if (index == 0){
selectType.value = item.gameMaterialDatas[0].url
emits('clickSelect', item.gameMaterialDatas[0]);
}
}
list.value.push(item);
})
res.data.map(item => {
item.gameMaterialDatas.map(item2 => {
if (item2.url == props.imageUrl){
activeName.value = item.label;
}
})
})
})
} catch (e) {
}
}
getList();
const handleClick = (tab, event) => {
}
const updateIcons = (file) => {
listFale.value=file;
}
</script>
<style lang="scss" scoped>
.tab-container {
position: relative;
// width: 462px;
// height: 300px;
overflow: hidden;
display: flex;
align-items: center;
}
.tab-scroll-content {
overflow-x: auto;
white-space: nowrap;
flex-grow: 1;
}
.scroll-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
z-index: 1;
user-select: none; /* 禁止用户选择文本 */
}
.left-btn {
left: 10px; /* 根据需要调整位置 */
}
.right-btn {
right: 10px; /* 根据需要调整位置 */
}
/* 可选为el-tab-pane设置内联块样式以确保它们在同一行显示 */
.el-tab-pane {
display: inline-block;
}
.tab-content{
// width: 462px;
height: 500px;
overflow-y: auto;
.contents{
// width: 455px;
display: flex;
flex-wrap: wrap;
.contentsBorder{
width: 70px;
height: 70px;
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
.Uncheck{
border: 1px solid #d1d5db;
}
.select{
border: 1px solid #409EFF;
}
}
}
.buttonClass{
width: 70px;
text-align: center;
height: 40px;
line-height: 40px;
border: 1px solid #409EFF;
color: #fff;
background: #409EFF;
border-radius: 5px;
}
.imgArrow{
display: flex;
align-items: center;
// width: 500px;
justify-content: right;
padding-right: 0px;
color: #409EFF;
cursor: pointer;
}
.borderOverflow{
border: 1px solid #d1d5db;
overflow: hidden;
}
.disable-click {
pointer-events: none;
}
</style>
<style>
.contentsIcon .el-upload--picture-card {
width: 70px !important; /* 设置上传后图片卡片的宽度 */
height: 70px !important; /* 设置上传后图片卡片的高度 */
}
</style>

View File

@ -29,7 +29,7 @@ const selectedValue = defineModel();
const currencyList = ref([]);
const isFinish = ref(false); //
const isError = ref(false); //
const localList = getLocalStorage('currencyList')?.filter(v => v.status == 0) || []; //
const localList = getLocalStorage('currencySelect')?.filter(v => v.status == 0) || []; //
if (localList.length) {
currencyList.value = localList;

View File

@ -0,0 +1,298 @@
<template>
<!-- 新增和修改时 -->
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange"
v-if="psType !== 'detail'">
{{ t('全部平台') }}
</el-checkbox>
<!-- 新增和修改时 -->
<el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange" v-if="psType !== 'detail'">
<el-collapse accordion>
<!-- 游戏平台 -->
<el-collapse-item v-for="item in platformList" :key="item.gamePlatformId" :name="item.gamePlatformId">
<template #title>
<el-checkbox :label="t(item.gamePlatformName+item.currencyCode)" :value="item.gamePlatformId"
@click.stop="stopFn"></el-checkbox>
</template>
<template #icon="{ isActive }">
<span class="check-text">{{ item.checkGameList.length ? t('已勾选{}个游戏', item.checkGameList.length) : ''
}}</span>
<span :class="'icon-ele ' + (isActive ? 'icon-active' : '')">
<el-icon>
<ArrowRight />
</el-icon>
</span>
</template>
<!-- 游戏列表 -->
<div class="search-box">
<el-input v-model="item.searchName" @input="searchGame(item)" style="width: 300px"
:placeholder="t('游戏搜索')" clearable />
<span class="total">{{ t('共{}款游戏', item.searchLengt) }}</span>
<el-button type="primary" @click="clearCheckGame(item)" v-if="item.checkGameList.length" link
style="margin-left: 30px;">{{ t('清空勾选') }}</el-button>
</div>
<div class="game-list">
<el-checkbox-group v-model="item.checkGameList" @change="checkGameChange(item)">
<template v-for="game in item.gameList" :key="game.id">
<el-checkbox v-if="game.gameName.indexOf(item.searchName) !== -1" :label="t(game.gameName)"
:value="game.id"></el-checkbox>
</template>
</el-checkbox-group>
<span class="no-game" v-if="item.searchLengt === 0">{{ t('') }}</span>
</div>
</el-collapse-item>
</el-collapse>
</el-checkbox-group>
<!-- 详情展示时 -->
<ul class="detail-item" v-else>
<template v-for="item in platformList" :key="item.gamePlatformId">
<li v-if="checkedCities.indexOf(item.gamePlatformId) !== -1">
<span class="p-name">{{ item.gamePlatformName }}</span>
<div class="tag-span" >
<template v-for="game in item.gameList" :key="game.id">
<el-tag type="primary" v-if="item.checkGameList.indexOf(game.id) !== -1">{{ game.gameName }}</el-tag>
</template>
</div>
</li>
</template>
</ul>
</template>
<script setup>
import { getGameTypesGame } from "@/api/discounts/realtimeRebate";
const props = defineProps({
gameTypeId: { // ID
type: [String, Number],
default: ''
},
selectedPlatforms: { //
type: Object,
default: {}
},
platforms: { //
type: Array,
default: []
},
psType: {
type: String,
default: ''
}
});
const platformList = ref(props.platforms); //
const emit = defineEmits(['selectPlatform']);
const checkAll = ref(false), isIndeterminate = ref(false), checkedCities = ref([]); //
const optionsIds = platformList.value.map(i => i.gamePlatformId); // id
//
platformList.value.forEach(item => {
item.checkGameList = []; //
item.searchName = ''; //
item.searchLengt = item.gameList.length; // ;
});
//
const stopFn = (e) => { }
//
const searchGame = (item) => {
item.searchName = item.searchName.replace(/ {2,}/g, ' ');
item.searchLengt = item.gameList.filter(i => i.gameName.indexOf(item.searchName) !== -1).length;
}
//
const checkGameChange = (val) => {
//
if (checkedCities.value.indexOf(val.gamePlatformId) === -1) {
checkedCities.value.push(val.gamePlatformId);
} else {
if (val.checkGameList.length === 0) {
checkedCities.value.splice(checkedCities.value.indexOf(val.gamePlatformId), 1);
}
}
//
handleCheckedCitiesChange(checkedCities.value, 'checkGame');
}
//
const clearCheckGame = (item) => {
item.checkGameList = [];
item.searchName = '';
item.searchLengt = item.gameList.length;
//
if (checkedCities.value.indexOf(item.gamePlatformId) !== -1) {
checkedCities.value.splice(checkedCities.value.indexOf(item.gamePlatformId), 1);
//
handleCheckedCitiesChange(checkedCities.value);
}
}
//
if (props.selectedPlatforms) {
props.selectedPlatforms.forEach(thisData => {
if (thisData.gameTypeId === props.gameTypeId) {
//
const _checkedCities = [];
thisData.gamePlatforms.forEach(item => {
_checkedCities.push(item.platformId); //
if (item.gameIds?.length) { //
if (platformList.value.find(v => v.gamePlatformId === item.platformId) != undefined){
platformList.value.find(v => v.gamePlatformId === item.platformId).checkGameList = item.gameIds;
}
}
});
checkedCities.value = _checkedCities;
//
if (_checkedCities.length === 0) {
isIndeterminate.value = false;
} else {
if (_checkedCities.length === optionsIds.length) {
checkAll.value = true;
isIndeterminate.value = false;
} else {
checkAll.value = false;
isIndeterminate.value = true;
}
}
}
});
}
//
const handleCheckAllChange = (val) => {
isIndeterminate.value = false; //
if (val) {
checkedCities.value = optionsIds;
//
platformList.value.forEach(item => {
item.checkGameList = item.gameList.map(i => i.id);
});
} else {
checkedCities.value = [];
//
platformList.value.forEach(item => {
item.checkGameList = [];
});
}
const params = getParams(); //
emit('selectPlatform', params, props.gameTypeId);
}
//
const handleCheckedCitiesChange = (val, type) => {
const checkedCount = val.length;
checkAll.value = checkedCount === optionsIds.length; //
isIndeterminate.value = checkedCount > 0 && checkedCount < optionsIds.length; //
//
if (type !== 'checkGame') {
platformList.value.forEach(item => {
if (checkedCities.value.indexOf(item.gamePlatformId) !== -1) {
item.checkGameList = item.gameList.map(i => i.id);
} else {
item.checkGameList = [];
}
});
}
const params = getParams(); //
emit('selectPlatform', params, props.gameTypeId);
}
//
const getParams = () => {
const _list = [];
//
platformList.value.forEach(item => {
if (checkedCities.value.indexOf(item.gamePlatformId) !== -1) {
_list.push({
platformId: item.gamePlatformId,
gameIds: item.checkGameList
});
}
});
return _list;
}
</script>
<style scoped lang="scss">
.detail-item {
padding: 0;
margin: 0;
li {
width: 100%;
padding: 0 0 15px 0;
margin: 0;
line-height: 1;
.p-name {
display: inline-block;
color: #606266;
line-height: 1;
padding-bottom: 8px;
}
.tag-span {
:deep(.el-tag){
margin: 0 5px 5px 0;
}
}
&:last-child {
padding-bottom: 0;
}
}
}
//
.icon-active {
transform: rotate(90deg);
}
.icon-ele {
margin-right: 8px;
transition: all ease-in-out .3s;
i {
transform: translateY(2px);
color: #606266;
}
}
.check-text {
color: #606266;
margin: 0 5px 0 auto !important;
}
.search-box {
padding-bottom: 10px;
.total {
padding-left: 10px;
color: #606266;
}
}
.game-list {
background-color: rgb(0, 0, 0, .02);
padding: 10px;
.no-game {
width: 100%;
text-align: center;
display: inline-block;
color: #606266;
}
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<!-- 游戏平台展示 -->
<el-tabs v-model="gameActiveName" type="border-card">
<el-tab-pane v-for="item in gameTypes" :disabled="disabled" :key="item.gameTypeId" :name="item.gameTypeId">
<template #label>
<span>
{{ t(item.gameTypeName) }}<b>{{ platformCount[item.gameTypeId] ? '(' + platformCount[item.gameTypeId]
+ ')' : '' }}</b>
</span>
</template>
<!-- 游戏下的平台选项 -->
<platforms v-if="gameActiveName === item.gameTypeId" @selectPlatform="selectPlatform"
:gameTypeId="item.gameTypeId" :selectedPlatforms="selectedPlatforms" :key="item.gameTypeId"
:platforms="item.platforms" :psType="psType">
</platforms>
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import { getGameTypes } from "@/api/discounts/realtimeRebate";
import Platforms from "./Platforms.vue";
const props = defineProps({
auditPlatform: { //
type: String,
default: ''
},
disabled: { //
type: Boolean,
default: false
},
psType: {
type: String,
default: ''
},
currencyTypes: { //
type: Object,
default: {}
},
gameOpen: {
type: Array,
default: () => []
},
typeVerify: { //
type: Boolean,
default: false
},
});
//
const gameTypes = ref([]), gameActiveName = ref('');
if (props.typeVerify == false){
getGameTypes(props.currencyTypes).then(res => {
gameTypes.value = res.data;
gameActiveName.value = res.data[0].gameTypeId;
});
}else{
gameTypes.value = props.gameOpen
gameActiveName.value = props.gameOpen[0]?.gameTypeId;
}
//
const emit = defineEmits(['selectPlatform']);
const platformCount = ref({}), selectedPlatforms = ref([]); //
const selectPlatform = (gamePlatforms, gameTypeId) => {
const _findIndex = selectedPlatforms.value.findIndex(i => i.gameTypeId === gameTypeId);
//
if (_findIndex !== -1) {
//
if (gamePlatforms.length) {
selectedPlatforms.value[_findIndex].gamePlatforms = gamePlatforms; //
} else {
selectedPlatforms.value.splice(_findIndex, 1); //
}
} else {
//
if (gamePlatforms.length) {
selectedPlatforms.value.push({
gameTypeId: gameTypeId,
gamePlatforms: gamePlatforms
});
}
}
platformCount.value[gameTypeId] = gamePlatforms.length; //
emit('selectPlatform', selectedPlatforms.value.length ? JSON.stringify(selectedPlatforms.value) : '');
}
//
if (props.auditPlatform) {
selectedPlatforms.value = JSON.parse(props.auditPlatform); //
//
selectedPlatforms.value.forEach(gameItem => {
platformCount.value[gameItem.gameTypeId] = gameItem.gamePlatforms.length;
});
}
</script>

View File

@ -0,0 +1,298 @@
<template>
<!-- 新增和修改时 -->
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange"
v-if="psType !== 'detail'">
{{ t('全部平台') }}
</el-checkbox>
<!-- 新增和修改时 -->
<el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange" v-if="psType !== 'detail'">
<el-collapse accordion>
<!-- 游戏平台 -->
<el-collapse-item v-for="item in platformList" :key="item.platformCode" :name="item.platformCode">
<template #title>
<el-checkbox :label="t(item.platformName)" :value="item.platformCode"
@click.stop="stopFn"></el-checkbox>
</template>
<template #icon="{ isActive }">
<span class="check-text">{{ item.checkGameList.length ? t('已勾选{}个游戏', item.checkGameList.length) : ''
}}</span>
<span :class="'icon-ele ' + (isActive ? 'icon-active' : '')">
<el-icon>
<ArrowRight />
</el-icon>
</span>
</template>
<!-- 游戏列表 -->
<div class="search-box">
<el-input v-model="item.searchName" @input="searchGame(item)" style="width: 300px"
:placeholder="t('游戏搜索')" clearable />
<span class="total">{{ t('共{}款游戏', item.searchLengt) }}</span>
<el-button type="primary" @click="clearCheckGame(item)" v-if="item.checkGameList.length" link
style="margin-left: 30px;">{{ t('清空勾选') }}</el-button>
</div>
<div class="game-list">
<el-checkbox-group v-model="item.checkGameList" @change="checkGameChange(item)">
<template v-for="game in item.games" :key="game.gameCode">
<el-checkbox v-if="game.gameName.indexOf(item.searchName) !== -1" :label="t(game.gameName)"
:value="game.gameCode"></el-checkbox>
</template>
</el-checkbox-group>
<span class="no-game" v-if="item.searchLengt === 0">{{ t('') }}</span>
</div>
</el-collapse-item>
</el-collapse>
</el-checkbox-group>
<!-- 详情展示时 -->
<ul class="detail-item" v-else>
<template v-for="item in platformList" :key="item.platformCode">
<li v-if="checkedCities.indexOf(item.platformCode) !== -1">
<span class="p-name">{{ item.platformName }}</span>
<div class="tag-span" >
<template v-for="game in item.games" :key="game.gameCode">
<el-tag type="primary" v-if="item.checkGameList.indexOf(game.gameCode) !== -1">{{ game.gameName }}</el-tag>
</template>
</div>
</li>
</template>
</ul>
</template>
<script setup>
const props = defineProps({
gameTypeId: { // ID
type: [String, Number],
default: ''
},
selectedPlatforms: { //
type: Object,
default: {}
},
platforms: { //
type: Array,
default: []
},
psType: {
type: String,
default: ''
}
});
const platformList = ref(props.platforms); //
const emit = defineEmits(['selectPlatform']);
const checkAll = ref(false), isIndeterminate = ref(false), checkedCities = ref([]); //
const optionsIds = platformList.value.map(i => i.platformCode); // id
//
platformList.value.forEach(item => {
item.checkGameList = []; //
item.searchName = ''; //
item.searchLengt = item.games.length; // ;
});
//
const stopFn = (e) => { }
//
const searchGame = (item) => {
item.searchName = item.searchName.replace(/ {2,}/g, ' ');
item.searchLengt = item.games.filter(i => i.gameName.indexOf(item.searchName) !== -1).length;
}
//
const checkGameChange = (val) => {
//
if (checkedCities.value.indexOf(val.platformCode) === -1) {
checkedCities.value.push(val.platformCode);
} else {
if (val.checkGameList.length === 0) {
checkedCities.value.splice(checkedCities.value.indexOf(val.platformCode), 1);
}
}
//
handleCheckedCitiesChange(checkedCities.value, 'checkGame');
}
//
const clearCheckGame = (item) => {
item.checkGameList = [];
item.searchName = '';
item.searchLengt = item.games.length;
//
if (checkedCities.value.indexOf(item.platformCode) !== -1) {
checkedCities.value.splice(checkedCities.value.indexOf(item.platformCode), 1);
//
handleCheckedCitiesChange(checkedCities.value);
}
}
//
if (props.selectedPlatforms) {
props.selectedPlatforms.forEach(thisData => {
if (thisData.platformType === props.gameTypeId) {
//
const _checkedCities = [];
thisData.gameResultTreeDTOS.forEach(item => {
_checkedCities.push(item.platformCode); //
if (item.gameCodes?.length) { //
if (platformList.value.find(v => v.platformCode === item.platformCode) != undefined){
platformList.value.find(v => v.platformCode === item.platformCode).checkGameList = item.gameCodes;
}
}
});
checkedCities.value = _checkedCities;
//
if (_checkedCities.length === 0) {
isIndeterminate.value = false;
} else {
if (_checkedCities.length === optionsIds.length) {
checkAll.value = true;
isIndeterminate.value = false;
} else {
checkAll.value = false;
isIndeterminate.value = true;
}
}
}
});
}
//
const handleCheckAllChange = (val) => {
isIndeterminate.value = false; //
if (val) {
checkedCities.value = optionsIds;
//
platformList.value.forEach(item => {
item.checkGameList = item.gameCodes.map(i => i.id);
});
} else {
checkedCities.value = [];
//
platformList.value.forEach(item => {
item.checkGameList = [];
});
}
const params = getParams(); //
emit('selectPlatform', params, props.gameTypeId);
}
//
const handleCheckedCitiesChange = (val, type) => {
const checkedCount = val.length;
checkAll.value = checkedCount === optionsIds.length; //
isIndeterminate.value = checkedCount > 0 && checkedCount < optionsIds.length; //
//
if (type !== 'checkGame') {
platformList.value.forEach(item => {
if (checkedCities.value.indexOf(item.platformCode) !== -1) {
item.checkGameList = item.games.map(i => i.gameCode);
} else {
item.checkGameList = [];
}
});
}
const params = getParams(); //
emit('selectPlatform', params, props.gameTypeId);
}
//
const getParams = () => {
const _list = [];
//
platformList.value.forEach(item => {
if (checkedCities.value.indexOf(item.platformCode) !== -1) {
_list.push({
platformCode: item.platformCode,
gameCodes: item.checkGameList
});
}
});
return _list;
}
</script>
<style scoped lang="scss">
.detail-item {
padding: 0;
margin: 0;
li {
width: 100%;
padding: 0 0 15px 0;
margin: 0;
line-height: 1;
.p-name {
display: inline-block;
color: #606266;
line-height: 1;
padding-bottom: 8px;
}
.tag-span {
:deep(.el-tag){
margin: 0 5px 5px 0;
}
}
&:last-child {
padding-bottom: 0;
}
}
}
//
.icon-active {
transform: rotate(90deg);
}
.icon-ele {
margin-right: 8px;
transition: all ease-in-out .3s;
i {
transform: translateY(2px);
color: #606266;
}
}
.check-text {
color: #606266;
margin: 0 5px 0 auto !important;
}
.search-box {
padding-bottom: 10px;
.total {
padding-left: 10px;
color: #606266;
}
}
.game-list {
background-color: rgb(0, 0, 0, .02);
padding: 10px;
.no-game {
width: 100%;
text-align: center;
display: inline-block;
color: #606266;
}
}
</style>

View File

@ -0,0 +1,104 @@
<template>
<!-- 游戏平台展示 -->
<el-tabs v-model="gameActiveName" type="border-card" @tab-click="selectPlatformTab">
<el-tab-pane v-for="item in ff_game_type" :disabled="disabled" :key="item.value" :name="item.value" >
<template #label>
<span>
{{ t(item.label) }}<b>{{ platformCount[item.value] ? '(' + platformCount[item.value]
+ ')' : '' }}</b>
</span>
</template>
<!-- 游戏下的平台选项 -->
<platforms v-if="gameActiveName === item.value && lodingShow" @selectPlatform="selectPlatform"
:gameTypeId="item.value" :selectedPlatforms="selectedPlatforms" :key="item.value"
:platforms="gameTypes" :psType="psType">
</platforms>
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import { getGameTypes,getPlatformTree } from "@/api/discounts/realtimeRebate";
import Platforms from "./Platforms.vue";
const props = defineProps({
auditPlatform: { //
type: String,
default: ''
},
disabled: { //
type: Boolean,
default: false
},
psType: {
type: String,
default: ''
},
currencyTypes: { //
type: Object,
default: {}
},
gameOpen: {
type: Array,
default: () => []
},
typeVerify: { //
type: Boolean,
default: false
},
});
const { proxy } = getCurrentInstance();
const { jump_type,ff_game_type } = proxy.useDict('jump_type','ff_game_type');
//
const gameTypes = ref([]), gameActiveName = ref(ff_game_type[0]?.value);
const lodingShow = ref(true);
const selectPlatformTab = (tab, event) => { //
let obj = {platformType:tab.paneName};
lodingShow.value = false;
getPlatformTree(obj).then(res => {
gameTypes.value = res.data;
lodingShow.value = true;
// gameActiveName.value = res.data[0].gameTypeId;
});
}
selectPlatformTab({paneName:ff_game_type[0]?.value}); //
//
const emit = defineEmits(['selectPlatform']);
const platformCount = ref({}), selectedPlatforms = ref([]); //
const selectPlatform = (gameResultTreeDTOS, platformType) => {
const _findIndex = selectedPlatforms.value.findIndex(i => i.platformType === platformType);
//
if (_findIndex !== -1) {
//
if (gameResultTreeDTOS.length) {
selectedPlatforms.value[_findIndex].gameResultTreeDTOS = gameResultTreeDTOS; //
} else {
selectedPlatforms.value.splice(_findIndex, 1); //
}
} else {
//
if (gameResultTreeDTOS.length) {
selectedPlatforms.value.push({
platformType: platformType,
gameResultTreeDTOS: gameResultTreeDTOS
});
}
}
platformCount.value[platformType] = gameResultTreeDTOS.length; //
emit('selectPlatform', selectedPlatforms.value.length ? JSON.stringify(selectedPlatforms.value) : '');
}
//
if (props.auditPlatform) {
selectedPlatforms.value = JSON.parse(props.auditPlatform); //
//
selectedPlatforms.value.forEach(gameItem => {
platformCount.value[gameItem.platformType] = gameItem.gameResultTreeDTOS.length;
});
}
</script>

View File

@ -124,7 +124,7 @@ const disabledDate = (time) => {
return time.getTime() >= Date.now();
}
function getTimeFnTop(date) {
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
return dayjs(date).format('YYYY-MM-DD HH:mm:ss.SSS');
}
//
const timeTypeChange = (val) => {
@ -143,7 +143,7 @@ const timeTypeChange = (val) => {
case 'week':
dateRange.value = [
dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss')
dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss.SSS')
]
break
case 'month':
@ -172,7 +172,7 @@ const dateRangeChange = (dataValue) => {
}
if (!isNaN(start)){
dateRange.value[0] = dayjs(start).format('YYYY-MM-DD HH:mm:ss ');
dateRange.value[1] = dayjs(end).format('YYYY-MM-DD HH:mm:ss');
dateRange.value[1] = dayjs(end).format('YYYY-MM-DD HH:mm:ss.SSS');
}
}
@ -184,7 +184,7 @@ const dateRangeChange = (dataValue) => {
//
const getTimeFn = (startTime) => {
return [startTime.format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss')];
return [startTime.format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss.SSS')];
}
//

View File

@ -0,0 +1,232 @@
<template>
<div class="component-upload-image">
<el-upload multiple :action="uploadImgUrl" list-type="picture-card" :on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload" :on-error="handleUploadError"
ref="imageUpload" :before-remove="handleDelete" :show-file-list="false" :headers="headers" :file-list="fileList"
:on-preview="handlePictureCardPreview">
<el-icon class="avatar-uploader-icon">
<plus />
</el-icon>
</el-upload>
</div>
</template>
<script setup>
import { getToken, getLocalStorage } from "@/utils/auth";
const props = defineProps({
modelValue: [String, Object, Array],
//
limit: {
type: Number,
default: 5,
},
// (MB)
fileSize: {
type: Number,
default: 5,
},
typeUpImg:{
type: [Number, String],
default: "1"
},
//
imgSize: {
type: Object,
default: () => ({
width: 0,
height: 0
})
},
// , ['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["png", "jpg", "jpeg"],
},
//
isShowTip: {
type: Boolean,
default: true
},
singleUpload: {
type: Boolean,
default: false,
},
});
const { proxy } = getCurrentInstance();
const emit = defineEmits();
const number = ref(0);// fileList
const uploadList = ref([]); //
const dialogImageUrl = ref(""); //
const dialogVisible = ref(false); //
const baseUrl = getLocalStorage('fileUrl'); //
const uploadUrl = getLocalStorage('uploadUrl'); //
const uploadImgUrl = ref(uploadUrl + `/file/upload/localSysFile/${props.typeUpImg}`); //
const headers = ref({ Authorization: "Bearer " + getToken() }); //
const fileList = ref([]); //
//
watch(() => props.modelValue, val => {
if (val) {
//
const list = Array.isArray(val) ? val : props.modelValue.split(",");
//
fileList.value = list.map(item => {
if (typeof item === "string") {
if (item.indexOf(baseUrl) === -1) {
item = { name: baseUrl + item, url: baseUrl + item };
} else {
item = { name: item, url: item };
}
}
return item;
});
} else {
fileList.value = [];
return [];
}
}, { deep: true, immediate: true });
// loading
function handleBeforeUpload(file) {
let isImg = false;
if (props.fileType.length) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
isImg = props.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
} else {
isImg = file.type.indexOf("image") > -1;
}
if (!isImg) {
proxy.$modal.msgError(
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
);
return false;
}
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
// proxy.$modal.loading("...");
// number.value++;
//
const checkSize = new Promise(function (resolve, reject) {
//
let width = props.imgSize.width;
//
let height = props.imgSize.height;
let _URL = window.URL || window.webkitURL;
let img = new Image();
img.onload = function () {
let valid = img.width == width && img.height == height;
//
valid || (width === 0 && height === 0) ? resolve() : reject();
}
img.src = _URL.createObjectURL(file);
}).then(() => {
proxy.$modal.loading("正在上传图片,请稍候...");
number.value++;
}, () => {
proxy.$modal.msgError(`上传图片尺寸必须为${props.imgSize.width}x${props.imgSize.height}px!`);
return Promise.reject();
});
return checkSize;
}
//
function handleUploadSuccess(res, file) {
if (res.code === 200) {
const uploadedItem = { name: res.fileName, url: res.url, id: res.fileName };
uploadList.value.push(uploadedItem);
// ""
if (props.singleUpload) {
fileList.value = [uploadedItem]; //
uploadList.value = [];
number.value = 0;
emit("updateIcon", uploadedItem); // 👈
proxy.$modal.closeLoading();
} else {
uploadedSuccessfully(); //
}
} else {
number.value--;
proxy.$modal.closeLoading();
proxy.$modal.msgError(res.msg);
proxy.$refs.imageUpload.handleRemove(file);
uploadedSuccessfully();
}
}
//
function handleDelete(file) {
const findex = fileList.value.map(f => f.name).indexOf(file.name);
if (findex > -1 && uploadList.value.length === number.value) {
fileList.value.splice(findex, 1);
emit("updateIcon", listToString(fileList.value));
return false;
}
}
//
function uploadedSuccessfully() {
if (number.value > 0 && uploadList.value.length === number.value) {
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
uploadList.value = [];
number.value = 0;
emit("updateIcon", fileList.value);
proxy.$modal.closeLoading();
}
}
//
function handleUploadError() {
proxy.$modal.msgError("上传图片失败");
proxy.$modal.closeLoading();
}
//
function handlePictureCardPreview(file) {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
}
//
function listToString(list, separator) {
let strs = "";
separator = separator || ",";
for (let i in list) {
if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {
strs += list[i].url.replace(baseUrl, "") + separator;
}
}
return strs != "" ? strs.substr(0, strs.length - 1) : "";
}
</script>
<style scoped lang="scss">
// .el-upload--picture-card
:deep(.hide .el-upload--picture-card) {
display: none;
}
</style>
<style>
.component-upload-image .el-upload--picture-card {
width: 70px !important; /* 设置上传后图片卡片的宽度 */
height: 70px !important; /* 设置上传后图片卡片的高度 */
}
</style>

View File

@ -1,6 +1,6 @@
import Cookies from 'js-cookie'
const TokenKey = 'Agent-Token'
const TokenKey = 'Super-Token'
export function getToken() {
return Cookies.get(TokenKey)

View File

@ -14,7 +14,7 @@
<div class="card-left">
<div class="card-title">{{ card.title }}<span class="percentage">{{ card.percentage }}</span></div>
<div class="card-value">
<span class="" :style="card.cardClass =='pink' ? '':card.cardClass =='green'?'':'cursor: pointer;border-bottom: 2px solid #fff;'" @click="goPage(card.cardClass)">{{ card.value }}</span>
<span class="" :style="card.cardClass =='pink' ? '':card.cardClass =='green'?'':'cursor: pointer;'" >{{ card.value }}</span>
</div>
<div class="card-subtitle" v-html="card.subtitle" @click="handleClick"></div>
</div>
@ -104,92 +104,92 @@
}
]);
const handleClick = (e) => {
const type = e.target.dataset.type
let path = '';
let typeDay = '';
let activeName = '';
let timeType = '';
if (type == 'first') {
path = '/member/member';
typeDay = 'day';
timeType = 3;
}else if (type == 'proxy') {
path = '/agent/agent-info';
typeDay = 'day';
timeType = '';
}else if (type == 'totalCharge') {
path = '/member/member';
typeDay = '';
timeType = 3;
}else if (type == 'totalAgent') {
path = '/agent/agent-info';
typeDay = '';
timeType = '';
}else if (type == 'differenceRecharge') {
path = '/finance/recharge-order';
typeDay = 'day';
timeType = '';
}else if (type == 'differenceWithdrawal') {
path = '/finance/withdrawal';
typeDay = 'day';
timeType = '';
activeName = 'allWithdrawal';
}else if (type == 'betOnNoteOrder') {
path = '/game/details';
typeDay = 'day';
timeType = '';
activeName = 'details';
}else if (type == 'discountParticipants') {
path = '/discounts/discount-details';
typeDay = 'day';
timeType = '';
activeName = '';
}
else if (type == 'discountTask') {
path = '/discounts/task';
typeDay = '';
timeType = '';
activeName = '';
}else if (type == 'discountActivity') {
path = '/discounts/activity-center';
typeDay = '';
timeType = '';
activeName = '';
}
proxy.$router.push({
path: path,
query: {
activeName: activeName,
operateTimeType: typeDay,
timeType:timeType,
currencyType:props.currencyType,
}
});
// const type = e.target.dataset.type
// let path = '';
// let typeDay = '';
// let activeName = '';
// let timeType = '';
// if (type == 'first') {
// path = '/member/member';
// typeDay = 'day';
// timeType = 3;
// }else if (type == 'proxy') {
// path = '/agent/agent-info';
// typeDay = 'day';
// timeType = '';
// }else if (type == 'totalCharge') {
// path = '/member/member';
// typeDay = '';
// timeType = 3;
// }else if (type == 'totalAgent') {
// path = '/agent/agent-info';
// typeDay = '';
// timeType = '';
// }else if (type == 'differenceRecharge') {
// path = '/finance/recharge-order';
// typeDay = 'day';
// timeType = '';
// }else if (type == 'differenceWithdrawal') {
// path = '/finance/withdrawal';
// typeDay = 'day';
// timeType = '';
// activeName = 'allWithdrawal';
// }else if (type == 'betOnNoteOrder') {
// path = '/game/details';
// typeDay = 'day';
// timeType = '';
// activeName = 'details';
// }else if (type == 'discountParticipants') {
// path = '/discounts/discount-details';
// typeDay = 'day';
// timeType = '';
// activeName = '';
// }
// else if (type == 'discountTask') {
// path = '/discounts/task';
// typeDay = '';
// timeType = '';
// activeName = '';
// }else if (type == 'discountActivity') {
// path = '/discounts/activity-center';
// typeDay = '';
// timeType = '';
// activeName = '';
// }
// proxy.$router.push({
// path: path,
// query: {
// activeName: activeName,
// operateTimeType: typeDay,
// timeType:timeType,
// currencyType:props.currencyType,
// }
// });
}
// proxy.t('')+(props?.cardData?.profit||0)+' '+
const goPage = (cardClass) => {
let path = '';
let typeDay = '';
if (cardClass == 'orange'){
path = '/member/member';
typeDay = 'day';
}else if (cardClass == 'blue'){
path = '/member/member';
typeDay = '';
}else if (cardClass == 'yellow'){
path = '/game/details';
typeDay = 'day';
}else if (cardClass == 'purple'){
path = '/discounts/discount-details';
typeDay = 'day';
}
proxy.$router.push({
path: path,
query: {
activeName: 'details',
operateTimeType: typeDay
}
});
// let path = '';
// let typeDay = '';
// if (cardClass == 'orange'){
// path = '/member/member';
// typeDay = 'day';
// }else if (cardClass == 'blue'){
// path = '/member/member';
// typeDay = '';
// }else if (cardClass == 'yellow'){
// path = '/game/details';
// typeDay = 'day';
// }else if (cardClass == 'purple'){
// path = '/discounts/discount-details';
// typeDay = 'day';
// }
// proxy.$router.push({
// path: path,
// query: {
// activeName: 'details',
// operateTimeType: typeDay
// }
// });
}
</script>
@ -249,7 +249,7 @@
margin-top: 10px;
}
:deep(.card-subtitle a){
text-decoration: underline!important;
/* text-decoration: underline!important; */
}
.percentage {
font-size: 14px;

View File

@ -226,16 +226,16 @@ import { el } from 'element-plus/es/locales.mjs';
}
const handleTap = (tab) => {
//
let path = '/chart/operationalStatistics';
let query = { };
router.replace({ path, query });
// let path = '/chart/operationalStatistics';
// let query = { };
// router.replace({ path, query });
}
const operationList = ref([]);
const homeOperationLists = () => {
if (!props.isLoading)return;
loadings.value = false;
let obj = {
tenantId:props.tenantId,
tenantId:props.tenantId == 0 ? '' : props.tenantId,
operationType:tabPosition.value,
currencyCode:props.currencyType,
startDate:dateRange.value[0],

View File

@ -81,7 +81,7 @@
const homeNumberLists = () => {
if (!props.isLoading)return;
let obj = {
tenantId:props.tenantId,
tenantId:props.tenantId == '0'?'':props.tenantId,
platformCode: platformCode.value,
numberType: activeName.value,
currencyCode: props.currencyType

View File

@ -4,7 +4,7 @@
<div style="margin-bottom: 15px;">
<custom-select v-model="currencyType" :options="currencySelectArr" style="width: 220px;"
@change="getHomeIndexs"></custom-select>
<custom-select style="width: 130px;" v-if="siteSelect.length > 0" @change="getHomeIndexs" collapse-tags collapse-tags-tooltip v-model="tenantId" :options="siteSelect" :placeholder="t('请选择')"></custom-select>
<custom-select style="width: 130px;" v-if="siteSelect.length > 0" @change="getHomeIndexs" collapse-tags collapse-tags-tooltip v-model="tenantId" clearable :options="siteSelect" :placeholder="t('请选择')"></custom-select>
</div>
<el-row>
<el-col :span="24" style="background:rgb(255,255,255);padding:16px 16px 0px;margin-bottom:32px">
@ -51,21 +51,31 @@ const homeOperationReportResponses = ref([]);
const isLoading = ref(false);
const getSiteSelects = () => {
getSiteSelect().then(response => {
siteSelect.value = response.data.map((item,index) => {
if (index == 0){
tenantId.value = item.tenantId;
}
return {
...item,
label: item.siteName,
value: item.tenantId,
}
});
siteSelect.value = [
{
label: '全部',
value: '0', // ID 'all'
},
...response.data.map((item, index) => {
if (index === 0) {
tenantId.value = item.tenantId;
}
return {
...item,
label: item.siteName,
value: item.tenantId,
};
}),
];
getHomeIndexs();
})
}
const getHomeIndexs = async () => {
getHomeIndex({currencyCode:currencyType.value,tenantId:tenantId.value}).then((res) => {
let obj = {
currencyCode:currencyType.value,
tenantId:tenantId.value == '0'?'':tenantId.value,
}
getHomeIndex(obj).then((res) => {
cardData.value = res.data.homePageResponse;
homeOperationReportResponses.value = res.data.homeOperationReportResponses;
isLoading.value = true;

View File

@ -169,7 +169,9 @@
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
<el-form-item label="返回参数:" >
<div style="width: 100%;">{{ form.jsonResult }}</div>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="操作状态:">
@ -242,7 +244,7 @@ function getList() {
/** 操作日志类型字典翻译 */
function typeFormat(row, column) {
return proxy.selectDictLabel(sys_oper_type.value, row.businessType);
return proxy.selectDictLabel(sys_oper_type.value || {}, row.businessType);
}
/** 搜索按钮操作 */
@ -308,3 +310,5 @@ function handleExport() {
getList();
</script>
<style scoped>
</style>

View File

@ -104,6 +104,7 @@ import CustomSelect from '@/components/CustomSelect';
import AddSiteDialog from "./components/AddSiteDialog"; //
import ModifyDialog from "./components/ModifyDialog";
import { getLocalStorage } from "@/utils/auth";
import dayjs from 'dayjs';
import Crontab from '@/components/Crontab'
import { onMounted } from "vue";
const router = useRouter();
@ -132,7 +133,7 @@ queryParams: {
pageNum: 1,
pageSize: 10,
searchType:'siteName',
month: '',
month: dayjs().subtract(1, "month").format("YYYY-MM"),
},
});
//

View File

@ -6,7 +6,7 @@
<custom-select style="width: 130px;" v-if="siteSelect.length > 0" collapse-tags collapse-tags-tooltip v-model="siteIdNo" :options="siteSelect" :placeholder="t('请选择')"></custom-select>
</el-form-item>
<el-form-item prop="timeType">
<el-select v-model="queryParams.timeType" :placeholder="t('请选择')" clearable style="width: 150px;">
<el-select v-model="queryParams.timeType" :placeholder="t('请选择')" style="width: 150px;">
<el-option :label="t('最后登录时间')" :value="1" />
<el-option :label="t('注册时间')" :value="2" />
</el-select>

View File

@ -0,0 +1,138 @@
<template>
<el-dialog :title="t('修改')" v-model="open" width="600px" append-to-body align-center>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="add-form">
<!-- <el-form-item :label="t('币种')">
<el-input :value="t('全部币种')" disabled></el-input>
</el-form-item>
<el-form-item :label="t('链接名称')" prop="categoryName">
<div class="flex-box">
<dict-select v-model="form.openUrlLang" dictKey="ff_open_url_lang"></dict-select>
<el-input class="flex-input" v-model="form.categoryName" :placeholder="t('请输入链接名称')"></el-input>
</div>
</el-form-item>
<el-form-item :label="t('链接类型')" prop="open_url_type">
<dict-select v-model="form.openUrlType" dictKey="ff_open_url_type"
@change="openUrlTypeChange"></dict-select>
</el-form-item>
<el-form-item :label="t('外部URL')" prop="openUrl" v-if="form.openUrlType == 1">
<el-input v-model="form.openUrl" maxlength="500" show-word-limit :placeholder="t('请输入外部URL')"></el-input>
</el-form-item>
<el-form-item :label="t('打开方式')" prop="openType">
<dict-select v-model="form.openType" dictKey="jump_type" disabled></dict-select>
</el-form-item>
<el-form-item :label="t('备注')" prop="remark">
<el-input v-model="form.remark" type="textarea" maxlength="50" show-word-limit
:placeholder="t('请输入备注')"></el-input>
</el-form-item>
<el-form-item :label="t('类型icon')" prop="iconUrl">
<image-upload v-model="form.iconUrl" :limit="1" :fileType="['jpg', 'png', 'jpeg']"
:fileSize="1"></image-upload>
</el-form-item> -->
<el-form-item :label="t('类型')" prop="iconUrl">
<custom-select v-model="form.showType" :options="showTypeSelect" :placeholder="t('选择类型')" ></custom-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="cancel">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as game from "@/api/game/game";
import ImageUpload from "@/components/ImageUpload";
import CustomSelect from "@/components/CustomSelect";
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submit'])
const open = ref(false)
const form = ref({
showType: 0,
})
const rules = {
categoryName: [{ required: true, message: proxy.t('请输入链接名称'), trigger: 'blur' }],
openUrl: [{ required: true, message: proxy.t('请输入外部URL'), trigger: 'blur' }]
}
const showTypeSelect = [
{ label: proxy.t('游戏'), value: 0 },
{ label: proxy.t('平台'), value: 1 }
];
const formRef = ref(null);
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
if (valid) {
loadingButton.value = true;
if (form.value.id) {
if (JSON.stringify(form.value) != oldForm.value) {
game.updateLinks(form.value).then(response => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功'));
cancel()
emits('submit')
}).catch(() => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
cancel()
}
} else {
game.addLinks(form.value).then(response => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('新增成功'));
cancel()
emits('submit')
}).catch(() => {
loadingButton.value = false;
});
}
}
});
}
const showModal = (id) => {
if (id) {
getInfo(id)
}
open.value = true
}
const cancel = () => {
open.value = false
}
const openUrlTypeChange = (val) => {
form.value.openType = val == 1 ? '1' : '2'
}
const numberToStringList = ['openUrlLang', 'openUrlType', 'openType']
const getInfo = async (id) => {
const res = await game.getCategory(id)
numberToStringList.forEach(key => {
if (res.data[key] !== undefined) {
res.data[key] = res.data[key]?.toString()
}
})
form.value = res.data
setTimeout(() => {
let objForm = form.value;
oldForm.value = JSON.stringify(objForm);
}, 500);
}
defineExpose({ showModal })
</script>
<style scoped lang="scss">
.flex-box {
width: 100%;
display: flex;
align-items: center;
gap: 20px;
.flex-input {
flex: 1;
}
}
</style>

View File

@ -0,0 +1,186 @@
<template>
<el-dialog :title="t('热门行数设置')" v-model="open" width="600px" append-to-body align-center>
<!-- <el-table :data="tableData" border :span-method="objectSpanMethod">
<el-table-column align="center" prop="currencyCode" :label="t('币种')"></el-table-column>
<el-table-column align="center" prop="label" :label="t('当前版本: 竖版图标')"></el-table-column>
<el-table-column align="center" prop="num" :label="t('修改')">
<template #default="{ row }">
<el-input v-model.number="row.num" :placeholder="t('请输入内容')" clearable>
<template #append>{{ t('行') }}</template>
</el-input>
</template>
</el-table-column>
</el-table> -->
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="add-form">
<el-form-item :label="t('首页H5版')" prop="h5IndexRows">
<el-input v-model="form.h5IndexRows" >
<template #append>{{ t('行') }}</template>
</el-input>
</el-form-item>
<el-form-item :label="t('二级页H5版')" prop="h5LevelRows">
<el-input v-model="form.h5LevelRows" >
<template #append>{{ t('行') }}</template>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="cancel">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as game from '@/api/game/game'
import { ref } from 'vue';
const { proxy } = getCurrentInstance()
const emits = defineEmits(['submit'])
const open = ref(false);
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const showModal = (id) => {
open.value = true
getInfo(id)
}
const tableData = ref([])
const rawData = ref([])
const form = reactive({})
const rules = reactive({
h5IndexRows: [
{ required: true, message: '请输入', trigger: 'change' },
{
validator: (rule, value, callback) => {
if (value == '') {
callback(new Error('请输入数字'));
} else if (isNaN(value) || value < 0 || value > 10) {
callback(new Error('请输入 0 到 10 之间的数字'));
} else {
callback(); //
}
},
trigger: 'change',
}
],
h5LevelRows: [
{ required: true, message: '请输入', trigger: 'change' },
{
validator: (rule, value, callback) => {
if (value == '') {
callback(new Error('请输入数字'));
} else if (isNaN(value) || value < 0 || value > 10) {
callback(new Error('请输入 0 到 10 之间的数字'));
} else {
callback(); //
}
},
trigger: 'change',
}
],
})
const labels = [
{ key: 'h5IndexRows', label: proxy.t('首页H5版') },
{ key: 'h5LevelRows', label: proxy.t('二级页H5版') }
];
const getInfo = async (id) => {
tableData.value = []
const res = await game.getCategory(id)
// res.data.categoryRows.forEach(item => {
// labels.forEach(label => {
// const num = item[label.key];
// if (num) {
// tableData.value.push({
// currencyCode: item.currencyCode,
// label: label.label,
// num: num,
// keys: label.key
// });
// }
// });
// })
form.h5IndexRows = res.data.h5IndexRows
form.h5LevelRows = res.data.h5LevelRows
form.id = res.data.id
rawData.value = res.data.categoryRows
setTimeout(() => {
let objForm = form;
oldForm.value = JSON.stringify(objForm);
}, 500);
}
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex === 0) {
const currencyCode = row.currencyCode;
let count = 0;
for (let i = rowIndex; i < tableData.value.length; i++) {
if (tableData.value[i].currencyCode === currencyCode) {
count++;
} else {
break;
}
}
if (count > 1 && rowIndex % count === 0) {
return {
rowspan: count,
colspan: 1
};
} else {
return {
rowspan: 0,
colspan: 0
};
}
}
};
//
const validateNum = () => {
for (let i = 0; i < tableData.value.length; i++) {
const item = tableData.value[i];
if (!('num' in item) || typeof item.num !== 'number' || !Number.isInteger(item.num) || item.num <= 0) {
throw new Error(item.label + proxy.t('填写的数据有误,请重新填写!'));
}
}
}
const submitForm = () => {
try {
loadingButton.value = true;
validateNum()
// rawData.value.forEach(item => {
// tableData.value.forEach(row => {
// if (row.currencyCode === item.currencyCode) {
// item[row.keys] = row.num
// }
// })
// })
if (JSON.stringify(form) != oldForm.value) {
game.updateCategory(form).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(res.msg)
cancel()
emits('submit')
}).catch(() => {
loadingButton.value = false;
})
}else{
loadingButton.value = false;
cancel()
}
} catch (error) {
loadingButton.value = false;
proxy.$modal.msgError(error.message)
console.error(error.message);
}
}
const cancel = () => {
open.value = false
}
defineExpose({
showModal
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,210 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="handleQuery">
<template #left>
<el-form-item prop="currencyCode">
<currency-select v-model="queryParams.currencyCode" @change="handleQuery"></currency-select>
</el-form-item>
<el-form-item prop="showType">
<custom-select v-model="queryParams.showType" :options="showTypeSelect" :placeholder="t('选择类型')" @change="handleQuery"></custom-select>
</el-form-item>
</template>
<template #right>
<!-- <el-button type="primary" icon="Plus" @click="handleAddLink('')">{{ t('') }}</el-button> -->
</template>
</table-search-card>
<el-table v-loading="loading" :data="gameList" @selection-change="handleSelectionChange" class="c-table-main" stripe
ref="dragTable" row-key="id" border show-overflow-tooltip>
<el-table-column type="selection" width="55" align="center" />
<table-drag-sort v-model:tableList="gameList" @dragEnd="dragEnd"></table-drag-sort>
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
<el-table-column :label="t('类型名称')" align="center" prop="categoryName" />
<el-table-column align="center" prop="categorySwitch" width="130">
<template #header>
<span>{{ t('类型开关') }}</span>
<IconTips>{{ t('无子游戏时自动隐藏该类型') }}</IconTips>
</template>
<template #default="{ row }">
<base-switch v-model="row.categorySwitch" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'categorySwitch')" />
</template>
</el-table-column>
<el-table-column :label="t('打开方式')" align="center" prop="openType" width="100">
<template #default="{ row }">
<span v-if="row.openType === 1">{{ t('') }}</span>
<span v-else>{{ row.openType === 2 ? t('') : '--' }}</span>
</template>
</el-table-column>
<el-table-column label="icon" align="center" prop="iconUrl" width="100">
<template #default="{ row }">
<image-preview v-if="row.iconUrl" :src="row.iconUrl" :width="50" :height="50" />
<span v-else>--</span>
</template>
</el-table-column>
<el-table-column :label="t('链接地址')" align="center" prop="openUrl" width="150">
<template #default="{ row }">
<span>{{ row.openUrl || '--' }}</span>
</template>
</el-table-column>
<el-table-column :label="t('展示类型')" align="center" prop="openUrl" width="150">
<template #default="{ row }">
<span >{{ row.showType==0?'游戏':'平台'}}</span>
</template>
</el-table-column>
<el-table-column :label="t('首页显示行数')" align="center" prop="h5IndexRows" width="120" />
<el-table-column :label="t('二级页面显示行数')" align="center" prop="h5LevelRows" width="140" />
<el-table-column :label="t('备注')" align="center" prop="remark" width="100">
<template #default="{ row }">
<span>{{ row.remark || '--' }}</span>
</template>
</el-table-column>
<el-table-column :label="t('操作')" align="center" class-name="small-padding fixed-width" width="150">
<template #default="scope">
<el-button link type="primary" @click="handleSetting(scope.row)"
v-hasPermi="['game:game:edit']" v-if="scope.row.openType == -1 && scope.row.categoryType != 11 && scope.row.categoryType != 8 && scope.row.categoryType != 7 && scope.row.categoryType != 6 && scope.row.categoryType != 3">{{ t('行数设置') }}</el-button>
<!-- <el-button link type="primary" @click="handleAddLink(scope.row.id)"
v-hasPermi="['game:game:edit']" v-if="scope.row.categoryType != 11 && scope.row.categoryType != 8 && scope.row.categoryType != 7 && scope.row.categoryType != 6 && scope.row.categoryType != 3">{{ t('修改') }}</el-button> -->
<el-button link type="primary" @click="handleDelete(scope.row)"
v-hasPermi="['game:game:edit']" v-if="scope.row.openType != -1">{{ t('删除') }}</el-button>
</template>
</el-table-column>
<table-operation></table-operation>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
<!-- 行数设置 -->
<rows-setting ref="rowsSettingRef" @submit="getList"></rows-setting>
<!-- 新增外部链接弹窗 -->
<add-link ref="addLinkRef" @submit="getList"></add-link>
</template>
<script setup name="Category">
import * as game from "@/api/game/game";
import useInitDataStore from "@/store/modules/initData";
import baseSwitch from "@/components/BaseSwitch";
import CustomSelect from "@/components/CustomSelect";
import RowsSetting from "./components/RowsSetting";
import AddLink from "./components/AddLink";
import ImagePreview from "@/components/ImagePreview";
import TableDragSort from '@/components/TableDragSort';
import IconTips from "@/components/IconTips";
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const gameList = ref([]);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: 'sort_no',
isAsc: 'asc',
showType: '',
currencyCode: useInitData.dictInitData.currencyCode||useInitData.currencyCode,
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询平台管理列表 */
function getList() {
loading.value = true;
game.listCategory(queryParams.value).then(response => {
gameList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
const showTypeSelect = [
{ label: proxy.t('游戏'), value: 0 },
{ label: proxy.t('平台'), value: 1 }
];
//
function reset() {
form.value = {
id: null
};
proxy.resetForm("gameRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 修改行数设置按钮操作 */
const rowsSettingRef = ref()
function handleSetting(row) {
rowsSettingRef.value.showModal(row.id)
}
//
const addLinkRef = ref()
function handleAddLink(id = null) {
addLinkRef.value.showModal(id)
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm(proxy.t('是否确认删除该数据项?')).then(function () {
return game.delCategory(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess(proxy.t('删除成功'));
}).catch(() => { });
}
//
const dragEnd = (row) => {
game.categorySort(row).then(() => {
if (row.isTop) {
proxy.$modal.msgSuccess(proxy.t('置顶成功'));
}
getList();
})
}
//
const beforeSwitchChange = async (row, undateKeys) => {
const _status = row[undateKeys] === 1 ? 2 : 1
const _data = {
id: row.id
}
_data[undateKeys] = _status
try {
await game.updateCategorySwitch(_data).then(() => {
proxy.$modal.msgSuccess(_status === 1 ? proxy.t('开启成功') : proxy.t('关闭成功'))
getList()
})
return true;
} catch (error) {
console.error(proxy.t('接口调用失败'), error);
return false; //
}
}
getList();
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,243 @@
<template>
<!-- 新增 -->
<el-dialog :title="addEditStatus=='add' ? t('新增') : t('修改')" :close-on-click-modal="false" v-model="showDialog"
width="700px" append-to-body>
<el-scrollbar max-height="900px">
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="130px" class="add-form">
<!-- <el-form-item :label="t('版式风格')" prop="currencyCodes">
{{ formAll.platformType }}
</el-form-item> -->
<el-form-item :label="t('子游戏ID')" prop="id">
<el-input v-model="formAll.id" disabled />
</el-form-item>
<el-form-item :label="t('子游戏名称')" prop="gameName">
<el-input v-model="formAll.gameName" disabled />
</el-form-item>
<el-form-item :label="t('icon图样式')" prop="iconStyle">
<el-radio-group v-model="formAll.iconStyle">
<el-radio :value="1">{{ t('默认') }}</el-radio>
<el-radio :value="2">{{ t('自定义') }}</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="formAll.iconStyle == 1">
<el-form-item :label="t('品牌LOGO')" prop="gameLogo">
<div class="upload-box-vioce">
<image-upload :disabled="formAll.iconStyle == 1" :typeUpImg="3" v-model="formAll.gameLogo" :limit="1"
:isShowTip="false" :isdrag="true"></image-upload>
</div>
</el-form-item>
<el-form-item :label="t('icon图预览')" prop="gameIcon">
<div class="upload-box-vioce11">
<image-upload :disabled="formAll.iconStyle == 1" :typeUpImg="3" v-model="formAll.gameIcon" :limit="1"
:isShowTip="false" :isdrag="true"></image-upload>
</div>
</el-form-item>
</div>
<div v-if="formAll.iconStyle == 2">
<el-form-item :label="t('品牌LOGO')" prop="customGameLogo">
<div class="upload-box-vioce">
<image-upload :disabled="formAll.iconStyle == 1" :typeUpImg="3" v-model="formAll.customGameLogo" :limit="1"
:isShowTip="false" :isdrag="true"></image-upload>
</div>
</el-form-item>
<el-form-item :label="t('icon图预览')" prop="customGameIcon">
<div class="upload-box-vioce11">
<image-upload :disabled="formAll.iconStyle == 1" :typeUpImg="3" v-model="formAll.customGameIcon" :limit="1"
:isShowTip="false" :isdrag="true"></image-upload>
</div>
</el-form-item>
</div>
</el-form>
</el-scrollbar>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="closeDialog">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { formatTime,finalTimestamp } from '@/utils/ruoyi'; //
import ImageUpload from "@/components/ImageUpload";
import { updateGame } from "@/api/game/game";
import { nextTick, onMounted, ref } from "vue"; //
import { getLocalStorage } from "@/utils/auth";
const langList = getLocalStorage('langList')?.filter(v => v.langType == 1 && v.langStatus).map(item => {
return {
label: item.name,
value: item.id
};
}); //
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const { proxy } = getCurrentInstance() //
const emits = defineEmits(['submit', 'update:show']) //
const props = defineProps({ //
data: {
type: Object, //
default: {}
},
show: {
type: Boolean, //
default: false
},
addEditStatus:{ // /
type: String,
default: 'add'
},
modifyDate: { //
type: Object,
default: {}
}
})
const showDialog = computed({ //
get() {
return props.show
},
set(value) {
emits('update:show', value)
}
})
const activeNameLang = ref(0);//
const langOptionAll = ref([]); // tabs
const formAll = reactive({
})
//
nextTick(() => {
if (props.addEditStatus != 'edit') return;
Object.assign(formAll, props.modifyDate)
setTimeout(() => {
let objForm = { ...formAll }
oldForm.value = JSON.stringify(objForm);
}, 500);
});
//
const rules = reactive({
iconStyle: [
{ required: true, message: proxy.t('请选择icon图样式'), trigger: 'blur' }
],
})
//
const closeDialog = () => {
showDialog.value = false
}
//
const formRef = ref(null)
//
const submitForm = () => {
//
formRef.value.validate(valid => {
if (valid) {
loadingButton.value = true;
//
let formData = {
...formAll
};
if (JSON.stringify(formAll) != oldForm.value) {
updateGame(formData).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功!'));
emits('submit');
closeDialog();
}).catch(() => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
closeDialog();
}
}
});
};
</script>
<style scope lang="scss">
.w100 {
width: 100%;
}
.upload-box-vioce{
height: 90px !important;
overflow: hidden;
.upload-tips {
color: #999;
font-size: 12px;
line-height: 1.5;
padding-left: 10px;
}
.component-upload-image .el-upload--picture-card {
width: 180px !important;
height: 90px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 180px!important;
height: 90px!important;
}
:deep(.el-upload-list) {
width:180px!important;
height: 90px!important;
.el-upload,
.el-upload-list--picture-card .el-upload-list__item {
width: 180px!important;
height: 90px!important;
}
.el-upload-list__item {
margin: 0;
border: none;
width: 180px!important;
height: 90px!important;
}
}
}
.upload-box-vioce11{
height: 400px !important;
overflow: hidden;
.upload-tips {
color: #999;
font-size: 12px;
line-height: 1.5;
padding-left: 10px;
}
.component-upload-image .el-upload--picture-card {
width: 300px !important;
height: 400px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 300px!important;
height: 400px!important;
}
:deep(.el-upload-list) {
width:300px!important;
height: 400px!important;
.el-upload,
.el-upload-list--picture-card .el-upload-list__item {
width: 300px!important;
height: 400px!important;
}
.el-upload-list__item {
margin: 0;
border: none;
width: 300px!important;
height: 400px!important;
}
}
}
</style>

View File

@ -0,0 +1,288 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<el-form-item prop="currencyCode">
<currency-select style="width: 200px;" v-model="queryParams.currencyCode" @change="platformListInit()"></currency-select>
</el-form-item>
<el-form-item prop="gameType">
<custom-select v-model="queryParams.gameType" style="width: 200px;" :options="gameTypeOptions" @change="gameTypeChange" :clearable="false"></custom-select>
</el-form-item>
<!-- <el-form-item prop="gameType">
<dict-select v-model="queryParams.gameType" :config="{hasCheckAll:true,filterValue:['8','7','6','3','9']}" dictKey="ff_game_type" @change="gameTypeChange"
:clearable="false" :isDefault="useInitData.dictInitData.platformType ? false : true" ></dict-select>
</el-form-item> -->
<el-form-item prop="platformId">
<el-select v-model="queryParams.platformId" style="width: 200px;">
<el-option v-for="item in platformList" :key="item.id" :label="item.platformName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item prop="idOrName">
<el-input v-model="queryParams.idOrName" :placeholder="t('请输入子游戏名称/ID')" @keyup.enter="handleQuery" />
</el-form-item>
</template>
<template #right>
<el-button type="primary" @click="handleApiGame" >{{ t('同步API游戏') }}</el-button>
<el-button type="primary" @click="handleGamesTenants" >{{ t('同步游戏到租户') }}</el-button>
</template>
</table-search-card>
<el-table v-loading="loading" :data="gameList" @selection-change="handleSelectionChange" class="c-table-main" stripe
ref="dragTable" row-key="id" border>
<el-table-column type="selection" width="55" align="center" />
<table-drag-sort v-model:tableList="gameList" @dragEnd="dragEnd"></table-drag-sort>
<el-table-column :label="t('平台名称')" align="center" prop="platformName" />
<el-table-column :label="t('游戏ID')" align="center" prop="id" />
<el-table-column :label="t('子游戏名称')" align="center" prop="gameName" />
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
<el-table-column :label="t('热门一')" align="center" prop="popularOne" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.popularOne" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'popularOne')" />
</template>
</el-table-column>
<el-table-column :label="t('热门二')" align="center" prop="popularTwo" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.popularTwo" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'popularTwo')" />
</template>
</el-table-column>
<el-table-column :label="t('推荐(角标)')" align="center" prop="recommendedStatus" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.recommendedStatus" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'recommendedStatus')" />
</template>
</el-table-column>
<el-table-column :label="t('维护开关')" align="center" prop="stopStatus" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.stopStatus" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'stopStatus')" />
</template>
</el-table-column>
<el-table-column :label="t('游戏开关')" align="center" prop="gameStatus" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.gameStatus" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'gameStatus')"
style="--el-switch-on-color: #00a854; --el-switch-off-color: #ff4949" />
</template>
</el-table-column>
<el-table-column :label="t('子游戏icon')" align="center" prop="promotionalImage" width="100">
<template #default="scope">
<image-preview v-if="scope.row.iconStyle == 1" :src="scope.row.gameIcon" :width="50" :height="50" />
<image-preview v-if="scope.row.iconStyle == 2" :src="scope.row.customGameIcon" :width="50" :height="50" />
</template>
</el-table-column>
<el-table-column :label="t('操作')" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)"
v-hasPermi="['game:game:edit']">{{ t('修改') }}</el-button>
<el-button link type="primary" @click="handleSynchronous(scope.row)"
v-hasPermi="['game:game:sync']">{{ t('同步') }}</el-button>
</template>
</el-table-column>
<table-operation></table-operation>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
<add-dialog v-if="isShowDialog"
:addEditStatus="addEditStatus" :modifyDate="modifyDate" @submit="getList"
v-model:show="isShowDialog"></add-dialog>
</template>
<script setup name="Game">
import AddDialog from "./AddDialog"///
import * as game from "@/api/game/game";
import { platformSelect,getGamePlatformApiSync,getGamePlatformTenantSync } from "@/api/game/platform";
import useInitDataStore from "@/store/modules/initData";
import baseSwitch from "@/components/BaseSwitch";
import CurrencySelect from "@/components/CurrencySelect";
import { onBeforeUnmount } from "vue";
import DictSelect from "@/components/DictSelect";
import ImagePreview from "@/components/ImagePreview";
import TableDragSort from '@/components/TableDragSort';
import CustomSelect from "@/components/CustomSelect";
const emits = defineEmits(["reset"])
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const gameList = ref([]);
const open = ref(false);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const gameTypeOptions = ref([
{ label: '电子', value: '1' },
{ label: '棋牌', value: '2' },
{ label: '真人', value: '3' },
{ label: '捕鱼', value: '4' },
{ label: '体育', value: '6' },
{ label: '斗鸡', value: '7' },
{ label: '电竞', value: '8' },
{ label: '彩票', value: '9' },
{ label: '区块链', value: '10' },
]);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: 'sort_no',
isAsc: 'asc',
currencyCode: 'VND',
gameType: '1',
platformId: '',
idOrName: null,
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询平台管理列表 */
function getList() {
loading.value = true;
game.listGame(queryParams.value).then(response => {
gameList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
//
function reset() {
form.value = {
id: null
};
proxy.resetForm("gameRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
}
/** 重置按钮操作 */
function resetQuery() {
queryParams.value.gameType = useInitData.dictInitData.platformType
queryParams.value.platformId = useInitData.dictInitData.platformId
queryParams.value.pageNum = 1;
platformListInit(true)
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
const addEditStatus = ref('add'), isShowDialog = ref(false), editDataId = ref(''),modifyDate = ref({});
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const _id = row.id || ids.value
game.getGame(_id).then(response => {
modifyDate.value = response.data;
isShowDialog.value = true;
addEditStatus.value = 'edit'
title.value = proxy.t('修改平台管理');
});
// proxy.$modal.msgError("")
}
const handleSynchronous = (row) => {
proxy.$modal.confirm(proxy.t('当前设置宣传图同步到所有币种下生效')).then(() => {
game.gameGameSync({id:row.id}).then(() => {
proxy.$modal.msgSuccess(proxy.t('同步成功'));
getList();
})
}).catch(() => {})
}
// api
const handleApiGame = () => {
proxy.$modal.confirm(proxy.t('是否确认同步?')).then(() => {
getGamePlatformApiSync({}).then(() => {
proxy.$modal.msgSuccess(proxy.t('同步成功'));
getList();
})
}).catch(() => {})
}
//
const handleGamesTenants = () => {
proxy.$modal.confirm(proxy.t('是否确认同步?')).then(() => {
getGamePlatformTenantSync({}).then(() => {
proxy.$modal.msgSuccess(proxy.t('同步成功'));
getList();
})
}).catch(() => {})
}
//
const dragEnd = (row) => {
game.gameSort(row).then(() => {
if (row.isTop) {
proxy.$modal.msgSuccess(proxy.t('置顶成功'));
}
getList();
})
}
//
const platformList = ref([])
const platformListInit = async (isFirst = false) => {
let { platformId, gameType } = queryParams.value
await platformSelect({ platformType: gameType,currencyCode:queryParams.value.currencyCode }).then(res => {
platformList.value = res.data
queryParams.value.platformId = isFirst && platformId ? platformId : res?.data?.length ? res.data[0].id : null
getList();
})
}
//
const gameTypeChange = () => {
queryParams.value.pageNum = 1;
// platformListInit()
}
//
const beforeSwitchChange = async (row, undateKeys) => {
const _status = row[undateKeys] === 1 ? 2 : 1
const _data = {
id: row.id
}
_data[undateKeys] = _status
try {
await game.updateGameSwitch(_data).then(() => {
proxy.$modal.msgSuccess(_status === 1 ? proxy.t('开启成功') : proxy.t('关闭成功'))
getList()
})
return true;
} catch (error) {
console.error(proxy.t('接口调用失败'), error);
return false; //
}
}
watch(() => queryParams.value.gameType, (newValue) => {
if (newValue) {
platformListInit(newValue === useInitData.dictInitData.platformType ? true : false)
}
}, { immediate: true });
onBeforeUnmount(() => {
useInitData.setStateData('platformId', null)
useInitData.setStateData('platformType', null)
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,43 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane v-for="item in tabs" :key="item.name" :label="item.label" :name="item.name">
<template #label>
<span class="tabs-label">{{ item.label }}
<span v-if="platItem.hotOne == '2' && item.name == 'popular1'"
style="color: #51f300;">{{ t('生效中') }}</span>
<span v-if="platItem.hotTwo == '2' && item.name == 'popular2'"
style="color: #51f300;">{{ t('生效中') }}</span>
</span>
</template>
</el-tab-pane>
</el-tabs>
<div class="tabs-main-box">
<platform v-if="activeName === 'platform'" @toGameManage="toGameManage"></platform>
<game v-if="activeName === 'game'">
</game>
</div>
</div>
</template>
<!-- 游戏管理 -->
<script setup name="Manage">
import platform from "./platform"
const { proxy } = getCurrentInstance();
import game from "./game"
const platItem = ref({})
const activeName = ref('platform')
const tabs = ref([
{ label: proxy.t('平台管理'), name: 'platform' },
{ label: proxy.t('子游戏管理'), name: 'game' },
])
//
const toGameManage = () => {
activeName.value = 'game'
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,581 @@
<template>
<!-- 新增 -->
<el-dialog :title="addEditStatus=='add' ? t('新增') : t('修改')" align-center :close-on-click-modal="false" v-model="showDialog" :width="formAll.promotionalStyle==1 ?'1900px':'700px'" append-to-body>
<!-- <el-scrollbar max-height="900px" > -->
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="130px" class="add-form">
<el-row :gutter="20">
<el-col :span="formAll.promotionalStyle==1?12:24">
<el-form-item :label="t('版式风格')" prop="iconType">
<el-radio-group v-model="formAll.iconType" @change="generateImage" style="margin-bottom: 0px">
<el-radio-button :value="1">{{ t('方形图标') }}</el-radio-button>
<el-radio-button :value="2">{{ t('竖版图标') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('平台名称')" prop="platformName">
<el-input v-model="formAll.platformName" disabled />
</el-form-item>
<el-form-item :label="t('最低准入')" prop="minAmount">
<number-input v-model="formAll.minAmount" ></number-input>
</el-form-item>
<el-form-item :label="t('平台宣传语')" prop="promotionalText">
<el-input v-model="formAll.promotionalText" :placeholder="t('请输入平台宣传语')" />
</el-form-item>
<el-form-item :label="t('平台跳转方式')" prop="iosJump">
<div style="width: 100%;display: flex;">
<div style="width: 80px;text-align: right;margin-right: 10px;">IOS:</div>
<el-radio-group v-model="formAll.iosJump" style="margin-bottom: 0px">
<el-radio :value="1">{{ t('内嵌') }}</el-radio>
<el-radio :value="2">{{ t('外链') }}</el-radio>
</el-radio-group>
</div>
<div style="width: 100%;display: flex;">
<div style="width: 80px;text-align: right;margin-right: 10px;">Android:</div>
<el-radio-group v-model="formAll.androidJump" style="margin-bottom: 0px">
<el-radio :value="1">{{ t('内嵌') }}</el-radio>
<el-radio :value="2">{{ t('外链') }}</el-radio>
</el-radio-group>
</div>
<div style="width: 100%;display: flex;">
<div style="width: 80px;text-align: right;margin-right: 10px;">H5:</div>
<el-radio-group v-model="formAll.h5Jump" style="margin-bottom: 0px">
<el-radio :value="1">{{ t('内嵌') }}</el-radio>
<el-radio :value="2">{{ t('外链') }}</el-radio>
</el-radio-group>
</div>
</el-form-item>
<el-form-item :label="t('宣传图样式')" prop="promotionalStyle">
<el-radio-group v-model="formAll.promotionalStyle">
<el-radio :value="1">{{ t('默认') }}</el-radio>
<el-radio :value="2">{{ t('自定义') }}</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="formAll.promotionalStyle == 1">
<el-form-item :label="t('宣传图图标')" prop="promotionalIcon">
<banner-icon @clickSelect="handleSelection('three',$event)" :disabled="shouwLoding" :imageUrl="formAll.promotionalIcon" :query="materialIcon" url="/game/material/group/select"></banner-icon>
</el-form-item>
</div>
<div v-if="formAll.promotionalStyle == 2">
<el-form-item :label="t('宣传图')" prop="customPromotionalImage">
<div v-if="formAll.iconType == 2" class="upload-box-vioce11">
<image-upload v-model="formAll.customPromotionalImage" :typeUpImg="3" :limit="1" :isShowTip="false"
:isdrag="true"></image-upload>
</div>
<div v-if="formAll.iconType == 1" class="upload-box-vioce22">
<image-upload v-model="formAll.customPromotionalImage" :typeUpImg="3" :limit="1" :isShowTip="false"
:isdrag="true"></image-upload>
</div>
<div >{{ t('只能上传png文件且不超过1MB图片尺寸为300px * 400px') }}</div>
</el-form-item>
<el-form-item :label="t('热门图')" prop="customPopularStyle">
<div v-if="formAll.iconType == 2" class="upload-box-vioce11">
<image-upload v-model="formAll.customPopularStyle" :typeUpImg="3" :limit="1" :isShowTip="false"
:isdrag="true"></image-upload>
</div>
<div v-if="formAll.iconType == 1" class="upload-box-vioce22">
<image-upload v-model="formAll.customPopularStyle" :typeUpImg="3" :limit="1" :isShowTip="false"
:isdrag="true"></image-upload>
</div>
<div >{{ t('只能上传png文件且不超过1MB图片尺寸为300px * 400px') }}</div>
</el-form-item>
</div>
</el-col>
<el-col :span="12" v-if="formAll.promotionalStyle == 1">
<div v-if="formAll.promotionalStyle == 1">
<el-form-item :label="t('图片背景')" prop="promotionalBackground">
<BannerColour @clickSelect="handleSelection('two',$event)" :disabled="shouwLoding" :backgroundColor="formAll.promotionalBackground" :query="materialTypess" url="/game/material/group/select"></BannerColour>
</el-form-item>
<el-form-item v-if="formAll.promotionalStyle == 1" :label="t('品牌LOGO')" prop="platformLogo">
<div class="upload-box-vioce" style="border:1px solid #409eff;border-radius: 5px;width: 213px;height:90px !important;text-align: center;display: flex;justify-content: center;align-items: center;">
<img style="width: 100px;" :src="fileHost+formAll.platformLogo"/>
</div>
</el-form-item>
<el-form-item v-if="formAll.promotionalStyle == 2" :label="t('品牌LOGO')" prop="customPlatformLogo">
<div class="upload-box-vioce">
<image-upload v-model="formAll.customPlatformLogo" :typeUpImg="3" :limit="1" :isShowTip="false"
:isdrag="true"></image-upload>
</div>
</el-form-item>
<el-form-item :label="t('宣传图预览')">
<div style=" position: absolute; top: -9999px; left: -9999px; visibility: hidden; ">
<div class="" v-if="formAll.iconType == 1" ref="captureArea" :style="`display: flex;align-items: center;justify-content: space-between;width: 400px;height: 150px;background: url(${formAll.popularStyleGb}) no-repeat;background-size: 100% 100%;`">
<div class="" style="width: 40%;">
<p style="margin: 0;text-align: center;"><img style="width: 100px;height: auto;" :src="formAll.platformLogoGb"/></p>
<p style="margin: 0;text-align: center;font-size: 16px;font-weight: 600;"> </p>
</div>
<div style="width: 60%;">
<div style="width: 260px;height: 150px;">
<img style="width: 100%;height: 100%;" :src="formAll.promotionalImageGb"/>
</div>
</div>
</div>
<div v-if="formAll.iconType == 2" class="" ref="captureArea" :style="`display: flex;align-items: center;justify-content: space-between;width: 210px;height: 280px;background: url(${formAll.popularStyleGb}) no-repeat;background-size: 100% 100%;`">
<div :style="`width: 210px; height: 280px;display: flex;align-items: center;position: relative;background: url(${formAll.promotionalImageGb});
background-size: cover;
background-position: center;
background-repeat: no-repeat;`">
<div class="" :style="`position: absolute;bottom: 0;left: 0;width: 100%;`">
<div style="margin: 0;text-align: center;position: relative;top: 0px;"><img style="width: 58px;height: auto;" crossorigin="anonymous" :src="formAll.platformLogoGb"/></div>
<div style="margin: 0;text-align: center;font-size: 16px;font-weight: 600;color: #fff;height: 35px;"> </div>
</div>
</div>
</div>
</div>
<img :src="resolvedImageUrl" style="border-radius: 5px;" alt="Generated Image" />
</el-form-item>
<el-form-item :label="t('热门图预览')">
<div style="position: absolute; top: -8999px; left: -8999px; visibility: hidden;">
<div class="" v-if="formAll.iconType == 1" ref="captureAreaPop" :style="`display: flex;align-items: center;justify-content: space-between;width: 400px;height: 150px;background: url(${formAll.popularStyleGb}) no-repeat;background-size: 100% 100%;`">
<div class="" style="width: 40%;">
<p style="margin: 0;text-align: center;"><img style="width: 100px;height: auto;" :src="formAll.platformLogoGb"/></p>
<p style="margin: 0;text-align: center;font-size: 16px;font-weight: 600;"> </p>
</div>
<div style="width: 60%;">
<div style="width: 260px;height: 150px;">
<img style="width: 100%;height: 100%;" :src="formAll.promotionalImageGb"/>
</div>
</div>
</div>
<div v-if="formAll.iconType == 2" class="" ref="captureAreaPop" :style="`display: flex;align-items: center;justify-content: space-between;width: 210px;height: 280px;background: url(${formAll.popularStyleGb}) no-repeat;background-size: 100% 100%;`">
<div :style="`width: 210px; height: 245px;display: flex;align-items: center;margin-top:35px; position: relative;background: url(${formAll.promotionalImageGb});
background-size: cover;
background-position: center;
background-repeat: no-repeat;`">
<div class="" :style="`position: absolute;top: -40px;left: 0;width: 100%;`">
<div style="margin: 0;text-align: center;"><img style="width: 70px;height: auto;" crossorigin="anonymous" :src="formAll.platformLogoGb"/></div>
</div>
<div class="" :style="`position: absolute;height:80px;bottom: 0;left: 0;width: 100%;`">
<div style="margin: 0;text-align: center;font-size: 16px;font-weight: 600;color: #fff;margin-top: 45px;height: 35px;"> </div>
</div>
</div>
</div>
</div>
<img :src="resolvedPopularStyle" style="border-radius: 5px;" alt="Generated Image" />
</el-form-item>
</div>
</el-col>
</el-row>
</el-form>
<!-- </el-scrollbar> -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="closeDialog">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { formatTime,finalTimestamp } from '@/utils/ruoyi'; //
import ImageUpload from "@/components/ImageUpload";
import NumberInput from "@/components/NumberInput";
import { updatePlatform } from "@/api/game/platform";
import BannerColour from "@/components/BannerColour"; // Banner
import BannerIcon from "@/components/BannerIcon"; // Banner
import { getToken } from '@/utils/auth'
import { nextTick, onMounted, ref } from "vue"; //
import { getLocalStorage } from "@/utils/auth";
const fileHost = getLocalStorage('fileUrl') || ''; // host
import html2canvas from 'html2canvas';
const uploadUrl = getLocalStorage('uploadUrl');
const uploadImgUrl = ref(uploadUrl + "/file/upload/localSysFile/3"); //
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const langList = getLocalStorage('langList')?.filter(v => v.langType == 1 && v.langStatus).map(item => {
return {
label: item.name,
value: item.id
};
}); //
const { proxy } = getCurrentInstance() //
const emits = defineEmits(['submit', 'update:show']) //
const props = defineProps({ //
data: {
type: Object, //
default: {}
},
show: {
type: Boolean, //
default: false
},
addEditStatus:{ // /
type: String,
default: 'add'
},
modifyDate: { //
type: Object,
default: {}
}
})
const materialIcon = ref({ //
materialTypes:'2'
});
const materialTypess = ref({ //
materialTypes:'1'
});
const showDialog = computed({ //
get() {
return props.show
},
set(value) {
emits('update:show', value)
}
})
const activeNameLang = ref(0);//
const langOptionAll = ref([]); // tabs
const formAll = reactive({
iconType:1, // 1: 2:
})
const loadImageAsBase64 = async(url)=> {
const res = await fetch(uploadUrl+url, { mode: 'cors' })
const blob = await res.blob()
return await new Promise((resolve) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.readAsDataURL(blob)
})
}
//
nextTick(async () => {
if (props.addEditStatus != 'edit') return;
Object.assign(formAll, props.modifyDate)
formAll.id = props.modifyDate.id;
formAll.iconType = props.modifyDate.iconType|| 1;
formAll.platformName = props.modifyDate.platformName;
formAll.minAmount = props.modifyDate.minAmount;
if (props.modifyDate.promotionalStyle == 1){
formAll.promotionalImage = props.modifyDate.promotionalImage;
formAll.platformLogoGb = await loadImageAsBase64(props.modifyDate.platformLogo);
formAll.popularStyleGb = await loadImageAsBase64(props.modifyDate.promotionalBackground);
formAll.promotionalImageGb = await loadImageAsBase64(props.modifyDate.promotionalIcon);
formAll.popularStyle = props.modifyDate.popularStyle;
}
formAll.promotionalStyle = props.modifyDate.promotionalStyle;
setTimeout(() => {
let objForm = { ...formAll }
oldForm.value = JSON.stringify(objForm);
}, 500);
});
const captureArea = ref(null);
const captureAreaPop = ref(null);
//
const waitForImagesLoaded = async (container) => {
const imgs = container.querySelectorAll('img');
await Promise.all([...imgs].map(img => {
return new Promise(resolve => {
if (img.complete) return resolve();
img.onload = img.onerror = () => resolve();
});
}));
};
const shouwLoding = ref(false);
const generateImage = async () => {
shouwLoding.value = true;
const el = captureArea.value;
const el2 = captureAreaPop.value;
if (!el || !el2) return;
el.style.visibility = 'visible';
el2.style.visibility = 'visible';
await nextTick();
await waitForImagesLoaded(el);
await waitForImagesLoaded(el2);
await new Promise(resolve => setTimeout(resolve, 100));
const canvas = await html2canvas(el, {
useCORS: true,
backgroundColor: '#fff'
});
formAll.promotionalImage = canvas.toDataURL('image/png');
await new Promise(resolve => setTimeout(resolve, 100)); //
const canvas2 = await html2canvas(el2, {
useCORS: true,
backgroundColor: '#fff'
});
formAll.popularStyle = canvas2.toDataURL('image/png');
shouwLoding.value = false;
el.style.visibility = 'hidden';
el2.style.visibility = 'hidden';
};
//
const rules = reactive({
promotionalStyle: [
{ required: true, message: proxy.t('请选择icon图样式'), trigger: 'change' },
],
minAmount: [
{ required: true, message: proxy.t('请输入最小投注金额'), trigger: 'change' },
]
})
//
const closeDialog = () => {
showDialog.value = false
}
const resolvedImageUrl = computed(() => {
const url = formAll.promotionalImage
if (!url) return ''
if (url.startsWith('data:image/')) {
return url // base64
}
if (url.startsWith('http://') || url.startsWith('https://')) {
return url // URL fileHost
}
return fileHost + url // fileHost
})
const resolvedPopularStyle = computed(() => {
const url = formAll.popularStyle
if (!url) return ''
if (url.startsWith('data:image/')) {
return url // base64
}
if (url.startsWith('http://') || url.startsWith('https://')) {
return url // URL fileHost
}
return fileHost + url // fileHost
})
const getColorFromUrl = (url) => {
//
const match = url.match(/\/([^\/]+)\.png$/)
if (match && match[1]) {
return `#${match[1]}` // #
}
return null
}
const colorGb = ref('');
const isShow = ref(true); //
//
const handleSelection = async(type, en) => {
switch (type) {
case 'two':
isShow.value = false;
const color = getColorFromUrl(en.url);
colorGb.value = color;
if (formAll.promotionalBackground == en.url){
return
}
formAll.popularStyleGb = await loadImageAsBase64(en.url);
formAll.promotionalBackground = en.url;
nextTick(() => {
isShow.value = true;
generateImage();
});
break;
case 'three':
isShow.value = false;
if (formAll.promotionalIcon == en.url){
return
}
formAll.promotionalImageGb = await loadImageAsBase64(en.url);
formAll.promotionalIcon = en.url;
nextTick(() => {
isShow.value = true;
generateImage();
});
break;
default:
break;
}
};
function base64ToFile(base64, filename = 'image.png') {
const arr = base64.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
}
const uploadBase64Image = async(base64) =>{
if (!/^data:image\/(png|jpeg|jpg|gif|bmp);base64,/.test(base64)) {
// Base64 URL
return { url: base64 };
}
const file = base64ToFile(base64, 'upload.png')
const formData = new FormData()
formData.append('file', file)
const res = await fetch(uploadImgUrl.value, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + getToken(),
},
body: formData
})
return await res.json()
}
//
const formRef = ref(null)
//
const submitForm = async() => {
//
formRef.value.validate(async(valid) => {
if (valid) {
loadingButton.value = true;
let promotionalImages = await uploadBase64Image(formAll.promotionalImage)
let popularStyles = await uploadBase64Image(formAll.popularStyle)
//
let formData = {
...formAll,
promotionalImage:promotionalImages.url,
popularStyle:popularStyles.url,
};
delete formData.platformLogoGb;
delete formData.popularStyleGb;
delete formData.promotionalImageGb;
if (JSON.stringify(formAll) != oldForm.value) {
updatePlatform(formData).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功!'));
emits('submit');
closeDialog();
}).catch(error => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
closeDialog();
}
}
});
};
</script>
<style scope lang="scss">
.w100 {
width: 100%;
}
.upload-box-vioce{
height: 90px !important;
overflow: hidden;
.upload-tips {
color: #999;
font-size: 12px;
line-height: 1.5;
padding-left: 10px;
}
.component-upload-image .el-upload--picture-card {
width: 180px !important;
height: 90px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 180px!important;
height: 90px!important;
}
:deep(.el-upload-list) {
width:180px!important;
height: 90px!important;
.el-upload,
.el-upload-list--picture-card .el-upload-list__item {
width: 180px!important;
height: 90px!important;
}
.el-upload-list__item {
margin: 0;
border: none;
width: 180px!important;
height: 90px!important;
}
}
}
.upload-box-vioce11{
height: 400px !important;
overflow: hidden;
.upload-tips {
color: #999;
font-size: 12px;
line-height: 1.5;
padding-left: 10px;
}
.component-upload-image .el-upload--picture-card {
width: 300px !important;
height: 400px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 300px!important;
height: 400px!important;
}
:deep(.el-upload-list) {
width:300px!important;
height: 400px!important;
.el-upload,
.el-upload-list--picture-card .el-upload-list__item {
width: 300px!important;
height: 400px!important;
}
.el-upload-list__item {
margin: 0;
border: none;
width: 300px!important;
height: 400px!important;
}
}
}
.upload-box-vioce22{
height: 200px !important;
overflow: hidden;
.upload-tips {
color: #999;
font-size: 12px;
line-height: 1.5;
padding-left: 10px;
}
.component-upload-image .el-upload--picture-card {
width: 400px !important;
height: 200px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 400px!important;
height: 200px!important;
}
:deep(.el-upload-list) {
width:400px!important;
height: 200px!important;
.el-upload,
.el-upload-list--picture-card .el-upload-list__item {
width: 400px!important;
height: 200px!important;
}
.el-upload-list__item {
margin: 0;
border: none;
width: 400px!important;
height: 200px!important;
}
}
}
.disable-click {
pointer-events: none;
}
</style>

View File

@ -0,0 +1,243 @@
<template>
<el-dialog :title="t('游戏管理设置')" v-model="open" width="800px" append-to-body align-center>
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="260px" class="add-form">
<el-form-item :label="t('返回大厅按钮')" prop="returnHome">
<el-radio-group v-model="formAll.returnHome">
<el-radio :value="1">{{ t('二次弹窗确认(默认)') }}</el-radio>
<el-radio :value="2">{{ t('直接返回') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('已首充才能进入游戏(未充值无法进入)')" prop="needRecharge">
<el-radio-group v-model="formAll.needRecharge">
<el-radio :value="false">{{ t('不限制(默认)') }}</el-radio>
<el-radio :value="true">{{ t('开启') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('强制要求下载APP')" prop="forceDownload">
<el-radio-group v-model="formAll.forceDownload">
<el-radio :value="false">{{ t('不限制(默认)') }}</el-radio>
<el-radio :value="true">{{ t('开启(只能在APP游戏)') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('弹窗提示语')" prop="forceType">
<el-radio-group v-model="formAll.forceType">
<el-radio :value="1">{{ t('系统自带') }}</el-radio>
<el-radio :value="2">{{ t('自定义') }}</el-radio>
</el-radio-group>
<div v-if="formAll.forceType == 1" style="width: 100%;">
<div style="width: 100%;">
<el-tabs v-model="forcePopNameLang" class="demo-tabs" style="width: 90%;">
<el-tab-pane v-for="tab in langList" :name="tab?.value">
<template #label>
{{ tab?.label }}
<!-- <el-icon v-if="isDotVisible(tab)" style="margin-left: 4px;" color="rgb(245, 108, 108)"><WarningFilled /></el-icon> -->
</template>
</el-tab-pane>
</el-tabs>
</div>
<div v-for="(item,index) in formAll.forcePopPromptDefault" style="width: 100%;">
<div v-if="forcePopNameLang == item.lang" :contenteditable="false" class="textarea-like" :disabled="true" v-html="item.msg" :placeholder="t('请输入规则说明')"></div>
</div>
</div>
<div v-if="formAll.forceType == 2" style="width: 100%;margin-top: 10px;margin-right: 10px;">
<div style="width: 100%;">
<el-tabs v-model="forcePopNameLang" class="demo-tabs" style="width: 90%;">
<el-tab-pane v-for="tab in langList" :name="tab?.value">
<template #label>
{{ tab?.label }}
<!-- <el-icon v-if="isDotVisible(tab)" style="margin-left: 4px;" color="rgb(245, 108, 108)"><WarningFilled /></el-icon> -->
</template>
</el-tab-pane>
</el-tabs>
</div>
<div v-for="(item,index) in formAll.forcePopPrompt" style="width: 100%;">
<el-input v-if="forcePopNameLang == item.lang" v-model="item.msg" type="textarea" style="margin-top: 10px;" :rows="5" :placeholder="t('请输入')" maxlength="1000" show-word-limit />
</div>
</div>
</el-form-item>
<!-- <el-form-item :label="t('仅限已首充会员强制下载APP')" prop="gameRechargeDownloadApp">
<el-radio-group v-model="formAll.gameRechargeDownloadApp">
<el-radio value="2">{{ t('开启(仅限已首充会员)') }}</el-radio>
<el-radio value="1">{{ t('关闭(全部限制)') }}</el-radio>
</el-radio-group>
</el-form-item> -->
<!-- <el-form-item :label="t('仅限Android设备强制下载APP')" prop="gameAndroidDownloadApp">
<el-radio-group v-model="formAll.gameAndroidDownloadApp">
<el-radio value="2">{{ t('开启(推荐)') }}</el-radio>
<el-radio value="1">{{ t('关闭(所有设备都限制)') }}</el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item :label="t('充值次数触发强制转原生APP')" prop="rechargeCnt">
<NumberInput v-model="formAll.rechargeCnt" style="width: 120px;"></NumberInput><span style="margin-left: 5px;">{{ t('') }}</span>
</el-form-item>
<el-form-item :label="t('转原生提示语')" prop="rechargeType">
<el-radio-group v-model="formAll.rechargeType">
<el-radio :value="1">{{ t('系统自带') }}</el-radio>
<el-radio :value="2">{{ t('自定义') }}</el-radio>
</el-radio-group>
<div v-if="formAll.rechargeType == 1" style="width: 100%;">
<div style="width: 100%;">
<el-tabs v-model="activeNameLang" class="demo-tabs" style="width: 90%;">
<el-tab-pane v-for="tab in langList" :name="tab?.value">
<template #label>
{{ tab?.label }}
<!-- <el-icon v-if="isDotVisible(tab)" style="margin-left: 4px;" color="rgb(245, 108, 108)"><WarningFilled /></el-icon> -->
</template>
</el-tab-pane>
</el-tabs>
</div>
<div style="width: 100%;" v-for="(item,index) in formAll.rechargePopPromptDefault">
<div v-if="activeNameLang == item.lang" :contenteditable="false" class="textarea-like" :disabled="true" v-html="item.msg" :placeholder="t('请输入规则说明')"></div>
</div>
</div>
<div v-if="formAll.rechargeType == 2" style="width: 100%;margin-top: 10px;margin-right: 10px;">
<div style="width: 100%;">
<el-tabs v-model="activeNameLang" class="demo-tabs" style="width: 90%;">
<el-tab-pane v-for="tab in langList" :name="tab?.value">
<template #label>
{{ tab?.label }}
<!-- <el-icon v-if="isDotVisible(tab)" style="margin-left: 4px;" color="rgb(245, 108, 108)"><WarningFilled /></el-icon> -->
</template>
</el-tab-pane>
</el-tabs>
</div>
<div v-for="(item,index) in formAll.rechargePopPrompt" style="width: 100%;">
<el-input v-if="activeNameLang == item.lang" v-model="item.msg" type="textarea" style="margin-top: 10px;" :rows="5" :placeholder="t('请输入')" maxlength="1000" show-word-limit />
</div>
</div>
</el-form-item>
<el-form-item :label="t('游戏只显示一行,超过使用省略号展示')" prop="nameExceeds">
<el-radio-group v-model="formAll.nameExceeds">
<el-radio :value="false">{{ t('关闭(默认)') }}</el-radio>
<el-radio :value="true">{{ t('开启') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-text>
<el-icon color="#ff9900">
<InfoFilled />
</el-icon>
{{ t("功能说明:此功能将进行全局限制,虽然可以提高马甲包用户的留存率,但可能影响用户体验;与渠道链接的限制重复,建议可设置在渠道链接,按渠道设置马甲包来源,并限制防止用户流失。") }}
</el-text>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" v-h="['game:config:add']" @click="submitForm" :loading="loadingButton">{{ t(' ') }}</el-button>
<el-button @click="cancel">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as platform from "@/api/game/platform";
import NumberInput from "@/components/NumberInput"; //
import CustomSelect from "@/components/CustomSelect"; //
const { proxy } = getCurrentInstance();
import { getLocalStorage } from "@/utils/auth";
const langListRaw = getLocalStorage('langList') || []
const langList = Array.from(
new Map(
langListRaw.map(item => [item.countryLang, {
label: item.name,
value: item.countryLang
}])
).values()
) //
const emits = defineEmits([])
const open = ref(false);
const activeNameLang = ref(localStorage.getItem('lang')|| 'zh-CN');
const forcePopNameLang = ref(localStorage.getItem('lang')|| 'zh-CN');
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const formAll = reactive({
forceType:1,
forcePopPromptDefault: [
{
lang:'',
msg:'',
}
],
forcePopPrompt:[
{
lang:'',
msg:''
}
],
rechargeType:1,
rechargePopPromptDefault: [
{
lang:'',
msg:'',
}
],
rechargePopPrompt:[
{
lang:'',
msg:''
}
],
})
const rules = {
memberAccount: [{ required: true, message: proxy.t('请选择是否开启'), trigger: 'change' }],
password: [{ required: true, message: proxy.t('请选择是否开启'), trigger: 'change' }],
rechargeCnt: [{ required: true, message: proxy.t('请输入数字'), trigger: 'change' }],
}
const formRef = ref(null)
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
if (valid) {
loadingButton.value = true;
if (JSON.stringify(formAll) != oldForm.value) {
platform.postGameConfig(formAll).then(response => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功'));
cancel()
}).catch(() => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
cancel()
}
}
});
}
const showModal = () => {
getConfig()
open.value = true
}
const cancel = () => {
open.value = false
}
const getConfig = async () => {
await platform.gameConfig().then(res => {
Object.assign(formAll, res.data);
setTimeout(() => {
let objForm = { ...formAll }
oldForm.value = JSON.stringify(objForm);
}, 500);
})
}
defineExpose({ showModal })
</script>
<style scoped lang="scss">
.textarea-like {
width: 90%;
height: 100px;
min-height: 100px; /* 设置最小高度 */
border: 1px solid #ccc;
padding: 5px;
overflow-y: auto; /* 添加滚动条 */
resize: vertical; /* 允许垂直方向上拖动调整高度 */
}
.textarea-like[disabled] {
background-color: #f5f5f5; /* 设置禁用时的背景颜色为灰色 */
color: #aaa; /* 设置禁用时的文本颜色为灰色 */
cursor: not-allowed; /* 设置禁用时的鼠标指针为禁止图标 */
}
</style>

View File

@ -0,0 +1,325 @@
<template>
<el-dialog :title="t('有效投注配置')" v-model="open" width="800px" append-to-body align-center>
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="260px" class="add-form">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="有效类型有效投注设置" name="bettingSettings"></el-tab-pane>
<el-tab-pane label="不计入有效投注的有效(既排除)" name="validBets"></el-tab-pane>
</el-tabs>
<div v-if="activeName == 'bettingSettings'">
<div class="formBetting-box">
<el-form-item :label="t('体育默认比例(0-100)')" prop="sportsRatio">
<NumberInput v-model="formAll.sportsRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item label-width="0" class="clt-item">
<span slot="label" class="label-box">
{{ t('输赢绝对值计算有效投注') }}
<icon-tips width="300"> {{ t('开启后,以会员的输赢分绝对值作为有效投注,例如: 以香港盘赔率0.7的盘口为例A投注100注单结果为输输赢值-100 则A的有效投注额为100。B投注100注单结果为赢 输赢值70则B的有效投注额为70。') }}</icon-tips>
</span>
<div class="item-right">
<el-switch :active-value="true" @change="changeSwitch('sportsAbs')" :inactive-value="false" style="margin-right: 10px; --el-switch-on-color: #13ce66;"
inline-prompt
active-text="开"
inactive-text="关"
v-model="formAll.sportsAbs" />
</div>
</el-form-item>
<el-form-item label-width="0" class="clt-item">
<span slot="label" class="label-box">
{{ t('取最小值作为有效投注') }}
<icon-tips width="300"> {{ t('开启后,有效投注将在投注金额和输赢金额绝对值之间取小的值,举例: 以香港盘赔率0.2盘口及赔率1.5盘口为例, D投注赔率0.2盘口500注单结果为赢输点值100则D的有效投注额为100(即取输赢金额作为有效投注)。 E投注赔率15盘口500注单结果为赢输赢值750。则E的有效投注额为500(即取投注金额作为有效投注)。') }}</icon-tips>
</span>
<div class="item-right">
<el-switch :active-value="true" @change="changeSwitch('sportsMin')" :inactive-value="false" style="margin-right: 10px; --el-switch-on-color: #13ce66;"
inline-prompt
active-text="开"
inactive-text="关"
v-model="formAll.sportsMin" />
</div>
</el-form-item>
<!-- <el-form-item label-width="0" class="clt-item" prop="sportsMaxOddsValue">
<span slot="label" class="label-box">
{{ t('按最大赔率计算有效投注') }}
<icon-tips width="300"> {{ t(`开启后,需要设定最大赔率,若会员为赢,且所赢的赔率大于倍率封顶值,则按封顶最大值作为有效投注。举例:
以香港盘设定最大倍率封顶值为1.0最终开奖赔率1.5的盘口为例
C投注200注单结果为赢输赢值300则有效投注额为200*1.0=200
[按最大倍率计算有效投注低赔率不计算有效投注皆开启时最大赔率设定值不可小于最小赔率的设定值`) }}</icon-tips>
</span>
<div class="item-right">
<el-switch :active-value="true" :inactive-value="false" style="margin-right: 10px; --el-switch-on-color: #13ce66;"
inline-prompt
active-text="开"
inactive-text="关"
v-model="formAll.sportsMaxOdds" />
<NumberInput v-if="formAll.sportsMaxOdds" v-model="formAll.sportsMaxOddsValue" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</div>
</el-form-item>
<el-form-item label-width="0" class="clt-item" prop="sportsMinOddsValue">
<span slot="label" class="label-box">
{{ t('低赔率不计算有效投注') }}
<icon-tips width="300"> {{ t(`开启后需要设定不计算有效投注的最小赔率若会员为赢且赔率小于等于此不计算有效投注的最小赔率则该局有效投注直接按0计以免通过低赔率刷流水。
举例:以香港盘不计算有效投注的最小赔率设置为0.5赔率为0.4的盘口为例
F投注300注单结果为赢输赢值120因赔率0.4小于所设置的最小值05所以该局的有效投注为0(即不计入)
*按最大倍率计算有效投注低赔率不计算有效投注皆开启时最大赔率设定值不可小于最小赔率的设定值`) }}</icon-tips>
</span>
<div class="item-right">
<el-switch :active-value="true" :inactive-value="false" style="margin-right: 10px; --el-switch-on-color: #13ce66;"
inline-prompt
active-text="开"
inactive-text="关"
v-model="formAll.sportsMinOdds" />
<NumberInput v-if="formAll.sportsMinOdds" v-model="formAll.sportsMinOddsValue" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</div>
</el-form-item> -->
</div>
<el-form-item :label="t('棋牌默认比例(0-100)')" prop="cardRatio">
<NumberInput v-model="formAll.cardRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('捕鱼默认比例(0-100)')" prop="fishingRatio">
<NumberInput v-model="formAll.fishingRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('电子默认比例(0-100)')" prop="electronicRatio">
<NumberInput v-model="formAll.electronicRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('真人默认比例(0-100)')" prop="videoRatio">
<NumberInput v-model="formAll.videoRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('斗鸡默认比例(0-100)')" prop="cockfightingRatio">
<NumberInput v-model="formAll.cockfightingRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('电竞默认比例(0-100)')" prop="esportsRatio">
<NumberInput v-model="formAll.esportsRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
<el-form-item :label="t('彩票默认比例(0-100)')" prop="lotteryRatio">
<NumberInput v-model="formAll.lotteryRatio" style="width: 180px;">
<template #append>%</template>
</NumberInput>
</el-form-item>
</div>
<div v-if="activeName == 'validBets'">
<platform-selection-tree style="width: 100%; margin-top: 5px;"
@selectPlatform="selectPlatform('auditPlatform',$event)"
:auditPlatform="formAll.auditPlatform"></platform-selection-tree>
</div>
<!-- <el-form-item :label="t('仅限已首充会员强制下载APP')" prop="gameRechargeDownloadApp">
<el-radio-group v-model="formAll.gameRechargeDownloadApp">
<el-radio value="2">{{ t('开启(仅限已首充会员)') }}</el-radio>
<el-radio value="1">{{ t('关闭(全部限制)') }}</el-radio>
</el-radio-group>
</el-form-item> -->
<!-- <el-form-item :label="t('仅限Android设备强制下载APP')" prop="gameAndroidDownloadApp">
<el-radio-group v-model="formAll.gameAndroidDownloadApp">
<el-radio value="2">{{ t('开启(推荐)') }}</el-radio>
<el-radio value="1">{{ t('关闭(所有设备都限制)') }}</el-radio>
</el-radio-group>
</el-form-item> -->
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" v-hasPermi="['game:turnover:config:add']" @click="submitForm" :loading="loadingButton">{{ t(' ') }}</el-button>
<el-button @click="cancel">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import * as platform from "@/api/game/platform";
import NumberInput from "@/components/NumberInput"; //
import CustomSelect from "@/components/CustomSelect"; //
import PlatformSelection from "@/components/PlatformSelection"; //
import PlatformSelectionTree from "@/components/PlatformSelectionTree";
import IconTips from "@/components/IconTips"; //
const { proxy } = getCurrentInstance();
import { getLocalStorage } from "@/utils/auth";
const langListRaw = getLocalStorage('langList') || []
const langList = Array.from(
new Map(
langListRaw.map(item => [item.countryLang, {
label: item.name,
value: item.countryLang
}])
).values()
) //
const emits = defineEmits([])
const open = ref(false);
const activeName = ref('bettingSettings');
const activeNameLang = ref(localStorage.getItem('lang')|| 'zh-CN');
const forcePopNameLang = ref(localStorage.getItem('lang')|| 'zh-CN');
const loadingButton = ref(false);
const oldForm = shallowRef({ });
const formAll = reactive({
})
const validateNumberInRange = (rule, value, callback) => {
const num = Number(value);
if (isNaN(num)) {
callback(new Error(proxy.t('请输入数字')));
} else if (num < 0 || num > 100) {
callback(new Error(proxy.t('请输入 0 到 100 之间的数字')));
} else {
callback();
}
}
const rules = {
sportsRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
cardRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
fishingRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
electronicRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
videoRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
cockfightingRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
esportsRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
lotteryRatio: [
{ validator: validateNumberInRange, trigger: 'change' }
],
sportsMaxOddsValue: [
{ validator: validateNumberInRange, trigger: 'change' }
],
sportsMinOddsValue: [
{ validator: validateNumberInRange, trigger: 'change' }
]
}
const formRef = ref(null)
const submitForm = () => {
proxy.$refs["formRef"].validate(valid => {
if (valid) {
loadingButton.value = true;
let dataArr = JSON.parse(formAll.auditPlatform);
let obj = {
...formAll,
gamePlatformTreeResultDTO:dataArr
}
delete obj.auditPlatform;
if (JSON.stringify(obj) != oldForm.value) {
platform.postGameTurnoverConfig(obj).then(response => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功'));
cancel()
}).catch(() => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
cancel()
}
}
});
}
const handleClick = (tab, event) => {
}
const changeSwitch = (val) => {
if (val == 'sportsAbs'){
if (formAll.sportsAbs) {
formAll.sportsMin = false
}
}else if (val == 'sportsMin'){
if (formAll.sportsMin) {
formAll.sportsAbs = false
}
}
}
const showModal = () => {
getConfig()
open.value = true
}
//
const selectPlatform = (type,val) => {
formAll.auditPlatform = val;
}
const cancel = () => {
open.value = false
}
const getConfig = async () => {
await platform.gameTurnoverConfig().then(res => {
Object.assign(formAll, res.data);
formAll.auditPlatform = JSON.stringify(res.data.gamePlatformTreeResultDTO);
setTimeout(() => {
let dataArr = JSON.parse(formAll.auditPlatform);
let obj = {
...formAll,
gamePlatformTreeResultDTO:dataArr
}
delete obj.auditPlatform;
oldForm.value = JSON.stringify(obj);
}, 500);
})
}
defineExpose({ showModal })
</script>
<style scoped lang="scss">
.textarea-like {
width: 90%;
height: 100px;
min-height: 100px; /* 设置最小高度 */
border: 1px solid #ccc;
padding: 5px;
overflow-y: auto; /* 添加滚动条 */
resize: vertical; /* 允许垂直方向上拖动调整高度 */
}
.textarea-like[disabled] {
background-color: #f5f5f5; /* 设置禁用时的背景颜色为灰色 */
color: #aaa; /* 设置禁用时的文本颜色为灰色 */
cursor: not-allowed; /* 设置禁用时的鼠标指针为禁止图标 */
}
.formBetting-box{
border:1px solid #ccc;
border-radius: 5px;
padding-top: 10px;
}
.clt-item {
.label-box {
vertical-align: middle;
width: 260px;
text-align: right;
padding-right: 12px;
word-break: break-all;
line-height: 20px;
box-sizing: border-box;
}
:deep(.el-form-item__error) {
padding-left: 260px;
}
.item-right {
width: calc(100% - 260px);
}
}
</style>

View File

@ -0,0 +1,294 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<el-form-item prop="currencyCode">
<currency-select style="width: 200px;" v-model="queryParams.currencyCode" @change="handleQuery"></currency-select>
</el-form-item>
<el-form-item prop="platformType">
<custom-select v-model="queryParams.platformType" style="width: 200px;" :options="gameTypeOptions" :clearable="false"></custom-select>
</el-form-item>
<el-form-item prop="platformName">
<el-input v-model="queryParams.platformName" :placeholder="t('请输入平台名称')" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item prop="platformJump">
<el-select v-model="queryParams.platformJump" style="width: 200px;" :placeholder="t('请选择平台跳转方式')">
<el-option v-for="dict in jump_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</template>
<template #right>
</template>
</table-search-card>
<el-table v-loading="loading" :data="platformList" @selection-change="handleSelectionChange" class="c-table-main"
stripe ref="dragTable" row-key="id" border>
<el-table-column type="selection" width="55" align="center" />
<table-drag-sort v-model:tableList="platformList" @dragEnd="dragEnd"></table-drag-sort>
<el-table-column :label="t('平台ID')" align="center" prop="id" />
<el-table-column :label="t('平台名称')" align="center" prop="platformName" />
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
<el-table-column :label="t('维护开关')" align="center" prop="stopStatus" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.stopStatus" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'stopStatus')" />
</template>
</el-table-column>
<el-table-column :label="t('平台开关')" align="center" prop="platformStatus" label-class-name="text-warning">
<template #default="{ row }">
<base-switch v-model="row.platformStatus" :active-value="1" :inactive-value="2"
:before-change="() => beforeSwitchChange(row, 'platformStatus')"
activeText="开"
inactiveText="关"
style="--el-switch-on-color: #00a854; --el-switch-off-color: #ff4949" />
</template>
</el-table-column>
<el-table-column :label="t('子游戏数量')" align="center" prop="gameCount" width="110">
<template #default="{ row }">
<el-row justify="center">
<span v-if="!['8','7','6','3','9'].includes(row.platformType)">
<el-text style="width: 30px;margin-right: 10px;">{{ row.gameCount }}</el-text>
<el-link type="primary" :underline="false" @click="toGameManage(row)">{{ t('') }}</el-link>
</span>
<span v-else>--</span>
</el-row>
</template>
</el-table-column>
<el-table-column align="center" prop="minAmount" width="110">
<template #header>
<span>{{ t('最低准入') }}</span>
<IconTips>{{ t('准入必须大于注册赠送,防止被套利') }}</IconTips>
</template>
<template #default="{ row }">
{{ row.minAmount || '--' }}
</template>
</el-table-column>
<el-table-column :label="t('宣传图')" align="center" prop="popularStyle" width="100">
<template #default="scope">
<div v-if="scope.row.promotionalStyle == 1">
<image-preview :src="scope.row.popularStyle" :width="50" :height="50" />
</div>
<div v-if="scope.row.promotionalStyle == 2">
<image-preview :src="scope.row.customPopularStyle" :width="50" :height="50" />
</div>
</template>
</el-table-column>
<el-table-column :label="t('平台跳转方式')" align="center" width="250">
<template #default="{ row }">
<el-row justify="space-between">
<span>IOS:{{ row.iosJump === 1 ? t('内嵌') : t('外链') }}</span>
<span>Android:{{ row.androidJump === 1 ? t('内嵌') : t('外链') }}</span>
<span>H5:{{ row.h5Jump === 1 ? t('内嵌') : t('外链') }}</span>
</el-row>
</template>
</el-table-column>
<el-table-column :label="t('操作')" align="center" class-name="small-padding fixed-width" width="110">
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)"
v-hasPermi="['game:platform:edit']">{{ t('修改') }}</el-button>
<el-button link type="primary" @click="handleSynchronous(scope.row)"
v-hasPermi="['game:platform:sync']">{{ t('同步') }}</el-button>
</template>
</el-table-column>
<!-- <table-operation></table-operation> -->
<el-table-column :label="t('操作时间')" align="center" prop="createTime" width="180">
<template #default="{ row }">
{{ formatTime(row.createTime) }}
</template>
</el-table-column>
</el-table>
<BettingConfiguration v-if="lodingShow" ref="bettingConfigurationRef"></BettingConfiguration>
<add-dialog v-if="isShowDialog"
:addEditStatus="addEditStatus" :modifyDate="modifyDate" @submit="getList"
v-model:show="isShowDialog"></add-dialog>
</template>
<script setup name="Platform">
import AddDialog from "./components/AddDialog"///
import * as platform from "@/api/game/platform";
import GameRestrictions from "./components/GameRestrictions.vue"
import BettingConfiguration from "./components/bettingConfiguration.vue"
import useInitDataStore from "@/store/modules/initData";
import baseSwitch from "@/components/BaseSwitch";
import ImagePreview from "@/components/ImagePreview";
import TableDragSort from '@/components/TableDragSort';
import IconTips from "@/components/IconTips";
import CurrencySelect from "@/components/CurrencySelect";
import DictSelect from "@/components/DictSelect";
import CustomSelect from "@/components/CustomSelect";
import { formatTime } from '@/utils/ruoyi'; //
import { nextTick, ref } from "vue";
const emits = defineEmits(["toGameManage"]);
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const { ff_game_type } = proxy.useDict('ff_game_type');
const jump_type = ref([
{ label: '内链', value: '1' },
{ label: '外链', value: '2' },
]);
const gameTypeOptions = ref([
{ label: '电子', value: '1' },
{ label: '棋牌', value: '2' },
{ label: '真人', value: '3' },
{ label: '捕鱼', value: '4' },
{ label: '体育', value: '6' },
{ label: '斗鸡', value: '7' },
{ label: '电竞', value: '8' },
{ label: '彩票', value: '9' },
{ label: '区块链', value: '10' },
]);
const platformList = ref([]);
const open = ref(false);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const title = ref("");
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 1000,
orderByColumn: 'sort_no',
isAsc: 'asc',
platformJump: null,
currencyCode: 'VND',
platformType: '1',
platformName: null,
},
rules: {
platformName: [
{ required: true, message: proxy.t('平台名称不能为空'), trigger: "blur" }
],
}
});
//platformType
ff_game_type.forEach((item,index) => {
if(index == 0){
//useInitData.dictInitData.platformType使
data.queryParams.platformType = useInitData.dictInitData.platformType || item.value
}
})
const { queryParams, form, rules } = toRefs(data);
/** 查询平台管理列表 */
function getList() {
loading.value = true;
platform.listPlatform(queryParams.value).then(response => {
platformList.value = response.rows;
nextTick(() => {
loading.value = false;
});
});
}
//
function reset() {
form.value = {
id: null
};
proxy.resetForm("platformRef");
}
/** 搜索按钮操作 */
function handleQuery() {
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
queryParams.value.platformType = useInitData.dictInitData.platformType
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
const addEditStatus = ref('add'), isShowDialog = ref(false), editDataId = ref(''),modifyDate = ref({});
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const _id = row.id || ids.value
platform.getPlatform(_id).then(response => {
modifyDate.value = response.data;
isShowDialog.value = true;
addEditStatus.value = 'edit'
title.value = proxy.t('修改平台管理');
});
// proxy.$modal.msgError("")
}
const handleSynchronous = (row) => {
proxy.$modal.confirm(proxy.t('当前设置宣传图同步到所有币种下生效')).then(() => {
platform.gamePlatformSync({id:row.id}).then(() => {
proxy.$modal.msgSuccess(proxy.t('同步成功'));
getList();
})
}).catch(() => {})
}
//
const dragEnd = (row) => {
platform.platformSort(row).then(() => {
if (row.isTop) {
proxy.$modal.msgSuccess(proxy.t('置顶成功'));
}
getList();
})
}
//
const beforeSwitchChange = async (row, undateKeys) => {
const _status = row[undateKeys] === 1 ? 2 : 1
const _data = {
id: row.id
}
_data[undateKeys] = _status
try {
await platform.updatePlatformSwitch(_data).then(() => {
proxy.$modal.msgSuccess(_status === 1 ? proxy.t('开启成功') : proxy.t('关闭成功'))
getList()
})
return true;
} catch (error) {
console.error(proxy.t('接口调用失败'), error);
return false; //
}
}
//
const toGameManage = (row) => {
const { id, platformType,currencyCode } = row
useInitData.setStateData('currencyCode', String(currencyCode))
useInitData.setStateData('platformId', String(id))
useInitData.setStateData('platformType', String(platformType))
emits('toGameManage')
}
const bettingConfigurationRef = ref(null);
const lodingShow = ref(true);
const openBettingConfiguration = () => {
lodingShow.value = false;
nextTick(() => {
lodingShow.value = true;
nextTick(()=>{
bettingConfigurationRef.value.showModal();
})
})
}
watch(() => queryParams.value.platformType, (newValue) => {
if (newValue) {
getList()
}
}, { immediate: true });
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,213 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<el-form-item prop="currencyCode">
<currency-select v-model="queryParams.currencyCode" @change="handleQuery"></currency-select>
</el-form-item>
<el-form-item prop="platformType">
<dict-select v-model="queryParams.platformType" dictKey="ff_game_type" :empty-values="[null, undefined]"
:clearable="false" :addOptions="{ label: t('全部类型'), value: '' }"></dict-select>
</el-form-item>
<el-form-item prop="popularCategory">
<el-select v-model="queryParams.popularCategory" :empty-values="[null, undefined]">
<el-option v-for="item in popularCategoryList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item prop="name">
<el-input v-model="queryParams.name" :placeholder="t('请输入平台/子游戏名称')" @keyup.enter="handleQuery" />
</el-form-item>
</template>
<template #right>
{{ t('是否启用') }}
<el-switch
v-model="IsEnabledOne"
v-if="popularType == 1"
active-value="2" inactive-value="1"
class="ml-2"
@click="handleUp(1)"
style="--el-switch-on-color: #13ce66; margin-left: 4px;"
/>
<el-switch
v-model="IsEnabledTow"
v-if="popularType == 2"
active-value="2" inactive-value="1"
class="ml-2"
@click="handleUp(2)"
style="--el-switch-on-color: #13ce66; margin-left: 4px;"
/>
</template>
</table-search-card>
<el-table v-loading="loading" :data="gameList" @selection-change="handleSelectionChange" class="c-table-main" stripe
ref="dragTable" row-key="id" border>
<el-table-column type="selection" width="55" align="center" />
<table-drag-sort v-model:tableList="gameList" @dragEnd="dragEnd"></table-drag-sort>
<el-table-column :label="t('游戏类型')" align="center" prop="platformType">
<template #default="{ row }">
<dict-tag :options="ff_game_type" :value="row.platformType" />
</template>
</el-table-column>
<el-table-column :label="t('热门类别')" align="center" prop="popularCategory">
<template #default="{ row }">
{{ row.popularCategory === 1 ? t('平台') : t('子游戏') }}
</template>
</el-table-column>
<el-table-column :label="t('平台名称')" align="center" prop="platformName" />
<el-table-column :label="t('热门名称')" align="center" prop="gameName" />
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
<el-table-column :label="t('操作')" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleDelete(scope.row)"
v-hasPermi="['game:game:edit']">{{ t('移除') }}</el-button>
</template>
</el-table-column>
<table-operation></table-operation>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</template>
<script setup name="Popular">
import * as game from "@/api/game/game";
import useInitDataStore from "@/store/modules/initData";
import TableDragSort from '@/components/TableDragSort';
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const { ff_game_type } = proxy.useDict('ff_game_type')
const emits = defineEmits(['updateGames']); //
const props = defineProps({
//
// 1:1 2:2
popularType: {
type: Number,
default: 1,
required: true
},
hotOne: {
type: String,
default: '1',
},
hotTwo: {
type: String,
default: '1',
}
})
const gameList = ref([]); //
const loading = ref(true);//
const ids = ref([]);//
const single = ref(true);//
const IsEnabledOne = ref('1');//
const IsEnabledTow = ref('1');//
const multiple = ref(true); //
const total = ref(0); //
const data = reactive({
form: {},
queryParams: { //
pageNum: 1,
pageSize: 20,
orderByColumn: 'sort_no',
isAsc: 'asc',
currencyCode: useInitData.dictInitData.currencyCode||useInitData.currencyCode,
platformType: '',
popularCategory: '',
name: null,
popularType: null
},
rules: {
},
popularCategoryList: [
{
label: proxy.t('热门类别'),
value: ''
},
{
label: proxy.t('平台'),
value: '1'
},
{
label: proxy.t('子游戏'),
value: '2'
}
]
});
const { queryParams, form, rules, popularCategoryList } = toRefs(data);
/** 查询热门管理列表 */
function getList() {
loading.value = true;
queryParams.value.popularType = props.popularType
game.listPopular(queryParams.value).then(response => {
gameList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
}
const handleUp = (type)=>{
emits('updateGames', type);
}
// props.hotOne,props.hotTwotrue false,1false 2true
watch(() => [props.hotOne, props.hotTwo], ([hotOne, hotTwo]) => {
nextTick(() => {
IsEnabledOne.value = hotOne;
IsEnabledTow.value = hotTwo;
});
},{ immediate: true })
/** 重置按钮操作 */
function resetQuery() {
queryParams.value.pageNum = 1;
getList();
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 移除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm(proxy.t('是否确认移除"') + row.gameName + '"').then(function () {
return game.delPopular(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess(proxy.t('移除成功'));
}).catch(() => { });
}
//
const dragEnd = (row) => {
game.popularSort(row).then(() => {
if (row.isTop) {
proxy.$modal.msgSuccess(proxy.t('置顶成功'));
}
getList();
})
}
// popularType
watch(() => props.popularType, (newVal, oldVal) => {
//
resetQuery();
});
getList();
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,140 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<el-form-item prop="currencyCode" class="w120px">
<currency-select v-model="queryParams.currencyCode" @change="handleQuery"></currency-select>
</el-form-item>
<el-form-item prop="gameType">
<dict-select v-model="queryParams.gameType" dictKey="ff_game_type" :empty-values="[null, undefined]"
:clearable="false" :addOptions="{ label: t('全部类型'), value: '' }" @change="gameTypeChange"></dict-select>
</el-form-item>
<el-form-item prop="platformId">
<el-select v-model="queryParams.platformId" :empty-values="[null, undefined]">
<el-option v-for="item in platformList" :key="item.id" :label="item.platformName" :value="item.id" />
</el-select>
</el-form-item>
</template>
</table-search-card>
<el-table v-loading="loading" :data="gameList" @selection-change="handleSelectionChange" class="c-table-main" stripe
ref="dragTable" row-key="id" border>
<el-table-column :label="t('投注时间')" align="center" prop="wagersTime">
<template #default="{ row }">
{{ formatTime(row.wagersTime) }}
</template>
</el-table-column>
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
<el-table-column :label="t('游戏类型')" align="center" prop="gameType" >
<template #default="{ row }">
<dict-text dictKey="ff_game_type" :value="`${row.gameType}`"></dict-text>
</template>
</el-table-column>
<el-table-column :label="t('平台ID')" align="center" prop="platformId" />
<el-table-column :label="t('平台名称')" align="center" prop="platformName" />
<el-table-column :label="t('游戏ID')" align="center" prop="gameId" />
<el-table-column :label="t('子游戏名称')" align="center" prop="gameName" />
<el-table-column :label="t('注单排名')" align="center" prop="ranking" />
<el-table-column :label="t('注单量')" align="center" prop="orderCnt" />
<el-table-column :label="t('总投注')" align="center" prop="betAmountSum" />
<el-table-column :label="t('有效投注')" align="center" prop="turnoverSum" />
<el-table-column :label="t('盈亏')" align="center" prop="surplusSum" />
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</template>
<script setup name="Popular">
import * as game from "@/api/game/game";
import useInitDataStore from "@/store/modules/initData";
import TableSearchDate from "@/components/TableSearchDate";
import { platformSelect } from "@/api/game/platform";
import DictText from "@/components/DictText";
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const gameList = ref([]);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 20,
beginWagersTime: '',
endWagersTime: '',
currencyCode: useInitData.dictInitData.currencyCode||useInitData.currencyCode,
gameType: '',
platformId: ''
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询热门管理列表 */
function getList() {
loading.value = true;
game.listRanking(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
gameList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
}
/** 重置按钮操作 */
function resetQuery() {
queryParams.value.pageNum = 1;
dateRange.value = []
operateTimeType.value = 'month'
getList();
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
//
const platformList = ref([])
const platformListInit = () => {
platformSelect({ platformType: queryParams.value.gameType,currencyCode:queryParams.value.currencyCode }).then(res => {
res.data.unshift({ platformName: proxy.t('全部平台'), id: '' })
platformList.value = res.data
})
}
//
const gameTypeChange = () => {
queryParams.value.pageNum = 1;
platformListInit()
}
//
const dateRange = ref([])
const operateTimeType = ref('day')
platformListInit();
//
onMounted(() => {
getList();
});
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,96 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="handleQuery">
<template #left>
<el-form-item prop="currencyCode">
<currency-select v-model="queryParams.currencyCode" @change="handleQuery"></currency-select>
</el-form-item>
<el-form-item prop="gameType">
<dict-select v-model="queryParams.gameType" dictKey="ff_game_type" :empty-values="[null, undefined]"
:clearable="false" :addOptions="{ label: t('全部类型'), value: '' }"></dict-select>
</el-form-item>
<el-form-item prop="gameName">
<el-input v-model="queryParams.gameName" :placeholder="t('请输入子游戏名称')" @keyup.enter="handleQuery" />
</el-form-item>
</template>
</table-search-card>
<el-table v-loading="loading" :data="gameList" @selection-change="handleSelectionChange" class="c-table-main" stripe
ref="dragTable" row-key="id" border>
<el-table-column :label="t('游戏类型')" align="center" prop="gameType">
<template #default="{ row }">
<dict-tag :options="ff_game_type" :value="row.gameType" />
</template>
</el-table-column>
<el-table-column :label="t('热门类别')" align="center" prop="platformSourceType">
<template #default="{ row }">
{{ row.popularCategory === 1 ? t('平台') : t('子游戏') }}
</template>
</el-table-column>
<el-table-column :label="t('平台名称')" align="center" prop="platformName" />
<el-table-column :label="t('热门名称')" align="center" prop="gameName" />
<el-table-column :label="t('币种')" align="center" prop="currencyDisplay" />
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</template>
<script setup name="System">
import * as game from "@/api/game/game";
import useInitDataStore from "@/store/modules/initData";
const useInitData = useInitDataStore();
const { proxy } = getCurrentInstance();
const { ff_game_type } = proxy.useDict('ff_game_type')
const gameList = ref([]);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 20,
currencyCode: useInitData.dictInitData.currencyCode||useInitData.currencyCode,
gameType: '',
gameName: null
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询系统热门列表 */
function getList() {
loading.value = true;
game.listSystem(queryParams.value).then(response => {
gameList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
getList();
</script>
<style scoped lang="scss"></style>

View File

@ -1,7 +1,7 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form>
@ -114,7 +114,7 @@ const noticeTypeArr = ref([
{ label: proxy.t('日常公告'), value: '1' },
{ label: proxy.t('不停机维护'), value: '2' },
])
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const data = reactive({
form: {},
queryParams: {
@ -173,11 +173,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//
onMounted(() => {

View File

@ -1,7 +1,7 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form>
@ -110,7 +110,7 @@ const noticeTypeArr = ref([
{ label: proxy.t('日常公告'), value: '1' },
{ label: proxy.t('不停机维护'), value: '2' },
])
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const data = reactive({
form: {},
queryParams: {
@ -170,11 +170,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//
onMounted(() => {

View File

@ -1,7 +1,7 @@
<template>
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
<template #left>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form>
@ -110,7 +110,7 @@ const noticeTypeArr = ref([
{ label: proxy.t('日常公告'), value: '1' },
{ label: proxy.t('不停机维护'), value: '2' },
])
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const data = reactive({
form: {},
queryParams: {
@ -170,11 +170,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//
onMounted(() => {

View File

@ -85,7 +85,8 @@
<table-operation></table-operation>
<el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleStop(scope.row)" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<el-button link type="primary" @click="handleStop(scope.row)" v-if="scope.row.status == 1" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<el-button link type="primary" v-if="scope.row.status == 2 || scope.row.status == 3" @click="handleOpen(scope.row)" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<!-- <el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button>
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button> -->
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button>
@ -110,7 +111,7 @@
<script setup name="Agent">
import { listAgent, createAgent, selectPlatform } from "@/api/agent";
import { superTenantQuotaflow,superCommonCurrencySelect,superCommonPlatformTypeSelect,getSuperBetlist } from "@/api/super/tenant";
import {getMaintenanceList,postMaintenanceStop} from "@/api/siteManagement";
import {getMaintenanceList,postMaintenanceStop,postMaintenanceOpen} from "@/api/siteManagement";
import CustomSelect from '@/components/CustomSelect'
import CheckboxSelect from "@/components/CheckboxSelect"; //
import TableSearchDate from '@/components/TableSearchDate'
@ -293,7 +294,18 @@ superCommonPlatformTypeSelect().then(response => {
showLoding2.value = true;
});
}
const handleOpen = (row) => {
proxy.$modal.confirm(proxy.t('确认此操作,是否继续?')).then(() => {
let obj = {
id: row.id,
}
return postMaintenanceOpen(obj);
}).then(() => {
getList();
proxy.$modal.msgSuccess(proxy.t('站点启用成功!'));
}).catch(() => { });
};
const getJobStatusName =(val) => {
const status = sys_job_status.value.find(item => item.value == val);
return status ? status.label : '未知状态';

View File

@ -250,7 +250,7 @@ const handleOpen = (row) => {
return postMaintenanceOpen(obj);
}).then(() => {
getList();
proxy.$modal.msgSuccess(proxy.t('站点注销成功!'));
proxy.$modal.msgSuccess(proxy.t('站点启用成功!'));
}).catch(() => { });
};

View File

@ -124,7 +124,7 @@
<table-operation></table-operation>
<el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleStop(scope.row)" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<el-button link type="primary" @click="handleStop(scope.row)" v-if="scope.row.status == 1" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<!-- <el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button>
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button> -->
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button>

View File

@ -124,7 +124,8 @@
<table-operation></table-operation>
<el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleStop(scope.row)" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<el-button link type="primary" @click="handleStop(scope.row)" v-if="scope.row.status == 1" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<el-button link type="primary" v-if="scope.row.status == 2 || scope.row.status == 3" @click="handleOpen(scope.row)" v-hasPermi="['site:maintenance:stop']">{{ t('') }}</el-button>
<!-- <el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button> -->
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('') }}</el-button>
</template>
@ -148,7 +149,7 @@
<script setup name="Agent">
import { listAgent, createAgent, selectPlatform } from "@/api/agent";
import { superTenantQuotaflow,superCommonCurrencySelect,superCommonPlatformTypeSelect,getSuperBetlist } from "@/api/super/tenant";
import {getMaintenanceList,postMaintenanceStop} from "@/api/siteManagement";
import {getMaintenanceList,postMaintenanceStop,postMaintenanceOpen} from "@/api/siteManagement";
import CustomSelect from '@/components/CustomSelect';
import CheckboxSelect from "@/components/CheckboxSelect"; //
import TableSearchDate from '@/components/TableSearchDate'
@ -327,7 +328,18 @@ superCommonPlatformTypeSelect().then(response => {
showLoding2.value = true;
});
}
const handleOpen = (row) => {
proxy.$modal.confirm(proxy.t('确认此操作,是否继续?')).then(() => {
let obj = {
id: row.id,
}
return postMaintenanceOpen(obj);
}).then(() => {
getList();
proxy.$modal.msgSuccess(proxy.t('站点启用成功!'));
}).catch(() => { });
};
const getJobStatusName =(val) => {
const status = sys_job_status.value.find(item => item.value == val);
return status ? status.label : '未知状态';

View File

@ -1,62 +1,87 @@
<template>
<!-- 详情 -->
<el-dialog :title="t('额度修改')" :close-on-click-modal="false" align-center v-model="showDialog" width="700px" append-to-body>
<el-dialog :title="t('绑定api租户')" :close-on-click-modal="false" align-center v-model="showDialog" width="900px" style="height: 700px;" append-to-body>
<el-scrollbar max-height="700px" >
<div style="display: flex;justify-content: space-between;margin-bottom: 10px;">
<div></div>
<div>
<el-button type="primary" @click="handleAdd">{{t('')}}</el-button>
</div>
</div>
<el-table class="c-table-main" height="530px" :data="tenantList" border>
<el-table-column :label="t('租户KEY')" align="center" min-width="120" prop="tenantKey">
<template #default="{ row }">
{{ row.tenantKey }}
</template>
</el-table-column>
<el-table-column :label="t('租户密钥')" align="center" min-width="120" prop="secretKey">
<template #default="{ row }">
{{ row.secretKey}}
</template>
</el-table-column>
<el-table-column :label="t('币种')" align="center" min-width="120" prop="currencyCode">
<template #default="{ row }">
{{ row.currencyCode}}
</template>
</el-table-column>
<el-table-column :label="t('操作时间')" align="center" min-width="120" prop="currencyCode">
<template #default="{ row }">
{{ row.updateTime ? formatTime(row.updateTime): formatTime(row.createTime) }}
</template>
</el-table-column>
<el-table-column :label="t('操作')" align="center" min-width="120" prop="quota">
<template #default="{ row }">
<el-button @click="handleEdit(row)" type="primary">{{t('修改')}}</el-button>
<el-button @click="handleDelect(row)" type="primary">{{t('删除')}}</el-button>
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="150px" class="site-form">
<el-form-item label="租户id" prop="tenantKey">
<el-input v-model="formAll.tenantKey" placeholder="请输入租户id" />
</el-form-item>
<el-form-item label="密钥" prop="secretKey">
<el-input v-model="formAll.secretKey" placeholder="请输入密钥" />
</el-form-item>
<el-form-item label="日期" prop="ShowStartTime">
<el-date-picker
style="width: 600px;"
v-model="formAll.ShowStartTime"
type="datetimerange"
range-separator="-"
:start-placeholder="t('开始时间')"
:end-placeholder="t('结束时间')"
/>
</el-form-item>
</el-form>
</template>
</el-table-column>
</el-table>
</el-scrollbar>
<template #footer>
<div class="dialog-footer" style="display: flex;justify-content: center;">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="closeDialog">{{ t(' ') }}</el-button>
<!-- <el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button> -->
<el-button @click="closeDialog">{{ t(' ') }}</el-button>
</div>
</template>
<el-dialog :title="addStatus == 'add'?t('新增租户'):t('修改租户')" align-center v-model="showDialogTenant" width="700px" append-to-body>
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="150px" class="site-form">
<el-form-item label="租户KEY" prop="tenantKey">
<el-input v-model="formAll.tenantKey" placeholder="请输入租户KEY" />
</el-form-item>
<el-form-item label="租户密钥" prop="secretKey">
<el-input v-model="formAll.secretKey" placeholder="请输入密钥" />
</el-form-item>
<el-form-item label="币种" prop="currencyCode">
<custom-select v-model="formAll.currencyCode" :options="currencySelectArr" style="width: 100%;"></custom-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer" style="display: flex;justify-content: center;">
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
<el-button @click="closeDialog1">{{ t(' ') }}</el-button>
</div>
</template>
</el-dialog>
</el-dialog>
</template>
<script setup>
import { formatTime,finalTimestamp } from '@/utils/ruoyi'; //
import ImageUpload from "@/components/ImageUpload";
import BaseCheckbox from "@/components/BaseCheckbox"; //
import IconTips from "@/components/IconTips"; //
// import SkinSelector from "@/components/SkinSelector";
import CurrencySelect from '@/components/CurrencySelect'; //
import CheckboxSelect from "@/components/CheckboxSelect"; // /
import CustomSelect from "@/components/CustomSelect";
import NumberInput from "@/components/NumberInput";
import { updateGame } from "@/api/game/game";
import { getMaterialList } from "@/api/common"; //
import CustomSelect from "@/components/CustomSelect"; //
import { nextTick, onMounted, ref } from "vue"; //
import { getLocalStorage } from "@/utils/auth";
import { postSiteBindApiGame } from "@/api/siteManagement";
import { postSiteBindApiGame,getSiteBindApiGameInfo,postSiteUpdateApiGame,postSiteDeleteApiGame } from "@/api/siteManagement";
import { id } from 'element-plus/es/locales.mjs';
const langListRaw = getLocalStorage('langList') || []
const langList = Array.from(
new Map(
langListRaw?.filter(v => v.langType == 1 && v.langStatus).map(item => [item.countryLang, {
label: item.name,
value: item.id
}])
).values()
) //
const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
return {
label: `${item.currencyName}(${item.currencyCode})`,
value: item.currencyCode
};
});
const { proxy } = getCurrentInstance() //
const emits = defineEmits(['submit', 'update:show']) //
const props = defineProps({ //
@ -88,10 +113,9 @@ const showDialog = computed({ //弹窗显示控制
})
const formAll = reactive({
ShowStartTime:[]
})
const oldForm = shallowRef({ });
const showDialogTenant = ref(false);
const rules = reactive({
tenantKey: [
{ required: true, message: proxy.t('请输入租户id'), trigger: 'change' }
@ -105,33 +129,52 @@ const rules = reactive({
]
})
const tenantList = ref([]);
const getSiteBindApiGameInfos = () => {
getSiteBindApiGameInfo({
siteId: props.modifyDate.id
}).then(res => {
tenantList.value = res.data;
})
}
//
nextTick(() => {
Object.assign(formAll, props.modifyDate)
// Object.assign(formAll, props.modifyDate);
formAll.siteId = props.modifyDate.id;
getSiteBindApiGameInfos();
});
const getClientSkinName = (val) => {
let resdata = getLocalStorage('materialGroupSelect');
let items = resdata.find(item => item.id == val.clientSkinStyle)?.gameMaterialDatas||[];
return items.find(item => item.id == val.clientSkin)?.mainColor || '--';
const addStatus = ref('add')
//
const handleAdd = () => {
addStatus.value = 'add';
showDialogTenant.value = true;
}
const getLangName = (langPattern) => {
let resdata = getLocalStorage('langSelect');
let arrSelect = langPattern.split(',');
let arrName = [];
arrSelect.forEach(itemSele => {
let names = resdata.find(item => item.id == itemSele)?.name;
arrName.push(names);
})
return arrName.join(',');
const handleEdit = (row) => {
addStatus.value = 'edit';
showDialogTenant.value = true;
Object.assign(formAll, row);
setTimeout(() => {
oldForm.value = JSON.stringify(formAll);
}, 500);
}
const handleDelect = (row) => {
proxy.$modal.confirm(proxy.t('确认是否删除?')).then(() => {
postSiteDeleteApiGame({siteId:formAll.siteId,id:row.id}).then(() => {
proxy.$modal.msgSuccess(proxy.t('删除成功'));
getSiteBindApiGameInfos();
})
}).catch(() => {})
}
//
const closeDialog = () => {
showDialog.value = false
}
const closeDialog1 = () => {
showDialogTenant.value = false
}
const formRef = ref(null);
const loadingButton = ref(false);
//
@ -141,22 +184,45 @@ const submitForm = () => {
if (valid) {
loadingButton.value = true;
//
let formData = {
siteId: formAll.siteId,
tenantKey:formAll.tenantKey,
secretKey:formAll.secretKey,
beginTime:finalTimestamp(formAll.ShowStartTime[0]),
endTime:finalTimestamp(formAll.ShowStartTime[1]),
};
postSiteBindApiGame(formData).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功!'));
emits('submit');
closeDialog();
}).catch(error => {
loadingButton.value = false;
});
if (addStatus.value == 'add'){
let formData = {
siteId: formAll.siteId,
tenantKey:formAll.tenantKey,
secretKey:formAll.secretKey,
currencyCode:formAll.currencyCode
};
postSiteBindApiGame(formData).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('新增成功!'));
getSiteBindApiGameInfos();
closeDialog1();
}).catch(error => {
loadingButton.value = false;
});
}else{
let formData = {
id: formAll.id,
siteId: formAll.siteId,
tenantKey:formAll.tenantKey,
secretKey:formAll.secretKey,
currencyCode:formAll.currencyCode
};
if (JSON.stringify(formAll) != oldForm.value) {
postSiteUpdateApiGame(formData).then(res => {
loadingButton.value = false;
proxy.$modal.msgSuccess(proxy.t('修改成功!'));
getSiteBindApiGameInfos();
closeDialog1();
}).catch(error => {
loadingButton.value = false;
});
}else{
loadingButton.value = false;
closeDialog1();
}
}
}
});
};

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -200,7 +200,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -281,10 +281,13 @@ const handleLogin = (row) => {
})
};
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -190,7 +190,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -260,11 +260,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -190,7 +190,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -261,11 +261,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -190,7 +190,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -261,11 +261,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -192,7 +192,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -263,11 +263,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -190,7 +190,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -261,11 +261,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -7,7 +7,7 @@
<el-option :label="t('注销时间')" :value="2" />
</el-select>
</el-form-item>
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
<table-search-date v-model:dateRange="dateRange" ref="searchDateRef" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
<!-- <select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
@handleQuery="handleQuery">
</select-input-form> -->
@ -190,7 +190,7 @@ const queryParamsList = ref([{
label: proxy.t('所属主站'),
value: 'id',
}]);
const dateRange = ref([]),operateTimeType = ref("");
const dateRange = ref([]),operateTimeType = ref("day");
const formatType = 'YYYY-MM-DD HH:mm:ss'; //
const data = reactive({
form: {},
@ -260,11 +260,13 @@ function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
const searchDateRef = ref(null);
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
dateRange.value = [];
operateTimeType.value = "day";
searchDateRef.value.timeTypeChange(operateTimeType.value)
}
//

View File

@ -138,11 +138,13 @@
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<template #default="scope">
<el-switch
v-if="userInfo.userName != scope.row.userName"
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
<span v-else>{{ scope.row.status == 0 ? '' : '' }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
@ -341,7 +343,7 @@
</template>
<script setup name="User">
import { getToken } from "@/utils/auth";
import { getToken,getLocalStorage } from "@/utils/auth";
import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect } from "@/api/system/user";
const router = useRouter();
@ -365,6 +367,8 @@
const roleOptions = ref([]);
const pwdType = ref("password");
const objItem = ref(null);
const userInfo = reactive(getLocalStorage('userInfo'));
/*** 用户导入参数 */
const upload = reactive({
//

View File

@ -24,25 +24,25 @@ export default defineConfig(({ mode, command }) => {
port: 80,
host: true,
open: true,
// proxy: {
// '/dev-api': {
// // target: 'http://192.168.50.139:9080',
// // target: 'http://192.168.50.233:8081',
// // target: 'http://192.168.50.178:8080',
// target: 'http://192.168.50.11:8081',
// changeOrigin: true,
// rewrite: (p) => p.replace(/^\/dev-api/, '')
// }
// },
proxy: {
'/ff-api': {
target: 'https://superapi.pgbet188.net', // 线上接口地址
changeOrigin: true, // 是否允许跨域
pathRewrite: {
'^/ff-api': '' // 如果你需要去掉前缀,例如将 /api/xxx 替换为 /xxx
}
'/dev-api': {
// target: 'http://192.168.50.139:9080',
// target: 'http://192.168.50.233:8081',
// target: 'http://192.168.50.178:8080',
target: 'http://192.168.50.11:8081',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}
}
},
// proxy: {
// '/ff-api': {
// target: 'https://superapi.pgbet188.net', // 线上接口地址
// changeOrigin: true, // 是否允许跨域
// pathRewrite: {
// '^/ff-api': '' // 如果你需要去掉前缀,例如将 /api/xxx 替换为 /xxx
// }
// }
// }
},
css: {
postcss: {