410 lines
9.2 KiB
Plaintext
410 lines
9.2 KiB
Plaintext
<script lang="ts">
|
|
import { type PropType } from "vue"
|
|
import { getUid } from "../../core/util/xCoreUtil.uts"
|
|
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
|
|
import { checkIsCssUnit, getUnit } from "../../core/util/xCoreUtil.uts"
|
|
import { xConfig } from "../../config/xConfig.uts"
|
|
|
|
/**
|
|
* @name 步进器 xStepper
|
|
* @description 可整数,小数
|
|
* @page /pages/index/stepper
|
|
* @category 表单组件
|
|
* @constant 平台兼容
|
|
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
|
|
*/
|
|
export default {
|
|
data() {
|
|
return {
|
|
_value: 0,
|
|
_input_value: "",
|
|
addDomDisabeld: false,
|
|
surDomDisabeld: false
|
|
}
|
|
},
|
|
emits: [
|
|
/**
|
|
* 输入值或者点击按钮时触发
|
|
* @param {number} str - 当前的值。
|
|
*/
|
|
'change', 'update:modelValue',
|
|
],
|
|
props: {
|
|
/**
|
|
* 当前值,可v-model
|
|
*/
|
|
modelValue: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
/**
|
|
* 最大值
|
|
*/
|
|
max: {
|
|
type: Number,
|
|
default: 100
|
|
},
|
|
/**
|
|
* 组件宽
|
|
*/
|
|
width: {
|
|
type: String,
|
|
default: "auto"
|
|
},
|
|
/**
|
|
* 最小值
|
|
*/
|
|
min: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
/**
|
|
* 开启后自动隐藏限制的按钮
|
|
* 最小时隐藏减号按钮
|
|
*/
|
|
autoHideBtn:{
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* 是否禁用整个组件
|
|
*/
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* 是否禁用输入框
|
|
*/
|
|
disabledInput: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* 步进值
|
|
*/
|
|
step: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
/**
|
|
* 如果进步值是小数位需要设置此值
|
|
*/
|
|
decimalLen: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
/**
|
|
* 按钮的颜色
|
|
*/
|
|
btnColor: {
|
|
type: String,
|
|
default: "info"
|
|
},
|
|
/**
|
|
* 按钮的暗黑颜色
|
|
* 空值读取全局的Input暗黑背景色
|
|
*/
|
|
darkBtnColor: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
/**
|
|
* 输入框的背景色
|
|
*/
|
|
bgColor: {
|
|
type: String,
|
|
default: "info"
|
|
},
|
|
/**
|
|
* 输入框的自定样式
|
|
* 可以写背景字体等样式
|
|
*/
|
|
inputStyle: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
/**
|
|
* 输入框的暗黑背景色
|
|
* 空值读取全局的Input暗黑背景色
|
|
*/
|
|
darkBgColor: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
/**
|
|
* 按钮的宽
|
|
*/
|
|
btnWidth: {
|
|
type: String,
|
|
default: "36"
|
|
},
|
|
/**
|
|
* 输入框及按钮的高
|
|
*/
|
|
height: {
|
|
type: String,
|
|
default: "36"
|
|
},
|
|
/**
|
|
* 按钮的圆角。
|
|
*/
|
|
round: {
|
|
type: String,
|
|
default: "4"
|
|
},
|
|
|
|
/**
|
|
* 是否按钮与输入框独立开来
|
|
* 不和输入框粘一起。
|
|
*/
|
|
splitBtn: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* 按钮文本颜色,暗黑时取白色
|
|
*/
|
|
btnFontColor: {
|
|
type: String,
|
|
default: "#333333"
|
|
},
|
|
/**
|
|
* 文本颜色,暗黑时取白色
|
|
*/
|
|
fontColor: {
|
|
type: String,
|
|
default: "#333333"
|
|
},
|
|
/**
|
|
* 文本文字大小
|
|
*/
|
|
fontSize: {
|
|
type: String,
|
|
default: "14"
|
|
},
|
|
},
|
|
computed: {
|
|
_round() : string {
|
|
if (this.round == "") {
|
|
return checkIsCssUnit(xConfig.progressRadius, xConfig.unit)
|
|
}
|
|
return checkIsCssUnit(this.round, xConfig.unit)
|
|
},
|
|
_width() : string {
|
|
return checkIsCssUnit(this.width, xConfig.unit)
|
|
},
|
|
_inputStyle() : string {
|
|
return this.inputStyle
|
|
},
|
|
|
|
_fontSize() : string {
|
|
let fontSize = checkIsCssUnit(this.fontSize, xConfig.unit);
|
|
if (xConfig.fontScale == 1) return fontSize;
|
|
let sizeNumber = parseInt(fontSize)
|
|
if (isNaN(sizeNumber)) {
|
|
sizeNumber = 14
|
|
}
|
|
return (sizeNumber * xConfig.fontScale).toString() + getUnit(fontSize)
|
|
},
|
|
_unFontSize() : string {
|
|
return this.fontSize
|
|
},
|
|
_btnFontColor() : string {
|
|
return getDefaultColor(this.btnFontColor)
|
|
},
|
|
_fontColor() : string {
|
|
if (xConfig.dark == 'dark') return '#ffffff'
|
|
return getDefaultColor(this.fontColor)
|
|
},
|
|
_height() : string {
|
|
return checkIsCssUnit(this.height, xConfig.unit)
|
|
},
|
|
_btnWidth() : string {
|
|
return checkIsCssUnit(this.btnWidth, xConfig.unit)
|
|
},
|
|
_splitBtn() : boolean {
|
|
return this.splitBtn
|
|
},
|
|
_disabledInput() : boolean {
|
|
return this.disabledInput
|
|
},
|
|
_btnColor() : string {
|
|
let color = getDefaultColor(this.btnColor)
|
|
if (xConfig.dark == 'dark') {
|
|
if (this.darkBtnColor == "") {
|
|
color = xConfig.inputDarkColor
|
|
} else {
|
|
color = getDefaultColor(this.darkBtnColor)
|
|
}
|
|
}
|
|
return color
|
|
},
|
|
_bgColor() : string {
|
|
|
|
let color = getDefaultColor(this.bgColor)
|
|
if (xConfig.dark == 'dark') {
|
|
if (this.darkBgColor == "") {
|
|
color = xConfig.inputDarkColor
|
|
} else {
|
|
color = getDefaultColor(this.darkBgColor)
|
|
}
|
|
}
|
|
return color
|
|
},
|
|
_max() : number {
|
|
return this.max
|
|
},
|
|
_min() : number {
|
|
return this.min
|
|
},
|
|
_step() : number {
|
|
return this.step
|
|
},
|
|
_disabled() : boolean {
|
|
return this.disabled
|
|
}
|
|
},
|
|
watch: {
|
|
modelValue(newval : number) {
|
|
if (newval == this._value) return;
|
|
this.setValue(newval, false)
|
|
}
|
|
},
|
|
mounted() {
|
|
this.setValue(this.modelValue, false)
|
|
},
|
|
methods: {
|
|
isInRange(value : number) : boolean {
|
|
return value >= this._min && value <= this._max;
|
|
},
|
|
clampValue(value : number) : number {
|
|
return Math.min(Math.max(value, this._min), this._max);
|
|
},
|
|
getDecimalPlaces() : number {
|
|
return this.decimalLen;
|
|
},
|
|
/**
|
|
* 加
|
|
*/
|
|
handleIncrement() {
|
|
|
|
const newValue = Math.min(this._value + this._step, this.max);
|
|
let val = this.clampValue(parseFloat(newValue.toFixed(this.decimalLen)));
|
|
|
|
this.setValue(val, true)
|
|
},
|
|
/**减 */
|
|
handleDecrement() {
|
|
const newValue = Math.max(this._value - this._step, this.min);
|
|
let val = this.clampValue(parseFloat(newValue.toFixed(this.decimalLen)));
|
|
this.setValue(val, true)
|
|
},
|
|
handleInputChange(event : UniInputEvent) {
|
|
this._input_value = event.detail.value
|
|
},
|
|
getDien(str:string):string{
|
|
let v1 = str.split(".")
|
|
let result = v1[0]
|
|
if(v1.length==0){
|
|
result = '0.'
|
|
for(let i =0;i<this.decimalLen;i++){
|
|
result+='0'
|
|
}
|
|
}else if(v1.length==1){
|
|
result = result + "."
|
|
for(let i =0;i<this.decimalLen;i++){
|
|
result+='0'
|
|
}
|
|
}else{
|
|
result = result + "." + v1[1].substring(0,this.decimalLen)
|
|
}
|
|
return result
|
|
},
|
|
inputBlur() {
|
|
const inputValue = parseFloat(this._input_value);
|
|
if (!isNaN(inputValue)) {
|
|
let str = this.getDien(inputValue + '')
|
|
let val = this.clampValue(parseFloat(str));
|
|
this.setValue(val, true)
|
|
} else {
|
|
this.setValue(parseFloat(this._min.toFixed(this.decimalLen)), true)
|
|
}
|
|
},
|
|
setValue(value : number, isEmit : boolean) {
|
|
const clampedValue = this.clampValue(value);
|
|
this._value = clampedValue;
|
|
this._input_value = this._value.toString();
|
|
this.addDomDisabeld = this._value >= this.max
|
|
this.surDomDisabeld = this._value <= this.min
|
|
|
|
if (isEmit) {
|
|
/**
|
|
* 等同v-model
|
|
*/
|
|
this.$emit("update:modelValue", clampedValue)
|
|
/**
|
|
* 输入值或者点击按钮时触发
|
|
* @param {number} 当前的值。
|
|
*/
|
|
this.$emit("change", clampedValue)
|
|
}
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
<template>
|
|
<view class="xStepper" :style="{width:_width,borderRadius:_round}">
|
|
<view v-if="(!surDomDisabeld&&autoHideBtn)||!autoHideBtn" :hover-start-time="20" :hover-stay-time="150" :hover-class="addDomDisabeld?'':'xStepperHoverbtn'"
|
|
@click="handleDecrement" class="xStepperBtn"
|
|
:style="{backgroundColor:_btnColor,height:_height,width:_btnWidth,opacity:surDomDisabeld?0.6:1,borderRadius:_splitBtn?'50px':'0rpx'}">
|
|
<x-icon class="xStepperBtnBtn" :color="_btnFontColor" :font-size="_unFontSize"
|
|
name="subtract-line"></x-icon>
|
|
</view>
|
|
|
|
<input v-if="(!surDomDisabeld&&autoHideBtn)||!autoHideBtn" :always-embed="true" :disabled="_disabledInput||_disabled" @blur="inputBlur" @input="handleInputChange" :value="_input_value" class="xStepperInput"
|
|
:style="[
|
|
{backgroundColor:_splitBtn?'transparent':_btnColor,height:_height,color:_fontColor,fontSize:_fontSize},
|
|
_inputStyle
|
|
]"
|
|
:type="decimalLen>0?'digit':'number'" />
|
|
<view :hover-start-time="20" :hover-stay-time="150" :hover-class="addDomDisabeld?'':'xStepperHoverbtn'"
|
|
@click="handleIncrement" class="xStepperBtn"
|
|
:style="{backgroundColor:_btnColor,height:_height,width:_btnWidth,borderRadius:_splitBtn?'50px':'0rpx'}">
|
|
<x-icon class="xStepperBtnBtn" :style="{opacity:addDomDisabeld?0.6:1}" :color="_btnFontColor"
|
|
:font-size="_unFontSize" name="add-line"></x-icon>
|
|
</view>
|
|
|
|
</view>
|
|
</template>
|
|
<style scoped>
|
|
.xStepperBtnBtn {
|
|
pointer-events: none;
|
|
}
|
|
|
|
.xStepperHoverbtn {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.xStepper {
|
|
display: flex;
|
|
flex-direction: row;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.xStepperInput {
|
|
flex: 1;
|
|
margin: 0 1px;
|
|
padding: 0 5px;
|
|
text-align: center;
|
|
}
|
|
|
|
.xStepperBtn {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
</style> |