gaoluyang
2026-06-24 c0cb161bb52ce0fbdce5c66ec391d107c75e2452
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<script lang="ts" setup>
import { InputNumber } from 'ant-design-vue';
 
type NumberRangeValue = [number | undefined, number | undefined];
 
const props = withDefaults(
  defineProps<{
    maxPlaceholder?: string;
    min?: number;
    minPlaceholder?: string;
    precision?: number;
    value?: NumberRangeValue;
  }>(),
  {
    maxPlaceholder: '最大值',
    min: undefined,
    minPlaceholder: '最小值',
    precision: 2,
    value: undefined,
  },
);
 
const emit = defineEmits<{
  'update:value': [value: NumberRangeValue | undefined];
}>();
 
function normalizeValue(value: unknown) {
  if (typeof value === 'number') {
    return Number.isFinite(value) ? value : undefined;
  }
  if (typeof value === 'string' && value.trim() !== '') {
    const numberValue = Number(value);
    return Number.isFinite(numberValue) ? numberValue : undefined;
  }
  return undefined;
}
 
function updateValue(index: 0 | 1, value: unknown) {
  const next: NumberRangeValue = [
    props.value?.[0] ?? undefined,
    props.value?.[1] ?? undefined,
  ];
  next[index] = normalizeValue(value);
  emit(
    'update:value',
    next[0] === undefined && next[1] === undefined ? undefined : next,
  );
}
</script>
 
<template>
  <div class="flex w-full items-center gap-2">
    <InputNumber
      :controls="false"
      :min="min"
      :placeholder="minPlaceholder"
      :precision="precision"
      :value="value?.[0]"
      class="min-w-0 flex-1"
      @update:value="updateValue(0, $event)"
    />
    <span class="shrink-0 text-muted-foreground">至</span>
    <InputNumber
      :controls="false"
      :min="min"
      :placeholder="maxPlaceholder"
      :precision="precision"
      :value="value?.[1]"
      class="min-w-0 flex-1"
      @update:value="updateValue(1, $event)"
    />
  </div>
</template>