| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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 // 尺寸ï¼pxï¼ï¼æ£æ¹å½¢ï¼ä¼å
äº width/height |
| | | url?: string // 头åå¾ç URLï¼ä¸ºç©ºæ¶èµ°è²å¡æå |
| | | user?: User // é¢å¤çç¨æ·ä¿¡æ¯ï¼ä¼ äºç¹å»å°±ä¸ç¨ç°ææ¥å£ï¼å¼¹åçç¨ï¼ |
| | | }>(), |
| | | { |
| | | 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)) |
| | | |
| | | /** 头åç¹å»ï¼previewable èµ° 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ï¼clickableï¼ |
| | | - 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> |