fix: 新增公众号管理相关页面,引入配置文件修改。
This commit is contained in:
172
src/views/wxma/wxuser/index.vue
Normal file
172
src/views/wxma/wxuser/index.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption"
|
||||
:permission="permissionList"
|
||||
@on-load="getPageF"
|
||||
@refresh-change="refreshChange"
|
||||
@row-update="handleUpdate"
|
||||
@row-save="handleSave"
|
||||
@row-del="handleDel"
|
||||
@sort-change="sortChange"
|
||||
@search-change="searchChange"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<template #sex="scope">
|
||||
<el-tag size="small" effect="light" :type="scope.row.sex == '1' ? 'success' : scope.row.sex == '2' ? 'danger' : 'warning'">
|
||||
{{ scope.row.$sex || '未知' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMaUser">
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
import { getPage, addObj, putObj, delObj } from '@/api/wxma/wxuser'
|
||||
import { tableOption } from '@/const/crud/wxma/wxuser'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 20, // 每页显示多少条
|
||||
ascs: [],
|
||||
descs: 'create_time'
|
||||
},
|
||||
paramsSearch: {},
|
||||
tableLoading: false,
|
||||
selectionData: [],
|
||||
dialogTagging: false
|
||||
})
|
||||
const { page, tableData, tableLoading } = toRefs(data)
|
||||
|
||||
const permissionList = computed(() => {
|
||||
return {
|
||||
addBtn: checkPermi(['wxma:wxuser:add']),
|
||||
delBtn: checkPermi(['wxma:wxuser:del']),
|
||||
editBtn: checkPermi(['wxma:wxuser:edit']),
|
||||
viewBtn: checkPermi(['wxma:wxuser:get'])
|
||||
}
|
||||
})
|
||||
|
||||
function selectionChange(list) {
|
||||
data.selectionData = list
|
||||
}
|
||||
|
||||
function searchChange(params, done) {
|
||||
params = proxy.filterForm(params)
|
||||
data.paramsSearch = params
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page, params)
|
||||
done()
|
||||
}
|
||||
|
||||
function sortChange(val) {
|
||||
const prop = val.prop ? val.prop.replace(/([A-Z])/g, '_$1').toLowerCase() : ''
|
||||
if (val.order == 'ascending') {
|
||||
data.page.descs = []
|
||||
data.page.ascs = prop
|
||||
} else if (val.order == 'descending') {
|
||||
data.page.ascs = []
|
||||
data.page.descs = prop
|
||||
} else {
|
||||
data.page.ascs = []
|
||||
data.page.descs = []
|
||||
}
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize,
|
||||
descs: data.page.descs,
|
||||
ascs: data.page.ascs,
|
||||
appType: '1'
|
||||
},
|
||||
params,
|
||||
data.paramsSearch
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.records
|
||||
data.page.total = response.data.total
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleDel(row, index) {
|
||||
proxy
|
||||
.$confirm('是否确认删除', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(function () {
|
||||
return delObj(row.id)
|
||||
})
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function handleUpdate(row, index, done, loading) {
|
||||
putObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function handleSave(row, done, loading) {
|
||||
addObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
getPageF(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
404
src/views/wxmp/wxautoreply/index.vue
Normal file
404
src/views/wxmp/wxautoreply/index.vue
Normal file
@@ -0,0 +1,404 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="type" @tab-click="handleClick">
|
||||
<el-tab-pane name="1">
|
||||
<template #label>
|
||||
<span>关注时回复</span>
|
||||
</template>
|
||||
<avue-crud
|
||||
style="padding: 0"
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:permission="permissionList"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption1"
|
||||
@refresh-change="refreshChange"
|
||||
>
|
||||
<template #menu-left="">
|
||||
<div class="add_but" v-if="tableData.length <= 0">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新 增</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<el-button link icon="el-icon-edit" plain type="primary" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button link icon="el-icon-delete" type="danger" plain @click="handleDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="2">
|
||||
<template #label>
|
||||
<span><i class="el-icon-chat-line-round"></i> 消息回复</span>
|
||||
</template>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:permission="permissionList"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption2"
|
||||
@refresh-change="refreshChange"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<template #menu-left>
|
||||
<div class="add_but">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新 增</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<el-button link icon="el-icon-edit" type="primary" plain @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button link icon="el-icon-delete" type="danger" plain @click="handleDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="3">
|
||||
<template #label>
|
||||
<span><i class="el-icon-news"></i> 关键词回复</span>
|
||||
</template>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:permission="permissionList"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption3"
|
||||
@on-load="getPageF"
|
||||
@refresh-change="refreshChange"
|
||||
@sort-change="sortChange"
|
||||
@search-change="searchChange"
|
||||
>
|
||||
<template #menu-left>
|
||||
<div class="add_but">
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新 增</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<el-button link icon="el-icon-edit" type="primary" plain @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button link icon="el-icon-delete" type="danger" plain @click="handleDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-dialog :title="handleType == 'add' ? '新增回复消息' : '修改回复消息'" v-model="dialog1Visible" width="50%">
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="请求消息类型" v-if="type == '2'">
|
||||
<el-select v-model="objData.reqType" placeholder="请选择">
|
||||
<template v-for="item in dictData.get('wx_req_type')" :key="item.value">
|
||||
<el-option v-if="item.value !== 'event'" :label="item.label" :value="item.value" :disabled="item.disabled" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="匹配类型" v-if="type == '3'">
|
||||
<el-select v-model="objData.repMate" placeholder="请选择" style="width: 100px">
|
||||
<el-option v-for="item in dictData.get('wx_rep_mate')" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词" v-if="type == '3'">
|
||||
<el-input placeholder="请输入内容" v-model="objData.reqKey" clearable> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="回复消息">
|
||||
<div v-if="hackResetWxReplySelect" style="width: 100%">
|
||||
<WxReplySelect :objData="objData"></WxReplySelect>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialog1Visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpAutoreply">
|
||||
/**
|
||||
* 消息自动回复
|
||||
*/
|
||||
import { getPage, getObj, addObj, putObj, delObj } from '@/api/wxmp/wxautoreply'
|
||||
import { tableOption1, tableOption2, tableOption3 } from '@/const/crud/wxmp/wxautoreply'
|
||||
import WxReplySelect from '@/components/wx-reply/main.vue'
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
import { computed, getCurrentInstance, nextTick, onMounted, reactive } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 20, // 每页显示多少条
|
||||
ascs: [], //升序字段
|
||||
descs: [] //降序字段
|
||||
},
|
||||
paramsSearch: {},
|
||||
tableLoading: false,
|
||||
dialog1Visible: false,
|
||||
type: '1', //类型(1、关注时回复;2、消息回复;3、关键词回复)
|
||||
objData: {
|
||||
repType: 'text'
|
||||
},
|
||||
handleType: null,
|
||||
dictData: new Map(),
|
||||
hackResetWxReplySelect: false
|
||||
})
|
||||
|
||||
const { tableData, tableLoading, page, dialog1Visible, objData, type, handleType, dictData, hackResetWxReplySelect } = toRefs(data)
|
||||
const permissionList = computed(() => {
|
||||
return {
|
||||
addBtn: checkPermi(['wxmp:wxautoreply:add']),
|
||||
delBtn: checkPermi(['wxmp:wxautoreply:del']),
|
||||
editBtn: checkPermi(['wxmp:wxautoreply:edit']),
|
||||
viewBtn: checkPermi(['wxmp:wxautoreply:get'])
|
||||
}
|
||||
})
|
||||
|
||||
function onCreated() {
|
||||
getPageF(data.page)
|
||||
data.dictData.set('wx_rep_mate', [
|
||||
{
|
||||
value: '1',
|
||||
label: '全匹配'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '半匹配'
|
||||
}
|
||||
])
|
||||
data.dictData.set('wx_req_type', [
|
||||
{
|
||||
value: 'text',
|
||||
label: '文本'
|
||||
},
|
||||
{
|
||||
value: 'image',
|
||||
label: '图片'
|
||||
},
|
||||
{
|
||||
value: 'voice',
|
||||
label: '语音'
|
||||
},
|
||||
{
|
||||
value: 'video',
|
||||
label: '视频'
|
||||
},
|
||||
{
|
||||
value: 'shortvideo',
|
||||
label: '小视频'
|
||||
},
|
||||
{
|
||||
value: 'location',
|
||||
label: '地理位置'
|
||||
},
|
||||
{
|
||||
value: 'link',
|
||||
label: '链接消息'
|
||||
},
|
||||
{
|
||||
value: 'event',
|
||||
label: '事件推送'
|
||||
}
|
||||
])
|
||||
}
|
||||
onCreated()
|
||||
|
||||
onMounted(() => {})
|
||||
|
||||
function handleAdd() {
|
||||
data.hackResetWxReplySelect = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetWxReplySelect = true //重建组件
|
||||
})
|
||||
data.handleType = 'add'
|
||||
data.dialog1Visible = true
|
||||
data.objData = {
|
||||
repType: 'text'
|
||||
}
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
data.hackResetWxReplySelect = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetWxReplySelect = true //重建组件
|
||||
})
|
||||
data.handleType = 'edit'
|
||||
data.dialog1Visible = true
|
||||
data.objData = Object.assign({}, row)
|
||||
}
|
||||
|
||||
function handleClick(tab, event) {
|
||||
data.tableData = []
|
||||
data.page.currentPage = 1
|
||||
data.type = tab.paneName
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function searchChange(params, done) {
|
||||
params = /* Warn: Unknown source: filterForm */ proxy.filterForm(params)
|
||||
data.paramsSearch = params
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page, params)
|
||||
done()
|
||||
}
|
||||
|
||||
function sortChange(val) {
|
||||
const prop = val.prop ? val.prop.replace(/([A-Z])/g, '_$1').toLowerCase() : ''
|
||||
if (val.order == 'ascending') {
|
||||
data.page.descs = []
|
||||
data.page.ascs = prop
|
||||
} else if (val.order == 'descending') {
|
||||
data.page.ascs = []
|
||||
data.page.descs = prop
|
||||
} else {
|
||||
data.page.ascs = []
|
||||
data.page.descs = []
|
||||
}
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize,
|
||||
descs: data.page.descs,
|
||||
ascs: data.page.ascs,
|
||||
type: data.type
|
||||
},
|
||||
params,
|
||||
data.paramsSearch
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.records
|
||||
data.page.total = response.data.total
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
if (data.type == '2') {
|
||||
const wxReqType = data.dictData.get('wx_req_type')
|
||||
for (let i = 0; i < wxReqType.length; i++) {
|
||||
wxReqType[i].disabled = false
|
||||
for (let j = 0; j < data.tableData.length; j++) {
|
||||
if (wxReqType[i].value == data.tableData[j].reqType) {
|
||||
wxReqType[i].disabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleDel(row, index) {
|
||||
proxy
|
||||
.$confirm('是否确认删除此数据', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(function () {
|
||||
return delObj(row.id)
|
||||
})
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function handleSubmit(row) {
|
||||
if (data.handleType == 'add') {
|
||||
addObj(
|
||||
Object.assign(
|
||||
{
|
||||
type: data.type
|
||||
},
|
||||
data.objData
|
||||
)
|
||||
).then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
data.dialog1Visible = false
|
||||
})
|
||||
}
|
||||
if (data.handleType == 'edit') {
|
||||
putObj(data.objData).then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
data.dialog1Visible = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpdate(row, index, done, loading) {
|
||||
putObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function handleSave(row, done, loading) {
|
||||
addObj(
|
||||
Object.assign(
|
||||
{
|
||||
type: data.type
|
||||
},
|
||||
data.objData
|
||||
)
|
||||
)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
data.dialog1Visible = false
|
||||
})
|
||||
.catch(() => {
|
||||
done()
|
||||
})
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
data.objData = {
|
||||
repType: 'text'
|
||||
}
|
||||
getPageF(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 去掉 ruoyi 的样式
|
||||
.avue-crud :deep(.el-card__body) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
793
src/views/wxmp/wxdraft/index.vue
Normal file
793
src/views/wxmp/wxdraft/index.vue
Normal file
@@ -0,0 +1,793 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="add_but">
|
||||
<el-button type="primary" @click="handleAddNews">新 增 </el-button>
|
||||
</div>
|
||||
<el-dialog
|
||||
:title="operateMaterial == 'add' ? '新建图文' : '修改图文'"
|
||||
append-to-body
|
||||
:before-close="dialogNewsClose"
|
||||
:close-on-click-modal="false"
|
||||
v-model="dialogNewsVisible"
|
||||
width="80%"
|
||||
top="20px"
|
||||
>
|
||||
<div class="left">
|
||||
<div class="select-item">
|
||||
<div v-for="(news, index) in articlesAdd" :key="news.id">
|
||||
<div class="news-main father" v-if="index == 0" :class="{ activeAddNews: isActiveAddNews == index }" @click="activeNews(index)">
|
||||
<div class="news-content">
|
||||
<el-image class="material-img" :src="news.thumbUrl">
|
||||
<template #error><div class="flex-c material-img">未设置</div> </template>
|
||||
</el-image>
|
||||
<div class="news-content-title">{{ news.title }}</div>
|
||||
</div>
|
||||
<div class="child" v-if="articlesAdd.length > 1">
|
||||
<el-button size="small" icon="Bottom" @click="downNews(index)">下移</el-button>
|
||||
<el-button v-if="operateMaterial == 'add'" size="small" type="danger" icon="Delete" @click="minusNews(index)">删除 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="news-main-item father" v-if="index > 0" :class="{ activeAddNews: isActiveAddNews == index }" @click="activeNews(index)">
|
||||
<div class="news-content-item">
|
||||
<div class="news-content-item-title">{{ news.title }}</div>
|
||||
<div class="news-content-item-img">
|
||||
<el-image class="material-img" style="height: 55px" :src="news.thumbUrl">
|
||||
<template #error><div class="flex-c material-img" style="background: #eeeeee">未设置</div> </template>
|
||||
</el-image>
|
||||
</div>
|
||||
</div>
|
||||
<div class="child">
|
||||
<el-button v-if="articlesAdd.length > index + 1" size="small" icon="Bottom" @click="downNews(index)">下移 </el-button>
|
||||
<el-button size="small" icon="Top" @click="upNews(index)">上移</el-button>
|
||||
<el-button v-if="operateMaterial == 'add'" size="small" type="danger" icon="Delete" @click="minusNews(index)">删除 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="articlesAdd.length < 8 && operateMaterial == 'add'" class="news-main-plus">
|
||||
<el-button @click="plusNews" type="primary" icon="Plus" circle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right" v-loading="addMaterialLoading">
|
||||
<!--富文本编辑器组件-->
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="封面标题" name="title">
|
||||
<div>
|
||||
<div class="thumb-div">
|
||||
<div class="input-tt" style="display: flex">封面:</div>
|
||||
<div>
|
||||
<img
|
||||
class="material-img"
|
||||
v-if="articlesAdd[isActiveAddNews].thumbUrl"
|
||||
:src="articlesAdd[isActiveAddNews].thumbUrl"
|
||||
:class="isActiveAddNews == 0 ? 'avatar' : 'avatar1'"
|
||||
/>
|
||||
<el-icon v-else class="avatar-uploader-icon" :class="isActiveAddNews == 0 ? 'avatar' : 'avatar1'"><Plus /></el-icon>
|
||||
<div class="thumb-but">
|
||||
<el-upload
|
||||
:action="actionUrl"
|
||||
:headers="headers"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-success="handleUploadSuccess"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeThumbImageUpload"
|
||||
:data="uploadData"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button size="small" type="primary"> 本地上传 </el-button>
|
||||
</template>
|
||||
<el-button size="small" type="primary" @click="openMaterial" style="margin-left: 5px">素材库选择 </el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">支持bmp/png/jpeg/jpg/gif格式,大小不超过2M</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="选择图片" v-model="dialogImageVisible" width="80%" append-to-body>
|
||||
<WxMaterialSelect :objData="{ repType: 'image' }" @selectMaterial="selectMaterial"></WxMaterialSelect>
|
||||
</el-dialog>
|
||||
<div class="digest">
|
||||
<div class="input-tt">标题:</div>
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].title" placeholder="请输入标题"></el-input>
|
||||
<div class="input-tt">作者:</div>
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].author" placeholder="请输入作者"></el-input>
|
||||
<div class="input-tt">原文地址:</div>
|
||||
<el-input v-model="articlesAdd[isActiveAddNews].contentSourceUrl" placeholder="请输入原文地址"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-tt">摘要:</div>
|
||||
<el-input :rows="5" type="textarea" v-model="articlesAdd[isActiveAddNews].digest" placeholder="请输入摘要" maxlength="120"></el-input>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="内容详情" name="content">
|
||||
<div style="padding-bottom: 20px">
|
||||
<WxEditor v-model="articlesAdd[isActiveAddNews].content" :minHeight="350" :uploadData="uploadData" v-if="hackResetEditor" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogNewsVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="subNews">提 交</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<div class="waterfall" v-loading="tableLoading">
|
||||
<template v-for="item in tableData" :key="item.id">
|
||||
<div v-if="item.content && item.content.newsItem" class="waterfall-item">
|
||||
<WxNews :objData="item.content.newsItem"></WxNews>
|
||||
<el-row class="ope-row">
|
||||
<el-button type="success" icon="Promotion" size="small" @click="handlePublishNews(item)">发布</el-button>
|
||||
<el-button type="primary" size="small" plain icon="el-icon-edit" @click="handleEditNews(item)">编辑</el-button>
|
||||
<el-button type="danger" size="small" plain icon="el-icon-delete" @click="delMaterial(item)">删除</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="tableData.length <= 0 && !tableLoading" class="el-table__empty-block">
|
||||
<el-empty />
|
||||
</div>
|
||||
<el-pagination
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
v-model:current-page="page.currentPage"
|
||||
:page-sizes="[10, 20]"
|
||||
:page-size="page.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="page.total"
|
||||
class="pagination"
|
||||
>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpDraft">
|
||||
import { getPage, addObj, delObj, putObj, publish } from '@/api/wxmp/wxdraft'
|
||||
import { getPage as getPage1 } from '@/api/wxmp/wxmaterial'
|
||||
import WxEditor from '@/components/WxEditor/WxEditor.vue'
|
||||
import WxNews from '@/components/wx-news/main.vue'
|
||||
import WxMaterialSelect from '@/components/wx-material-select/main.vue'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { getCurrentInstance, nextTick, onMounted, reactive } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
page1: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
tableLoading: false,
|
||||
fileList: [],
|
||||
dialogVideoVisible: false,
|
||||
dialogNewsVisible: false,
|
||||
addMaterialLoading: false,
|
||||
uploadData: {
|
||||
mediaType: 'image',
|
||||
title: '',
|
||||
introduction: ''
|
||||
},
|
||||
articlesAdd: [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
],
|
||||
isActiveAddNews: 0,
|
||||
dialogImageVisible: false,
|
||||
imageListData: [],
|
||||
tableLoading1: false,
|
||||
operateMaterial: 'add',
|
||||
articlesMediaId: '',
|
||||
hackResetEditor: false,
|
||||
actionUrl: ref(import.meta.env.VITE_APP_BASE_API + '/wxmaterial/materialFileUpload'), // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + getToken()
|
||||
},
|
||||
activeName: 'title'
|
||||
})
|
||||
const {
|
||||
activeName,
|
||||
materialType,
|
||||
tableData,
|
||||
tableLoading,
|
||||
page,
|
||||
page1,
|
||||
fileList,
|
||||
dialogVideoVisible,
|
||||
dialogNewsVisible,
|
||||
addMaterialLoading,
|
||||
uploadData,
|
||||
uploadRules,
|
||||
articlesAdd,
|
||||
isActiveAddNews,
|
||||
dialogImageVisible,
|
||||
imageListData,
|
||||
tableLoading1,
|
||||
operateMaterial,
|
||||
articlesMediaId,
|
||||
hackResetEditor,
|
||||
actionUrl,
|
||||
headers
|
||||
} = toRefs(data)
|
||||
|
||||
onMounted(() => {
|
||||
getPageF(data.page)
|
||||
})
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableData = []
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize
|
||||
},
|
||||
params
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.items
|
||||
data.page.total = response.data.totalCount
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function sizeChange(val) {
|
||||
data.page.currentPage = 1
|
||||
data.page.pageSize = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function currentChange(val) {
|
||||
data.page.currentPage = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function delMaterial(item) {
|
||||
proxy
|
||||
.$confirm('此操作将永久删除该草稿, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.tableLoading = true
|
||||
delObj({
|
||||
id: item.mediaId
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
data.tableLoading = false
|
||||
|
||||
proxy.$message.error('删除出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getPage1F() {
|
||||
data.tableLoading1 = true
|
||||
getPage1({
|
||||
current: data.page1.currentPage,
|
||||
size: data.page1.pageSize,
|
||||
type: 'image'
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading1 = false
|
||||
data.imageListData = response.data.items
|
||||
data.page1.total = response.data.totalCount
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading1 = false
|
||||
})
|
||||
}
|
||||
|
||||
function openMaterial() {
|
||||
data.imageListData = null
|
||||
data.page1.currentPage = 1
|
||||
getPage1F()
|
||||
data.dialogImageVisible = true
|
||||
}
|
||||
|
||||
function dialogNewsClose(done) {
|
||||
/* Warn: Unknown source: $confirm */
|
||||
proxy
|
||||
.$confirm('修改内容可能还未保存,确定关闭吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
data.isActiveAddNews = 0
|
||||
done()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function downNews(index) {
|
||||
const temp = data.articlesAdd[index]
|
||||
data.articlesAdd[index] = data.articlesAdd[index + 1]
|
||||
data.articlesAdd[index + 1] = temp
|
||||
data.isActiveAddNews = index + 1
|
||||
}
|
||||
|
||||
function upNews(index) {
|
||||
const temp = data.articlesAdd[index]
|
||||
data.articlesAdd[index] = data.articlesAdd[index - 1]
|
||||
data.articlesAdd[index - 1] = temp
|
||||
data.isActiveAddNews = index - 1
|
||||
}
|
||||
|
||||
function activeNews(index) {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
data.isActiveAddNews = index
|
||||
}
|
||||
|
||||
function minusNews(index) {
|
||||
proxy
|
||||
.$confirm('确定删除该图文吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.articlesAdd.splice(index, 1)
|
||||
if (data.isActiveAddNews == index) {
|
||||
data.isActiveAddNews = 0
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function plusNews() {
|
||||
data.articlesAdd.push({
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
})
|
||||
data.isActiveAddNews = data.articlesAdd.length - 1
|
||||
}
|
||||
|
||||
function subNews() {
|
||||
data.addMaterialLoading = true
|
||||
if (data.operateMaterial == 'add') {
|
||||
addObj({
|
||||
articles: data.articlesAdd
|
||||
})
|
||||
.then((response) => {
|
||||
data.addMaterialLoading = false
|
||||
data.dialogNewsVisible = false
|
||||
if (response.code == 200) {
|
||||
data.isActiveAddNews = 0
|
||||
data.articlesAdd = [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
]
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error('新增图文出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.addMaterialLoading = false
|
||||
})
|
||||
}
|
||||
if (data.operateMaterial == 'edit') {
|
||||
putObj({
|
||||
articles: data.articlesAdd,
|
||||
mediaId: data.articlesMediaId
|
||||
})
|
||||
.then((response) => {
|
||||
data.addMaterialLoading = false
|
||||
data.dialogNewsVisible = false
|
||||
if (response.code == 200) {
|
||||
data.isActiveAddNews = 0
|
||||
data.articlesAdd = [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
]
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error('修改图文出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.addMaterialLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function handleEditNews(item) {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
if (data.operateMaterial == 'add') {
|
||||
data.isActiveAddNews = 0
|
||||
}
|
||||
data.operateMaterial = 'edit'
|
||||
data.articlesAdd = JSON.parse(JSON.stringify(item.content.newsItem))
|
||||
data.articlesMediaId = item.mediaId
|
||||
data.dialogNewsVisible = true
|
||||
}
|
||||
|
||||
function handleAddNews() {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
if (data.operateMaterial == 'edit') {
|
||||
data.isActiveAddNews = 0
|
||||
data.articlesAdd = [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
data.operateMaterial = 'add'
|
||||
data.dialogNewsVisible = true
|
||||
}
|
||||
|
||||
function beforeThumbImageUpload(file) {
|
||||
data.addMaterialLoading = true
|
||||
const isType = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/bmp' || file.type === 'image/jpg'
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isType) {
|
||||
proxy.$message.error('上传图片格式不对!')
|
||||
}
|
||||
if (!isLt) {
|
||||
proxy.$message.error('上传图片大小不能超过2M!')
|
||||
}
|
||||
data.addMaterialLoading = false
|
||||
return isType && isLt
|
||||
}
|
||||
|
||||
function handleUploadSuccess(response, file, fileList) {
|
||||
data.tableLoading = false
|
||||
data.addMaterialLoading = false
|
||||
if (response.code == 200) {
|
||||
data.dialogVideoVisible = false
|
||||
data.fileList = []
|
||||
data.uploadData.title = ''
|
||||
data.uploadData.introduction = ''
|
||||
data.articlesAdd[data.isActiveAddNews].thumbMediaId = response.data.mediaId
|
||||
data.articlesAdd[data.isActiveAddNews].thumbUrl = response.data.url
|
||||
} else {
|
||||
proxy.$message.error('上传出错:' + response.msg)
|
||||
}
|
||||
}
|
||||
|
||||
function selectMaterial(item) {
|
||||
data.dialogImageVisible = false
|
||||
data.articlesAdd[data.isActiveAddNews].thumbMediaId = item.mediaId
|
||||
data.articlesAdd[data.isActiveAddNews].thumbUrl = item.url
|
||||
}
|
||||
|
||||
function handlePublishNews(item) {
|
||||
proxy
|
||||
.$confirm(
|
||||
'你正在通过发布的方式发表内容。 发布不占用群发次数,一天可多次发布。已发布内容不会推送给用户,也不会展示在公众号主页中。 发布后,你可以前往发表记录获取链接,也可以将发布内容添加到自定义菜单、自动回复、话题和页面模板中。',
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
data.tableLoading = true
|
||||
publish(item.mediaId)
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
|
||||
proxy.$message.success('发布任务提交成功')
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
float: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.add_but {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.ope-row {
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eaeaea;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
.el-upload__tip {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.left {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
vertical-align: top;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.right {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
min-height: 500px;
|
||||
}
|
||||
.avatar-uploader {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: unset !important;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #165dff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 220px;
|
||||
height: 120px;
|
||||
}
|
||||
.avatar1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.digest {
|
||||
width: 70%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap: 10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
.news-main {
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 120px;
|
||||
}
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
}
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
color: #ffffff;
|
||||
position: absolute;
|
||||
min-height: 25px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
padding: 5px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.news-main-item {
|
||||
background-color: #ffffff;
|
||||
padding: 5px 0px;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
align-items: center;
|
||||
width: 70%;
|
||||
}
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
// background-color: #acadae;
|
||||
}
|
||||
.input-tt {
|
||||
padding: 5px;
|
||||
}
|
||||
.activeAddNews {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.activeAddNews::before {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
content: '';
|
||||
border: 5px solid #2bb673;
|
||||
}
|
||||
.news-main-plus {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 50px;
|
||||
}
|
||||
.icon-plus {
|
||||
margin: 10px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.select-item {
|
||||
width: 60%;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.father .child {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 25px;
|
||||
height: 0;
|
||||
}
|
||||
.father:hover .child {
|
||||
display: block;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.thumb-div {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
.thumb-but {
|
||||
margin: 5px;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.flex-c {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
331
src/views/wxmp/wxfreepublish/index.vue
Normal file
331
src/views/wxmp/wxfreepublish/index.vue
Normal file
@@ -0,0 +1,331 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="waterfall" v-loading="tableLoading">
|
||||
<template v-for="item in tableData" :key="item.id">
|
||||
<div v-if="item.content && item.content.newsItem" class="waterfall-item">
|
||||
<WxNews :objData="item.content.newsItem"></WxNews>
|
||||
<el-row class="ope-row flex-c">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="delMaterial(item)"></el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="tableData.length <= 0 && !tableLoading" class="el-table__empty-block">
|
||||
<el-empty />
|
||||
</div>
|
||||
<el-pagination
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
v-model:current-page="page.currentPage"
|
||||
:page-sizes="[10, 20]"
|
||||
:page-size="page.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="page.total"
|
||||
class="pagination"
|
||||
>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpFreePublish">
|
||||
import { getPage, delObj } from '@/api/wxmp/wxfreepublish'
|
||||
import WxNews from '@/components/wx-news/main.vue'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { getCurrentInstance, onMounted, reactive, ref, watch } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const tree = ref(null)
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
page1: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
tableLoading: false,
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + getToken()
|
||||
}
|
||||
})
|
||||
const { tableData, tableLoading, page, page1, headers } = toRefs(data)
|
||||
|
||||
watch(
|
||||
() => proxy.filterText,
|
||||
(val) => {
|
||||
tree.value.filter(val)
|
||||
}
|
||||
)
|
||||
onMounted(() => {
|
||||
getPageF(data.page)
|
||||
})
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableData = []
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize
|
||||
},
|
||||
params
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.items
|
||||
data.page.total = response.data.totalCount
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function sizeChange(val) {
|
||||
data.page.currentPage = 1
|
||||
data.page.pageSize = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function currentChange(val) {
|
||||
data.page.currentPage = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function delMaterial(item) {
|
||||
proxy
|
||||
.$confirm('删除后用户将无法访问此页面,确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.tableLoading = true
|
||||
delObj({
|
||||
id: item.articleId
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
data.tableLoading = false
|
||||
proxy.$message.error('删除出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
float: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.add_but {
|
||||
padding: 10px;
|
||||
}
|
||||
.ope-row {
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eaeaea;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
.el-upload__tip {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.left {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
vertical-align: top;
|
||||
margin-top: 200px;
|
||||
}
|
||||
.right {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
margin-top: -40px;
|
||||
}
|
||||
.avatar-uploader {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: unset !important;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #165dff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 230px;
|
||||
height: 120px;
|
||||
}
|
||||
.avatar1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.digest {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap: 10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
.news-main {
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 120px;
|
||||
}
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
}
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
color: #ffffff;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
width: 98%;
|
||||
padding: 1%;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
height: 25px;
|
||||
}
|
||||
.news-main-item {
|
||||
background-color: #ffffff;
|
||||
padding: 5px 0px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
margin-left: -3px;
|
||||
}
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
background-color: #acadae;
|
||||
}
|
||||
.input-tt {
|
||||
padding: 5px;
|
||||
}
|
||||
.activeAddNews {
|
||||
border: 5px solid #2bb673;
|
||||
}
|
||||
.news-main-plus {
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
}
|
||||
.icon-plus {
|
||||
margin: 10px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.select-item {
|
||||
width: 60%;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.father .child {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 25px;
|
||||
}
|
||||
.father:hover .child {
|
||||
display: block;
|
||||
}
|
||||
.thumb-div {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
.thumb-but {
|
||||
margin: 5px;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
886
src/views/wxmp/wxmaterial/index.vue
Normal file
886
src/views/wxmp/wxmaterial/index.vue
Normal file
@@ -0,0 +1,886 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="materialType" @tab-click="handleClick">
|
||||
<el-tab-pane name="image">
|
||||
<template #label>
|
||||
<span>图片</span>
|
||||
</template>
|
||||
<div class="add_but">
|
||||
<el-upload
|
||||
:action="actionUrl"
|
||||
:headers="headers"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeImageUpload"
|
||||
:data="uploadData"
|
||||
>
|
||||
<el-button type="primary" icon="Upload">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">支持bmp/png/jpeg/jpg/gif格式,大小不超过2M</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="waterfall" v-loading="tableLoading">
|
||||
<div class="waterfall-item" v-for="item in tableData" :key="item.id">
|
||||
<a target="_blank" :href="item.url">
|
||||
<img class="material-img" :src="item.url" />
|
||||
<div class="item-name">{{ item.name }}</div>
|
||||
</a>
|
||||
<el-row class="ope-row flex-c">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="delMaterial(item)"></el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tableData.length <= 0 && !tableLoading" class="el-table__empty-block">
|
||||
<el-empty />
|
||||
</div>
|
||||
<el-pagination
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
v-model:current-page="page.currentPage"
|
||||
:page-sizes="[10, 20]"
|
||||
:page-size="page.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="page.total"
|
||||
class="pagination"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="voice">
|
||||
<template #label>
|
||||
<span>语音</span>
|
||||
</template>
|
||||
<div class="add_but">
|
||||
<el-upload
|
||||
:action="actionUrl"
|
||||
:headers="headers"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-success="handleUploadSuccess"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeVoiceUpload"
|
||||
:data="uploadData"
|
||||
>
|
||||
<el-button type="primary" icon="Upload">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">格式支持mp3/wma/wav/amr,文件大小不超过2M,播放长度不超过60s</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-table :data="tableData" stripe border v-loading="tableLoading">
|
||||
<el-table-column prop="mediaId" label="media_id"> </el-table-column>
|
||||
<el-table-column prop="name" label="名称"> </el-table-column>
|
||||
<el-table-column prop="updateTime" label="更新时间"> </el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot="scope">
|
||||
<el-button link icon="el-icon-download" type="primary" @click="handleDown(scope.row)">下载</el-button>
|
||||
<el-button link icon="el-icon-delete" type="danger" @click="delMaterial(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
v-model:current-page="page.currentPage"
|
||||
:page-sizes="[10, 20]"
|
||||
:page-size="page.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="page.total"
|
||||
class="pagination"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="video">
|
||||
<template #label>
|
||||
<span>视频</span>
|
||||
</template>
|
||||
<div class="add_but">
|
||||
<el-button type="primary" icon="Plus" @click="handleAddVideo">新建</el-button>
|
||||
</div>
|
||||
<el-dialog title="新建视频" v-model="dialogVideoVisible">
|
||||
<el-upload
|
||||
ref="uploadVideo"
|
||||
:action="actionUrl"
|
||||
:headers="headers"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-success="handleUploadSuccess"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeVideoUpload"
|
||||
:auto-upload="false"
|
||||
:data="uploadData"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">选择视频</el-button>
|
||||
</template>
|
||||
<div class="el-upload__tip">格式支持MP4,文件大小不超过10MB</div>
|
||||
</el-upload>
|
||||
<el-form :model="uploadData" :rules="uploadRules" ref="uploadForm">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="uploadData.title" placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="introduction">
|
||||
<el-input
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
v-model="uploadData.introduction"
|
||||
placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVideoVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="subVideo">提 交</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-table :data="tableData" stripe border v-loading="tableLoading">
|
||||
<el-table-column prop="mediaId" label="media_id"> </el-table-column>
|
||||
<el-table-column prop="name" label="名称"> </el-table-column>
|
||||
<el-table-column prop="updateTime" label="更新时间"> </el-table-column>
|
||||
<el-table-column fixed="right" label="操作">
|
||||
<template v-slot="scope">
|
||||
<el-button link icon="el-icon-view" type="primary" @click="handleInfo(scope.row)">查看</el-button>
|
||||
<el-button link icon="el-icon-delete" type="danger" @click="delMaterial(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
v-model:current-page="page.currentPage"
|
||||
:page-sizes="[10, 20]"
|
||||
:page-size="page.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="page.total"
|
||||
class="pagination"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpMaterial">
|
||||
import { getPage, addObj, delObj, getMaterialOther, getMaterialVideo } from '@/api/wxmp/wxmaterial'
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
import WxEditor from '@/components/WxEditor/WxEditor.vue'
|
||||
import WxNews from '@/components/wx-news/main.vue'
|
||||
import WxMaterialSelect from '@/components/wx-material-select/main.vue'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const uploadVideo = ref(null)
|
||||
|
||||
const data = reactive({
|
||||
materialType: 'image',
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
page1: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 10 // 每页显示多少条
|
||||
},
|
||||
tableLoading: false,
|
||||
fileList: [],
|
||||
dialogVideoVisible: false,
|
||||
dialogNewsVisible: false,
|
||||
addMaterialLoading: false,
|
||||
uploadData: {
|
||||
mediaType: 'image',
|
||||
title: '',
|
||||
introduction: ''
|
||||
},
|
||||
uploadRules: {
|
||||
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
|
||||
introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }]
|
||||
},
|
||||
articlesAdd: [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
],
|
||||
isActiveAddNews: 0,
|
||||
dialogImageVisible: false,
|
||||
imageListData: [],
|
||||
tableLoading1: false,
|
||||
operateMaterial: 'add',
|
||||
articlesMediaId: '',
|
||||
hackResetEditor: false,
|
||||
actionUrl: ref(import.meta.env.VITE_APP_BASE_API + '/wxmaterial/materialFileUpload'), // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + getToken()
|
||||
}
|
||||
})
|
||||
|
||||
const {
|
||||
materialType,
|
||||
tableData,
|
||||
tableLoading,
|
||||
page,
|
||||
page1,
|
||||
fileList,
|
||||
dialogVideoVisible,
|
||||
dialogNewsVisible,
|
||||
addMaterialLoading,
|
||||
uploadData,
|
||||
uploadRules,
|
||||
articlesAdd,
|
||||
isActiveAddNews,
|
||||
dialogImageVisible,
|
||||
imageListData,
|
||||
tableLoading1,
|
||||
operateMaterial,
|
||||
articlesMediaId,
|
||||
hackResetEditor,
|
||||
actionUrl,
|
||||
headers
|
||||
} = toRefs(data)
|
||||
onMounted(() => {
|
||||
getPageF(data.page)
|
||||
})
|
||||
|
||||
function dialogNewsClose(done) {
|
||||
proxy
|
||||
.$confirm('修改内容可能还未保存,确定关闭吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
data.isActiveAddNews = 0
|
||||
done()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function downNews(index) {
|
||||
const temp = data.articlesAdd[index]
|
||||
data.articlesAdd[index] = data.articlesAdd[index + 1]
|
||||
data.articlesAdd[index + 1] = temp
|
||||
data.isActiveAddNews = index + 1
|
||||
}
|
||||
|
||||
function upNews(index) {
|
||||
const temp = data.articlesAdd[index]
|
||||
data.articlesAdd[index] = data.articlesAdd[index - 1]
|
||||
data.articlesAdd[index - 1] = temp
|
||||
data.isActiveAddNews = index - 1
|
||||
}
|
||||
|
||||
function getPage1() {
|
||||
data.tableLoading1 = true
|
||||
getPageF({
|
||||
current: data.page1.currentPage,
|
||||
size: data.page1.pageSize,
|
||||
type: 'image'
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading1 = false
|
||||
data.imageListData = response.data.items
|
||||
data.page1.total = response.data.totalCount
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading1 = false
|
||||
})
|
||||
}
|
||||
|
||||
function selectMaterial(item) {
|
||||
data.dialogImageVisible = false
|
||||
data.articlesAdd[data.isActiveAddNews].thumbMediaId = item.mediaId
|
||||
data.articlesAdd[data.isActiveAddNews].thumbUrl = item.url
|
||||
}
|
||||
|
||||
function openMaterial() {
|
||||
data.imageListData = null
|
||||
data.page1.currentPage = 1
|
||||
getPage1()
|
||||
data.dialogImageVisible = true
|
||||
}
|
||||
|
||||
function activeNews(index) {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
data.isActiveAddNews = index
|
||||
}
|
||||
|
||||
function minusNews(index) {
|
||||
proxy
|
||||
.$confirm('确定删除该图文吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.articlesAdd.splice(index, 1)
|
||||
if (data.isActiveAddNews == index) {
|
||||
data.isActiveAddNews = 0
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function plusNews() {
|
||||
data.articlesAdd.push({
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
})
|
||||
data.isActiveAddNews = data.articlesAdd.length - 1
|
||||
}
|
||||
|
||||
function handleInfo(row) {
|
||||
data.tableLoading = true
|
||||
getMaterialVideo({
|
||||
mediaId: row.mediaId
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
const downUrl = response.data.downUrl
|
||||
window.open(downUrl, '_blank')
|
||||
} else {
|
||||
proxy.$message.error('获取微信视频素材出错:' + response.data.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleDown(row) {
|
||||
data.tableLoading = true
|
||||
getMaterialOther({
|
||||
mediaId: row.mediaId,
|
||||
fileName: row.name
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]))
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
link.setAttribute('download', row.name)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function subNews() {
|
||||
data.addMaterialLoading = true
|
||||
if (data.operateMaterial == 'add') {
|
||||
addObj({
|
||||
articles: data.articlesAdd
|
||||
})
|
||||
.then((response) => {
|
||||
data.addMaterialLoading = false
|
||||
data.dialogNewsVisible = false
|
||||
if (response.code == 200) {
|
||||
data.isActiveAddNews = 0
|
||||
data.articlesAdd = [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
]
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error('新增图文出错:' + response.data.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.addMaterialLoading = false
|
||||
})
|
||||
}
|
||||
if (data.operateMaterial == 'edit') {
|
||||
// materialNewsUpdate({
|
||||
// articles: data.articlesAdd,
|
||||
// mediaId: data.articlesMediaId,
|
||||
// })
|
||||
// .then((response) => {
|
||||
// data.addMaterialLoading = false;
|
||||
// data.dialogNewsVisible = false;
|
||||
// if (response.code == 200) {
|
||||
// data.isActiveAddNews = 0;
|
||||
// data.articlesAdd = [
|
||||
// {
|
||||
// title: "",
|
||||
// thumbMediaId: "",
|
||||
// author: "",
|
||||
// digest: "",
|
||||
// showCoverPic: "",
|
||||
// content: "",
|
||||
// contentSourceUrl: "",
|
||||
// needOpenComment: "",
|
||||
// onlyFansCanComment: "",
|
||||
// thumbUrl: "",
|
||||
// },
|
||||
// ];
|
||||
// getPageF(data.page);
|
||||
// } else {
|
||||
// proxy.$message.error("修改图文出错:" + response.data.msg);
|
||||
// }
|
||||
// })
|
||||
// .catch(() => {
|
||||
// data.addMaterialLoading = false;
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
function subVideo() {
|
||||
proxy.$refs.uploadForm.validate((valid) => {
|
||||
if (valid) {
|
||||
uploadVideo.value.submit()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleAddVideo() {
|
||||
data.dialogVideoVisible = true
|
||||
}
|
||||
|
||||
function handleEditNews(item) {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
if (data.operateMaterial == 'add') {
|
||||
data.isActiveAddNews = 0
|
||||
}
|
||||
data.operateMaterial = 'edit'
|
||||
data.articlesAdd = JSON.parse(JSON.stringify(item.content.articles))
|
||||
data.articlesMediaId = item.mediaId
|
||||
data.dialogNewsVisible = true
|
||||
}
|
||||
|
||||
function handleAddNews() {
|
||||
data.hackResetEditor = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetEditor = true //重建组件
|
||||
})
|
||||
if (data.operateMaterial == 'edit') {
|
||||
data.isActiveAddNews = 0
|
||||
data.articlesAdd = [
|
||||
{
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: '',
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: '',
|
||||
onlyFansCanComment: '',
|
||||
thumbUrl: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
data.operateMaterial = 'add'
|
||||
data.dialogNewsVisible = true
|
||||
}
|
||||
|
||||
function beforeThumbImageUpload(file) {
|
||||
data.addMaterialLoading = true
|
||||
const isType = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/bmp' || file.type === 'image/jpg'
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isType) {
|
||||
proxy.$message.error('上传图片格式不对!')
|
||||
}
|
||||
if (!isLt) {
|
||||
proxy.$message.error('上传图片大小不能超过2M!')
|
||||
}
|
||||
data.addMaterialLoading = false
|
||||
return isType && isLt
|
||||
}
|
||||
|
||||
function beforeImageUpload(file) {
|
||||
data.tableLoading = true
|
||||
const isType = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/bmp' || file.type === 'image/jpg'
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isType) {
|
||||
proxy.$message.error('上传图片格式不对!')
|
||||
}
|
||||
if (!isLt) {
|
||||
proxy.$message.error('上传图片大小不能超过2M!')
|
||||
}
|
||||
data.tableLoading = false
|
||||
return isType && isLt
|
||||
}
|
||||
|
||||
function beforeVoiceUpload(file) {
|
||||
data.tableLoading = true
|
||||
const isType = file.type === 'audio/mp3' || file.type === 'audio/wma' || file.type === 'audio/wav' || file.type === 'audio/amr'
|
||||
const isLt = file.size / 1024 / 1024 < 2
|
||||
if (!isType) {
|
||||
proxy.$message.error('上传语音格式不对!')
|
||||
}
|
||||
if (!isLt) {
|
||||
proxy.$message.error('上传语音大小不能超过2M!')
|
||||
}
|
||||
data.tableLoading = false
|
||||
return isType && isLt
|
||||
}
|
||||
|
||||
function beforeVideoUpload(file) {
|
||||
data.addMaterialLoading = true
|
||||
const isType = file.type === 'video/mp4'
|
||||
const isLt = file.size / 1024 / 1024 < 10
|
||||
if (!isType) {
|
||||
proxy.$message.error('上传视频格式不对!')
|
||||
}
|
||||
if (!isLt) {
|
||||
proxy.$message.error('上传视频大小不能超过10M!')
|
||||
}
|
||||
data.addMaterialLoading = false
|
||||
return isType && isLt
|
||||
}
|
||||
|
||||
function delMaterial(item) {
|
||||
proxy
|
||||
.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.tableLoading = true
|
||||
delObj({
|
||||
id: item.mediaId
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
data.tableLoading = false
|
||||
|
||||
proxy.$message.error('删除出错:' + response.data.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleUploadError(response) {
|
||||
proxy.$message.error('上传出错:' + response)
|
||||
}
|
||||
function handleUploadSuccess(response, file, fileList) {
|
||||
data.tableLoading = false
|
||||
data.addMaterialLoading = false
|
||||
if (response.code == 200) {
|
||||
data.dialogVideoVisible = false
|
||||
data.fileList = []
|
||||
data.uploadData.title = ''
|
||||
data.uploadData.introduction = ''
|
||||
if (data.materialType != 'news') {
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
data.articlesAdd[data.isActiveAddNews].thumbMediaId = response.data.mediaId
|
||||
data.articlesAdd[data.isActiveAddNews].thumbUrl = response.data.url
|
||||
}
|
||||
} else {
|
||||
data.fileList = []
|
||||
proxy.$message.error('上传出错:' + response.msg)
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick(tab, event) {
|
||||
const materialType = tab.paneName
|
||||
data.page.currentPage = 1
|
||||
data.materialType = materialType
|
||||
getPageF(data.page)
|
||||
data.uploadData.mediaType = materialType
|
||||
if (materialType == 'news') {
|
||||
data.uploadData.mediaType = 'image'
|
||||
}
|
||||
}
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableData = []
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize,
|
||||
type: data.materialType
|
||||
},
|
||||
params
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.items
|
||||
data.page.total = response.data.totalCount
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function sizeChange(val) {
|
||||
data.page.currentPage = 1
|
||||
data.page.pageSize = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function currentChange(val) {
|
||||
data.page.currentPage = val
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
getPageF(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
float: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.add_but {
|
||||
padding: 10px;
|
||||
}
|
||||
.ope-row {
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eaeaea;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
.el-upload__tip {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.left {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
vertical-align: top;
|
||||
margin-top: 200px;
|
||||
}
|
||||
.right {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
margin-top: -40px;
|
||||
}
|
||||
.avatar-uploader {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: unset !important;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px solid #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 230px;
|
||||
height: 120px;
|
||||
}
|
||||
.avatar1 {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.digest {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
.waterfall {
|
||||
width: 100%;
|
||||
column-gap: 10px;
|
||||
column-count: 5;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.waterfall-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
break-inside: avoid;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
p {
|
||||
line-height: 30px;
|
||||
}
|
||||
@media (min-width: 992px) and (max-width: 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
.waterfall {
|
||||
column-count: 2;
|
||||
}
|
||||
p {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.waterfall {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
.news-main {
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 120px;
|
||||
}
|
||||
.news-content {
|
||||
background-color: #acadae;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
}
|
||||
.news-content-title {
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
color: #ffffff;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
width: 98%;
|
||||
padding: 1%;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
height: 25px;
|
||||
}
|
||||
.news-main-item {
|
||||
background-color: #ffffff;
|
||||
padding: 5px 0px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.news-content-item {
|
||||
position: relative;
|
||||
margin-left: -3px;
|
||||
}
|
||||
.news-content-item-title {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
.news-content-item-img {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
background-color: #acadae;
|
||||
}
|
||||
.input-tt {
|
||||
padding: 5px;
|
||||
}
|
||||
.activeAddNews {
|
||||
border: 5px solid #2bb673;
|
||||
}
|
||||
.news-main-plus {
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
}
|
||||
.icon-plus {
|
||||
margin: 10px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.select-item {
|
||||
width: 60%;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.father .child {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 25px;
|
||||
}
|
||||
.father:hover .child {
|
||||
display: block;
|
||||
}
|
||||
.thumb-div {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
.thumb-but {
|
||||
margin: 5px;
|
||||
}
|
||||
.material-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
BIN
src/views/wxmp/wxmenu/assets/demo.png
Normal file
BIN
src/views/wxmp/wxmenu/assets/demo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
src/views/wxmp/wxmenu/assets/iphone_backImg.png
Normal file
BIN
src/views/wxmp/wxmenu/assets/iphone_backImg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
src/views/wxmp/wxmenu/assets/logo.png
Normal file
BIN
src/views/wxmp/wxmenu/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
BIN
src/views/wxmp/wxmenu/assets/menu_foot.png
Normal file
BIN
src/views/wxmp/wxmenu/assets/menu_foot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/views/wxmp/wxmenu/assets/menu_head.png
Normal file
BIN
src/views/wxmp/wxmenu/assets/menu_head.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
564
src/views/wxmp/wxmenu/detail.vue
Normal file
564
src/views/wxmp/wxmenu/detail.vue
Normal file
@@ -0,0 +1,564 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="public-account-management clearfix" v-loading="saveLoading">
|
||||
<!--左边配置菜单-->
|
||||
<div class="left">
|
||||
<div class="weixin-hd">
|
||||
<div class="weixin-title">
|
||||
{{ menuName }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="weixin-menu menu_main clearfix">
|
||||
<div class="menu_bottom" v-for="(item, i) of menu.button" :key="i">
|
||||
<!-- 一级菜单 -->
|
||||
<div @click="menuFun(i, item)" class="menu_item el-icon-s-fold" :class="{ active: isActive == i }">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<!--以下为二级菜单-->
|
||||
<div class="submenu" v-if="isSubMenuFlag == i">
|
||||
<template v-for="(subItem, k) in item.sub_button" :key="k">
|
||||
<div v-if="item.sub_button" class="subtitle menu_bottom">
|
||||
<div class="menu_subItem" :class="{ active: isSubMenuActive == i + '' + k }" @click="subMenuFun(subItem, i, k)">
|
||||
{{ subItem.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
|
||||
<div class="menu_bottom menu_addicon" v-if="!item.sub_button || item.sub_button.length < 5" @click="addSubMenu(i, item)">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 一级菜单加号 -->
|
||||
<div class="menu_bottom menu_addicon" v-if="menuKeyLength < 3" @click="addMenu">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="save_div">
|
||||
<!--<el-button class="save_btn" type="warning" size="small" @click="saveFun">保存菜单</el-button>-->
|
||||
<el-button class="save_btn" type="success" size="small" @click="saveAndReleaseFun">保存并发布菜单</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!--右边配置-->
|
||||
<div v-if="showRightFlag" class="right">
|
||||
<div class="configure_page">
|
||||
<div class="delete_btn">
|
||||
<el-button size="small" type="danger" icon="el-icon-delete" @click="deleteMenu(tempObj)">删除当前菜单</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<span>菜单名称:</span>
|
||||
<el-input class="input_width" v-model="tempObj.name" placeholder="请输入菜单名称" :maxlength="nameMaxlength" clearable></el-input>
|
||||
</div>
|
||||
<div v-if="showConfigurContent">
|
||||
<div class="menu_content">
|
||||
<span>菜单内容:</span>
|
||||
<el-select v-model="tempObj.type" clearable placeholder="请选择" class="menu_option">
|
||||
<el-option v-for="item in menuOptions" :label="item.label" :value="item.value" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type == 'view'">
|
||||
<span>跳转链接:</span>
|
||||
<el-input class="input_width" v-model="tempObj.url" placeholder="请输入链接" clearable></el-input>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type == 'miniprogram'">
|
||||
<div class="applet">
|
||||
<span>小程序的appid:</span>
|
||||
<el-input class="input_width" v-model="tempObj.appid" placeholder="请输入小程序的appid" clearable></el-input>
|
||||
</div>
|
||||
<div class="applet">
|
||||
<span>小程序的页面路径:</span>
|
||||
<el-input class="input_width" v-model="tempObj.pagepath" placeholder="请输入小程序的页面路径,如:pages/index" clearable></el-input>
|
||||
</div>
|
||||
<div class="applet">
|
||||
<span>备用网页:</span>
|
||||
<el-input class="input_width" v-model="tempObj.url" placeholder="不支持小程序的老版本客户端将打开本网页" clearable></el-input>
|
||||
</div>
|
||||
<p class="blue">tips:需要和公众号进行关联才可以把小程序绑定带微信菜单上哟!</p>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type == 'article_view_limited'">
|
||||
<el-row>
|
||||
<div class="select-item" v-if="tempObj && tempObj.content && tempObj.content.articles">
|
||||
<WxNews :objData="tempObj.content.articles"></WxNews>
|
||||
<el-row class="ope-row">
|
||||
<el-button type="danger" icon="el-icon-delete" circle @click="deleteTempObj"></el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
<div v-if="!tempObj.content || !tempObj.content.articles">
|
||||
<el-row>
|
||||
<el-col :span="24" style="text-align: center">
|
||||
<el-button type="success" @click="openMaterial"
|
||||
>素材库选择<el-icon class="el-icon--right"><CircleCheck /></el-icon
|
||||
></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-dialog title="选择图文" v-model="dialogNewsVisible" width="90%">
|
||||
<WxMaterialSelect :objData="{ repType: 'news' }" @selectMaterial="selectMaterial"></WxMaterialSelect>
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="configur_content" v-if="tempObj.type == 'click' || tempObj.type == 'scancode_waitmsg'">
|
||||
<WxReplySelect v-model:objData="tempObj" v-if="hackResetWxReplySelect"></WxReplySelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--一进页面就显示的默认页面,当点击左边按钮的时候,就不显示了-->
|
||||
<div v-if="!showRightFlag" class="right">
|
||||
<p>请选择菜单配置</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpMenuDetail">
|
||||
import { save, saveAndRelease, getList } from '@/api/wxmp/wxmenu'
|
||||
import WxReplySelect from '@/components/wx-reply/main.vue'
|
||||
import WxNews from '@/components/wx-news/main.vue'
|
||||
import WxMaterialSelect from '@/components/wx-material-select/main.vue'
|
||||
import { computed, getCurrentInstance, nextTick, onMounted, reactive } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
showRightFlag: false, //右边配置显示默认详情还是配置详情
|
||||
menu: {
|
||||
button: []
|
||||
}, //横向菜单
|
||||
isActive: -1, // 一级菜单点中样式
|
||||
isSubMenuActive: -1, // 一级菜单点中样式
|
||||
isSubMenuFlag: -1, // 二级菜单显示标志
|
||||
tempObj: {}, //右边临时变量,作为中间值牵引关系
|
||||
tempSelfObj: {
|
||||
//一些临时值放在这里进行判断,如果放在tempObj,由于引用关系,menu也会多了多余的参数
|
||||
},
|
||||
visible2: false, //素材内容 "选择素材"按钮弹框显示隐藏
|
||||
tableData: [], //素材内容弹框数据,
|
||||
menuName: '',
|
||||
showConfigurContent: true,
|
||||
nameMaxlength: 0, //名称最大长度
|
||||
menuOptions: [
|
||||
{
|
||||
value: 'view',
|
||||
label: '跳转网页'
|
||||
},
|
||||
{
|
||||
value: 'miniprogram',
|
||||
label: '跳转小程序'
|
||||
},
|
||||
{
|
||||
value: 'click',
|
||||
label: '点击回复'
|
||||
},
|
||||
{
|
||||
value: 'article_view_limited',
|
||||
label: '跳转图文消息'
|
||||
},
|
||||
{
|
||||
value: 'scancode_push',
|
||||
label: '扫码直接返回结果'
|
||||
},
|
||||
{
|
||||
value: 'scancode_waitmsg',
|
||||
label: '扫码回复'
|
||||
},
|
||||
{
|
||||
value: 'pic_sysphoto',
|
||||
label: '系统拍照发图'
|
||||
},
|
||||
{
|
||||
value: 'pic_photo_or_album',
|
||||
label: '拍照或者相册'
|
||||
},
|
||||
{
|
||||
value: 'pic_weixin',
|
||||
label: '微信相册'
|
||||
},
|
||||
{
|
||||
value: 'location_select',
|
||||
label: '选择地理位置'
|
||||
}
|
||||
],
|
||||
dialogNewsVisible: false,
|
||||
saveLoading: false,
|
||||
hackResetWxReplySelect: false
|
||||
})
|
||||
const {
|
||||
showRightFlag,
|
||||
menu,
|
||||
isActive,
|
||||
isSubMenuActive,
|
||||
isSubMenuFlag,
|
||||
tempObj,
|
||||
tempSelfObj,
|
||||
menuName,
|
||||
showConfigurContent,
|
||||
nameMaxlength,
|
||||
menuOptions,
|
||||
dialogNewsVisible,
|
||||
saveLoading,
|
||||
hackResetWxReplySelect
|
||||
} = toRefs(data)
|
||||
|
||||
const menuKeyLength = computed(() => {
|
||||
return data.menu.button.length
|
||||
})
|
||||
|
||||
function onCreated() {
|
||||
getMenuFun()
|
||||
}
|
||||
onCreated()
|
||||
|
||||
onMounted(() => {})
|
||||
|
||||
function deleteTempObj() {}
|
||||
|
||||
function openMaterial() {
|
||||
data.dialogNewsVisible = true
|
||||
}
|
||||
|
||||
function selectMaterial(item) {
|
||||
if (item.content.articles.length > 1) {
|
||||
proxy.$alert('您选择的是多图文,将默认跳转第一篇', '提示', {
|
||||
confirmButtonText: '确定'
|
||||
})
|
||||
}
|
||||
data.dialogNewsVisible = false
|
||||
data.tempObj.article_id = item.articleId
|
||||
data.tempObj.mediaName = item.name
|
||||
data.tempObj.url = item.url
|
||||
item.mediaType = data.tempObj.mediaType
|
||||
item.content.articles = item.content.articles.slice(0, 1)
|
||||
data.tempObj.content = item.content
|
||||
}
|
||||
|
||||
function getMenuFun() {
|
||||
getList().then((res) => {
|
||||
data.menu.button = JSON.parse(res.msg).button
|
||||
})
|
||||
}
|
||||
|
||||
function handleClick(tab, event) {
|
||||
data.tempObj.mediaType = tab.paneName
|
||||
}
|
||||
|
||||
function saveAndReleaseFun() {
|
||||
proxy
|
||||
.$confirm('确定要保证并发布该菜单吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.saveLoading = true
|
||||
saveAndRelease({
|
||||
strWxMenu: data.menu
|
||||
})
|
||||
.then((response) => {
|
||||
data.saveLoading = false
|
||||
if (response.code == 200) {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '发布成功',
|
||||
type: 'success'
|
||||
})
|
||||
} else {
|
||||
proxy.$message.error(response.data.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.saveLoading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function menuFun(i, item) {
|
||||
data.hackResetWxReplySelect = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetWxReplySelect = true //重建组件
|
||||
})
|
||||
data.showRightFlag = true //右边菜单
|
||||
data.tempObj = item //这个如果放在顶部,flag会没有。因为重新赋值了。
|
||||
data.tempSelfObj.grand = '1' //表示一级菜单
|
||||
data.tempSelfObj.index = i //表示一级菜单索引
|
||||
data.isActive = i //一级菜单选中样式
|
||||
data.isSubMenuFlag = i //二级菜单显示标志
|
||||
data.isSubMenuActive = -1 //二级菜单去除选中样式
|
||||
data.nameMaxlength = 4
|
||||
if (item.sub_button && item.sub_button.length > 0) {
|
||||
data.showConfigurContent = false
|
||||
} else {
|
||||
data.showConfigurContent = true
|
||||
}
|
||||
}
|
||||
|
||||
function subMenuFun(subItem, index, k) {
|
||||
data.hackResetWxReplySelect = false //销毁组件
|
||||
nextTick(() => {
|
||||
data.hackResetWxReplySelect = true //重建组件
|
||||
})
|
||||
data.showRightFlag = true //右边菜单
|
||||
data.tempObj = subItem //将点击的数据放到临时变量,对象有引用作用
|
||||
data.tempSelfObj.grand = '2' //表示二级菜单
|
||||
data.tempSelfObj.index = index //表示一级菜单索引
|
||||
data.tempSelfObj.secondIndex = k //表示二级菜单索引
|
||||
data.isSubMenuActive = index + '' + k //二级菜单选中样式
|
||||
data.isActive = -1 //一级菜单去除样式
|
||||
data.showConfigurContent = true
|
||||
data.nameMaxlength = 7
|
||||
}
|
||||
|
||||
function addMenu() {
|
||||
const menuKeyLengthTemp = menuKeyLength.value
|
||||
const addButton = {
|
||||
name: '菜单名称',
|
||||
sub_button: []
|
||||
}
|
||||
data.menu.button[menuKeyLengthTemp] = addButton
|
||||
menuFun(menuKeyLength.value - 1, addButton)
|
||||
}
|
||||
|
||||
function addSubMenu(i, item) {
|
||||
if (!item.sub_button || item.sub_button.length <= 0) {
|
||||
item.sub_button = []
|
||||
data.showConfigurContent = false
|
||||
}
|
||||
const subMenuKeyLength = item.sub_button.length //获取二级菜单key长度
|
||||
const addButton = {
|
||||
name: '子菜单名称'
|
||||
}
|
||||
item.sub_button[subMenuKeyLength] = addButton
|
||||
subMenuFun(item.sub_button[subMenuKeyLength], i, subMenuKeyLength)
|
||||
}
|
||||
|
||||
function deleteMenu(obj) {
|
||||
proxy
|
||||
.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
deleteData() // 删除菜单数据
|
||||
data.tempObj = {}
|
||||
data.showRightFlag = false
|
||||
data.isActive = -1
|
||||
data.isSubMenuActive = -1
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function deleteData() {
|
||||
// 一级菜单的删除方法
|
||||
if (data.tempSelfObj.grand == '1') {
|
||||
data.menu.button.splice(data.tempSelfObj.index, 1)
|
||||
}
|
||||
// 二级菜单的删除方法
|
||||
if (data.tempSelfObj.grand == '2') {
|
||||
data.menu.button[data.tempSelfObj.index].sub_button.splice(data.tempSelfObj.secondIndex, 1)
|
||||
}
|
||||
proxy.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped="scoped">
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
.clearfix::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
div {
|
||||
text-align: left;
|
||||
}
|
||||
.weixin-hd {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 426px;
|
||||
left: 0px;
|
||||
width: 300px;
|
||||
height: 64px;
|
||||
background: transparent url(assets/menu_head.png) no-repeat 0 0;
|
||||
background-position: 0 0;
|
||||
background-size: 100%;
|
||||
}
|
||||
.weixin-title {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 33px;
|
||||
left: 0px;
|
||||
}
|
||||
.weixin-menu {
|
||||
background: transparent url(assets/menu_foot.png) no-repeat 0 0;
|
||||
padding-left: 43px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.menu_option {
|
||||
width: 40% !important;
|
||||
}
|
||||
.public-account-management {
|
||||
min-width: 1200px;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
.left {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
width: 350px;
|
||||
height: 715px;
|
||||
background: url('assets/iphone_backImg.png') no-repeat;
|
||||
background-size: 100% auto;
|
||||
padding: 518px 25px 88px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
/*第一级菜单*/
|
||||
.menu_main {
|
||||
.menu_bottom {
|
||||
position: relative;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 85.5px;
|
||||
text-align: center;
|
||||
border: 1px solid #ebedee;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
&.menu_addicon {
|
||||
height: 46px;
|
||||
line-height: 46px;
|
||||
}
|
||||
.menu_item {
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
&.active {
|
||||
border: 1px solid #2bb673;
|
||||
}
|
||||
}
|
||||
.menu_subItem {
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
&.active {
|
||||
border: 1px solid #2bb673;
|
||||
}
|
||||
}
|
||||
}
|
||||
i {
|
||||
color: #2bb673;
|
||||
}
|
||||
/*第二级菜单*/
|
||||
.submenu {
|
||||
position: absolute;
|
||||
width: 85.5px;
|
||||
bottom: 45px;
|
||||
.subtitle {
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
.save_div {
|
||||
margin-top: 15px;
|
||||
text-align: center;
|
||||
.save_btn {
|
||||
bottom: 20px;
|
||||
left: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*右边菜单内容*/
|
||||
.right {
|
||||
float: left;
|
||||
width: 63%;
|
||||
background-color: #e8e7e7;
|
||||
padding: 20px;
|
||||
margin-left: 20px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
.configure_page {
|
||||
.delete_btn {
|
||||
text-align: right;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.menu_content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.configur_content {
|
||||
margin-top: 20px;
|
||||
background-color: #fff;
|
||||
padding: 20px 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.blue {
|
||||
color: #29b6f6;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.applet {
|
||||
margin-bottom: 20px;
|
||||
span {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
.material {
|
||||
.input_width {
|
||||
width: 30%;
|
||||
}
|
||||
.el-textarea {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.public-account-management {
|
||||
.el-input {
|
||||
width: 70%;
|
||||
margin-right: 2%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
text-align: right;
|
||||
margin-right: 25px;
|
||||
}
|
||||
.select-item {
|
||||
width: 280px;
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.select-item2 {
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px auto;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
.ope-row {
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.item-name {
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
222
src/views/wxmp/wxmsg/index.vue
Normal file
222
src/views/wxmp/wxmsg/index.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:permission="permissionList"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption"
|
||||
@on-load="getPageF"
|
||||
@refresh-change="refreshChange"
|
||||
@row-update="handleUpdate"
|
||||
@row-save="handleSave"
|
||||
@row-del="handleDel"
|
||||
@sort-change="sortChange"
|
||||
@search-change="searchChange"
|
||||
>
|
||||
<template #appName="scope">
|
||||
<el-tag type="success" size="small">{{ scope.row.appName }}</el-tag>
|
||||
</template>
|
||||
<template #nickName="scope">
|
||||
<el-badge :value="scope.row.countMsg" class="count-msg">
|
||||
<img class="head-img" :src="scope.row.headimgUrl" />
|
||||
<div class="nick-name">{{ scope.row.nickName }}</div>
|
||||
</el-badge>
|
||||
</template>
|
||||
<template #readFlag="scope">
|
||||
<el-tag :type="scope.row.readFlag == '1' ? 'success' : 'danger'" size="small">{{ scope.row.$readFlag }}</el-tag>
|
||||
</template>
|
||||
<template #repContent="scope">
|
||||
<div v-if="scope.row.repType == 'event' && scope.row.repEvent == 'subscribe'">
|
||||
<el-tag type="success" size="small">关注</el-tag>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'event' && scope.row.repEvent == 'unsubscribe'">
|
||||
<el-tag type="danger" size="small">取消关注</el-tag>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'event' && scope.row.repEvent == 'CLICK'"><el-tag size="small">点击菜单</el-tag>:【{{ scope.row.repName }}】</div>
|
||||
<div v-if="scope.row.repType == 'event' && scope.row.repEvent == 'VIEW'"><el-tag size="small">点击菜单链接</el-tag>:【{{ scope.row.repUrl }}】</div>
|
||||
<div v-if="scope.row.repType == 'event' && scope.row.repEvent == 'scancode_waitmsg'">
|
||||
<el-tag size="small">扫码结果:</el-tag>:【{{ scope.row.repContent }}】
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'text'">{{ scope.row.repContent }}</div>
|
||||
<div v-if="scope.row.repType == 'image'">
|
||||
<a target="_blank" :href="scope.row.repUrl"><img :src="scope.row.repUrl" style="width: 100px" /></a>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'voice'">
|
||||
<WxVoicePlayer :objData="scope.row"></WxVoicePlayer>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'video'">
|
||||
<WxVideoPlayer :objData="scope.row" style="margin-top: 40px"></WxVideoPlayer>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'shortvideo'">
|
||||
<WxVideoPlayer :objData="scope.row" style="margin-top: 40px"></WxVideoPlayer>
|
||||
</div>
|
||||
<div v-if="scope.row.repType == 'link'">
|
||||
<el-tag size="small">链接</el-tag>:<a :href="scope.row.repUrl" target="_blank">{{ scope.row.repName }}</a>
|
||||
</div>
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<el-button link icon="el-icon-chat-line-round" type="primary" plain @click="wxMsgDo(scope.row, scope.index)">消息</el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="用户消息" v-model="dialogMsgVisible" width="700px">
|
||||
<WxMsg :wxUserId="wxUserId" v-if="dialogMsgVisible"></WxMsg>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpMsg">
|
||||
import { getPage, getObj, addObj, putObj, delObj } from '@/api/wxmp/wxmsg'
|
||||
import { tableOption } from '@/const/crud/wxmp/wxmsg'
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
import WxMsg from '@/components/wx-msg/main.vue'
|
||||
import WxVideoPlayer from '@/components/wx-video-play/main.vue'
|
||||
import WxVoicePlayer from '@/components/wx-voice-play/main.vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
dialogMsgVisible: false,
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 20, // 每页显示多少条
|
||||
ascs: [], //升序字段
|
||||
descs: 'create_time' //降序字段
|
||||
},
|
||||
paramsSearch: {},
|
||||
tableLoading: false,
|
||||
wxUserId: ''
|
||||
})
|
||||
const { tableData, tableLoading, page, dialogMsgVisible, wxUserId } = toRefs(data)
|
||||
|
||||
const permissionList = computed(() => {
|
||||
return {
|
||||
addBtn: checkPermi(['wxmp:wxmsg:add']),
|
||||
delBtn: checkPermi(['wxmp:wxmsg:del']),
|
||||
editBtn: checkPermi(['wxmp:wxmsg:edit']),
|
||||
viewBtn: checkPermi(['wxmp:wxmsg:get'])
|
||||
}
|
||||
})
|
||||
|
||||
function wxMsgDo(row) {
|
||||
data.wxUserId = row.wxUserId
|
||||
data.dialogMsgVisible = true
|
||||
row.readFlag = '1'
|
||||
}
|
||||
|
||||
function searchChange(params, done) {
|
||||
params = proxy.filterForm(params)
|
||||
data.paramsSearch = params
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page, params)
|
||||
done()
|
||||
}
|
||||
|
||||
function sortChange(val) {
|
||||
const prop = val.prop ? val.prop.replace(/([A-Z])/g, '_$1').toLowerCase() : ''
|
||||
if (val.order == 'ascending') {
|
||||
data.page.descs = []
|
||||
data.page.ascs = prop
|
||||
} else if (val.order == 'descending') {
|
||||
data.page.ascs = []
|
||||
data.page.descs = prop
|
||||
} else {
|
||||
data.page.ascs = []
|
||||
data.page.descs = []
|
||||
}
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize,
|
||||
descs: data.page.descs,
|
||||
ascs: data.page.ascs,
|
||||
type: '1'
|
||||
},
|
||||
params,
|
||||
data.paramsSearch
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.records
|
||||
data.page.total = response.data.total
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleDel(row, index) {
|
||||
proxy
|
||||
.$confirm('是否确认删除此数据', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(function () {
|
||||
return delObj(row.id)
|
||||
})
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function handleUpdate(row, index, done, loading) {
|
||||
putObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function handleSave(row, done, loading) {
|
||||
addObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
getPageF(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.head-img {
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
303
src/views/wxmp/wxsummary/index.vue
Normal file
303
src/views/wxmp/wxsummary/index.vue
Normal file
@@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="clearfix">
|
||||
<span class="demonstration">时间范围</span>
|
||||
<el-date-picker
|
||||
format="YYYY-MM-DD"
|
||||
v-model="dateValues"
|
||||
type="daterange"
|
||||
:picker-options="datePickerOptions"
|
||||
@change="changeDate"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
>
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
<el-row justify="center">
|
||||
<el-col :span="12">
|
||||
<div id="userSummaryChart" :style="{ width: '80%', height: '378px' }"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div id="userCumulateChart" :style="{ width: '80%', height: '378px' }"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div id="interfaceSummaryChart" :style="{ width: '80%', height: '378px' }"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div id="interfaceSummaryChart2" :style="{ width: '80%', height: '378px' }"></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpSummary">
|
||||
import { dayjs } from 'element-plus'
|
||||
// 引入基本模板
|
||||
import * as echarts from 'echarts'
|
||||
import { getInterfaceSummary, getUserSummary, getUserCumulate } from '@/api/wxmp/wxsummary'
|
||||
|
||||
import { getCurrentInstance, onMounted, reactive } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
datePickerOptions: {
|
||||
disabledDate(date) {
|
||||
return date >= new Date(new Date() - 3600 * 1000 * 24)
|
||||
}
|
||||
},
|
||||
startDate: dayjs().add(-7, 'days').format('YYYY-MM-DD'),
|
||||
endDate: dayjs().add(-1, 'days').format('YYYY-MM-DD'),
|
||||
dateValues: [dayjs().add(-7, 'days').format('YYYY-MM-DD'), dayjs().add(-1, 'days').format('YYYY-MM-DD')],
|
||||
|
||||
xAxisData: [],
|
||||
seriesData1: [],
|
||||
seriesData2: [],
|
||||
seriesData3: [],
|
||||
seriesData4: [],
|
||||
seriesData5: [],
|
||||
seriesData6: [],
|
||||
seriesData7: []
|
||||
})
|
||||
const {
|
||||
datePickerOptions,
|
||||
startDate,
|
||||
endDate,
|
||||
dateValues,
|
||||
xAxisData,
|
||||
seriesData1,
|
||||
seriesData2,
|
||||
seriesData3,
|
||||
seriesData4,
|
||||
seriesData5,
|
||||
seriesData6,
|
||||
seriesData7
|
||||
} = toRefs(data)
|
||||
|
||||
onMounted(() => {
|
||||
getSummary()
|
||||
})
|
||||
|
||||
function changeDate() {
|
||||
const startDate = new Date(data.dateValues[0])
|
||||
const endDate = new Date(data.dateValues[1])
|
||||
if (dayjs(endDate).diff(dayjs(startDate), 'day') > 6) {
|
||||
proxy.$message.error('时间间隔7天以内,请重新选择')
|
||||
return false
|
||||
} else {
|
||||
data.startDate = dayjs(startDate).format('YYYY-MM-DD')
|
||||
data.endDate = dayjs(endDate).format('YYYY-MM-DD')
|
||||
data.xAxisData = []
|
||||
data.seriesData1 = []
|
||||
data.seriesData2 = []
|
||||
data.seriesData5 = []
|
||||
data.seriesData6 = []
|
||||
getSummary()
|
||||
}
|
||||
}
|
||||
|
||||
function getSummary() {
|
||||
const days = dayjs(data.endDate).diff(dayjs(data.startDate), 'day') //相差天数
|
||||
for (let i = 0; i <= days; i++) {
|
||||
data.xAxisData.push(dayjs(data.startDate).add(i, 'days').format('YYYY-MM-DD'))
|
||||
data.seriesData1.push(0)
|
||||
data.seriesData2.push(0)
|
||||
data.seriesData5.push(0)
|
||||
data.seriesData6.push(0)
|
||||
}
|
||||
getUserSummary({
|
||||
startDate: data.startDate,
|
||||
endDate: data.endDate
|
||||
})
|
||||
.then((response) => {
|
||||
data.xAxisData.forEach((item, index, arr) => {
|
||||
response.data.forEach((item2, index2, arr2) => {
|
||||
if (item2.refDate.indexOf(item) >= 0) {
|
||||
data.seriesData5[index] = data.seriesData5[index] + item2.newUser
|
||||
data.seriesData6[index] = data.seriesData6[index] + item2.cancelUser
|
||||
}
|
||||
})
|
||||
})
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
const userSummaryChart = echarts.init(document.getElementById('userSummaryChart'))
|
||||
// 绘制图表
|
||||
userSummaryChart.setOption({
|
||||
title: { text: '用户增减数据' },
|
||||
color: ['#67C23A', '#F56C6C'],
|
||||
legend: {
|
||||
data: ['新增用户', '取消关注的用户']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: data.xAxisData
|
||||
},
|
||||
yAxis: {},
|
||||
series: [
|
||||
{
|
||||
name: '新增用户',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
barGap: 0,
|
||||
data: data.seriesData5
|
||||
},
|
||||
{
|
||||
name: '取消关注的用户',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: data.seriesData6
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
|
||||
getUserCumulate({
|
||||
startDate: data.startDate,
|
||||
endDate: data.endDate
|
||||
})
|
||||
.then((response) => {
|
||||
response.data.forEach((item, index, arr) => {
|
||||
data.seriesData7[index] = item.cumulateUser
|
||||
})
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
const userCumulateChart = echarts.init(document.getElementById('userCumulateChart'))
|
||||
// 绘制图表
|
||||
userCumulateChart.setOption({
|
||||
title: { text: '累计用户数据' },
|
||||
legend: {
|
||||
data: ['累计用户量']
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: data.xAxisData
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '累计用户量',
|
||||
data: data.seriesData7,
|
||||
type: 'line',
|
||||
smooth: true
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
|
||||
//获取接口数据
|
||||
getInterfaceSummary({
|
||||
startDate: data.startDate,
|
||||
endDate: data.endDate
|
||||
})
|
||||
.then((response) => {
|
||||
response.data.forEach((item, index, arr) => {
|
||||
data.seriesData1[index] = item.callbackCount
|
||||
data.seriesData2[index] = item.maxTimeCost
|
||||
data.seriesData3[index] = item.totalTimeCost
|
||||
data.seriesData4[index] = item.failCount
|
||||
})
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
const interfaceSummaryChart = echarts.init(document.getElementById('interfaceSummaryChart'))
|
||||
// 绘制图表
|
||||
interfaceSummaryChart.setOption({
|
||||
title: { text: '接口分析数据' },
|
||||
color: ['#67C23A', '#F56C6C'],
|
||||
legend: {
|
||||
data: ['被动回复用户消息的次数', '失败次数']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: data.xAxisData
|
||||
},
|
||||
yAxis: {},
|
||||
series: [
|
||||
{
|
||||
name: '被动回复用户消息的次数',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
barGap: 0,
|
||||
data: data.seriesData1
|
||||
},
|
||||
{
|
||||
name: '失败次数',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: data.seriesData4
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
const interfaceSummaryChart2 = echarts.init(document.getElementById('interfaceSummaryChart2'))
|
||||
// 绘制图表
|
||||
interfaceSummaryChart2.setOption({
|
||||
title: { text: '接口分析数据' },
|
||||
color: ['#E6A23C', '#409EFF'],
|
||||
legend: {
|
||||
data: ['最大耗时', '总耗时']
|
||||
},
|
||||
tooltip: {},
|
||||
xAxis: {
|
||||
data: data.xAxisData
|
||||
},
|
||||
yAxis: {},
|
||||
series: [
|
||||
{
|
||||
name: '最大耗时',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: data.seriesData2
|
||||
},
|
||||
{
|
||||
name: '总耗时',
|
||||
type: 'bar',
|
||||
label: {
|
||||
normal: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
data: data.seriesData3
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demonstration {
|
||||
font-size: 15px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
382
src/views/wxmp/wxuser/index.vue
Normal file
382
src/views/wxmp/wxuser/index.vue
Normal file
@@ -0,0 +1,382 @@
|
||||
<template>
|
||||
<div>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption"
|
||||
:permission="permissionList"
|
||||
@on-load="getPageF"
|
||||
@refresh-change="refreshChange"
|
||||
@row-update="handleUpdate"
|
||||
@row-save="handleSave"
|
||||
@row-del="handleDel"
|
||||
@sort-change="sortChange"
|
||||
@search-change="searchChange"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<template #subscribe="scope">
|
||||
<el-tag size="small" effect="dark" :type="scope.row.subscribe == '1' ? 'success' : scope.row.subscribe == '0' ? 'danger' : 'warning'">
|
||||
{{ scope.row.$subscribe }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #sex="scope">
|
||||
<el-tag size="small" effect="light" :type="scope.row.sex == '1' ? 'success' : scope.row.sex == '2' ? 'danger' : 'warning'">
|
||||
{{ scope.row.$sex || '未知' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #latitude="scope">
|
||||
<el-link
|
||||
v-if="scope.row.longitude"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
:href="
|
||||
'https://map.qq.com/?type=marker&isopeninfowin=1&markertype=1&pointx=' +
|
||||
scope.row.longitude +
|
||||
'&pointy=' +
|
||||
scope.row.latitude +
|
||||
'&name=' +
|
||||
scope.row.nickName +
|
||||
'&ref=joolun'
|
||||
"
|
||||
>
|
||||
<i class="el-icon-map-location"></i>
|
||||
</el-link>
|
||||
</template>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="
|
||||
dialogTagging = true
|
||||
taggingType = 'tagging'
|
||||
"
|
||||
icon="el-icon-document"
|
||||
v-hasPermi="['wxmp:wxuser:tagging']"
|
||||
>打标签
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
@click="
|
||||
dialogTagging = true
|
||||
taggingType = 'unTagging'
|
||||
"
|
||||
icon="el-icon-document"
|
||||
v-hasPermi="['wxmp:wxuser:tagging']"
|
||||
>去除标签
|
||||
</el-button>
|
||||
<el-button type="danger" @click="synchroWxUserF" icon="el-icon-refresh" v-hasPermi="['wxmp:wxuser:synchro']">同步用户 </el-button>
|
||||
<el-dialog :title="taggingType == 'tagging' ? '请选择要打的标签' : '请选择要去除的标签'" v-model="dialogTagging" width="30%">
|
||||
<el-checkbox-group v-model="checkedTags">
|
||||
<el-checkbox v-for="tag in userTagsData" :label="tag.id" :key="tag.id">{{ tag.name }} </el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogTagging = false">取 消</el-button>
|
||||
<el-button type="primary" @click="toTagging">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<el-button link v-hasPermi="['wxmp:wxuser:edit:remark']" icon="el-icon-edit" type="primary" plain @click="updateRemarkF(scope.row, scope.index)"
|
||||
>修改备注
|
||||
</el-button>
|
||||
<el-button link v-hasPermi="['wxmp:wxuser:index']" icon="el-icon-chat-line-round" type="primary" plain @click="wxMsgDo(scope.row, scope.index)"
|
||||
>消息
|
||||
</el-button>
|
||||
</template>
|
||||
<template #tagidListSearch="scope">
|
||||
<el-select v-model="scope.row.tagidList" placeholder="请选择">
|
||||
<el-option v-for="item in userTagsData" :key="item.id" :label="item.name" :value="item.id"> </el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="用户消息" v-model="dialogMsgVisible" width="700px">
|
||||
<WxMsg :wxUserId="wxUserId" v-if="dialogMsgVisible"></WxMsg>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpUser">
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
import { getPage, getObj, addObj, putObj, delObj, synchroWxUser, updateRemark, tagging } from '@/api/wxmp/wxuser'
|
||||
import { getList as listUserTags } from '@/api/wxmp/wxusertags'
|
||||
import { tableOption } from '@/const/crud/wxmp/wxuser'
|
||||
import WxMsg from '@/components/wx-msg/main.vue'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const crud = ref(null)
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 20, // 每页显示多少条
|
||||
ascs: [],
|
||||
descs: 'subscribe_time'
|
||||
},
|
||||
paramsSearch: {},
|
||||
tableLoading: false,
|
||||
selectionData: [],
|
||||
dialogTagging: false,
|
||||
checkedTags: [],
|
||||
userTagsData: [],
|
||||
taggingType: '',
|
||||
dialogMsgVisible: false,
|
||||
wxUserId: ''
|
||||
})
|
||||
const { tableData, tableLoading, page, dialogTagging, checkedTags, userTagsData, taggingType, dialogMsgVisible, wxUserId } = toRefs(data)
|
||||
|
||||
const permissionList = computed(() => {
|
||||
return {
|
||||
addBtn: checkPermi(['wxmp:wxuser:add']),
|
||||
delBtn: checkPermi(['wxmp:wxuser:del']),
|
||||
editBtn: checkPermi(['wxmp:wxuser:edit']),
|
||||
viewBtn: checkPermi(['wxmp:wxuser:get'])
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
listUserTagsF()
|
||||
})
|
||||
|
||||
function listUserTagsF() {
|
||||
data.tableLoading = true
|
||||
listUserTags()
|
||||
.then((response) => {
|
||||
if (response.code == 200) {
|
||||
const userTagsData = response.data
|
||||
data.userTagsData = userTagsData
|
||||
crud.value.DIC.tagidList = userTagsData
|
||||
} else {
|
||||
proxy.$message.error('获取用户标签出错:' + response.msg)
|
||||
}
|
||||
data.tableLoading = false
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
getPageF(data.page)
|
||||
})
|
||||
}
|
||||
|
||||
function wxMsgDo(row) {
|
||||
data.wxUserId = row.id
|
||||
data.dialogMsgVisible = true
|
||||
}
|
||||
|
||||
function toTagging() {
|
||||
const openIdList = []
|
||||
for (let i = 0; i < data.selectionData.length; i++) {
|
||||
openIdList.push(data.selectionData[i].openId)
|
||||
}
|
||||
if (data.checkedTags.length <= 0) {
|
||||
proxy.$message.error('请选择标签')
|
||||
return
|
||||
}
|
||||
if (openIdList.length <= 0) {
|
||||
proxy.$message.error('请选择用户')
|
||||
return
|
||||
}
|
||||
data.tableLoading = true
|
||||
tagging({
|
||||
taggingType: data.taggingType,
|
||||
tagIds: data.checkedTags,
|
||||
openIds: openIdList
|
||||
})
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
data.checkedTags = []
|
||||
crud.value.selectClear()
|
||||
if (response.code == 200) {
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error('打标签出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
data.dialogTagging = false
|
||||
}
|
||||
|
||||
function selectionChange(list) {
|
||||
data.selectionData = list
|
||||
}
|
||||
|
||||
function searchChange(params, done) {
|
||||
params = proxy.filterForm(params)
|
||||
data.paramsSearch = params
|
||||
data.page.currentPage = 1
|
||||
getPageF(data.page, params)
|
||||
done()
|
||||
}
|
||||
|
||||
function synchroWxUserF() {
|
||||
proxy
|
||||
.$confirm('同步用户需要一定时间,用户量越大、用时越久,请耐心等待,勿重复提交;确认此操作吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
data.tableLoading = true
|
||||
synchroWxUser()
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error('同步微信用户出错:' + response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
setTimeout(() => {
|
||||
if (data.tableLoading) {
|
||||
data.tableLoading = false
|
||||
proxy.$alert('同步请求发送成功,系统正在处理中,请稍后刷新查看同步结果,用户量越大用时越久,请耐心等待,勿重复提交', '提示', {
|
||||
confirmButtonText: '确定'
|
||||
})
|
||||
}
|
||||
}, 3000)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function sortChange(val) {
|
||||
const prop = val.prop ? val.prop.replace(/([A-Z])/g, '_$1').toLowerCase() : ''
|
||||
if (val.order == 'ascending') {
|
||||
data.page.descs = []
|
||||
data.page.ascs = prop
|
||||
} else if (val.order == 'descending') {
|
||||
data.page.ascs = []
|
||||
data.page.descs = prop
|
||||
} else {
|
||||
data.page.ascs = []
|
||||
data.page.descs = []
|
||||
}
|
||||
getPageF(data.page)
|
||||
}
|
||||
|
||||
function getPageF(page, params) {
|
||||
data.tableLoading = true
|
||||
getPage(
|
||||
Object.assign(
|
||||
{
|
||||
current: page.currentPage,
|
||||
size: page.pageSize,
|
||||
descs: data.page.descs,
|
||||
ascs: data.page.ascs,
|
||||
appType: '2'
|
||||
},
|
||||
params,
|
||||
data.paramsSearch
|
||||
)
|
||||
)
|
||||
.then((response) => {
|
||||
data.tableData = response.data.records
|
||||
data.page.total = response.data.total
|
||||
data.page.currentPage = page.currentPage
|
||||
data.page.pageSize = page.pageSize
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function updateRemarkF(row, index) {
|
||||
proxy
|
||||
.$prompt('请输入备注', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /\S/,
|
||||
inputErrorMessage: '输入不能为空'
|
||||
})
|
||||
.then(({ value }) => {
|
||||
data.tableLoading = true
|
||||
row.remark = value
|
||||
updateRemark(row)
|
||||
.then((response) => {
|
||||
data.tableLoading = false
|
||||
if (response.code == 200) {
|
||||
data.tableData.splice(index, 1, Object.assign({}, row))
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
} else {
|
||||
proxy.$message.error(response.msg)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleDel(row, index) {
|
||||
proxy
|
||||
.$confirm('是否确认删除', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(function () {
|
||||
return delObj(row.id)
|
||||
})
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function handleUpdate(row, index, done, loading) {
|
||||
putObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function handleSave(row, done, loading) {
|
||||
addObj(row)
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPageF(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
getPageF(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
151
src/views/wxmp/wxusertags/index.vue
Normal file
151
src/views/wxmp/wxusertags/index.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div>
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:page="page"
|
||||
:data="tableData"
|
||||
:table-loading="tableLoading"
|
||||
:option="tableOption"
|
||||
@on-load="getPage"
|
||||
@refresh-change="refreshChange"
|
||||
@row-update="handleUpdate"
|
||||
@row-save="handleSave"
|
||||
@row-del="handleDel"
|
||||
@sort-change="sortChange"
|
||||
@search-change="searchChange"
|
||||
>
|
||||
</avue-crud>
|
||||
<el-dialog title="用户消息" v-model="dialogMsgVisible" width="40%">
|
||||
<WxMsg :wxUserId="wxUserId" v-if="dialogMsgVisible"></WxMsg>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="WxMpUserTags">
|
||||
import WxMsg from '@/components/wx-msg/main.vue'
|
||||
import { getList, addObj, putObj, delObj } from '@/api/wxmp/wxusertags'
|
||||
import { tableOption } from '@/const/crud/wxmp/wxusertags'
|
||||
import { checkPermi, checkRole } from '@/utils/permission'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const data = reactive({
|
||||
tableData: [],
|
||||
page: {
|
||||
total: 0, // 总页数
|
||||
currentPage: 1, // 当前页数
|
||||
pageSize: 20, // 每页显示多少条
|
||||
ascs: [],
|
||||
descs: 'subscribe_time'
|
||||
},
|
||||
paramsSearch: {},
|
||||
tableLoading: false,
|
||||
dialogMsgVisible: false,
|
||||
wxUserId: ''
|
||||
})
|
||||
|
||||
const { page, tableData, tableLoading, dialogMsgVisible, wxUserId } = toRefs(data)
|
||||
const permissionList = computed(() => {
|
||||
return {
|
||||
addBtn: checkPermi(['wxmp:wxusertags:add']),
|
||||
delBtn: checkPermi(['wxmp:wxusertags:del']),
|
||||
editBtn: checkPermi(['wxmp:wxusertags:edit']),
|
||||
viewBtn: checkPermi(['wxmp:wxusertags:get'])
|
||||
}
|
||||
})
|
||||
|
||||
function searchChange(params, done) {
|
||||
params = proxy.filterForm(params)
|
||||
data.paramsSearch = params
|
||||
data.page.currentPage = 1
|
||||
getPage(data.page, params)
|
||||
done()
|
||||
}
|
||||
|
||||
function sortChange(val) {
|
||||
const prop = val.prop ? val.prop.replace(/([A-Z])/g, '_$1').toLowerCase() : ''
|
||||
if (val.order == 'ascending') {
|
||||
data.page.descs = []
|
||||
data.page.ascs = prop
|
||||
} else if (val.order == 'descending') {
|
||||
data.page.ascs = []
|
||||
data.page.descs = prop
|
||||
} else {
|
||||
data.page.ascs = []
|
||||
data.page.descs = []
|
||||
}
|
||||
getPage(data.page)
|
||||
}
|
||||
|
||||
function getPage(page, params) {
|
||||
data.tableLoading = true
|
||||
getList(Object.assign({}, params, data.paramsSearch))
|
||||
.then((response) => {
|
||||
data.tableData = response.data
|
||||
data.tableLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
data.tableLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleDel(row, index) {
|
||||
proxy
|
||||
.$confirm('是否确认删除', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(function () {
|
||||
return delObj({
|
||||
id: row.id
|
||||
})
|
||||
})
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
getPage(data.page)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function handleUpdate(row, index, done, loading) {
|
||||
putObj(Object.assign({}, row))
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPage(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function handleSave(row, done, loading) {
|
||||
addObj(Object.assign({}, row))
|
||||
.then(() => {
|
||||
proxy.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
})
|
||||
done()
|
||||
getPage(data.page)
|
||||
})
|
||||
.catch(() => {
|
||||
loading()
|
||||
})
|
||||
}
|
||||
|
||||
function refreshChange(page) {
|
||||
getPage(data.page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
Reference in New Issue
Block a user