From 27cd042df9aca0383a49f3514bc21958dd890912 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 29 六月 2026 15:42:23 +0800
Subject: [PATCH] 银川 1.联调产品维护页面 2.添加IM即时通讯模块

---
 src/views/im/home/components/user/user-info-card.vue |  121 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/src/views/im/home/components/user/user-info-card.vue b/src/views/im/home/components/user/user-info-card.vue
new file mode 100644
index 0000000..ec33489
--- /dev/null
+++ b/src/views/im/home/components/user/user-info-card.vue
@@ -0,0 +1,121 @@
+<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()
+}
+
+/** 閿洏浜嬩欢锛欵sc 閿叧闂悕鐗� */
+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 璇︽儏鍏辩敤涓�浠界粍浠�
+    - 瑙﹀彂锛歶seImUiStore.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>

--
Gitblit v1.9.3