Introducing new features. 微信模块功能优化

This commit is contained in:
aeizzz 2023-02-27 18:34:52 +08:00
parent 30b66bd4fd
commit 6aa288cdf2
14 changed files with 774 additions and 58 deletions

View File

@ -2,7 +2,7 @@ import request from '/@/utils/request';
export function getPage(query) {
return request({
url: '/mp/wx-material/page',
url: '/admin/wx-material/page',
method: 'get',
params: query
})
@ -10,7 +10,7 @@ export function getPage(query) {
export function addObj(obj) {
return request({
url: '/mp/wx-material/materialNews',
url: '/admin/wx-material/materialNews',
method: 'post',
data: obj
})
@ -18,7 +18,7 @@ export function addObj(obj) {
export function materialNewsUpdate(obj) {
return request({
url: '/mp/wx-material/materialNews',
url: '/admin/wx-material/materialNews',
method: 'put',
data: obj
})
@ -26,14 +26,14 @@ export function materialNewsUpdate(obj) {
export function getObj(id) {
return request({
url: '/mp/wx-material/' + id,
url: '/admin/wx-material/' + id,
method: 'get'
})
}
export function delObj(query) {
return request({
url: '/mp/wx-material',
url: '/admin/wx-material',
method: 'delete',
params: query
})
@ -41,7 +41,7 @@ export function delObj(query) {
export function putObj(obj) {
return request({
url: '/mp/wx-material',
url: '/admin/wx-material',
method: 'put',
data: obj
})
@ -49,7 +49,7 @@ export function putObj(obj) {
export function getMaterialOther(query) {
return request({
url: '/mp/wx-material/materialOther',
url: '/admin/wx-material/materialOther',
method: 'get',
params: query,
responseType: 'blob'
@ -58,7 +58,7 @@ export function getMaterialOther(query) {
export function getMaterialVideo(query) {
return request({
url: '/mp/wx-material/materialVideo',
url: '/admin/wx-material/materialVideo',
method: 'get',
params: query
})
@ -66,7 +66,7 @@ export function getMaterialVideo(query) {
export function getTempMaterialOther(query) {
return request({
url: '/mp/wx-material/tempMaterialOther',
url: '/admin/wx-material/tempMaterialOther',
method: 'get',
params: query,
responseType: 'blob'

View File

@ -57,6 +57,9 @@ const getDeptTree = () => {
if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
result.then((r: any) => {
state.List = r.data
if(r.data.length > 0){
handleNodeClick(r.data[0])
}
})
}
}

View File

@ -10,6 +10,8 @@
:limit="limit"
:on-error="handleUploadError"
:on-remove="handleRemove"
:data="data"
:auto-upload="autoUpload"
:on-success="handleUploadSuccess" class="upload-file-uploader" drag multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
@ -33,8 +35,10 @@
:file-list="fileList"
:headers="headers"
:limit="limit"
:auto-upload="autoUpload"
:on-error="handleUploadError"
:on-remove="handleRemove"
:data="data"
:on-success="handleUploadSuccess" class="upload-file-uploader" multiple>
<el-button type="primary" link>点击上传</el-button>
</el-upload>
@ -76,6 +80,13 @@ const props = defineProps({
validator:(value: string) => {
return ['default','simple'].includes(value)
}
},
data: {
type: Object
},
autoUpload: {
type: Boolean,
default: true
}
});
@ -185,4 +196,13 @@ watch(() => props.modelValue, val => {
}, { deep: true, immediate: true });
const submit = () => {
fileUpload.value.submit()
}
defineExpose({
submit
})
</script>

View File

@ -0,0 +1,162 @@
<template>
<div v-if="props.objData.type === 'image'">
<div class="waterfall" v-loading="state.loading">
<div class="waterfall-item" v-for="item in state.dataList" :key="item.mediaId">
<img class="material-img" :src="item.url" />
<p class="item-name">{{ item.name }}</p>
<el-row class="ope-row">
<el-button size="mini" type="success" @click="selectMaterial(item)"
>选择
<el-icon class="el-icon--right"><el-icon-circle-check /></el-icon>
</el-button>
</el-row>
</div>
</div>
<pagination v-bind="state.pagination"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"/>
</div>
<div v-else-if="props.objData.type === 'voice'">
<!-- 列表 -->
<el-table v-loading="state.loading" :data="state.dataList">
<el-table-column label="编号" align="center" prop="mediaId" />
<el-table-column label="文件名" align="center" prop="name" />
<el-table-column label="语音" align="center">
<template v-slot="scope">
<wx-voice-player :url="scope.row.url" />
</template>
</el-table-column>
<el-table-column
label="上传时间"
align="center"
prop="createTime"
width="180"
>
<template v-slot="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
fixed="right"
class-name="small-padding fixed-width"
>
<template v-slot="scope">
<el-button
size="mini"
type="text"
icon="el-icon-circle-plus"
@click="selectMaterial(scope.row)"
>选择</el-button
>
</template>
</el-table-column>
</el-table>
<pagination v-bind="state.pagination"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"/>
</div>
<div v-else-if="props.objData.type === 'video'">
<!-- 列表 -->
<el-table v-loading="state.loading" :data="state.dataList">
<el-table-column label="编号" align="center" prop="mediaId" />
<el-table-column label="文件名" align="center" prop="name" />
<el-table-column label="标题" align="center" prop="title" />
<el-table-column label="介绍" align="center" prop="introduction" />
<el-table-column label="视频" align="center" prop="url">
</el-table-column>
<el-table-column
label="上传时间"
align="center"
prop="createTime"
width="180"
>
<template v-slot="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
fixed="right"
class-name="small-padding fixed-width"
>
<template v-slot="scope">
<el-button
size="mini"
type="text"
icon="el-icon-circle-plus"
@click="selectMaterial(scope.row)"
>选择</el-button
>
</template>
</el-table-column>
</el-table>
<pagination v-bind="state.pagination"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"/>
</div>
<div v-else-if="props.objData.type === 'news'">
<div class="waterfall" v-loading="state.loading">
<template v-for="item in state.dataList">
<div v-if="item.content && item.content.newsItem" class="waterfall-item" :key="item.id">
<!-- <wx-news :articles="item.content.newsItem" />-->
<el-row class="ope-row">
<el-button size="mini" type="success" @click="selectMaterial(item)">
选择<el-icon class="el-icon--right"
><el-icon-circle-check
/></el-icon>
</el-button>
</el-row>
</div>
</template>
</div>
<pagination v-bind="state.pagination"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"/>
</div>
</template>
<script setup lang="ts" name="wx-material-select">
import {defineEmits} from "vue";
import {BasicTableProps, useTable} from "/@/hooks/table";
import {getPage} from "/@/api/mp/wx-material";
const emit = defineEmits(["selectMaterial"])
const props = defineProps({
objData: {
type: Object, // type - accountId -
required: true,
},
newsType: {
// 12稿
type: String,
default: '1',
},
})
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
type: props.objData.repType,
appId: props.objData.accountId
},
pageList: getPage
})
const {
currentChangeHandle,
sizeChangeHandle
} = useTable(state)
const selectMaterial = (item : any) => {
emit('selectMaterial', item,props.objData.accountId)
}
</script>

View File

@ -26,6 +26,8 @@ export interface BasicTableProps {
descs?: string[]
ascs?: string[]
props?: any
}
export interface Pagination {
@ -60,7 +62,11 @@ export function useTable(options?: BasicTableProps) {
loading: false,
selectObjs: [],
descs: [],
ascs: []
ascs: [],
props: {
item: 'records',
totalCount: 'total'
}
}
const mergeDefaultOptions = (options: any, props: any): BasicTableProps => {
@ -86,8 +92,8 @@ export function useTable(options?: BasicTableProps) {
descs: state.descs,
ascs: state.ascs
}).then((res: any) => {
state.dataList = state.isPage ? res.data.records : res.data
state.pagination!.total = state.isPage ? res.data.total : 0
state.dataList = state.isPage ? res.data[state.props.item] : res.data
state.pagination!.total = state.isPage ? res.data[state.props.totalCount] : 0
}).catch((err: any) => {
ElMessage.error(err.data.msg)
}).finally(() => {

View File

@ -148,10 +148,6 @@
</template>
<script>
import {
CircleCheck as ElIconCircleCheck,
CirclePlus as ElIconCirclePlus,
} from '@element-plus/icons'
import WxNews from '@/views/mp/components/wx-news/main.vue'
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue'
import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue'

View File

@ -8,7 +8,6 @@
<el-input v-model="form.tag" :placeholder="t('wxAccountTag.inputTagTip')"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
@ -37,7 +36,7 @@ const loading = ref(false)
//
const form = reactive({
id: '',
wxAccountAppid: '',
tag: '',
});
@ -47,7 +46,7 @@ const dataRules = ref({})
//
const openDialog = (id: string) => {
visible.value = true
form.id = ''
form.wxAccountAppid = id
//
if (dataFormRef.value) {
@ -61,30 +60,16 @@ const onSubmit = () => {
if (!valid) {
return false
}
//
if (form.id) {
loading.value = true
putObj(form).then(() => {
useMessage().success(t('common.editSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
}).finally(() => {
loading.value = false
})
} else {
loading.value = true
addObj(form).then(() => {
useMessage().success(t('common.addSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
}).finally(() => {
loading.value = false
})
}
loading.value = true
addObj(form).then(() => {
useMessage().success(t('common.addSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
}).finally(() => {
loading.value = false
})
})
}

View File

@ -22,15 +22,15 @@
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-button v-auth="'mp_wxAccountTag_add'" class="ml10" formDialogRef icon="folder-add" type="primary"
@click="formDialogRef.openDialog()">
<el-button v-auth="'mp_wx_account_tag_add'" class="ml10" formDialogRef icon="folder-add" type="primary"
@click="formDialogRef.openDialog(state.queryForm.wxAccountAppid)">
{{ $t('common.addBtn') }}
</el-button>
<el-button v-auth="'mp_wxAccountTag_export'" class="ml10" formDialogRef icon="Download" type="primary"
<el-button v-auth="'mp_wx_account_tag_export'" class="ml10" formDialogRef icon="Download" type="primary"
@click="exportExcel">
{{ $t('common.exportBtn') }}
</el-button>
<el-button v-auth="'mp_wxAccountTag_del'" :disabled="multiple" class="ml10" formDialogRef icon="Delete"
<el-button v-auth="'mp_wx_account_tag_del'" :disabled="multiple" class="ml10" formDialogRef icon="Delete"
type="primary" @click="handleDelete(selectObjs)">
{{ $t('common.delBtn') }}
</el-button>

View File

@ -48,9 +48,14 @@
<el-table-column :label="t('account.url')" prop="url" show-overflow-tooltip/>
<el-table-column :label="t('account.token')" prop="token" show-overflow-tooltip/>
<el-table-column :label="t('account.aeskey')" prop="aeskey" show-overflow-tooltip/>
<el-table-column :label="t('account.qrUrl')" prop="qrUrl" show-overflow-tooltip/>
<el-table-column :label="$t('common.action')" width="150">
<el-table-column :label="t('account.qrUrl')" prop="qrUrl" show-overflow-tooltip>
<template #default="scope">
<a target="_blank" :href="scope.row.qrUrl"><img :src="scope.row.qrUrl" style="width: 100px"></a>
</template>
</el-table-column>
<el-table-column :label="$t('common.action')" width="200">
<template #default="scope">
<el-button v-auth="'mp_wxaccount_edit'" text type="primary"
@click="formDialogRef.openDialog(scope.row.id)">{{ $t('common.editBtn') }}
</el-button>
@ -58,6 +63,15 @@
$t('common.delBtn')
}}
</el-button>
<el-button
type="text"
@click="access(scope.row,scope.index)">
接入
</el-button>
<el-button
type="text"
@click="generate(scope.row,scope.index)">二维码
</el-button>
</template>
</el-table-column>
</el-table>
@ -66,12 +80,22 @@
<!-- 编辑新增 -->
<form-dialog ref="formDialogRef" @refresh="getDataList(false)"/>
<el-dialog v-model="dialogFormVisible" title="接入">
<el-row :gutter="20">
<el-col :span="6">服务器地址(URL)</el-col>
<el-col id="target" :span="12">{{ wxurl }}</el-col>
<el-col :span="6">
<el-button id="btn" type="primary" style="float: right;" @click="copyLink">点击复制</el-button>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script lang="ts" name="systemWxAccount" setup>
import {BasicTableProps, useTable} from "/@/hooks/table";
import {delObjs, fetchList} from "/@/api/mp/wx-account";
import {delObjs, fetchList, generateQr} from "/@/api/mp/wx-account";
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
@ -137,4 +161,18 @@ const handleDelete = (ids: string[]) => {
})
})
};
const dialogFormVisible = ref(false)
const wxurl = ref("")
const access = (row: any) => {
dialogFormVisible.value = true
wxurl.value = row.url + '/mp/' + row.appid + '/portal'
}
const generate = (row: any) => {
generateQr(row.appid).then(() => {
useMessage().success("获取成功")
getDataList()
})
}
</script>

View File

@ -11,7 +11,7 @@ export default {
type: '消息分类',
repType: '消息类型',
repEvent: '事件类型',
repContent: '回复类型文本保存文字、地理位置信息',
repContent: '内容',
repMediaId: '回复类型',
repName: '回复的素材名、视频和音乐的标题',
repDesc: '视频和音乐的描述',

View File

@ -44,10 +44,32 @@
<el-table-column align="center" type="selection" width="60"/>
<el-table-column :label="t('wxFansMsg.index')" type="index" width="80"/>
<el-table-column :label="t('wxFansMsg.appName')" prop="appName" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.wxUserId')" prop="wxUserId" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.nickName')" prop="nickName" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.repMediaId')" prop="repMediaId" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.content')" prop="content" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.repType')" prop="repType" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.openId')" prop="openId" show-overflow-tooltip/>
<el-table-column :label="t('wxFansMsg.repContent')" prop="repContent" show-overflow-tooltip>
<template #default="scope">
<div v-if="scope.row.repType === 'event' && scope.row.repEvent === 'subscribe'"><el-tag type="success" size="mini">关注</el-tag></div>
<div v-if="scope.row.repType === 'event' && scope.row.repEvent === 'unsubscribe'"><el-tag type="danger" size="mini">取消关注</el-tag></div>
<div v-if="scope.row.repType === 'event' && scope.row.repEvent === 'CLICK'"><el-tag size="mini">点击菜单</el-tag>{{ scope.row.repName }}</div>
<div v-if="scope.row.repType === 'event' && scope.row.repEvent === 'VIEW'"><el-tag size="mini">点击菜单链接</el-tag>{{ scope.row.repUrl }}</div>
<div v-if="scope.row.repType === 'event' && scope.row.repEvent === 'scancode_waitmsg'"><el-tag size="mini">扫码结果</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 :obj-data="scope.row"></WxVoicePlayer>
</div>
<div v-if="scope.row.repType === 'video'">
<WxVideoPlayer :obj-data="scope.row" style="margin-top: 40px"></WxVideoPlayer>
</div>
<div v-if="scope.row.repType === 'shortvideo'">
<WxVideoPlayer :obj-data="scope.row" style="margin-top: 40px"></WxVideoPlayer>
</div>
<div v-if="scope.row.repType === 'link'"><el-tag size="mini">链接</el-tag><a :href="scope.row.repUrl" target="_blank">{{ scope.row.repName }}</a></div>
</template>
</el-table-column>
<el-table-column :label="t('wxFansMsg.readFlag')" prop="readFlag" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="response_type" :value="scope.row.readFlag"></dict-tag>

View File

@ -0,0 +1,36 @@
<template>
<el-dialog
:title="operateMaterial === 'add'?'新建图文':'修改图文'"
:before-close="dialogNewsClose"
:close-on-click-modal="false"
v-model="dialogNewsVisible"
width="80%"
top="20px">
</el-dialog>
</template>
<script setup lang="ts" name="wx-news-form">
import {useMessageBox} from "/@/hooks/message";
const dialogNewsVisible = ref(false)
const operateMaterial = ref("")
const dialogNewsClose = () => {
useMessageBox().confirm("修改内容可能还未保存,确定关闭吗?").then(() => {
dialogNewsVisible.value = false
})
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,305 @@
<template>
<div class="layout-padding">
<el-row :gutter="20">
<el-col :md="4">
<el-card class="layout-padding-auto" shadow="hover">
<query-tree :query="deptData.queryList"
@node-click="handleNodeClick"/>
</el-card>
</el-col>
<el-col :span="20">
<el-card class="layout-padding-auto" shadow="hover">
<el-tabs v-model="materialType" @tab-click="handleClick">
<el-tab-pane name="image" label="image">
<template #label><i class="el-icon-picture"></i> 图片</template>
<div class="add_but">
<upload-file @click="handelImageChange" type="simple" :uploadFileUrl="actionUrl" :data="uploadData"></upload-file>
</div>
<div v-loading="state.loading" class="waterfall">
<div v-for="item in state.dataList" :key="item.id" class="waterfall-item">
<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">
<el-button type="danger" icon="el-icon-delete" circle @click="delMaterial(item)"></el-button>
</el-row>
</div>
</div>
<div v-if="state.dataList.length <=0 && !state.loading" class="el-table__empty-block">
<span class="el-table__empty-text">暂无数据</span>
</div>
<pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle"/>
</el-tab-pane>
<el-tab-pane name="voice" label="voice">
<template #label><i class="el-icon-microphone"></i> 语音</template>
<div class="add_but">
<upload-file @click="handelImageChange" type="simple" :uploadFileUrl="actionUrl" :data="uploadData"></upload-file>
</div>
<el-table
v-loading="state.loading"
:data="state.dataList"
stripe
border>
<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
type="text"
icon="el-icon-download"
size="small"
plain
@click="handleDown(scope.row)">下载
</el-button>
<el-button
type="text"
icon="el-icon-delete"
size="small"
plain
@click="delMaterial(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle"/>
</el-tab-pane>
<el-tab-pane name="video" label="video">
<template #label><i class="el-icon-video-play"></i> 视频</template>
<div class="add_but">
<el-button size="mini" type="primary" @click="handleAddVideo">新建</el-button>
</div>
<el-dialog v-loading="addMaterialLoading" title="新建视频" v-model="dialogVideoVisible">
<upload-file @click="handelImageChange" type="simple" :uploadFileUrl="actionUrl" :data="uploadData" :auto-upload="false" ref="uploadFileVideo" :limit="1"></upload-file>
<el-form
ref="uploadForm"
:model="uploadData"
:rules="uploadRules">
<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
v-model="uploadData.introduction"
:rows="3"
type="textarea"
placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容"></el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVideoVisible = false"> </el-button>
<el-button type="primary" @click="subVideo"> </el-button>
</template>
</el-dialog>
<el-table
v-loading="state.loading"
:data="state.dataList"
stripe
border>
<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
type="text"
icon="el-icon-view"
size="small"
plain
@click="handleInfo(scope.row)">查看
</el-button>
<el-button
v-if="permissions.mp_wxmaterial_del"
type="text"
icon="el-icon-delete"
size="small"
plain
@click="delMaterial(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane name="news" label="news">
<template #label><i class="el-icon-news"></i> 图文</template>
<div class="add_but">
<el-button type="primary" size="mini" @click="handleAddNews"> </el-button>
</div>
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts" name="wx-material">
import { fetchAccountList } from "/@/api/mp/wx-account";
import {useMessage, useMessageBox} from "/@/hooks/message";
import {BasicTableProps, useTable} from "/@/hooks/table";
import { delObj,getPage } from '/@/api/mp/wx-material'
const QueryTree = defineAsyncComponent(() => import('/@/components/QueryTree/index.vue'))
const deptData = reactive({
queryList: () => {
return fetchAccountList()
}
})
const checkAppId = ref()
const uploadData = ref({
appId: '',
mediaType: 'image',
title: '',
introduction: '',
})
const materialType = ref("image")
//
const handleNodeClick = (data: any) => {
checkAppId.value = data.appid
uploadData.value.appId = data.appid
state.queryForm.appId = data.appid
state.queryForm.type = materialType.value
getDataList()
}
const handleClick = (tab) => {
if (checkAppId.value) {
// getPage(this.page)
} else {
useMessage().error("请选择公众号")
}
materialType.value = tab.paneName
uploadData.value.mediaType = tab.paneName
}
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
appId: '',
type: ''
},
pageList: getPage,
createdIsNeed: false,
props: {
item: 'item',
totalCount: 'totalCount'
}
})
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
} = useTable(state)
const handelImageChange = () => {
console.log("111111111")
getDataList()
}
const delMaterial = (item: any) => {
useMessageBox().confirm("此操作将永久删除该文件, 是否继续?").then(() => {
delObj({
id: item.mediaId,
appId: checkAppId.value
}).then(() => {
getDataList()
})
})
}
const actionUrl = ref("/admin/wx-material/materialFileUpload")
//
const dialogVideoVisible = ref(false)
const addMaterialLoading = ref(false)
const handleAddVideo = () => {
dialogVideoVisible.value = true
}
const uploadRules = reactive({
title: [
{ required: true, message: '请输入标题', trigger: 'blur' }
],
introduction: [
{ required: true, message: '请输入描述', trigger: 'blur' }
]
})
const uploadForm = ref()
const uploadFileVideo = ref()
const subVideo = () => {
uploadForm.value.validate((valid: boolean) => {
if (!valid) {
return false
}
uploadFileVideo.value.submit()
}).finally(() => {
dialogVideoVisible.value = false
})
}
//
const dialogNewsVisible = ref(true)
const handleAddNews = () => {
dialogNewsVisible.value = true
}
</script>
<style scoped>
</style>

View File

@ -45,6 +45,10 @@
</el-icon>
</div>
</div>
<div class="save_div">
<el-button class="save_btn" type="success" size="small" @click="handleSave">保存并发布菜单</el-button>
<el-button class="save_btn" type="danger" size="small" @click="handleDelete">清空菜单</el-button>
</div>
</div>
<div v-if="showRightFlag" class="right">
@ -68,6 +72,51 @@
<el-option v-for="item in menuOptions" :key="item.value" :label="item.label" :value="item.value"/>
</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 />
</div>
<div class="configur_content" v-if="tempObj.type === 'miniprogram'">
<div class="applet">
<span>小程序的 appid </span>
<el-input class="input_width" v-model="tempObj.miniProgramAppId" placeholder="请输入小程序的appid" clearable />
</div>
<div class="applet">
<span>小程序的页面路径</span>
<el-input class="input_width" v-model="tempObj.miniProgramPagePath"
placeholder="请输入小程序的页面路径pages/index" clearable />
</div>
<div class="applet">
<span>小程序的备用网页</span>
<el-input class="input_width" v-model="tempObj.url" placeholder="不支持小程序的老版本客户端将打开本网页" clearable />
</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.replyArticles">
<wx-news :articles="tempObj.replyArticles" />
<el-row class="ope-row">
<el-button type="danger" icon="el-icon-delete" circle @click="deleteMaterial" />
</el-row>
</div>
<div v-else>
<el-row>
<el-col :span="24" style="text-align: center">
<el-button type="success" @click="openMaterial">
素材库选择<i class="el-icon-circle-check el-icon--right"></i>
</el-button>
</el-col>
</el-row>
</div>
<el-dialog title="选择图文" v-model="dialogNewsVisible" width="90%">
<wx-material-select :objData="{type: 'news', accountId: this.accountId}" @selectMaterial="selectMaterial" />
</el-dialog>
</el-row>
</div>
<div class="configur_content" v-if="tempObj.type === 'click' || tempObj.type === 'scancode_waitmsg'">
<wx-reply-select :objData="tempObj.reply" v-if="hackResetWxReplySelect" />
</div>
</div>
</div>
</div>
@ -79,15 +128,18 @@
</template>
<script lang="ts" name="wx-menu" setup>
import { saveObj } from '/@/api/mp/wx-menu'
// 使
import {fetchAccountList} from "/@/api/mp/wx-account";
import {useMessage, useMessageBox} from "/@/hooks/message";
const WxMaterialSelect = defineAsyncComponent(() => import("/@/components/wechart/wx-material-select/main.vue"))
const QueryTree = defineAsyncComponent(() => import('/@/components/QueryTree/index.vue'))
//
const handleNodeClick = (e: any) => {
const handleNodeClick = (node: any) => {
accountId.value = node.appid
}
const deptData = reactive({
@ -160,7 +212,10 @@ const menuOptions = ref([
const showRightFlag = ref(false)
let tempObj = ref({})
let tempObj = ref({
replyArticles: [] as any,
articleId: ''
})
const tempSelfObj = reactive({
grand: '', //
@ -239,6 +294,94 @@ const deleteMenu = () => {
}
const handleSave = () => {
useMessageBox().confirm("").then(() => {
return saveObj(accountId.value, convertMenuFormList());
})
}
const convertMenuFormList = () => {
const menuList = [] as any;
menuList.forEach(item => {
let menu = convertMenuForm(item);
menuList.push(menu);
//
if (!item.children || item.children.length <= 0) {
return;
}
menu.children = [];
item.children.forEach(subItem => {
menu.children.push(convertMenuForm(subItem))
})
})
return menuList;
}
// menu menu
const convertMenuForm = (menu: any) => {
let result = {
...menu,
children: undefined, //
reply: undefined, //
}
if (menu.type === 'click' || menu.type === 'scancode_waitmsg') {
result.replyMessageType = menu.reply.type;
result.replyContent = menu.reply.content;
result.replyMediaId = menu.reply.mediaId;
result.replyMediaUrl = menu.reply.url;
result.replyTitle = menu.reply.title;
result.replyDescription = menu.reply.description;
result.replyThumbMediaId = menu.reply.thumbMediaId;
result.replyThumbMediaUrl = menu.reply.thumbMediaUrl;
result.replyArticles = menu.reply.articles;
result.replyMusicUrl = menu.reply.musicUrl;
result.replyHqMusicUrl = menu.reply.hqMusicUrl;
}
return result;
}
const deleteMaterial = () => {
tempObj.value.replyArticles = []
tempObj.value.articleId = ""
}
const dialogNewsVisible = ref(false)
const openMaterial = () => {
dialogNewsVisible.value = true
}
const selectMaterial = (item) => {
const articleId = item.articleId;
const articles = item.content.newsItem;
//
if (articles.length > 1) {
// this.$alert('', '', {
// confirmButtonText: ''
// })
}
dialogNewsVisible.value = false
//
tempObj.value.articleId = articleId;
tempObj.value.replyArticles = [];
articles.forEach(article => {
tempObj.value.replyArticles.push({
title: article.title,
description: article.digest,
picUrl: article.picUrl,
url: article.url,
})
})
}
const handleDelete = () => {
}
</script>