types(DatetimePicker): use tsx (#8181)

This commit is contained in:
neverland 2021-02-19 20:21:42 +08:00 committed by GitHub
parent d092d669f2
commit 7daca89102
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 77 additions and 47 deletions

View File

@ -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)}
/> />
); );
}, },

View File

@ -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` |

View File

@ -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` |

View File

@ -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)}
/> />
); );
}, },

View File

@ -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(),

View File

@ -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);

View File

@ -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())
); );
} }