gaoluyang
2026-06-24 712aa51536236d43e87273e4ce45ac5691dffad8
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<script setup>
import { ref, watch } from 'vue';
 
import { Button, Input } from 'ant-design-vue';
 
const props = defineProps({
  value: {
    type: String,
    default: '',
  },
});
const emit = defineEmits(['change']);
 
const units = [
  { key: 'Y', label: '年', presets: [1, 2, 3, 4] },
  { key: 'M', label: '月', presets: [1, 2, 3, 4] },
  { key: 'D', label: '天', presets: [1, 2, 3, 4] },
  { key: 'H', label: '时', presets: [4, 8, 12, 24] },
  { key: 'm', label: '分', presets: [5, 10, 30, 50] },
  { key: 'S', label: '秒', presets: [5, 10, 30, 50] },
];
const custom = ref({ Y: '', M: '', D: '', H: '', m: '', S: '' });
const isoString = ref('');
 
function setUnit(key, val) {
  if (!val || Number.isNaN(val)) {
    custom.value[key] = '';
    return;
  }
  custom.value[key] = val;
  updateIsoString();
}
 
function updateIsoString() {
  let str = 'P';
  if (custom.value.Y) str += `${custom.value.Y}Y`;
  if (custom.value.M) str += `${custom.value.M}M`;
  if (custom.value.D) str += `${custom.value.D}D`;
  if (custom.value.H || custom.value.m || custom.value.S) str += 'T';
  if (custom.value.H) str += `${custom.value.H}H`;
  if (custom.value.m) str += `${custom.value.m}M`;
  if (custom.value.S) str += `${custom.value.S}S`;
  isoString.value = str === 'P' ? '' : str;
  emit('change', isoString.value);
}
 
watch(
  () => props.value,
  (val) => {
    if (!val) return;
    // 解析ISO 8601字符串到custom
    const match = val.match(
      /^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/,
    );
    if (match) {
      custom.value.Y = match[1] || '';
      custom.value.M = match[2] || '';
      custom.value.D = match[3] || '';
      custom.value.H = match[4] || '';
      custom.value.m = match[5] || '';
      custom.value.S = match[6] || '';
      updateIsoString();
    }
  },
  { immediate: true },
);
</script>
 
<template>
  <div>
    <div class="mb-2.5">
      当前选择:<Input v-model:value="isoString" readonly class="w-[300px]" />
    </div>
    <div v-for="unit in units" :key="unit.key" class="mb-2">
      <span>{{ unit.label }}:</span>
      <Button.Group>
        <Button
          v-for="val in unit.presets"
          :key="val"
          size="small"
          @click="setUnit(unit.key, val)"
        >
          {{ val }}
        </Button>
        <Input
          v-model:value="custom[unit.key]"
          size="small"
          class="ml-2 w-[60px]"
          placeholder="自定义"
          @change="setUnit(unit.key, custom[unit.key])"
        />
      </Button.Group>
    </div>
  </div>
</template>