<template>
	<view class="upload_box">
		<view class="upload_list">
			<view v-for="(item, index) in fileList" :key="index" class="flex_box upload_item">
				<view @click="$openFile(item.url)" class="flex_box upload_left">
					<u-image
						width="60rpx"
						height="60rpx"
						:showError="false"
						:showLoading="false"
						:src="`${$IMG_URL}/static/format/${fileTypes.indexOf(item.type) === '-1' ? 'file' : item.type}.png`"
					></u-image>
					<view class="upload_content">
						<view class="upload_name">{{ item.name }}</view>
						<view v-if="item.size" class="upload_text">{{ item.size }}</view>
					</view>
				</view>
				<u-image
					v-if="!isDetail"
					@click="deletePic(index)"
					width="48rpx"
					height="48rpx"
					:showError="false"
					:showLoading="false"
					:src="`${$IMG_URL}/static/home/icon_cancel@2x.png`"
				></u-image>
				<view class="service_check">
					<u-icon color="#FD910C" size="24rpx" :name="item.status === 'success' ? 'checkmark-circle-fill' : 'close-circle-fill'"></u-icon>
				</view>
			</view>
		</view>
		<!-- #ifdef APP -->
		<view class="upload_btn_box" v-if="(!isDetail || limit === fileList.length) && fileShow">
			<template v-if="authList['WRITE_EXTERNAL_STORAGE'] && authList['CAMERA']">
				<lsj-upload
					ref="lsjUpload"
					:wxFileType="wxFileType"
					:extension="extension"
					:childId="childId"
					:width="width"
					:height="height"
					:option="option"
					:size="fileSize"
					:count="limit"
					:multiple="multiple"
					:formats="fileType"
					:accept="fileAccept"
					:debug="debug"
					:instantly="instantly"
					@uploadEnd="onuploadEnd"
					@progress="onprogre"
					@change="change"
				>
					<view class="upload_btn">
						<u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
					</view>
				</lsj-upload>
			</template>
			<view v-else-if="!authList['WRITE_EXTERNAL_STORAGE']" class="upload_btn_auth" @tap.stop="openAuth('WRITE_EXTERNAL_STORAGE')">
				<view class="upload_btn">
					<u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
				</view>
			</view>
			<view v-else class="upload_btn_auth" @tap.stop="openAuth('CAMERA')">
				<view class="upload_btn">
					<u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
				</view>
			</view>
		</view>
		<yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" :permissionID="permissionID"></yk-authpup>
		<!-- #endif -->
		<!-- #ifndef APP -->
		<view class="upload_btn_box" v-if="(!isDetail || limit === fileList.length) && fileShow">
			<lsj-upload
				ref="lsjUpload"
				:wxFileType="wxFileType"
				:extension="extension"
				:childId="childId"
				:width="width"
				:height="height"
				:option="option"
				:size="fileSize"
				:count="limit"
				:multiple="multiple"
				:formats="fileType"
				:accept="fileAccept"
				:debug="debug"
				:instantly="instantly"
				@uploadEnd="onuploadEnd"
				@progress="onprogre"
				@change="change"
			>
				<view class="upload_btn">
					<u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
				</view>
			</lsj-upload>
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
import { mapGetters } from 'vuex'
import ykAuthpup from '@/components/yk-authpup/yk-authpup'
import { getFileName } from '@/common/request/apis/index'
export default {
	name: 'UploadFile',
	components: {
		ykAuthpup
	},
	props: {
		// 值
		value: [String, Object, Array],
		// 宽度
		width: {
			type: String,
			default: '104rpx'
		},
		// 高度
		height: {
			type: String,
			default: '104rpx'
		},
		// 数量限制
		limit: {
			type: Number,
			default: 9
		},
		// 大小限制(MB)
		fileSize: {
			type: Number,
			default: 200
		},
		// 文件类型, 例如'png, jpg, jpeg']
		fileType: {
			type: String,
			default: ''
		},
		// 文件类型, 例如'audio/*, video/*, image/*']
		fileAccept: {
			type: String,
			default: '*'
		},
		// 是否文件覆盖图片
		isOne: {
			type: Boolean,
			default: false
		},
		// 强制刷新
		fileShow: {
			type: Boolean,
			default: true
		},
		// 是否多选
		multiple: {
			type: Boolean,
			default: true
		},
		// 是否显示提示
		isShowTip: {
			type: Boolean,
			default: true
		},
		// 是否详情
		isDetail: {
			type: Boolean,
			default: false
		},
		//id
		childId: {
			type: String,
			default: 'lsjUpload'
		},
		// 微信选择文件类型
		//all=从所有文件选择，
		//video=只能选择视频文件，
		//image=只能选择图片文件，
		//file=可以选择除了图片和视频之外的其它的文件
		wxFileType: { type: String, default: 'all' },
		extension: { type: Array, default: () => ['*'] }
	},
	data() {
		return {
			fileTypes: ['bmp', 'doc', 'docx', 'gif', 'jpeg', 'jpg', 'mp3', 'mp4', 'pdf', 'png', 'ppt', 'pptx', 'rar', 'wav', 'webm', 'webp', 'xls', 'xlsx', 'zip'],
			// 上传接口参数
			option: {
				// 上传服务器地址，需要替换为你的接口地址
				url: this.$UPLOAD_URL, // 该地址非真实路径，需替换为你项目自己的接口地址
				// 上传附件的key
				name: 'file',
				// 根据你接口需求自定义请求头,默认不要写content-type,让浏览器自适配
				header: {
					token: `${this.$store.getters.token}`
				},
				// 根据你接口需求自定义body参数
				formData: {
					filename: ''
				}
			},
			// 选择文件后是否立即自动上传，true=选择后立即上传
			instantly: true,
			// 文件回显列表
			files: new Map(),
			// 微信小程序Map对象for循环不显示，所以转成普通数组，不要问为什么，我也不知道
			wxFiles: [],
			// 是否打印日志
			debug: false,
			// 文件显示列表
			fileList: [],
			// 权限判断
			permissionID: ''
		}
	},
	watch: {
		value: {
			async handler(val) {
				if (val) {
					// if (this.fileList.length > 0) return
					// 首先将值转为数组
					const list = Array.isArray(val) ? val : this.value.split(',')
					const files = []
					// 然后将数组转为对象数组
					for (let i = 0; i < list.length; i++) {
						let item = list[i]
						if (typeof item === 'string') {
							let name = item + ''
							let size = ''
							if (name && name.lastIndexOf('/') > -1) {
								const result = await getFileName({
									file_name: name,
									type: 1
								})
								name = result && result.code === 1 ? result.data.filename : name
								size = result && result.code === 1 ? this.$filterSize(result.data.filesize) : size
							}
							item = {
								name: name,
								url: this.getUrl(item),
								fullurl: item,
								size: size,
								status: 'success',
								message: '',
								type: item.slice(item.lastIndexOf('.') + 1).toLowerCase()
							}
						}
						files.push(item)
					}
					this.fileList = files
				} else {
					this.fileList = []
					return []
				}
			},
			deep: true,
			immediate: true
		}
	},
	computed: {
		// 是否显示提示
		showTip() {
			return this.isShowTip && (this.fileType || this.fileSize)
		},
		...mapGetters('auth', ['authList', 'onceIn'])
	},
	mounted() {
		// #ifdef APP
		// if (this.onceIn) {
		// 	this.$store.commit('auth/edit', {data: false, index: 'onceIn'})
		// 	this.openAuth('WRITE_EXTERNAL_STORAGE')
		// }
		// #endif
	},
	methods: {
		//打开自定义权限目的弹框
		openAuth(permissionID) {
			this.permissionID = permissionID //这个是对应的权限 ACCESS_FINE_LOCATION 位置权限 / WRITE_EXTERNAL_STORAGE 存储空间/照片权限 / CAMERA相机权限 / CALL_PHONE 拨打电话
			setTimeout(() => {
				this.$refs['authpup'].open()
			}, 500)
		},
		//用户授权权限后的回调
		changeAuth() {
			//这里是权限通过后执行自己的代码逻辑
			console.log('权限已授权，可执行自己的代码逻辑了')
			this.authList[this.permissionID] = true
			const list = { ...this.authList }
			this.$store.commit('auth/edit', { data: list, index: 'authList' })
			if (!this.authList['CAMERA']) {
				this.openAuth('CAMERA')
			}
		},
		// 手动触发
		actionClick() {
			// 强制更新视图
			this.$forceUpdate()
			console.log(this.extension)
			this.$nextTick(() => {
				this.$refs.lsjUpload.onClick()
			})
		},
		// 刷新组件
		refresh() {
			this.$refs.lsjUpload.hide()
			this.$nextTick(() => {
				setTimeout(() => {
					this.$refs.lsjUpload.show()
				}, 200)
			})
		},
		/**
		 * 某文件上传结束回调(成功失败都回调)
		 * @param {Object} item 当前上传完成的文件
		 */
		onuploadEnd(item) {
			if (item) {
				if (this.isOne) {
					this.files.clear()
					this.wxFiles = []
					this.fileList = []
				}
				// 更新当前窗口状态变化的文件
				this.files.set(item.name, item)
				this.wxFiles = [...this.files.values()]
				// 强制更新视图
				this.$forceUpdate()
				const isHas = this.fileList.find((file) => file.name === item.name)
				if (item.responseText && !isHas) {
					const result = JSON.parse(item.responseText)
					if (result.code === 1) {
						this.fileList.push({
							status: 'success',
							name: item.name,
							size: this.$filterSize(item.size),
							message: '',
							url: result.data.fullurl,
							fullurl: result.data.url,
							type: result.data.url.slice(result.data.url.lastIndexOf('.') + 1).toLowerCase()
						})
					} else {
						uni.showModal({
							content: `${item.name}上传失败，请重新上传`,
							showCancel: false
						})
					}
				}
			}
			let isAll = [...this.files.values()].find((item) => item.type !== 'success')
			if (!isAll) {
				this.setUrl()
			}
		},
		/**
		 * 上传进度回调
		 * 如果网页上md文档没有渲染出事件名称onprogre，请复制代码的小伙伴自行添加上哈，没有哪个事件是只(item)的
		 * @param {Object} item 当前正在上传的文件
		 */
		onprogre(item) {
			// 更新当前状态变化的文件
			this.files.set(item.name, item)
			// 微信小程序Map对象for循环不显示，所以转成普通数组，不要问为什么，我也不知道
			this.wxFiles = [...this.files.values()]

			// 强制更新视图
			this.$forceUpdate()
		},
		/**
		 * 文件选择回调
		 * @param {Object} files 已选择的所有文件Map集合
		 */
		change(files) {
			const list = [...files.values()]
			if (list.length === 0) return
			uni.showLoading({
				title: '上传中',
				mask: true
			})
			// 更新选择的文件
			this.files = files
			// 强制更新视图
			this.$forceUpdate()
			this.wxFiles = [...list]
		},
		/**
		 * 移除某个文件
		 * @param {Object} name 带后缀名的文件名称
		 */
		deletePic(index) {
			// name=指定文件名，不传name默认移除所有文件
			this.$refs.lsjUpload.clear(this.fileList[index].name)
			this.fileList.splice(index, 1)
			this.setUrl()
		},
		// 设置图片
		setUrl() {
			let that = this
			let urls = []
			let list = []
			for (let i = 0; i < that.fileList.length; i++) {
				if (that.fileList[i].status === 'success') {
					urls.push(that.fileList[i].fullurl)
					list.push({
						url: that.fileList[i].fullurl,
						fullurl: that.fileList[i].url,
						index: i,
						name: that.fileList[i].name
					})
				}
			}
			that.$emit('input', urls.join(','))
			that.$emit('change', list)
			uni.hideLoading()
		},
		// 设置域名
		getUrl(url) {
			if (url.indexOf('http') === -1) url = this.$UPLOAD_BASE + url
			return url
		}
	}
}
</script>

<style lang="scss" scoped>
.upload_box {
	position: relative;
	.upload_btn_box {
		position: relative;
		z-index: 99;
		.upload_btn_auth {
			width: 96rpx;
			height: 96rpx;
		}
		.upload_btn {
			width: 96rpx;
			height: 96rpx;
			position: relative;
		}
	}

	.upload_list {
		.upload_item {
			background: rgba(134, 158, 180, 0.1);
			border-radius: 8rpx;
			padding: 8rpx 24rpx 8rpx 8rpx;
			margin-bottom: 24rpx;
			position: relative;

			.upload_left {
				width: calc(100% - 48rpx);
				padding-left: 16rpx;
			}

			.upload_content {
				width: calc(100% - 96rpx);
				padding: 0 16rpx;

				.upload_name {
					width: 100%;
					word-break: break-all;
					font-size: 28rpx;
					color: #333333;
					line-height: 40rpx;
					margin-bottom: 8rpx;
				}

				.upload_text {
					font-size: 24rpx;
					color: #999999;
					line-height: 34rpx;
				}
			}

			.service_check {
				position: absolute;
				top: 0;
				right: 0;
				z-index: 10;
				text-align: center;
				padding: 6rpx;
			}
		}
	}
}
</style>
