You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
9.2 KiB
Vue

1 year ago
<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>