mirror of
https://gitee.com/log4j/pig-ui.git
synced 2024-12-23 05:40:20 +08:00
✨ Introducing new features. 微信模块功能优化
This commit is contained in:
parent
30b66bd4fd
commit
6aa288cdf2
@ -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'
|
||||
|
@ -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])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
162
src/components/wechart/wx-material-select/main.vue
Normal file
162
src/components/wechart/wx-material-select/main.vue
Normal 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: {
|
||||
// 图文类型:1、已发布图文;2、草稿箱图文
|
||||
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>
|
@ -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(() => {
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -11,7 +11,7 @@ export default {
|
||||
type: '消息分类',
|
||||
repType: '消息类型',
|
||||
repEvent: '事件类型',
|
||||
repContent: '回复类型文本保存文字、地理位置信息',
|
||||
repContent: '内容',
|
||||
repMediaId: '回复类型',
|
||||
repName: '回复的素材名、视频和音乐的标题',
|
||||
repDesc: '视频和音乐的描述',
|
||||
|
@ -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>
|
||||
|
36
src/views/mp/wx-material/components/news-form.vue
Normal file
36
src/views/mp/wx-material/components/news-form.vue
Normal 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>
|
305
src/views/mp/wx-material/index.vue
Normal file
305
src/views/mp/wx-material/index.vue
Normal 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>
|
@ -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>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user