增加游戏ip屏蔽的配置

This commit is contained in:
zhl 2020-11-11 15:29:12 +08:00
parent feeb88c16a
commit d29bc132d5
7 changed files with 442 additions and 31 deletions

View File

@ -16,6 +16,7 @@
"dependencies": {
"axios": "0.18.0",
"echarts": "^4.2.1",
"el-tree-transfer": "^2.3.2",
"element-ui": "^2.9.1",
"install": "^0.12.2",
"js-cookie": "2.2.0",

View File

@ -10,6 +10,14 @@ export function getRegions(params) {
})
}
export function getRegionWithId(params) {
return request({
url: '/common/loc/china_region_id',
method: 'get',
params,
})
}
export function getAreas() {
return request({
url: '/common/loc/china_area',

View File

@ -57,7 +57,6 @@ export function deployCfg(data) {
})
}
export function updateRC(data) {
return request({
url: '/games/update_rc',
@ -65,3 +64,19 @@ export function updateRC(data) {
data
})
}
export function getIpInfo(gid, pid) {
const url = `/games/ip/${gid}/${pid}`
return request({
url: url,
method: 'get',
})
}
export function saveIpInfo(data) {
return request({
url: '/games/ip/update',
method: 'post',
data
})
}

View File

@ -112,6 +112,12 @@ const gamesRouter = {
name: 'GameDetailsBanner',
meta: { title: 'Banner广告配置' }
},
{
path: 'settings/ip',
component: () => import('@/views/games/details/settings/ip'),
name: 'GameDetailsIP',
meta: { title: 'IP屏蔽' }
},
{
path: 'recommendation',
component: () => import('@/views/games/details/recommendation'),

View File

@ -21,6 +21,7 @@
<el-menu-item :index="`/games/details/${uid}/settings/sign`">签到</el-menu-item>
<el-menu-item :index="`/games/details/${uid}/settings/online`">在线</el-menu-item>
<el-menu-item :index="`/games/details/${uid}/settings/banner`">banner</el-menu-item>
<el-menu-item :index="`/games/details/${uid}/settings/ip`">IP屏蔽</el-menu-item>
</el-submenu>
<el-menu-item
v-if="uid !== 'new'"

View File

@ -14,7 +14,7 @@
style="color: #E6A23C"
>{{
tip
}}</span>
}}</span>
</div>
<el-form
ref="settingForm"
@ -59,10 +59,10 @@
trigger: 'blur'
}"
>
<span slot="label">{{item.title}}
<span slot="label">{{ item.title }}
<span
class="tip-wrap"
v-if="settingsCommentList[item.key]"
class="tip-wrap"
>
<el-tooltip
class="item"
@ -71,7 +71,7 @@
placement="top"
:disabled="!settingsCommentList[item.key]"
>
<svg-icon icon-class="question" />
<svg-icon icon-class="question"/>
</el-tooltip>
</span>
</span>
@ -117,13 +117,13 @@
>发布</el-button>
<el-button
v-if="permEdit"
@click="reset"
type="success"
@click="reset"
>重置</el-button>
</el-form-item>
</el-form>
<div class="divider" />
<div class="divider"/>
</el-col>
<el-col :span="10">
<div class="al-c">
@ -137,16 +137,16 @@
class="mgb-20 multiple-select"
style="width: 300px"
value-key="key"
@remove-tag="delSetting"
filterable
@remove-tag="delSetting"
>
<el-tooltip
v-for="item in settingsList"
:key="item.key"
class="item"
:content="item.comment"
placement="left"
v-for="item in settingsList"
:key="item.key"
:disabled="!item.comment"
>
<el-option
@ -159,17 +159,17 @@
</el-select>
<div class="btn-group">
<el-button
v-if="permSettings"
type="success"
size="small"
@click="addSetting"
v-if="permSettings"
>添加新的配置项</el-button>
<el-button
v-show="selectedSettings.length > 0"
v-if="permEdit"
type="danger"
size="small"
@click="clearSettings"
v-if="permEdit"
>清空</el-button>
<el-button
size="small"
@ -218,13 +218,13 @@
label="名称"
prop="value.title"
>
<el-input v-model="newSettingForm.value.title" />
<el-input v-model="newSettingForm.value.title"/>
</el-form-item>
<el-form-item
label="key"
prop="key"
>
<el-input v-model="newSettingForm.key" />
<el-input v-model="newSettingForm.key"/>
<span class="ipt-tip">该值写入redis并传入客户端请谨慎填写</span>
</el-form-item>
<el-form-item
@ -255,15 +255,15 @@
label="是否禁用"
prop="disabled"
>
<el-switch v-model="newSettingForm.disabled"></el-switch>
<el-switch v-model="newSettingForm.disabled"/>
</el-form-item>
<el-form-item
label="说明"
prop="comment"
>
<el-input
type="textarea"
v-model="newSettingForm.comment"
type="textarea"
/>
</el-form-item>
</el-form>
@ -280,9 +280,9 @@
<script>
import vueJsonEditor from 'vue-json-editor'
import {Promise} from 'q'
import {mapGetters} from 'vuex'
import {getGame} from '@/api/games'
import { Promise } from 'q'
import { mapGetters } from 'vuex'
import { getGame } from '@/api/games'
import {
resetSettings,
getGameSettings,
@ -343,12 +343,12 @@ export default {
comment: '',
},
newSettingRules: {
key: [{required: true, message: '请输入 key 值', trigger: 'blur'}],
key: [{ required: true, message: '请输入 key 值', trigger: 'blur' }],
'value.title': [
{required: true, message: '请填写名称', trigger: 'blur'},
{ required: true, message: '请填写名称', trigger: 'blur' },
],
'value.type': [
{required: true, message: '请选择值类型', trigger: 'blur'},
{ required: true, message: '请选择值类型', trigger: 'blur' },
],
},
}
@ -388,9 +388,9 @@ export default {
},
// left
getGameInfo(cb) {
getGame({uid: this.uid})
getGame({ uid: this.uid })
.then(res => {
const {data} = res
const { data } = res
if (data.errcode === 0) {
this.gameInfo = data.gameInfo
this.platformsArr = data.gameInfo.platforms
@ -418,7 +418,7 @@ export default {
id: this.gameInfo.game_id,
pid: this.platform_id,
}).then(res => {
const {data} = res
const { data } = res
if (data.errcode !== 0) {
this.$notify.error({
title: '错误',
@ -513,7 +513,7 @@ export default {
pid: this.platform_id,
})
.then(res => {
const {data} = res
const { data } = res
if (data.errcode === 0) {
this.settingsForm.settings = data.records
this.selectedSettings = data.records
@ -558,7 +558,7 @@ export default {
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
.then(async() => {
//
this.saveSettings()
.then(() => {
@ -569,7 +569,7 @@ export default {
platform: this.platform_id,
type: this.settingType,
}).then(res => {
const {data} = res
const { data } = res
if (data.errcode !== 0) {
this.$notify.error({
title: '错误',
@ -604,7 +604,7 @@ export default {
platform: this.platform_id,
type: this.settingType,
}).then(res => {
const {data} = res
const { data } = res
if (data.errcode !== 0) {
this.$notify.error({
title: '错误',
@ -628,7 +628,7 @@ export default {
// right
getSettingsList() {
getSettingItems().then(res => {
const {data} = res
const { data } = res
if (data.errcode !== 0) {
this.$notify.error({
title: '错误',
@ -735,7 +735,7 @@ export default {
comment: this.newSettingForm.comment,
},
}).then(res => {
const {data} = res
const { data } = res
if (data.errcode !== 0) {
this.$message.error(data.errmsg)
return

View File

@ -0,0 +1,380 @@
<template>
<div class="main-content">
<el-form
ref="mainForm"
:rules="mainFormRules"
label-width="120px"
style="width: 60%"
>
<el-form-item label="平台">
<el-select
v-model="platform_id"
style="width: 70%"
@change="changePlatform"
>
<el-option
v-for="item in platformsArr"
:key="item.platform.platform_id"
:label="item.platform.name"
:value="item.platform.platform_id"
/>
</el-select>
</el-form-item>
<el-form-item
label="启动参数白名单"
prop="name"
>
<el-input v-model="whiteTxt"/>
</el-form-item>
<el-form-item
label="地区"
>
<tree-transfer
:title="areaOptions.areaTitles"
:from_data="areaFrom"
:to_data="areaSelected"
:default-props="{label:'name'}"
mode="transfer"
height="540px"
filter
:open-all="areaOptions.openAll"
high-light
@addBtn="addArea"
@removeBtn="removeArea"
/>
</el-form-item>
<el-form-item
label="屏蔽时间段"
prop="share_word"
>
<el-row
v-for="(item, index) in timeGroups"
:key="index"
class="share-group"
type="flex"
align="middle"
:gutter="16"
>
<el-col :span="8">
<div class="txt ell">{{ item.start }}</div>
</el-col>
<el-col :span="8">
<div class="txt ell">{{ item.end }}</div>
</el-col>
<el-col :span="16">
<el-button
type="primary"
size="mini"
@click="editTimeGroup(item, index)"
>编辑</el-button>
<el-button
type="danger"
size="mini"
@click="delTimeGroup(index)"
>删除</el-button>
</el-col>
</el-row>
<el-button
v-if="permEdit"
size="mini"
@click="addTimeGroup"
>添加时间段</el-button>
</el-form-item>
<el-form-item>
<el-button
v-if="permEdit"
type="primary"
@click="save"
>保存</el-button>
</el-form-item>
</el-form>
<!-- Modal - 编辑时间段 -->
<el-dialog
title="修改时间"
:visible.sync="modalEditTimeVisible"
width="35%"
>
<el-form
ref="timeForm"
:model="timeForm"
:rules="timeFormRules"
>
<el-form-item
label="起始时间"
prop="start"
>
<el-time-select
v-model="timeForm.start"
placeholder="起始时间"
:picker-options="{
start: '00:00',
step: '00:15',
end: '24:00'
}"
/>
</el-form-item>
<el-form-item
label="结束时间"
prop="end"
>
<el-time-select
v-model="timeForm.end"
placeholder="结束时间"
:picker-options="{
start: '00:00',
step: '00:15',
end: '24:00',
minTime: timeForm.start
}"
/>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="closeModalTimeEdit"> </el-button>
<el-button
v-if="permEdit"
type="primary"
@click="saveTime"
> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getRegionWithId } from '@/api/common'
import treeTransfer from 'el-tree-transfer'
import { getGame, getIpInfo, saveIpInfo } from '@/api/games'
import { mapGetters } from 'vuex'
export default {
name: 'GameDetailsIP',
components: {
treeTransfer,
},
data() {
return {
// common
uid: '',
gid: '',
permEdit: false,
platform_id: 'all',
areas: [],
areaFrom: [],
whiteTxt: '',
areaSelected: [],
timeGroups: [],
areaOptions: {
openAll: false,
areaTitles: ['可选地区', '已选地区'],
},
platformsArr: [{ platform: { platform_id: 'all', name: '所有平台' }}],
mainForm: {
},
mainFormRules: {
},
timeForm: {
},
timeFormRules: {
start: [{ required: true, message: '请选择开始时间', trigger: 'blur' }],
end: [{ required: true, message: '请选择结束时间', trigger: 'blur' }]
},
modalEditTimeVisible: false,
}
},
computed: {
...mapGetters(['userInfo']),
},
async mounted() {
this.uid = this.$route.params.uid
this.permEdit =
this.userInfo.permissions.includes(`${this.uid}-edit`) ||
this.userInfo.permissions.includes(`games-writeable`)
await this.fetchGameInfo()
await this.fetchRegins()
if (this.gid) {
await this.fetchIpInfo(this.gid, this.platform_id)
}
this.rebuildAreaData()
},
methods: {
save() {
this.updateIpInfo()
},
async reset() {
try {
await this.$confirm('确定忽略任何修改?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
this.$refs['mainForm'].resetFields()
} catch (err) {
console.log('cancel clicked')
}
},
async changePlatform() {
if (!this.gid) {
this.$message.error('无法获取游戏基本信息')
return
}
await this.fetchIpInfo(this.gid, this.platform_id)
this.rebuildAreaData()
},
addArea(fromData, toData, obj) {
console.log('fromData:', fromData)
console.log('toData:', toData)
console.log('obj:', obj)
this.areaFrom = fromData
this.areaSelected = toData
const map = new Map(this.areaFrom.map(i => [i.id, i]))
for (const area of this.areaSelected) {
area.all = !map.has(area.id)
}
},
removeArea(fromData, toData, obj) {
console.log('fromData:', fromData)
console.log('toData:', toData)
console.log('obj:', obj)
this.areaFrom = fromData
this.areaSelected = toData
const map = new Map(this.areaFrom.map(i => [i.id, i]))
for (const area of this.areaSelected) {
area.all = !map.has(area.id)
}
},
addTimeGroup() {
this.timeForm = {}
this.openModalTimeEdit()
},
editTimeGroup(item, index) {
this.timeForm = this.timeGroups[index]
this.openModalTimeEdit()
},
async delTimeGroup(index) {
try {
await this.$confirm('确定删除该时间段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
this.timeGroups.splice(index, 1)
} catch (err) {
console.log('cancel clicked')
}
},
openModalTimeEdit() {
this.modalEditTimeVisible = true
},
closeModalTimeEdit() {
this.$refs['timeForm'].clearValidate()
this.modalEditTimeVisible = false
},
saveTime() {
console.log(this.timeForm)
if (!this.timeForm.idx) {
let maxIdx = 0
for (const obj of this.timeGroups) {
maxIdx = Math.max(maxIdx, obj.idx)
}
this.timeForm.idx = maxIdx + 1
this.timeGroups.push(this.timeForm)
}
this.closeModalTimeEdit()
},
async fetchRegins() {
try {
const res = await getRegionWithId()
const data = res.data
if (data['errcode'] === 0) {
this.areas = data.records
} else {
this.$message.error(`服务器返回errcode: ${data['errcode']}, msg: ${data['errmsg']}`)
}
} catch (err) {
console.error(err)
this.$message.error('获取地区基本信息出错')
}
},
async fetchGameInfo() {
try {
const res = await getGame({ uid: this.uid })
const { data } = res
if (data['errcode'] === 0) {
this.platformsArr.push(...data.gameInfo.platforms)
this.gid = data.gameInfo.game_id
} else {
this.$message.error(`服务器返回errcode: ${data['errcode']}, msg: ${data['errmsg']}`)
}
} catch (err) {
console.log(err)
this.$message.error('获取游戏基本信息出错')
}
},
async fetchIpInfo(gid, pid) {
try {
const res = await getIpInfo(gid, pid)
const { data } = res
if (data['errcode'] === 0) {
const ipdata = data.data || {}
this.whiteTxt = ipdata['more_params'] || ''
this.timeGroups = ipdata.times || []
this.areaSelected = ipdata.areas || []
} else {
this.$message.error(`服务器返回errcode: ${data['errcode']}, msg: ${data['errmsg']}`)
}
} catch (err) {
console.log(err)
this.$message.error('获取配置信息出错')
}
},
async updateIpInfo() {
try {
const dataSave = {
game_id: this.gid,
platform_id: this.platform_id,
more_params: this.whiteTxt,
times: this.timeGroups,
areas: this.areaSelected
}
const res = await saveIpInfo({ data: dataSave })
const { data } = res
if (data['errcode'] === 0) {
console.log('success')
this.$message({
message: '保存成功',
type: 'success'
})
} else {
this.$message.error(`服务器返回errcode: ${data['errcode']}, msg: ${data['errmsg']}`)
}
} catch (err) {
console.error(err)
this.$message.error('保存出错')
}
},
rebuildAreaData() {
const arr = []
const map = new Map(this.areaSelected.map(i => [i.id, i]))
for (const area of this.areas) {
if (map.has(area.id)) {
const subMap = new Map(map.get(area.id).children.map(i => [i.id, i]))
const subArr = []
for (const sub of area.children) {
if (!subMap.has(sub.id)) {
subArr.push(sub)
}
}
if (subArr.length > 0) {
area.children = subArr
arr.push(area)
}
} else {
arr.push(area)
}
}
this.areaFrom = arr
}
}
}
</script>