<template>
	<view
		class="fs-avatar"
		:class="[
			shape,
			{
				radius,
				fixed
			}
		]"
		:style="{
			width: width || size,
			height: height || size,
			right: fixed ? right : 0,
			bottom: fixed ? bottom : 0,
			border: borderStyle,
			'margin-left': avatarGroup.margin + 'rpx'
		}"
		@click="handleClick"
	>
		<image
			class="fs-avatar-img"
			:src="errImg"
			v-if="errImg"
			:lazy-load="lazyLoad"
			:mode="imageMode"
			@click="handlePreview"
		/>
		<image
			class="fs-avatar-img"
			:src="src"
			v-if="src"
			:lazy-load="lazyLoad"
			:mode="imageMode"
			:show-menu-by-longpress="showMenu"
			@click="handlePreview"
			@error="handleError"
		/>
		<view v-else class="fs-avatar-slot" :class="['bg-' + bgColorType]" :style="{ backgroundColor: bgColor }">
			<slot></slot>
		</view>
	</view>
</template>

<script>
/**
 * 头像组件
 * @description 头像组件
 * @property {String} src 头像地址
 * @property {String} shape = [circle | square] 头像类型
 * @property {String} size 头像大小
 * @property {String} width 头像宽
 * @property {String} height 头像高
 * @property {String} bgColor 背景颜色
 * @property {String} bgColorType = [primary | danger | warning | info | success] 背景颜色类型
 * @property {Boolean} border 是否展示边框
 * @property {String} borderWidth 边框宽
 * @property {String} borderColor 边框颜色
 * @property {Boolean} lazyLoad 是否懒加载
 * @property {String} imageMode 图片模式
 * @property {Boolean} preview 是否预览图片
 * @property {Boolean} radius 是否圆角
 * @property {String} link 跳转地址
 * @property {String} linkType 跳转类型
 * @property {Boolean} fixed 是否悬浮
 * @property {String} right 悬浮右边距（仅在fixed为true时有效）
 * @property {String} bottom 悬浮下边距（仅在fixed为true时有效）
 * @property {Boolean} showMenu 长按图片显示菜单
 * @property {String} defaultErrorImg 图片加载失败显示的默认图片
 * @example <fs-avatar size="100rpx" src="***"></fs-avatar>
 */
export default {
	name: 'fs-avatar'
}
</script>

<script setup>
import { computed, inject, ref } from 'vue'
import config from '@/utils/config'

const props = defineProps({
	src: String,
	shape: {
		type: String,
		default: 'circle', // square, circle
		validator(value) {
			return ['circle', 'square'].includes(value)
		}
	},
	size: {
		type: String,
		default: '80rpx'
	},
	width: String,
	height: String,
	bgColor: String,
	bgColorType: {
		type: String,
		default: 'primary',
		validator(value) {
			return ['primary', 'success', 'info', 'warning', 'danger'].includes(value)
		}
	},
	border: Boolean,
	borderWidth: {
		type: String,
		default: '4rpx'
	},
	borderColor: {
		type: String,
		default: '#fff'
	},
	lazyLoad: Boolean,
	imageMode: {
		type: String,
		default: 'scaleToFill'
	},
	preview: Boolean,
	radius: Boolean,
	link: String,
	linkType: {
		type: String,
		default: 'navigateTo'
	},
	fixed: Boolean,
	right: {
		type: String,
		default: '40rpx'
	},
	bottom: {
		type: String,
		default: '60rpx'
	},
	showMenu: Boolean,
	defaultErrorImg: {
		type: String,
		default: config.defaultErrorImg
	}
})

const emits = defineEmits(['click'])

const avatarGroup = inject('avatarGroup', {})

const borderStyle = computed(() => {
	return props.border || avatarGroup.border ? `${props.borderWidth} solid ${props.borderColor}` : 'none'
})

const handleClick = () => {
	if (props.link) {
		uni[props.linkType]({
			url: props.link
		})
	}
	emits('click')
}

const handlePreview = () => {
	if (props.preview) {
		uni.previewImage({
			urls: [props.src || errImg.value]
		})
	}
}

const errImg = ref('')
const handleError = e => {
	errImg.value = props.defaultErrorImg
}
</script>

<style lang="scss" scoped>
.fs-avatar {
	display: inline-block;
	white-space: nowrap;
	position: relative;
	overflow: hidden;
	vertical-align: middle;
	text-align: center;

	&.radius {
		border-radius: var(--radius);
	}
	&.circle,
	&.circle &-img {
		border-radius: 50%;
	}
	&.fixed {
		position: fixed;
		z-index: 50;
		margin-bottom: var(--window-bottom);
	}

	&-img {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	&-slot {
		width: 100%;
		height: 100%;
		display: flex;
		justify-content: center;
		align-items: center;
		color: #fff;
		white-space: normal;
		line-height: 1;
	}
}
</style>
