测试环境链接替换,部分问题修复,增加批量退菜功能
This commit is contained in:
201
pageCreditBuyer/components/number-box.vue
Normal file
201
pageCreditBuyer/components/number-box.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="custom-number-box">
|
||||
<div
|
||||
class="number-btn number-btn-minus"
|
||||
:class="{ disabled: isMinDisabled || isDisabled }"
|
||||
@click="handleMinus"
|
||||
>
|
||||
<span>-</span>
|
||||
</div>
|
||||
|
||||
<input
|
||||
v-model="inputValue"
|
||||
class="number-input"
|
||||
type="text"
|
||||
:disabled="isDisabled"
|
||||
@input="handleInput"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="number-btn number-btn-plus"
|
||||
:class="{ disabled: isMaxDisabled || isDisabled }"
|
||||
@click="handlePlus"
|
||||
>
|
||||
<span>+</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 28
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// ✅ 新增:是否整数(默认 true)
|
||||
integer: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const inputValue = ref('')
|
||||
const isDisabled = computed(() => props.disabled)
|
||||
|
||||
// 监听外部值
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
inputValue.value = ''
|
||||
return
|
||||
}
|
||||
const num = Number(val)
|
||||
inputValue.value = isNaN(num) ? '' : String(num)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 减号禁用
|
||||
const isMinDisabled = computed(() => {
|
||||
if (inputValue.value === '') return true
|
||||
const val = Number(inputValue.value)
|
||||
return val <= props.min
|
||||
})
|
||||
|
||||
// 加号禁用
|
||||
const isMaxDisabled = computed(() => {
|
||||
if (inputValue.value === '') return false
|
||||
const val = Number(inputValue.value)
|
||||
return val >= props.max
|
||||
})
|
||||
|
||||
// 减
|
||||
function handleMinus() {
|
||||
if (inputValue.value === '') return
|
||||
let val = Number(inputValue.value) - props.step
|
||||
val = Math.max(val, props.min)
|
||||
if (props.integer) val = Math.round(val)
|
||||
inputValue.value = String(val)
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
|
||||
// 加
|
||||
function handlePlus() {
|
||||
let val
|
||||
if (inputValue.value === '') {
|
||||
val = props.min
|
||||
} else {
|
||||
val = Number(inputValue.value) + props.step
|
||||
}
|
||||
val = Math.min(val, props.max)
|
||||
if (props.integer) val = Math.round(val)
|
||||
inputValue.value = String(val)
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
|
||||
// 输入时处理
|
||||
function handleInput() {
|
||||
let val = inputValue.value.trim()
|
||||
if (val === '') {
|
||||
emit('update:modelValue', '')
|
||||
return
|
||||
}
|
||||
|
||||
// 如果是整数,禁止输入小数点
|
||||
if (props.integer) val = val.replace(/\./g, '')
|
||||
|
||||
const num = Number(val)
|
||||
if (isNaN(num)) {
|
||||
inputValue.value = ''
|
||||
emit('update:modelValue', '')
|
||||
return
|
||||
}
|
||||
|
||||
inputValue.value = val
|
||||
emit('update:modelValue', num)
|
||||
}
|
||||
|
||||
// 失焦校验
|
||||
function handleBlur() {
|
||||
const val = inputValue.value.trim()
|
||||
if (val === '') {
|
||||
emit('update:modelValue', '')
|
||||
return
|
||||
}
|
||||
|
||||
let num = Number(val)
|
||||
if (isNaN(num)) {
|
||||
inputValue.value = ''
|
||||
emit('update:modelValue', '')
|
||||
return
|
||||
}
|
||||
|
||||
// 限制范围
|
||||
num = Math.max(props.min, Math.min(props.max, num))
|
||||
|
||||
// ✅ 整数控制
|
||||
if (props.integer) num = Math.round(num)
|
||||
|
||||
inputValue.value = String(num)
|
||||
emit('update:modelValue', num)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.custom-number-box {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.number-btn {
|
||||
width: 36px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f7fa;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.number-btn.disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.number-input {
|
||||
width: 50px;
|
||||
height: 32px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user