<template>
	<div :key="uploadKey" class="dish-image-upload">
		<el-upload ref="upload" action="" :limit="limit" :http-request="httpRequest" :multiple="true"
			:disabled="currentAuth === 'view'" :on-exceed="onExceed" :show-file-list="false" :on-change="changes"
			:on-progress="uploadProcess" :file-list="fileList" accept=".jpg,.jpeg,.png,.gif,.bmp">
			<template v-if="currentAuth === 'view'" #tip>
				<el-button :loading="loading" type="primary" size="default" :disabled="true">点击上传</el-button>
			</template>
			<template v-else #trigger>
				<el-button :loading="loading" type="primary" size="default">点击上传</el-button>
			</template>
			<template #tip>
				<div class="el-upload__tip">
					支持上传多张图片，格式限 JPG、JPEG、PNG、GIF、BMP，单张不超过 {{ maxValue }}MB
				</div>
			</template>
		</el-upload>

		<el-progress v-if="progressFlag" :percentage="loadProgress" style="margin-top: 10px"></el-progress>

		<div class="image-list">
			<div class="image-item" v-for="(item, index) in dataListNew" :key="item.url || item.uid || index">
				<el-image class="image-thumb" :src="item.lsUrl || item.url" :preview-src-list="previewList"
					:initial-index="index" fit="cover" hide-on-click-modal :preview-teleported="true" :z-index="9999">
					<template #error>
						<div class="image-error">图片</div>
					</template>
				</el-image>
				<div v-if="currentAuth !== 'view'" class="image-actions">
					<el-tooltip effect="dark" content="删除" placement="top">
						<el-icon style="cursor: pointer;">
							<Delete @click="deleteById(item, index)" />
						</el-icon>
					</el-tooltip>
				</div>
				<el-tooltip effect="dark" :content="item.name" placement="top">
					<div class="image-name">{{ item.name }}</div>
				</el-tooltip>
			</div>
		</div>
	</div>
</template>

<script>
import OSSSerivce, {
	httpRequest,
	fileName,
	beforeAvatarUpload
} from '@/api/sys/OSSService'
import moment from 'moment'
export default {
	props: {
		modelValue: {
			type: String,
			default: ''
		},
		auth: {
			type: String,
			default: ''
		},
		limit: {
			type: Number,
			default: 9
		},
		directory: {
			type: String,
			default: 'dish'
		},
		maxSize: {
			type: Number,
			default: 10
		}
	},
	data() {
		return {
			uploadKey: '',
			progressFlag: false,
			loadProgress: 0,
			fileList: [],
			dataList: [],
			dataListNew: [],
			ossService: null,
			localAuth: '',
			uploadDirectory: 'dish',
			maxValue: 10,
			loading: false,
			fileLoading: true,
			innerValue: '',
			setValueKey: 0
		}
	},
	computed: {
		previewList() {
			return this.dataListNew.map(item => item.lsUrl || item.url).filter(item => item)
		},
		currentAuth() {
			return this.localAuth || this.auth
		}
	},
	watch: {
		modelValue(val) {
			if (val !== this.innerValue) {
				this.setValue(val)
			}
		}
	},
	created() {
		this.ossService = new OSSSerivce()
	},
	mounted() {
		this.uploadDirectory = this.directory || 'dish'
		this.maxValue = this.maxSize || 10
		this.setValue(this.modelValue)
	},
	methods: {
		async newUpload(auth, value, directory, maxValue) {
			this.localAuth = auth
			this.uploadDirectory = directory || 'dish'
			this.maxValue = maxValue || 10
			await this.setValue(value)
		},
		async setValue(value) {
			const key = ++this.setValueKey
			const urls = this.parseValue(value)
			this.innerValue = urls.join(',')
			this.dataList = []
			this.dataListNew = []
			this.fileList = []
			this.fileLoading = false
			for (const url of urls) {
				const item = {
					name: this.getFileNameByUrl(url),
					url: url,
					status: 'success'
				}
				await this.fillPreviewUrl(item)
				if (key !== this.setValueKey) {
					return
				}
				this.dataList.push(item)
				this.dataListNew.push(item)
				this.fileList.push(item)
			}
			this.fileLoading = true
		},
		parseValue(value) {
			if (value === undefined || value === null || value === '') {
				return []
			}
			if (Array.isArray(value)) {
				return value.map(item => item.url || item).filter(item => item)
			}
			return value.split(',').map(item => item.trim()).filter(item => item)
		},
		async httpRequest(file) {
			await httpRequest(file, fileName(file), this.uploadDirectory, this.maxValue)
		},
		uploadProcess(event) {
			this.progressFlag = true
			this.loadProgress = parseInt(event.percent)
			if (this.loadProgress >= 100) {
				this.loadProgress = 100
				setTimeout(() => {
					this.progressFlag = false
				}, 1000)
			}
		},
		async changes(file) {
			if (file.status === 'ready') {
				return
			}
			if (this.dataListNew.length >= this.limit) {
				this.$message.warning(`当前限制上传 ${this.limit} 张图片`)
				return
			}
			if (!this.isImage(file.name)) {
				this.$message.warning('仅支持 JPG、JPEG、PNG、GIF、BMP 图片')
				return
			}
			if (!beforeAvatarUpload(file.raw || file, [], this.maxValue)) {
				this.$message.error('图片大小不能超过 ' + this.maxValue + ' MB')
				return
			}
			const url = file.raw && file.raw.url ? file.raw.url : file.url
			if (!url) {
				return
			}
			const exists = this.dataListNew.some(item => item.url === url || item.name === file.name)
			if (exists) {
				this.$message.error(`${file.name}已存在，无法重复上传`)
				return
			}
			const item = {
				name: file.name,
				url: url,
				status: 'success',
				createTime: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
				createBy: {
					id: this.$store.state.user.id,
					name: this.$store.state.user.name
				}
			}
			await this.fillPreviewUrl(item)
			this.fileList.push(item)
			this.dataList.push(item)
			this.dataListNew.push(item)
			this.emitValue()
		},
		async fillPreviewUrl(item) {
			if (!item.url) {
				return
			}
			if (item.url.indexOf('http') === 0) {
				item.lsUrl = item.url
				return
			}
			try {
				item.lsUrl = await this.ossService.getTemporaryUrl(item.url)
			} catch (e) {
				item.lsUrl = item.url
			}
		},
		deleteById(row, index) {
			this.dataListNew.splice(index, 1)
			this.dataList = this.dataList.filter(item => item.url !== row.url)
			this.fileList = this.fileList.filter(item => item.url !== row.url)
			this.emitValue()
		},
		clearUpload() {
			this.$refs.upload && this.$refs.upload.clearFiles()
			this.dataList = []
			this.dataListNew = []
			this.fileList = []
			this.innerValue = ''
			this.$emit('update:modelValue', '')
		},
		getDataList() {
			return this.dataListNew
		},
		checkProgress() {
			if (this.progressFlag === true) {
				this.$message.warning('请等待图片上传完成后再进行操作')
				return true
			}
			if (this.fileLoading === false) {
				this.$message.warning('请等待图片加载完成后再进行操作')
				return true
			}
			const invalidFile = this.dataListNew.find(file => !file.url)
			if (invalidFile) {
				this.$message.warning(`${invalidFile.name}的URL为空，请检查后重新上传`)
				return true
			}
			return false
		},
		emitValue() {
			const value = this.dataListNew.map(item => item.url).filter(item => item).join(',')
			this.innerValue = value
			this.$emit('update:modelValue', value)
		},
		isImage(name) {
			const suffix = (name || '').substring((name || '').lastIndexOf('.') + 1).toLowerCase()
			return ['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(suffix)
		},
		getFileNameByUrl(url) {
			if (!url) {
				return ''
			}
			const arr = url.split('/')
			return arr[arr.length - 1]
		},
		onExceed() {
			this.$message.warning(`当前限制上传 ${this.limit} 张图片`)
		}
	}
}
</script>

<style scoped>
.dish-image-upload {
	width: 100%;
}

.image-list {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 10px;
}

.image-item {
	width: 104px;
	position: relative;
	border-radius: 4px;
	background-color: #f7f9fa;
	padding: 6px;
}

.image-thumb {
	width: 92px;
	height: 92px;
	border-radius: 4px;
	background-color: #f0f2f5;
}

.image-actions {
	position: absolute;
	top: 6px;
	right: 6px;
	width: 24px;
	height: 24px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 0 4px 0 4px;
	background: rgba(245, 108, 108, 0.9);
	color: #fff;
}

.image-name {
	margin-top: 4px;
	font-size: 12px;
	line-height: 18px;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.image-error {
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #909399;
	font-size: 12px;
}

.el-upload__tip {
	color: #909399;
	line-height: 20px;
}
</style>
