208 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | ||
|   <s-layout
 | ||
|     class="chat-wrap"
 | ||
|     :title="!isReconnecting ? '连接客服成功' : '会话重连中'"
 | ||
|     navbar="inner"
 | ||
|   >
 | ||
|     <!--  覆盖头部导航栏背景颜色  -->
 | ||
|     <div class="page-bg" :style="{ height: sys_navBar + 'px' }"></div>
 | ||
|     <!--  聊天区域  -->
 | ||
|     <MessageList ref="messageListRef">
 | ||
|       <template #bottom>
 | ||
|         <message-input
 | ||
|           v-model="chat.msg"
 | ||
|           @on-tools="onTools"
 | ||
|           @send-message="onSendMessage"
 | ||
|         ></message-input>
 | ||
|       </template>
 | ||
|     </MessageList>
 | ||
|     <!--  聊天工具  -->
 | ||
|     <tools-popup
 | ||
|       :show-tools="chat.showTools"
 | ||
|       :tools-mode="chat.toolsMode"
 | ||
|       @close="handleToolsClose"
 | ||
|       @on-emoji="onEmoji"
 | ||
|       @image-select="onSelect"
 | ||
|       @on-show-select="onShowSelect"
 | ||
|     >
 | ||
|       <message-input
 | ||
|         v-model="chat.msg"
 | ||
|         @on-tools="onTools"
 | ||
|         @send-message="onSendMessage"
 | ||
|       ></message-input>
 | ||
|     </tools-popup>
 | ||
|     <!--  商品订单选择  -->
 | ||
|     <SelectPopup
 | ||
|       :mode="chat.selectMode"
 | ||
|       :show="chat.showSelect"
 | ||
|       @select="onSelect"
 | ||
|       @close="chat.showSelect = false"
 | ||
|     />
 | ||
|   </s-layout>
 | ||
| </template>
 | ||
| 
 | ||
| <script setup>
 | ||
|   import MessageList from '@/pages/chat/components/messageList.vue';
 | ||
|   import { reactive, ref, toRefs } from 'vue';
 | ||
|   import sheep from '@/sheep';
 | ||
|   import ToolsPopup from '@/pages/chat/components/toolsPopup.vue';
 | ||
|   import MessageInput from '@/pages/chat/components/messageInput.vue';
 | ||
|   import SelectPopup from '@/pages/chat/components/select-popup.vue';
 | ||
|   import {
 | ||
|     KeFuMessageContentTypeEnum,
 | ||
|     WebSocketMessageTypeConstants,
 | ||
|   } from '@/pages/chat/util/constants';
 | ||
|   import FileApi from '@/sheep/api/infra/file';
 | ||
|   import KeFuApi from '@/sheep/api/promotion/kefu';
 | ||
|   import { useWebSocket } from '@/sheep/hooks/useWebSocket';
 | ||
|   import { jsonParse } from '@/sheep/util';
 | ||
| 
 | ||
|   const sys_navBar = sheep.$platform.navbar;
 | ||
| 
 | ||
|   const chat = reactive({
 | ||
|     msg: '',
 | ||
|     scrollInto: '',
 | ||
|     showTools: false,
 | ||
|     toolsMode: '',
 | ||
|     showSelect: false,
 | ||
|     selectMode: '',
 | ||
|   });
 | ||
| 
 | ||
|   // 发送消息
 | ||
|   async function onSendMessage() {
 | ||
|     if (!chat.msg) return;
 | ||
|     try {
 | ||
|       const data = {
 | ||
|         contentType: KeFuMessageContentTypeEnum.TEXT,
 | ||
|         content: JSON.stringify({ text: chat.msg }),
 | ||
|       };
 | ||
|       await KeFuApi.sendKefuMessage(data);
 | ||
|       await messageListRef.value.refreshMessageList();
 | ||
|       chat.msg = '';
 | ||
|     } finally {
 | ||
|       chat.showTools = false;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   const messageListRef = ref();
 | ||
| 
 | ||
|   //======================= 聊天工具相关 start =======================
 | ||
| 
 | ||
|   function handleToolsClose() {
 | ||
|     chat.showTools = false;
 | ||
|     chat.toolsMode = '';
 | ||
|   }
 | ||
| 
 | ||
|   function onEmoji(item) {
 | ||
|     chat.msg += item.name;
 | ||
|   }
 | ||
| 
 | ||
|   // 点击工具栏开关
 | ||
|   function onTools(mode) {
 | ||
|     if (isReconnecting.value) {
 | ||
|       sheep.$helper.toast('您已掉线!请返回重试');
 | ||
|       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 res = await FileApi.uploadFile(data.tempFiles[0].path);
 | ||
|         msg = {
 | ||
|           contentType: KeFuMessageContentTypeEnum.IMAGE,
 | ||
|           content: JSON.stringify({ picUrl: res.data }),
 | ||
|         };
 | ||
|         break;
 | ||
|       case 'goods':
 | ||
|         msg = {
 | ||
|           contentType: KeFuMessageContentTypeEnum.PRODUCT,
 | ||
|           content: JSON.stringify(data),
 | ||
|         };
 | ||
|         break;
 | ||
|       case 'order':
 | ||
|         msg = {
 | ||
|           contentType: KeFuMessageContentTypeEnum.ORDER,
 | ||
|           content: JSON.stringify(data),
 | ||
|         };
 | ||
|         break;
 | ||
|     }
 | ||
|     if (msg) {
 | ||
|       // 发送消息
 | ||
|       // scrollBottom();
 | ||
|       await KeFuApi.sendKefuMessage(msg);
 | ||
|       await messageListRef.value.refreshMessageList();
 | ||
|       chat.showTools = false;
 | ||
|       chat.showSelect = false;
 | ||
|       chat.selectMode = '';
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   //======================= 聊天工具相关 end =======================
 | ||
|   const { options } = useWebSocket({
 | ||
|     // 连接成功
 | ||
|     onConnected: async () => {},
 | ||
|     // 收到消息
 | ||
|     onMessage: async (data) => {
 | ||
|       const type = data.type;
 | ||
|       if (!type) {
 | ||
|         console.error('未知的消息类型:' + data);
 | ||
|         return;
 | ||
|       }
 | ||
|       // 2.2 消息类型:KEFU_MESSAGE_TYPE
 | ||
|       if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
 | ||
|         // 刷新消息列表
 | ||
|         await messageListRef.value.refreshMessageList(jsonParse(data.content));
 | ||
|         return;
 | ||
|       }
 | ||
|       // 2.3 消息类型:KEFU_MESSAGE_ADMIN_READ
 | ||
|       if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
 | ||
|         console.log('管理员已读消息');
 | ||
|       }
 | ||
|     },
 | ||
|   });
 | ||
|   const isReconnecting = toRefs(options).isReconnecting; // 重连状态
 | ||
| </script>
 | ||
| 
 | ||
| <style scoped lang="scss">
 | ||
|   .chat-wrap {
 | ||
|     .page-bg {
 | ||
|       width: 100%;
 | ||
|       position: absolute;
 | ||
|       top: 0;
 | ||
|       left: 0;
 | ||
|       background-color: var(--ui-BG-Main);
 | ||
|       z-index: 1;
 | ||
|     }
 | ||
| 
 | ||
|     .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);
 | ||
|     }
 | ||
|   }
 | ||
| </style>
 |