ChatWindow.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <!-- @format -->
  2. <script setup>
  3. import dayjs from 'dayjs'
  4. import { useMessage } from './useMessage'
  5. import { useUserStore } from '@/stores/modules/user'
  6. const props = defineProps({
  7. isUseContact: {
  8. type: Boolean,
  9. default: true,
  10. },
  11. })
  12. defineEmits(['scroll-top'])
  13. const {
  14. onScrollTop,
  15. loading,
  16. noMore,
  17. selectedContact,
  18. messageList,
  19. isScrollBottom,
  20. } = useMessage()
  21. const userStore = useUserStore()
  22. const { avatar } = storeToRefs(userStore)
  23. const chatContainer = ref(null)
  24. const isScrolledToTop = ref(false)
  25. const status = computed(() => {
  26. return loading.value ? '加载中...' : noMore.value ? '没有更多了~' : ''
  27. })
  28. function scrollToBottom() {
  29. nextTick(() => {
  30. if (chatContainer.value) {
  31. const timer = setTimeout(() => {
  32. clearTimeout(timer)
  33. chatContainer.value.scrollTop = chatContainer.value.scrollHeight
  34. }, 300)
  35. }
  36. })
  37. }
  38. async function handleScroll(event) {
  39. if (!chatContainer.value)
  40. return
  41. const scrollTop = event.target.scrollTop
  42. const previousScrollHeight = chatContainer.value.scrollHeight
  43. isScrolledToTop.value = scrollTop <= 0
  44. if (isScrolledToTop.value && !loading.value) {
  45. await onScrollTop()
  46. chatContainer.value.scrollTop = (chatContainer.value.scrollHeight - previousScrollHeight)
  47. }
  48. }
  49. watch(
  50. () => isScrollBottom.value,
  51. (val) => {
  52. !!val && scrollToBottom()
  53. },
  54. {
  55. immediate: true,
  56. },
  57. )
  58. </script>
  59. <template>
  60. <div
  61. ref="chatContainer"
  62. class="space-y-4 overflow-y-auto scroll-custom pb-30px"
  63. :class="isUseContact ? 'h-530px' : 'h-355px'"
  64. @scroll="handleScroll"
  65. >
  66. <div class="text-center text-#999 text-14px">
  67. {{ status }}
  68. </div>
  69. <div v-for="message in messageList" :key="message.id">
  70. <div v-if="message.senderType === '1'" class="flex items-center">
  71. <img
  72. v-if="selectedContact.sessionType === '2'"
  73. :src="selectedContact.brandInfo?.brandLogo"
  74. class="w-40px h-40px object-cover b-rd-50%"
  75. >
  76. <img
  77. v-if="selectedContact.sessionType === '1'"
  78. src="@/assets/images/avatar.png"
  79. class="b-rd-50% w-40px h-40px b-rd-50%"
  80. alt=""
  81. srcset=""
  82. >
  83. <div
  84. class="ml-20px flex items-center w-60% "
  85. >
  86. <div v-if="message.type === '1'" class=" p-10px bg-#fff b-rd-20px b-rd-tl-0 w-full">
  87. {{ message.content }}
  88. </div>
  89. <div v-if="message.type === '2'" class="w-200px h-200px">
  90. <img :src="message.imageUrl" class="w-100% h-100% object-cover" alt="" srcset="">
  91. </div>
  92. </div>
  93. <div
  94. class="text-14px text-#999 ml-20px"
  95. >
  96. {{ dayjs(message.sendTime).format("YYYY/MM/DD HH:MM") }}
  97. </div>
  98. </div>
  99. <div v-if="message.senderType === '2'" class="flex justify-end items-center">
  100. <div
  101. class="text-14px text-#999 mr-20px"
  102. >
  103. {{ dayjs(message.sendTime).format("YYYY/MM/DD HH:MM") }}
  104. </div>
  105. <div
  106. class="w-60% mr-20px"
  107. :class="{ 'flex justify-end': message.type === '2' }"
  108. >
  109. <div v-if="message.type === '1'" class="py-10px b-rd-20px b-rd-tr-0 px-20px bg-#CDA98F text-#fff">
  110. {{ message.content }}
  111. </div>
  112. <div v-if="message.type === '2'" class="w-200px h-200px">
  113. <img :src="message.imageUrl" class="w-100% h-100% object-cover" alt="" srcset="">
  114. </div>
  115. </div>
  116. <img v-if="avatar" :src="avatar" class="w-40px h-40px">
  117. <img v-else src="@/assets/images/avatar.png" class="w-40px h-40px">
  118. </div>
  119. </div>
  120. </div>
  121. </template>
  122. <style lang="less" scoped>
  123. .scroll-custom {
  124. &::-webkit-scrollbar {
  125. display: none;
  126. }
  127. }
  128. </style>