ソースを参照

新增:接收 websocket 消息

安浩浩 1 年間 前
コミット
063a61644a

+ 8 - 3
src/api/im/message/index.ts

@@ -26,17 +26,22 @@ export interface ImMessageRespVO {
   sequence: number // 序号
 }
 
+export interface pullParams {
+  sequence: number
+  size: number
+}
+
 // 发送消息
-export const sendMessage = async (data: ImMessageSendReqVO) => {
+export const sendMessage = async (data: ImMessageSendReqVO): Promise<ImMessageSendRespVO> => {
   return await request.post({ url: `/im/message/send`, data })
 }
 
 // 消息列表-拉取大于 sequence 的消息列表
-export const pullMessageList = async (params: { sequence: number; size: number }) => {
+export const pullMessageList = async (params: pullParams): Promise<ImMessageRespVO[]> => {
   return await request.get({ url: `/im/message/pull`, params })
 }
 
 // 消息列表-根据接收人和发送时间进行分页查询
-export const getMessageList = async (params: any) => {
+export const getMessageList = async (params: any): Promise<ImMessageRespVO[]> => {
   return await request.get({ url: `/im/message/list`, params })
 }

+ 12 - 0
src/layout/components/ImChat/src/ImChat.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { Dialog } from '@/components/Dialog'
 import { shallowRef, defineAsyncComponent, DefineComponent } from 'vue'
+import { webSocketStore } from '@/store/modules/webSocketStore'
 
 // 异步加载可能的对话框内容组件
 const IMComponent = defineAsyncComponent(() => import('@/views/im/index.vue'))
@@ -13,6 +14,17 @@ function openDialog() {
   dialogVisible.value = true
   currentComponent.value = IMComponent // 加载 IM 组件
 }
+// 登录成功后初始化 WebSocket 连接
+const { status, data, initWebSocket } = webSocketStore()
+
+/** 监听接收到的数据 */
+const messageList = ref([] as { time: number; text: string }[]) // 消息列表
+
+// ========== 初始化 =========
+onMounted(() => {
+  // 首次加载 websocket
+  initWebSocket()
+})
 </script>
 
 <template>

+ 26 - 0
src/store/modules/imMessageStore.ts

@@ -0,0 +1,26 @@
+import { defineStore } from 'pinia'
+
+export interface ImMessageWebSocket {
+  id: number // 编号
+  conversationType: number // 会话类型
+  senderId: number // 发送人编号
+  senderNickname: string // 发送人昵称
+  senderAvatar: string // 发送人头像
+  receiverId: number // 接收人编号
+  contentType: number // 内容类型
+  content: string // 内容
+  sendTime: string // 发送时间
+  sequence: number // 序号
+}
+
+export const imMessageStore = defineStore({
+  id: 'imMessage',
+  state: () => ({
+    messages: [] as ImMessageWebSocket[]
+  }),
+  actions: {
+    addMessage(message: ImMessageWebSocket) {
+      this.messages.push(message)
+    }
+  }
+})

+ 81 - 0
src/store/modules/webSocketStore.ts

@@ -0,0 +1,81 @@
+import { defineStore } from 'pinia'
+import { useWebSocket, WebSocketStatus } from '@vueuse/core'
+import { getAccessToken } from '@/utils/auth'
+import { imMessageStore, ImMessageWebSocket } from './imMessageStore'
+
+// 从 imMessageStore 中导入 addMessage 方法
+const { addMessage } = imMessageStore()
+export const webSocketStore = defineStore({
+  id: 'websocket',
+  state: () => ({
+    data: ref(null) as any,
+    status: ref<WebSocketStatus> as any,
+    close: null as ((code?: number | undefined, reason?: string | undefined) => void) | null,
+    open: null as (() => void) | null,
+    send: null as
+      | ((data: string | ArrayBuffer | Blob, useBuffer?: boolean | undefined) => boolean)
+      | null,
+    pingInterval: null as NodeJS.Timeout | null
+  }),
+  actions: {
+    initWebSocket() {
+      const server =
+          (import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
+          '?token=' +
+          getAccessToken(),
+        { data, status, close, open, send } = useWebSocket(server, {
+          autoReconnect: true,
+          heartbeat: true,
+          onMessage(ws, event) {
+            // ws 状态不是 open 时不处理
+            if (ws.readyState !== WebSocket.OPEN) return
+            try {
+              // 1. 收到心跳
+              if (data.value === 'pong') {
+                console.log('websocket 收到心跳包')
+                return
+              }
+              console.log('websocket 收到消息', event.data)
+              // 2.1 解析 type 消息类型
+              const jsonMessage = JSON.parse(data.value)
+              const type = jsonMessage.type
+              const content = JSON.parse(jsonMessage.content)
+              if (!type) {
+                // message.error('未知的消息类型:' + data.value)
+                return
+              }
+              // 2.2 消息类型:demo-message-receive
+              if (type === 'im-message-receive') {
+                const message: ImMessageWebSocket = {
+                  id: content.id,
+                  conversationType: content.conversationType,
+                  senderId: content.senderId,
+                  senderNickname: content.senderNickname,
+                  senderAvatar: content.senderAvatar,
+                  receiverId: content.receiverId,
+                  contentType: content.contentType,
+                  content: content.content,
+                  sendTime: content.sendTime,
+                  sequence: content.sequence
+                }
+
+                // 保存到 pina imMessageStore
+                addMessage(message)
+
+                return
+              }
+            } catch (error) {
+              console.error(error)
+            }
+          }
+        })
+      this.status = status
+      this.data = data
+      this.send = send
+      this.close = close
+      this.open = open
+
+      console.log('websocket 初始化成功')
+    }
+  }
+})

+ 150 - 0
src/views/im/Contacts/components/contactInfo.vue

@@ -0,0 +1,150 @@
+<script setup>
+import { useStore } from 'vuex'
+import router from '@/router'
+import { useRoute } from 'vue-router'
+import { ArrowLeft } from '@element-plus/icons-vue'
+import { messageType } from '@/constant'
+/* 单人头像 */
+import defaultSingleAvatar from '@/assets/imgs/im/avatar/theme2x.png'
+/* store */
+const store = useStore()
+/* route */
+const route = useRoute()
+const { CHAT_TYPE } = messageType
+
+/* 进入会话 */
+const toChatMessage = () => {
+  console.log('>>>>>>>...route.query')
+  router.push({
+    path: '/chat/conversation/message',
+    query: {
+      id: route.query.id,
+      chatType: route.query.chatType
+    }
+  })
+}
+</script>
+
+<template>
+  <div class="app_container">
+    <el-header class="contactInfo_header">
+      <el-page-header style="margin-top: 12px" :icon="ArrowLeft" @click="$router.back(-1)" />
+      <el-divider />
+    </el-header>
+    <el-main class="contactInfo_main">
+      <div class="contactInfo_main_card">
+        <div class="contactInfo_box">
+          <div class="avatar">
+            <el-avatar
+              class="avatar_img"
+              :src="nowContactInfo.avatarurl ? nowContactInfo.avatarurl : defaultSingleAvatar"
+            />
+          </div>
+          <div class="name">
+            <p>
+              {{
+                nowContactInfo.nickname
+                  ? `${nowContactInfo.nickname}(${nowContactInfo.hxId})`
+                  : nowContactInfo.hxId
+              }}
+            </p>
+          </div>
+        </div>
+        <div class="contaactInfo_btn">
+          <el-button type="primary" size="large" @click="toChatMessage">发起会话 </el-button>
+        </div>
+      </div>
+    </el-main>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.app_container {
+  background: #f1f2f4;
+  height: 100%;
+  border-radius: 0 5px 5px 0;
+  overflow: hidden;
+
+  .contactInfo_header {
+    display: flex;
+    flex-direction: column;
+    height: 60px;
+    line-height: 60px;
+  }
+
+  .contactInfo_main {
+    height: 100%;
+
+    .contactInfo_main_card {
+      width: 100%;
+      height: 90%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      margin: 0 auto;
+      border-radius: 5px;
+      transition: all 0.5s;
+
+      &:hover {
+        background: #fff;
+        box-shadow: 12px 12px 2px 1px rgba(125, 125, 126, 0.068);
+      }
+
+      .contactInfo_box {
+        width: 80%;
+        min-height: 500px;
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-start;
+        align-items: center;
+
+        .avatar > .avatar_img {
+          width: 80px;
+          height: 80px;
+        }
+
+        .name {
+          margin-top: 15px;
+          font-size: 22px;
+        }
+
+        .func_box {
+          width: 100%;
+
+          .single_func {
+            height: 100px;
+            // background: #000;
+            margin-top: 25px;
+            cursor: pointer;
+
+            .add_black_list {
+              display: flex;
+              flex-direction: row;
+              align-items: center;
+              justify-content: space-between;
+              font-size: 16px;
+            }
+
+            .del_friend {
+              width: 100%;
+              color: red;
+              transition: all 0.3s;
+            }
+          }
+        }
+      }
+
+      .contaactInfo_btn {
+        width: 80%;
+        text-align: center;
+      }
+    }
+  }
+}
+
+//干掉原有样式里面的竖线
+::v-deep .el-page-header__left::after {
+  width: 0px !important;
+}
+</style>

+ 116 - 0
src/views/im/Contacts/components/friendItem.vue

@@ -0,0 +1,116 @@
+<script setup>
+import { computed } from 'vue'
+import { useStore } from 'vuex'
+// import router from '@/router'
+import { messageType } from '@/constant'
+/* 默认头像 */
+import defaultAvatar from '@/assets/images/avatar/theme2x.png'
+/* store */
+const store = useStore()
+
+//处理friendList进行分类处理
+const classifyFriendList = computed(() => store.getters.sortedFriendList)
+//点击对应联系人跳转至用户详情页
+const { CHAT_TYPE } = messageType
+</script>
+
+<template>
+    <div class="friendItem_container">
+        <div
+            v-for="(friendName, friendItemKey) in classifyFriendList"
+            :key="friendItemKey"
+        >
+            <div class="friend_main">
+                <div class="friend_title">
+                    <p>
+                        {{
+                            friendItemKey === ' '
+                                ? '#'
+                                : friendItemKey.toUpperCase()
+                        }}
+                    </p>
+
+                    <el-divider style="margin: 0" />
+                </div>
+
+                <el-row>
+                    <el-col
+                        class="friendItem_box"
+                        :span="24"
+                        v-for="item in friendName"
+                        :key="item.hxId"
+                        @click="
+                            $emit('toContacts', {
+                                id: item.hxId,
+                                chatType: CHAT_TYPE.SINGLE
+                            })
+                        "
+                    >
+                        <el-avatar
+                            style="margin-right: 11px"
+                            :size="33.03"
+                            :src="
+                                item.avatarurl ? item.avatarurl : defaultAvatar
+                            "
+                        >
+                        </el-avatar>
+                        <span class="friend_name">
+                            {{ item.nickname ? item.nickname : item.hxId }}
+                        </span>
+                    </el-col>
+                </el-row>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.friendItem_box {
+    height: 66px;
+    width: 100%;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: flex-start;
+    // background: #000;
+    padding: 0 22px;
+    background: #efefef;
+    font-weight: 500;
+    font-size: 14px;
+    line-height: 20px;
+    /* identical to box height */
+    text-align: center;
+    color: #333333;
+    cursor: pointer;
+
+    .friend_name {
+        display: inline-block;
+        text-align: left;
+        width: 80%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+    }
+
+    &:hover {
+        background: #dcdcdc;
+    }
+}
+
+.friend_main {
+    width: 100%;
+
+    .friend_title {
+        width: 100%;
+        height: 32px;
+        mix-blend-mode: normal;
+        opacity: 0.21;
+        font-size: 14px;
+        padding-left: 23px;
+        font-weight: 400;
+        font-size: 12px;
+        line-height: 32px;
+        letter-spacing: 0.342857px;
+    }
+}
+</style>

+ 29 - 4
src/views/im/Contacts/index.vue

@@ -1,5 +1,30 @@
-<script setup lang="ts"></script>
+<template>
+  <el-container style="height: 100%">
+    <el-aside class="contacts_box">
+      <SearchInput :searchType="'contacts'" />
+      <el-scrollbar class="contacts_collapse" tag="div" :always="false">
+        <!-- 联系人群组列表 -->
+        <el-collapse />
+      </el-scrollbar>
+    </el-aside>
+    <el-main class="contacts_infors_main_box" />
+  </el-container>
+</template>
+<script lang="ts" setup>
+/* 相关组件 */
+import { SearchInput } from '@/components/Im/SearchInput'
+import * as UserApi from '@/api/system/user'
 
-<template></template>
-
-<style scoped lang="scss"></style>
+//好友列表
+const friendList = computed(() => {})
+const getUserList = async () => {
+  const data = await UserApi.getSimpleUserList()
+  console.log('data', data)
+  friendList.value = data
+}
+/** 初始化 */
+onMounted(() => {
+  getUserList()
+})
+</script>
+<style lang="scss" scoped></style>

+ 2 - 2
src/views/im/Message/components/inputBox/index.vue

@@ -116,9 +116,9 @@ const sendTextMessage = _.debounce(async () => {
   messageQuoteRef.value?.clearQuoteContent()
   try {
     console.log('imMessageSendReqVO', imMessageSendReqVO)
-    await MessageApi.sendMessage(imMessageSendReqVO)
+    const imMessageSendRespVO = await MessageApi.sendMessage(imMessageSendReqVO)
+    console.log('>>>>>发送成功', imMessageSendRespVO)
   } catch (error) {
-    //handleSDKErrorNotifi(error.type, error.message)
     console.log('>>>>>>>发送失败+++++++', error)
   } finally {
     isAtAll.value = false

+ 19 - 105
src/views/im/Message/components/messageList/index.vue

@@ -25,21 +25,20 @@ const props = defineProps({
 })
 const { nowPickInfo } = toRefs(props)
 const { messageData } = toRefs(props)
+console.log('>>>>>messageData', messageData)
 /* 处理时间显示间隔 */
-const handleMsgTimeShow = (time, index) => {
-  console.log('>>>>>时间显示', time, index)
+const handleMsgTimeShow = (sendTime, index) => {
   const msgList = Array.from(messageData.value)
   if (index !== 0) {
-    const lastTime = msgList[index - 1].time
-    console.log('>>>>>时间间隔', time - lastTime, time, lastTime)
-    return time - lastTime > 50000 ? formatDate(time, 'MM/DD/HH:mm') : ''
+    const lastTime = msgList[index - 1].sendTime
+    return sendTime - lastTime > 50000 ? formatDate(sendTime, 'MM/DD/HH:mm') : ''
   } else {
-    return formatDate(time, 'MM/DD/HH:mm')
+    return formatDate(sendTime, 'MM/DD/HH:mm')
   }
 }
 /* computed-- 消息来源是否为自己 */
 const isMyself = (msgBody) => {
-  return msgBody.from === '1'
+  return msgBody.senderId === userStore.user.id || msgBody.receiverId === userStore.user.id
 }
 /* 文本中是否包含link */
 const isLink = computed(() => {
@@ -51,15 +50,11 @@ const isLink = computed(() => {
 const loginUserInfo = {
   avatarurl: avatar.value
 }
-/* 获取他人的用户信息 */
-const otherUserInfo = (from) => {
-  return {
-    avatarurl: 'https://avatars.githubusercontent.com/u/2?v=4'
-  }
-}
 //处理聊天对方昵称展示
-const handleNickName = (from) => {
-  return from === '1' ? '我' : '对方'
+const handleNickName = (msgBody) => {
+  return msgBody.senderId === userStore.user.id || msgBody.receiverId === userStore.user.id
+    ? '我'
+    : '对方'
 }
 //引用消息
 let clickQuoteMsgId = ref('')
@@ -102,121 +97,40 @@ const startplayAudio = (msgBody) => {
     >
       <!-- 普通消息气泡 -->
       <div
-        v-if="!msgBody.isRecall && msgBody.type !== ALL_MESSAGE_TYPE.OA_NOTIFICATION"
+        v-if="msgBody.conversationType !== 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.sendTime, index) }}
         </div>
-        <el-avatar
-          class="message_item_avator"
-          :src="
-            isMyself(msgBody)
-              ? loginUserInfo.avatarurl
-              : otherUserInfo(msgBody.from).avatarurl || defaultAvatar
-          "
-        />
+        <el-avatar class="message_item_avator" :src="loginUserInfo.avatarurl" />
         <!-- 普通消息内容 -->
         <div class="message_box_card">
           <span v-show="!isMyself(msgBody)" class="message_box_nickname">{{
-            handleNickName(msgBody.from)
+            handleNickName(msgBody)
           }}</span>
           <el-dropdown
             class="message_box_content"
-            :class="[
-              isMyself(msgBody) ? 'message_box_content_mine' : 'message_box_content_other',
-              clickQuoteMsgId === msgBody.id && 'quote_msg_avtive'
-            ]"
+            :class="[isMyself(msgBody) ? 'message_box_content_mine' : 'message_box_content_other']"
             trigger="contextmenu"
             placement="bottom-end"
           >
             <!-- 文本类型消息 -->
             <p
               style="padding: 10px; line-height: 20px"
-              v-if="msgBody.type === ALL_MESSAGE_TYPE.TEXT"
+              v-if="msgBody.contentType === ALL_MESSAGE_TYPE.TEXT"
             >
-              <template v-if="!isLink(msgBody.msg)">
-                {{ msgBody.msg }}
+              <template v-if="!isLink(msgBody.content)">
+                {{ msgBody.content }}
               </template>
-              <template v-else> <span v-html="paseLink(msgBody.msg).msg"> </span></template>
+              <template v-else> <span v-html="paseLink(msgBody.content).msg"> </span></template>
             </p>
             <!-- 图片类型消息 -->
-            <!-- <div> -->
-            <el-image
-              v-if="msgBody.type === ALL_MESSAGE_TYPE.IMAGE"
-              style="border-radius: 5px"
-              :src="msgBody.thumb"
-              :preview-src-list="[msgBody.url]"
-              :initial-index="1"
-              fit="cover"
-            />
-            <!-- </div> -->
             <!-- 语音类型消息 -->
-            <div
-              :class="[
-                'message_box_content_audio',
-                isMyself(msgBody)
-                  ? 'message_box_content_audio_mine'
-                  : 'message_box_content_audio_other'
-              ]"
-              v-if="msgBody.type === ALL_MESSAGE_TYPE.AUDIO"
-              @click="startplayAudio(msgBody)"
-              :style="`width:${msgBody.length * 10}px`"
-            >
-              <span class="audio_length_text"> {{ msgBody.length }}′′ </span>
-              <div
-                :class="[
-                  isMyself(msgBody) ? 'play_audio_icon_mine' : 'play_audio_icon_other',
-                  audioPlayStatus.playMsgId === msgBody.id && 'start_play_audio'
-                ]"
-                style="background-size: 100% 100%"
-              ></div>
-            </div>
-            <div v-if="msgBody.type === ALL_MESSAGE_TYPE.LOCAL">
-              <p style="padding: 10px">[暂不支持位置消息展示]</p>
-            </div>
             <!-- 文件类型消息 -->
-            <div v-if="msgBody.type === ALL_MESSAGE_TYPE.FILE" class="message_box_content_file">
-              <div class="file_text_box">
-                <div class="file_name">
-                  {{ msgBody.filename }}
-                </div>
-                <div class="file_size">
-                  {{ fileSizeFormat(msgBody.file_length) }}
-                </div>
-                <a class="file_download" :href="msgBody.url" download>点击下载</a>
-              </div>
-              <span class="iconfont icon-wenjian"></span>
-            </div>
-            <!-- 自定义类型消息 -->
-            <div v-if="msgBody.type === ALL_MESSAGE_TYPE.CUSTOM" class="message_box_content_custom">
-              <template v-if="msgBody.customEvent && CUSTOM_TYPE[msgBody.customEvent]">
-                <div class="user_card">
-                  <div class="user_card_main">
-                    <!-- 头像 -->
-                    <el-avatar
-                      shape="circle"
-                      :size="50"
-                      :src="
-                        (msgBody.customExts && msgBody.customExts.avatarurl) ||
-                        msgBody.customExts.avatar ||
-                        defaultAvatar
-                      "
-                      fit="cover"
-                    />
-                    <!-- 昵称 -->
-                    <span class="nickname">{{
-                      (msgBody.customExts && msgBody.customExts.nickname) || msgBody.customExts.uid
-                    }}</span>
-                  </div>
-                  <el-divider style="margin: 5px 0; border-top: 1px solid black" />
-                  <p style="font-size: 8px">个人名片</p>
-                </div>
-              </template>
-            </div>
           </el-dropdown>
         </div>
       </div>

+ 18 - 74
src/views/im/Message/index.vue

@@ -5,6 +5,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'
+import { ImMessageRespVO } from '@/api/im/message'
 
 const { query } = useRoute() // 查询参数
 
@@ -25,10 +26,10 @@ const delTheFriend = () => {
 }
 // 当前聊天对象信息
 const nowPickInfo = ref({
-  id: 1,
+  id: 100,
   chatType: CHAT_TYPE.SINGLE,
   userInfo: {
-    nickname: '芋道源码',
+    nickname: '芋道',
     userStatus: '1'
   },
   groupDetail: {
@@ -42,78 +43,16 @@ const nowPickInfo = ref({
 const groupDetail = computed(() => {
   return nowPickInfo.value.groupDetail
 })
-//获取其id对应的消息内容
-const messageData = computed(() => [
-  {
-    id: 1,
-    type: ALL_MESSAGE_TYPE.TEXT,
-    isRecall: false,
-    time: '1711944110000',
-    from: '1',
-    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: '1711944221000',
-    from: '2',
-    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: false,
-    time: '1711944332000',
-    from: '1',
-    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
-  }
-])
+//获取对应的消息内容
+const pullParams = reactive({
+  sequence: 0,
+  size: 100
+})
+const messageData = ref([])
+const getMessageData = async () => {
+  messageData.value = await MessageApi.pullMessageList(pullParams)
+}
+console.log(messageData)
 
 /* 消息相关 */
 const loadingHistoryMsg = ref(false) //是否正在加载中
@@ -124,6 +63,7 @@ const fechHistoryMessage = (loadType) => {
   console.log(loadType)
   console.log('加载更多')
   loadingHistoryMsg.value = true
+  getMessageData()
   setTimeout(() => {
     loadingHistoryMsg.value = false
   }, 1000)
@@ -137,6 +77,10 @@ const inputBox = ref(null)
 const reEditMessage = (msg) => (inputBox.value.textContent = msg)
 //消息引用
 const messageQuote = (msg) => inputBox.value.handleQuoteMessage(msg)
+/** 初始化 **/
+onMounted(() => {
+  getMessageData()
+})
 </script>
 
 <template>

+ 12 - 14
src/views/im/index.vue

@@ -1,17 +1,3 @@
-<script lang="ts" setup>
-import { shallowRef, defineAsyncComponent, DefineComponent } from 'vue'
-import NavBar from './NavBar/index.vue'
-
-// 定义异步加载的组件
-const ConversationComponent = defineAsyncComponent(
-  () => import('@/views/im/Conversation/index.vue')
-)
-
-const currentComponent = shallowRef<DefineComponent | null>(ConversationComponent) // 默认加载对话组件
-
-defineOptions({ name: 'IM' })
-</script>
-
 <template>
   <div class="app-container">
     <el-container class="chat_container">
@@ -24,7 +10,19 @@ defineOptions({ name: 'IM' })
     </el-container>
   </div>
 </template>
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent, DefineComponent } from 'vue'
+import NavBar from './NavBar/index.vue'
+
+defineOptions({ name: 'IM' })
 
+// 定义异步加载的组件
+const conversationComponent = defineAsyncComponent(
+  () => import('@/views/im/Conversation/index.vue')
+)
+
+const currentComponent = shallowRef<DefineComponent | null>(conversationComponent) // 默认加载对话组件
+</script>
 <style lang="scss" scoped>
 .app-container {
   position: fixed;