mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-24 10:20:19 +08:00
types(DatetimePicker): use tsx (#8181)
This commit is contained in:
parent
d092d669f2
commit
7daca89102
@ -1,15 +1,23 @@
|
|||||||
import { ref, watch, computed, nextTick, onMounted } from 'vue';
|
import { ref, watch, computed, nextTick, onMounted, PropType } from 'vue';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { isDate } from '../utils/validate/date';
|
import { isDate } from '../utils/validate/date';
|
||||||
import { pick, padZero, createNamespace } from '../utils';
|
import { pick, range, padZero, createNamespace } from '../utils';
|
||||||
import { times, sharedProps, getTrueValue, getMonthEndDay } from './utils';
|
import {
|
||||||
|
times,
|
||||||
|
ColumnType,
|
||||||
|
pickerKeys,
|
||||||
|
sharedProps,
|
||||||
|
getTrueValue,
|
||||||
|
getMonthEndDay,
|
||||||
|
DatetimePickerType,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Picker, { pickerProps } from '../picker';
|
import Picker from '../picker';
|
||||||
|
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const [createComponent] = createNamespace('date-picker');
|
const [createComponent] = createNamespace('date-picker');
|
||||||
@ -17,17 +25,18 @@ const [createComponent] = createNamespace('date-picker');
|
|||||||
export default createComponent({
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
...sharedProps,
|
...sharedProps,
|
||||||
|
modelValue: Date as PropType<Date>,
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String as PropType<DatetimePickerType>,
|
||||||
default: 'datetime',
|
default: 'datetime',
|
||||||
},
|
},
|
||||||
minDate: {
|
minDate: {
|
||||||
type: Date,
|
type: Date as PropType<Date>,
|
||||||
default: () => new Date(currentYear - 10, 0, 1),
|
default: () => new Date(currentYear - 10, 0, 1),
|
||||||
validator: isDate,
|
validator: isDate,
|
||||||
},
|
},
|
||||||
maxDate: {
|
maxDate: {
|
||||||
type: Date,
|
type: Date as PropType<Date>,
|
||||||
default: () => new Date(currentYear + 10, 11, 31),
|
default: () => new Date(currentYear + 10, 11, 31),
|
||||||
validator: isDate,
|
validator: isDate,
|
||||||
},
|
},
|
||||||
@ -36,22 +45,23 @@ export default createComponent({
|
|||||||
emits: ['confirm', 'cancel', 'change', 'update:modelValue'],
|
emits: ['confirm', 'cancel', 'change', 'update:modelValue'],
|
||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const formatValue = (value) => {
|
const formatValue = (value?: Date) => {
|
||||||
if (!isDate(value)) {
|
if (isDate(value)) {
|
||||||
value = props.minDate;
|
const timestamp = range(
|
||||||
|
value.getTime(),
|
||||||
|
props.minDate.getTime(),
|
||||||
|
props.maxDate.getTime()
|
||||||
|
);
|
||||||
|
return new Date(timestamp);
|
||||||
}
|
}
|
||||||
|
return props.minDate;
|
||||||
value = Math.max(value, props.minDate.getTime());
|
|
||||||
value = Math.min(value, props.maxDate.getTime());
|
|
||||||
|
|
||||||
return new Date(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const picker = ref();
|
const picker = ref();
|
||||||
const currentDate = ref(formatValue(props.modelValue));
|
const currentDate = ref(formatValue(props.modelValue));
|
||||||
|
|
||||||
const getBoundary = (type, value) => {
|
const getBoundary = (type: 'max' | 'min', value: Date) => {
|
||||||
const boundary = props[`${type}Date`];
|
const boundary = props[`${type}Date` as const];
|
||||||
const year = boundary.getFullYear();
|
const year = boundary.getFullYear();
|
||||||
let month = 1;
|
let month = 1;
|
||||||
let date = 1;
|
let date = 1;
|
||||||
@ -98,7 +108,7 @@ export default createComponent({
|
|||||||
currentDate.value
|
currentDate.value
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = [
|
let result: Array<{ type: ColumnType; range: number[] }> = [
|
||||||
{
|
{
|
||||||
type: 'year',
|
type: 'year',
|
||||||
range: [minYear, maxYear],
|
range: [minYear, maxYear],
|
||||||
@ -205,7 +215,7 @@ export default createComponent({
|
|||||||
const { type } = props;
|
const { type } = props;
|
||||||
const indexes = picker.value.getIndexes();
|
const indexes = picker.value.getIndexes();
|
||||||
|
|
||||||
const getValue = (type) => {
|
const getValue = (type: ColumnType) => {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
originColumns.value.forEach((column, columnIndex) => {
|
originColumns.value.forEach((column, columnIndex) => {
|
||||||
if (type === column.type) {
|
if (type === column.type) {
|
||||||
@ -301,11 +311,10 @@ export default createComponent({
|
|||||||
v-slots={slots}
|
v-slots={slots}
|
||||||
ref={picker}
|
ref={picker}
|
||||||
columns={columns.value}
|
columns={columns.value}
|
||||||
readonly={props.readonly}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
{...pick(props, Object.keys(pickerProps))}
|
{...pick(props, pickerKeys)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
@ -284,8 +284,8 @@ export default {
|
|||||||
| show-toolbar | Whether to show toolbar | _boolean_ | `true` |
|
| show-toolbar | Whether to show toolbar | _boolean_ | `true` |
|
||||||
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
||||||
| readonly | Whether to be readonly | _boolean_ | `false` |
|
| readonly | Whether to be readonly | _boolean_ | `false` |
|
||||||
| filter | Option filter | _(type, vals) => vals_ | - |
|
| filter | Option filter | _(type: string, values: string[]) => string[]_ | - |
|
||||||
| formatter | Option text formatter | _(type, val) => val_ | - |
|
| formatter | Option text formatter | _(type: string, value: string) => string_ | - |
|
||||||
| columns-order | Array for ordering columns, where item can be set to<br> `year`, `month`, `day`, `hour` and `minute` | _string[]_ | - |
|
| columns-order | Array for ordering columns, where item can be set to<br> `year`, `month`, `day`, `hour` and `minute` | _string[]_ | - |
|
||||||
| item-height | Option height, supports `px` `vw` `vh` `rem` unit, default `px` | _number \| string_ | `44` |
|
| item-height | Option height, supports `px` `vw` `vh` `rem` unit, default `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | Count of visible columns | _number \| string_ | `6` |
|
| visible-item-count | Count of visible columns | _number \| string_ | `6` |
|
||||||
|
@ -293,8 +293,8 @@ export default {
|
|||||||
| show-toolbar | 是否显示顶部栏 | _boolean_ | `true` |
|
| show-toolbar | 是否显示顶部栏 | _boolean_ | `true` |
|
||||||
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
||||||
| readonly | 是否为只读状态,只读状态下无法切换选项 | _boolean_ | `false` |
|
| readonly | 是否为只读状态,只读状态下无法切换选项 | _boolean_ | `false` |
|
||||||
| filter | 选项过滤函数 | _(type, vals) => vals_ | - |
|
| filter | 选项过滤函数 | _(type: string, values: string[]) => string[]_ | - |
|
||||||
| formatter | 选项格式化函数 | _(type, val) => val_ | - |
|
| formatter | 选项格式化函数 | _(type: string, value: string) => string_ | - |
|
||||||
| columns-order | 自定义列排序数组, 子项可选值为<br> `year`、`month`、`day`、`hour`、`minute` | _string[]_ | - |
|
| columns-order | 自定义列排序数组, 子项可选值为<br> `year`、`month`、`day`、`hour`、`minute` | _string[]_ | - |
|
||||||
| item-height | 选项高度,支持 `px` `vw` `vh` `rem` 单位,默认 `px` | _number \| string_ | `44` |
|
| item-height | 选项高度,支持 `px` `vw` `vh` `rem` 单位,默认 `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `6` |
|
| visible-item-count | 可见的选项个数 | _number \| string_ | `6` |
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
import { ref, watch, computed, nextTick, onMounted } from 'vue';
|
import { ref, watch, computed, nextTick, onMounted } from 'vue';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { pick, range, padZero, createNamespace } from '../utils';
|
import {
|
||||||
import { times, sharedProps } from './utils';
|
pick,
|
||||||
|
range,
|
||||||
|
padZero,
|
||||||
|
createNamespace,
|
||||||
|
ComponentInstance,
|
||||||
|
} from '../utils';
|
||||||
|
import { times, sharedProps, pickerKeys } from './utils';
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Picker, { pickerProps } from '../picker';
|
import Picker from '../picker';
|
||||||
|
|
||||||
const [createComponent] = createNamespace('time-picker');
|
const [createComponent] = createNamespace('time-picker');
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
...sharedProps,
|
...sharedProps,
|
||||||
|
modelValue: String,
|
||||||
minHour: {
|
minHour: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 0,
|
default: 0,
|
||||||
@ -36,7 +43,7 @@ export default createComponent({
|
|||||||
emits: ['confirm', 'cancel', 'change', 'update:modelValue'],
|
emits: ['confirm', 'cancel', 'change', 'update:modelValue'],
|
||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const formatValue = (value) => {
|
const formatValue = (value?: string) => {
|
||||||
const { minHour, maxHour, maxMinute, minMinute } = props;
|
const { minHour, maxHour, maxMinute, minMinute } = props;
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@ -44,13 +51,13 @@ export default createComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let [hour, minute] = value.split(':');
|
let [hour, minute] = value.split(':');
|
||||||
hour = padZero(range(hour, minHour, maxHour));
|
hour = padZero(range(+hour, +minHour, +maxHour));
|
||||||
minute = padZero(range(minute, minMinute, maxMinute));
|
minute = padZero(range(+minute, +minMinute, +maxMinute));
|
||||||
|
|
||||||
return `${hour}:${minute}`;
|
return `${hour}:${minute}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const picker = ref();
|
const picker = ref<ComponentInstance>();
|
||||||
const currentDate = ref(formatValue(props.modelValue));
|
const currentDate = ref(formatValue(props.modelValue));
|
||||||
|
|
||||||
const ranges = computed(() => [
|
const ranges = computed(() => [
|
||||||
@ -97,12 +104,12 @@ export default createComponent({
|
|||||||
];
|
];
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
picker.value.setValues(values);
|
picker.value!.setValues(values);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateInnerValue = () => {
|
const updateInnerValue = () => {
|
||||||
const [hourIndex, minuteIndex] = picker.value.getIndexes();
|
const [hourIndex, minuteIndex] = picker.value!.getIndexes();
|
||||||
const [hourColumn, minuteColumn] = originColumns.value;
|
const [hourColumn, minuteColumn] = originColumns.value;
|
||||||
|
|
||||||
const hour = hourColumn.values[hourIndex] || hourColumn.values[0];
|
const hour = hourColumn.values[hourIndex] || hourColumn.values[0];
|
||||||
@ -173,11 +180,10 @@ export default createComponent({
|
|||||||
v-slots={slots}
|
v-slots={slots}
|
||||||
ref={picker}
|
ref={picker}
|
||||||
columns={columns.value}
|
columns={columns.value}
|
||||||
readonly={props.readonly}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onConfirm={onConfirm}
|
onConfirm={onConfirm}
|
||||||
{...pick(props, Object.keys(pickerProps))}
|
{...pick(props, pickerKeys)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
@ -1,5 +1,5 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { pick, createNamespace } from '../utils';
|
import { pick, createNamespace, ComponentInstance } from '../utils';
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
import TimePicker from './TimePicker';
|
import TimePicker from './TimePicker';
|
||||||
import DatePicker from './DatePicker';
|
import DatePicker from './DatePicker';
|
||||||
@ -13,10 +13,11 @@ export default createComponent({
|
|||||||
props: {
|
props: {
|
||||||
...TimePicker.props,
|
...TimePicker.props,
|
||||||
...DatePicker.props,
|
...DatePicker.props,
|
||||||
|
modelValue: [String, Date],
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { attrs, slots }) {
|
setup(props, { attrs, slots }) {
|
||||||
const root = ref();
|
const root = ref<ComponentInstance>();
|
||||||
|
|
||||||
useExpose({
|
useExpose({
|
||||||
getPicker: () => root.value?.getPicker(),
|
getPicker: () => root.value?.getPicker(),
|
@ -1,20 +1,34 @@
|
|||||||
|
import { PropType } from 'vue';
|
||||||
import { isNaN } from '../utils/validate/number';
|
import { isNaN } from '../utils/validate/number';
|
||||||
import { pickerProps } from '../picker';
|
import { pickerProps } from '../picker';
|
||||||
|
|
||||||
|
export type ColumnType = 'year' | 'month' | 'day' | 'hour' | 'minute';
|
||||||
|
|
||||||
|
export type DatetimePickerType =
|
||||||
|
| 'date'
|
||||||
|
| 'time'
|
||||||
|
| 'datetime'
|
||||||
|
| 'datehour'
|
||||||
|
| 'month-day'
|
||||||
|
| 'year-month';
|
||||||
|
|
||||||
export const sharedProps = {
|
export const sharedProps = {
|
||||||
...pickerProps,
|
...pickerProps,
|
||||||
filter: Function,
|
filter: Function as PropType<(type: string, values: string[]) => string[]>,
|
||||||
modelValue: null,
|
columnsOrder: Array as PropType<ColumnType[]>,
|
||||||
columnsOrder: Array,
|
|
||||||
formatter: {
|
formatter: {
|
||||||
type: Function,
|
type: Function as PropType<(type: string, value: string) => string>,
|
||||||
default: (type: string, value: unknown) => value,
|
default: (type: string, value: string) => value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function times(n: number, iteratee: (index: number) => any[]) {
|
export const pickerKeys = Object.keys(pickerProps) as Array<
|
||||||
|
keyof typeof pickerProps
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function times<T>(n: number, iteratee: (index: number) => T) {
|
||||||
let index = -1;
|
let index = -1;
|
||||||
const result = Array(n);
|
const result: T[] = Array(n);
|
||||||
|
|
||||||
while (++index < n) {
|
while (++index < n) {
|
||||||
result[index] = iteratee(index);
|
result[index] = iteratee(index);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { isNaN } from './number';
|
import { isNaN } from './number';
|
||||||
|
|
||||||
export function isDate(val: Date): val is Date {
|
export function isDate(val: unknown): val is Date {
|
||||||
return (
|
return (
|
||||||
Object.prototype.toString.call(val) === '[object Date]' &&
|
Object.prototype.toString.call(val) === '[object Date]' &&
|
||||||
!isNaN(val.getTime())
|
!isNaN((val as Date).getTime())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user