|
|
@@ -0,0 +1,121 @@
|
|
|
+<template>
|
|
|
+ <view class="fs-number-box" :class="{'fs-number-box-round': round}">
|
|
|
+ <view
|
|
|
+ class="fs-number-box-item fs-number-box-left"
|
|
|
+ @click="minus">
|
|
|
+ <fs-icon type="icon-minus" size="32rpx" :color="minusDisabled ? '#c8c9cc' : ''"></fs-icon>
|
|
|
+ </view>
|
|
|
+ <input
|
|
|
+ class="fs-number-box-item fs-number-box-middle"
|
|
|
+ type="number"
|
|
|
+ :value="modelValue"
|
|
|
+ @blur="handleChange"
|
|
|
+ :disabled="disableInput"
|
|
|
+ />
|
|
|
+ <view
|
|
|
+ class="fs-number-box-item fs-number-box-right"
|
|
|
+ @click="add">
|
|
|
+ <fs-icon type="icon-plus" size="32rpx" :color="addDisabled ? '#c8c9cc' : ''"></fs-icon>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ name: 'fs-number-box',
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, watch, computed } from 'vue'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ },
|
|
|
+ min: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ },
|
|
|
+ max: {
|
|
|
+ type: Number,
|
|
|
+ default: Number.MAX_SAFE_INTEGER
|
|
|
+ },
|
|
|
+ step: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ },
|
|
|
+ round: Boolean,
|
|
|
+ disableInput: Boolean,
|
|
|
+})
|
|
|
+
|
|
|
+const emits = defineEmits(['update:modelValue','change'])
|
|
|
+
|
|
|
+let initValue = ref(props.modelValue)
|
|
|
+watch(() => props.modelValue, val => {
|
|
|
+ initValue.value = val
|
|
|
+})
|
|
|
+watch(initValue, val => {
|
|
|
+ emits('update:modelValue', val)
|
|
|
+ emits('change', val)
|
|
|
+})
|
|
|
+const add = () => {
|
|
|
+ initValue.value += Number(props.step)
|
|
|
+ if (initValue.value > props.max) {
|
|
|
+ initValue.value = props.max
|
|
|
+ }
|
|
|
+}
|
|
|
+const minus = () => {
|
|
|
+ initValue.value -= Number(props.step)
|
|
|
+ if (initValue.value < props.min) {
|
|
|
+ initValue.value = props.min
|
|
|
+ }
|
|
|
+}
|
|
|
+const handleChange = e => {
|
|
|
+ initValue.value = Number(e.detail.value) || props.min
|
|
|
+
|
|
|
+ if (initValue.value < props.min) {
|
|
|
+ initValue.value = props.min
|
|
|
+ } else if (initValue.value > props.max) {
|
|
|
+ initValue.value = props.max
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const minusDisabled = computed(() => initValue.value === props.min)
|
|
|
+const addDisabled = computed(() => initValue.value === props.max)
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.fs-number-box{
|
|
|
+ display: inline-flex;
|
|
|
+ border: 2rpx solid var(--border-color);
|
|
|
+ height: 60rpx;
|
|
|
+ background-color: #fff;
|
|
|
+
|
|
|
+ &-round{
|
|
|
+ border-radius: 30rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-item{
|
|
|
+ display: flex;
|
|
|
+ height: 100%;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-left,
|
|
|
+ &-right{
|
|
|
+ width: 60rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-middle{
|
|
|
+ box-sizing: border-box;
|
|
|
+ width: 80rpx;
|
|
|
+ border-left: 2rpx solid var(--border-color);
|
|
|
+ border-right: 2rpx solid var(--border-color);
|
|
|
+ padding: 10rpx;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|