77 lines
1.8 KiB
Vue
77 lines
1.8 KiB
Vue
<template>
|
|
<el-input
|
|
v-model="displayText"
|
|
:placeholder="placeholder"
|
|
:disabled="disabled"
|
|
:clearable="clearable"
|
|
style="width: 100%"
|
|
@focus="handleFocus"
|
|
@blur="handleBlur"
|
|
@input="handleInput"
|
|
/>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { formatMoneyDisplay, parseMoneyToNumber, sanitizeMoneyInput } from '@/utils/money-format'
|
|
|
|
defineOptions({ name: 'AmountInput' })
|
|
|
|
interface Props {
|
|
modelValue: number | null
|
|
min?: number
|
|
max?: number
|
|
precision?: number
|
|
placeholder?: string
|
|
disabled?: boolean
|
|
clearable?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
min: undefined,
|
|
max: undefined,
|
|
precision: 2,
|
|
placeholder: '',
|
|
disabled: false,
|
|
clearable: true
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
'update:modelValue': [value: number | null]
|
|
change: [value: number | null]
|
|
}>()
|
|
|
|
const displayText = ref('')
|
|
const isFocused = ref(false)
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
(val) => {
|
|
if (!isFocused.value) {
|
|
displayText.value = formatMoneyDisplay(val, props.precision)
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
function handleFocus() {
|
|
isFocused.value = true
|
|
displayText.value = sanitizeMoneyInput(displayText.value, props.precision)
|
|
}
|
|
|
|
function handleInput(val: string) {
|
|
displayText.value = sanitizeMoneyInput(val, props.precision)
|
|
}
|
|
|
|
function handleBlur() {
|
|
isFocused.value = false
|
|
let num = parseMoneyToNumber(displayText.value, props.precision)
|
|
if (num !== null) {
|
|
if (props.min !== undefined && num < props.min) num = props.min
|
|
if (props.max !== undefined && num > props.max) num = props.max
|
|
}
|
|
emit('update:modelValue', num)
|
|
emit('change', num)
|
|
displayText.value = formatMoneyDisplay(num, props.precision)
|
|
}
|
|
</script>
|