316 lines
9.2 KiB
Vue
316 lines
9.2 KiB
Vue
<template>
|
||
<view class="tm-stepper d-inline-block">
|
||
<view class="flex-center" :style="{ width: `${width}rpx` }">
|
||
<view :class="[isJianDisabled||disabled?'opacity-6 gray':'']">
|
||
<tm-button @touchcancel="endlongpressEvent" @touchend="endlongpressEvent"
|
||
@touchstart="$emit('touchstart', 'minus')" @longpress="longpressEvent('-')" :fllowTheme="fllowTheme"
|
||
:disabled="isJianDisabled || disabled ? true : false"
|
||
:shadow="isJianDisabled || disabled ? 0 : shadwo_num" :black="black_tmeme" @click="setStep('-')"
|
||
:item-class="circular?' pa-0':` round-l-${round} `" icon-size="24" :round="circular?round:0"
|
||
:theme="disabled ? '' : color_tmeme" :width="height" :height="height" block icon="icon-minus">
|
||
</tm-button>
|
||
</view>
|
||
<input v-if="fixed!=0" @blur="inputVal" @input="inputVal" :disabled="(disabled||disabledInput)"
|
||
v-model="setVal" type="digit" :style="{ height: `${height}rpx`, width: `calc(100% - ${height}rpx)` }"
|
||
class="text-align-center text-size-n fulled"
|
||
:class="[`text-${font_color}`, black_tmeme&&!circular ? 'grey-darken-4 bk' : '',black_tmeme? 'text-grey-lighten-4' : '',circular?'':'grey-lighten-4']" />
|
||
<input v-if="fixed==0" @blur="inputVal" @input="inputVal" :disabled="(disabled||disabledInput)"
|
||
v-model="setVal" type="number" :style="{ height: `${height}rpx`, width: `calc(100% - ${height}rpx)` }"
|
||
class="text-align-center grey-lighten-4 text-size-n fulled"
|
||
:class="[`text-${font_color}`, black_tmeme&&!circular ? 'grey-darken-4 bk' : '',black_tmeme? 'text-grey-lighten-4' : '',circular?'':'grey-lighten-4']" />
|
||
<view :class="[isAddDisabled||disabled?'opacity-6 gray':'']">
|
||
<tm-button @touchcancel="endlongpressEvent" @touchend="endlongpressEvent"
|
||
@touchstart="$emit('touchstart', 'add')" @longpress="longpressEvent('+')" :fllowTheme="fllowTheme"
|
||
:shadow="isAddDisabled || disabled ? 0 : shadwo_num" :black="black_tmeme" @click="setStep('+')"
|
||
:item-class="circular?' pa-0':` round-r-${round} `" icon-size="24" :round="circular?round:0"
|
||
:theme="disabled ? '' : color_tmeme" :disabled="isAddDisabled || disabled ? true : false"
|
||
:width="height" :height="height" block icon="icon-plus"></tm-button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
/**
|
||
* 步进器
|
||
* @property {String|Number} value = [] 默认:'',值,推荐使用value.sync或者v-model
|
||
* @property {Boolean} disabled = [] 默认:false,是否禁用
|
||
* @property {Boolean} black = [] 默认:false,是否暗黑模式。
|
||
* @property {Number|String} step = [] 默认:1, 步幅。
|
||
* @property {String} color = [] 默认:primary, 主题色。
|
||
* @property {String} fontColor = [] 默认:black, 输入框的文字主题色。
|
||
* @property {String|Number} round = [] 默认:3, 圆角。
|
||
* @property {String|Number} shadow = [] 默认:3, 圆角。
|
||
* @property {String|Number} max = [] 默认:999, 最大值。
|
||
* @property {String|Number} min = [] 默认:0, 最小值。
|
||
* @property {String|Number} width = [] 默认:200, 宽度,单位rpx。
|
||
* @property {String|Number} height = [] 默认:70, 高度,单位rpx。
|
||
* @property {String} name = [] 默认:'',提交表单时的的字段名称标识
|
||
* @property {Boolean|String} disabledInput = [] 默认:false,是否禁用输入框
|
||
* @property {Boolean|String} circular = [] 默认:false,按钮四角是否跟随圆角
|
||
* @property {Number} fixed = [] 默认:0, 小数点位数
|
||
* @example <tm-stepper value="50"></tm-stepper>
|
||
*/
|
||
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
|
||
|
||
export default {
|
||
components: {
|
||
tmButton
|
||
},
|
||
name: 'tm-stepper',
|
||
model: {
|
||
prop: 'value',
|
||
event: 'input'
|
||
},
|
||
props: {
|
||
value: {
|
||
type: Number | String,
|
||
default: 0
|
||
},
|
||
//提交表单时的的字段名称
|
||
name: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
//禁用输入功能
|
||
disabledInput: {
|
||
type: Boolean | String,
|
||
default: false
|
||
},
|
||
black: {
|
||
type: Boolean | String,
|
||
default: null
|
||
},
|
||
// 步幅,默认1
|
||
step: {
|
||
type: Number,
|
||
default: 1
|
||
},
|
||
//固定小数点位数,0表示整数
|
||
fixed: {
|
||
type: Number,
|
||
default: NaN
|
||
},
|
||
color: {
|
||
type: String,
|
||
default: 'primary'
|
||
},
|
||
fontColor: {
|
||
type: String,
|
||
default: 'black'
|
||
},
|
||
round: {
|
||
type: String | Number,
|
||
default: 3
|
||
},
|
||
circular: {
|
||
type: Boolean | String,
|
||
default: false
|
||
},
|
||
shadow: {
|
||
type: String | Number,
|
||
default: 3
|
||
},
|
||
// 跟随主题色的改变而改变。
|
||
fllowTheme: {
|
||
type: Boolean | String,
|
||
default: true
|
||
},
|
||
max: {
|
||
type: Number | String,
|
||
default: 999
|
||
},
|
||
min: {
|
||
type: Number | String,
|
||
default: 0
|
||
},
|
||
height: {
|
||
type: Number | String,
|
||
default: 60
|
||
},
|
||
width: {
|
||
type: Number | String,
|
||
default: 180
|
||
},
|
||
//回调函数。默认返回true即增减,否则不执行增减。
|
||
callback: {
|
||
type: Function | Object | Boolean,
|
||
default: true
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
setVal: '',
|
||
timeid: 598985656
|
||
};
|
||
},
|
||
mounted() {
|
||
this.setVal = this.value;
|
||
},
|
||
watch: {
|
||
value: function(val) {
|
||
this.jianchData(parseFloat(val));
|
||
}
|
||
},
|
||
computed: {
|
||
isJianDisabled() {
|
||
if (isNaN(parseInt(this.setVal))) return false;
|
||
if (parseInt(this.setVal) <= this.min) return true;
|
||
return false;
|
||
},
|
||
isAddDisabled() {
|
||
if (isNaN(parseInt(this.setVal))) return false;
|
||
if (parseInt(this.setVal) >= this.max) return true;
|
||
return false;
|
||
},
|
||
black_tmeme: function() {
|
||
if (this.black !== null) return this.black;
|
||
return this.$tm.vx.state().tmVuetify.black;
|
||
},
|
||
color_tmeme: function() {
|
||
if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
|
||
.fllowTheme) {
|
||
return this.$tm.vx.state().tmVuetify.color;
|
||
}
|
||
return this.color;
|
||
},
|
||
font_color: function() {
|
||
if (this.fontColor) return this.fontColor;
|
||
return this.color;
|
||
},
|
||
shadwo_num: function() {
|
||
if (typeof this.shadow !== 'undefined') return this.shadow;
|
||
return 3;
|
||
}
|
||
},
|
||
destroyed() {
|
||
clearInterval(this.timeid);
|
||
},
|
||
methods: {
|
||
async setStep(ty) {
|
||
if (this.disabled) return;
|
||
|
||
if (typeof this.callback !== 'boolean' && this.callback !== true) {
|
||
uni.showLoading({
|
||
title: '...',
|
||
mask: true
|
||
})
|
||
let p = await this.callasync();
|
||
uni.hideLoading();
|
||
if (p !== true) return;
|
||
}
|
||
this.$nextTick(function() {
|
||
var val = parseFloat(this.value);
|
||
if (!isNaN(this.fixed) && this.fixed > 0) {
|
||
val = val.toFixed(this.fixed)
|
||
if (isNaN(val) || val == 0 || val == '0' || val == '' || !val) {
|
||
val = '0.' + this.strWidth(this.fixed) + this.step
|
||
}
|
||
val = parseFloat(val)
|
||
let setval = '0.' + this.strWidth(this.fixed) + this.step
|
||
setval = parseFloat(setval);
|
||
if (ty == '+') {
|
||
val += setval
|
||
} else {
|
||
val -= setval
|
||
}
|
||
} else if (!isNaN(this.fixed) && this.fixed == 0) {
|
||
val = val.toFixed(this.fixed)
|
||
val = parseInt(val)
|
||
if (ty == '+') {
|
||
val += this.step
|
||
} else {
|
||
val -= this.step
|
||
}
|
||
} else if (isNaN(this.fixed)) {
|
||
if (ty == '+') {
|
||
val += this.step
|
||
} else {
|
||
val -= this.step
|
||
}
|
||
}
|
||
|
||
if (val < 0) {
|
||
if (val <= this.min) {
|
||
val = this.min;
|
||
}
|
||
clearInterval(this.timeid);
|
||
} else if (val >= this.max) {
|
||
val = this.max;
|
||
clearInterval(this.timeid);
|
||
}
|
||
const realVal = val;
|
||
this.setVal = isNaN(realVal) ? '' : String(val);
|
||
this.$emit('input', this.setVal);
|
||
this.$emit('update:value', this.setVal);
|
||
this.$emit('change', this.setVal);
|
||
});
|
||
|
||
},
|
||
inputVal(e) {
|
||
var val = parseFloat(e.detail.value)
|
||
this.jianchData(val);
|
||
},
|
||
strWidth(len) {
|
||
let v = '';
|
||
for (let i = 0; i < len - 1; i++) {
|
||
v += '0';
|
||
}
|
||
return v;
|
||
},
|
||
jianchData(val) {
|
||
|
||
this.$nextTick(function() {
|
||
if (!isNaN(this.fixed) && this.fixed > 0) {
|
||
val = val.toFixed(this.fixed)
|
||
if (isNaN(val) || val == 0 || val == '0' || val == '' || !val) {
|
||
val = '0.' + this.strWidth(this.fixed) + this.step
|
||
}
|
||
} else if (!isNaN(this.fixed) && this.fixed == 0) {
|
||
val = val.toFixed(this.fixed)
|
||
}
|
||
const realval = val;
|
||
if (val < this.min) {
|
||
val = String(this.min);
|
||
}
|
||
if (val > this.max) {
|
||
val = String(this.max);
|
||
}
|
||
this.setVal = isNaN(parseFloat(realval)) ? '' : String(val);
|
||
this.$emit('input', this.setVal);
|
||
this.$emit('update:value', this.setVal);
|
||
this.$emit('change', this.setVal);
|
||
});
|
||
},
|
||
longpressEvent(ty) {
|
||
if (this.disabled) return;
|
||
let t = this;
|
||
clearInterval(this.timeid);
|
||
this.timeid = setInterval(async function() {
|
||
await t.setStep(ty);
|
||
}, 250);
|
||
},
|
||
endlongpressEvent(ty) {
|
||
clearInterval(this.timeid);
|
||
},
|
||
//异步回调
|
||
async callasync() {
|
||
let verify = this.callback;
|
||
verify = await verify()
|
||
if (typeof verify === 'function') {
|
||
verify = await verify()
|
||
}
|
||
if (typeof verify !== 'boolean') verify = true;
|
||
|
||
return verify;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss"></style>
|