榆山数据端小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
7.1 KiB

import baseComponent from '../helpers/baseComponent'
import classNames from '../helpers/classNames'
import eventsMixin from '../helpers/eventsMixin'
import NP from './utils'
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1
const toNumberWhenUserInput = (num) => {
if (/\.\d*0$/.test(num) || num.length > 16) {
return num
}
if (isNaN(num)) {
return num
}
return Number(num)
}
const getValidValue = (value, min, max) => {
let val = parseFloat(value)
if (isNaN(val)) {
return value
}
if (val < min) {
val = min
}
if (val > max) {
val = max
}
return val
}
const defaultEvents = {
onChange() {},
onFocus() {},
onBlur() {},
}
baseComponent({
behaviors: [eventsMixin({ defaultEvents })],
externalClasses: ['wux-sub-class', 'wux-input-class', 'wux-add-class'],
relations: {
'../field/index': {
type: 'ancestor',
},
},
properties: {
prefixCls: {
type: String,
value: 'wux-input-number',
},
shape: {
type: String,
value: 'square',
},
min: {
type: Number,
value: -MAX_SAFE_INTEGER,
},
max: {
type: Number,
value: MAX_SAFE_INTEGER,
},
step: {
type: Number,
value: 1,
},
defaultValue: {
type: Number,
value: 0,
},
value: {
type: Number,
value: 0,
},
disabled: {
type: Boolean,
value: true,
},
longpress: {
type: Boolean,
value: false,
},
color: {
type: String,
value: 'balanced',
},
controlled: {
type: Boolean,
value: false,
},
},
data: {
inputValue: 0,
disabledMin: false,
disabledMax: false,
},
computed: {
classes: ['prefixCls, shape, color, disabledMin, disabledMax', function(prefixCls, shape, color, disabledMin, disabledMax) {
const wrap = classNames(prefixCls, {
[`${prefixCls}--${shape}`]: shape,
})
const sub = classNames(`${prefixCls}__selector`, {
[`${prefixCls}__selector--sub`]: true,
[`${prefixCls}__selector--${color}`]: color,
[`${prefixCls}__selector--disabled`]: disabledMin,
})
const add = classNames(`${prefixCls}__selector`, {
[`${prefixCls}__selector--add`]: true,
[`${prefixCls}__selector--${color}`]: color,
[`${prefixCls}__selector--disabled`]: disabledMax,
})
const icon = `${prefixCls}__icon`
const input = `${prefixCls}__input`
return {
wrap,
sub,
add,
icon,
input,
}
}],
},
observers: {
value(newVal) {
if (this.data.controlled) {
this.setValue(newVal, false)
}
},
'inputValue, min, max'(inputValue, min, max) {
const disabledMin = inputValue <= min
const disabledMax = inputValue >= max
this.setData({
disabledMin,
disabledMax,
})
},
},
methods: {
/**
* 更新值
*/
updated(inputValue) {
if (this.hasFieldDecorator) return
if (this.data.inputValue !== inputValue) {
this.setData({ inputValue })
}
},
/**
* 设置值
*/
setValue(value, runCallbacks = true) {
const { min, max } = this.data
const inputValue = NP.strip(getValidValue(value, min, max))
this.updated(inputValue)
if (runCallbacks) {
this.triggerEvent('change', { value: inputValue })
}
},
/**
* 数字计算函数
*/
calculation(type, isLoop) {
const {
disabledMax,
disabledMin,
inputValue,
step,
longpress,
controlled,
} = this.data
// add
if (type === 'add') {
if (disabledMax) return
this.setValue(NP.plus(inputValue, step))
}
// sub
if (type === 'sub') {
if (disabledMin) return
this.setValue(NP.minus(inputValue, step))
}
// longpress
if (longpress && isLoop) {
this.timeout = setTimeout(() => this.calculation(type, isLoop), 100)
}
},
/**
* 当键盘输入时触发 input 事件
*/
onInput(e) {
this.clearInputTimer()
this.inputTime = setTimeout(() => {
const value = toNumberWhenUserInput(e.detail.value)
this.setValue(value)
}, 300)
},
/**
* 输入框聚焦时触发
*/
onFocus(e) {
this.triggerEvent('focus', e.detail)
},
/**
* 输入框失去焦点时触发
*/
onBlur(e) {
// always set input value same as value
this.setData({
inputValue: this.data.inputValue,
})
this.triggerEvent('blur', e.detail)
},
/**
* 手指触摸后超过350ms再离开
*/
onLongpress(e) {
const { type } = e.currentTarget.dataset
const { longpress } = this.data
if (longpress) {
this.calculation(type, true)
}
},
/**
* 手指触摸后马上离开
*/
onTap(e) {
const { type } = e.currentTarget.dataset
const { longpress } = this.data
if (!longpress || longpress && !this.timeout) {
this.calculation(type, false)
}
},
/**
* 手指触摸动作结束
*/
onTouchEnd() {
this.clearTimer()
},
/**
* 手指触摸动作被打断如来电提醒弹窗
*/
onTouchCancel() {
this.clearTimer()
},
/**
* 清除长按的定时器
*/
clearTimer() {
if (this.timeout) {
clearTimeout(this.timeout)
this.timeout = null
}
},
/**
* 清除输入框的定时器
*/
clearInputTimer() {
if (this.inputTime) {
clearTimeout(this.inputTime)
this.inputTime = null
}
},
},
attached() {
const { defaultValue, value, controlled } = this.data
const inputValue = controlled ? value : defaultValue
this.setValue(inputValue, false)
},
detached() {
this.clearTimer()
this.clearInputTimer()
},
})