<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>