瀏覽代碼

客服:组件初步抽离

puhui999 10 月之前
父節點
當前提交
3355f5e853
共有 5 個文件被更改,包括 314 次插入230 次删除
  1. 19 10
      pages.json
  2. 102 0
      pages/chat/components/messageInput.vue
  3. 166 0
      pages/chat/components/toolsPopup.vue
  4. 25 213
      pages/chat/index.vue
  5. 2 7
      pages/chat/socket.js

+ 19 - 10
pages.json

@@ -86,7 +86,8 @@
 	],
 	"subPackages": [{
 			"root": "pages/goods",
-			"pages": [{
+			"pages": [
+              {
 					"path": "index",
 					"style": {
 						"navigationBarTitleText": "商品详情"
@@ -150,7 +151,8 @@
 		},
 		{
 			"root": "pages/order",
-			"pages": [{
+			"pages": [
+              {
 					"path": "detail",
 					"style": {
 						"navigationBarTitleText": "订单详情"
@@ -249,7 +251,8 @@
 		},
 		{
 			"root": "pages/user",
-			"pages": [{
+			"pages": [
+              {
 					"path": "info",
 					"style": {
 						"navigationBarTitleText": "我的信息"
@@ -335,7 +338,8 @@
 		},
 		{
 			"root": "pages/commission",
-			"pages": [{
+			"pages": [
+              {
 					"path": "index",
 					"style": {
 						"navigationBarTitleText": "分销"
@@ -432,7 +436,8 @@
 		},
 		{
 			"root": "pages/app",
-			"pages": [{
+			"pages": [
+              {
 				"path": "sign",
 				"style": {
 					"navigationBarTitleText": "签到中心"
@@ -447,7 +452,8 @@
 		},
 		{
 			"root": "pages/public",
-			"pages": [{
+			"pages": [
+              {
 					"path": "setting",
 					"style": {
 						"navigationBarTitleText": "系统设置"
@@ -496,7 +502,8 @@
 		},
 		{
 			"root": "pages/coupon",
-			"pages": [{
+			"pages": [
+              {
 					"path": "list",
 					"style": {
 						"navigationBarTitleText": "领券中心"
@@ -538,7 +545,8 @@
 		},
 		{
 			"root": "pages/pay",
-			"pages": [{
+			"pages": [
+              {
 					"path": "index",
 					"style": {
 						"navigationBarTitleText": "收银台"
@@ -578,7 +586,8 @@
 		},
 		{
 			"root": "pages/activity",
-			"pages": [{
+			"pages": [
+              {
 					"path": "groupon/detail",
 					"style": {
 						"navigationBarTitleText": "拼团详情"
@@ -652,4 +661,4 @@
 			}
 		]
 	}
-}
+}

+ 102 - 0
pages/chat/components/messageInput.vue

@@ -0,0 +1,102 @@
+<template>
+  <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="message"
+        placeholder="请输入你要咨询的问题"
+      ></uni-easyinput>
+    </view>
+    <text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
+    <text
+      v-if="!message"
+      class="sicon-edit"
+      :class="{ 'is-active': toolsMode === 'tools' }"
+      @tap.stop="onTools('tools')"
+    ></text>
+    <button v-if="message" class="ss-reset-button send-btn" @tap="sendMessage">
+      发送
+    </button>
+  </view>
+</template>
+
+<script setup>
+  import { computed } from 'vue';
+  /**
+   * 消息发送组件
+   */
+  const props = defineProps({
+    // 消息
+    modelValue: {
+      type: String,
+      default: '',
+    },
+    // 工具模式
+    toolsMode: {
+      type: String,
+      default: '',
+    },
+  });
+  const emits = defineEmits(['update:modelValue', 'onTools', 'sendMessage']);
+  const message = computed({
+    get() {
+      return props.modelValue;
+    },
+    set(newValue) {
+      emits(`update:modelValue`, newValue);
+    }
+  });
+
+
+  // 打开工具菜单
+  function onTools(mode) {
+    emits('onTools', mode);
+  }
+
+  // 发送消息
+  function sendMessage() {
+    emits('sendMessage');
+  }
+</script>
+
+<style scoped lang="scss">
+  .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;
+    }
+  }
+</style>

+ 166 - 0
pages/chat/components/toolsPopup.vue

@@ -0,0 +1,166 @@
+<template>
+  <su-popup
+    :show="showTools"
+    @close="handleClose"
+  >
+    <view class="ss-modal-box ss-flex-col">
+      <slot></slot>
+      <view class="content ss-flex ss-flex-1">
+        <template v-if="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">
+                <image
+                  v-for="item in emoji" :key="item"
+                  class="emoji-img"
+                  :src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)"
+                  @tap="onEmoji(item)"
+                >
+                </image>
+              </view>
+            </swiper-item>
+          </swiper>
+        </template>
+        <template v-else>
+          <view class="image">
+            <s-uploader
+              file-mediatype="image"
+              :imageStyles="{ width: 50, height: 50, border: false }"
+              @select="imageSelect({ 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>
+</template>
+
+<script setup>
+  /**
+   * 聊天工具
+   */
+  import { emojiPage } from '@/pages/chat/emoji';
+  import sheep from '@/sheep';
+
+  const props = defineProps({
+    // 工具模式
+    toolsMode: {
+      type: String,
+      default: '',
+    },
+    // 控制工具菜单弹出
+    showTools: {
+      type: Boolean,
+      default: () => false,
+    },
+  });
+  const emits = defineEmits(['onEmoji', 'imageSelect', 'onShowSelect', 'close']);
+
+  // 关闭弹出工具菜单
+  function handleClose() {
+    emits('close');
+  }
+
+  // 选择表情
+  function onEmoji(emoji) {
+    emits('onEmoji', emoji);
+  }
+
+  // 选择图片
+  function imageSelect(val) {
+    emits('imageSelect', val);
+  }
+
+  // 选择商品或订单
+  function onShowSelect(mode) {
+    emits('onShowSelect', mode);
+  }
+</script>
+
+<style scoped lang="scss">
+  .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>

+ 25 - 213
pages/chat/index.vue

@@ -159,119 +159,13 @@
       </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>
+      <message-input v-model="chat.msg" @on-tools="onTools" @send-message="onSendMessage"></message-input>
     </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>
+    <!--  聊天工具  -->
+    <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"
@@ -286,10 +180,12 @@
   import sheep from '@/sheep';
   import { computed, reactive, toRefs } from 'vue';
   import { onLoad } from '@dcloudio/uni-app';
-  import { emojiList, emojiPage } from './emoji.js';
+  import { emojiList } from './emoji.js';
   import SelectPopup from './components/select-popup.vue';
   import GoodsItem from './components/goods.vue';
   import OrderItem from './components/order.vue';
+  import MessageInput from './components/messageInput.vue';
+  import ToolsPopup from './components/toolsPopup.vue';
   import { useChatWebSocket } from './socket';
 
   const {
@@ -372,12 +268,23 @@
     },
   });
 
+  //======================= 聊天工具相关 =======================
+
+  function handleToolsClose() {
+    chat.showTools = false;
+    chat.toolsMode = '';
+  }
+
+  function onEmoji(item) {
+    chat.msg += item.name;
+  }
+
   // 点击工具栏开关
   function onTools(mode) {
-    if (!socketState.value.isConnect) {
-      sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
-      return;
-    }
+    // if (!socketState.value.isConnect) {
+    //   sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
+    //   return;
+    // }
 
     if (!chat.toolsMode || chat.toolsMode === mode) {
       chat.showTools = !chat.showTools;
@@ -523,10 +430,6 @@
     // scrollBottom();
   }
 
-  function onEmoji(item) {
-    chat.msg += item.name;
-  }
-
   function selEmojiFile(name) {
     for (let index in emojiList) {
       if (emojiList[index].name === name) {
@@ -761,98 +664,6 @@
         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>
 <style>
@@ -861,6 +672,7 @@
     height: 24px;
     margin: 0 3px;
   }
+
   .full-img {
     object-fit: cover;
     width: 100px;

+ 2 - 7
pages/chat/socket.js

@@ -304,12 +304,7 @@ export function useChatWebSocket(socketConfig) {
 
   // 用户id,获取token
   const getUserToken = async (id) => {
-    const res = await chat.unifiedToken();
-    if (res.error === 0) {
-      uni.setStorageSync('socketUserToken', res.data.token);
-      // SocketIo && SocketIo.connected && socketLogin(res.data.token)
-    }
-    return res;
+    return uni.getStorageSync('token');
   };
 
   // 用户登录
@@ -818,4 +813,4 @@ export function useChatWebSocket(socketConfig) {
     showTime,
     formatTime,
   };
-}
+}