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-avatar.vue |  134 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/src/views/im/home/components/user/user-avatar.vue b/src/views/im/home/components/user/user-avatar.vue
new file mode 100644
index 0000000..de5f633
--- /dev/null
+++ b/src/views/im/home/components/user/user-avatar.vue
@@ -0,0 +1,134 @@
+<script lang="ts" setup>
+import type { User } from '../../types'
+
+import { computed } from 'vue'
+
+import { Image } from 'ant-design-vue'
+
+import { ImFriendAddSource } from '../../../utils/constants'
+import { getAvatarBgColor, getAvatarText } from '../../../utils/user'
+import { useImUiStore } from '../../store/uiStore'
+
+defineOptions({ name: 'ImUserAvatar', inheritAttrs: false })
+
+const props = withDefaults(
+  defineProps<{
+    addSource?: number // 鍔犲ソ鍙嬫潵婧愶紱鐐瑰ご鍍忓脊 UserInfoCard 鏃堕�忎紶缁� FriendAddDialog锛堥粯璁� 1=鎼滅储锛�
+    addSourceExtra?: string // 鍔犲ソ鍙嬫潵婧愰檮鍔狅細addSource=2锛堢兢鑱婏級鏃朵紶缇ゅ悕锛岃瘽鏈嫾涓恒�屾垜鏄� XX 缇ょ殑 YY銆�
+    clickable?: boolean // 鏄惁鐐瑰嚮寮瑰嚭 UserInfoCard锛涢粯璁� true
+    id?: number | string // 鐢ㄦ埛 id锛涗紶浜嗘墠鑳界偣寮�鍚嶇墖
+    name?: string // 鐢ㄦ埛鍚嶏紙鑹插崱鏂囧瓧 + 鍚嶇墖澶囩敤锛�
+    previewable?: boolean // 鏄惁鐐瑰ご鍍忕洿鎺ユ斁澶ч瑙堬紱寮�鍚悗蹇界暐 clickable锛屼笉鍐嶅脊鍚嶇墖
+    previewZIndex?: number // 棰勮灞� z-index锛涙斁鍦ㄩ珮 z-index 寮瑰眰锛堝 UserInfoCard锛夐噷鏃堕渶鎵嬪姩鎶珮
+    radius?: string // 鍦嗚锛屾敮鎸� CSS 闀垮害锛涢粯璁� 15% 鏂瑰潡灏忓渾瑙掞紙鍙傝�冨井淇★級
+    size?: number // 灏哄锛坧x锛夛紝姝f柟褰紱浼樺厛浜� width/height
+    url?: string // 澶村儚鍥剧墖 URL锛涗负绌烘椂璧拌壊鍗℃枃瀛�
+    user?: User // 棰濆鐨勭敤鎴蜂俊鎭紝浼犱簡鐐瑰嚮灏变笉鐢ㄧ幇鎷夋帴鍙o紙寮瑰悕鐗囩敤锛�
+  }>(),
+  {
+    addSourceExtra: undefined,
+    clickable: true,
+    id: undefined,
+    name: undefined,
+    previewable: false,
+    previewZIndex: 2000,
+    radius: '15%',
+    size: 42,
+    url: undefined,
+    user: undefined,
+    addSource: ImFriendAddSource.SEARCH
+  }
+)
+
+const uiStore = useImUiStore()
+
+const imgStyle = computed(() => ({
+  width: `${props.size}px`,
+  height: `${props.size}px`,
+  borderRadius: props.radius
+}))
+
+const textStyle = computed(() => ({
+  width: `${props.size}px`,
+  height: `${props.size}px`,
+  fontSize: `${Math.floor(props.size * (avatarText.value.length > 1 ? 0.34 : 0.42))}px`,
+  background: textColor.value,
+  borderRadius: props.radius
+}))
+
+/** 鑹插崱棣栧瓧锛氫腑鏂囧彇 1 涓瓧銆佽嫳鏂� / 鎷変竵鍙栧墠 2 涓瓧姣� */
+const avatarText = computed(() => getAvatarText(props.name))
+
+/** 鑹插崱搴曡壊锛氭寜鏄电О charCode 鍝堝笇鍙栬皟鑹叉澘鑹� */
+const textColor = computed(() => getAvatarBgColor(props.name))
+
+/** 澶村儚鐐瑰嚮锛歱reviewable 璧� el-image 棰勮涓嶅脊鍚嶇墖锛涘惁鍒欐寜 user / id 浠讳竴鍏ュ弬鎵撳紑鍚嶇墖 */
+function handleClick(e: MouseEvent) {
+  if (props.previewable) {
+    return
+  }
+  if (!props.clickable) {
+    return
+  }
+  // 鎯呭喌涓�锛氭湁棰勪紶 user 淇℃伅锛氬氨鐩存帴鐢紝鐪佷竴娆℃帴鍙�
+  if (props.user) {
+    uiStore.openUserInfoCardAtEvent(props.user, e, props.addSource, props.addSourceExtra)
+    return
+  }
+  // 鎯呭喌浜岋細鏃犻浼� user 淇℃伅锛氭墦寮�鍚嶇墖锛屼紶鏈�灏忓繀瑕佷俊鎭紙id + 鏄电О + 澶村儚锛夛紝浣嶇疆鍦ㄩ紶鏍囧彸渚�
+  const numId = Number(props.id)
+  if (!numId || numId <= 0) {
+    return
+  }
+  uiStore.openUserInfoCardAtEvent(
+    {
+      id: numId,
+      nickname: props.name,
+      avatar: props.url
+    },
+    e,
+    props.addSource,
+    props.addSourceExtra
+  )
+}
+</script>
+
+<template>
+  <!--
+    閫氱敤鐢ㄦ埛澶村儚缁勪欢
+    - 鏈� url 鏃跺睍绀哄浘鐗囷紱鏃� url 鏃跺睍绀鸿壊鍗� + 棣栧瓧姣�/棣栧瓧
+    - 鐐瑰嚮榛樿瑙﹀彂 UserInfoCard锛坈lickable锛�
+    - previewable=true 鏃舵敼涓虹偣澶村儚鐩存帴鏀惧ぇ棰勮锛堢敤浜庡悕鐗� / 璇︽儏椤电瓑澶уご鍍忎綅锛�
+  -->
+  <div
+    class="relative inline-flex"
+    :style="{ cursor: clickable && !previewable ? 'pointer' : 'default' }"
+    v-bind="$attrs"
+    @click="handleClick"
+  >
+    <Image
+      v-if="url && previewable"
+      class="block overflow-hidden"
+      :src="url"
+      :preview="{ src: url, zIndex: previewZIndex }"
+      :style="imgStyle"
+    />
+    <img
+      v-else-if="url"
+      class="block overflow-hidden object-cover"
+      :src="url"
+      :style="imgStyle"
+      loading="lazy"
+      :alt="name || 'avatar'"
+    />
+    <div
+      v-else
+      class="flex items-center justify-center text-white font-medium select-none"
+      :style="textStyle"
+    >
+      {{ avatarText }}
+    </div>
+    <!-- 鍏佽澶栭儴鎻掑叆瑁呴グ锛屽缇よ亰瑙掓爣 -->
+    <slot></slot>
+  </div>
+</template>

--
Gitblit v1.9.3