Procházet zdrojové kódy

【功能完善】商城:客服消息改为游标查询,消息 JSON 化

YunaiV před 9 měsíci
rodič
revize
87c6e967f2
3 změnil soubory, kde provedl 103 přidání a 61 odebrání
  1. 27 11
      pages/chat/components/messageList.vue
  2. 29 10
      pages/chat/index.vue
  3. 47 40
      sheep/util/index.js

+ 27 - 11
pages/chat/components/messageList.vue

@@ -1,20 +1,35 @@
 <template>
   <!--  聊天虚拟列表  -->
-  <z-paging ref="pagingRef" v-model="messageList" use-chat-record-mode use-virtual-list
-            cell-height-mode="dynamic" default-page-size="20" :auto-clean-list-when-reload="false"
-            safe-area-inset-bottom bottom-bg-color="#f8f8f8" :back-to-top-style="backToTopStyle"
-            :auto-show-back-to-top="showNewMessageTip" @backToTopClick="onBackToTopClick"
-            @scrolltoupper="onScrollToUpper" @query="queryList">
+  <z-paging
+    ref="pagingRef"
+    v-model="messageList"
+    use-chat-record-mode
+    use-virtual-list
+    cell-height-mode="dynamic"
+    default-page-size="20"
+    :auto-clean-list-when-reload="false"
+    safe-area-inset-bottom
+    bottom-bg-color="#f8f8f8"
+    :back-to-top-style="backToTopStyle"
+    :auto-show-back-to-top="showNewMessageTip"
+    @backToTopClick="onBackToTopClick"
+    @scrolltoupper="onScrollToUpper"
+    @query="queryList"
+  >
     <template #top>
       <!-- 撑一下顶部导航 -->
       <view :style="{ height: sys_navBar + 'px' }"></view>
     </template>
     <!-- style="transform: scaleY(-1)"必须写,否则会导致列表倒置!!! -->
     <!-- 注意不要直接在chat-item组件标签上设置style,因为在微信小程序中是无效的,请包一层view -->
-    <template #cell="{item,index}">
+    <template #cell="{ item, index }">
       <view style="transform: scaleY(-1)">
         <!--  消息渲染  -->
-        <MessageListItem :message="item" :message-index="index" :message-list="messageList"></MessageListItem>
+        <MessageListItem
+          :message="item"
+          :message-index="index"
+          :message-list="messageList"
+        ></MessageListItem>
       </view>
     </template>
     <!-- 底部聊天输入框 -->
@@ -41,13 +56,13 @@
   const showNewMessageTip = ref(false); // 显示有新消息提示
   const refreshMessage = ref(false); // 更新消息列表
   const backToTopStyle = reactive({
-    'width': '100px',
+    width: '100px',
     'background-color': '#fff',
     'border-radius': '30px',
     'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)',
-    'display': 'flex',
-    'justifyContent': 'center',
-    'alignItems': 'center',
+    display: 'flex',
+    justifyContent: 'center',
+    alignItems: 'center',
   }); // 返回顶部样式
   const queryParams = reactive({
     pageNo: 1, // 只用于触底计算
@@ -106,6 +121,7 @@
       onScrollToUpper();
     }
   };
+
   /** 滚动到最新消息 */
   const onBackToTopClick = (event) => {
     event(false); // 禁用默认操作

+ 29 - 10
pages/chat/index.vue

@@ -1,17 +1,35 @@
 <template>
-  <s-layout class="chat-wrap" :title="!isReconnecting ? '连接客服成功' : '会话重连中'" navbar="inner">
+  <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>
+        <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
+      :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
@@ -30,7 +48,10 @@
   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 {
+    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';
@@ -105,7 +126,7 @@
         const res = await FileApi.uploadFile(data.tempFiles[0].path);
         msg = {
           contentType: KeFuMessageContentTypeEnum.IMAGE,
-          content: JSON.stringify({picUrl: res.data}),
+          content: JSON.stringify({ picUrl: res.data }),
         };
         break;
       case 'goods':
@@ -135,8 +156,7 @@
   //======================= 聊天工具相关 end =======================
   const { options } = useWebSocket({
     // 连接成功
-    onConnected: async () => {
-    },
+    onConnected: async () => {},
     // 收到消息
     onMessage: async (data) => {
       const type = data.type;
@@ -161,7 +181,6 @@
 
 <style scoped lang="scss">
   .chat-wrap {
-
     .page-bg {
       width: 100%;
       position: absolute;

+ 47 - 40
sheep/util/index.js

@@ -1,4 +1,4 @@
-import dayjs from "dayjs";
+import dayjs from 'dayjs';
 
 /**
  * 将一个整数转换为分数保留两位小数
@@ -6,10 +6,10 @@ import dayjs from "dayjs";
  * @return {number} 分数
  */
 export const formatToFraction = (num) => {
-  if (typeof num === 'undefined') return 0
-  const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
-  return parseFloat((parsedNumber / 100).toFixed(2))
-}
+  if (typeof num === 'undefined') return 0;
+  const parsedNumber = typeof num === 'string' ? parseFloat(num) : num;
+  return parseFloat((parsedNumber / 100).toFixed(2));
+};
 
 /**
  * 将一个数转换为 1.00 这样
@@ -19,26 +19,26 @@ export const formatToFraction = (num) => {
  * @return {string} 分数
  */
 export const floatToFixed2 = (num) => {
-  let str = '0.00'
+  let str = '0.00';
   if (typeof num === 'undefined') {
-    return str
+    return str;
   }
-  const f = formatToFraction(num)
-  const decimalPart = f.toString().split('.')[1]
-  const len = decimalPart ? decimalPart.length : 0
+  const f = formatToFraction(num);
+  const decimalPart = f.toString().split('.')[1];
+  const len = decimalPart ? decimalPart.length : 0;
   switch (len) {
     case 0:
-      str = f.toString() + '.00'
-      break
+      str = f.toString() + '.00';
+      break;
     case 1:
-      str = f.toString() + '.0'
-      break
+      str = f.toString() + '.0';
+      break;
     case 2:
-      str = f.toString()
-      break
+      str = f.toString();
+      break;
   }
-  return str
-}
+  return str;
+};
 
 /**
  * 将一个分数转换为整数
@@ -47,11 +47,11 @@ export const floatToFixed2 = (num) => {
  * @return {number} 整数
  */
 export const convertToInteger = (num) => {
-  if (typeof num === 'undefined') return 0
-  const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+  if (typeof num === 'undefined') return 0;
+  const parsedNumber = typeof num === 'string' ? parseFloat(num) : num;
   // TODO 分转元后还有小数则四舍五入
-  return Math.round(parsedNumber * 100)
-}
+  return Math.round(parsedNumber * 100);
+};
 
 /**
  * 时间日期转换
@@ -64,16 +64,16 @@ export const convertToInteger = (num) => {
  * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
  * @returns {string} 返回拼接后的时间字符串
  */
-export function formatDate(date, format= 'YYYY-MM-DD HH:mm:ss') {
+export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
   // 日期不存在,则返回空
   if (!date) {
-    return ''
+    return '';
   }
   // 日期存在,则进行格式化
   if (format === undefined) {
-    format = 'YYYY-MM-DD HH:mm:ss'
+    format = 'YYYY-MM-DD HH:mm:ss';
   }
-  return dayjs(date).format(format)
+  return dayjs(date).format(format);
 }
 
 /**
@@ -85,16 +85,22 @@ export function formatDate(date, format= 'YYYY-MM-DD HH:mm:ss') {
  * @param {*} children 孩子节点字段 默认 'children'
  * @param {*} rootId 根Id 默认 0
  */
-export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children', rootId = 0) {
+export function handleTree(
+  data,
+  id = 'id',
+  parentId = 'parentId',
+  children = 'children',
+  rootId = 0,
+) {
   // 对源数据深度克隆
-  const cloneData = JSON.parse(JSON.stringify(data))
+  const cloneData = JSON.parse(JSON.stringify(data));
   // 循环所有项
-  const treeData = cloneData.filter(father => {
-    let branchArr = cloneData.filter(child => {
+  const treeData = cloneData.filter((father) => {
+    let branchArr = cloneData.filter((child) => {
       //返回每一项的子级数组
-      return father[id] === child[parentId]
+      return father[id] === child[parentId];
     });
-    branchArr.length > 0 ? father.children = branchArr : '';
+    branchArr.length > 0 ? (father.children = branchArr) : '';
     //返回第一层
     return father[parentId] === rootId;
   });
@@ -120,17 +126,18 @@ export function resetPagination(pagination) {
  * @param source 源对象
  */
 export const copyValueToTarget = (target, source) => {
-  const newObj = Object.assign({}, target, source)
+  const newObj = Object.assign({}, target, source);
   // 删除多余属性
   Object.keys(newObj).forEach((key) => {
     // 如果不是target中的属性则删除
     if (Object.keys(target).indexOf(key) === -1) {
-      delete newObj[key]
+      delete newObj[key];
     }
-  })
+  });
   // 更新目标对象值
-  Object.assign(target, newObj)
-}
+  Object.assign(target, newObj);
+};
+
 /**
  * 解析 JSON 字符串
  *
@@ -138,9 +145,9 @@ export const copyValueToTarget = (target, source) => {
  */
 export function jsonParse(str) {
   try {
-    return JSON.parse(str)
+    return JSON.parse(str);
   } catch (e) {
-    console.error(`str[${str}] 不是一个 JSON 字符串`)
-    return ''
+    console.error(`str[${str}] 不是一个 JSON 字符串`);
+    return '';
   }
 }