first commit

This commit is contained in:
2025-12-26 23:19:09 +08:00
commit b29d128e41
788 changed files with 100922 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
<template>
<el-upload
ref="fileUpload"
:action="actionUrl"
:headers="headers"
multiple
:limit="1"
:on-success="handleUploadSuccess"
:file-list="fileList"
:before-upload="beforeThumbImageUpload"
:auto-upload="autoUpload"
:data="uploadData"
>
<template #tip>
<div class="el-upload__tip" v-if="props.type.length > 0">支持{{ props.type.join('/') }}格式大小不超过2M</div>
</template>
<el-button type="primary">本地上传</el-button>
</el-upload>
</template>
<script setup lang="ts" name="wx-file-upload">
import { Session } from '/@/utils/storage';
import { useMessage } from '/@/hooks/message';
const actionUrl = ref('/api/mp/wx-material/materialFileUpload');
const fileUpload = ref();
const headers = computed(() => {
const tenantId = Session.getTenant();
return {
Authorization: 'Bearer ' + Session.getToken(),
'TENANT-ID': tenantId,
};
});
// 定义刷新表格emit
const emit = defineEmits(['success']);
const fileList = ref([]);
const props = defineProps({
uploadData: {
type: Object,
default: () => {
return {
appId: '',
mediaType: 'image',
title: '',
introduction: '',
};
},
},
autoUpload: {
type: Boolean,
default: true,
},
type: {
type: Array,
default: () => {
return [];
},
},
});
const beforeThumbImageUpload = (file: any) => {
let isType = true;
if (props.type?.length > 0) {
isType = props.type?.includes(file.type);
}
const isLt = file.size / 1024 / 1024 < 2;
if (!isType) {
useMessage().error('上传文件格式不对!');
}
if (!isLt) {
useMessage().error('上传文件大小不能超过2M!!');
}
return isType && isLt;
};
const handleUploadSuccess = (response, file, fileList) => {
fileList.value = [];
emit('success', response, file, fileList);
};
const submit = () => {
return new Promise((resolve) => {
fileUpload.value.submit();
resolve('');
});
};
defineExpose({
submit,
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,166 @@
<template>
<el-dialog title="选择图文" v-model="visible" :close-on-click-modal="false" draggable width="80%">
<div v-if="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 type="success" @click="selectMaterial(item)"
>选择
<el-icon class="el-icon--right"></el-icon>
</el-button>
</el-row>
</div>
</div>
<pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle" />
</div>
<div v-else-if="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" 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 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="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 @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="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 :obj-data="item.content.newsItem"></wx-news>
<el-row class="ope-row">
<el-button type="success" @click="selectMaterial(item)"> 选择<el-icon class="el-icon--right" /> </el-button>
</el-row>
</div>
</template>
</div>
<pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle" />
</div>
</el-dialog>
</template>
<script setup lang="ts" name="wx-material-select">
import { BasicTableProps, useTable } from '/@/hooks/table';
import { getPage } from '/@/api/mp/wx-material';
const WxNews = defineAsyncComponent(() => import('../wx-news/index.vue'));
const emit = defineEmits(['selectMaterial']);
const objData = reactive({
repType: '',
accountId: '',
type: '',
});
const visible = ref(false);
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
type: '',
appId: '',
},
pageList: getPage,
createdIsNeed: false,
props: {
item: 'items',
totalCount: 'totalCount',
},
});
const { getDataList, currentChangeHandle, sizeChangeHandle } = useTable(state);
const selectMaterial = (item: any) => {
visible.value = false;
emit('selectMaterial', item, objData.accountId);
};
const openDialog = (data: any) => {
state.queryForm.type = data.type;
state.queryForm.appId = data.accountId;
objData.type = data.type;
objData.accountId = data.accountId;
visible.value = true;
getDataList();
};
// 暴露变量
defineExpose({
openDialog,
});
</script>
<style lang="scss" scoped>
/*瀑布流样式*/
.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;
}
.material-img {
width: 100%;
}
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;
}
}
/*瀑布流样式*/
</style>

View File

@@ -0,0 +1,101 @@
.avue-card {
&__item {
margin-bottom: 16px;
border: 1px solid #e8e8e8;
background-color: #fff;
box-sizing: border-box;
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5;
list-style: none;
font-feature-settings: 'tnum';
cursor: pointer;
height: 200px;
&:hover {
border-color: rgba(0, 0, 0, 0.09);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
}
&--add {
border: 1px dashed #000;
width: 100%;
color: rgba(0, 0, 0, 0.45);
background-color: #fff;
border-color: #d9d9d9;
border-radius: 2px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
i {
margin-right: 10px;
}
&:hover {
color: #40a9ff;
background-color: #fff;
border-color: #40a9ff;
}
}
}
&__body {
display: flex;
padding: 24px;
}
&__detail {
flex: 1;
}
&__avatar {
width: 48px;
height: 48px;
border-radius: 48px;
overflow: hidden;
margin-right: 12px;
img {
width: 100%;
height: 100%;
}
}
&__title {
color: rgba(0, 0, 0, 0.85);
margin-bottom: 12px;
font-size: 16px;
&:hover {
color: #1890ff;
}
}
&__info {
color: rgba(0, 0, 0, 0.45);
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
height: 64px;
}
&__menu {
display: flex;
justify-content: space-around;
height: 50px;
background: #f7f9fa;
color: rgba(0, 0, 0, 0.45);
text-align: center;
line-height: 50px;
&:hover {
color: #1890ff;
}
}
}
/** joolun 额外加的 */
.avue-comment__main {
flex: unset !important;
border-radius: 5px !important;
margin: 0 8px !important;
}
.avue-comment__header {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.avue-comment__body {
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}

View File

@@ -0,0 +1,92 @@
/* 来自 https://github.com/nmxiaowei/avue/blob/master/styles/src/element-ui/comment.scss */
.avue-comment {
margin-bottom: 30px;
display: flex;
align-items: flex-start;
&--reverse {
flex-direction: row-reverse;
.avue-comment__main {
&:before,
&:after {
left: auto;
right: -8px;
border-width: 8px 0 8px 8px;
}
&:before {
border-left-color: #dedede;
}
&:after {
border-left-color: #f8f8f8;
margin-right: 1px;
margin-left: auto;
}
}
}
&__avatar {
width: 48px;
height: 48px;
border-radius: 50%;
border: 1px solid transparent;
box-sizing: border-box;
vertical-align: middle;
}
&__header {
padding: 5px 15px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
}
&__author {
font-weight: 700;
font-size: 14px;
color: #999;
}
&__main {
flex: 1;
margin: 0 20px;
position: relative;
border: 1px solid #dedede;
border-radius: 2px;
&:before,
&:after {
position: absolute;
top: 10px;
left: -8px;
right: 100%;
width: 0;
height: 0;
display: block;
content: ' ';
border-color: transparent;
border-style: solid solid outset;
border-width: 8px 8px 8px 0;
pointer-events: none;
}
&:before {
border-right-color: #dedede;
z-index: 1;
}
&:after {
border-right-color: #f8f8f8;
margin-left: 1px;
z-index: 2;
}
}
&__body {
padding: 15px;
overflow: hidden;
background: #fff;
font-family: Segoe UI, Lucida Grande, Helvetica, Arial, Microsoft YaHei, FreeSans, Arimo, Droid Sans, wenquanyi micro hei, Hiragino Sans GB,
Hiragino Sans GB W3, FontAwesome, sans-serif;
color: #333;
font-size: 14px;
}
blockquote {
margin: 0;
font-family: Georgia, Times New Roman, Times, Kai, Kaiti SC, KaiTi, BiauKai, FontAwesome, serif;
padding: 1px 0 1px 15px;
border-left: 4px solid #ddd;
}
}

View File

@@ -0,0 +1,258 @@
<template>
<el-dialog title="用户消息" v-model="visible" :close-on-click-modal="false" draggable>
<div v-loading="mainLoading" class="msg-main">
<div id="msg-div" class="msg-div">
<div v-if="!tableLoading">
<div v-if="loadMore" class="el-table__empty-block" @click="loadingMore"><span class="el-table__empty-text">点击加载更多</span></div>
<div v-if="!loadMore" class="el-table__empty-block"><span class="el-table__empty-text">没有更多了</span></div>
</div>
<div v-for="item in tableData" :key="item.id" class="execution" id="msgTable">
<div class="avue-comment" :class="item.type === '2' ? 'avue-comment--reverse' : ''">
<div class="avatar-div">
<name-avatar v-if="item.type === '1'" scale="2" :name="item.nickName" />
<name-avatar v-if="item.type !== '1'" scale="2" :face-url="item.appLogo" />
</div>
<div class="avue-comment__main">
<div class="avue-comment__header">
<div class="avue-comment__create_time">{{ item.createTime }}</div>
</div>
<div class="avue-comment__body" :style="item.type === '2' ? 'background: #6BED72;' : ''">
<div v-if="item.repType === 'event' && item.repEvent === 'subscribe'">
<el-tag type="success" size="mini">关注</el-tag>
</div>
<div v-if="item.repType === 'event' && item.repEvent === 'unsubscribe'">
<el-tag type="danger" size="mini">取消关注</el-tag>
</div>
<div v-if="item.repType === 'event' && item.repEvent === 'CLICK'">
<el-tag size="mini">点击菜单</el-tag>
{{ item.repName }}
</div>
<div v-if="item.repType === 'event' && item.repEvent === 'VIEW'">
<el-tag size="mini">点击菜单链接</el-tag>
{{ item.repUrl }}
</div>
<div v-if="item.repType === 'event' && item.repEvent === 'scancode_waitmsg'">
<el-tag size="mini">扫码结果</el-tag>
{{ item.repContent }}
</div>
<div v-if="item.repType === 'text'">{{ item.repContent }}</div>
<div v-if="item.repType === 'image'">
<a target="_blank" :href="item.repUrl"><img :src="item.repUrl" style="width: 100px" /></a>
</div>
<div v-if="item.repType === 'voice'">
<SvgIcon name="local-wx-voice" :size="80" @click="loadVideo(item)"></SvgIcon>
</div>
<div v-if="item.repType === 'video'" style="text-align: center">
<SvgIcon name="local-wx-video" :size="80" @click="loadVideo(item)"></SvgIcon>
</div>
<div v-if="item.repType === 'shortvideo'" style="text-align: center">
<svg-icon name="local-wx-video" :size="80" @click="loadVideo(item)"></svg-icon>
</div>
<div v-if="item.repType === 'location'">
<el-link
type="primary"
target="_blank"
:href="
'https://map.qq.com/?type=marker&isopeninfowin=1&markertype=1&pointx=' +
item.repLocationY +
'&pointy=' +
item.repLocationX +
'&name=' +
item.repContent +
'&ref=joolun'
"
>
<img
:src="
'https://apis.map.qq.com/ws/staticmap/v2/?zoom=10&markers=color:blue|label:A|' +
item.repLocationX +
',' +
item.repLocationY +
'&key=PFFBZ-RBM3V-IEEPP-UH6KE-6QUQE-C4BVJ&size=250*180'
"
/>
<p />
<i class="el-icon-map-location"></i>{{ item.repContent }}
</el-link>
</div>
<div v-if="item.repType === 'link'" class="avue-card__detail">
<el-link type="success" :underline="false" target="_blank" :href="item.repUrl">
<div class="avue-card__title"><i class="el-icon-link"></i>{{ item.repName }}</div>
</el-link>
<div class="avue-card__info" style="height: unset">{{ item.repDesc }}</div>
</div>
<div v-if="item.repType === 'news'" style="width: 300px">
<wx-news :obj-data="JSON.parse(item.content)"></wx-news>
</div>
<div v-if="item.repType === 'music'">
<el-link type="success" :underline="false" target="_blank" :href="item.repUrl">
<div class="avue-card__body" style="padding: 10px; background-color: #fff; border-radius: 5px">
<div class="avue-card__avatar"><img :src="item.repThumbUrl" alt="" /></div>
<div class="avue-card__detail">
<div class="avue-card__title" style="margin-bottom: unset">{{ item.repName }}</div>
<div class="avue-card__info" style="height: unset">{{ item.repDesc }}</div>
</div>
</div>
</el-link>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-loading="sendLoading" class="msg-send" @keyup.enter="sendMsg">
<wx-reply :objData="objData"></wx-reply>
<el-button type="success" class="send-but" @click="sendMsg">发送(S)</el-button>
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts" name="wx-msg">
import { fetchList, addObj } from '/@/api/mp/wx-fans-msg';
import { useMessage } from '/@/hooks/message';
import { getMaterialVideo } from '/@/api/mp/wx-material';
const WxReply = defineAsyncComponent(() => import('../wx-reply/index.vue'));
const WxNews = defineAsyncComponent(() => import('../wx-news/index.vue'));
const NameAvatar = defineAsyncComponent(() => import('/@/components/NameAvatar/index.vue'));
const visible = ref(false);
// 各种loading
const mainLoading = ref(false);
const sendLoading = ref(false);
const loadMore = ref(false);
const objData = ref({
repType: 'text',
appId: '',
}) as any;
const page = reactive({
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10, // 每页显示多少条
ascs: [], //升序字段
descs: 'create_time', //降序字段
});
const wxData = reactive({
appId: '',
wxUserId: '',
});
const sendMsg = () => {
if (objData.value) {
if (objData.value.repType === 'news') {
if (JSON.parse(objData.value.content).length > 1) {
useMessage().error('图文消息条数限制在1条以内已默认发送第一条');
objData.value.content = JSON.parse(objData.value.content)[0];
}
}
sendLoading.value = true;
addObj(
Object.assign(
{
wxUserId: wxData.wxUserId,
appId: wxData.appId,
},
objData.value
)
)
.then(() => {
tableData.value = [];
getData().then(() => {
//box-container是添加overflow的父div也就是出现滚动条的div
var scrollTarget = document.getElementById('msg-div');
//scrollTarget.scrollHeight是获取dom元素的高度然后设置scrollTop
scrollTarget.scrollTop = scrollTarget.scrollHeight;
});
})
.finally(() => {
sendLoading.value = false;
});
}
};
const tableData = ref([] as any);
const tableLoading = ref(false);
const openDialog = (data: any) => {
wxData.wxUserId = data.wxUserId;
wxData.appId = data.appId;
objData.value.appId = data.appId;
getData();
visible.value = true;
};
const getData = () => {
tableLoading.value = true;
return fetchList({
...page,
...wxData,
}).then((res) => {
const data = res.data.records.reverse();
tableData.value = [...data, ...tableData.value];
page.total = res.data.total;
tableLoading.value = false;
if (data.length < page.pageSize || data.length === 0) {
loadMore.value = false;
}
});
};
const loadVideo = (item) => {
getMaterialVideo({
mediaId: item.repMediaId,
appId: item.appId,
}).then((response) => {
const data = response.data;
window.open(data.downUrl, 'target', '');
});
};
const loadingMore = () => {
page.currentPage = page.currentPage + 1;
getData();
};
// 暴露变量
defineExpose({
openDialog,
});
</script>
<style lang="scss" scoped>
@import './comment.scss';
@import './card.scss';
.msg-main {
margin-top: -30px;
padding: 10px;
}
.msg-div {
height: 50vh;
overflow: auto;
background-color: #eaeaea;
margin-left: 10px;
margin-right: 10px;
}
.msg-send {
padding: 10px;
}
.avatar-div {
text-align: center;
width: 80px;
}
.send-but {
float: right;
margin-top: 8px !important;
}
</style>

View File

@@ -0,0 +1,90 @@
<template>
<div class="news-home">
<div v-for="(news, index) in props.objData" :key="index" class="news-div">
<a v-if="index === 0" target="_blank" :href="news.url">
<div class="news-main">
<div class="news-content">
<img class="material-img" :src="news.thumbUrl" style="width: 280; height: 120" />
<div class="news-content-title">
<span>{{ news.title }}</span>
</div>
</div>
</div>
</a>
<a v-if="index > 0" target="_blank" :href="news.url">
<div class="news-main-item">
<div class="news-content-item">
<div class="news-content-item-title">{{ news.title }}</div>
<div class="news-content-item-img">
<img class="material-img" :src="news.thumbUrl" height="100%" />
</div>
</div>
</div>
</a>
</div>
</div>
</template>
<script setup lang="ts" name="wx-news">
const props = defineProps({
objData: {
type: Array,
default: () => [],
},
});
</script>
<style lang="scss" scoped>
.news-home {
background-color: #ffffff;
width: 100%;
margin: auto;
}
.news-main {
width: 100%;
margin: auto;
}
.news-content {
background-color: #acadae;
width: 100%;
position: relative;
}
.news-content-title {
display: inline-block;
font-size: 12px;
color: #ffffff;
position: absolute;
left: 0px;
bottom: 0px;
background-color: black;
width: 98%;
padding: 1%;
opacity: 0.65;
white-space: normal;
box-sizing: unset !important;
}
.news-main-item {
background-color: #ffffff;
padding: 5px 0px;
border-top: 1px solid #eaeaea;
}
.news-content-item {
position: relative;
}
.news-content-item-title {
display: inline-block;
font-size: 10px;
width: 70%;
margin-left: 1%;
white-space: normal;
}
.news-content-item-img {
display: inline-block;
width: 25%;
background-color: #acadae;
margin-right: 1%;
}
.material-img {
width: 100%;
}
</style>

View File

@@ -0,0 +1,309 @@
<template>
<el-tabs v-model="objData.repType" type="border-card" @tab-click="handleClick" style="width: 100%">
<el-tab-pane name="text" label="text">
<template #label><i class="el-icon-document"></i> 文本</template>
<el-input v-model="objData.repContent" type="textarea" :rows="5" placeholder="请输入内容"> </el-input>
</el-tab-pane>
<el-tab-pane name="image" label="image">
<template #label><i class="el-icon-picture"></i> 图片</template>
<el-row>
<div v-if="objData.repUrl" class="select-item">
<img class="material-img" :src="objData.repUrl" />
<p v-if="objData.repName" class="item-name">{{ objData.repName }}</p>
<el-row class="ope-row">
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
</el-row>
</div>
<div v-if="!objData.repUrl" style="width: 100%">
<el-row style="text-align: center">
<el-col :span="12" class="col-select">
<el-button type="success" @click="openMaterial({ type: 'image', accountId: props.objData.appId })"
>素材库选择<i class="fansel-icon--right"></i>
</el-button>
</el-col>
<el-col :span="12" class="col-add">
<wx-file-upload :data="uploadData" @success="handelUpload"></wx-file-upload>
</el-col>
</el-row>
</div>
</el-row>
</el-tab-pane>
<el-tab-pane name="voice" label="voice">
<template #label><i class="el-icon-phone"></i> 语音</template>
<el-row>
<div v-if="objData.repName" class="select-item">
<p class="item-name">{{ objData.repName }}</p>
<div class="item-infos">
<img :src="WxVoice" style="width: 100px" @click="loadVideo(item)" />
</div>
<el-row class="ope-row">
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
</el-row>
</div>
<div v-if="!objData.repName" style="width: 100%">
<el-row style="text-align: center">
<el-col :span="12" class="col-select">
<el-button type="success" @click="openMaterial({ type: 'voice', accountId: props.objData.appId })"
>素材库选择<i class="fansel-icon--right"></i>
</el-button>
</el-col>
<el-col :span="12" class="col-add">
<wx-file-upload :data="uploadData" @success="handelUpload"></wx-file-upload>
</el-col>
</el-row>
</div>
</el-row>
</el-tab-pane>
<el-tab-pane name="video" label="video">
<template #label><i class="el-icon-share"></i> 视频</template>
<el-row style="text-align: center; flex: 1">
<el-input v-if="objData.repUrl" v-model="objData.repName" placeholder="请输入标题" style="margin: 10px"></el-input>
<el-input v-if="objData.repUrl" v-model="objData.repDesc" placeholder="请输入描述" style="margin: 10px"></el-input>
</el-row>
<el-row style="text-align: center">
<el-col :span="12" class="col-select">
<a v-if="objData.repUrl" target="_blank" :href="objData.repUrl"> <SvgIcon name="local-wx-video" :size="45" /> </a
></el-col>
<el-col :span="12" class="col-add">
<el-button type="success" @click="openMaterial({ type: 'video', accountId: props.objData.appId })">素材库选择 </el-button>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane name="news" label="news">
<template #label><i class="el-icon-news"></i> 图文</template>
<el-row>
<div v-if="objData.content" class="select-item">
<wx-news :obj-data="JSON.parse(objData.content)"></wx-news>
<el-row class="ope-row">
<el-button type="danger" icon="el-icon-delete" circle @click="deleteObj"></el-button>
</el-row>
</div>
<div v-if="!objData.content" style="width: 100%">
<el-row style="text-align: center">
<el-col :span="24" class="col-select2">
<el-button type="success" @click="openMaterial({ type: 'news', accountId: props.objData.appId })"
>素材库选择<i class="fansel-icon--right"></i>
</el-button>
</el-col>
</el-row>
</div>
</el-row>
</el-tab-pane>
</el-tabs>
<wx-material-select ref="dialogNewsRef" @selectMaterial="selectMaterial"></wx-material-select>
</template>
<script setup lang="ts" name="wx-reply">
import { getMaterialVideo } from '/@/api/mp/wx-material';
import { useMessage } from '/@/hooks/message';
const WxMaterialSelect = defineAsyncComponent(() => import('/@/components/Wechat/wx-material-select/main.vue'));
const WxFileUpload = defineAsyncComponent(() => import('/@/components/Wechat/fileUpload/index.vue'));
const WxNews = defineAsyncComponent(() => import('/@/components/Wechat/wx-news/index.vue'));
const props = defineProps({
objData: {
type: Object,
default: () => {
return {
repType: '',
repContent: '',
repName: '',
repDesc: '',
repUrl: '',
};
},
},
});
const uploadData = reactive({
mediaType: props.objData.repType,
title: '',
introduction: '',
appId: props.objData.appId,
});
const tempObj = ref({}) as any;
const handleClick = (tab) => {
uploadData.mediaType = tab.paneName;
uploadData.appId = props.objData.appId;
const tempObjItem = tempObj.value[tab.paneName];
if (tempObjItem) {
props.objData.repName = tempObjItem.repName ? tempObjItem.repName : null;
props.objData.repMediaId = tempObjItem.repMediaId ? tempObjItem.repMediaId : null;
props.objData.media_id = tempObjItem.media_id ? tempObjItem.media_id : null;
props.objData.repUrl = tempObjItem.repUrl ? tempObjItem.repUrl : null;
props.objData.content = tempObjItem.content ? tempObjItem.content : null;
props.objData.repDesc = tempObjItem.repDesc ? tempObjItem.repDesc : null;
} else {
props.objData.repName = '';
props.objData.repMediaId = '';
props.objData.media_id = '';
props.objData.repUrl = '';
props.objData.content = '';
props.objData.repDesc = '';
}
};
const deleteObj = () => {
props.objData.repName = '';
props.objData.repUrl = '';
props.objData.content = '';
};
const openMaterial = (data: any) => {
dialogNewsRef.value.openDialog(data);
};
const dialogNewsRef = ref();
const selectMaterial = (item, appId) => {
let tempObjItem = {
repType: '',
repMediaId: '',
media_id: '',
content: '',
} as any;
tempObjItem.repType = props.objData.repType;
tempObjItem.repMediaId = item.mediaId;
tempObjItem.media_id = item.mediaId;
tempObjItem.content = item.content;
props.objData.repMediaId = item.mediaId;
props.objData.media_id = item.mediaId;
props.objData.content = item.content;
if (props.objData.repType === 'music') {
tempObjItem.repThumbMediaId = item.mediaId;
tempObjItem.repThumbUrl = item.url;
props.objData.repThumbMediaId = item.mediaId;
props.objData.repThumbUrl = item.url;
} else {
tempObjItem.repName = item.name;
tempObjItem.repUrl = item.url;
props.objData.repName = item.name;
props.objData.repUrl = item.url;
}
if (props.objData.repType === 'video') {
getMaterialVideo({
mediaId: item.mediaId,
appId: appId,
}).then((response) => {
const data = response.data;
tempObjItem.repDesc = data.description || '';
tempObjItem.repUrl = data.downUrl;
props.objData.repName = data.title;
props.objData.repDesc = data.description || '';
props.objData.repUrl = data.downUrl;
});
}
if (props.objData.repType === 'news') {
props.objData.content = JSON.stringify(item.content.newsItem);
}
tempObj.value[props.objData.repType] = tempObjItem;
};
const handelUpload = (response) => {
if (response.code === 0) {
const item = response.data;
selectMaterial(item, props.objData.appId);
} else {
useMessage().error('上传错误' + response.msg);
}
};
const loadVideo = (item) => {
getMaterialVideo({
mediaId: item.repMediaId,
appId: item.appId,
}).then((response) => {
const data = response.data;
window.open(data.downUrl, 'target', '');
});
};
</script>
<style scoped lang="scss">
.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;
}
.el-form-item__content {
line-height: unset !important;
}
.col-select {
border: 1px solid rgb(234, 234, 234);
padding: 50px 0px;
height: 160px;
width: 49.5%;
}
.col-select2 {
border: 1px solid rgb(234, 234, 234);
padding: 50px 0px;
height: 160px;
}
.col-add {
border: 1px solid rgb(234, 234, 234);
padding: 50px 0px;
height: 160px;
width: 49.5%;
float: right;
}
.avatar-uploader-icon {
border: 1px solid #d9d9d9;
font-size: 28px;
color: #8c939d;
width: 100px !important;
height: 100px !important;
line-height: 100px !important;
text-align: center;
}
.material-img {
width: 100%;
}
.thumb-div {
display: inline-block;
text-align: center;
}
.item-infos {
width: 30%;
margin: auto;
}
</style>