<template>
	<view class="stepper-box">
		<view class="reduce" :style="{'height': height + 'px'}" :class="{'disabled': priceValue <= min || disabled}" @click.stop="onReduce"></view>
		<input class="uni-input" :style="{'width': width + 'px','height': height + 'px'}" :class="{'disabled': disabled}" :disabled="disabled" @click.stop @input="onInput"
			v-model="priceValue" type="digit" />
		<view class="plus" :style="{'height': height + 'px'}" :class="{'disabled': priceValue >= maxNumber || disabled}" @click.stop="onPlus"></view>
	</view>
</template>

<script>
	/**
	 * 步进器
	 * @description 步进器
	 * @property {Number}
	 */
	import {
		debounce
	} from '@/utils/util.js'
	let timer = null;
	export default {
		props: {
			value: {
				type: Number,
				default: 1
			},
			digit: {
				type: Number,
				default: 4
			},
			min: {
				type: [Number, String, undefined],
				default: 0.001
			},
			max: {
				type: [Number, String, undefined],
				default: Number.MAX_SAFE_INTEGER
			},
			disabled: {
				type: Boolean,
				default: false
			},
			item: {
				type: Object
			},
			height: {
				type: [Number, String],
				default: 26
			},
			width: {
				type: [Number, String],
				default: 44
			}
		},
		watch: {
			value: {
				handler(newV) {
					this.priceValue = Number(newV)
				},
				immediate: true
			}
		},
		data() {
			return {
				priceValue: 1
			}
		},
		computed: {
			maxNumber() {
				let newVal = ''
				if (['string', 'number'].includes(typeof this.max) && this.max !== '' && !isNaN(Number(this.max))) {
					newVal = Number(this.max)
				} else {
					newVal = Number.MAX_SAFE_INTEGER
				}
				return newVal
			}
		},
		methods: {
			onInput: debounce(function(e) {
				const {
					value
				} = e.detail || {
					value: 1
				}
				let formatted = String(value).replace(/[^0-9.]/g, '')
				const pair = formatted.split('.');
				if (formatted.indexOf('.') !== -1) {
					formatted = `${pair[0]}.${pair[1].slice(0, 4)}`
				}
				let priceMin = Number(this.min) || 0.0001
				formatted = Math.max(Math.min(this.maxNumber, formatted), priceMin)
				this.priceValue = formatted
				const digitValue = parseFloat(Number(formatted).toFixed(this.digit))
				this.$emit('input', digitValue, this.item)
			}, 1000),
			// 减少数量
			onReduce() {
				if (this.priceValue <= this.min || this.disabled) return
				let number = this.priceValue > (this.min + 1) ? (this.priceValue - 1).toFixed(4) : this.min
				this.priceValue = Math.floor(Number(number))
				if (timer) {
					clearTimeout(timer)
					timer = null
				}
				let that = this
				timer = setTimeout(() => {
					const digitValue = parseFloat(Number(number).toFixed(this.digit))
					this.$emit('reduce', digitValue, that.item)
					clearTimeout(timer)
					timer = null
				}, 300)
			},
			// 增加数量
			onPlus() {
				if (this.priceValue >= this.maxNumber || this.disabled) return
				let number = this.priceValue > (this.maxNumber - 1) ? this.maxNumber : (this.priceValue + 1).toFixed(4)
				this.priceValue = Number(number)
				if (timer) {
					clearTimeout(timer)
					timer = null
				}
				let that = this
				timer = setTimeout(() => {
					const digitValue = parseFloat(Number(number).toFixed(this.digit))
					this.$emit('plus', digitValue, that.item)
					clearTimeout(timer)
					timer = null
				}, 300)
			}
		}
	}
</script>
<style lang="scss">
	.stepper-box {
		display: inline-flex;
		align-self: flex-end;

		.reduce {
			flex: none;
			box-sizing: border-box;
			width: 32px;
			border: 1rpx solid #D5E2F3;
			border-right: 1rpx solid #D5E2F3;
			border-top-left-radius: 4px;
			border-bottom-left-radius: 4px;
			position: relative;

			&.disabled {
				background-color: #f5f5f5;
			}

			&::after {
				content: " ";
				position: absolute;
				top: 50%;
				left: 12px;
				width: 8px;
				height: 0;
				border-top: 1px solid #D5E2F3;
			}
		}

		.uni-input {
			flex: auto;
			box-sizing: border-box;
			text-align: center;
			font-size: 12px;
			color: #B60001;
			border-top: 1rpx solid #D5E2F3;
			border-bottom: 1rpx solid #D5E2F3;

			&.disabled {
				color: #D5E2F3;
				background-color: #f5f5f5;
			}
		}

		.plus {
			flex: none;
			box-sizing: border-box;
			width: 32px;
			border: 1rpx solid #D5E2F3;
			border-left: 1rpx solid #D5E2F3;
			border-top-right-radius: 4px;
			border-bottom-right-radius: 4px;
			position: relative;

			&.disabled {
				background-color: #f5f5f5;
			}

			&::before {
				content: " ";
				position: absolute;
				top: 50%;
				left: 12px;
				width: 8px;
				height: 0;
				border-top: 1px solid #D5E2F3;
			}

			&::after {
				content: " ";
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translateY(-50%);
				width: 0;
				height: 8px;
				border-right: 1px solid #D5E2F3;
			}
		}
	}
</style>