| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import { computed, onMounted, onUnmounted } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | |
| | | import { getCurrentUserId } from '#/views/im/utils/auth' |
| | | |
| | | import { ImConversationType } from '../../../utils/constants' |
| | | import { getFriendDisplayName } from '../../../utils/user' |
| | | import { useConversationStore } from '../../store/conversationStore' |
| | | import { useFriendStore } from '../../store/friendStore' |
| | | import { useImUiStore } from '../../store/uiStore' |
| | | import UserInfo, { type UserInfoRelation } from './user-info.vue' |
| | | |
| | | defineOptions({ name: 'ImUserInfoCard' }) |
| | | |
| | | const uiStore = useImUiStore() |
| | | const conversationStore = useConversationStore() |
| | | const friendStore = useFriendStore() |
| | | const router = useRouter() |
| | | |
| | | const card = computed(() => uiStore.userInfoCard) |
| | | const user = computed(() => card.value.user) |
| | | |
| | | const isSelf = computed(() => { |
| | | const myId = getCurrentUserId() |
| | | return !!user.value?.id && user.value.id === myId |
| | | }) |
| | | const isActiveFriend = computed(() => { |
| | | if (!user.value?.id || isSelf.value) { |
| | | return false |
| | | } |
| | | return friendStore.isActiveFriend(user.value.id) |
| | | }) |
| | | const relation = computed<UserInfoRelation>(() => { |
| | | if (!user.value) { |
| | | return 'readonly' |
| | | } |
| | | if (isSelf.value) { |
| | | return 'self' |
| | | } |
| | | if (isActiveFriend.value) { |
| | | return 'friend' |
| | | } |
| | | return 'stranger' |
| | | }) |
| | | |
| | | const remark = computed(() => { |
| | | if (!isActiveFriend.value || !user.value?.id) { |
| | | return undefined |
| | | } |
| | | return friendStore.getFriend(user.value.id)?.displayName || '' |
| | | }) |
| | | |
| | | /** å
³éåçï¼ç¹å»é®ç½© / Esc / UserInfo æä¸æ¥çå 餿åäºä»¶ */ |
| | | function handleClose() { |
| | | uiStore.closeUserInfoCard() |
| | | } |
| | | |
| | | /** é®çäºä»¶ï¼Esc é®å
³éåç */ |
| | | function handleKeydown(e: KeyboardEvent) { |
| | | if (e.key === 'Escape' && card.value.show) { |
| | | handleClose() |
| | | } |
| | | } |
| | | |
| | | onMounted(() => window.addEventListener('keydown', handleKeydown)) |
| | | onUnmounted(() => window.removeEventListener('keydown', handleKeydown)) |
| | | |
| | | /** åæ¶æ¯ï¼UserInfo æä¸æ¥ç"åæ¶æ¯"ï¼ç±æ¬ç»ä»¶æ¥åå openConversation + è·³æ¶æ¯ Tab + å
³æµ®å± */ |
| | | function handleSendMessage() { |
| | | if (!user.value) { |
| | | return |
| | | } |
| | | // å friendStore éçææ°å¤æ³¨ / å
ææ°ï¼é¿å
æ°å»ºä¼è¯ç¨è¿ææ°æ® |
| | | const friend = friendStore.getFriend(user.value.id) |
| | | const conversationName = friend |
| | | ? getFriendDisplayName(friend) |
| | | : user.value.nickname || '' |
| | | conversationStore.openConversation( |
| | | user.value.id, |
| | | ImConversationType.PRIVATE, |
| | | conversationName, |
| | | user.value.avatar || '', |
| | | { silent: !!friend?.silent } |
| | | ) |
| | | // 跳转ä¼è¯ Tabï¼å¦æä¸å¨çè¯ï¼ï¼å¹¶ä¸ä¸ç®¡å½åè·¯ç±æ¯å¥é½å
åå°ä¼è¯å表页 |
| | | if (router.currentRoute.value.name !== 'ImHomeConversation') { |
| | | router.push({ name: 'ImHomeConversation' }) |
| | | } |
| | | uiStore.closeUserInfoCard() |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <!-- |
| | | ç¨æ·åçæµ®å± |
| | | - ä»
æ¿æ
"æµ®å±å®ä½ + å
³éé»è¾ï¼ç¹é®ç½© / Escï¼"ï¼åçè§è§èµ° <UserInfo>ï¼ä¸ contact 详æ
å
±ç¨ä¸ä»½ç»ä»¶ |
| | | - 触åï¼useImUiStore.openUserInfoCard(user, position)ï¼æ¬ç»ä»¶è®¢é
storeï¼å
¨å±åªæä¸ä»½å®ä¾ |
| | | - å
³ç³»æç± isSelf / isActiveFriend æ´¾ç relation prop éå° UserInfoï¼å é¤ / å 好å / 夿³¨è½åºé½å¨ UserInfo å
éç¯ |
| | | --> |
| | | <teleport to="body"> |
| | | <div v-if="card.show" class="fixed inset-0 z-9998" @click.self="handleClose"> |
| | | <div |
| | | class="fixed w-80 p-4 bg-[var(--ant-color-bg-elevated)] rounded-md shadow-xl" |
| | | :style="{ left: `${card.position.x }px`, top: `${card.position.y }px` }" |
| | | @click.stop |
| | | > |
| | | <UserInfo |
| | | :user="user" |
| | | :display-name="remark" |
| | | :relation="relation" |
| | | :preview-z-index="10000" |
| | | :add-source="card.addSource" |
| | | :add-source-extra="card.addSourceExtra" |
| | | @chat="handleSendMessage" |
| | | @deleted="handleClose" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </teleport> |
| | | </template> |