Skip to content

Commit

Permalink
feat: 日期选择支持多选 (#261)
Browse files Browse the repository at this point in the history
* fix: 日期选择支持多选

* fix: 解决 ts 类型问题

* refactor: 处理ts提示

* refactor: 处理ts提示

* fix: 解决一些 bug

Co-authored-by: wanchun <[email protected]>
  • Loading branch information
winixt and wanchun committed Jan 11, 2023
1 parent 85897fd commit 638b792
Show file tree
Hide file tree
Showing 24 changed files with 187 additions and 77 deletions.
6 changes: 3 additions & 3 deletions components/cascader/cascaderMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import {
import { isFunction, isString } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import LoadingOutlined from '../icon/LoadingOutlined';
import Scrollbar from '../scrollbar';
import getElementFromRef from '../_util/getElementFromRef';
import { COMPONENT_NAME } from './const';
import useCascaderMenu from './useCascaderMenu';
import type { InnerCascaderOption } from './interface';
import CascaderNode from './cascaderNode';
import Scrollbar from '../scrollbar';
import getElementFromRef from '../_util/getElementFromRef';
import { scrollIntoParentView } from './helper';
import type { InnerCascaderOption } from './interface';

const prefixCls = getPrefixCls('cascader-menu');
const scrollbarContainerClass = `${prefixCls}-dropdown`;
Expand Down
4 changes: 2 additions & 2 deletions components/cascader/cascaderNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import RightOutlined from '../icon/RightOutlined';
import CheckOutlined from '../icon/CheckOutlined';
import Checkbox from '../checkbox/checkbox.vue';
import Radio from '../radio/radio.vue';
import { CHECK_STRATEGY, COMPONENT_NAME, EXPAND_TRIGGER } from './const';
import useCascaderNode from './useCascaderNode';
import Ellipsis from '../ellipsis';
import Tooltip from '../tooltip';
import { useLocale } from '../config-provider/useLocale';
import useCascaderNode from './useCascaderNode';
import { CHECK_STRATEGY, COMPONENT_NAME, EXPAND_TRIGGER } from './const';

const prefixCls = getPrefixCls('cascader-node');

Expand Down
4 changes: 2 additions & 2 deletions components/cascader/props.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ExtractPropTypes, PropType, InjectionKey, Ref } from 'vue';
import { CHECK_STRATEGY, EXPAND_TRIGGER } from './const';
import { extractPropsDefaultValue } from '../_util/utils';
import { CHECK_STRATEGY, EXPAND_TRIGGER } from './const';
import type { ExtractPropTypes, PropType, InjectionKey, Ref } from 'vue';

import type {
CascaderOption,
Expand Down
7 changes: 6 additions & 1 deletion components/collapse/collapseExpose.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { isNumber, isString } from 'lodash-es';
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../_util/constants';
<<<<<<< HEAD:components/collapse/collapseExpose.ts
import type { ExtractPropTypes } from 'vue';
import { definePropType } from './common';
import type { CollapseActiveName } from './common';
=======
import { definePropType, CollapseActiveName } from './common';
import type { ExtractPropTypes } from 'vue';
>>>>>>> d9c5759 (refactor: 处理ts提示):components/collapse/collapse.ts

type Arrayable<T> = T | T[];

Expand All @@ -26,7 +31,7 @@ export const collapseProps = {
default: () => mutable([] as const), // 常量
},
};
export type CollapseProps = ExtractPropTypes<typeof collapseProps>;
export type CollapseProps = Partial<ExtractPropTypes<typeof collapseProps>>;

export const collapseEmits = {
[UPDATE_MODEL_EVENT]: emitChangeFn,
Expand Down
6 changes: 4 additions & 2 deletions components/collapse/collapseItemExpose.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { definePropType, generateId } from './common';
import type { ExtractPropTypes } from 'vue';
import type { CollapseActiveName } from './common';
import { definePropType, generateId } from './common';

export const collapseItemProps = {
title: {
Expand All @@ -13,4 +13,6 @@ export const collapseItemProps = {
},
disabled: Boolean,
};
export type CollapseItemProps = ExtractPropTypes<typeof collapseItemProps>;
export type CollapseItemProps = Partial<
ExtractPropTypes<typeof collapseItemProps>
>;
25 changes: 18 additions & 7 deletions components/date-picker/calendars.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,16 @@ import {
} from 'vue';
import { isFunction, isArray, isNumber } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import Calendar from './calendar.vue';
import { useNormalModel } from '../_util/use/useModel';
import FButton from '../button';
import { useLocale } from '../config-provider/useLocale';
import Calendar from './calendar.vue';
import { getTimestampFromFormat } from './helper';
import { RANGE_POSITION, COMMON_PROPS, RANGE_PROPS } from './const';
import { useRange, useSelectStatus } from './useRange';
import { useDisable } from './use';
import { useLocale } from '../config-provider/useLocale';
import { pickerFactory } from './pickerHandler';
import { PickerType, pickerFactory } from './pickerHandler';
const prefixCls = getPrefixCls('calendars');
Expand Down Expand Up @@ -180,18 +180,26 @@ export default defineComponent({
return !tempCurrentValue.value.length;
}
if (pickerRef.value.name === PickerType.datemultiple) {
return false;
}
return !tempCurrentValue.value[0];
});
const visibleFooter = computed(
() =>
props.control ||
pickerRef.value.name === PickerType.datemultiple ||
pickerRef.value.isRange ||
pickerRef.value.hasTime,
);
const change = () => {
if (pickerRef.value.isRange) {
if (
pickerRef.value.isRange ||
pickerRef.value.name === PickerType.datemultiple
) {
emit('change', tempCurrentValue.value);
} else {
emit('change', tempCurrentValue.value[0]);
Expand All @@ -201,7 +209,10 @@ export default defineComponent({
const updateTempCurrentValue = (val: number[]) => {
tempCurrentValue.value = val;
if (pickerRef.value.isRange) {
if (
pickerRef.value.isRange ||
pickerRef.value.name === PickerType.datemultiple
) {
emit('tmpSelectedDateChange', tempCurrentValue.value);
} else {
emit('tmpSelectedDateChange', tempCurrentValue.value[0]);
Expand All @@ -213,8 +224,8 @@ export default defineComponent({
};
const handleTempCurrentValue = () => {
if (pickerRef.value.isRange) {
tempCurrentValue.value = selectedDates.value || [];
if (isArray(selectedDates.value)) {
tempCurrentValue.value = selectedDates.value;
} else {
tempCurrentValue.value = selectedDates.value
? [selectedDates.value]
Expand Down
43 changes: 30 additions & 13 deletions components/date-picker/datePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
:modelValue="dateText"
:placeholder="singlePlaceHolder"
:disabled="disabled"
:canEdit="pickerRef.name !== PickerType.datemultiple"
:clearable="clearable"
:innerIsFocus="inputIsFocus"
:class="attrs.class"
Expand Down Expand Up @@ -98,9 +99,7 @@ import {
provide,
} from 'vue';
import { format, isValid } from 'date-fns';
import { isEqual } from 'lodash-es';
import RangeInput from './rangeInput.vue';
import Calendars from './calendars.vue';
import { isEqual, isNil, isArray } from 'lodash-es';
import InputInner from '../input/inputInner.vue';
import Popper from '../popper';
import useFormAdaptor from '../_util/use/useFormAdaptor';
Expand All @@ -109,16 +108,17 @@ import getPrefixCls from '../_util/getPrefixCls';
import { useTheme } from '../_theme/useTheme';
import { DateOutlined, SwapRightOutlined } from '../icon';
import { isEmptyValue, strictParse } from './helper';
import { COMMON_PROPS, RANGE_PROPS } from './const';
import type { GetContainer } from '../_util/interface';
import { useLocale } from '../config-provider/useLocale';
import { FORM_ITEM_INJECTION_KEY } from '../_util/constants';
import { noop } from '../_util/utils';
import { pickerFactory } from './pickerHandler';
import type { Picker } from './pickerHandler';
import { COMMON_PROPS, RANGE_PROPS } from './const';
import { isEmptyValue, strictParse } from './helper';
import Calendars from './calendars.vue';
import RangeInput from './rangeInput.vue';
import { pickerFactory, PickerType } from './pickerHandler';
import { useDisable } from './use';
import type { GetContainer } from '../_util/interface';
import type { Picker } from './pickerHandler';
const prefixCls = getPrefixCls('date-picker');
Expand Down Expand Up @@ -188,6 +188,16 @@ const useInput = ({
return '';
}
if (!picker.value.isRange) {
if (isArray(visibleValue.value)) {
return visibleValue.value
.map((item) => {
return format(
item,
props.format || picker.value.format,
);
})
.join('; ');
}
return format(
visibleValue.value,
props.format || picker.value.format,
Expand Down Expand Up @@ -316,7 +326,7 @@ export default defineComponent({
const visibleValue = computed(() => {
if (isOpened.value) {
return isEmptyValue(tmpSelectedDates.value)
return isNil(tmpSelectedDates.value)
? currentValue.value
: tmpSelectedDates.value;
}
Expand Down Expand Up @@ -351,8 +361,12 @@ export default defineComponent({
// 事件
const clear = () => {
const initValue: [] | null = pickerRef.value.isRange ? [] : null;
tmpSelectedDateChange(initValue);
const initValue: [] | null =
pickerRef.value.isRange ||
pickerRef.value.name === PickerType.datemultiple
? []
: null;
tmpSelectedDateChange(null);
handleChange(initValue);
emit('clear');
};
Expand Down Expand Up @@ -388,7 +402,9 @@ export default defineComponent({
cacheEvent = e;
// 非弹窗内容点击导致的失焦,进行 blur 的校验
if (!calendarsRef.value.$el.contains(e.relatedTarget)) {
isOpened.value && updatePopperOpen(false);
if (isOpened.value) {
updatePopperOpen(false);
}
checkBlur();
}
};
Expand Down Expand Up @@ -418,6 +434,7 @@ export default defineComponent({
handleDateInputBlur();
handleBlur(event);
},
PickerType,
pickerRef,
changeDateByInput,
Expand Down
14 changes: 14 additions & 0 deletions components/date-picker/pickerHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { DateObj } from './interface';
export const PickerType = {
date: 'date',
datetime: 'datetime',
datemultiple: 'datemultiple',
daterange: 'daterange',
datetimerange: 'datetimerange',
datemonthrange: 'datemonthrange',
Expand Down Expand Up @@ -37,6 +38,17 @@ export class DatePicker implements Picker {
return new Date(val);
}
}
export class DateMultiplePicker implements Picker {
name = PickerType.datemultiple;
confirmLang = '';
placeholderLang = 'datePicker.selectDate';
format = 'yyyy-MM-dd';
isRange = false;
hasTime = false;
getDateFromStr(val: string): Date {
return new Date(val);
}
}

export class DateTimePicker implements Picker {
name = PickerType.datetime;
Expand Down Expand Up @@ -182,6 +194,8 @@ export function pickerFactory(type: string): Picker {
return new DatePicker();
case PickerType.datetime:
return new DateTimePicker();
case PickerType.datemultiple:
return new DateMultiplePicker();
case PickerType.daterange:
return new DateRangePicker();
case PickerType.datetimerange:
Expand Down
28 changes: 24 additions & 4 deletions components/date-picker/useCalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { isNil } from 'lodash-es';
import { endOfMonth } from 'date-fns';
import getPrefixCls from '../_util/getPrefixCls';
import { useNormalModel } from '../_util/use/useModel';
import { useLocale } from '../config-provider/useLocale';
import { PickerType } from './pickerHandler';
import type { Picker } from './pickerHandler';

import { RANGE_POSITION, SELECTED_STATUS, YEAR_COUNT } from './const';
import {
Expand All @@ -15,6 +15,7 @@ import {
transformTimeToDate,
fillDate,
} from './helper';
import type { Picker } from './pickerHandler';

import type { CalendarProps } from './calendar.vue';
import type {
Expand All @@ -23,7 +24,6 @@ import type {
DayItem,
UpdateSelectedDates,
} from './interface';
import { useLocale } from '../config-provider/useLocale';

const prefixCls = getPrefixCls('calendar');
const WEEK_NAMES = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
Expand All @@ -47,7 +47,7 @@ export const useCurrentDate = (props: CalendarProps, emit: CalendarEmits) => {
watch(
() => props.modelValue,
() => {
if (props.modelValue && !props.rangePosition) {
if (props.modelValue?.length === 1 && !props.rangePosition) {
updateCurrentDate(parseDate(props.modelValue[0]));
}
},
Expand Down Expand Up @@ -111,8 +111,20 @@ export const useSelectedDates = (
selectedDates.value = [anotherDate, newDate];
}
emit('selectedDay');
} else if (picker.value.name === PickerType.datemultiple) {
const selectedDateIndex = selectedDates.value.findIndex((item) => {
return (
item.year === newDate.year &&
item.month === newDate.month &&
item.day === newDate.day
);
});
if (selectedDateIndex !== -1) {
selectedDates.value.splice(selectedDateIndex, 1);
} else {
selectedDates.value.push(newDate);
}
} else if (!picker.value.isRange) {
emit('selectedDay');
selectedDates.value = [newDate];
} else {
// 变更日期的时候,继承当前位置的时间
Expand Down Expand Up @@ -146,6 +158,13 @@ export const useSelectedDates = (
transformDateToTimestamp(selectedDates.value[0]),
transformDateToTimestamp(selectedDates.value[1], true),
]);
} else if (picker.value.name === PickerType.datemultiple) {
emit(
'change',
selectedDates.value.map((item) => {
return transformDateToTimestamp(item);
}),
);
} else {
emit('change', [transformDateToTimestamp(selectedDates.value[0])]);
}
Expand Down Expand Up @@ -436,6 +455,7 @@ export function useDay({
PickerType.datetime,
PickerType.daterange,
PickerType.datetimerange,
PickerType.datemultiple,
].some((type) => props.type === type),
);

Expand Down
11 changes: 6 additions & 5 deletions components/ellipsis/ellipsis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
import { isObject } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import Tooltip from '../tooltip';
import type { ToolTipProps } from '../tooltip';
import { useTheme } from '../_theme/useTheme';
import type { ToolTipProps } from '../tooltip';

const prefixCls = getPrefixCls('ellipsis');

Expand All @@ -22,9 +22,10 @@ const ellipsisProps = {
},
tooltip: {
type: [Boolean, Object] as PropType<boolean | ToolTipProps>,
default: {
showAfter: 500,
},
default: () =>
({
showAfter: 500,
} as ToolTipProps),
},
class: [String, Array, Object] as PropType<string | object | []>,
style: {
Expand All @@ -35,7 +36,7 @@ const ellipsisProps = {
},
} as const;

export type EllipsisProps = ExtractPropTypes<typeof ellipsisProps>;
export type EllipsisProps = Partial<ExtractPropTypes<typeof ellipsisProps>>;

export default defineComponent({
name: 'FEllipsis',
Expand Down
Loading

0 comments on commit 638b792

Please sign in to comment.