分享小程序 编辑页、列表页

This commit is contained in:
yulixing 2019-06-27 16:17:54 +08:00
parent dcc8d47550
commit 079dd1e75e
4 changed files with 734 additions and 48 deletions

View File

@ -7,3 +7,40 @@ export function getPic(data) {
data
})
}
export function saveTpl(data) {
return request({
url: '/games/mp_share/save_tpl',
method: 'post',
data
})
}
export function getTpl(params) {
return request({
url: '/games/mp_share/get_tpl',
method: 'get',
params
})
}
export function getTpls(params) {
return request({
url: '/games/mp_share/get_tpls',
method: 'get',
params
})
}
export function updateTpl(data) {
return request({
url: '/games/mp_share/update_tpl',
method: 'post',
data
})
}
export function delTpl(data) {
return request({
url: '/games/mp_share/del_tpl',
method: 'post',
data
})
}

View File

@ -246,8 +246,14 @@ const gamesRouter = {
path: 'mp/edit',
component: () => import('@/views/games/details/mp/edit'),
name: 'GameDetailsMpEdit',
meta: { title: '小程序编辑' }
}
meta: { title: '分享小程序模板编辑' }
},
{
path: 'mp/index',
component: () => import('@/views/games/details/mp/index'),
name: 'GameDetailsMp',
meta: { title: '分享小程序模板列表' }
},
]
}
]

View File

@ -10,6 +10,15 @@
class="mgb-20"
show-icon
/>
<el-button
class="w100 mgb-20"
@click="openImportModal"
>快速导入</el-button>
<el-button
class="w100 mgb-20"
style="margin-left: 0;"
@click="exportTpl"
>快速导出</el-button>
<el-form
ref="tplForm"
:model="tplForm"
@ -17,19 +26,31 @@
class="tpl-form"
label-width="80px"
>
<el-form-item label="模板名称" prop="tpl_name">
<el-form-item
label="模板名称"
prop="tpl_name"
>
<el-input v-model="tplForm.tpl_name" />
</el-form-item>
<el-form-item label="模板 ID" prop="tpl_id">
<el-form-item
label="模板 ID"
prop="tpl_id"
>
<el-input v-model="tplForm.tpl_id" />
</el-form-item>
<el-form-item label="画布宽度" prop="base_style.width">
<el-form-item
label="画布宽度"
prop="base_style.width"
>
<el-input
v-model="tplForm.base_style.width"
placeholder="例500px"
/>
</el-form-item>
<el-form-item label="画布高度" prop="base_style.height">
<el-form-item
label="画布高度"
prop="base_style.height"
>
<el-input
v-model="tplForm.base_style.height"
placeholder="例500px"
@ -45,13 +66,19 @@
show-alpha
></el-color-picker>
</el-form-item>
<el-form-item label="画布圆角" prop="base_style['border-radius']">
<el-form-item
label="画布圆角"
prop="base_style['border-radius']"
>
<el-input
v-model="tplForm.base_style['border-radius']"
placeholder="例10px"
/>
</el-form-item>
<el-form-item label="绘制组" prop="views">
<el-form-item
label="绘制组"
prop="views"
>
<el-table
:data="tplForm.views"
style="width: 100%"
@ -59,11 +86,20 @@
@row-click="rowClick"
:row-class-name="tableRowClassName"
>
<el-table-column type="index" width="30" />
<el-table-column label="内容" show-overflow-tooltip>
<el-table-column
type="index"
width="30"
/>
<el-table-column
label="内容"
show-overflow-tooltip
>
<template slot-scope="scope">
<!-- 图片 -->
<div v-if="scope.row.type === 'image'" style="line-height: 0">
<div
v-if="scope.row.type === 'image'"
style="line-height: 0"
>
<el-image
style="width: 30px; height: 30px"
:src="scope.row.form[0].value"
@ -86,36 +122,61 @@
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span @click.stop="editView(scope.$index, scope.row)"
><svg-icon icon-class="edit"
/></span>
<span @click.stop="delView(scope.$index, scope.row)"
><svg-icon icon-class="close"
/></span>
<span @click.stop="upView(scope.$index)"
><svg-icon icon-class="up"
/></span>
<span @click.stop="downView(scope.$index)"
><svg-icon icon-class="down"
/></span>
<span @click.stop="editView(scope.$index, scope.row)">
<svg-icon icon-class="edit" /></span>
<span @click.stop="delView(scope.$index, scope.row)">
<svg-icon icon-class="close" /></span>
<span @click.stop="upView(scope.$index)">
<svg-icon icon-class="up" /></span>
<span @click.stop="downView(scope.$index)">
<svg-icon icon-class="down" /></span>
</template>
</el-table-column>
</el-table>
<span class="ipt-tip">图片绘制顺序为表格中条目顺序决定</span>
<el-button size="mini" @click="addView">添加</el-button>
<el-button
size="mini"
@click="addView"
>添加</el-button>
</el-form-item>
<el-form-item label="预览图" v-if="tplForm.prev_url">
<el-form-item
label="预览图"
v-if="tplForm.prev_url"
>
<el-image
:src="tplForm.prev_url"
style="border: 1px dashed #dcdfe6; border-radius: 4px;"
></el-image>
</el-form-item>
<el-form-item label="备注" prop="comment">
<el-input v-model="tplForm.comment" type="textarea" />
<el-form-item
label="备注"
prop="comment"
>
<el-input
v-model="tplForm.comment"
type="textarea"
/>
</el-form-item>
<el-form-item>
<el-button type="success" @click="getPrevImg">生成预览图</el-button>
<el-button type="primary">保存</el-button>
<el-button
type="success"
@click="getPrevImg"
>生成</el-button>
<el-button
type="primary"
@click="saveTpl"
v-if="isNew"
>保存</el-button>
<el-button
type="warning"
@click="updateTpl"
v-if="!isNew"
>更新</el-button>
<el-button
type="danger"
@click="delTpl"
v-if="!isNew"
>删除</el-button>
</el-form-item>
</el-form>
</el-col>
@ -123,7 +184,10 @@
<!-- 模板预览 -->
<el-col :span="14">
<div class="preview">
<div class="main-box" :style="previewInfo.base_style">
<div
class="main-box"
:style="previewInfo.base_style"
>
<template v-for="(item, index) in previewInfo.views">
<template v-if="item.type === 'image'">
<el-image
@ -135,12 +199,20 @@
></el-image>
</template>
<template v-else-if="item.type === 'text'">
<p class="view text" :style="item.style" :key="index">
<p
class="view text"
:style="item.style"
:key="index"
>
<span>{{ item.text }}</span>
</p>
</template>
<template v-else>
<div class="view" :key="index" :style="item.style"></div>
<div
class="view"
:key="index"
:style="item.style"
></div>
</template>
</template>
</div>
@ -162,7 +234,10 @@
:rules="modalFormRules"
label-width="100px"
>
<el-form-item label="绘制类型" prop="type">
<el-form-item
label="绘制类型"
prop="type"
>
<el-select
v-model="modalForm.type"
style="width: 100%"
@ -183,7 +258,10 @@
>
<el-switch v-model="modalForm.replaceable"></el-switch>
</el-form-item>
<el-form-item label="是否可清除" prop="erasable">
<el-form-item
label="是否可清除"
prop="erasable"
>
<el-switch v-model="modalForm.erasable"></el-switch>
<span class="ipt-tip">用于水印元素</span>
</el-form-item>
@ -212,7 +290,10 @@
:src="modalForm.type === 'image' ? modalForm.form[0].value : ''"
class="uploader-img"
/>
<i v-else class="el-icon-plus uploader-icon" />
<i
v-else
class="el-icon-plus uploader-icon"
/>
</el-upload>
</el-form-item>
@ -225,7 +306,10 @@
:rules="item.rules"
v-if="item.show"
>
<el-select v-model="item.value" style="width: 100%">
<el-select
v-model="item.value"
style="width: 100%"
>
<el-option
v-for="(font, idx) in item.data"
:key="idx"
@ -265,8 +349,7 @@
:key="idx"
v-model="item.value"
:label="al.value"
>{{ al.label }}</el-radio
>
>{{ al.label }}</el-radio>
</el-form-item>
</template>
@ -305,15 +388,47 @@
<span slot="footer">
<el-button @click="closeModal"> </el-button>
<el-button type="primary" @click="saveView">保存</el-button>
<el-button
type="primary"
@click="saveView"
>保存</el-button>
</span>
</el-dialog>
<!-- modal-导入 -->
<el-dialog
title="快速导入"
:visible.sync="modalImportVisible"
width="50%"
>
<vue-json-editor
v-model="importTpl"
lang="en"
mode="code"
:modes="['code', 'tree']"
:show-btns="false"
/>
<span
slot="footer"
class="dialog-footer"
>
<el-button @click="modalImportVisible = false"> </el-button>
<el-button
type="primary"
@click="changeTpl"
> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import vueJsonEditor from 'vue-json-editor'
import { getPic } from '@/api/mp_share'
import { getPic, saveTpl, getTpl, updateTpl, delTpl } from '@/api/mp_share'
import { getToken } from '@/utils/auth'
export default {
@ -374,9 +489,10 @@ export default {
deep: true
}
},
computed: {},
data() {
return {
// common
isNew: true,
//
token: '',
fonts: [
@ -385,31 +501,30 @@ export default {
value: 'muyao',
name: 'muyao',
path: 'fonts/muyao.ttf',
loc_path: '/fonts/muyao.ttf',
loc_path: '/fonts/muyao.ttf'
},
{
label: '手书体',
value: 'shoushuti',
name: 'shoushuti',
path: 'fonts/shoushuti.ttf',
loc_path: '/fonts/shoushuti.ttf',
loc_path: '/fonts/shoushuti.ttf'
},
{
label: '思源',
value: 'siyuan',
name: 'siyuan',
path: 'fonts/siyuan.otf',
loc_path: '/fonts/siyuan.otf',
loc_path: '/fonts/siyuan.otf'
},
{
label: '杨任东',
value: 'yangrendong',
name: 'yangrendong',
path: 'fonts/yangrendong.ttf',
loc_path: '/fonts/yangrendong.ttf',
loc_path: '/fonts/yangrendong.ttf'
}
],
//
tplForm: {
tpl_name: '',
@ -799,7 +914,10 @@ export default {
}
],
//
previewInfo: {}
previewInfo: {},
//
modalImportVisible: false,
importTpl: ''
}
},
mounted() {
@ -810,9 +928,23 @@ export default {
}
// token
this.token = getToken()
// TODO: isNew = false isNew = true
if (this.$route.query.tpl_uid) {
getTpl({ tpl_uid: this.$route.query.tpl_uid })
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.tplForm = data.tpl
this.isNew = false
}
})
.catch(err => {
console.log(err)
})
}
},
methods: {
save() {},
// form
addView() {
// modalForm
@ -1021,6 +1153,74 @@ export default {
this.$message.error('请按要求填写表单')
}
})
},
// page
saveTpl() {
this.$refs['tplForm'].validate(valid => {
if (valid) {
saveTpl({ tpl: this.tplForm })
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.$message.success('模板保存成功!')
this.isNew = false
this.tplForm._id = data.result._id
}
})
.catch(err => {
console.log(err)
})
} else {
this.$message.error('请按要求填写表单')
}
})
},
updateTpl() {
updateTpl({ tpl: this.tplForm })
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.$message.success('模板更新成功!')
}
})
.catch(err => {
console.log(err)
})
},
delTpl() {
this.$confirm('是否确认删除此模板?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
delTpl({ _id: this.tplForm._id })
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.$message.success('模板已删除!')
// TODO:
}
})
.catch(err => {
console.log(err)
})
})
.catch(() => {
this.$message.info('已取消删除!')
})
},
openImportModal() {
this.modalImportVisible = true
},
changeTpl() {
this.tplForm = this.importTpl
this.modalImportVisible = false
console.log(this.importTpl)
},
exportTpl() {
console.log(JSON.stringify(this.tplForm))
}
}
}

View File

@ -0,0 +1,443 @@
<template>
<div class="main-content">
<!-- filter -->
<!-- <el-form
ref="filterForm"
:inline="true"
:model="filterForm"
class="filter"
>
<el-form-item
label="分享类型"
prop="shareType"
>
<el-select
v-model="filterForm.shareType"
placeholder="请选择分享类型"
>
<el-option
v-for="(item, index) in shareTypes"
:key="index"
:label="`${item.value}(${item.key})`"
:value="item.key"
/>
</el-select>
</el-form-item>
<el-form-item
label="类型"
prop="type"
>
<el-select
v-model="filterForm.type"
placeholder="请选择类型"
>
<el-option
label="分享优先"
:value="0"
/>
<el-option
label="广告优先"
:value="1"
/>
<el-option
label="只分享"
:value="2"
/>
<el-option
label="只广告"
:value="3"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="search"
>查询</el-button>
<el-button @click="reset('filterForm')">重置</el-button>
</el-form-item>
</el-form> -->
<!-- toolbar -->
<!-- <div class="toolbar clearfix">
<div class="l fl">
<el-button
v-if="permEdit"
type="primary"
@click="addShare"
>新增</el-button>
<el-button
v-if="batch.show && permEdit"
type="danger"
@click="batchDel"
>批量删除</el-button>
<el-button
v-if="permEdit"
@click="batchOpt"
>{{ batch.txt }}</el-button>
</div>
<div class="r fr">
<el-button
type="primary"
@click="refreshData"
>刷新</el-button>
</div>
</div> -->
<!-- table -->
<!-- <el-table
v-loading="isLoaded"
:data="tableData"
style="width: 100%"
class="table mgt-20 mgb-20"
@selection-change="tableSelectionChange"
@row-click="rowClick"
>
<el-table-column
v-if="batch.show"
type="selection"
width="55"
/>
<el-table-column
prop="gameName"
label="游戏"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="typeName"
label="分享类型"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="type"
label="类型"
show-overflow-tooltip
sortable
:formatter="formatType"
/>
<el-table-column
label="分享图"
show-overflow-tooltip
sortable
width="260"
>
<template slot-scope="scope">
<img
:src="scope.row.share_image"
width="30"
height="30"
style="vertical-align: middle"
/>
<span>{{ scope.row.share_word }}</span>
</template>
</el-table-column>
<el-table-column
prop="ad_id"
label="广告ID"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="default_share"
label="默认分享"
show-overflow-tooltip
sortable
:formatter="formatDefault"
/>
<el-table-column
prop="areaName"
label="地域"
show-overflow-tooltip
sortable
:formatter="formatArea"
/>
<el-table-column
prop="sex"
label="性别"
show-overflow-tooltip
sortable
:formatter="formatSex"
/>
<el-table-column
prop="name"
label="操作"
fixed="right"
width="126"
>
<template slot-scope="scope">
<el-button
v-if="permView"
type="text"
size="small"
@click.stop="editShare(scope.row)"
>详情</el-button>
<el-button
v-if="permEdit"
type="text"
size="small"
@click.stop="delShare(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table> -->
<!-- pagination -->
<div class="prev-box">
<router-link :to="`/games/details/mp/edit?tpl_uid=${item._id}`" v-for="(item, index) in tpls" :key="index">
<el-image
style="width: 200px; height: 200px; border: 1px solid #f0f0f0"
:src="item.prev_url"
fit="contain"
></el-image>
</router-link>
</div>
<el-pagination
class="al-r"
layout="total, sizes, prev, pager, next, jumper"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="total"
@size-change="sizeChange"
@current-change="pageChange"
/>
</div>
</template>
<script>
import { getShareList, getShareTypes, delShares } from '@/api/share'
import {
getPic,
saveTpl,
getTpl,
getTpls,
updateTpl,
delTpl
} from '@/api/mp_share'
import { getGame } from '@/api/games'
import { mapGetters } from 'vuex'
import getPageTitle from '@/utils/get-page-title'
export default {
name: 'GameDetailShare',
data() {
return {
// common
uid: '',
permView: false,
permEdit: false,
gameInfo: {},
// filter
shareTypes: [],
filterForm: {
shareType: '',
type: ''
},
// toolbar
batch: {
show: false,
txt: '批量操作'
},
// table
tpls: [],
tableData: [],
isLoaded: false,
multipleSelection: [],
// pagination
currentPage: 1,
pageSize: 10,
total: 0
}
},
computed: {
...mapGetters(['userInfo'])
},
mounted() {
this.getData()
this.uid = this.$route.params.uid
this.permEdit =
this.userInfo.permissions.includes(`${this.uid}-edit`) ||
this.userInfo.permissions.includes(`${this.uid}-publish`) ||
this.userInfo.permissions.includes(`games-writeable`)
this.permView =
this.userInfo.permissions.includes(`${this.uid}-readable`) ||
this.userInfo.permissions.includes(`${this.uid}-edit`) ||
this.userInfo.permissions.includes(`${this.uid}-publish`) ||
this.userInfo.permissions.includes(`games-writeable`)
},
methods: {
// common
getGameInfo(cb) {
getGame({ uid: this.uid })
.then(res => {
const { data } = res
if (data.errcode === 0) {
this.gameInfo = data.gameInfo
this.$route.meta.title = this.gameInfo.game_name
document.title = getPageTitle(this.gameInfo.game_name)
if (cb && cb instanceof Function) cb()
}
})
.catch(err => {
console.log(err)
})
},
// filter
getShareTypes() {
getShareTypes()
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.shareTypes = data.records
}
})
.catch(err => {
console.log(err)
})
},
search() {
this.currentPage = 1
this.getData()
},
reset(formName) {
this.$refs[formName].resetFields()
},
// toolbar
refreshData() {
this.currentPage = 1
this.getData()
},
addShare() {
this.$router.push(`/games/details/${this.uid}/share/edit?id=new`)
},
batchDel() {
this.$confirm(
`是否删除所选${this.multipleSelection.length}条分享图?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
.then(() => {
const ids = this.multipleSelection.map(item => {
return item._id
})
delShares({
ids: ids
}).then(res => {
const { data } = res
if (data.errcode === 0) {
this.$message.success('删除成功!')
}
this.refreshData()
})
})
.catch(() => {
this.$notify.info({
title: '消息',
message: '已取消删除'
})
})
},
batchOpt() {
this.batch.show = !this.batch.show
this.batch.txt = this.batch.show ? '关闭' : '批量操作'
},
// table
getData() {
getTpls({
currentPage: this.currentPage,
pageSize: this.pageSize
}).then(res => {
const data = res.data
if(data.errcode === 0) {
this.tpls = data.records
this.total = data.total
}
}).catch(err => {
console.log(err)
})
},
formatDefault(row, column, cellValue, index) {
return cellValue ? '是' : '否'
},
formatType(row, column, cellValue, index) {
if (cellValue === 0) {
return '分享优先'
} else if (cellValue === 1) {
return '广告优先'
} else if (cellValue === 2) {
return '只分享'
} else if (cellValue === 3) {
return '只广告'
}
},
formatSex(row, column, cellValue, index) {
if (cellValue === '0') {
return '不指定'
} else if (cellValue === '1') {
return '男'
} else if (cellValue === '2') {
return '女'
}
},
formatArea(row, column, cellValue, index) {
return cellValue ? cellValue : '不指定'
},
delShare(row) {
this.$confirm('是否删除该分享图?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
delShares({
ids: [row._id],
uid: this.uid
})
.then(res => {
const data = res.data
if (data.errcode === 0) {
this.$message.success('删除成功')
this.refreshData()
}
})
.catch(err => {
console.log(err)
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
tableSelectionChange(val) {
this.multipleSelection = val
},
editShare(row) {
this.$router.push(`/games/details/${this.uid}/share/edit?id=${row._id}`)
},
rowClick(row, column, event) {
this.$router.push(`/games/details/${this.uid}/share/edit?id=${row._id}`)
},
// pagination
sizeChange(val) {
this.pageSize = val
this.getData()
},
pageChange(val) {
this.currentPage = val
this.getData()
}
}
}
</script>