Эх сурвалжийг харах

【新增】:mall 客服选择并发送图片信息

puhui999 11 сар өмнө
parent
commit
e45cade877

+ 26 - 7
src/views/mall/promotion/kefu/components/KeFuChatBox.vue

@@ -71,10 +71,14 @@
     </el-main>
     <el-footer height="230px">
       <div class="h-[100%]">
-        <div class="chat-tools">
+        <div class="chat-tools flex items-center">
           <EmojiSelectPopover @select-emoji="handleEmojiSelect" />
+          <PictureSelectUpload
+            class="ml-15px mt-3px cursor-pointer"
+            @send-picture="handleSendPicture"
+          />
         </div>
-        <el-input v-model="message" :rows="6" type="textarea" />
+        <el-input v-model="message" :rows="6" style="border-style: none" type="textarea" />
         <div class="h-45px flex justify-end">
           <el-button class="mt-10px" type="primary" @click="handleSendMessage">发送</el-button>
         </div>
@@ -88,9 +92,10 @@
 import { ElScrollbar as ElScrollbarType } from 'element-plus'
 import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
 import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
-import EmojiSelectPopover from './EmojiSelectPopover.vue'
-import { Emoji, useEmoji } from './emoji'
-import { KeFuMessageContentTypeEnum } from './constants'
+import EmojiSelectPopover from './tools/EmojiSelectPopover.vue'
+import PictureSelectUpload from './tools/PictureSelectUpload.vue'
+import { Emoji, useEmoji } from './tools/emoji'
+import { KeFuMessageContentTypeEnum } from './tools/constants'
 import { isEmpty } from '@/utils/is'
 import { UserTypeEnum } from '@/utils/constants'
 import { createImageViewer } from '@/components/ImageViewer'
@@ -126,6 +131,16 @@ const showChatBox = computed(() => !isEmpty(keFuConversation.value))
 const handleEmojiSelect = (item: Emoji) => {
   message.value += item.name
 }
+// 处理图片发送
+const handleSendPicture = async (picUrl: string) => {
+  // 组织发送消息
+  const msg = {
+    conversationId: keFuConversation.value.id,
+    contentType: KeFuMessageContentTypeEnum.IMAGE,
+    content: picUrl
+  }
+  await sendMessage(msg)
+}
 // 发送消息
 const handleSendMessage = async () => {
   // 1. 校验消息是否为空
@@ -139,6 +154,11 @@ const handleSendMessage = async () => {
     contentType: KeFuMessageContentTypeEnum.TEXT,
     content: message.value
   }
+  await sendMessage(msg)
+}
+
+// 发送消息 【共用】
+const sendMessage = async (msg: any) => {
   await KeFuMessageApi.sendKeFuMessage(msg)
   message.value = ''
   // 3. 加载消息列表
@@ -248,9 +268,8 @@ onBeforeUnmount(() => {
   .chat-tools {
     width: 100%;
     border: #e4e0e0 solid 1px;
+    border-radius: 10px;
     height: 44px;
-    display: flex;
-    align-items: center;
   }
 
   ::v-deep(textarea) {

+ 2 - 2
src/views/mall/promotion/kefu/components/KeFuConversationBox.vue

@@ -35,9 +35,9 @@
 
 <script lang="ts" setup>
 import { KeFuConversationApi, KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
-import { useEmoji } from './emoji'
+import { useEmoji } from './tools/emoji'
 import { formatDate, getNowDateTime } from '@/utils/formatTime'
-import { KeFuMessageContentTypeEnum } from '@/views/mall/promotion/kefu/components/constants'
+import { KeFuMessageContentTypeEnum } from './tools/constants'
 
 defineOptions({ name: 'KeFuConversationBox' })
 const { replaceEmoji } = useEmoji()

+ 10 - 0
src/views/mall/promotion/kefu/components/images/picture.svg

@@ -0,0 +1,10 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+        "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1720063872285" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6895"
+     width="200" height="200">
+    <path d="M782.16 880.98c-179.31 23.91-361 23.91-540.32 0C138.89 867.25 62 779.43 62 675.57V348.43c0-103.86 76.89-191.69 179.84-205.41 179.31-23.91 361-23.91 540.31 0C885.11 156.75 962 244.57 962 348.43v327.13c0 103.87-76.89 191.69-179.84 205.42z"
+          fill="#FF554D" p-id="6896"></path>
+    <path d="M226.11 596.86c-9.74 47.83 17.26 95.6 63.48 111.3C333.49 723.08 394.55 737 469.53 737c59.25 0 105.46-8.69 140.23-19.7 51.59-16.34 79.94-71.16 63.37-122.68-24.47-76.11-65.57-180.7-106.68-180.7-64.62 0-64.62 96.92-64.62 96.92S437.22 317 372.61 317c-82.11 0-117.85 139.12-146.5 279.86z"
+          fill="#FFFFFF" p-id="6897"></path>
+    <path d="M782 347m-60 0a60 60 0 1 0 120 0 60 60 0 1 0-120 0Z" fill="#FFBC55" p-id="6898"></path>
+</svg>

+ 1 - 1
src/views/mall/promotion/kefu/components/index.ts

@@ -1,5 +1,5 @@
 import KeFuConversationBox from './KeFuConversationBox.vue'
 import KeFuChatBox from './KeFuChatBox.vue'
-import * as Constants from './constants'
+import * as Constants from './tools/constants'
 
 export { KeFuConversationBox, KeFuChatBox, Constants }

+ 1 - 1
src/views/mall/promotion/kefu/components/EmojiSelectPopover.vue → src/views/mall/promotion/kefu/components/tools/EmojiSelectPopover.vue

@@ -2,7 +2,7 @@
 <template>
   <el-popover :width="500" placement="top" trigger="click">
     <template #reference>
-      <Icon :size="30" class="ml-10px" icon="twemoji:grinning-face" />
+      <Icon :size="30" class="ml-10px cursor-pointer" icon="twemoji:grinning-face" />
     </template>
     <ElScrollbar height="300px">
       <ul class="ml-2 flex flex-wrap px-2">

+ 92 - 0
src/views/mall/promotion/kefu/components/tools/PictureSelectUpload.vue

@@ -0,0 +1,92 @@
+<template>
+  <div>
+    <img :src="Picture" style="width: 35px; height: 35px" @click="selectAndUpload" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+import Picture from '@/views/mall/promotion/kefu/components/images/picture.svg'
+import * as FileApi from '@/api/infra/file'
+
+defineOptions({ name: 'PictureSelectUpload' })
+const message = useMessage()
+const emits = defineEmits<{
+  (e: 'send-picture', v: string): void
+}>()
+// 选择并上传文件
+const selectAndUpload = async () => {
+  const files: any = await getFiles()
+  message.success('图片发送请稍等。。。')
+  const res = await FileApi.updateFile({ file: files[0].file })
+  message.success('图片发送成功!')
+  emits('send-picture', res.data)
+}
+
+/**
+ * 唤起文件选择窗口,并获取选择的文件
+ * @param {Object} options - 配置选项
+ * @param {boolean} [options.multiple=true] - 是否支持多选
+ * @param {string} [options.accept=''] - 文件上传格式限制
+ * @param {number} [options.limit=1] - 单次上传最大文件数
+ * @param {number} [options.fileSize=500] - 单个文件大小限制(单位:MB)
+ * @returns {Promise<Array>} 选择的文件列表,每个文件带有一个uid
+ */
+async function getFiles(options = {}) {
+  const { multiple, accept, limit, fileSize } = {
+    multiple: true,
+    accept: 'image/jpeg, image/png, image/gif',
+    limit: 1,
+    fileSize: 500,
+    ...options
+  }
+
+  // 创建文件选择元素
+  const input = document.createElement('input')
+  input.type = 'file'
+  input.style.display = 'none'
+  if (multiple) input.multiple = true
+  if (accept) input.accept = accept
+
+  // 将文件选择元素添加到文档中
+  document.body.appendChild(input)
+
+  // 触发文件选择元素的点击事件
+  input.click()
+
+  // 等待文件选择元素的 change 事件
+  try {
+    const files = await new Promise((resolve, reject) => {
+      input.addEventListener('change', (event: any) => {
+        const filesArray = Array.from(event?.target?.files || [])
+
+        // 从文档中移除文件选择元素
+        document.body.removeChild(input)
+
+        // 判断是否超出上传数量限制
+        if (filesArray.length > limit) {
+          reject({ errorType: 'limit', files: filesArray })
+          return
+        }
+
+        // 判断是否超出上传文件大小限制
+        const oversizedFiles = filesArray.filter((file: File) => file.size / 1024 ** 2 > fileSize)
+        if (oversizedFiles.length > 0) {
+          reject({ errorType: 'fileSize', files: oversizedFiles })
+          return
+        }
+
+        // 生成文件列表,并添加 uid
+        const fileList = filesArray.map((file, index) => ({ file, uid: Date.now() + index }))
+        resolve(fileList)
+      })
+    })
+
+    return files
+  } catch (error) {
+    console.error('选择文件出错:', error)
+    throw error
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 0 - 0
src/views/mall/promotion/kefu/components/constants.ts → src/views/mall/promotion/kefu/components/tools/constants.ts


+ 0 - 0
src/views/mall/promotion/kefu/components/emoji.ts → src/views/mall/promotion/kefu/components/tools/emoji.ts