| 1 | 'use client' |
| 2 | |
| 3 | import type { ForwardedRef } from 'react' |
| 4 | import type { SocialAccount } from '@/api/accounts/account.types' |
| 5 | import { forwardRef, memo } from 'react' |
| 6 | import { PlatformIcon } from '@/components/common/PlatformIcon' |
| 7 | import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' |
| 8 | import { usePlatformInfo } from '@/hooks/usePlatformMetadata' |
| 9 | import { getOssUrl } from '@/utils/oss' |
| 10 | import styles from './avatarPlat.module.scss' |
| 11 | |
| 12 | export interface IAvatarPlatRef {} |
| 13 | |
| 14 | export interface IAvatarPlatProps { |
| 15 | account?: Partial<SocialAccount> |
| 16 | size?: 'large' | 'default' | 'small' | number |
| 17 | className?: string |
| 18 | width?: number |
| 19 | avatarWidth?: number |
| 20 | disabled?: boolean |
| 21 | fallbackText?: string |
| 22 | } |
| 23 | |
| 24 | const sizeClassMap: Record<string, string> = { |
| 25 | large: 'h-10 w-10', |
| 26 | default: 'h-8 w-8', |
| 27 | small: 'h-6 w-6', |
| 28 | } |
| 29 | |
| 30 | function getAvatar(url: string) { |
| 31 | if (url?.includes('https://')) { |
| 32 | return url |
| 33 | } |
| 34 | else { |
| 35 | return `${getOssUrl(url)}` |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | const AvatarPlat = memo( |
| 40 | forwardRef( |
| 41 | ( |
| 42 | { account, size = 'default', className, width, avatarWidth, disabled, fallbackText }: IAvatarPlatProps, |
| 43 | ref: ForwardedRef<IAvatarPlatRef>, |
| 44 | ) => { |
| 45 | // 添加防护检查 |
| 46 | if (!account || !account.type) { |
| 47 | console.warn('AvatarPlat: account or account.type is undefined', account) |
| 48 | return null |
| 49 | } |
| 50 | |
| 51 | const plat = usePlatformInfo(account.type) |
| 52 | if (!plat) { |
| 53 | console.warn('AvatarPlat: platform not found for type', account.type) |
| 54 | return null |
| 55 | } |
| 56 | |
| 57 | const isNumberSize = typeof size === 'number' || typeof avatarWidth === 'number' |
| 58 | const avatarSizePx = avatarWidth || (typeof size === 'number' ? size : undefined) |
| 59 | const sizeClassName = isNumberSize ? '' : sizeClassMap[size as string] || sizeClassMap.default |
| 60 | |
| 61 | return ( |
| 62 | <> |
| 63 | <div className={`${styles.avatarPlat} ${className} ${disabled ? styles.disabled : ''}`}> |
| 64 | <Avatar |
| 65 | className={sizeClassName} |
| 66 | style={{ |
| 67 | ...(avatarSizePx ? { width: avatarSizePx, height: avatarSizePx } : {}), |
| 68 | ...(disabled ? { opacity: 0.5 } : {}), |
| 69 | }} |
| 70 | > |
| 71 | <AvatarImage src={getAvatar(account!.avatar!)} alt={account.nickname || ''} /> |
| 72 | <AvatarFallback className="text-xs"> |
| 73 | {fallbackText || account.nickname?.[0] || '?'} |
| 74 | </AvatarFallback> |
| 75 | </Avatar> |
| 76 | <PlatformIcon |
| 77 | platform={account.type} |
| 78 | style={ |
| 79 | !width |
| 80 | ? { |
| 81 | width: size === 'large' ? 16 : size === 'default' ? 12.5 : 10, |
| 82 | opacity: disabled ? 0.5 : 1, |
| 83 | } |
| 84 | : { |
| 85 | width, |
| 86 | opacity: disabled ? 0.5 : 1, |
| 87 | } |
| 88 | } |
| 89 | /> |
| 90 | </div> |
| 91 | </> |
| 92 | ) |
| 93 | }, |
| 94 | ), |
| 95 | ) |
| 96 | |
| 97 | export default AvatarPlat |
| 98 |