2026-08-04 1498eff8df14d0c4963fa32745ecb2a495eac3cb
src/views/im/home/components/friend/friend-item.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
<script lang="ts" setup>
import type { FriendLite } from '../../types'
import { useImUiStore } from '../../store/uiStore'
import { UserAvatar } from '../user'
defineOptions({ name: 'ImFriendItem' })
const props = withDefaults(
  defineProps<{
    active?: boolean
    friend: FriendLite
    menu?: boolean // æ˜¯å¦å¯ç”¨å³é”®èœå•;在选择器弹窗里一般关闭
  }>(),
  {
    active: false,
    menu: true
  }
)
const emit = defineEmits<{
  chat: [friend: FriendLite]
  click: [friend: FriendLite]
  delete: [friend: FriendLite]
}>()
const uiStore = useImUiStore()
/** å³é”®èœå•:发送消息 / åˆ é™¤å¥½å‹ */
function handleContextMenu(event: MouseEvent) {
  if (!props.menu) {
    return
  }
  uiStore.openContextMenu(
    { x: event.clientX, y: event.clientY },
    [
      { key: 'chat', name: '发送消息' },
      { key: 'delete', name: '删除好友' }
    ],
    (item) => {
      if (item.key === 'chat') emit('chat', props.friend)
      else if (item.key === 'delete') emit('delete', props.friend)
    }
  )
}
</script>
<template>
  <!--
    å¥½å‹å•行项
    - å¤´åƒ + æ˜µç§°
    - é€‰ä¸­æ€ active
    - å³é”®èœå•(发消息 / åˆ é™¤å¥½å‹ï¼‰ç”±å…¨å±€ ContextMenu æ‰¿æŽ¥
  -->
  <div
    class="relative flex items-center gap-2.5 px-4 py-3 cursor-pointer transition-colors hover:bg-[var(--ant-color-fill)]"
    :class="{ '!bg-[#d9ecff] dark:!bg-[var(--ant-color-primary-bg-hover)]': active }"
    @click="$emit('click', friend)"
    @contextmenu.prevent="handleContextMenu"
  >
    <!-- prefix slot:放在头像前,给选择类弹窗的 checkbox / åœ†ç‚¹ç”¨ï¼Œä¸ä¼ åˆ™ä¸æ¸²æŸ“ -->
    <slot name="prefix"></slot>
    <!-- å¤´åƒ -->
    <UserAvatar
      :id="friend.id"
      :url="friend.avatar"
      :name="friend.nickname"
      :size="42"
      :clickable="false"
    />
    <!-- å•行展示 displayName ä¼˜å…ˆï¼›æ˜µç§°ä»…在好友详情面板展示,列表里不重复 -->
    <div class="flex flex-1 min-w-0">
      <div class="overflow-hidden text-sm truncate text-[var(--ant-color-text)]">
        {{ friend.displayName || friend.nickname }}
      </div>
    </div>
    <slot></slot>
  </div>
</template>