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

diff --git a/src/views/im/home/components/group/group-avatar.vue b/src/views/im/home/components/group/group-avatar.vue
new file mode 100644
index 0000000..021714f
--- /dev/null
+++ b/src/views/im/home/components/group/group-avatar.vue
@@ -0,0 +1,131 @@
+<script lang="ts" setup>
+import type { GroupMember } from '../../types'
+
+import { computed, ref, watch } from 'vue'
+
+import {
+  buildGroupAvatar,
+  getCachedGroupAvatar,
+  setCachedGroupAvatar
+} from '../../../utils/group'
+import { getMemberDisplayName } from '../../../utils/user'
+import { useFriendStore } from '../../store/friendStore'
+import { useGroupStore } from '../../store/groupStore'
+import { UserAvatar } from '../user'
+
+defineOptions({ name: 'ImGroupAvatar' })
+
+const props = withDefaults(
+  defineProps<{
+    clickable?: boolean // 鏄惁鍙偣鍑伙紙榛樿 false锛屽垪琛ㄩ噷浠呭睍绀猴級
+    groupId: number // 缇ょ紪鍙凤紱鐢ㄤ簬鏌� store 鎷挎垚鍛樺ご鍍�
+    name?: string // 缇ゅ悕锛涜壊鍗″厹搴曟枃瀛�
+    previewable?: boolean // 鏄惁鐐瑰ご鍍忕洿鎺ユ斁澶ч瑙堬紙缇よ鎯呭ぇ澶村儚浣嶇敤锛�
+    previewZIndex?: number // 棰勮灞� z-index
+    radius?: string // 鍦嗚锛孋SS 闀垮害
+    size?: number // 灏哄锛坧x锛夛紝姝f柟褰�
+    url?: string // 鏈嶅姟绔凡璁剧疆鐨勭兢澶村儚 URL锛涢潪绌哄垯鐩存帴鐢紝涓嶆嫾鍥�
+  }>(),
+  {
+    clickable: false,
+    name: '',
+    previewable: false,
+    previewZIndex: 2000,
+    radius: '15%',
+    size: 42,
+    url: ''
+  }
+)
+
+const friendStore = useFriendStore()
+const groupStore = useGroupStore()
+const mergedUrl = ref('')
+// 绔炴�佷繚鎶わ細涓㈠純杩囨湡 await 缁撴灉
+let mergeToken = 0
+
+/** 鎸夊鍣� size 脳 DPR 绠� canvas 瀹為檯鍍忕礌锛岄伩鍏� 2x / 3x retina 灞忔嫾鍥剧硦锛汥PR 灏侀《 3 闃叉瓒呴珮鍒嗚鲸鐜囩敾甯冭繃澶� */
+function getTargetSize(size: number): number {
+  const dpr = Math.min(window.devicePixelRatio || 1, 3)
+  return Math.max(Math.round(size * dpr), 64)
+}
+
+/** store 閲屾暣缇ゆ垚鍛樻槸鍚︺�屽畬鏁村姞杞姐�嶈繃锛涘彧鍦ㄤ负 true 鏃舵墠鎷煎浘锛岄伩鍏嶅垪琛ㄥ満鏅壒閲忓彂鎺ュ彛 */
+const loadedMembers = computed<GroupMember[] | null>(() => {
+  const g = groupStore.getGroup(props.groupId)
+  if (!g?.membersLoaded || !g.members) {
+    return null
+  }
+  return g.members
+})
+
+/** 鍓� 9 涓垚鍛樼殑鎷煎浘鍏ュ弬锛沶ame 璧� getMemberDisplayName 鍙e緞锛堝ソ鍙嬪娉� > 缇ゆ樀绉� > 鐪熷疄鏄电О锛� */
+const memberItems = computed(() => {
+  const members = loadedMembers.value
+  if (!members) {
+    return []
+  }
+  return members.slice(0, 9).map((m) => ({
+    avatar: m.avatar || '',
+    name: getMemberDisplayName(m, friendStore.getFriend(m.userId))
+  }))
+})
+
+/** 鎴愬憳蹇収绛惧悕锛氭嫾 (avatar, name) 瀛楁锛屽師鍦颁慨鏀逛换涓�瀛楁閮戒細璁� watch 閲嶇畻 */
+const memberSignature = computed(() =>
+  memberItems.value.map((it) => `${it.avatar}#${it.name}`).join('|')
+)
+
+/** 璧� buildGroupAvatar 鎷煎浘骞跺啓鍥� mergedUrl锛沵ergeToken 鏍¢獙閬垮厤鑰� await 瑕嗙洊鏂扮粨鏋� */
+async function applyMerge(key: string, targetSize: number): Promise<void> {
+  const myToken = ++mergeToken
+  const cached = getCachedGroupAvatar(key)
+  if (cached) {
+    mergedUrl.value = cached
+    return
+  }
+  const dataUrl = await buildGroupAvatar(memberItems.value, { targetSize })
+  if (myToken !== mergeToken) {
+    return
+  }
+  if (dataUrl) {
+    setCachedGroupAvatar(key, dataUrl)
+  }
+  mergedUrl.value = dataUrl
+}
+
+watch(
+  () => [props.url, props.groupId, props.size, memberSignature.value] as const,
+  ([url, groupId, size, signature]) => {
+    if (url) {
+      mergedUrl.value = ''
+      return
+    }
+    if (!signature) {
+      mergeToken++
+      mergedUrl.value = ''
+      groupStore.loadGroupMemberList(groupId)
+      return
+    }
+    const targetSize = getTargetSize(size)
+    const key = `${groupId}:${targetSize}:${signature}`
+    applyMerge(key, targetSize)
+  },
+  { immediate: true }
+)
+
+/** 鏈�缁堝睍绀� url锛氭湇鍔$ url 浼樺厛 鈫� 鎷煎浘 鈫� 绌哄瓧绗︿覆锛堣 UserAvatar 璧拌壊鍗★級 */
+const finalUrl = computed(() => props.url || mergedUrl.value)
+</script>
+
+<template>
+  <!-- url 闈炵┖璧板師鍥撅紱url 绌烘椂鍙栧墠 9 涓垚鍛樺ご鍍忔嫾涔濆鏍� dataURL锛屾垚鍛樻湭鍦� store 缂撳瓨鏃惰蛋鑹插崱鍏滃簳 -->
+  <UserAvatar
+    :url="finalUrl"
+    :name="name"
+    :size="size"
+    :radius="radius"
+    :clickable="clickable"
+    :previewable="previewable"
+    :preview-z-index="previewZIndex"
+  />
+</template>

--
Gitblit v1.9.3