<template>
	<view class="fs-file-list">
		<view v-for="(item, index) in modelValue" :key="index" class="fs-file-box">
			<fs-icon type="icon-close" size="20px" colorType="danger" class="fs-file-del" @click="handleDel(index)"></fs-icon>
			<fs-avatar
				v-if="mediaType === 'image'"
				:src="formatPath(item)"
				:shape="shape"
				:size="size"
				:width="width"
				:height="height"
				radius
				@click="handlePreview(formatPath(item))"
			></fs-avatar>
			<video v-else :src="formatPath(item)" controls class="fs-file-video"></video>
		</view>
		<view class="fs-file-box" @click="upload" v-if="modelValue.length < count">
			<slot>
				<fs-avatar :shape="shape" :size="size" :width="width" :height="height" radius bgColor="#EBEFF5">
					<fs-icon type="icon-plus" size="50px"></fs-icon>
				</fs-avatar>
			</slot>
		</view>
	</view>
</template>

<script>
/**
 * 上传组件
 * @description 上传组件
 * @property {String} action 上传地址
 * @property {String} name 文件对应的key,开发者在服务器端通过这个key可以获取到文件二进制内容
 * @property {Object} HTTP 请求 Header, header 中不能设置 Referer
 * @property {String} mediaType = [image | video] 媒体类型
 * @property {Number} count 最多上传数量
 * @property {String} shape 上传框形状
 * @property {String} size 上传框大小
 * @property {String} width 上传框宽度(优先级高于size)
 * @property {String} height 上传框高度(优先级高于size)
 * @property {String} height 上传框高度(优先级高于size)
 * @property {String} height 上传框高度(优先级高于size)
 * @property {Object} chooseDatachooseImage/chooseVideo参数
 * @property {Object} formData 上传数据
 * @property {String} pathKey	接口返回的图片路径的key(如果没有可设置成空)
 * @property {Boolean} editable	图片编辑
 * @property {Boolean} cloudUpload	是否云上传(需配置云服务空间)
 */
export default {
	name: 'fs-upload'
}
</script>

<script setup>
import { getCurrentInstance } from 'vue'
import utils from '@/utils/utils'
import config from '@/utils/config'

const { proxy } = getCurrentInstance()

const props = defineProps({
	action: String,
	name: {
		type: String,
		default: 'file'
	},
	header: {
		type: Object,
		default: () => {}
	},
	count: {
		type: Number,
		default: 1
	},
	chooseData: {
		type: Object,
		default: () => {}
	},
	modelValue: {
		type: Array,
		default: () => []
	},
	mediaType: {
		type: String,
		default: 'image',
		validator(value) {
			return ['image', 'video'].includes(value)
		}
	},
	shape: {
		type: String,
		default: 'square',
		validator(value) {
			return ['square', 'circle'].includes(value)
		}
	},
	size: {
		type: String,
		default: '150rpx'
	},
	width: {
		type: String,
		default: '150rpx'
	},
	height: {
		type: String,
		default: '150rpx'
	},
	formData: {
		type: Object,
		default() {
			return {}
		}
	},
	pathKey: {
		type: String,
		default: 'filePath'
	},
	editable: Boolean,
	cloudUpload: Boolean
})
const emit = defineEmits(['update:modelValue'])

const handlePreview = current => {
	uni.previewImage({
		current,
		urls: props.modelValue.map(item => formatPath(item))
	})
}
const upload = async () => {
	let methods = ''
	if (props.mediaType === 'image') {
		methods = 'chooseAndUploadImage'
	} else {
		methods = 'chooseAndUploadVideo'
	}
	utils[methods](
		{
			count: props.count,
			...props.chooseData
		},
		{
			url: props.action || proxy.$uploadUrl,
			name: props.name,
			header: props.header,
			formData: props.formData,
			editable: props.editable
		},
		props.cloudUpload
	).then(res => {
		const fileList = [...props.modelValue, ...res]
		fileList.length > props.count && fileList.splice(props.count)
		emit('update:modelValue', fileList)
	})
}
const handleDel = index => {
	props.modelValue.splice(index, 1)
	emit('update:modelValue', props.modelValue)
}

const formatPath = item => {
	const path = props.pathKey ? item[props.pathKey] : item
	return utils.isHttp(path) ? path : config.baseUrl + path
}
</script>

<style lang="scss" scoped>
.fs-file {
	&-list {
		display: flex;
		flex-wrap: wrap;
		padding-top: var(--gutter);
	}
	&-box {
		position: relative;
		margin-bottom: var(--gutter);
		margin-left: var(--gutter);
	}
	&-video {
		width: 300rpx;
		height: 200rpx;
	}
	&-del {
		position: absolute;
		top: 0;
		right: 0;
		transform: translate(50%, -50%);
		font-size: 22px;
		color: var(--sub);
		z-index: 10;
	}
}
</style>
