mirror of
https://github.com/VickScarlet/lifeRestart.git
synced 2026-04-16 12:52:41 +08:00
增加微信小程序版
This commit is contained in:
287
liferestartWX/utils/wux/input-number/index.js
Normal file
287
liferestartWX/utils/wux/input-number/index.js
Normal file
@@ -0,0 +1,287 @@
|
||||
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()
|
||||
},
|
||||
})
|
||||
6
liferestartWX/utils/wux/input-number/index.json
Normal file
6
liferestartWX/utils/wux/input-number/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"wux-icon": "../icon/index"
|
||||
}
|
||||
}
|
||||
9
liferestartWX/utils/wux/input-number/index.wxml
Normal file
9
liferestartWX/utils/wux/input-number/index.wxml
Normal file
@@ -0,0 +1,9 @@
|
||||
<view class="wux-class {{ classes.wrap }}">
|
||||
<view bindlongpress="onLongpress" bindtap="onTap" bindtouchend="onTouchEnd" touchcancel="onTouchCancel" data-type="sub" class="wux-sub-class {{ classes.sub }}">
|
||||
<wux-icon wux-class="{{ classes.icon }}" type="ios-remove"></wux-icon>
|
||||
</view>
|
||||
<input bindinput="onInput" bindfocus="onFocus" bindblur="onBlur" value="{{ inputValue }}" disabled="{{ disabled }}" type="number" class="wux-input-class {{ classes.input }}" />
|
||||
<view bindlongpress="onLongpress" bindtap="onTap" bindtouchend="onTouchEnd" touchcancel="onTouchCancel" data-type="add" class="wux-add-class {{ classes.add }}">
|
||||
<wux-icon wux-class="{{ classes.icon }}" type="ios-add"></wux-icon>
|
||||
</view>
|
||||
</view>
|
||||
118
liferestartWX/utils/wux/input-number/index.wxss
Normal file
118
liferestartWX/utils/wux/input-number/index.wxss
Normal file
@@ -0,0 +1,118 @@
|
||||
.wux-input-number {
|
||||
position: relative;
|
||||
display: -ms-flexbox;
|
||||
display: flex
|
||||
}
|
||||
.wux-input-number__input {
|
||||
width: 96rpx;
|
||||
height: 52rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 52rpx;
|
||||
color: rgba(0,0,0,.65);
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
padding: 6rpx 0;
|
||||
text-align: center;
|
||||
min-height: inherit;
|
||||
box-sizing: border-box
|
||||
}
|
||||
.wux-input-number__selector {
|
||||
width: 68rpx;
|
||||
height: 52rpx;
|
||||
font-size: 48rpx;
|
||||
line-height: 52rpx;
|
||||
color: #33cd5f;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
box-sizing: border-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center
|
||||
}
|
||||
.wux-input-number__selector--disabled {
|
||||
color: #ccc!important
|
||||
}
|
||||
.wux-input-number__selector--sub {
|
||||
border-right: none;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 4rpx 0 0 4rpx
|
||||
}
|
||||
.wux-input-number__selector--add {
|
||||
border-left: none;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 0 4rpx 4rpx 0
|
||||
}
|
||||
.wux-input-number__icon {
|
||||
font-size: inherit!important;
|
||||
vertical-align: middle;
|
||||
line-height: inherit
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__input {
|
||||
border-color: transparent
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector {
|
||||
width: 52rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #33cd5f
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--disabled {
|
||||
border-color: #ccc!important
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--light {
|
||||
color: #ddd
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--light {
|
||||
border-color: #ddd
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--stable {
|
||||
color: #b2b2b2
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--stable {
|
||||
border-color: #b2b2b2
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--positive {
|
||||
color: #387ef5
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--positive {
|
||||
border-color: #387ef5
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--calm {
|
||||
color: #11c1f3
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--calm {
|
||||
border-color: #11c1f3
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--assertive {
|
||||
color: #ef473a
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--assertive {
|
||||
border-color: #ef473a
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--balanced {
|
||||
color: #33cd5f
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--balanced {
|
||||
border-color: #33cd5f
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--energized {
|
||||
color: #ffc900
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--energized {
|
||||
border-color: #ffc900
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--royal {
|
||||
color: #886aea
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--royal {
|
||||
border-color: #886aea
|
||||
}
|
||||
.wux-input-number .wux-input-number__selector--dark {
|
||||
color: #444
|
||||
}
|
||||
.wux-input-number--circle .wux-input-number__selector--dark {
|
||||
border-color: #444
|
||||
}
|
||||
135
liferestartWX/utils/wux/input-number/utils.js
Normal file
135
liferestartWX/utils/wux/input-number/utils.js
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* https://github.com/nefe/number-precision
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
/**
|
||||
* @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
|
||||
* 问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
|
||||
*/
|
||||
/**
|
||||
* 把错误的数据转正
|
||||
* strip(0.09999999999999998)=0.1
|
||||
*/
|
||||
function strip(num, precision) {
|
||||
if (precision === void 0) { precision = 12; }
|
||||
return +parseFloat(num.toPrecision(precision));
|
||||
}
|
||||
/**
|
||||
* Return digits length of a number
|
||||
* @param {*number} num Input number
|
||||
*/
|
||||
function digitLength(num) {
|
||||
// Get digit length of e
|
||||
var eSplit = num.toString().split(/[eE]/);
|
||||
var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
|
||||
return len > 0 ? len : 0;
|
||||
}
|
||||
/**
|
||||
* 把小数转成整数,支持科学计数法。如果是小数则放大成整数
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function float2Fixed(num) {
|
||||
if (num.toString().indexOf('e') === -1) {
|
||||
return Number(num.toString().replace('.', ''));
|
||||
}
|
||||
var dLen = digitLength(num);
|
||||
return dLen > 0 ? strip(num * Math.pow(10, dLen)) : num;
|
||||
}
|
||||
/**
|
||||
* 检测数字是否越界,如果越界给出提示
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function checkBoundary(num) {
|
||||
if (_boundaryCheckingState) {
|
||||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
|
||||
console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 精确乘法
|
||||
*/
|
||||
function times(num1, num2) {
|
||||
var others = [];
|
||||
for (var _i = 2; _i < arguments.length; _i++) {
|
||||
others[_i - 2] = arguments[_i];
|
||||
}
|
||||
if (others.length > 0) {
|
||||
return times.apply(void 0, [times(num1, num2), others[0]].concat(others.slice(1)));
|
||||
}
|
||||
var num1Changed = float2Fixed(num1);
|
||||
var num2Changed = float2Fixed(num2);
|
||||
var baseNum = digitLength(num1) + digitLength(num2);
|
||||
var leftValue = num1Changed * num2Changed;
|
||||
checkBoundary(leftValue);
|
||||
return leftValue / Math.pow(10, baseNum);
|
||||
}
|
||||
/**
|
||||
* 精确加法
|
||||
*/
|
||||
function plus(num1, num2) {
|
||||
var others = [];
|
||||
for (var _i = 2; _i < arguments.length; _i++) {
|
||||
others[_i - 2] = arguments[_i];
|
||||
}
|
||||
if (others.length > 0) {
|
||||
return plus.apply(void 0, [plus(num1, num2), others[0]].concat(others.slice(1)));
|
||||
}
|
||||
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
/**
|
||||
* 精确减法
|
||||
*/
|
||||
function minus(num1, num2) {
|
||||
var others = [];
|
||||
for (var _i = 2; _i < arguments.length; _i++) {
|
||||
others[_i - 2] = arguments[_i];
|
||||
}
|
||||
if (others.length > 0) {
|
||||
return minus.apply(void 0, [minus(num1, num2), others[0]].concat(others.slice(1)));
|
||||
}
|
||||
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
/**
|
||||
* 精确除法
|
||||
*/
|
||||
function divide(num1, num2) {
|
||||
var others = [];
|
||||
for (var _i = 2; _i < arguments.length; _i++) {
|
||||
others[_i - 2] = arguments[_i];
|
||||
}
|
||||
if (others.length > 0) {
|
||||
return divide.apply(void 0, [divide(num1, num2), others[0]].concat(others.slice(1)));
|
||||
}
|
||||
var num1Changed = float2Fixed(num1);
|
||||
var num2Changed = float2Fixed(num2);
|
||||
checkBoundary(num1Changed);
|
||||
checkBoundary(num2Changed);
|
||||
return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1)));
|
||||
}
|
||||
/**
|
||||
* 四舍五入
|
||||
*/
|
||||
function round(num, ratio) {
|
||||
var base = Math.pow(10, ratio);
|
||||
return divide(Math.round(times(num, base)), base);
|
||||
}
|
||||
var _boundaryCheckingState = true;
|
||||
/**
|
||||
* 是否进行边界检查,默认开启
|
||||
* @param flag 标记开关,true 为开启,false 为关闭,默认为 true
|
||||
*/
|
||||
function enableBoundaryChecking(flag) {
|
||||
if (flag === void 0) { flag = true; }
|
||||
_boundaryCheckingState = flag;
|
||||
}
|
||||
|
||||
var index = { strip: strip, plus: plus, minus: minus, times: times, divide: divide, round: round, digitLength: digitLength, float2Fixed: float2Fixed, enableBoundaryChecking: enableBoundaryChecking };
|
||||
|
||||
export default index;
|
||||
Reference in New Issue
Block a user