853 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			853 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | |
|   <s-layout class="chat-wrap" title="客服" navbar="inner">
 | |
|     <div class="status">
 | |
|       {{ socketState.isConnect ? customerServiceInfo.title : '网络已断开,请检查网络后刷新重试' }}
 | |
|     </div>
 | |
|     <div class="page-bg" :style="{ height: sys_navBar + 'px' }"></div>
 | |
|     <view class="chat-box" :style="{ height: pageHeight + 'px' }">
 | |
|       <scroll-view
 | |
|         :style="{ height: pageHeight + 'px' }"
 | |
|         scroll-y="true"
 | |
|         :scroll-with-animation="false"
 | |
|         :enable-back-to-top="true"
 | |
|         :scroll-into-view="chat.scrollInto"
 | |
|       >
 | |
|         <button
 | |
|           class="loadmore-btn ss-reset-button"
 | |
|           v-if="
 | |
|             chatList.length &&
 | |
|             chatHistoryPagination.lastPage > 1 &&
 | |
|             loadingMap[chatHistoryPagination.loadStatus].title
 | |
|           "
 | |
|           @click="onLoadMore"
 | |
|         >
 | |
|           {{ loadingMap[chatHistoryPagination.loadStatus].title }}
 | |
|           <i
 | |
|             class="loadmore-icon sa-m-l-6"
 | |
|             :class="loadingMap[chatHistoryPagination.loadStatus].icon"
 | |
|           ></i>
 | |
|         </button>
 | |
|         <view class="message-item ss-flex-col" v-for="(item, index) in chatList" :key="index">
 | |
|           <view class="ss-flex ss-row-center ss-col-center">
 | |
|             <!-- 日期 -->
 | |
|             <view v-if="item.from !== 'system' && showTime(item, index)" class="date-message">
 | |
|               {{ formatTime(item.date) }}
 | |
|             </view>
 | |
|             <!-- 系统消息 -->
 | |
|             <view v-if="item.from === 'system'" class="system-message">
 | |
|               {{ item.content.text }}
 | |
|             </view>
 | |
|           </view>
 | |
|           <!-- 常见问题 -->
 | |
|           <view v-if="item.mode === 'template' && item.content.list.length" class="template-wrap">
 | |
|             <view class="title">猜你想问</view>
 | |
|             <view
 | |
|               class="item"
 | |
|               v-for="(item, index) in item.content.list"
 | |
|               :key="index"
 | |
|               @click="onTemplateList(item)"
 | |
|             >
 | |
|               * {{ item.title }}
 | |
|             </view>
 | |
|           </view>
 | |
| 
 | |
|           <view
 | |
|             v-if="
 | |
|               (item.from === 'customer_service' && item.mode !== 'template') ||
 | |
|               item.from === 'customer'
 | |
|             "
 | |
|             class="ss-flex ss-col-top"
 | |
|             :class="[
 | |
|               item.from === 'customer_service'
 | |
|                 ? `ss-row-left`
 | |
|                 : item.from === 'customer'
 | |
|                 ? `ss-row-right`
 | |
|                 : '',
 | |
|             ]"
 | |
|           >
 | |
|             <!-- 客服头像 -->
 | |
|             <image
 | |
|               v-show="item.from === 'customer_service'"
 | |
|               class="chat-avatar ss-m-r-24"
 | |
|               :src="
 | |
|                 sheep.$url.cdn(item?.sender?.avatar) ||
 | |
|                 sheep.$url.static('/static/img/shop/chat/default.png')
 | |
|               "
 | |
|               mode="aspectFill"
 | |
|             ></image>
 | |
| 
 | |
|             <!-- 发送状态 -->
 | |
|             <span
 | |
|               v-if="
 | |
|                 item.from === 'customer' &&
 | |
|                 index == chatData.chatList.length - 1 &&
 | |
|                 chatData.isSendSucces !== 0
 | |
|               "
 | |
|               class="send-status"
 | |
|             >
 | |
|               <image
 | |
|                 v-if="chatData.isSendSucces == -1"
 | |
|                 class="loading"
 | |
|                 :src="sheep.$url.static('/static/img/shop/chat/loading.png')"
 | |
|                 mode="aspectFill"
 | |
|               ></image>
 | |
|               <!-- <image
 | |
|                 v-if="chatData.isSendSucces == 1"
 | |
|                 class="warning"
 | |
|                 :src="sheep.$url.static('/static/img/shop/chat/warning.png')"
 | |
|                 mode="aspectFill"
 | |
|                 @click="onAgainSendMessage(item)"
 | |
|               ></image> -->
 | |
|             </span>
 | |
| 
 | |
|             <!-- 内容 -->
 | |
|             <template v-if="item.mode === 'text'">
 | |
|               <view class="message-box" :class="[item.from]">
 | |
|                 <div
 | |
|                   class="message-text ss-flex"
 | |
|                   @click="onRichtext"
 | |
|                   v-html="replaceEmoji(item.content.text)"
 | |
|                 ></div>
 | |
|               </view>
 | |
|             </template>
 | |
|             <template v-if="item.mode === 'image'">
 | |
|               <view class="message-box" :class="[item.from]" :style="{ width: '200rpx' }">
 | |
|                 <su-image
 | |
|                   class="message-img"
 | |
|                   isPreview
 | |
|                   :previewList="[sheep.$url.cdn(item.content.url)]"
 | |
|                   :current="0"
 | |
|                   :src="sheep.$url.cdn(item.content.url)"
 | |
|                   :height="200"
 | |
|                   :width="200"
 | |
|                   mode="scaleToFill"
 | |
|                 ></su-image>
 | |
|               </view>
 | |
|             </template>
 | |
|             <template v-if="item.mode === 'goods'">
 | |
|               <GoodsItem
 | |
|                 :goodsData="item.content.item"
 | |
|                 @tap="
 | |
|                   sheep.$router.go('/pages/goods/index', {
 | |
|                     id: item.content.item.id,
 | |
|                   })
 | |
|                 "
 | |
|               />
 | |
|             </template>
 | |
|             <template v-if="item.mode === 'order'">
 | |
|               <OrderItem
 | |
|                 from="msg"
 | |
|                 :orderData="item.content.item"
 | |
|                 @tap="
 | |
|                   sheep.$router.go('/pages/order/detail', {
 | |
|                     id: item.content.item.id,
 | |
|                   })
 | |
|                 "
 | |
|               />
 | |
|             </template>
 | |
|             <!-- user头像 -->
 | |
|             <image
 | |
|               v-show="item.from === 'customer'"
 | |
|               class="chat-avatar ss-m-l-24"
 | |
|               :src="sheep.$url.cdn(customerUserInfo.avatar)"
 | |
|               mode="aspectFill"
 | |
|             >
 | |
|             </image>
 | |
|           </view>
 | |
|         </view>
 | |
|         <view id="scrollBottom"></view>
 | |
|       </scroll-view>
 | |
|     </view>
 | |
|     <su-fixed bottom>
 | |
|       <view class="send-wrap ss-flex">
 | |
|         <view class="left ss-flex ss-flex-1">
 | |
|           <uni-easyinput
 | |
|             class="ss-flex-1 ss-p-l-22"
 | |
|             :inputBorder="false"
 | |
|             :clearable="false"
 | |
|             v-model="chat.msg"
 | |
|             placeholder="请输入你要咨询的问题"
 | |
|           ></uni-easyinput>
 | |
|         </view>
 | |
|         <text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
 | |
|         <text
 | |
|           v-if="!chat.msg"
 | |
|           class="sicon-edit"
 | |
|           :class="{ 'is-active': chat.toolsMode == 'tools' }"
 | |
|           @tap.stop="onTools('tools')"
 | |
|         ></text>
 | |
|         <button v-if="chat.msg" class="ss-reset-button send-btn" @tap="onSendMessage">
 | |
|           发送
 | |
|         </button>
 | |
|       </view>
 | |
|     </su-fixed>
 | |
|     <su-popup
 | |
|       :show="chat.showTools"
 | |
|       @close="
 | |
|         chat.showTools = false;
 | |
|         chat.toolsMode = '';
 | |
|       "
 | |
|     >
 | |
|       <view class="ss-modal-box ss-flex-col">
 | |
|         <view class="send-wrap ss-flex">
 | |
|           <view class="left ss-flex ss-flex-1">
 | |
|             <uni-easyinput
 | |
|               class="ss-flex-1 ss-p-l-22"
 | |
|               :inputBorder="false"
 | |
|               :clearable="false"
 | |
|               v-model="chat.msg"
 | |
|               placeholder="请输入你要咨询的问题"
 | |
|             ></uni-easyinput>
 | |
|           </view>
 | |
|           <text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
 | |
|           <text></text>
 | |
|           <text
 | |
|             v-if="!chat.msg"
 | |
|             class="sicon-edit"
 | |
|             :class="{ 'is-active': chat.toolsMode == 'tools' }"
 | |
|             @tap.stop="onTools('tools')"
 | |
|           ></text>
 | |
|           <button v-if="chat.msg" class="ss-reset-button send-btn" @tap="onSendMessage">
 | |
|             发送
 | |
|           </button>
 | |
|         </view>
 | |
|         <view class="content ss-flex ss-flex-1">
 | |
|           <template v-if="chat.toolsMode == 'emoji'">
 | |
|             <swiper
 | |
|               class="emoji-swiper"
 | |
|               :indicator-dots="true"
 | |
|               circular
 | |
|               indicator-active-color="#7063D2"
 | |
|               indicator-color="rgba(235, 231, 255, 1)"
 | |
|               :autoplay="false"
 | |
|               :interval="3000"
 | |
|               :duration="1000"
 | |
|             >
 | |
|               <swiper-item v-for="emoji in emojiPage" :key="emoji">
 | |
|                 <view class="ss-flex ss-flex-wrap">
 | |
|                   <template v-for="item in emoji" :key="item">
 | |
|                     <image
 | |
|                       class="emoji-img"
 | |
|                       :src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)"
 | |
|                       @tap="onEmoji(item)"
 | |
|                     >
 | |
|                     </image>
 | |
|                   </template>
 | |
|                 </view>
 | |
|               </swiper-item>
 | |
|             </swiper>
 | |
|           </template>
 | |
|           <template v-else>
 | |
|             <view class="image">
 | |
|               <s-uploader
 | |
|                 file-mediatype="image"
 | |
|                 :imageStyles="{ width: 50, height: 50, border: false }"
 | |
|                 @select="onSelect({ type: 'image', data: $event })"
 | |
|               >
 | |
|                 <image
 | |
|                   class="icon"
 | |
|                   :src="sheep.$url.static('/static/img/shop/chat/image.png')"
 | |
|                   mode="aspectFill"
 | |
|                 ></image>
 | |
|               </s-uploader>
 | |
|               <view>图片</view>
 | |
|             </view>
 | |
|             <view class="goods" @tap="onShowSelect('goods')">
 | |
|               <image
 | |
|                 class="icon"
 | |
|                 :src="sheep.$url.static('/static/img/shop/chat/goods.png')"
 | |
|                 mode="aspectFill"
 | |
|               ></image>
 | |
|               <view>商品</view>
 | |
|             </view>
 | |
|             <view class="order" @tap="onShowSelect('order')">
 | |
|               <image
 | |
|                 class="icon"
 | |
|                 :src="sheep.$url.static('/static/img/shop/chat/order.png')"
 | |
|                 mode="aspectFill"
 | |
|               ></image>
 | |
|               <view>订单</view>
 | |
|             </view>
 | |
|           </template>
 | |
|         </view>
 | |
|       </view>
 | |
|     </su-popup>
 | |
| 
 | |
|     <SelectPopup
 | |
|       :mode="chat.selectMode"
 | |
|       :show="chat.showSelect"
 | |
|       @select="onSelect"
 | |
|       @close="chat.showSelect = false"
 | |
|     />
 | |
|   </s-layout>
 | |
| </template>
 | |
| 
 | |
| <script setup>
 | |
|   import sheep from '@/sheep';
 | |
|   import { computed, reactive, toRefs } from 'vue';
 | |
|   import { onLoad } from '@dcloudio/uni-app';
 | |
|   import { emojiList, emojiPage } from './emoji.js';
 | |
|   import SelectPopup from './components/select-popup.vue';
 | |
|   import GoodsItem from './components/goods.vue';
 | |
|   import OrderItem from './components/order.vue';
 | |
|   import { useChatWebSocket } from './socket';
 | |
| 
 | |
|   const {
 | |
|     socketInit,
 | |
|     state: chatData,
 | |
|     socketSendMsg,
 | |
|     formatChatInput,
 | |
|     socketHistoryList,
 | |
|     onDrop,
 | |
|     onPaste,
 | |
|     getFocus,
 | |
|     // upload,
 | |
|     getUserToken,
 | |
|     // socketTest,
 | |
|     showTime,
 | |
|     formatTime,
 | |
|   } = useChatWebSocket();
 | |
|   const chatList = toRefs(chatData).chatList;
 | |
|   const customerServiceInfo = toRefs(chatData).customerServerInfo;
 | |
|   const chatHistoryPagination = toRefs(chatData).chatHistoryPagination;
 | |
|   const customerUserInfo = toRefs(chatData).customerUserInfo;
 | |
|   const socketState = toRefs(chatData).socketState;
 | |
| 
 | |
|   const sys_navBar = sheep.$platform.navbar;
 | |
|   const chatConfig = computed(() => sheep.$store('app').chat);
 | |
| 
 | |
|   const { screenHeight, safeAreaInsets, safeArea, screenWidth } = sheep.$platform.device;
 | |
|   const pageHeight = safeArea.height - 44 - 35 - 50;
 | |
| 
 | |
|   const chatStatus = {
 | |
|     online: {
 | |
|       text: '在线',
 | |
|       colorVariate: '#46c55f',
 | |
|     },
 | |
|     offline: {
 | |
|       text: '离线',
 | |
|       colorVariate: '#b5b5b5',
 | |
|     },
 | |
|     busy: {
 | |
|       text: '忙碌',
 | |
|       colorVariate: '#ff0e1b',
 | |
|     },
 | |
|   };
 | |
| 
 | |
|   // 加载更多
 | |
|   const loadingMap = {
 | |
|     loadmore: {
 | |
|       title: '查看更多',
 | |
|       icon: 'el-icon-d-arrow-left',
 | |
|     },
 | |
|     nomore: {
 | |
|       title: '没有更多了',
 | |
|       icon: '',
 | |
|     },
 | |
|     loading: {
 | |
|       title: '加载中... ',
 | |
|       icon: 'el-icon-loading',
 | |
|     },
 | |
|   };
 | |
|   const onLoadMore = () => {
 | |
|     chatHistoryPagination.value.page < chatHistoryPagination.value.lastPage && socketHistoryList();
 | |
|   };
 | |
| 
 | |
|   const chat = reactive({
 | |
|     msg: '',
 | |
|     scrollInto: '',
 | |
| 
 | |
|     showTools: false,
 | |
|     toolsMode: '',
 | |
| 
 | |
|     showSelect: false,
 | |
|     selectMode: '',
 | |
|     chatStyle: {
 | |
|       mode: 'inner',
 | |
|       color: '#F8270F',
 | |
|       type: 'color',
 | |
|       alwaysShow: 1,
 | |
|       src: '',
 | |
|       list: {},
 | |
|     },
 | |
|   });
 | |
| 
 | |
|   // 点击工具栏开关
 | |
|   function onTools(mode) {
 | |
|     if (!socketState.value.isConnect) {
 | |
|       sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (!chat.toolsMode || chat.toolsMode === mode) {
 | |
|       chat.showTools = !chat.showTools;
 | |
|     }
 | |
|     chat.toolsMode = mode;
 | |
|     if (!chat.showTools) {
 | |
|       chat.toolsMode = '';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function onShowSelect(mode) {
 | |
|     chat.showTools = false;
 | |
|     chat.showSelect = true;
 | |
|     chat.selectMode = mode;
 | |
|   }
 | |
| 
 | |
|   async function onSelect({ type, data }) {
 | |
|     let msg = '';
 | |
|     switch (type) {
 | |
|       case 'image':
 | |
|         const { path, fullurl } = await sheep.$api.app.upload(data.tempFiles[0].path, 'default');
 | |
|         msg = {
 | |
|           from: 'customer',
 | |
|           mode: 'image',
 | |
|           date: new Date().getTime(),
 | |
|           content: {
 | |
|             url: fullurl,
 | |
|             path: path,
 | |
|           },
 | |
|         };
 | |
|         break;
 | |
|       case 'goods':
 | |
|         msg = {
 | |
|           from: 'customer',
 | |
|           mode: 'goods',
 | |
|           date: new Date().getTime(),
 | |
|           content: {
 | |
|             item: {
 | |
|               id: data.goods.id,
 | |
|               title: data.goods.title,
 | |
|               image: data.goods.image,
 | |
|               price: data.goods.price,
 | |
|               stock: data.goods.stock,
 | |
|             },
 | |
|           },
 | |
|         };
 | |
|         break;
 | |
|       case 'order':
 | |
|         msg = {
 | |
|           from: 'customer',
 | |
|           mode: 'order',
 | |
|           date: new Date().getTime(),
 | |
|           content: {
 | |
|             item: {
 | |
|               id: data.id,
 | |
|               order_sn: data.order_sn,
 | |
|               create_time: data.create_time,
 | |
|               pay_fee: data.pay_fee,
 | |
|               items: data.items.filter((item) => ({
 | |
|                 goods_id: item.goods_id,
 | |
|                 goods_title: item.goods_title,
 | |
|                 goods_image: item.goods_image,
 | |
|                 goods_price: item.goods_price,
 | |
|               })),
 | |
|               status_text: data.status_text,
 | |
|             },
 | |
|           },
 | |
|         };
 | |
|         break;
 | |
|     }
 | |
|     if (msg) {
 | |
|       socketSendMsg(msg, () => {
 | |
|         scrollBottom();
 | |
|       });
 | |
|       // scrollBottom();
 | |
|       chat.showTools = false;
 | |
|       chat.showSelect = false;
 | |
|       chat.selectMode = '';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function onAgainSendMessage(item) {
 | |
|     if (!socketState.value.isConnect) {
 | |
|       sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
 | |
|       return;
 | |
|     }
 | |
|     if (!item) return;
 | |
|     const data = {
 | |
|       from: 'customer',
 | |
|       mode: 'text',
 | |
|       date: new Date().getTime(),
 | |
|       content: item.content,
 | |
|     };
 | |
|     socketSendMsg(data, () => {
 | |
|       scrollBottom();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   function onSendMessage() {
 | |
|     if (!socketState.value.isConnect) {
 | |
|       sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
 | |
|       return;
 | |
|     }
 | |
|     if (!chat.msg) return;
 | |
|     const data = {
 | |
|       from: 'customer',
 | |
|       mode: 'text',
 | |
|       date: new Date().getTime(),
 | |
|       content: {
 | |
|         text: chat.msg,
 | |
|       },
 | |
|     };
 | |
|     socketSendMsg(data, () => {
 | |
|       scrollBottom();
 | |
|     });
 | |
|     chat.showTools = false;
 | |
|     // scrollBottom();
 | |
|     chat.msg = '';
 | |
|   }
 | |
| 
 | |
|   // 点击猜你想问
 | |
|   function onTemplateList(e) {
 | |
|     if (!socketState.value.isConnect) {
 | |
|       sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
 | |
|       return;
 | |
|     }
 | |
|     const data = {
 | |
|       from: 'customer',
 | |
|       mode: 'text',
 | |
|       date: new Date().getTime(),
 | |
|       content: {
 | |
|         text: e.title,
 | |
|       },
 | |
|       customData: {
 | |
|         question_id: e.id,
 | |
|       },
 | |
|     };
 | |
|     socketSendMsg(data, () => {
 | |
|       scrollBottom();
 | |
|     });
 | |
|     // scrollBottom();
 | |
|   }
 | |
| 
 | |
|   function onEmoji(item) {
 | |
|     chat.msg += item.name;
 | |
|   }
 | |
| 
 | |
|   function selEmojiFile(name) {
 | |
|     for (let index in emojiList) {
 | |
|       if (emojiList[index].name === name) {
 | |
|         return emojiList[index].file;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   function replaceEmoji(data) {
 | |
|     let newData = data;
 | |
|     if (typeof newData !== 'object') {
 | |
|       let reg = /\[(.+?)\]/g; // [] 中括号
 | |
|       let zhEmojiName = newData.match(reg);
 | |
|       if (zhEmojiName) {
 | |
|         zhEmojiName.forEach((item) => {
 | |
|           let emojiFile = selEmojiFile(item);
 | |
|           newData = newData.replace(
 | |
|             item,
 | |
|             `<img class="chat-img" style="width:25px;height:25px;margin:0 3px" src="${sheep.$url.cdn(
 | |
|               '/static/img/chat/emoji/' + emojiFile,
 | |
|             )}"/>`,
 | |
|           );
 | |
|         });
 | |
|       }
 | |
|     }
 | |
|     return newData;
 | |
|   }
 | |
| 
 | |
|   function scrollBottom() {
 | |
|     let timeout = null;
 | |
|     chat.scrollInto = '';
 | |
|     clearTimeout(timeout);
 | |
|     timeout = setTimeout(() => {
 | |
|       chat.scrollInto = 'scrollBottom';
 | |
|     }, 100);
 | |
|   }
 | |
| 
 | |
|   onLoad(async () => {
 | |
|     const { error } = await getUserToken();
 | |
|     if (error === 0) {
 | |
|       socketInit(chatConfig.value, () => {
 | |
|         scrollBottom();
 | |
|       });
 | |
|     } else {
 | |
|       socketState.value.isConnect = false;
 | |
|     }
 | |
|   });
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
|   .page-bg {
 | |
|     width: 100%;
 | |
|     position: absolute;
 | |
|     top: 0;
 | |
|     left: 0;
 | |
|     background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
 | |
|     background-size: 750rpx 100%;
 | |
|     z-index: 1;
 | |
|   }
 | |
|   .chat-wrap {
 | |
|     // :deep() {
 | |
|     //   .ui-navbar-box {
 | |
|     //     background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
 | |
|     //   }
 | |
|     // }
 | |
| 
 | |
|     .status {
 | |
|       position: relative;
 | |
|       box-sizing: border-box;
 | |
|       z-index: 3;
 | |
|       height: 70rpx;
 | |
|       padding: 0 30rpx;
 | |
|       background: var(--ui-BG-Main-opacity-1);
 | |
|       display: flex;
 | |
|       align-items: center;
 | |
|       font-size: 30rpx;
 | |
|       font-weight: 400;
 | |
|       color: var(--ui-BG-Main);
 | |
|     }
 | |
| 
 | |
|     .chat-box {
 | |
|       padding: 0 20rpx 0;
 | |
| 
 | |
|       .loadmore-btn {
 | |
|         width: 98%;
 | |
|         height: 40px;
 | |
|         font-size: 12px;
 | |
|         color: #8c8c8c;
 | |
| 
 | |
|         .loadmore-icon {
 | |
|           transform: rotate(90deg);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .message-item {
 | |
|         margin-bottom: 33rpx;
 | |
|       }
 | |
| 
 | |
|       .date-message,
 | |
|       .system-message {
 | |
|         width: fit-content;
 | |
|         border-radius: 12rpx;
 | |
|         padding: 8rpx 16rpx;
 | |
|         margin-bottom: 16rpx;
 | |
|         background-color: var(--ui-BG-3);
 | |
|         color: #999;
 | |
|         font-size: 24rpx;
 | |
|       }
 | |
| 
 | |
|       .chat-avatar {
 | |
|         width: 70rpx;
 | |
|         height: 70rpx;
 | |
|         border-radius: 50%;
 | |
|       }
 | |
| 
 | |
|       .send-status {
 | |
|         color: #333;
 | |
|         height: 80rpx;
 | |
|         margin-right: 8rpx;
 | |
|         display: flex;
 | |
|         align-items: center;
 | |
| 
 | |
|         .loading {
 | |
|           width: 32rpx;
 | |
|           height: 32rpx;
 | |
|           -webkit-animation: rotating 2s linear infinite;
 | |
|           animation: rotating 2s linear infinite;
 | |
| 
 | |
|           @-webkit-keyframes rotating {
 | |
|             0% {
 | |
|               transform: rotateZ(0);
 | |
|             }
 | |
| 
 | |
|             100% {
 | |
|               transform: rotateZ(360deg);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           @keyframes rotating {
 | |
|             0% {
 | |
|               transform: rotateZ(0);
 | |
|             }
 | |
| 
 | |
|             100% {
 | |
|               transform: rotateZ(360deg);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         .warning {
 | |
|           width: 32rpx;
 | |
|           height: 32rpx;
 | |
|           color: #ff3000;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .message-box {
 | |
|         max-width: 50%;
 | |
|         font-size: 16px;
 | |
|         line-height: 20px;
 | |
|         // max-width: 500rpx;
 | |
|         white-space: normal;
 | |
|         word-break: break-all;
 | |
|         word-wrap: break-word;
 | |
|         padding: 20rpx;
 | |
|         border-radius: 10rpx;
 | |
|         color: #fff;
 | |
|         background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
 | |
| 
 | |
|         &.customer_service {
 | |
|           background: #fff;
 | |
|           color: #333;
 | |
|         }
 | |
|         :deep() {
 | |
|           .imgred {
 | |
|             width: 100%;
 | |
|           }
 | |
|           .imgred,
 | |
|           img {
 | |
|             width: 100% !important;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       :deep() {
 | |
|         .goods,
 | |
|         .order {
 | |
|           max-width: 500rpx;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .message-img {
 | |
|         width: 100px;
 | |
|         height: 100px;
 | |
|         border-radius: 6rpx;
 | |
|       }
 | |
| 
 | |
|       .template-wrap {
 | |
|         // width: 100%;
 | |
|         padding: 20rpx 24rpx;
 | |
|         background: #fff;
 | |
|         border-radius: 10rpx;
 | |
| 
 | |
|         .title {
 | |
|           font-size: 26rpx;
 | |
|           font-weight: 500;
 | |
|           color: #333;
 | |
|           margin-bottom: 29rpx;
 | |
|         }
 | |
| 
 | |
|         .item {
 | |
|           font-size: 24rpx;
 | |
|           color: var(--ui-BG-Main);
 | |
|           margin-bottom: 16rpx;
 | |
| 
 | |
|           &:last-of-type {
 | |
|             margin-bottom: 0;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .error-img {
 | |
|         width: 400rpx;
 | |
|         height: 400rpx;
 | |
|       }
 | |
| 
 | |
|       #scrollBottom {
 | |
|         height: 120rpx;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .send-wrap {
 | |
|       padding: 18rpx 20rpx;
 | |
|       background: #fff;
 | |
| 
 | |
|       .left {
 | |
|         height: 64rpx;
 | |
|         border-radius: 32rpx;
 | |
|         background: var(--ui-BG-1);
 | |
|       }
 | |
| 
 | |
|       .bq {
 | |
|         font-size: 50rpx;
 | |
|         margin-left: 10rpx;
 | |
|       }
 | |
| 
 | |
|       .sicon-edit {
 | |
|         font-size: 50rpx;
 | |
|         margin-left: 10rpx;
 | |
|         transform: rotate(0deg);
 | |
|         transition: all linear 0.2s;
 | |
| 
 | |
|         &.is-active {
 | |
|           transform: rotate(45deg);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .send-btn {
 | |
|         width: 100rpx;
 | |
|         height: 60rpx;
 | |
|         line-height: 60rpx;
 | |
|         border-radius: 30rpx;
 | |
|         background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
 | |
|         font-size: 26rpx;
 | |
|         color: #fff;
 | |
|         margin-left: 11rpx;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .content {
 | |
|     width: 100%;
 | |
|     align-content: space-around;
 | |
|     border-top: 1px solid #dfdfdf;
 | |
|     padding: 20rpx 0 0;
 | |
| 
 | |
|     .emoji-swiper {
 | |
|       width: 100%;
 | |
|       height: 280rpx;
 | |
|       padding: 0 20rpx;
 | |
| 
 | |
|       .emoji-img {
 | |
|         width: 50rpx;
 | |
|         height: 50rpx;
 | |
|         display: inline-block;
 | |
|         margin: 10rpx;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .image,
 | |
|     .goods,
 | |
|     .order {
 | |
|       width: 33.3%;
 | |
|       height: 280rpx;
 | |
|       text-align: center;
 | |
|       font-size: 24rpx;
 | |
|       color: #333;
 | |
|       display: flex;
 | |
|       flex-direction: column;
 | |
|       align-items: center;
 | |
|       justify-content: center;
 | |
| 
 | |
|       .icon {
 | |
|         width: 50rpx;
 | |
|         height: 50rpx;
 | |
|         margin-bottom: 21rpx;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     :deep() {
 | |
|       .uni-file-picker__container {
 | |
|         justify-content: center;
 | |
|       }
 | |
| 
 | |
|       .file-picker__box {
 | |
|         display: none;
 | |
| 
 | |
|         &:last-of-type {
 | |
|           display: flex;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| </style>
 |