Ver Fonte

实时消息弹出

刘洋 há 2 anos atrás
pai
commit
d1e4545f67

+ 38 - 9
src/components/shared/message/Message.vue

@@ -2,11 +2,7 @@
   <message-component>
     <div ref="messageIcon" v-bind="$attrs" class="message-icon">
       <span v-show="unReadMessages?.newCount" class="un-read-num">
-        {{
-          Math.min(unReadMessages?.newCount || 0, 99) > 99
-            ? Math.min(unReadMessages?.newCount || 0, 99) + '+'
-            : Math.min(unReadMessages?.newCount || 0, 99)
-        }}
+        {{ (unReadMessages?.newCount || 0) > 99 ? unReadMessages?.newCount + '+' : unReadMessages?.newCount }}
       </span>
       <svg-icon name="message"></svg-icon>
     </div>
@@ -58,12 +54,12 @@
 
 <script setup lang="ts" name="Message">
 /** 头部消息组件 */
-import { defineComponent, withDefaults, ref, useSlots, watch, inject } from 'vue'
+import { defineComponent, withDefaults, ref, useSlots, watch, inject, ShallowRef } from 'vue'
 import { ElPopover } from 'element-plus'
 import dayjs from 'dayjs'
 import useVW from '@/hooks/useVW'
 import useVModel from '@/hooks/useVModel'
-import useMessageLoop from '@/hooks/useMessageLoop'
+import useMessageLoop, { lastMsgs, setLastMsgs } from '@/hooks/useMessageLoop'
 import useMainStore from '@/store/main'
 import MessageWindow from '@/components/shared/message/MessageWindow.vue'
 import ConfirmButton from '@/components/common/ConfirmButton.vue'
@@ -98,6 +94,39 @@ const setReplyUserId = inject<(replyUserId: number | null) => void>('setReplyUse
 const messageIcon = ref<HTMLDivElement>()
 
 const unReadMessages = useMessageLoop()
+watch(
+  () => (unReadMessages as ShallowRef).value,
+  (val) => {
+    console.log(val)
+    if (!visibleMessageWindow.value) {
+      let newMsgs = val.messages
+      if (!newMsgs.length) {
+        return
+      }
+      if (!lastMsgs.messages.length) {
+        messageWindowType.value = 'view'
+        visibleMessageWindow.value = true
+        return
+      }
+      let recentMsgTime = Math.max.apply(
+        Math,
+        lastMsgs.messages.map((item) => {
+          return new Date(item.sendTime).getTime()
+        })
+      )
+      let newMsgTime = Math.max.apply(
+        Math,
+        newMsgs.map((item: any) => {
+          return new Date(item.sendTime).getTime()
+        })
+      )
+      if (newMsgTime > recentMsgTime) {
+        messageWindowType.value = 'view'
+        visibleMessageWindow.value = true
+      }
+    }
+  }
+)
 
 const messageWindowType = useVModel(props, 'type')
 
@@ -150,8 +179,8 @@ const onSendMessage = () => {
     width: 24px;
     height: 24px;
     line-height: 24px;
-    right: -12px;
-    top: -12px;
+    right: -15px;
+    top: -15px;
     text-align: center;
     color: $color--white;
     font-size: 10px;

+ 18 - 2
src/components/shared/message/MessageList.vue

@@ -46,18 +46,21 @@
 
 <script setup lang="ts" name="MessageList">
 /** 消息列表*/
-import { ref, watch } from 'vue'
+import { ref, watch, onUnmounted } from 'vue'
 import { ElButton, ElIcon } from 'element-plus'
 import dayjs from 'dayjs'
 import { Close } from '@element-plus/icons-vue'
 import useFetch from '@/hooks/useFetch'
 import MessageHistory from '@/components/shared/message/MessageHistory.vue'
 import ImagePreview from '../ImagePreview.vue'
+import useMainStore from '@/store/main'
+import uesFetch from '@/hooks/useFetch'
+import { setLastMsgs } from '@/hooks/useMessageLoop'
 
 import type { ExtractApiResponse } from '@/api/api'
 
 type MessageType = ExtractArrayValue<ExtractApiResponse<'getMessageList'>>
-
+const mainStore = useMainStore()
 const emits = defineEmits(['close', 'change-type', 'reply'])
 
 /** 图片预览 */
@@ -109,6 +112,19 @@ const onContentClick = (e: Event) => {
 }
 
 getMessageList().then((result) => (currentMessage.value = result?.[0]))
+watch(
+  () => mainStore.newMsgs,
+  () => {
+    getMessageList()
+  }
+)
+onUnmounted(() => {
+  uesFetch('getUnReadMessage')
+    .fetch()
+    .then((res) => {
+      setLastMsgs(res)
+    })
+})
 </script>
 
 <style scoped lang="scss">

+ 6 - 3
src/components/shared/message/MessageSend.vue

@@ -78,7 +78,7 @@ const replyUserId = useVModel(props, 'replyUserId')
 const previewModalVisible = ref<boolean>(false)
 
 /** 显示收件人tree */
-const showCheckUser = ref<boolean>(true)
+const showCheckUser = ref<boolean>(false)
 
 /** 消息内容 */
 const messageContent = ref<string>('')
@@ -202,7 +202,8 @@ const onSendMessage = async () => {
       receiveUserIds: checkedUsers.value?.filter(Boolean)?.map((u) => u.id),
     })
     ElMessage.success('发送成功')
-    emit('close')
+    messageContent.value = ''
+    // emit('close')
   } catch (error) {
     console.error(error)
   }
@@ -214,6 +215,7 @@ getUserGroup()
 <style scoped lang="scss">
 .message-list-modal {
   background-color: transparent;
+  width: 880px;
   .tree-box {
     width: 280px;
     height: 446px;
@@ -228,7 +230,8 @@ getUserGroup()
     box-shadow: 0px 6px 6px 0px rgba(0, 0, 0, 0.1);
   }
   .message-info-container {
-    width: 600px;
+    // width: 600px;
+    flex: 1;
     .message-info {
       height: 446px;
       background-color: $color--white;

+ 21 - 2
src/hooks/useMessageLoop.ts

@@ -5,6 +5,20 @@ import useMainStore from '@/store/main'
 import type { EffectScope, ShallowRef } from 'vue'
 import type { ExtractApiResponse } from '@/api/api'
 
+interface Msg {
+  newCount: number
+  messages: any[]
+}
+
+export const lastMsgs: Msg = {
+  newCount: 0,
+  messages: [],
+}
+export const setLastMsgs = (res: Msg) => {
+  lastMsgs.newCount = res.newCount
+  lastMsgs.messages = res.messages
+}
+
 const useMessageLoop = () => {
   const mainStore = useMainStore()
 
@@ -22,9 +36,14 @@ const useMessageLoop = () => {
   const getUnReadMessageFn = () => {
     getUnReadMessage()
     cleanTimer()
-    timer = window.setTimeout(getUnReadMessageFn, 30 * 1000)
+    timer = window.setTimeout(getUnReadMessageFn, 6 * 1000)
   }
-
+  watch(
+    () => unReadMessage.value,
+    (val: Msg) => {
+      mainStore.setNewMsgs(val)
+    }
+  )
   watch(
     () => mainStore?.myUserInfo?.role,
     () => {

+ 6 - 0
src/store/main.ts

@@ -11,12 +11,14 @@ interface MainStoreState {
   loginInfo?: ExtractApiResponse<'userLogin'>
   myUserInfo?: ExtractApiResponse<'getMyUserInfo'>
   userMarkConfig: ExtractApiResponse<'getUserMarkConfig'>
+  newMsgs: { newCount: number; messages: any[] }
 }
 
 interface MainStoreActions {
   getMyUserInfo: () => Promise<ExtractApiResponse<'getMyUserInfo'> | undefined>
   getUserMarkConfig: () => Promise<ExtractApiResponse<'getUserMarkConfig'> | undefined>
   setUserMarkConfig: (config: ExtractApiResponse<'getUserMarkConfig'>) => void
+  setNewMsgs: (msgData: { newCount: number; messages: any[] }) => void
 }
 
 const useMainStore = defineStore<'main', MainStoreState, Record<string, any>, MainStoreActions>('main', {
@@ -36,9 +38,13 @@ const useMainStore = defineStore<'main', MainStoreState, Record<string, any>, Ma
       myUserInfo: void 0,
       /** 用户配置信息 */
       userMarkConfig: {},
+      newMsgs: { newCount: 0, messages: [] },
     }
   },
   actions: {
+    setNewMsgs(msgData) {
+      this.newMsgs = msgData
+    },
     async getMyUserInfo() {
       try {
         this.myUserInfo = await useFetch('getMyUserInfo').fetch()