fix: 组件名称修改 css样式使用tindwind

This commit is contained in:
hw
2025-11-07 11:33:32 +08:00
parent 92a1909ad8
commit dcc543cd7f
29 changed files with 240 additions and 594 deletions

View File

@@ -4,9 +4,9 @@ VITE_PORT=5666
VITE_BASE=/ VITE_BASE=/
# 请求路径 # 请求路径
VITE_BASE_URL=http://127.0.0.1:48080 VITE_BASE_URL=http://47.103.66.220:48080
# 接口地址 # 接口地址
VITE_GLOB_API_URL=/admin-api VITE_GLOB_API_URL=http://47.103.66.220:48080/admin-api
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务 # 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=server VITE_UPLOAD_TYPE=server
# 是否打开 devtoolstrue 为打开false 为关闭 # 是否打开 devtoolstrue 为打开false 为关闭

View File

@@ -9,7 +9,7 @@ import { message } from 'ant-design-vue';
import * as MpAutoReplyApi from '#/api/mp/autoReply'; import * as MpAutoReplyApi from '#/api/mp/autoReply';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { ReplyType } from '#/views/mp/modules/wx-reply/components/types'; import { ReplyType } from '#/views/mp/modules/wx-reply/modules/types';
import ReplyForm from './ReplyForm.vue'; import ReplyForm from './ReplyForm.vue';
import { MsgType } from './types'; import { MsgType } from './types';

View File

@@ -19,7 +19,7 @@ import { getUser } from '#/api/mp/user';
import profile from '#/assets/imgs/profile.jpg'; import profile from '#/assets/imgs/profile.jpg';
import WxReplySelect, { ReplyType } from '#/views/mp/modules/wx-reply'; import WxReplySelect, { ReplyType } from '#/views/mp/modules/wx-reply';
import MsgList from './components/MsgList.vue'; import MsgList from './modules/msg-list.vue';
defineOptions({ name: 'WxMsg' }); defineOptions({ name: 'WxMsg' });
@@ -168,14 +168,21 @@ async function scrollToBottom() {
<template> <template>
<ContentWrap> <ContentWrap>
<Spin :spinning="loading"> <Spin :spinning="loading">
<div class="msg-div" ref="msgDivRef"> <div
class="ml-[10px] mr-[10px] h-[50vh] overflow-auto bg-[#eaeaea]"
ref="msgDivRef"
>
<!-- 加载更多 --> <!-- 加载更多 -->
<div v-if="!loading"> <div v-if="!loading">
<div class="empty-block" v-if="hasMore" @click="loadMore"> <div
<span class="empty-text">点击加载更多</span> class="cursor-pointer py-5 text-center"
v-if="hasMore"
@click="loadMore"
>
<span class="text-[#999]">点击加载更多</span>
</div> </div>
<div class="empty-block" v-if="!hasMore"> <div class="py-5 text-center" v-if="!hasMore">
<span class="empty-text">没有更多了</span> <span class="text-[#999]">没有更多了</span>
</div> </div>
</div> </div>
@@ -185,9 +192,9 @@ async function scrollToBottom() {
</Spin> </Spin>
<Spin :spinning="sendLoading"> <Spin :spinning="sendLoading">
<div class="msg-send"> <div class="p-[10px]">
<WxReplySelect ref="replySelectRef" v-model="reply" /> <WxReplySelect ref="replySelectRef" v-model="reply" />
<Button type="primary" class="send-but" @click="sendMsg"> <Button type="primary" class="float-right mb-2 mt-2" @click="sendMsg">
发送(S) 发送(S)
</Button> </Button>
</div> </div>
@@ -195,32 +202,4 @@ async function scrollToBottom() {
</ContentWrap> </ContentWrap>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.msg-div {
height: 50vh;
margin-right: 10px;
margin-left: 10px;
overflow: auto;
background-color: #eaeaea;
}
.msg-send {
padding: 10px;
}
.send-but {
float: right;
margin-top: 8px;
margin-bottom: 8px;
}
.empty-block {
padding: 20px;
text-align: center;
cursor: pointer;
}
.empty-text {
color: #999;
}
</style>

View File

@@ -5,7 +5,7 @@ import { formatDateTime } from '@vben/utils';
import avatarWechat from '#/assets/imgs/wechat.png'; import avatarWechat from '#/assets/imgs/wechat.png';
import Msg from './Msg.vue'; import Msg from './msg.vue';
// User 使 // User 使
type PropsUser = User; type PropsUser = User;
@@ -37,25 +37,30 @@ const getNickname = (sendFrom: SendFromType) =>
sendFrom === UserValue ? props.user.nickname : '公众号'; sendFrom === UserValue ? props.user.nickname : '公众号';
</script> </script>
<template> <template>
<div class="execution" v-for="item in props.list" :key="item.id"> <div v-for="item in props.list" :key="item.id">
<div <div
class="avue-comment" class="mb-[30px] flex items-start"
:class="{ 'avue-comment--reverse': item.sendFrom === MpBotValue }" :class="{ 'flex-row-reverse': item.sendFrom === MpBotValue }"
> >
<div class="avatar-div"> <div class="w-20 text-center">
<img :src="getAvatar(item.sendFrom)" class="avue-comment__avatar" /> <img
<div class="avue-comment__author"> :src="getAvatar(item.sendFrom)"
class="box-border h-12 w-12 rounded-full border border-transparent align-middle"
/>
<div class="text-sm font-bold text-[#999]">
{{ getNickname(item.sendFrom) }} {{ getNickname(item.sendFrom) }}
</div> </div>
</div> </div>
<div class="avue-comment__main"> <div class="relative mx-5 flex-1 rounded-[5px] border border-[#dedede]">
<div class="avue-comment__header"> <div
class="flex items-center justify-between rounded-t-[5px] border-b border-[#eee] bg-[#f8f8f8] px-[15px] py-[5px]"
>
<div class="avue-comment__create_time"> <div class="avue-comment__create_time">
{{ formatDateTime(item.createTime) }} {{ formatDateTime(item.createTime) }}
</div> </div>
</div> </div>
<div <div
class="avue-comment__body" class="overflow-hidden rounded-b-[5px] bg-white px-[15px] py-[15px] text-sm text-[#333]"
:style="item.sendFrom === MpBotValue ? 'background: #6BED72;' : ''" :style="item.sendFrom === MpBotValue ? 'background: #6BED72;' : ''"
> >
<Msg :item="item" /> <Msg :item="item" />
@@ -69,9 +74,4 @@ const getNickname = (sendFrom: SendFromType) =>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */ /* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
@import url('../comment.scss'); @import url('../comment.scss');
@import url('../card.scss'); @import url('../card.scss');
.avatar-div {
width: 80px;
text-align: center;
}
</style> </style>

View File

@@ -8,7 +8,7 @@ import WxVideoPlayer from '#/views/mp/modules/wx-video-play';
import WxVoicePlayer from '#/views/mp/modules/wx-voice-play'; import WxVoicePlayer from '#/views/mp/modules/wx-voice-play';
import { MsgType } from '../types'; import { MsgType } from '../types';
import MsgEvent from './MsgEvent.vue'; import MsgEvent from './msg-event.vue';
defineOptions({ name: 'Msg' }); defineOptions({ name: 'Msg' });
@@ -31,24 +31,29 @@ const item = ref<any>(props.item);
<div v-else-if="item.type === MsgType.Image"> <div v-else-if="item.type === MsgType.Image">
<a target="_blank" :href="item.mediaUrl"> <a target="_blank" :href="item.mediaUrl">
<img :src="item.mediaUrl" style="width: 100px" /> <img :src="item.mediaUrl" class="w-[100px]" />
</a> </a>
</div> </div>
<div <div
v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'" v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'"
style="text-align: center" class="text-center"
> >
<WxVideoPlayer :url="item.mediaUrl" /> <WxVideoPlayer :url="item.mediaUrl" />
</div> </div>
<div v-else-if="item.type === MsgType.Link" class="avue-card__detail"> <div v-else-if="item.type === MsgType.Link" class="flex-1">
<a target="_blank" :href="item.url"> <a target="_blank" :href="item.url">
<div class="avue-card__title"> <div
class="mb-3 text-base text-[rgba(0,0,0,0.85)] hover:text-[#1890ff]"
>
<Icon icon="ep:link" />{{ item.title }} <Icon icon="ep:link" />{{ item.title }}
</div> </div>
</a> </a>
<div class="avue-card__info" style="height: unset"> <div
class="h-auto overflow-hidden text-[rgba(0,0,0,0.45)]"
style="height: unset"
>
{{ item.description }} {{ item.description }}
</div> </div>
</div> </div>
@@ -61,7 +66,7 @@ const item = ref<any>(props.item);
/> />
</div> </div>
<div v-else-if="item.type === MsgType.News" style="width: 300px"> <div v-else-if="item.type === MsgType.News" class="w-[300px]">
<WxNews :articles="item.articles" /> <WxNews :articles="item.articles" />
</div> </div>

View File

@@ -1,8 +1,8 @@
export { default } from './main.vue';
export { export {
createEmptyReply, createEmptyReply,
NewsType, NewsType,
type Reply, type Reply,
ReplyType, ReplyType,
} from './components/types'; } from './modules/types';
export { default } from './main.vue';

View File

@@ -8,7 +8,7 @@
支持发送视频消息时支持新建视频 支持发送视频消息时支持新建视频
--> -->
<script lang="ts" setup> <script lang="ts" setup>
import type { Reply } from './components/types'; import type { Reply } from './modules/types';
import { computed, ref, unref, watch } from 'vue'; import { computed, ref, unref, watch } from 'vue';
@@ -16,13 +16,13 @@ import { IconifyIcon } from '@vben/icons';
import { Row, Tabs } from 'ant-design-vue'; import { Row, Tabs } from 'ant-design-vue';
import TabImage from './components/TabImage.vue'; import TabImage from './modules/tab-image.vue';
import TabMusic from './components/TabMusic.vue'; import TabMusic from './modules/tab-music.vue';
import TabNews from './components/TabNews.vue'; import TabNews from './modules/tab-news.vue';
import TabText from './components/TabText.vue'; import TabText from './modules/tab-text.vue';
import TabVideo from './components/TabVideo.vue'; import TabVideo from './modules/tab-video.vue';
import TabVoice from './components/TabVoice.vue'; import TabVoice from './modules/tab-voice.vue';
import { createEmptyReply, NewsType, ReplyType } from './components/types'; import { createEmptyReply, NewsType, ReplyType } from './modules/types';
defineOptions({ name: 'WxReplySelect' }); defineOptions({ name: 'WxReplySelect' });
@@ -137,83 +137,4 @@ defineExpose({
</Tabs> </Tabs>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
}
.select-item2 {
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
}
.ope-row {
padding-top: 10px;
text-align: center;
}
.input-margin-bottom {
margin-bottom: 2%;
}
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
}
.el-form-item__content {
line-height: unset !important;
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-select2 {
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.avatar-uploader-icon {
width: 100px !important;
height: 100px !important;
font-size: 28px;
line-height: 100px !important;
color: #8c939d;
text-align: center;
border: 1px solid #d9d9d9;
}
.material-img {
width: 100%;
}
.thumb-div {
display: inline-block;
text-align: center;
}
.item-infos {
width: 30%;
margin: auto;
}
</style>

View File

@@ -82,19 +82,30 @@ function selectMaterial(item: any) {
<template> <template>
<div> <div>
<!-- 情况一已经选择好素材或者上传好图片 --> <!-- 情况一已经选择好素材或者上传好图片 -->
<div class="select-item" v-if="reply.url"> <div
<img class="material-img" :src="reply.url" /> class="mx-auto mb-[10px] w-[280px] border border-[#eaeaea] p-[10px]"
<p class="item-name" v-if="reply.name">{{ reply.name }}</p> v-if="reply.url"
<Row class="ope-row" justify="center"> >
<img class="w-full" :src="reply.url" />
<p
class="overflow-hidden text-ellipsis whitespace-nowrap text-center text-xs"
v-if="reply.name"
>
{{ reply.name }}
</p>
<Row class="pt-[10px] text-center" justify="center">
<Button type="primary" danger shape="circle" @click="onDelete"> <Button type="primary" danger shape="circle" @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</Button> </Button>
</Row> </Row>
</div> </div>
<!-- 情况二未做完上述操作 --> <!-- 情况二未做完上述操作 -->
<Row v-else style="text-align: center" align="middle"> <Row v-else class="text-center" align="middle">
<!-- 选择素材 --> <!-- 选择素材 -->
<Col :span="12" class="col-select"> <Col
:span="12"
class="h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<Button type="primary" @click="showDialog = true"> <Button type="primary" @click="showDialog = true">
素材库选择 <IconifyIcon icon="ep:circle-check" /> 素材库选择 <IconifyIcon icon="ep:circle-check" />
</Button> </Button>
@@ -112,7 +123,10 @@ function selectMaterial(item: any) {
</Modal> </Modal>
</Col> </Col>
<!-- 文件上传 --> <!-- 文件上传 -->
<Col :span="12" class="col-add"> <Col
:span="12"
class="float-right h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<Upload <Upload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -130,7 +144,7 @@ function selectMaterial(item: any) {
<Button type="primary">上传图片</Button> <Button type="primary">上传图片</Button>
<template #tip> <template #tip>
<span> <span>
<div class="upload-tip"> <div class="text-center leading-[18px]">
支持 bmp/png/jpeg/jpg/gif 格式大小不超过 2M 支持 bmp/png/jpeg/jpg/gif 格式大小不超过 2M
</div> </div>
</span> </span>
@@ -141,53 +155,4 @@ function selectMaterial(item: any) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.material-img {
width: 100%;
}
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
.item-infos {
width: 30%;
margin: auto;
}
.ope-row {
padding-top: 10px;
text-align: center;
}
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
.upload-tip {
line-height: 18px;
text-align: center;
}
}
}
</style>

View File

@@ -85,18 +85,18 @@ function selectMaterial(item: any) {
<div> <div>
<Row align="middle" justify="center"> <Row align="middle" justify="center">
<Col :span="6"> <Col :span="6">
<Row align="middle" justify="center" class="thumb-div"> <Row align="middle" justify="center" class="inline-block text-center">
<Col :span="24"> <Col :span="24">
<Row align="middle" justify="center"> <Row align="middle" justify="center">
<img <img
style="width: 100px" class="w-[100px]"
v-if="reply.thumbMediaUrl" v-if="reply.thumbMediaUrl"
:src="reply.thumbMediaUrl" :src="reply.thumbMediaUrl"
/> />
<IconifyIcon v-else icon="ep:plus" /> <IconifyIcon v-else icon="ep:plus" />
</Row> </Row>
<Row align="middle" justify="center" style="margin-top: 2%"> <Row align="middle" justify="center" class="mt-[2%]">
<div class="thumb-but"> <div>
<Upload <Upload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -115,11 +115,7 @@ function selectMaterial(item: any) {
<Button type="link">本地上传</Button> <Button type="link">本地上传</Button>
</template> </template>
</Upload> </Upload>
<Button <Button type="link" @click="showDialog = true" class="ml-[5px]">
type="link"
@click="showDialog = true"
style="margin-left: 5px"
>
素材库选择 素材库选择
</Button> </Button>
</div> </div>
@@ -141,19 +137,19 @@ function selectMaterial(item: any) {
</Col> </Col>
<Col :span="18"> <Col :span="18">
<Input v-model:value="reply.title as string" placeholder="请输入标题" /> <Input v-model:value="reply.title as string" placeholder="请输入标题" />
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<Input <Input
v-model:value="reply.description as string" v-model:value="reply.description as string"
placeholder="请输入描述" placeholder="请输入描述"
/> />
</Col> </Col>
</Row> </Row>
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<Input <Input
v-model:value="reply.musicUrl as string" v-model:value="reply.musicUrl as string"
placeholder="请输入音乐链接" placeholder="请输入音乐链接"
/> />
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<Input <Input
v-model:value="reply.hqMusicUrl as string" v-model:value="reply.hqMusicUrl as string"
placeholder="请输入高质量音乐链接" placeholder="请输入高质量音乐链接"

View File

@@ -42,11 +42,11 @@ function onDelete() {
<div> <div>
<Row> <Row>
<div <div
class="select-item" class="mx-auto mb-[10px] w-[280px] border border-[#eaeaea] p-[10px]"
v-if="reply.articles && reply.articles.length > 0" v-if="reply.articles && reply.articles.length > 0"
> >
<WxNews :articles="reply.articles" /> <WxNews :articles="reply.articles" />
<Col class="ope-row"> <Col class="pt-[10px] text-center">
<Button type="primary" danger shape="circle" @click="onDelete"> <Button type="primary" danger shape="circle" @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</Button> </Button>
@@ -54,7 +54,7 @@ function onDelete() {
</div> </div>
<!-- 选择素材 --> <!-- 选择素材 -->
<Col :span="24" v-if="!reply.content"> <Col :span="24" v-if="!reply.content">
<Row style="text-align: center" align="middle"> <Row class="text-center" align="middle">
<Col :span="24"> <Col :span="24">
<Button type="primary" @click="showDialog = true"> <Button type="primary" @click="showDialog = true">
{{ {{
@@ -84,16 +84,4 @@ function onDelete() {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.ope-row {
padding-top: 10px;
text-align: center;
}
}
</style>

View File

@@ -26,5 +26,6 @@ const content = computed({
:rows="5" :rows="5"
placeholder="请输入内容" placeholder="请输入内容"
v-model:value="content as string" v-model:value="content as string"
class="w-full"
/> />
</template> </template>

View File

@@ -149,19 +149,19 @@ function selectMaterial(item: any) {
<Row> <Row>
<Input <Input
v-model:value="reply.title as string" v-model:value="reply.title as string"
class="input-margin-bottom" class="mb-[2%]"
placeholder="请输入标题" placeholder="请输入标题"
/> />
<Input <Input
class="input-margin-bottom" class="mb-[2%]"
v-model:value="reply.description as string" v-model:value="reply.description as string"
placeholder="请输入描述" placeholder="请输入描述"
/> />
<Row class="ope-row" justify="center"> <Row class="w-full pt-[10px] text-center" justify="center">
<WxVideoPlayer v-if="reply.url" :url="reply.url" /> <WxVideoPlayer v-if="reply.url" :url="reply.url" />
</Row> </Row>
<Col class="w-full"> <Col class="w-full">
<Row style="text-align: center" align="middle"> <Row class="text-center" align="middle">
<!-- 选择素材 --> <!-- 选择素材 -->
<Col :span="12"> <Col :span="12">
<Button type="primary" @click="showDialog = true"> <Button type="primary" @click="showDialog = true">
@@ -198,14 +198,4 @@ function selectMaterial(item: any) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.input-margin-bottom {
margin-bottom: 2%;
}
.ope-row {
width: 100%;
padding-top: 10px;
text-align: center;
}
</style>

View File

@@ -83,20 +83,30 @@ function selectMaterial(item: Reply) {
</script> </script>
<template> <template>
<div> <div>
<div class="select-item2" v-if="reply.url"> <div
<p class="item-name">{{ reply.name }}</p> class="mx-auto mb-[10px] border border-[#eaeaea] p-[10px]"
<Row class="ope-row" justify="center"> v-if="reply.url"
>
<p
class="overflow-hidden text-ellipsis whitespace-nowrap text-center text-xs"
>
{{ reply.name }}
</p>
<Row class="w-full pt-[10px] text-center" justify="center">
<WxVoicePlayer :url="reply.url" /> <WxVoicePlayer :url="reply.url" />
</Row> </Row>
<Row class="ope-row" justify="center"> <Row class="w-full pt-[10px] text-center" justify="center">
<Button type="primary" danger shape="circle" @click="onDelete"> <Button type="primary" danger shape="circle" @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</Button> </Button>
</Row> </Row>
</div> </div>
<Row v-else style="text-align: center"> <Row v-else class="text-center">
<!-- 选择素材 --> <!-- 选择素材 -->
<Col :span="12" class="col-select"> <Col
:span="12"
class="h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<Button type="primary" @click="showDialog = true"> <Button type="primary" @click="showDialog = true">
素材库选择<IconifyIcon icon="ep:circle-check" /> 素材库选择<IconifyIcon icon="ep:circle-check" />
</Button> </Button>
@@ -114,7 +124,10 @@ function selectMaterial(item: Reply) {
</Modal> </Modal>
</Col> </Col>
<!-- 文件上传 --> <!-- 文件上传 -->
<Col :span="12" class="col-add"> <Col
:span="12"
class="float-right h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<Upload <Upload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -131,7 +144,7 @@ function selectMaterial(item: Reply) {
> >
<Button type="primary">点击上传</Button> <Button type="primary">点击上传</Button>
<template #tip> <template #tip>
<div class="upload-tip"> <div class="text-center leading-[18px]">
格式支持 mp3/wma/wav/amr文件大小不超过 2M播放长度不超过 60s 格式支持 mp3/wma/wav/amr文件大小不超过 2M播放长度不超过 60s
</div> </div>
</template> </template>
@@ -141,44 +154,4 @@ function selectMaterial(item: Reply) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item2 {
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
.ope-row {
width: 100%;
padding-top: 10px;
text-align: center;
}
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
.upload-tip {
line-height: 18px;
text-align: center;
}
}
}
</style>

View File

@@ -9,7 +9,7 @@ import { ElMessage } from 'element-plus';
import * as MpAutoReplyApi from '#/api/mp/autoReply'; import * as MpAutoReplyApi from '#/api/mp/autoReply';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { ReplyType } from '#/views/mp/modules/wx-reply/components/types'; import { ReplyType } from '#/views/mp/modules/wx-reply/modules/types';
import ReplyForm from './ReplyForm.vue'; import ReplyForm from './ReplyForm.vue';
import { MsgType } from './types'; import { MsgType } from './types';

View File

@@ -19,7 +19,7 @@ import { getUser } from '#/api/mp/user';
import profile from '#/assets/imgs/profile.jpg'; import profile from '#/assets/imgs/profile.jpg';
import WxReplySelect, { ReplyType } from '#/views/mp/modules/wx-reply'; import WxReplySelect, { ReplyType } from '#/views/mp/modules/wx-reply';
import MsgList from './components/MsgList.vue'; import MsgList from './modules/msg-list.vue';
defineOptions({ name: 'WxMsg' }); defineOptions({ name: 'WxMsg' });
@@ -167,15 +167,22 @@ async function scrollToBottom() {
<template> <template>
<ContentWrap> <ContentWrap>
<div class="msg-div" ref="msgDivRef"> <div
class="ml-[10px] mr-[10px] h-[50vh] overflow-auto bg-[#eaeaea]"
ref="msgDivRef"
>
<!-- 加载更多 --> <!-- 加载更多 -->
<div v-loading="loading"></div> <div v-loading="loading"></div>
<div v-if="!loading"> <div v-if="!loading">
<div class="el-table__empty-block" v-if="hasMore" @click="loadMore"> <div
<span class="el-table__empty-text">点击加载更多</span> class="cursor-pointer py-5 text-center"
v-if="hasMore"
@click="loadMore"
>
<span class="text-[#999]">点击加载更多</span>
</div> </div>
<div class="el-table__empty-block" v-if="!hasMore"> <div class="py-5 text-center" v-if="!hasMore">
<span class="el-table__empty-text">没有更多了</span> <span class="text-[#999]">没有更多了</span>
</div> </div>
</div> </div>
@@ -183,31 +190,13 @@ async function scrollToBottom() {
<MsgList :list="list" :account-id="accountId" :user="user" /> <MsgList :list="list" :account-id="accountId" :user="user" />
</div> </div>
<div class="msg-send" v-loading="sendLoading"> <div class="p-[10px]" v-loading="sendLoading">
<WxReplySelect ref="replySelectRef" v-model="reply" /> <WxReplySelect ref="replySelectRef" v-model="reply" />
<el-button type="success" class="send-but" @click="sendMsg"> <el-button type="success" class="float-right mb-2 mt-2" @click="sendMsg">
发送(S) 发送(S)
</el-button> </el-button>
</div> </div>
</ContentWrap> </ContentWrap>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.msg-div {
height: 50vh;
margin-right: 10px;
margin-left: 10px;
overflow: auto;
background-color: #eaeaea;
}
.msg-send {
padding: 10px;
}
.send-but {
float: right;
margin-top: 8px;
margin-bottom: 8px;
}
</style>

View File

@@ -5,7 +5,7 @@ import { formatDateTime } from '@vben/utils';
import avatarWechat from '#/assets/imgs/wechat.png'; import avatarWechat from '#/assets/imgs/wechat.png';
import Msg from './Msg.vue'; import Msg from './msg.vue';
// User 使 // User 使
type PropsUser = User; type PropsUser = User;
@@ -37,25 +37,30 @@ const getNickname = (sendFrom: SendFromType) =>
sendFrom === UserValue ? props.user.nickname : '公众号'; sendFrom === UserValue ? props.user.nickname : '公众号';
</script> </script>
<template> <template>
<div class="execution" v-for="item in props.list" :key="item.id"> <div v-for="item in props.list" :key="item.id">
<div <div
class="avue-comment" class="mb-[30px] flex items-start"
:class="{ 'avue-comment--reverse': item.sendFrom === MpBotValue }" :class="{ 'flex-row-reverse': item.sendFrom === MpBotValue }"
> >
<div class="avatar-div"> <div class="w-20 text-center">
<img :src="getAvatar(item.sendFrom)" class="avue-comment__avatar" /> <img
<div class="avue-comment__author"> :src="getAvatar(item.sendFrom)"
class="box-border h-12 w-12 rounded-full border border-transparent align-middle"
/>
<div class="text-sm font-bold text-[#999]">
{{ getNickname(item.sendFrom) }} {{ getNickname(item.sendFrom) }}
</div> </div>
</div> </div>
<div class="avue-comment__main"> <div class="relative mx-5 flex-1 rounded-[5px] border border-[#dedede]">
<div class="avue-comment__header"> <div
class="flex items-center justify-between rounded-t-[5px] border-b border-[#eee] bg-[#f8f8f8] px-[15px] py-[5px]"
>
<div class="avue-comment__create_time"> <div class="avue-comment__create_time">
{{ formatDateTime(item.createTime) }} {{ formatDateTime(item.createTime) }}
</div> </div>
</div> </div>
<div <div
class="avue-comment__body" class="overflow-hidden rounded-b-[5px] bg-white px-[15px] py-[15px] text-sm text-[#333]"
:style="item.sendFrom === MpBotValue ? 'background: #6BED72;' : ''" :style="item.sendFrom === MpBotValue ? 'background: #6BED72;' : ''"
> >
<Msg :item="item" /> <Msg :item="item" />
@@ -69,9 +74,4 @@ const getNickname = (sendFrom: SendFromType) =>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */ /* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
@import url('../comment.scss'); @import url('../comment.scss');
@import url('../card.scss'); @import url('../card.scss');
.avatar-div {
width: 80px;
text-align: center;
}
</style> </style>

View File

@@ -8,7 +8,7 @@ import WxVideoPlayer from '#/views/mp/modules/wx-video-play';
import WxVoicePlayer from '#/views/mp/modules/wx-voice-play'; import WxVoicePlayer from '#/views/mp/modules/wx-voice-play';
import { MsgType } from '../types'; import { MsgType } from '../types';
import MsgEvent from './MsgEvent.vue'; import MsgEvent from './msg-event.vue';
defineOptions({ name: 'Msg' }); defineOptions({ name: 'Msg' });
@@ -31,29 +31,34 @@ const item = ref<any>(props.item);
<div v-else-if="item.type === MsgType.Image"> <div v-else-if="item.type === MsgType.Image">
<a target="_blank" :href="item.mediaUrl"> <a target="_blank" :href="item.mediaUrl">
<img :src="item.mediaUrl" style="width: 100px" /> <img :src="item.mediaUrl" class="w-[100px]" />
</a> </a>
</div> </div>
<div <div
v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'" v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'"
style="text-align: center" class="text-center"
> >
<WxVideoPlayer :url="item.mediaUrl" /> <WxVideoPlayer :url="item.mediaUrl" />
</div> </div>
<div v-else-if="item.type === MsgType.Link" class="avue-card__detail"> <div v-else-if="item.type === MsgType.Link" class="flex-1">
<el-link <el-link
type="success" type="success"
:underline="false" :underline="false"
target="_blank" target="_blank"
:href="item.url" :href="item.url"
> >
<div class="avue-card__title"> <div
class="mb-3 text-base text-[rgba(0,0,0,0.85)] hover:text-[#1890ff]"
>
<i class="el-icon-link"></i>{{ item.title }} <i class="el-icon-link"></i>{{ item.title }}
</div> </div>
</el-link> </el-link>
<div class="avue-card__info" style="height: unset"> <div
class="h-auto overflow-hidden text-[rgba(0,0,0,0.45)]"
style="height: unset"
>
{{ item.description }} {{ item.description }}
</div> </div>
</div> </div>
@@ -66,7 +71,7 @@ const item = ref<any>(props.item);
/> />
</div> </div>
<div v-else-if="item.type === MsgType.News" style="width: 300px"> <div v-else-if="item.type === MsgType.News" class="w-[300px]">
<WxNews :articles="item.articles" /> <WxNews :articles="item.articles" />
</div> </div>

View File

@@ -1,8 +1,8 @@
export { default } from './main.vue';
export { export {
createEmptyReply, createEmptyReply,
NewsType, NewsType,
type Reply, type Reply,
ReplyType, ReplyType,
} from './components/types'; } from './modules/types';
export { default } from './main.vue';

View File

@@ -8,7 +8,7 @@
支持发送视频消息时支持新建视频 支持发送视频消息时支持新建视频
--> -->
<script lang="ts" setup> <script lang="ts" setup>
import type { Reply } from './components/types'; import type { Reply } from './modules/types';
import { computed, ref, unref, watch } from 'vue'; import { computed, ref, unref, watch } from 'vue';
@@ -16,13 +16,13 @@ import { IconifyIcon } from '@vben/icons';
import { ElRow, ElTabPane, ElTabs } from 'element-plus'; import { ElRow, ElTabPane, ElTabs } from 'element-plus';
import TabImage from './components/TabImage.vue'; import TabImage from './modules/tab-image.vue';
import TabMusic from './components/TabMusic.vue'; import TabMusic from './modules/tab-music.vue';
import TabNews from './components/TabNews.vue'; import TabNews from './modules/tab-news.vue';
import TabText from './components/TabText.vue'; import TabText from './modules/tab-text.vue';
import TabVideo from './components/TabVideo.vue'; import TabVideo from './modules/tab-video.vue';
import TabVoice from './components/TabVoice.vue'; import TabVoice from './modules/tab-voice.vue';
import { createEmptyReply, NewsType, ReplyType } from './components/types'; import { createEmptyReply, NewsType, ReplyType } from './modules/types';
defineOptions({ name: 'WxReplySelect' }); defineOptions({ name: 'WxReplySelect' });
@@ -137,83 +137,4 @@ defineExpose({
</ElTabs> </ElTabs>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
}
.select-item2 {
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
}
.ope-row {
padding-top: 10px;
text-align: center;
}
.input-margin-bottom {
margin-bottom: 2%;
}
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
}
.el-form-item__content {
line-height: unset !important;
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-select2 {
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.avatar-uploader-icon {
width: 100px !important;
height: 100px !important;
font-size: 28px;
line-height: 100px !important;
color: #8c939d;
text-align: center;
border: 1px solid #d9d9d9;
}
.material-img {
width: 100%;
}
.thumb-div {
display: inline-block;
text-align: center;
}
.item-infos {
width: 30%;
margin: auto;
}
</style>

View File

@@ -88,19 +88,30 @@ function selectMaterial(item: any) {
<template> <template>
<div> <div>
<!-- 情况一已经选择好素材或者上传好图片 --> <!-- 情况一已经选择好素材或者上传好图片 -->
<div class="select-item" v-if="reply.url"> <div
<img class="material-img" :src="reply.url" /> class="mx-auto mb-[10px] w-[280px] border border-[#eaeaea] p-[10px]"
<p class="item-name" v-if="reply.name">{{ reply.name }}</p> v-if="reply.url"
<ElRow class="ope-row" justify="center"> >
<img class="w-full" :src="reply.url" />
<p
class="overflow-hidden text-ellipsis whitespace-nowrap text-center text-xs"
v-if="reply.name"
>
{{ reply.name }}
</p>
<ElRow class="pt-[10px] text-center" justify="center">
<ElButton type="danger" circle @click="onDelete"> <ElButton type="danger" circle @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</ElButton> </ElButton>
</ElRow> </ElRow>
</div> </div>
<!-- 情况二未做完上述操作 --> <!-- 情况二未做完上述操作 -->
<ElRow v-else style="text-align: center" align="middle"> <ElRow v-else class="text-center" align="middle">
<!-- 选择素材 --> <!-- 选择素材 -->
<ElCol :span="12" class="col-select"> <ElCol
:span="12"
class="h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<ElButton type="success" @click="showDialog = true"> <ElButton type="success" @click="showDialog = true">
素材库选择 <IconifyIcon icon="ep:circle-check" /> 素材库选择 <IconifyIcon icon="ep:circle-check" />
</ElButton> </ElButton>
@@ -119,7 +130,10 @@ function selectMaterial(item: any) {
</ElDialog> </ElDialog>
</ElCol> </ElCol>
<!-- 文件上传 --> <!-- 文件上传 -->
<ElCol :span="12" class="col-add"> <ElCol
:span="12"
class="float-right h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<ElUpload <ElUpload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -133,7 +147,7 @@ function selectMaterial(item: any) {
<ElButton type="primary">上传图片</ElButton> <ElButton type="primary">上传图片</ElButton>
<template #tip> <template #tip>
<span> <span>
<div class="el-upload__tip"> <div class="text-center leading-[18px]">
支持 bmp/png/jpeg/jpg/gif 格式大小不超过 2M 支持 bmp/png/jpeg/jpg/gif 格式大小不超过 2M
</div> </div>
</span> </span>
@@ -144,53 +158,4 @@ function selectMaterial(item: any) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.material-img {
width: 100%;
}
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
.item-infos {
width: 30%;
margin: auto;
}
.ope-row {
padding-top: 10px;
text-align: center;
}
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
.el-upload__tip {
line-height: 18px;
text-align: center;
}
}
}
</style>

View File

@@ -84,18 +84,18 @@ function selectMaterial(item: any) {
<div> <div>
<ElRow align="middle" justify="center"> <ElRow align="middle" justify="center">
<ElCol :span="6"> <ElCol :span="6">
<ElRow align="middle" justify="center" class="thumb-div"> <ElRow align="middle" justify="center" class="inline-block text-center">
<ElCol :span="24"> <ElCol :span="24">
<ElRow align="middle" justify="center"> <ElRow align="middle" justify="center">
<img <img
style="width: 100px" class="w-[100px]"
v-if="reply.thumbMediaUrl" v-if="reply.thumbMediaUrl"
:src="reply.thumbMediaUrl" :src="reply.thumbMediaUrl"
/> />
<IconifyIcon v-else icon="ep:plus" /> <IconifyIcon v-else icon="ep:plus" />
</ElRow> </ElRow>
<ElRow align="middle" justify="center" style="margin-top: 2%"> <ElRow align="middle" justify="center" class="mt-[2%]">
<div class="thumb-but"> <div>
<ElUpload <ElUpload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -113,7 +113,7 @@ function selectMaterial(item: any) {
type="primary" type="primary"
link link
@click="showDialog = true" @click="showDialog = true"
style="margin-left: 5px" class="ml-[5px]"
> >
素材库选择 素材库选择
</ElButton> </ElButton>
@@ -138,13 +138,13 @@ function selectMaterial(item: any) {
</ElCol> </ElCol>
<ElCol :span="18"> <ElCol :span="18">
<ElInput v-model="reply.title" placeholder="请输入标题" /> <ElInput v-model="reply.title" placeholder="请输入标题" />
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<ElInput v-model="reply.description" placeholder="请输入描述" /> <ElInput v-model="reply.description" placeholder="请输入描述" />
</ElCol> </ElCol>
</ElRow> </ElRow>
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<ElInput v-model="reply.musicUrl" placeholder="请输入音乐链接" /> <ElInput v-model="reply.musicUrl" placeholder="请输入音乐链接" />
<div style="margin: 20px 0"></div> <div class="my-5"></div>
<ElInput v-model="reply.hqMusicUrl" placeholder="请输入高质量音乐链接" /> <ElInput v-model="reply.hqMusicUrl" placeholder="请输入高质量音乐链接" />
</div> </div>
</template> </template>

View File

@@ -42,11 +42,11 @@ function onDelete() {
<div> <div>
<ElRow> <ElRow>
<div <div
class="select-item" class="mx-auto mb-[10px] w-[280px] border border-[#eaeaea] p-[10px]"
v-if="reply.articles && reply.articles.length > 0" v-if="reply.articles && reply.articles.length > 0"
> >
<WxNews :articles="reply.articles" /> <WxNews :articles="reply.articles" />
<ElCol class="ope-row"> <ElCol class="pt-[10px] text-center">
<ElButton type="danger" circle @click="onDelete"> <ElButton type="danger" circle @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</ElButton> </ElButton>
@@ -54,7 +54,7 @@ function onDelete() {
</div> </div>
<!-- 选择素材 --> <!-- 选择素材 -->
<ElCol :span="24" v-if="!reply.content"> <ElCol :span="24" v-if="!reply.content">
<ElRow style="text-align: center" align="middle"> <ElRow class="text-center" align="middle">
<ElCol :span="24"> <ElCol :span="24">
<ElButton type="success" @click="showDialog = true"> <ElButton type="success" @click="showDialog = true">
{{ {{
@@ -85,16 +85,4 @@ function onDelete() {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item {
width: 280px;
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.ope-row {
padding-top: 10px;
text-align: center;
}
}
</style>

View File

@@ -27,5 +27,6 @@ const content = computed({
:rows="5" :rows="5"
placeholder="请输入内容" placeholder="请输入内容"
v-model="content" v-model="content"
class="w-full"
/> />
</template> </template>

View File

@@ -90,21 +90,17 @@ function selectMaterial(item: any) {
<template> <template>
<div> <div>
<ElRow> <ElRow>
<ElInput v-model="reply.title" class="mb-[2%]" placeholder="请输入标题" />
<ElInput <ElInput
v-model="reply.title" class="mb-[2%]"
class="input-margin-bottom"
placeholder="请输入标题"
/>
<ElInput
class="input-margin-bottom"
v-model="reply.description" v-model="reply.description"
placeholder="请输入描述" placeholder="请输入描述"
/> />
<ElRow class="ope-row" justify="center"> <ElRow class="w-full pt-[10px] text-center" justify="center">
<WxVideoPlayer v-if="reply.url" :url="reply.url" /> <WxVideoPlayer v-if="reply.url" :url="reply.url" />
</ElRow> </ElRow>
<ElCol> <ElCol>
<ElRow style="text-align: center" align="middle"> <ElRow class="text-center" align="middle">
<!-- 选择素材 --> <!-- 选择素材 -->
<ElCol :span="12"> <ElCol :span="12">
<ElButton type="success" @click="showDialog = true"> <ElButton type="success" @click="showDialog = true">
@@ -147,14 +143,4 @@ function selectMaterial(item: any) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.input-margin-bottom {
margin-bottom: 2%;
}
.ope-row {
width: 100%;
padding-top: 10px;
text-align: center;
}
</style>

View File

@@ -89,20 +89,30 @@ function selectMaterial(item: Reply) {
</script> </script>
<template> <template>
<div> <div>
<div class="select-item2" v-if="reply.url"> <div
<p class="item-name">{{ reply.name }}</p> class="mx-auto mb-[10px] border border-[#eaeaea] p-[10px]"
<ElRow class="ope-row" justify="center"> v-if="reply.url"
>
<p
class="overflow-hidden text-ellipsis whitespace-nowrap text-center text-xs"
>
{{ reply.name }}
</p>
<ElRow class="w-full pt-[10px] text-center" justify="center">
<WxVoicePlayer :url="reply.url" /> <WxVoicePlayer :url="reply.url" />
</ElRow> </ElRow>
<ElRow class="ope-row" justify="center"> <ElRow class="w-full pt-[10px] text-center" justify="center">
<ElButton type="danger" circle @click="onDelete"> <ElButton type="danger" circle @click="onDelete">
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="ep:delete" />
</ElButton> </ElButton>
</ElRow> </ElRow>
</div> </div>
<ElRow v-else style="text-align: center"> <ElRow v-else class="text-center">
<!-- 选择素材 --> <!-- 选择素材 -->
<ElCol :span="12" class="col-select"> <ElCol
:span="12"
class="h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<ElButton type="success" @click="showDialog = true"> <ElButton type="success" @click="showDialog = true">
素材库选择<IconifyIcon icon="ep:circle-check" /> 素材库选择<IconifyIcon icon="ep:circle-check" />
</ElButton> </ElButton>
@@ -121,7 +131,10 @@ function selectMaterial(item: Reply) {
</ElDialog> </ElDialog>
</ElCol> </ElCol>
<!-- 文件上传 --> <!-- 文件上传 -->
<ElCol :span="12" class="col-add"> <ElCol
:span="12"
class="float-right h-[160px] w-[49.5%] border border-[rgb(234,234,234)] py-[50px]"
>
<ElUpload <ElUpload
:action="UPLOAD_URL" :action="UPLOAD_URL"
:headers="HEADERS" :headers="HEADERS"
@@ -134,7 +147,7 @@ function selectMaterial(item: Reply) {
> >
<ElButton type="primary">点击上传</ElButton> <ElButton type="primary">点击上传</ElButton>
<template #tip> <template #tip>
<div class="el-upload__tip"> <div class="text-center leading-[18px]">
格式支持 mp3/wma/wav/amr文件大小不超过 2M播放长度不超过 60s 格式支持 mp3/wma/wav/amr文件大小不超过 2M播放长度不超过 60s
</div> </div>
</template> </template>
@@ -144,44 +157,4 @@ function selectMaterial(item: Reply) {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.select-item2 {
padding: 10px;
margin: 0 auto 10px;
border: 1px solid #eaeaea;
.item-name {
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
text-align: center;
white-space: nowrap;
.ope-row {
width: 100%;
padding-top: 10px;
text-align: center;
}
}
.col-select {
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
}
.col-add {
float: right;
width: 49.5%;
height: 160px;
padding: 50px 0;
border: 1px solid rgb(234 234 234);
.el-upload__tip {
line-height: 18px;
text-align: center;
}
}
}
</style>