|
|
@@ -1,6 +1,6 @@
|
|
|
<script setup lang="ts">
|
|
|
import dayjs from 'dayjs'
|
|
|
-import { computed, watch } from 'vue'
|
|
|
+import { computed, ref, watch } from 'vue'
|
|
|
import type { Conversation } from '@tencentcloud/chat'
|
|
|
import { useImPopup } from '~/composables/useImPopup'
|
|
|
import TitleIcon from '~/assets/icons/tab-active.svg'
|
|
|
@@ -9,12 +9,22 @@ import CloseListIcon from '~/assets/icons/im/close-list.svg'
|
|
|
const { state, close } = useImPopup()
|
|
|
const { ready, conversationList, conversationLoading, conversationError, getConversationList, bizUserInfoMap } = useChat()
|
|
|
|
|
|
+type ViewMode = 'list' | 'detail'
|
|
|
+const view = ref<ViewMode>('list')
|
|
|
+const activeConversationId = ref<string | null>(null)
|
|
|
+
|
|
|
const list = computed(() => conversationList.value
|
|
|
? conversationList.value.filter((conv) => {
|
|
|
return conv.userProfile?.userID !== '10000'
|
|
|
})
|
|
|
: [])
|
|
|
|
|
|
+const activeConversation = computed(() => {
|
|
|
+ const id = activeConversationId.value
|
|
|
+ if (!id) return null
|
|
|
+ return list.value.find(c => c.conversationID === id) ?? null
|
|
|
+})
|
|
|
+
|
|
|
const getConversationName = (conv: Conversation) => {
|
|
|
const userNo = conv?.userProfile?.userID
|
|
|
const biz = userNo ? bizUserInfoMap.value?.[userNo] : undefined
|
|
|
@@ -55,6 +65,24 @@ const fetchConversations = async () => {
|
|
|
await getConversationList()
|
|
|
}
|
|
|
|
|
|
+const activeName = computed(() => activeConversation.value ? getConversationName(activeConversation.value) : '')
|
|
|
+const activeAvatar = computed(() => activeConversation.value ? getConversationAvatar(activeConversation.value) : '/avatar.png')
|
|
|
+const activeBizUserInfo = computed(() => {
|
|
|
+ const userNo = activeConversation.value?.userProfile?.userID
|
|
|
+ if (!userNo) return undefined
|
|
|
+ return bizUserInfoMap.value?.[userNo]
|
|
|
+})
|
|
|
+
|
|
|
+const openConversationDetail = (conv: Conversation) => {
|
|
|
+ activeConversationId.value = conv.conversationID
|
|
|
+ view.value = 'detail'
|
|
|
+}
|
|
|
+
|
|
|
+const backToList = () => {
|
|
|
+ view.value = 'list'
|
|
|
+ activeConversationId.value = null
|
|
|
+}
|
|
|
+
|
|
|
watch(
|
|
|
() => [state.visible, ready.value] as const,
|
|
|
([visible, isReady]) => {
|
|
|
@@ -66,6 +94,16 @@ watch(
|
|
|
const handleUpdateShow = (value: boolean) => {
|
|
|
if (!value) close()
|
|
|
}
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => state.visible,
|
|
|
+ (visible) => {
|
|
|
+ if (!visible) {
|
|
|
+ view.value = 'list'
|
|
|
+ activeConversationId.value = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+)
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
@@ -75,7 +113,20 @@ const handleUpdateShow = (value: boolean) => {
|
|
|
teleport="body"
|
|
|
@update:show="handleUpdateShow"
|
|
|
>
|
|
|
- <div class="im-popup">
|
|
|
+ <ImConversationDetail
|
|
|
+ v-if="view === 'detail'"
|
|
|
+ :conversation="activeConversation"
|
|
|
+ :name="activeName"
|
|
|
+ :avatar="activeAvatar"
|
|
|
+ :biz-user-info="activeBizUserInfo"
|
|
|
+ @back="backToList"
|
|
|
+ @close="close"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ class="im-popup"
|
|
|
+ >
|
|
|
<div class="im-popup__bg" />
|
|
|
|
|
|
<div class="im-popup__header">
|
|
|
@@ -139,6 +190,7 @@ const handleUpdateShow = (value: boolean) => {
|
|
|
:time="getConversationTimeLabel(conv)"
|
|
|
:message="getConversationLastText(conv)"
|
|
|
:unread="conv.unreadCount"
|
|
|
+ @click="openConversationDetail(conv)"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -151,6 +203,8 @@ const handleUpdateShow = (value: boolean) => {
|
|
|
height: 100vh;
|
|
|
padding: 16px 16px 20px;
|
|
|
position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
|
|
|
&__bg {
|
|
|
@include size(100%, 173px);
|
|
|
@@ -176,6 +230,7 @@ const handleUpdateShow = (value: boolean) => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
+ min-width: 0;
|
|
|
|
|
|
&-icon {
|
|
|
position: absolute;
|
|
|
@@ -198,6 +253,9 @@ const handleUpdateShow = (value: boolean) => {
|
|
|
gap: 10px;
|
|
|
position: relative;
|
|
|
z-index: 1;
|
|
|
+ flex: 1 1 auto;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: auto;
|
|
|
}
|
|
|
|
|
|
&__list {
|