index.client.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <template>
  2. <div class="h-50 bg-white justify-between w-full fixed z-[999] border-b box-border">
  3. <audio
  4. class="fixed top-0 left-0"
  5. ref="audioRef"
  6. :src="audioTips"
  7. style="opacity: 0; z-index: -1"
  8. ></audio>
  9. <NuxtLink to="/" class="absolute top-1/2 -translate-y-1/2 left-15">
  10. <img src="~/assets/img/logo.png" class="h-30 object-contain" />
  11. </NuxtLink>
  12. <div class="absolute right-15 top-1/2 -translate-y-1/2 flex items-center space-x-20">
  13. <div v-if="token" class="flex items-center space-x-10">
  14. <NuxtLink to="/profile" class="flex items-center">
  15. <van-image :src="userInfo.headImageUrl || defaultAvatar" round height="26" width="26" />
  16. </NuxtLink>
  17. <NuxtLink to="/profile/my-news" class="max-w-70 truncate text-black-6">
  18. <van-badge :dot="showDot" :offset="[-4, 5]">消息</van-badge>
  19. </NuxtLink>
  20. <NuxtLink to="/profile" class="max-w-70 truncate text-black-6">订单</NuxtLink>
  21. </div>
  22. <NuxtLink
  23. v-else-if="!token"
  24. :to="`/login?redirect=${route.fullPath}`"
  25. class="flex items-center text-black-6 space-x-5"
  26. >
  27. <div
  28. class="w-26 h-26 rounded-full bg-[#d9d9d9] text-black-6 flex items-center justify-center"
  29. >
  30. <span class="iconfont icon-profile"></span>
  31. </div>
  32. <span class="text-base">请登录</span>
  33. </NuxtLink>
  34. <img @click="handleClickMenu" src="~/assets/img/navbar/nav_menu.png" class="w-24 h-24" />
  35. </div>
  36. <van-popup v-model:show="isMenuShow" position="left" :style="{ height: '100%', width: '70%' }">
  37. <NavigationBarLeftMenu
  38. v-if="isMenuShow"
  39. v-model:visible="isMenuShow"
  40. @on-hide="isMenuShow = false"
  41. />
  42. </van-popup>
  43. </div>
  44. </template>
  45. <script setup>
  46. const chatsStore = useChatsStore()
  47. const { chatList, chatListLoading } = storeToRefs(chatsStore)
  48. import { XYWebSocket } from '@/utils/XYWebSocket.ts'
  49. import defaultAvatar from '~/assets/img/default_avatar.png'
  50. import audioTips from '@/assets/audio/message.mp3'
  51. const audioRef = ref(null)
  52. const isMenuShow = ref(false)
  53. function handleClickMenu() {
  54. isMenuShow.value = true
  55. }
  56. const route = useRoute()
  57. const authStore = useAuthStore()
  58. const { token } = storeToRefs(authStore)
  59. const userInfoStore = useUserInfoStore()
  60. const { userInfo } = storeToRefs(userInfoStore)
  61. watch(
  62. token,
  63. () => {
  64. if (token.value) {
  65. userInfoStore.getUserInfo()
  66. }
  67. },
  68. { immediate: true }
  69. )
  70. // 监听Socket
  71. onMounted(() => {
  72. chatsStore.getChatList()
  73. XYWebSocket.SocketEventsBus.on(XYWebSocket.SocketEvents.chatEvent, () => {
  74. chatsStore.getChatList()
  75. audioRef.value && audioRef.value.play()
  76. })
  77. })
  78. // 卸载Socket
  79. onUnmounted(() => {
  80. XYWebSocket.SocketEventsBus.off(XYWebSocket.SocketEvents.chatEvent)
  81. })
  82. // 是否有消息显示红点
  83. const showDot = computed(() => {
  84. let newTatol = chatList.value.reduce((sum, item) => sum + item?.unreadMessageCount, 0)
  85. if (newTatol) {
  86. return true
  87. } else {
  88. return false
  89. }
  90. })
  91. </script>
  92. <style lang="scss" scoped></style>