Browse Source

修改:获取消息内容优化

安浩浩 1 year ago
parent
commit
35b97b1ec0

+ 27 - 0
src/api/im/conversation/index.ts

@@ -0,0 +1,27 @@
+import request from '@/config/axios'
+
+export interface ImConversationRespVO {
+  id: number // 编号
+  userId: number // 所属用户
+  conversationType: number // 会话类型
+  targetId: number // 聊天对象编号
+  no: string // 会话标志
+  pinned: boolean // 是否置顶
+  lastReadTime: string // 最后已读时间
+  createTime: string // 创建时间
+}
+
+// 获得用户的会话列表
+export const getConversationList = async () => {
+  return await request.get({ url: `/im/conversation/list` })
+}
+
+// 置顶会话
+export const updatePinned = async (data: any) => {
+  return await request.post({ url: `/im/conversation/update-pinned`, data })
+}
+
+// 更新最后已读时间
+export const updateLastReadTime = async (data: any) => {
+  return await request.post({ url: `/im/conversation/update-last-read-time`, data })
+}

+ 3 - 3
src/layout/components/ImChat/src/ImChat.vue

@@ -1,12 +1,12 @@
 <script setup lang="ts">
 import { Dialog } from '@/components/Dialog'
-import { ref, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, DefineComponent } from 'vue'
 
 // 异步加载可能的对话框内容组件
 const IMComponent = defineAsyncComponent(() => import('@/views/im/index.vue'))
 
-const dialogVisible = ref(false)
-const currentComponent = ref(null)
+const dialogVisible = shallowRef(false)
+const currentComponent = shallowRef<DefineComponent | null>(null)
 
 // 添加点击事件处理函数,显示对话框并加载 IM 组件
 function openDialog() {

+ 6 - 0
src/utils/fileSizeFormat.ts

@@ -0,0 +1,6 @@
+// fileSizeFormat.ts
+export default function fileSizeFormat(value: number): string {
+  const s = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
+  const e = Math.floor(Math.log(value) / Math.log(1024))
+  return (value / Math.pow(1024, Math.floor(e))).toFixed(2) + ' ' + s[e]
+}

+ 20 - 0
src/utils/paseLink.ts

@@ -0,0 +1,20 @@
+interface ParsedLinkResult {
+  isLink: boolean
+  msg: string
+}
+
+const paseLink = (msg: string): ParsedLinkResult => {
+  let isLink = false
+  const reg =
+    /(https?\:\/\/|www\.)([a-zA-Z0-9-]+(\.[a-zA-Z0-9]+)+)(\:[0-9]{2,4})?\/?((\.[:_0-9a-zA-Z-]+)|[:_0-9a-zA-Z-]*\/?)*\??[:_#@*&%0-9a-zA-Z-/=]*/gm
+
+  msg = msg.replace(reg, function (v: string): string {
+    const prefix = /^https?/gm.test(v)
+    isLink = prefix
+    return "<a href='" + (prefix ? v : '//' + v) + "' target='_blank'>" + v + '</a>'
+  })
+
+  return { isLink, msg }
+}
+
+export default paseLink

+ 16 - 50
src/views/im/Conversation/components/ConversationList.vue

@@ -1,26 +1,11 @@
 <script setup lang="ts">
 import { formatDate } from '@/utils/formatTime'
 import { reactive } from 'vue'
-/* 头像相关 */
-import informIcon from '@/assets/imgs/im/avatar/inform.png'
+import * as ConversationApi from '@/api/im/conversation'
 /* route */
 const route = useRoute()
 /* router */
 const router = useRouter()
-//取系统通知数据
-const informDetail = computed(() => {
-  const informDetailArr = reactive([
-    {
-      from: '系统通知',
-      desc: '您有一条新的通知',
-      time: new Date(),
-      untreated: 1
-    }
-  ])
-  const lastInformDeatail = informDetailArr[0] || {}
-  const untreated = 1
-  return { untreated, lastInformDeatail }
-})
 
 //取好友列表(主要使用好友下的用户属性相关)
 const friendList = reactive({
@@ -40,10 +25,22 @@ const conversationList = reactive([
       msg: 'hello word!'
     },
     latestSendTime: new Date(),
-    unreadMessageNum: 5,
-    isMention: false
+    unreadMessageNum: 5
   }
 ])
+// let conversationList = reactive({})
+// // 获得用户的会话列表
+// const getConversationList = async () => {
+//   const res = await ConversationApi.getConversationList()
+//   if (res.code === 200) {
+//     console.log('会话列表', res.data)
+//     conversationList = res.data
+//   }
+// }
+// // 初始化
+// onMounted(() => {
+//   getConversationList()
+// })
 
 //处理会话name
 const handleConversationName = computed(() => {
@@ -53,7 +50,7 @@ const handleConversationName = computed(() => {
 const handleLastMsgNickName = computed(() => {
   return ''
 })
-const emit = defineEmits(['toInformDetails', 'toChatMessage'])
+const emit = defineEmits(['toChatMessage'])
 //普通会话
 const checkedConverItemIndex = ref(null)
 const toChatMessage = (item, itemKey, index) => {
@@ -69,36 +66,6 @@ const deleteConversation = (itemKey) => {
 </script>
 <template>
   <el-scrollbar class="session_list" style="overflow: auto" tag="ul">
-    <!-- 系统通知会话 -->
-    <li
-      v-if="JSON.stringify(informDetail.lastInformDeatail) !== '{}' && informDetail.untreated >= 1"
-      class="session_list_item"
-      @click="$emit('toInformDetails')"
-    >
-      <div class="item_body item_left">
-        <!-- 通知头像 -->
-        <div class="session_other_avatar">
-          <el-avatar :size="34" :src="informIcon" />
-        </div>
-      </div>
-      <div class="item_body item_main">
-        <div class="name">系统通知</div>
-        <div class="last_msg_body">
-          {{ informDetail.lastInformDeatail.from }}:{{ informDetail.lastInformDeatail.desc }}
-        </div>
-      </div>
-      <div class="item_body item_right">
-        <span class="time">{{
-          formatDate(informDetail.lastInformDeatail.time, 'MM/DD/HH:mm')
-        }}</span>
-        <span class="unReadNum_box" v-if="informDetail.untreated >= 1">
-          <sup
-            class="unReadNum_count"
-            v-text="informDetail.untreated >= 99 ? '99+' : informDetail.untreated"
-          ></sup>
-        </span>
-      </div>
-    </li>
     <!-- 普通会话 -->
     <template v-if="Object.keys(conversationList).length > 0">
       <li
@@ -133,7 +100,6 @@ const deleteConversation = (itemKey) => {
               <div class="item_body item_main">
                 <div class="name"> 好友 </div>
                 <div class="last_msg_body">
-                  <span class="last_msg_body_mention" v-if="item.isMention">[有人@我]</span>
                   <span v-show="item.conversationType === 2">好友</span>
                   {{ item.latestMessage.msg }}
                 </div>

+ 4 - 13
src/views/im/Conversation/index.vue

@@ -1,23 +1,14 @@
 <script setup lang="ts">
-import { ref, defineAsyncComponent } from 'vue'
+import { defineAsyncComponent, shallowRef } from 'vue'
 import { SearchInput } from '@/components/Im/SearchInput'
 import ConversationList from '../Conversation/components/ConversationList.vue'
 import { Welcome } from '@/components/Im/Welcome'
 
-// 异步加载可能的对话框内容组件
-const InformDetailsComponent = defineAsyncComponent(
-  () => import('@/views/im/InformDetails/index.vue')
-)
 const MessageComponent = defineAsyncComponent(() => import('@/views/im/Message/index.vue'))
 
-const currentComponent = ref(Welcome) // 默认加载欢迎页组件
+const currentComponent = shallowRef(Welcome) // 默认加载欢迎页组件
 
-// 更改为使用动态组件切换而非路由跳转
-const toInformDetails = () => {
-  currentComponent.value = InformDetailsComponent // 加载系统通知组件
-}
-
-const toChatMessage = (id, chatType) => {
+const toChatMessage = (id) => {
   console.log('>>>>>>>id', id)
   currentComponent.value = MessageComponent // 加载消息组件
 }
@@ -29,7 +20,7 @@ const toChatMessage = (id, chatType) => {
       <!-- 搜索组件 -->
       <SearchInput :searchType="'conversation'" />
       <div class="chat_conversation_list">
-        <ConversationList @to-inform-details="toInformDetails" @to-chat-message="toChatMessage" />
+        <ConversationList @to-chat-message="toChatMessage" />
       </div>
     </el-aside>
     <el-main class="chat_conversation_main_box">

+ 0 - 7
src/views/im/InformDetails/index.vue

@@ -1,7 +0,0 @@
-<script setup lang="ts"></script>
-
-<template>
-  <h2>系统通知</h2>
-</template>
-
-<style scoped lang="scss"></style>

+ 20 - 74
src/views/im/Message/components/messageList/index.vue

@@ -2,6 +2,15 @@
 import { formatDate } from '@/utils/formatTime'
 /* 默认头像 */
 import defaultAvatar from '@/assets/imgs/avatar.gif'
+import { useUserStore } from '@/store/modules/user'
+import avatarImg from '@/assets/imgs/avatar.gif'
+import paseLink from '@/utils/paseLink.ts'
+import fileSizeFormat from '@/utils/fileSizeFormat'
+import { messageType } from '@/constant/im'
+const { ALL_MESSAGE_TYPE, CUSTOM_TYPE } = messageType
+// 当前用户信息
+const userStore = useUserStore()
+const avatar = computed(() => userStore.user.avatar ?? avatarImg)
 /* props */
 const props = defineProps({
   messageData: {
@@ -16,25 +25,14 @@ const props = defineProps({
 })
 const { nowPickInfo } = toRefs(props)
 const { messageData } = toRefs(props)
-//消息类型
-const ALL_MESSAGE_TYPE = {
-  TEXT: 'txt',
-  IMAGE: 'img',
-  AUDIO: 'audio',
-  LOCAL: 'loc',
-  VIDEO: 'video',
-  FILE: 'file',
-  CUSTOM: 'custom',
-  CMD: 'cmd',
-  INFORM: 'inform' //这个类型不在环信消息类型内,属于自己定义的一种系统通知类的消息。
-}
 /* 处理时间显示间隔 */
 const handleMsgTimeShow = (time, index) => {
   console.log('>>>>>时间显示', time, index)
   const msgList = Array.from(messageData.value)
   if (index !== 0) {
     const lastTime = msgList[index - 1].time
-    return time - lastTime > 50000 ? formatDate(time, 'MM/DD/HH:mm') : false
+    console.log('>>>>>时间间隔', time - lastTime, time, lastTime)
+    return time - lastTime > 50000 ? formatDate(time, 'MM/DD/HH:mm') : ''
   } else {
     return formatDate(time, 'MM/DD/HH:mm')
   }
@@ -43,9 +41,15 @@ const handleMsgTimeShow = (time, index) => {
 const isMyself = (msgBody) => {
   return msgBody.from === '1'
 }
+/* 文本中是否包含link */
+const isLink = computed(() => {
+  return (msg) => {
+    return paseLink(msg).isLink
+  }
+})
 /* 获取自己的用户信息 */
 const loginUserInfo = {
-  avatarurl: 'https://avatars.githubusercontent.com/u/1?v=4'
+  avatarurl: avatar.value
 }
 /* 获取他人的用户信息 */
 const otherUserInfo = (from) => {
@@ -98,14 +102,14 @@ const startplayAudio = (msgBody) => {
     >
       <!-- 普通消息气泡 -->
       <div
-        v-if="!msgBody.isRecall && msgBody.type !== ALL_MESSAGE_TYPE.INFORM"
+        v-if="!msgBody.isRecall && msgBody.type !== ALL_MESSAGE_TYPE.OA_NOTIFICATION"
         class="message_box_item"
         :style="{
           flexDirection: isMyself(msgBody) ? 'row-reverse' : 'row'
         }"
       >
         <div class="message_item_time">
-          {{ handleMsgTimeShow(msgBody.time, index) || '' }}
+          {{ handleMsgTimeShow(msgBody.time, index) }}
         </div>
         <el-avatar
           class="message_item_avator"
@@ -136,12 +140,6 @@ const startplayAudio = (msgBody) => {
             >
               <template v-if="!isLink(msgBody.msg)">
                 {{ msgBody.msg }}
-                <!-- 已编辑 -->
-                <sup
-                  style="font-size: 7px; color: #707784"
-                  v-show="msgBody?.modifiedInfo?.operationCount"
-                  >(已编辑)</sup
-                >
               </template>
               <template v-else> <span v-html="paseLink(msgBody.msg).msg"> </span></template>
             </p>
@@ -219,62 +217,10 @@ const startplayAudio = (msgBody) => {
                 </div>
               </template>
             </div>
-            <!-- 右键点击弹起更多功能栏 -->
-            <template #dropdown>
-              <el-dropdown-menu>
-                <el-dropdown-item
-                  v-if="msgBody.type === ALL_MESSAGE_TYPE.TEXT && isSupported"
-                  @click="copyTextMessages(msgBody.msg)"
-                >
-                  复制
-                </el-dropdown-item>
-                <el-dropdown-item v-if="isMyself(msgBody)" @click="recallMessage(msgBody)">
-                  撤回
-                </el-dropdown-item>
-                <el-dropdown-item
-                  v-if="msgBody.type === ALL_MESSAGE_TYPE.TEXT && isMyself(msgBody)"
-                  @click="showModifyMsgModal(msgBody)"
-                >
-                  编辑
-                </el-dropdown-item>
-                <el-dropdown-item @click="onMsgQuote(msgBody)"> 引用 </el-dropdown-item>
-                <el-dropdown-item @click="deleteMessage(msgBody)"> 删除 </el-dropdown-item>
-                <el-dropdown-item v-if="!isMyself(msgBody)" @click="informOnMessage(msgBody)">
-                  举报
-                </el-dropdown-item>
-              </el-dropdown-menu>
-            </template>
           </el-dropdown>
-          <!-- 引用消息展示框 -->
-          <div
-            class="message_quote_box"
-            v-if="msgBody?.ext?.msgQuote"
-            @click="clickQuoteMessage(msgBody.ext.msgQuote)"
-          >
-            <p>
-              {{ msgBody?.ext?.msgQuote?.msgSender }}:{{ msgBody?.ext?.msgQuote?.msgPreview }}
-            </p>
-          </div>
         </div>
       </div>
-      <!-- 撤回消息通知通知 -->
-      <div v-if="msgBody.isRecall" class="recall_style">
-        {{ isMyself(msgBody) ? '你' : `${msgBody.from}` }}撤回了一条消息<span
-          class="reEdit"
-          v-show="isMyself(msgBody) && msgBody.type === ALL_MESSAGE_TYPE.TEXT"
-          @click="reEdit(msgBody.msg)"
-          >重新编辑</span
-        >
-      </div>
-      <!-- 灰色系统通知 -->
-      <div v-if="msgBody.type === ALL_MESSAGE_TYPE.INFORM" class="inform_style">
-        <p>
-          {{ msgBody.msg }}
-        </p>
-      </div>
     </div>
-    <ReportMessage ref="reportMessage" />
-    <ModifyMessage ref="modifyMessageRef" />
   </div>
 </template>
 

+ 48 - 16
src/views/im/Message/index.vue

@@ -4,6 +4,7 @@ import { messageType } from '@/constant/im'
 /* 组件 */
 import MessageList from './components/messageList/index.vue'
 import InputBox from './components/inputBox/index.vue'
+import * as MessageApi from '@/api/im/message'
 
 const { query } = useRoute() // 查询参数
 
@@ -47,34 +48,70 @@ const messageData = computed(() => [
     id: 1,
     type: ALL_MESSAGE_TYPE.TEXT,
     isRecall: false,
-    time: '1711944000000',
+    time: '1711944110000',
     from: '1',
-    msg: 'Hello, world!',
+    msg: 'Hello, world!111',
     modifiedInfo: {
       operationCount: 1
-    }
+    },
+    customExts: {
+      nickname: '芋道源码',
+      avatar: 'https://avatars.githubusercontent.com/u/2?v=4'
+    },
+    customEvent: {
+      type: '1',
+      data: {
+        type: '1',
+        data: 'https://avatars.githubusercontent.com/u/2?v=4'
+      }
+    },
+    file_length: 0
   },
   {
     id: 2,
     type: ALL_MESSAGE_TYPE.TEXT,
     isRecall: false,
-    time: '1711944001000',
+    time: '1711944221000',
     from: '2',
-    msg: 'Hi, there!',
+    msg: 'Hi, there!222',
     modifiedInfo: {
       operationCount: 0
-    }
+    },
+    customExts: {
+      nickname: '芋道源码',
+      avatar: 'https://avatars.githubusercontent.com/u/2?v=4'
+    },
+    customEvent: {
+      type: '1',
+      data: {
+        type: '1',
+        data: 'https://avatars.githubusercontent.com/u/2?v=4'
+      }
+    },
+    file_length: 0
   },
   {
     id: 3,
     type: ALL_MESSAGE_TYPE.TEXT,
-    isRecall: true,
-    time: '1711944002000',
+    isRecall: false,
+    time: '1711944332000',
     from: '1',
-    msg: 'Hello, world!',
+    msg: 'Hello, world!333',
     modifiedInfo: {
       operationCount: 0
-    }
+    },
+    customExts: {
+      nickname: '芋道源码',
+      avatar: 'https://avatars.githubusercontent.com/u/2?v=4'
+    },
+    customEvent: {
+      type: '1',
+      data: {
+        type: '1',
+        data: 'https://avatars.githubusercontent.com/u/2?v=4'
+      }
+    },
+    file_length: 0
   }
 ])
 
@@ -117,12 +154,7 @@ const messageQuote = (msg) => inputBox.value.handleQuoteMessage(msg)
       <el-scrollbar class="main_container" ref="messageContainer">
         <div class="innerRef">
           <div v-show="isMoreHistoryMsg" class="chat_message_tips">
-            <div
-              v-show="
-                messageData?.length && messageData[0].type !== ALL_MESSAGE_TYPE.OA_NOTIFICATION
-              "
-              class="load_more_msg"
-            >
+            <div v-show="messageData?.length" class="load_more_msg">
               <el-link
                 v-show="!loadingHistoryMsg"
                 :disabled="!isMoreHistoryMsg"

+ 2 - 2
src/views/im/index.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import { ref, defineAsyncComponent } from 'vue'
+import { shallowRef, defineAsyncComponent, DefineComponent } from 'vue'
 import NavBar from './NavBar/index.vue'
 
 // 定义异步加载的组件
@@ -7,7 +7,7 @@ const ConversationComponent = defineAsyncComponent(
   () => import('@/views/im/Conversation/index.vue')
 )
 
-const currentComponent = ref(ConversationComponent) // 默认加载对话组件
+const currentComponent = shallowRef<DefineComponent | null>(ConversationComponent) // 默认加载对话组件
 
 defineOptions({ name: 'IM' })
 </script>