gaoluyang
2 天以前 787ccc59ba89bacc075562a161ecf02bc76ebadc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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>