add 推荐列表

This commit is contained in:
yulixing 2019-07-01 14:24:41 +08:00
parent 9e5560b6ec
commit dd5afd7795
10 changed files with 495 additions and 138 deletions

View File

@ -56,3 +56,12 @@ export function updateFtp(data) {
data
})
}
export function updateRC(data) {
return request({
url: '/games/update_rc',
method: 'post',
data
})
}

View File

@ -43,4 +43,11 @@ export function delTpl(data) {
})
}
export function getFontList() {
return request({
url: '/games/mp_share/font_list',
method: 'get'
})
}

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="1561950353415" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3747" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M455.111111 56.888889h56.888889v739.555555H455.111111z" fill="#333333" p-id="3748"></path><path d="M722.488889 529.066667l45.511111 45.511111-284.444444 278.755555-278.755556-278.755555 39.822222-45.511111 238.933334 244.622222zM56.888889 910.222222h853.333333v56.888889H56.888889z" fill="#333333" p-id="3749"></path></svg>

After

Width:  |  Height:  |  Size: 698 B

1
src/icons/svg/to_top.svg Normal file
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="1561950380950" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2248" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M455.111111 227.555556h56.888889v739.555555H455.111111z" fill="#333333" p-id="2249"></path><path d="M722.488889 494.933333l45.511111-45.511111-284.444444-278.755555-278.755556 278.755555 39.822222 45.511111 238.933334-244.622222zM56.888889 56.888889h853.333333v56.888889H56.888889z" fill="#333333" p-id="2250"></path></svg>

After

Width:  |  Height:  |  Size: 698 B

View File

@ -1,19 +1,65 @@
// TODO: 修改字体路径
@font-face {
font-family: 'muyao';
src: url('http://ptfwuko7v.bkt.clouddn.com/muyao.ttf') format('truetype');
font-family: 'c1001';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1001.ttf') format('truetype');
}
@font-face {
font-family: 'shoushuti';
src: url('~@/assets/fonts/shoushuti.ttf') format('truetype');
font-family: 'c1002';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1002.ttf') format('truetype');
}
@font-face {
font-family: 'siyuan';
src: url('~@/assets/fonts/siyuan.otf') format('opentype');
font-family: 'c1003';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1003.ttf') format('truetype');
}
@font-face {
font-family: 'yangrendong';
src: url('~@/assets/fonts/yangrendong.ttf') format('truetype');
font-family: 'c1004';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1004.ttf') format('truetype');
}
@font-face {
font-family: 'c1005';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1005.ttf') format('truetype');
}
@font-face {
font-family: 'c1006';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1006.ttf') format('truetype');
}
@font-face {
font-family: 'c1007';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1007.ttf') format('truetype');
}
@font-face {
font-family: 'c1008';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1008.ttf') format('truetype');
}
@font-face {
font-family: 'c1009';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1009.ttf') format('truetype');
}
@font-face {
font-family: 'c1010';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1010.ttf') format('truetype');
}
@font-face {
font-family: 'c1011';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1011.ttf') format('truetype');
}
@font-face {
font-family: 'c1012';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=c1012.ttf') format('truetype');
}
@font-face {
font-family: 'e2001';
src: url('http://localhost:2333/api/mp_share/fonts/get_font?path=e2001.ttf') format('truetype');
}

View File

@ -46,9 +46,9 @@
>
<template slot="title">
<svg-icon
class="mgr-20"
style="margin-right: 20px;"
icon-class="del"
@click.stop="delAC"
@click.stop="delAC(index)"
/>
{{ item.title || '未命名'}}
</template>

View File

@ -9,6 +9,7 @@
<el-menu-item v-if="uid !== 'new'" :index="`/games/details/${uid}/achievement`">成就</el-menu-item>
<el-menu-item v-if="uid !== 'new'" :index="`/games/details/${uid}/invitation`">邀请</el-menu-item>
<el-menu-item v-if="uid !== 'new'" :index="`/games/details/${uid}/reward`">客服奖励</el-menu-item>
<el-menu-item :index="`/games/details/${uid}/recommendation`">推荐</el-menu-item>
<!-- <el-menu-item :index="`/games/details/${uid}/recommendation`">推荐</el-menu-item>
<el-menu-item :index="`/games/details/${uid}/reward`">奖励</el-menu-item>
<el-submenu :index="`/games/details/${uid}/gm/servers`">

View File

@ -45,7 +45,7 @@
:key="index"
>
<template slot="title">
<svg-icon class="mgr-20" icon-class="del" @click.stop="delIV"/>
<svg-icon style="margin-right: 20px;" icon-class="del" @click.stop="delIV(index)"/>
{{ `配置:${item.id}` || '未命名'}}
</template>

View File

@ -369,6 +369,28 @@
</el-form-item>
</template>
<template v-else-if="item.iptType === 'font-picker'">
<el-form-item
:label="item.label"
:prop="`form[${index}].value`"
:key="index"
:rules="item.rules"
v-if="item.show"
>
<el-select
v-model="item.value"
style="width: 100%"
>
<el-option
v-for="(val, key) in fontList"
:key="key"
:label="val.label"
:value="val.value"
/>
</el-select>
</el-form-item>
</template>
<template v-else>
<el-form-item
:label="item.label"
@ -428,7 +450,14 @@
<script>
import vueJsonEditor from 'vue-json-editor'
import { getPic, saveTpl, getTpl, updateTpl, delTpl } from '@/api/mp_share'
import {
getPic,
saveTpl,
getTpl,
updateTpl,
delTpl,
getFontList
} from '@/api/mp_share'
import { getToken } from '@/utils/auth'
export default {
@ -440,6 +469,7 @@ export default {
tplForm: {
handler: function(nVal, oVal) {
this.formPrev(nVal)
console.log(nVal)
},
immediate: true,
deep: true
@ -525,6 +555,7 @@ export default {
loc_path: '/fonts/yangrendong.ttf'
}
],
fontList: {},
//
tplForm: {
tpl_name: '',
@ -779,7 +810,7 @@ export default {
show: true
},
{
iptType: 'select',
iptType: 'font-picker',
data: [],
label: '字体类型',
name: 'font-family',
@ -921,15 +952,10 @@ export default {
}
},
mounted() {
for (let i = 0; i < this.textForm.length; i++) {
if (this.textForm[i].name === 'font-family') {
this.textForm[i].data = this.fonts
}
}
// token
this.token = getToken()
this.getFontList()
// TODO: isNew = false isNew = true
if (this.$route.query.tpl_uid) {
getTpl({ tpl_uid: this.$route.query.tpl_uid })
.then(res => {
@ -945,6 +971,19 @@ export default {
}
},
methods: {
// common
getFontList() {
getFontList()
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.fontList = data.font_list
}
})
.catch(err => {
console.log(err)
})
},
// form
addView() {
// modalForm
@ -1074,6 +1113,7 @@ export default {
}
}
})
console.log('res', result)
return result
})
},
@ -1082,7 +1122,7 @@ export default {
if (valid) {
// painter
const opt = {}
const fonts = []
const fonts = {}
//
opt.baseInfo = {}
console.log(this.previewInfo.base_style)
@ -1120,7 +1160,7 @@ export default {
}
if (style['font-family']) {
fonts.push(style['font-family'])
fonts[style['font-family']] = true
}
}
opt.views.push(obj)
@ -1128,27 +1168,29 @@ export default {
// fonts
opt.baseInfo
opt.baseInfo.fonts = []
this.fonts.map(font => {
if (fonts.indexOf(font.name) !== -1) {
opt.baseInfo.fonts.push(font)
for (const key in fonts) {
if (fonts.hasOwnProperty(key)) {
opt.baseInfo.fonts.push(this.fontList[key])
}
})
}
console.log('模板🤩', this.tplForm)
console.log('预览😘', this.previewInfo)
console.log('生成😡', opt)
//
getPic({ opt })
.then(res => {
const data = res.data
console.log(res)
if (data.errcode === 0) {
this.tplForm.prev_url = data.url
}
})
.catch(err => {
console.log(err)
})
// getPic({ opt })
// .then(res => {
// const data = res.data
// console.log(res)
// if (data.errcode === 0) {
// this.tplForm.prev_url = data.url
// }
// })
// .catch(err => {
// console.log(err)
// })
} else {
this.$message.error('请按要求填写表单')
}

View File

@ -1,133 +1,383 @@
<template>
<div class="main-content">
<el-alert title="此处仅显示已上线游戏" type="warning" show-icon class="mgb-20"/>
<!-- toolbar -->
<div class="toolbar clearfix">
<div class="l fl">
<el-button type="primary" @click="addGame">新增</el-button>
<el-button v-if="batch.show" type="danger" @click="batchDel">批量删除</el-button>
<el-button @click="batchOpt">{{ batch.txt }}</el-button>
<div style="width: 60%">
<el-alert
title="注意"
type="warning"
description="进行【平台切换】、【删除推荐】、【调整排序】等操作时,请注意保存!"
class="mgb-20"
show-icon
>
</el-alert>
<el-select
v-model="platform_id"
@change="changePlatform"
class="w100 mgb-20"
>
<el-option
v-for="item in platformsArr"
:key="item.platform.platform_id"
:label="item.platform.name"
:value="item.platform.platform_id"
/>
</el-select>
<el-collapse
v-model="activeNames"
v-if="RCList.length > 0"
>
<el-collapse-item
:name="index"
v-for="(item, index) in RCList"
:key="index"
>
<template slot="title">
<svg-icon
style="margin-right: 20px;"
icon-class="del"
@click.stop="delRC(index)"
/>
<span
class="ell"
style="display: inline-block;width: 100px"
>{{`${index + 1}`}}{{ item.game_name || '未命名'}}</span>
<svg-icon
style="margin-left: 20px;"
icon-class="to_top"
@click.stop="topRC(index)"
/>
<svg-icon
style="margin-left: 20px;"
icon-class="to_bottom"
@click.stop="bottomRC(index)"
/>
<svg-icon
style="margin-left: 20px;"
icon-class="up"
@click.stop="upRC(index)"
/>
<svg-icon
style="margin-left: 20px;"
icon-class="down"
@click.stop="downRC(index)"
/>
</template>
<el-form
:ref="`RCForm${index}`"
:model="item"
:rules="RCFormRules"
style="width: 100%"
label-width="100px"
class="mgt-20 mgb-20"
>
<el-form-item
label="游戏名称"
prop="game_name"
>
<el-input
v-model="item.game_name"
style="width: 70%"
/>
</el-form-item>
<el-form-item
label="游戏图标"
prop="game_icon"
class="uploader-box"
>
<el-upload
class="uploader"
action="/api/common/upload"
:show-file-list="false"
:on-success="
(res, file, fileList) => {
return uploadSuccess(
res,
file,
fileList,
index
)
}
"
:on-error="uploadErr"
:headers="{
authorization: 'Bearer ' + token
}"
name="image-file"
:data="{ sub_path: '/game_icon/', file_type: 'game_icon' }"
>
<img
v-if="item.game_icon"
:src="item.game_icon"
class="uploader-img"
/>
<i
v-else
class="el-icon-plus uploader-icon"
/>
</el-upload>
</el-form-item>
<el-form-item
label="AppID"
prop="app_id"
>
<el-input
v-model="item.app_id"
style="width: 70%"
/>
</el-form-item>
</el-form>
</el-collapse-item>
</el-collapse>
<div
class="tip mgt-20 mgb-20"
v-else
>
暂无推荐游戏请添加推荐游戏
</div>
<div class="r fr">
<el-button type="primary">刷新</el-button>
<div class="btn-group">
<el-button
class="mgt-20"
type="success"
@click="addRC"
v-if="permEdit"
>新增推荐</el-button>
<el-button
class="mgt-20"
type="primary"
v-if="permEdit"
@click="saveRCList"
>保存全部</el-button>
</div>
</div>
<!-- table -->
<el-table :data="tableData" style="width: 100%" class="table mgt-20 mgb-20">
<el-table-column v-if="batch.show" type="selection" width="55"/>
<el-table-column prop="gameid" label="游戏 ID" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="平台" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="游戏名称" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="游戏类型" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="点击数" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="火爆" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="新游" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="主推" show-overflow-tooltip sortable/>
<el-table-column prop="name" label="操作" fixed="right" width="126">
<template slot-scope="scope">
<el-button type="text" size="small" @click="viewGame(scope.row)">查看</el-button>
<el-button type="text" size="small" @click="editGame(scope.row)">编辑</el-button>
<el-button type="text" size="small" @click="delGame(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- pagination -->
<el-pagination
:hide-on-single-page="true"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="400"
class="al-r"
@size-change="sizeChange"
@current-change="pageChange"
/>
<!-- Modal -->
<el-dialog title="选择关联游戏" :visible.sync="modalVisible">
<el-table :data="gameList" height="300">
<el-table-column type="selection" width="55"/>
<el-table-column prop="gameid" label="游戏 ID" show-overflow-tooltip/>
<el-table-column prop="name" label="平台" show-overflow-tooltip/>
<el-table-column prop="name" label="游戏名称" show-overflow-tooltip/>
<el-table-column prop="name" label="游戏类型" show-overflow-tooltip/>
<el-table-column prop="name" label="点击数" show-overflow-tooltip/>
<el-table-column prop="name" label="火爆" show-overflow-tooltip/>
<el-table-column prop="name" label="新游" show-overflow-tooltip/>
<el-table-column prop="name" label="主推" show-overflow-tooltip/>
</el-table>
<div slot="footer">
<el-button @click="modalVisible = false"> </el-button>
<el-button type="primary" @click="modalVisible = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getGame, updateRC } from '@/api/games'
import getPageTitle from '@/utils/get-page-title'
import { reject, Promise } from 'q'
import { getToken } from '@/utils/auth'
export default {
name: 'GameDetailsRecommendation',
name: 'GameDetailsShare',
data() {
return {
// toolbar
batch: {
show: false,
txt: '批量操作'
// common
uid: '',
token: '',
platform_id: '',
platformsArr: [],
gameInfo: {},
permEdit: false,
// form
RCForm: {},
RCFormRules: {
game_name: [{ required: true, message: '请填写游戏名称', trigger: 'blur' }],
game_icon: [{ required: true, message: '请上传游戏图标', trigger: 'blur' }],
app_id: [{ required: true, message: '请填写AppID', trigger: 'blur' }]
},
// table
tableData: [
{
gameid: 123455555555555555555555555,
name: 'game'
}
],
// pagination
currentPage: 1,
// modal
modalVisible: false,
gameList: [
{
gameid: 123455555555555555555555555,
name: 'game'
}
]
activeNames: [],
defaultSetting: {
game_name: '',
game_icon: '',
app_id: ''
},
RCList: []
}
},
computed: {
...mapGetters(['userInfo'])
},
mounted() {
this.uid = this.$route.params.uid
this.type = this.$route.query.type ? this.$route.query.type : 'normal'
this.token = getToken()
this.permEdit =
this.userInfo.permissions.includes(`${this.uid}-edit`) ||
this.userInfo.permissions.includes(`${this.uid}-publish`) ||
this.userInfo.permissions.includes(`games-writeable`)
this.getGameInfo()
},
methods: {
// toolbar
addGame() {
this.modalVisible = true
getGameInfo() {
getGame({ uid: this.uid })
.then(res => {
const { data } = res
if (data.errcode === 0) {
this.gameInfo = data.gameInfo
this.platformsArr = data.gameInfo.platforms
this.$route.meta.title = this.gameInfo.game_name
document.title = getPageTitle(this.gameInfo.game_name)
if (this.$route.query.platform_id) {
this.platform_id = this.$route.query.platform_id
} else {
this.platform_id = this.platformsArr[0]
? this.platformsArr[0].platform.platform_id
: ''
}
if (
this.gameInfo.recommendation &&
this.gameInfo.recommendation[this.platform_id]
) {
this.RCList = this.gameInfo.recommendation[this.platform_id]
}
}
})
.catch(err => {
console.log(err)
})
},
batchDel() {
console.log('批量删除游戏')
changePlatform() {
this.$router.push(
`/games/details/${this.uid}/recommendation?platform_id=${
this.platform_id
}`
)
},
batchOpt() {
this.batch.show = !this.batch.show
this.batch.txt = this.batch.show ? '关闭' : '批量操作'
console.log('批量操作')
addRC() {
if (this.RCList.length === 10) {
this.$message.warning('最多存在10个推荐项目!')
return
}
const defaultSetting = JSON.parse(JSON.stringify(this.defaultSetting))
this.activeNames.push(this.RCList.length)
this.RCList.push(defaultSetting)
},
// table
viewGame(row) {
console.log('查看游戏')
delRC(index) {
this.$confirm('是否要删除该推荐?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.RCList.splice(index, 1)
this.$message.success('删除成功!')
})
.catch(() => {
this.$message.info('已取消删除!')
})
},
editGame(row) {
console.log('编辑游戏')
upRC(index) {
if (index === 0) {
this.$message.warning('已置顶!')
return
}
const temp = this.RCList[index]
this.RCList.splice(index, 1)
this.RCList.splice(index - 1, 0, temp)
},
delGame(row) {
console.log('删除游戏')
downRC(index) {
if (index === this.RCList.length - 1) {
this.$message.warning('已置底!')
return
}
const temp = this.RCList[index]
this.RCList.splice(index, 1)
this.RCList.splice(index + 1, 0, temp)
},
// pagination
sizeChange(val) {
console.log(`每页 ${val}`)
topRC(index) {
if (index === 0) {
this.$message.warning('已置顶!')
return
}
const temp = this.RCList[index]
this.RCList.splice(index, 1)
this.RCList.splice(0, 0, temp)
},
pageChange(val) {
console.log(`当前页: ${val}`)
bottomRC(index) {
if (index === this.RCList.length - 1) {
this.$message.warning('已置底!')
return
}
const temp = this.RCList[index]
this.RCList.splice(index, 1)
const lastIdx = this.RCList.length ? this.RCList.length - 1 : 0
this.RCList.push(temp)
},
uploadSuccess(res, file, fileList, index) {
this.RCList[index].game_icon = res.url
},
uploadErr() {
this.$message.error('图片上传失败!')
},
validForm(formName) {
return new Promise((resolve, reject) => {
this.$refs[formName][0].validate(valid => {
valid ? resolve() : reject()
})
})
},
saveRCList() {
if (this.RCList.length === 0) {
this.$confirm('当前无推荐游戏,是否清空?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.updateRC()
})
.catch(() => {
this.$message.info('已取消保存!')
})
return
}
const validArr = []
for (let i = 0; i < this.RCList.length; i++) {
validArr.push(this.validForm(`RCForm${i}`))
}
Promise.all(validArr)
.then(() => {
this.updateRC()
})
.catch(err => {
console.log(err)
this.$message.error('请按要求填写表单')
})
},
updateRC() {
return new Promise((resolve, reject) => {
updateRC({
_id: this.gameInfo._id,
platform_id: this.platform_id,
RCList: this.RCList
})
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.$message.success('保存成功!')
this.$router.push(
`/games/details/${this.uid}/recommendation?platform_id=${
this.platform_id
}`
)
resolve()
} else {
this.$message.error('保存失败!')
reject()
}
})
.catch(err => {
console.log(err)
})
})
}
}
}
</script>
<style lang="sass" scoped>
<style scoped>
.btn-group >>> .el-button + .el-button {
margin-left: 0;
}
</style>