<template>
	<div v-loading="isLoading" class="component-upload-image">
		<el-upload
			multiple
			:action="uploadUrl"
			:http-request="httpRequest"
			:list-type="listType"
			:disabled="disabledUpload"
			:before-upload="handleBeforeUpload"
			:limit="limit"
			:on-exceed="handleExceed"
			name="file"
			:on-remove="handleRemove"
			:show-file-list="true"
			:headers="headers"
			:file-list="fileList"
			:on-success="handleUploadSuccess"
			:auto-upload="true"
			:accept="accept.join(',')"
		>
			<el-button v-show="disabledUpload === false" plain icon="Upload"></el-button>
			<template v-if="disabledUpload === false" #tip>
				<!-- 上传提示 -->
				<el-tooltip v-if="showTip" placement="bottom">
					<div class="el-upload__tip">
						<el-icon><QuestionFilled /></el-icon>
					</div>
					<template #content>
						请上传
						<template v-if="fileSize">
							大小不超过
							<b style="color: #f56c6c">{{ fileSize }}MB</b>
						</template>
						<template v-if="accept">
							格式为
							<b style="color: #f56c6c">{{ accept.join('/') }}</b>
						</template>
						的文件
					</template>
				</el-tooltip>
			</template>

			<template #file="{ file }">
				<div>
					<el-link type="success" @click="previewFile(file)">{{ file.name }}</el-link>
					<el-button v-if="disabledUpload === false" text icon="Delete" @click="handleRemove(file)"></el-button>
				</div>
			</template>
		</el-upload>

		<el-dialog class="le-dialog" v-model="dialogVisible" :title="'预览 (' + dialogTitle + ')'" width="800px" append-to-body destroy-on-close>
			<iframe :src="dialogUrl" frameborder="0" width="100%" height="500" allowfullscreen></iframe>
		</el-dialog>
	</div>
</template>

<script setup>
import files from '@/api/common/files'
// import { getToken } from '@/utils/auth' // 需要获取到token
import { debounce } from 'lodash-es'
import { ElMessage } from 'element-plus'
import request from '@/utils/request'
import { computed, ref, watch } from 'vue'
import { QuestionFilled } from '@element-plus/icons-vue'

const props = defineProps({
	modelValue: {
		type: [String, Object, Array],
		default: undefined
	},
	// 数量限制
	limit: {
		type: Number,
		default: 5
	},
	// 文件所属模块
	source: {
		type: String,
		default: ''
	},
	// 大小限制(MB)
	fileSize: {
		type: Number,
		default: 5
	},
	// 是否显示提示
	isShowTip: {
		type: Boolean,
		default: true
	},
	// 文件列表类型
	listType: {
		type: String,
		default: 'picture'
	},
	accept: {
		type: Array,
		default: () => {
			return ['.docx', '.pptx', '.xlsx', '.zip', '.csv', '.pdf']
		}
	},
	preview: {
		type: Boolean,
		default: true
	},
	disabledUpload: {
		type: Boolean,
		default: false
	},
	return: {
		type: String,
		default: 'array',
		validator(value) {
			// 这个值必须与下列字符串中的其中一个相匹配
			return ['array', 'string'].includes(value)
		}
	},
	loading: {
		type: Boolean,
		default: false
	}
})

const isLoading = computed({
	get() {
		return props.loading
	},
	set(val) {
		console.log('set loading', val)
		emit('update:loading', val)
	}
})

const emit = defineEmits(['success', 'update:modelValue', 'update:loading'])
const number = ref(0)
const dialogUrl = ref('')
const dialogTitle = ref('')
const dialogVisible = ref(false)
// const baseUrl = import.meta.env.VITE_APP_BASE_INTERFACE
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_INTERFACE + '/file/upload') // 上传的服务器地址
// const headers = ref({ Authorization: 'Bearer ' + getToken() })
const headers = ref({ Authorization: 'Bearer =====' })
const fileList = ref([]) // 已上传的
const showTip = computed(() => props.isShowTip && (props.accept || props.fileSize))
let multipleCount = 0 //并发上传的数量

watch(
	() => props.modelValue,
	async val => {
		if (val) {
			// 首先将值转为数组
			const fileIdList = Array.isArray(val) ? val : props.modelValue.split(',')
			if (fileIdList.length > 0) {
				await files.batchGetUrlApi({ fileIdList }).then(res => {
					fileList.value = res.data
				})
			}
		} else {
			fileList.value = []
		}
	},
	{ deep: true, immediate: true }
)

function filterResponse(list) {
	return list.map(item => {
		return item.response ? item.response.data : item
	})
}

function getFileIds(list) {
	const ids = list.map(item => item.id)
	if (props.return === 'string') {
		return ids.join(',')
	} else {
		return ids
	}
}

const updateModelValue = debounce(() => {
	emit('update:modelValue', getFileIds(filterResponse(fileList.value)))
	emit('success', getFileIds(filterResponse(fileList.value)))
	isLoading.value = false
}, 300)

async function handleRemove(file) {
	isLoading.value = true
	try {
		await files.deleteUrlApi({
			fileIds: [file.id]
		})
		number.value--
		fileList.value = fileList.value.filter(item => item.id !== file.id)
		updateModelValue()
		emit('success', {})
		isLoading.value = false
	} catch (e) {
		isLoading.value = false
		console.log(e);
	}
}

function handleUploadSuccess(res) {
	console.log('handleUploadSuccess', res)
	isLoading.value = false
	fileList.value.push(res.data)
	number.value++
	multipleCount--
	if (multipleCount === 0) {
		updateModelValue()
	}
}

function handleBeforeUpload(file) {
	console.log('handleBeforeUpload', file)
	isLoading.value = true
	let isImg = false
	if (props.accept.length) {
		let fileExtension = ''
		if (file.name.toLowerCase().lastIndexOf('.') > -1) {
			fileExtension = file.name.toLowerCase().slice(file.name.toLowerCase().lastIndexOf('.'))
		}
		isImg = props.accept.some(type => {
			if (file.type.indexOf(type) > -1) return true
			if (fileExtension && fileExtension.indexOf(type) > -1) return true
			return false
		})
	} else {
		isImg = file.type.indexOf('image') > -1
	}
	if (!isImg) {
		ElMessage.error(`文件格式不正确, 请上传${props.accept.join('/')}格式文件!`)
		isLoading.value = false
		return false
	}
	if (props.fileSize) {
		const isLt = file.size / 1024 / 1024 < props.fileSize
		if (!isLt) {
			ElMessage.error(`上传头文件大小不能超过 ${props.fileSize} MB!`)
			isLoading.value = false
			return false
		}
	}
	multipleCount++
}

// 文件个数超出
function handleExceed() {
	ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`)
}

// 上传失败
// function handleUploadError() {
// ElMessage.error(`上传失败`)
// }

// 预览
function previewFile(file) {
	if (!props.preview) return

	const officeFiles = ['.docx', '.pptx', '.xlsx', '.doc', '.ppt', '.xls']
	const pdfFiles = ['.pdf']

	// 根据file.url确定是否是office文件
	const isOffice = officeFiles.some(item => file.name.indexOf(item) > -1)
	const isPdf = pdfFiles.some(item => file.name.indexOf(item) > -1)
	const isBlob = file.url.startsWith('blob:')

	if (isOffice) {
		let fileUrl = file.url
		if (isBlob) {
			fileUrl = file.response.data.url
		}
		dialogUrl.value = 'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(fileUrl)
	} else if (isPdf) {
		dialogUrl.value = isBlob ? file.response.data.url : file.url
	} else {
		// window.location.href = isBlob ? file.response.data.url : file.url
		window.open(isBlob ? file.response.data.url : file.url)
		return
	}

	dialogTitle.value = file.name
	dialogVisible.value = true
}

function httpRequest(options) {
	const data = new FormData()
	const params = { file: options.file, source: props.source }
	for (const key in params) {
		data.append(key, params[key])
	}
	return request({
		url: '/service-file/upload',
		method: 'post',
		data
	})
}
</script>

<style scoped lang="scss">
.upload-file-uploader {
	margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {
	border: 1px solid #e4e7ed;
	line-height: 2;
	margin-bottom: 10px;
	position: relative;
}
.upload-file-list .ele-upload-list__item-content {
	display: flex;
	justify-content: space-between;
	align-items: center;
	color: inherit;
}
.ele-upload-list__item-content-action .el-link {
	margin-right: 10px;
}
.el-upload__tip {
	display: inline-block;
	margin-left: 10px;
	line-height: 1.5;
}
</style>
