DatePicker.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <Picker
  3. v-bind="props"
  4. :value="value"
  5. :columns="columns"
  6. @selectTextChange="() => {}"
  7. @update:value="updateValue"
  8. />
  9. </template>
  10. <script setup lang="ts">
  11. import { computed, onMounted } from 'vue';
  12. import type { PickerProps } from './Picker.vue';
  13. import Picker from './Picker.vue';
  14. import { DateUtils } from '@imengyu/imengyu-utils';
  15. import type { PickerItem } from './Picker';
  16. // 更新 DatePickerProps 接口
  17. export interface DatePickerProps extends Omit<PickerProps, 'columns'|'value'> {
  18. modelValue?: Date,
  19. showYears?: boolean,
  20. showMonths?: boolean,
  21. showDays?: boolean,
  22. startYear?: number,
  23. endYear?: number,
  24. startMonth?: number,
  25. endMonth?: number,
  26. startDay?: number,
  27. endDay?: number,
  28. yearText?: string,
  29. monthText?: string,
  30. dayText?: string,
  31. }
  32. const emit = defineEmits([ 'update:modelValue', 'selectTextChange' ]);
  33. const props = withDefaults(defineProps<DatePickerProps>(), {
  34. pickerHeight: 300,
  35. pickerWidth: 750,
  36. showYears: true,
  37. showMonths: true,
  38. showDays: true,
  39. startYear: () => new Date().getFullYear() - 10,
  40. endYear: () => new Date().getFullYear() + 10,
  41. startMonth: 1,
  42. endMonth: 12,
  43. startDay: 1,
  44. // 暂时设为 31,后续根据年月动态调整
  45. endDay: 31,
  46. yearText: '年',
  47. monthText: '月',
  48. dayText: '日',
  49. });
  50. let forceUpdate = true;
  51. // 计算当前选中的值
  52. const value = computed(() => {
  53. const value : number[] = [];
  54. let date = props.modelValue;
  55. if (!date)
  56. date = new Date();
  57. if (props.showYears)
  58. value.push(date.getFullYear());
  59. if (props.showMonths)
  60. value.push(date.getMonth() + 1);
  61. if (props.showDays)
  62. value.push(date.getDate());
  63. return value;
  64. });
  65. // 计算选择器的列数据
  66. const columns = computed(() => {
  67. const cols = [] as PickerItem[][];
  68. const currentDate = props.modelValue ?? new Date();
  69. if (props.showYears) {
  70. const years = [] as PickerItem[];
  71. for (let i = props.startYear!; i <= props.endYear!; i++) {
  72. years.push({
  73. text: i.toString() + props.yearText,
  74. value: i,
  75. });
  76. }
  77. cols.push(years);
  78. }
  79. if (props.showMonths) {
  80. const months = [] as PickerItem[];
  81. for (let i = props.startMonth!; i <= props.endMonth!; i++) {
  82. months.push({
  83. text: i.toString() + props.monthText,
  84. value: i,
  85. });
  86. }
  87. cols.push(months);
  88. }
  89. if (props.showDays) {
  90. const selectedYear = props.showYears ? value.value[0] : currentDate.getFullYear();
  91. const selectedMonth = props.showMonths ? value.value[1] : currentDate.getMonth() + 1;
  92. const daysInMonth = DateUtils.getMonthDays(selectedYear, selectedMonth - 1) ?? 0;
  93. const days = [] as PickerItem[];
  94. for (let i = props.startDay!; i <= daysInMonth; i++) {
  95. days.push({
  96. text: i.toString() + props.dayText,
  97. value: i,
  98. });
  99. }
  100. cols.push(days);
  101. }
  102. return cols;
  103. });
  104. // 更新选中的值
  105. function updateValue(v: number[]) {
  106. if (props.modelValue || v.length > 0) {
  107. const date = new Date(props.modelValue ?? new Date());
  108. let index = 0;
  109. if (v.length > 0) {
  110. if (props.showYears) {
  111. date.setFullYear(v[index]);
  112. index++;
  113. }
  114. if (props.showMonths) {
  115. // 月份从 0 开始,所以减 1
  116. date.setMonth(v[index] - 1);
  117. index++;
  118. }
  119. if (props.showDays) {
  120. date.setDate(v[index]);
  121. }
  122. emit('update:modelValue', date);
  123. }
  124. emit('selectTextChange', DateUtils.formatDate(date, 'yyyy-MM-dd'), forceUpdate);
  125. } else {
  126. emit('selectTextChange', '', forceUpdate);
  127. }
  128. forceUpdate = false;
  129. }
  130. onMounted(() => updateValue([]));
  131. defineOptions({
  132. options: {
  133. styleIsolation: "shared",
  134. virtualHost: true,
  135. }
  136. })
  137. </script>