<template>
	<!-- 多图上传支持拖拽排序 -->
	<view class="con">
		<movable-area class="area" :style="{ height: areaHeight }" @mouseenter="mouseenter" @mouseleave="mouseleave">
			<block v-for="(item, index) in imageList" :key="item.id">
				<movable-view class="view" :x="item.x" :y="item.y" direction="all" :damping="40" :disabled="item.disable" @change="onChange($event, item)"
				 @touchstart="touchstart(item)" @mousedown="touchstart(item)" @touchend="touchend(item)" @mouseup="touchend(item)"
				 :style="{ width: viewWidth + 'px', height: viewWidth + 'px', 'z-index': item.zIndex, opacity: item.opacity }">
					<view class="area-con" :style="{ width: childWidth, height: childWidth, transform: 'scale(' + item.scale + ')' }">
						<image class="pre-image" :src="item.src" mode="aspectFill"></image>
						<view class="del-con" @click="delImage(item, index)" @touchstart.stop="delImageMp(item, index)" @touchend.stop="nothing()"
						 @mousedown.stop="nothing()" @mouseup.stop="nothing()">
							<view class="del-wrap">
								<image class="del-image" src="https://renwu.xiansqx.com/img/20210813/f44b954827604db8bc9c93f0ffc88ab5.png"></image>
							</view>
						</view>
					</view>
				</movable-view>
			</block>
			<view class="add" v-if="imageList.length < number" :style="{ top: add.y, left: add.x, width: viewWidth + 'px', height: viewWidth + 'px' }"
			 @click="addImages">
				<view class="add-wrap" :style="{ width: childWidth, height: childWidth }">
					<image style="width: 192rpx;height: 192rpx;" src="https://renwu.xiansqx.com/img/20210813/f44b954827604db8bc9c93f0ffc88ab5.png"></image>
				</view>
			</view>
		</movable-area>
	</view>
</template>

<script>
  import * as websocketUtils from 'utils/websocketUtils.js';
	export default {
		data() {
			return {
				imageList: [],
				width: 0,
				add: {
					x: 0,
					y: 0
				},
				colsValue: 0,
				viewWidth: 0,
				tempItem: null,
				timer: null,
				changeStatus: true,
				preStatus: true,
			}
		},
		props: {
			// 返回排序后图片
			list: {
				type: Array,
				default: function() {
					return []
				}
			},
			// 选择图片数量限制
			number: {
				type: Number,
				default: 5
			},
			// 图片父容器宽度（实际显示的图片宽度为 imageWidth / 1.1 ），单位 rpx
			imageWidth: {
				type: Number,
				default: 230
			},
			// 图片列数（cols > 0 则 imageWidth 无效）
			cols: {
				type: Number,
				default: 3
			},
			// 图片周围空白填充，单位 rpx
			padding: {
				type: Number,
				default: 10
			},
			// 拖动图片时放大倍数 [0, ∞)
			scale: {
				type: Number,
				default: 1.1
			},
			// 拖动图片时不透明度
			opacity: {
				type: Number,
				default: 0.7
			},
			// 自定义添加（需配合 @aaddImage 事件使用）
			custom: {
				type: Boolean,
				default: false
			}
		},
		computed: {
			areaHeight() {
				if (this.imageList.length < this.number) {
					return Math.ceil((this.imageList.length + 1) / this.colsValue) * this.viewWidth + 'px'
				} else {
					return Math.ceil(this.imageList.length / this.colsValue) * this.viewWidth + 'px'
				}
			},
			childWidth() {
				return this.viewWidth - this.rpx2px(this.padding) * 2 + 'px'
			},
		},
		created() {
			this.width = uni.getSystemInfoSync().windowWidth
			this.viewWidth = this.rpx2px(this.imageWidth)
		},
		mounted() {
			const query = uni.createSelectorQuery().in(this)
			query.select('.area').boundingClientRect(data => {
				this.colsValue = Math.floor(data.width / this.viewWidth)
				if (this.cols > 0) {
					this.colsValue = this.cols
					this.viewWidth = data.width / this.cols
				}
				for (let item of this.list) {
					this.addProperties(item)
				}
			})
			query.exec()
		},
		methods: {
			onChange(e, item) {
				if (!item) return
				item.oldX = e.detail.x
				item.oldY = e.detail.y
				if (e.detail.source === 'touch') {
					if (item.moveEnd) {
						item.offset = Math.sqrt(Math.pow(item.oldX - item.absX * this.viewWidth, 2) + Math.pow(item.oldY - item.absY *
							this.viewWidth, 2))
					}
					let x = Math.floor((e.detail.x + this.viewWidth / 2) / this.viewWidth)
					if (x >= this.colsValue) return
					let y = Math.floor((e.detail.y + this.viewWidth / 2) / this.viewWidth)
					let index = this.colsValue * y + x
					if (item.index != index && index < this.imageList.length) {
						this.changeStatus = false
						for (let obj of this.imageList) {
							if (item.index > index && obj.index >= index && obj.index < item.index) {
								this.change(obj, 1)
							} else if (item.index < index && obj.index <= index && obj.index > item.index) {
								this.change(obj, -1)
							} else if (obj.id != item.id) {
								obj.offset = 0
								obj.x = obj.oldX
								obj.y = obj.oldY
								setTimeout(() => {
									this.$nextTick(() => {
										obj.x = obj.absX * this.viewWidth
										obj.y = obj.absY * this.viewWidth
									})
								}, 0)
							}
						}
						item.index = index
						item.absX = x
						item.absY = y
						this.sortList()
					}
				}
			},
			change(obj, i) {
				obj.index += i
				obj.offset = 0
				obj.x = obj.oldX
				obj.y = obj.oldY
				obj.absX = obj.index % this.colsValue
				obj.absY = Math.floor(obj.index / this.colsValue)
				setTimeout(() => {
					this.$nextTick(() => {
						obj.x = obj.absX * this.viewWidth
						obj.y = obj.absY * this.viewWidth
					})
				}, 0)
			},
			touchstart(item) {
				this.imageList.forEach(v => {
					v.zIndex = v.index + 9
				})
				item.zIndex = 99
				item.moveEnd = true
				this.tempItem = item
				this.timer = setTimeout(() => {
					item.scale = this.scale
					item.opacity = this.opacity
					clearTimeout(this.timer)
					this.timer = null
				}, 200)
			},
			touchend(item) {
				this.previewImage(item)
				item.scale = 1
				item.opacity = 1
				item.x = item.oldX
				item.y = item.oldY
				item.offset = 0
				item.moveEnd = false
				setTimeout(() => {
					this.$nextTick(() => {
						item.x = item.absX * this.viewWidth
						item.y = item.absY * this.viewWidth
						this.tempItem = null
						this.changeStatus = true
					})
				}, 0)
			},
			previewImage(item) {
				if (this.timer && this.preStatus && this.changeStatus && item.offset < 28.28) {
					clearTimeout(this.timer)
					this.timer = null
					let src = this.list.findIndex(v => v === item.src)
					uni.previewImage({
						urls: this.list,
						current: src,
						success: () => {
							this.preStatus = false
							setTimeout(() => {
								this.preStatus = true
							}, 600)
						}
					})
				} else if (this.timer) {
					clearTimeout(this.timer)
					this.timer = null
				}
			},
			mouseenter() {
				//#ifdef H5
				this.imageList.forEach(v => {
					v.disable = false
				})
				//#endif

			},
			mouseleave() {
				//#ifdef H5
				if (this.tempItem) {
					this.imageList.forEach(v => {
						v.disable = true
						v.zIndex = v.index + 9
						v.offset = 0
						v.moveEnd = false
						if (v.id == this.tempItem.id) {
							if (this.timer) {
								clearTimeout(this.timer)
								this.timer = null
							}
							v.scale = 1
							v.opacity = 1
							v.x = v.oldX
							v.y = v.oldY
							this.$nextTick(() => {
								v.x = v.absX * this.viewWidth
								v.y = v.absY * this.viewWidth
								this.tempItem = null
							})
						}
					})
					this.changeStatus = true
				}
				//#endif
			},
			addImages() {
				console.log('addImages')
				if (this.custom) {
					this.$emit('addImage')
				} else {
					let checkNumber = this.number - this.imageList.length
					uni.chooseImage({
						count: checkNumber,
						sourceType: ['album', 'camera'],
						success: res => {
							let count = checkNumber <= res.tempFilePaths.length ? checkNumber : res.tempFilePaths.length
							for (let i = 0; i < count; i++) {
								this.$queue.showLoading("上传中...");
								uni.uploadFile({ // 上传接口
									url: websocketUtils.uploadFileUrl(), //真实的接口地址
									filePath: res.tempFilePaths[i],
									name: 'file',
									success: (uploadFileRes) => {
										// this.addProperties(JSON.parse(uploadFileRes.data).data.src) //列表接口
										this.addProperties(JSON.parse(uploadFileRes.data).data)
										uni.hideLoading();
									}
								});
							}
						}
					})
				}
			},
			addImage(image) {
				this.addProperties(image)
			},
			delImage(item, index) {
				this.imageList.splice(index, 1)
				for (let obj of this.imageList) {
					if (obj.index > item.index) {
						obj.index -= 1
						obj.x = obj.oldX
						obj.y = obj.oldY
						obj.absX = obj.index % this.colsValue
						obj.absY = Math.floor(obj.index / this.colsValue)
						this.$nextTick(() => {
							obj.x = obj.absX * this.viewWidth
							obj.y = obj.absY * this.viewWidth
						})
					}
				}
				this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'
				this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'
				this.sortList()
			},
			delImageMp(item, index) {
				//#ifdef MP
				this.delImage(item, index)
				//#endif
			},
			sortList() {
				let list = this.imageList.slice()
				console.log('获取到上传图片的列表', this.imageList)
				list.sort((a, b) => {
					return a.index - b.index
				})
				for (let i = 0; i < list.length; i++) {
					list[i] = list[i].src
				}
				console.log('list', list)
				this.$emit('update:list', list)
			},
			addProperties(item) {
				let absX = this.imageList.length % this.colsValue
				let absY = Math.floor(this.imageList.length / this.colsValue)
				let x = absX * this.viewWidth
				let y = absY * this.viewWidth
				this.imageList.push({
					src: item,
					x,
					y,
					oldX: x,
					oldY: y,
					absX,
					absY,
					scale: 1,
					zIndex: 9,
					opacity: 1,
					index: this.imageList.length,
					id: this.guid(),
					disable: false,
					offset: 0,
					moveEnd: false
				})
				this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'
				this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'
				this.sortList()
			},
			nothing() {},
			rpx2px(v) {
				return this.width * v / 750
			},
			guid() {
				function S4() {
					return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
				}
				return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
			}
		}
	}
</script>

<style lang="scss" scoped>
	.con {

		// padding: 30rpx;
		.area {
			width: 100%;

			.view {
				display: flex;
				justify-content: center;
				align-items: center;

				.area-con {
					position: relative;

					.pre-image {
						width: 100%;
						height: 100%;
					}

					.del-con {
						position: absolute;
						top: -8rpx;
						right: -4rpx;
						padding: 0 0 20rpx 20rpx;

						.del-wrap {
							width: 36rpx;
							height: 36rpx;
							background-color: #ff0000;
							border-radius: 50%;
							display: flex;
							justify-content: center;
							align-items: center;

							.del-image {
								width: 20rpx;
								height: 20rpx;
							}
						}
					}
				}
			}

			.add {
				position: absolute;
				display: flex;
				justify-content: center;
				align-items: center;

				.add-wrap {
					display: flex;
					justify-content: center;
					align-items: center;
					background-color: #FFFFFF;
				}
			}
		}
	}
</style>
