feat: 添加预算管理功能,支持分类预算和重置周期设置,优化用户界面
This commit is contained in:
101
src/components/EchoInput.vue
Normal file
101
src/components/EchoInput.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text',
|
||||
},
|
||||
inputmode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
step: {
|
||||
type: [String, Number],
|
||||
default: undefined,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
error: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'blur', 'focus', 'enter'])
|
||||
|
||||
const hasError = computed(() => !!props.error)
|
||||
|
||||
const handleInput = (event) => {
|
||||
emit('update:modelValue', event.target.value)
|
||||
}
|
||||
|
||||
const handleKeydown = (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
emit('enter', event)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<label v-if="label" class="block">
|
||||
<span class="text-xs font-bold text-stone-400">{{ label }}</span>
|
||||
<div
|
||||
class="mt-2 flex items-center gap-2 rounded-2xl border px-4 py-3 bg-white/80"
|
||||
:class="
|
||||
hasError
|
||||
? 'border-rose-300 shadow-sm shadow-rose-100'
|
||||
: 'border-stone-200 focus-within:border-stone-400'
|
||||
"
|
||||
>
|
||||
<slot name="prefix" />
|
||||
<input
|
||||
:type="type"
|
||||
:inputmode="inputmode || undefined"
|
||||
:step="step"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:value="modelValue"
|
||||
class="flex-1 bg-transparent text-sm text-stone-800 placeholder:text-stone-300 focus:outline-none"
|
||||
:class="inputClass"
|
||||
@input="handleInput"
|
||||
@blur="$emit('blur', $event)"
|
||||
@focus="$emit('focus', $event)"
|
||||
@keydown="handleKeydown"
|
||||
/>
|
||||
<slot name="suffix" />
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<p v-if="hasError" class="mt-1 text-[11px] text-rose-500 font-bold">
|
||||
{{ error }}
|
||||
</p>
|
||||
<p v-else-if="hint" class="mt-1 text-[11px] text-stone-400">
|
||||
{{ hint }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user