Răsfoiți Sursa

feat: 取消轮播卡片时将卡片置为已读的监听

zhouyuhao 8 luni în urmă
părinte
comite
8a5ebc3016

+ 39 - 26
src/components/NotificationMessageCard/src/NotificationMessageCard.vue

@@ -5,9 +5,15 @@ import FeatureUpdateCard from './components/FeatureUpdateCard.vue'
 import { useNotificationMessage } from '@/stores/modules/notificationMessage'
 
 const notificationMsgStore = useNotificationMessage()
-const props = defineProps<{
-  data: any
-}>()
+const props = withDefaults(
+  defineProps<{
+    data: any
+    isObserver?: boolean
+  }>(),
+  {
+    isObserver: true
+  }
+)
 
 const emit = defineEmits<{ seeAll: [] }>()
 const handleSeeAll = () => {
@@ -54,25 +60,26 @@ const watchCards = () => {
   })
 }
 
-watch(
-  () => props.data,
-  () => {
-    nextTick(() => {
-      setTimeout(() => {
-        watchCards()
-      }, 500)
-    })
-  },
-  {
-    immediate: true,
-    deep: true
-  }
-)
+if (props.isObserver) {
+  watch(
+    () => props.data,
+    () => {
+      nextTick(() => {
+        setTimeout(() => {
+          watchCards()
+        }, 500)
+      })
+    },
+    {
+      immediate: true,
+      deep: true
+    }
+  )
+}
 
 const clearReadData = () => {
-  const idsToRemove = new Set(props.data.map((item: any) => item.info.id))
-  const filteredId = notificationMsgStore.notificationMsgList.filter((id) => idsToRemove.has(id))
-  notificationMsgStore.removeNotificationMsgList(filteredId)
+  const idsToRemove = props.data.map((item: any) => item.info.id)
+  notificationMsgStore.removeNotificationMsgList(idsToRemove)
 
   // 清除当前页面的所有卡片的监听
   curPageAllCards.value.forEach((card: any) => {
@@ -83,13 +90,18 @@ const clearReadData = () => {
 // 定时将消息卡片未读的置为已读
 let timer = null
 onMounted(() => {
-  timer = setInterval(() => {
-    notificationMsgStore.markMessageAsRead()
-  }, 300000)
+  if (props.isObserver) {
+    timer = setInterval(() => {
+      notificationMsgStore.markMessageAsRead()
+    }, 300000)
+  }
 })
 onUnmounted(() => {
-  clearInterval(timer)
-  clearReadData()
+  if (props.isObserver) {
+    notificationMsgStore.markMessageAsRead()
+    clearReadData()
+    clearInterval(timer)
+  }
 })
 </script>
 
@@ -99,11 +111,12 @@ onUnmounted(() => {
     :data-card-id="item.info.id"
     :data-card-isread="item.info.isRead"
     v-for="item in data"
-    :key="item.info.id"
+    :key="item.info.id || Math.random()"
   >
     <EventCard @seeAll="handleSeeAll" v-if="item.notificationType === 'event'" :data="item.info" />
     <PasswordCard v-else-if="item.notificationType === 'password'" :data="item.info" />
     <FeatureUpdateCard v-else-if="item.notificationType === 'feature'" :data="item.info" />
+    <slot></slot>
   </div>
 </template>
 

+ 1 - 1
src/router/index.ts

@@ -8,7 +8,7 @@ const router = createRouter({
     {
       path: '/',
       name: 'Home',
-      redirect: '/dashboard',
+      redirect: '/booking',
       component: () => import('../views/Layout'),
       children: [
         {

+ 16 - 19
src/stores/modules/notificationMessage.ts

@@ -20,12 +20,15 @@ export const useNotificationMessage = defineStore('notificationMessage', {
     },
     removeNotificationMsgList(array: any[]) {
       this.notificationMsgList = this.notificationMsgList.filter((item) => !array.includes(item))
+
       localStorage.setItem('notificationMsgList', JSON.stringify(this.notificationMsgList))
     },
     setReadCardMap(id: string) {
+      // 将页面中从未读到已读的消息id存入readCardMap
       if (this.readCardMap.includes(id)) return
       this.readCardMap.push(id)
       localStorage.setItem('readCardMap', JSON.stringify(this.readCardMap))
+      // 将已读的消息从notificationMsgList中删除
       this.notificationMsgList = this.notificationMsgList.filter((item) => {
         return !this.readCardMap.includes(item)
       })
@@ -34,32 +37,26 @@ export const useNotificationMessage = defineStore('notificationMessage', {
     hasUnreadMessages() {
       $api.hasUnreadMessages().then((res) => {
         if (res.code === 200) {
-          // this.hasNewMsg = res.data.has_message
-          this.hasNewMsg = false
+          this.hasNewMsg = res.data.has_message
           localStorage.setItem('hasNewMsg', JSON.stringify(this.hasNewMsg))
         }
       })
     },
-    markMessageAsRead() {
+    async markMessageAsRead() {
       if (this.readCardMap.length === 0) return
+      console.log('置为已读')
+      this.readCardMap = []
+      localStorage.setItem('readCardMap', JSON.stringify(this.readCardMap))
 
-      // this.readCardMap = []
-      // localStorage.setItem('readCardMap', JSON.stringify(this.readCardMap))
+      // await $api.setMessageRead({ id: this.readCardMap }).then((res) => {
+      //   if (res.code === 200) {
+      //     this.readCardMap = []
+      //     localStorage.setItem('readCardMap', JSON.stringify(this.readCardMap))
 
-      // { id: this.readCardMap }
-      $api.setMessageRead().then((res) => {
-        if (res.code === 200) {
-          this.readCardMap = []
-          localStorage.setItem('readCardMap', JSON.stringify(this.readCardMap))
-
-          this.notificationMsgList = this.notificationMsgList.filter(
-            (item) => !this.readCardMap.includes(item.id)
-          )
-          localStorage.setItem('notificationMsgList', JSON.stringify(this.notificationMsg))
-          // 在将消息标记为已读后,再次检查是否有新消息
-          this.hasUnreadMessages()
-        }
-      })
+      //     // 在将消息标记为已读后,再次检查是否有新消息
+      //     this.hasUnreadMessages()
+      //   }
+      // })
     },
     clearData() {
       this.notificationMsgList = []

+ 19 - 64
src/views/Layout/src/components/Header/components/NotificationDrawer.vue

@@ -1,7 +1,9 @@
 <script setup lang="ts">
 import NotificationMessageCard from '@/components/NotificationMessageCard/src/NotificationMessageCard.vue'
 import { useRouter } from 'vue-router'
+import { useNotificationMessage } from '@/stores/modules/notificationMessage'
 
+const notificationMsgStore = useNotificationMessage()
 const router = useRouter()
 const loading = ref(false)
 
@@ -17,68 +19,6 @@ const notificationTypeList = ref({
 })
 
 const notificationList = ref<any[]>([])
-// const notificationList = [
-//   {
-//     notificationType: 'feature',
-//     info: {
-//       isRead: true,
-//       title: 'Feature Update',
-//       header: 'New feature online: Quick search has been released!',
-//       content:
-//         'We are pleased to announce that the quick search function is now officially online! You can now quickly find what you need by entering keywords, greatly improving your work efficiency. Go and experience it!'
-//     }
-//   },
-//   {
-//     notificationType: 'event',
-//     info: {
-//       type: 'milestone',
-//       isMultiple: true,
-//       numericRecords: 3,
-//       isRead: true,
-//       title: 'Milestone Update',
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       time: 'Jan 10, 2025 14:30 UTC+8',
-//       info: {
-//         route: ['Hong Kong', 'Shanghai', 'Ningbo']
-//       }
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       title: 'Password Notifications',
-//       isExpiration: true,
-//       tips: 'Password Expiration in 311 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       isRead: false,
-//       title: 'Password Notifications',
-//       isExpiration: false,
-//       tips: 'Password Expiration in 3 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       isRead: true,
-//       title: 'Password Notifications',
-//       isExpiration: true,
-//       tips: 'Password Expiration in 31111 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   }
-// ]
 
 const getNotificationList = () => {
   loading.value = true
@@ -124,19 +64,33 @@ const handleSettingMessage = () => {
   })
 }
 
-const clearData = () => {
+const closeDrawer = () => {
+  const idsToRemove = notificationList.value.map((item) => item.info.id)
+  notificationMsgStore.removeNotificationMsgList(idsToRemove)
+
+  notificationMsgStore.markMessageAsRead()
+  clearInterval(timer)
+
   notificationList.value = []
   notificationType.value = 'all'
 }
 
 const notificationListRef = ref<HTMLElement | null>(null)
+
+// 定时将消息卡片未读的置为已读
+let timer = null
+onMounted(() => {
+  timer = setInterval(() => {
+    notificationMsgStore.markMessageAsRead()
+  }, 300000)
+})
 </script>
 
 <template>
   <el-drawer
     ref="drawerRef"
     @open="getNotificationList"
-    @closed="clearData"
+    @closed="closeDrawer"
     class="notice-drawer"
     size="432px"
   >
@@ -304,6 +258,7 @@ div.layout-toolbar {
       top: 0;
       height: 40px;
       padding: 0 16px;
+      z-index: 3;
       line-height: 40px;
       background-color: var(--color-dialog-body-bg);
       border-bottom: 1px solid var(--color-border);

+ 9 - 109
src/views/Layout/src/components/Header/components/TrainingCard.vue

@@ -2,113 +2,10 @@
 import { onBeforeRouteUpdate } from 'vue-router'
 import NotificationMessageCard from '@/components/NotificationMessageCard/src/NotificationMessageCard.vue'
 import { useUserStore } from '@/stores/modules/user'
-import { useNotificationMessage } from '@/stores/modules/notificationMessage'
 import dayjs from 'dayjs'
 
 const userStore = useUserStore()
-const notificationMsgStore = useNotificationMessage()
 const notificationList = ref([])
-// const notificationList = [
-//   {
-//     notificationType: 'feature',
-//     info: {
-//       title: 'Feature Update',
-//       header: 'New feature online: Quick search has been released!',
-//       content:
-//         'We are pleased to announce that the quick search function is now officially online! You can now quickly find what you need by entering keywords, greatly improving your work efficiency. Go and experience it!'
-//     }
-//   },
-//   {
-//     notificationType: 'event',
-//     info: {
-//       type: 'milestone',
-//       isMultiple: true,
-//       numericRecords: 3,
-//       isRead: true,
-//       title: 'Milestone Update',
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       time: 'Jan 10, 2025 14:30 UTC+8'
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       title: 'Password Notifications',
-//       isExpiration: true,
-//       tips: 'Password Expiration in 311 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       title: 'Password Notifications',
-//       isExpiration: false,
-//       tips: 'Password Expiration in 3 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   },
-//   {
-//     notificationType: 'password',
-//     info: {
-//       title: 'Password Notifications',
-//       isExpiration: true,
-//       tips: 'Password Expiration in 31111 Days',
-//       content:
-//         'Your password will expire in 7 days. To ensure the security of your account, please change your password as soon as possible.'
-//     }
-//   },
-//   {
-//     notificationType: 'event',
-//     info: {
-//       type: 'milestone',
-//       isMultiple: true,
-//       numericRecords: 3,
-//       isRead: true,
-//       title: 'Milestone Update 1',
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       time: 'Jan 10, 2025 14:30 UTC+8'
-//     }
-//   },
-//   {
-//     notificationType: 'event',
-//     info: {
-//       type: 'milestone',
-//       isMultiple: true,
-//       numericRecords: 3,
-//       isRead: true,
-//       title: 'Milestone Update 2',
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       time: 'Jan 10, 2025 14:30 UTC+8'
-//     }
-//   },
-//   {
-//     notificationType: 'event',
-//     info: {
-//       type: 'milestone',
-//       isMultiple: true,
-//       numericRecords: 3,
-//       isRead: true,
-//       title: 'Milestone Update 3',
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       time: 'Jan 10, 2025 14:30 UTC+8'
-//     }
-//   }
-// ]
 
 const curCard = computed(() => {
   return notificationList.value[curIndex.value] || null
@@ -121,20 +18,19 @@ let trainingIntervalId = null
 let newMessageIntervalId = null
 // 轮询最新未读消息
 const pollingNewMessage = () => {
-  if (newMessageIntervalId) return
   // 每隔5分钟轮询一次
   newMessageIntervalId = setInterval(() => {
     getNotificationList(dayjs().format('MM/DD/YYYY HH:mm:ss'))
   }, 300000)
 }
+pollingNewMessage()
 
 // 登录后自动轮播消息
 const trainingCardAfterLogin = () => {
   curIndex.value = curIndex.value + 1
-  // 如果到达最后一个消息,设置为null以清除显示
+  // 如果消息展示完毕,清除定时器
   if (curIndex.value >= notificationList.value.length) {
     clearInterval(trainingIntervalId)
-    pollingNewMessage()
   }
 }
 
@@ -172,6 +68,7 @@ onBeforeRouteUpdate((to, from, next) => {
   if (to.name === 'Login') {
     clearInterval(trainingIntervalId)
     clearInterval(newMessageIntervalId)
+    newMessageIntervalId = null
   }
   next()
 })
@@ -202,7 +99,6 @@ const closeMessage = () => {
   if (!newMessageIntervalId) {
     clearInterval(trainingIntervalId)
     curIndex.value = -1
-    pollingNewMessage()
     return
   }
 
@@ -216,7 +112,7 @@ const closeMessage = () => {
     trainingIntervalId = setInterval(nextNotification, 2000)
   }
   // 将当前消息标记为已读
-  notificationMsgStore.setReadCardMap(curCard.value?.info?.id)
+  // notificationMsgStore.setReadCardMap(curCard.value?.info?.id)
 }
 </script>
 
@@ -229,7 +125,11 @@ const closeMessage = () => {
     >
       <span class="font_family icon-icon_reject_b"></span>
     </el-button>
-    <NotificationMessageCard v-if="curCard" :data="[curCard]"></NotificationMessageCard>
+    <NotificationMessageCard
+      :isObserver="false"
+      v-if="curCard"
+      :data="[curCard]"
+    ></NotificationMessageCard>
   </div>
 </template>
 

+ 38 - 36
src/views/SystemMessage/src/SystemMessage.vue

@@ -30,20 +30,10 @@ const notificationTypeList = ref({
 const setActiveItem = (item: string) => {
   activeItem.value = item
   activeName.value = 'All Notifications'
-  // if (activeItem.value === 'Feature Update') {
-  //   notificationList.value = [
-  //     {
-  //       notificationType: 'feature',
-  //       info: {
-  //         title: 'Feature Update',
-  //         header: 'New feature online: Quick search has been released!',
-  //         content:
-  //           'We are pleased to announce that the quick search function is now officially online! You can now quickly find what you need by entering keywords, greatly improving your work efficiency. Go and experience it!'
-  //       }
-  //     }
-  //   ]
-  //   return
-  // }
+
+  const idsToRemove = notificationList.value.map((item) => item.info.id)
+  notificationMsgStore.removeNotificationMsgList(idsToRemove)
+
   getNotificationList()
 }
 
@@ -55,25 +45,35 @@ const unreadNotificationList = computed(() => {
 const readNotificationList = computed(() => {
   return notificationList.value.filter((item) => item.info.isRead)
 })
-const getNotificationList = () => {
+const getNotificationList = async () => {
   loading.value = true
   const rulesType = Object.entries(notificationTypeList.value).find(
     (item) => item[1] === activeItem.value
   )?.[0]
-  $api
-    .getSystemMessageData({
-      rules_type: rulesType
-    })
-    .then((res) => {
-      if (res.code === 200) {
-        const data = res.data
-        notificationList.value = data.cardList
-        tabCountList.value = data.countList
-      }
-    })
-    .finally(() => {
-      loading.value = false
-    })
+  try {
+    await notificationMsgStore.markMessageAsRead()
+    $api
+      .getSystemMessageData({
+        rules_type: rulesType
+      })
+      .then((res) => {
+        if (res.code === 200) {
+          const data = res.data
+          notificationList.value = data.cardList
+          tabCountList.value = data.countList
+        }
+      })
+      .finally(() => {
+        loading.value = false
+      })
+  } catch (error) {
+    console.error(error)
+    loading.value = false
+  }
+}
+// 获取未读消息数量
+const getUnReadCount = () => {
+  return notificationList.value.filter((item) => !item.info.isRead).length
 }
 
 const activeName = ref('All Notifications')
@@ -103,7 +103,11 @@ onUnmounted(() => {
               <div v-if="item === activeItem" class="active-sign"></div>
               <span>{{ item }}</span>
               <div class="count" v-if="tabCountList?.[index]">
-                <span>{{ handleCount(tabCountList?.[index]) }}</span>
+                <span>{{
+                  item === activeItem
+                    ? handleCount(getUnReadCount())
+                    : handleCount(tabCountList?.[index])
+                }}</span>
               </div>
             </div>
           </el-collapse-item>
@@ -129,7 +133,7 @@ onUnmounted(() => {
             </template>
             <div style="padding: 10px 140px 0px 16px" v-if="activeName === 'All Notifications'">
               <NotificationMessageCard
-                key="All Notifications"
+                v-if="activeName === 'All Notifications'"
                 :data="notificationList"
               ></NotificationMessageCard>
             </div>
@@ -143,7 +147,7 @@ onUnmounted(() => {
             </template>
             <div style="padding: 10px 140px 0px 16px" v-if="activeName === 'Unread'">
               <NotificationMessageCard
-                key="Unread"
+                v-if="activeName === 'Unread'"
                 :data="unreadNotificationList"
               ></NotificationMessageCard>
             </div>
@@ -151,10 +155,8 @@ onUnmounted(() => {
           <el-tab-pane label="Read" name="Read">
             <template #label><span style="margin-right: 4px">Read</span> </template>
             <div style="padding: 10px 140px 0px 16px" v-if="activeName === 'Read'">
-              <NotificationMessageCard
-                key="Read"
-                :data="readNotificationList"
-              ></NotificationMessageCard>
+              <NotificationMessageCard v-if="activeName === 'Read'" :data="readNotificationList">
+              </NotificationMessageCard>
             </div>
           </el-tab-pane>
         </el-tabs>

+ 0 - 34
src/views/SystemMessage/src/components/SystemMessageDetail.vue

@@ -11,40 +11,6 @@ const notificationData = ref({
   numericRecords: -1,
   notificationList: []
 })
-// const notificationData: any = {
-//   title: 'Milestone Update Daily Summary (Jan 10, 2025)',
-//   numericRecords: 3,
-//   notificationList: [
-//     {
-//       mode: 'Ocean Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       timeLabel: 'ATA: ',
-//       time: '2510-12-1 14:30 UTC+8',
-//       timezone: 'Asia/Shanghai'
-//     },
-//     {
-//       mode: 'Air Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       timeLabel: 'ATA: ',
-//       time: '2510-12-1 14:30 UTC+8',
-//       timezone: 'Asia/Shanghai'
-//     },
-//     {
-//       mode: 'Air Freight',
-//       no: 'HBOL: SHJN2301234',
-//       tag: 'Booking Confirmed',
-//       location: 'Hong Kong',
-//       timeLabel: 'ATA: ',
-//       time: '2510-12-1 14:30 UTC+8',
-//       timezone: 'Asia/Shanghai',
-//       previous: 'Previous: Departure from Shanghai (08:15 UTC+8)'
-//     }
-//   ]
-// }
 
 const loading = ref(false)
 const getNotificationList = () => {