163 lines
3.5 KiB
Plaintext
163 lines
3.5 KiB
Plaintext
<script lang="ts">
|
|
export default {
|
|
name: "LayInputNumber",
|
|
};
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import "./index.less";
|
|
import layInput from "../input/index.vue";
|
|
import { LayIcon } from "@layui/icons-vue";
|
|
import layButton from "../button/index.vue";
|
|
import { ref, watch, withDefaults, computed, Ref } from "vue";
|
|
import { InputNumberSize } from "./interface";
|
|
import { add, sub } from "./math";
|
|
|
|
export interface InputNumberProps {
|
|
modelValue?: number;
|
|
name?: string;
|
|
disabled?: boolean;
|
|
disabledInput?: boolean;
|
|
size?: InputNumberSize;
|
|
step?: number;
|
|
position?: "right";
|
|
min?: number;
|
|
max?: number;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<InputNumberProps>(), {
|
|
disabled: false,
|
|
disabledInput: false,
|
|
modelValue: 0,
|
|
step: 1,
|
|
min: -Infinity,
|
|
max: Infinity,
|
|
size: "md",
|
|
});
|
|
|
|
const emit = defineEmits(["update:modelValue", "change"]);
|
|
let num: Ref<number> = ref(props.modelValue);
|
|
|
|
watch(num, (val) => {
|
|
if (props.max !== Infinity && val > props.max) {
|
|
num.value = props.max;
|
|
return;
|
|
}
|
|
if (props.min !== -Infinity && val < props.min) {
|
|
num.value = props.min;
|
|
return;
|
|
}
|
|
if (isNumber(num.value)) {
|
|
tempValue.value = Number(num.value);
|
|
emit("update:modelValue", tempValue.value);
|
|
emit("change", tempValue.value);
|
|
}
|
|
});
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
(val) => {
|
|
if (val !== num.value) {
|
|
num.value = props.modelValue;
|
|
}
|
|
}
|
|
);
|
|
|
|
let timer: any = 0;
|
|
const tempValue: Ref<number> = ref(0);
|
|
|
|
const minControl = computed(() => {
|
|
if (props.disabled) {
|
|
return true;
|
|
}
|
|
if (props.min !== -Infinity) {
|
|
return Number(props.min) >= num.value;
|
|
}
|
|
});
|
|
|
|
const maxControl = computed(() => {
|
|
if (props.disabled) {
|
|
return true;
|
|
}
|
|
if (props.max !== Infinity) {
|
|
return Number(props.max) <= num.value;
|
|
}
|
|
});
|
|
|
|
const addition = function () {
|
|
num.value = add(num.value, props.step);
|
|
};
|
|
|
|
const subtraction = function () {
|
|
num.value = sub(num.value, props.step);
|
|
};
|
|
|
|
const longDown = function (fn: Function) {
|
|
cancelLongDown();
|
|
if (props.disabled) {
|
|
return;
|
|
}
|
|
timer = setInterval(() => fn.call(timer), 150);
|
|
fn.call(timer);
|
|
};
|
|
|
|
const cancelLongDown = function () {
|
|
clearInterval(timer);
|
|
};
|
|
|
|
const inputChange = function () {
|
|
if (isNumber(num.value)) {
|
|
tempValue.value = Number(num.value);
|
|
return;
|
|
}
|
|
num.value = tempValue.value;
|
|
};
|
|
|
|
const isNumber = function (num: any) {
|
|
return !isNaN(num);
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="layui-input-number" :position="position" :size="size">
|
|
<lay-button
|
|
size="lg"
|
|
@mouseup="cancelLongDown"
|
|
@mousedown="longDown(subtraction)"
|
|
@blur="cancelLongDown"
|
|
:disabled="minControl"
|
|
class="layui-control-btn layui-subtraction-btn"
|
|
>
|
|
<lay-icon
|
|
:type="
|
|
position === 'right' ? 'layui-icon-down' : 'layui-icon-subtraction'
|
|
"
|
|
/>
|
|
</lay-button>
|
|
<div class="layui-input-number-input">
|
|
<lay-input
|
|
:max="max"
|
|
:min="min"
|
|
:name="name"
|
|
v-model="num"
|
|
:readonly="disabledInput || disabled"
|
|
:disabled="disabledInput || disabled"
|
|
@input="inputChange"
|
|
type="number"
|
|
/>
|
|
</div>
|
|
<lay-button
|
|
size="lg"
|
|
@mouseup="cancelLongDown"
|
|
@mousedown="longDown(addition)"
|
|
@blur="cancelLongDown"
|
|
:disabled="maxControl"
|
|
class="layui-control-btn layui-addition-btn"
|
|
>
|
|
<lay-icon
|
|
:type="position === 'right' ? 'layui-icon-up' : 'layui-icon-addition'"
|
|
/>
|
|
</lay-button>
|
|
</div>
|
|
</template>
|