Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(DatePicker): 支持季度选择器 #1178

Merged
merged 2 commits into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/_common
Submodule _common updated 58 files
+6 −0 docs/web/api/date-picker.md
+35 −2 js/date-picker/utils.ts
+2 −1 style/web/_global.less
+2 −1 style/web/_variables.less
+1 −1 style/web/components/alert/_index.less
+1 −1 style/web/components/anchor/_index.less
+2 −2 style/web/components/avatar/_var.less
+3 −3 style/web/components/badge/_index.less
+1 −0 style/web/components/badge/_var.less
+1 −1 style/web/components/button/_index.less
+2 −2 style/web/components/calendar/_index.less
+2 −2 style/web/components/calendar/_var.less
+1 −1 style/web/components/card/_var.less
+2 −0 style/web/components/cascader/_index.less
+8 −7 style/web/components/color-picker/_index.less
+2 −1 style/web/components/comment/_index.less
+3 −1 style/web/components/date-picker/_index.less
+3 −12 style/web/components/dialog/_index.less
+2 −2 style/web/components/dialog/_var.less
+1 −0 style/web/components/drawer/_index.less
+1 −1 style/web/components/drawer/_var.less
+0 −1 style/web/components/dropdown/_index.less
+1 −1 style/web/components/loading/_index.less
+1 −1 style/web/components/menu/_docs.less
+1 −1 style/web/components/menu/_index-v2.less
+1 −1 style/web/components/menu/_index.less
+2 −1 style/web/components/message/_index.less
+1 −1 style/web/components/message/_mixin.less
+1 −1 style/web/components/message/_var.less
+1 −1 style/web/components/notification/_index.less
+1 −1 style/web/components/notification/_mixin.less
+2 −2 style/web/components/notification/_var.less
+1 −1 style/web/components/popconfirm/_var.less
+1 −1 style/web/components/popup/_index.less
+2 −2 style/web/components/progress/_index.less
+4 −4 style/web/components/radio/_index.less
+1 −1 style/web/components/radio/_var.less
+1 −0 style/web/components/range-input/_index.less
+1 −1 style/web/components/range-input/_mixin.less
+1 −1 style/web/components/range-input/_var.less
+0 −1 style/web/components/select/_index.less
+7 −7 style/web/components/skeleton/_index.less
+5 −5 style/web/components/skeleton/_var.less
+1 −1 style/web/components/slider/_index.less
+1 −1 style/web/components/slider/_var.less
+2 −2 style/web/components/steps/_mixin.less
+2 −2 style/web/components/switch/_index.less
+2 −2 style/web/components/table/_docs.less
+1 −1 style/web/components/table/_index.less
+1 −1 style/web/components/tag/_var.less
+1 −1 style/web/components/tooltip/_index.less
+1 −1 style/web/components/transfer/_index.less
+1 −1 style/web/components/transfer/_var.less
+2 −2 style/web/components/tree/_docs.less
+10 −0 style/web/components/tree/_index.less
+1 −1 style/web/components/upload/_docs.less
+1 −1 style/web/components/upload/_var.less
+2 −1 style/web/theme/_radius.less
2 changes: 1 addition & 1 deletion src/date-picker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, ref) => {

// 头部快速切换
function onJumperClick({ trigger }) {
const monthCountMap = { date: 1, week: 1, month: 12, year: 120 };
const monthCountMap = { date: 1, week: 1, month: 12, quarter: 12, year: 120 };
const monthCount = monthCountMap[mode] || 0;

const current = new Date(year, month);
Expand Down
2 changes: 1 addition & 1 deletion src/date-picker/DatePickerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const DatePickerPanel = forwardRef<HTMLDivElement, DatePickerPanelProps>((props,
// 头部快速切换
function onJumperClick({ trigger }) {
const triggerMap = { prev: 'arrow-previous', next: 'arrow-next' };
const monthCountMap = { date: 1, week: 1, month: 12, year: 120 };
const monthCountMap = { date: 1, week: 1, month: 12, quarter: 12, year: 120 };
const monthCount = monthCountMap[mode] || 0;

const current = new Date(year, month);
Expand Down
5 changes: 3 additions & 2 deletions src/date-picker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { TdDateRangePickerProps } from './type';
import { RangeInputPopup } from '../range-input';
import RangePanel from './panel/RangePanel';
import useRange from './hooks/useRange';
import { initYearMonthTime } from './hooks/useRangeValue';
import { parseToDayjs, formatTime, formatDate, isValidDate, getDefaultFormat } from './hooks/useFormat';
import { subtractMonth, addMonth, extractTimeObj } from '../_common/js/date-picker/utils';
import { dateRangePickerDefaultProps } from './defaultProps';
Expand Down Expand Up @@ -76,7 +77,7 @@ const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>((props,

// 空数据重置为当前年月
if (!value.length) {
setYear([dayjs().year(), dayjs().year()]);
setYear(initYearMonthTime(value, mode, format).year);
setMonth([dayjs().month(), dayjs().month() + 1]);
} else if (value.length === 2 && !enableTimePicker) {
// 确保右侧面板月份比左侧大 避免两侧面板月份一致
Expand Down Expand Up @@ -158,7 +159,7 @@ const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>((props,
function onJumperClick({ trigger, partial }) {
const partialIndex = partial === 'start' ? 0 : 1;

const monthCountMap = { date: 1, week: 1, month: 12, year: 120 };
const monthCountMap = { date: 1, week: 1, month: 12, quarter: 12, year: 120 };
const monthCount = monthCountMap[mode] || 0;
const current = new Date(year[partialIndex], month[partialIndex]);

Expand Down
2 changes: 1 addition & 1 deletion src/date-picker/DateRangePickerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const DateRangePickerPanel = forwardRef<HTMLDivElement, DateRangePickerPanelProp
const partialIndex = partial === 'start' ? 0 : 1;

const triggerMap = { '-1': 'arrow-previous', 1: 'arrow-next' };
const monthCountMap = { date: 1, week: 1, month: 12, year: 120 };
const monthCountMap = { date: 1, week: 1, month: 12, quarter: 12, year: 120 };
const monthCount = monthCountMap[mode] || 0;
const current = new Date(year[partialIndex], month[partialIndex]);

Expand Down
132 changes: 132 additions & 0 deletions src/date-picker/__tests__/__snapshots__/date-picker.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5969,6 +5969,138 @@ exports[`panel.jsx 1`] = `
</DocumentFragment>
`;

exports[`quarter.jsx 1`] = `
<DocumentFragment>
<div
class="t-space t-space-vertical"
style="gap: 16px;"
>
<div
class="t-space-item"
>
<div
class="t-date-picker"
>
<div
class="t-popup__reference t-select-input t-select-input--empty"
>
<div
class="t-input__wrap"
value=""
>
<div
class="t-input t-size-m t-align-left t-is-default t-input--prefix t-input--suffix"
>
<div
class="t-input__prefix"
/>
<input
class="t-input__inner"
placeholder="请输入"
type="text"
value=""
/>
<span
class="t-input__suffix t-input__suffix-icon"
>
<svg
class="t-icon t-icon-calendar"
fill="none"
height="1em"
viewBox="0 0 16 16"
width="1em"
>
<path
d="M10 3H6V1.5H5V3H3a1 1 0 00-1 1v9a1 1 0 001 1h10a1 1 0 001-1V4a1 1 0 00-1-1h-2V1.5h-1V3zM5 5h1V4h4v1h1V4h2v2H3V4h2v1zM3 7h10v6H3V7z"
fill="currentColor"
fill-opacity="0.9"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="t-space-item"
>
<div
class="t-date-range-picker"
>
<div
class="t-range-input-popup"
>
<div
class="t-popup__reference t-range-input-popup"
>
<div
class="t-range-input"
value=""
>
<div
class="t-range-input__inner"
>
<div
class="t-input__wrap t-range-input__inner-left"
>
<div
class="t-input t-size-m t-align-left t-is-default"
>
<input
class="t-input__inner"
placeholder="请输入内容"
type="text"
value=""
/>
</div>
</div>
<div
class="t-range-input__inner-separator"
>
-
</div>
<div
class="t-input__wrap t-range-input__inner-right"
>
<div
class="t-input t-size-m t-align-left t-is-default"
>
<input
class="t-input__inner"
placeholder="请输入内容"
type="text"
value=""
/>
</div>
</div>
<span
class="t-range-input__suffix t-range-input__suffix-icon"
>
<svg
class="t-icon t-icon-calendar"
fill="none"
height="1em"
viewBox="0 0 16 16"
width="1em"
>
<path
d="M10 3H6V1.5H5V3H3a1 1 0 00-1 1v9a1 1 0 001 1h10a1 1 0 001-1V4a1 1 0 00-1-1h-2V1.5h-1V3zM5 5h1V4h4v1h1V4h2v2H3V4h2v1zM3 7h10v6H3V7z"
fill="currentColor"
fill-opacity="0.9"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;

exports[`week.jsx 1`] = `
<DocumentFragment>
<div
Expand Down
15 changes: 15 additions & 0 deletions src/date-picker/_example/quarter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { DatePicker, DateRangePicker, Space } from 'tdesign-react';

export default function YearDatePicker() {
function handleChange(value) {
console.log(value);
}

return (
<Space direction="vertical">
<DatePicker mode="quarter" clearable allowInput onChange={handleChange} />
<DateRangePicker mode="quarter" clearable allowInput onChange={handleChange} />
</Space>
);
}
4 changes: 4 additions & 0 deletions src/date-picker/_usage/date-picker-props.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"label": "month",
"value": "month"
},
{
"label": "quarter",
"value": "quarter"
},
{
"label": "week",
"value": "week"
Expand Down
4 changes: 4 additions & 0 deletions src/date-picker/_usage/date-range-picker-props.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"label": "month",
"value": "month"
},
{
"label": "quarter",
"value": "quarter"
},
{
"label": "week",
"value": "week"
Expand Down
4 changes: 2 additions & 2 deletions src/date-picker/date-picker.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enableTimePicker | Boolean | false | 是否显示时间选择 | N
firstDayOfWeek | Number | - | 第一天从星期几开始。可选项:1/2/3/4/5/6/7 | N
format | String | - | 用于格式化日期,全局配置默认为:'YYYY-MM-DD',[详细文档](https://day.js.org/docs/en/display/format) | N
inputProps | Object | - | 透传给输入框(Input)组件的参数。TS 类型:`InputProps`,[Input API Documents](./input?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
mode | String | date | 选择器模式。可选项:year/month/week/date | N
mode | String | date | 选择器模式。可选项:year/month/quarter/week/date | N
placeholder | String / Array | undefined | 占位符。TS 类型:`string` | N
popupProps | Object | - | 透传给 popup 组件的参数。TS 类型:`PopupProps`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
prefixIcon | TElement | - | 用于自定义组件前置图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
Expand Down Expand Up @@ -44,7 +44,7 @@ disableDate | Object / Array / Function | - | 禁用日期,示例:['A', 'B']
enableTimePicker | Boolean | false | 是否显示时间选择 | N
firstDayOfWeek | Number | - | 第一天从星期几开始。可选项:1/2/3/4/5/6/7 | N
format | String | - | 用于格式化日期,[详细文档](https://day.js.org/docs/en/display/format) | N
mode | String | date | 选择器模式。可选项:year/month/week/date | N
mode | String | date | 选择器模式。可选项:year/month/quarter/week/date | N
panelPreselection | Boolean | true | 在开始日期选中之前,面板是否显示预选状态,即是否高亮预选日期 | N
placeholder | String / Array | - | 占位符,值为数组表示可分别为开始日期和结束日期设置占位符。TS 类型:`string | Array<string>` | N
popupProps | Object | - | 透传给 popup 组件的参数。TS 类型:`PopupProps`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
Expand Down
26 changes: 26 additions & 0 deletions src/date-picker/hooks/useFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ export function parseToDayjs(value: string | Date | number, format: string, time
}
}
}

// format quarter
if (/Q/g.test(format)) {
if (typeof dateText !== 'string') {
dateText = dayjs(dateText).format(format);
}

const yearStr = dateText.split(/[-/.]/)[0];
const quarterStr = dateText.split(/[-/.]/)[1];
const quarterFormatStr = format.split(/[-/.]/)[1];
const firstWeek = dayjs(yearStr, 'YYYY').startOf('year');
for (let i = 0; i <= 52; i += 1) {
const nextQuarter = firstWeek.add(i, 'quarter');
if (nextQuarter.format(quarterFormatStr) === quarterStr) {
return nextQuarter;
}
}
}

// 兼容数据格式不标准场景 YYYY-MM-D
return dayjs(dateText, format).isValid() ? dayjs(dateText, format) : dayjs(dateText);
}
Expand Down Expand Up @@ -145,6 +164,13 @@ export function getDefaultFormat({
timeFormat: TIME_FORMAT,
};
}
if (mode === 'quarter') {
return {
format: format || 'YYYY-[Q]Q',
valueType: valueType || 'YYYY-[Q]Q',
timeFormat: TIME_FORMAT,
};
}
if (mode === 'week') {
return {
format: format || 'YYYY-wo',
Expand Down
14 changes: 7 additions & 7 deletions src/date-picker/hooks/useRangeValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ import { useState, useEffect } from 'react';
import dayjs from 'dayjs';
import useControlled from '../../hooks/useControlled';
import { TdDateRangePickerProps, DateValue } from '../type';
import { isValidDate, formatDate, formatTime, getDefaultFormat } from './useFormat';
import { isValidDate, formatDate, formatTime, getDefaultFormat, parseToDayjs } from './useFormat';
import { extractTimeFormat } from '../../_common/js/date-picker/utils';

export const PARTIAL_MAP = { first: 'start', second: 'end' };

// 初始化面板年份月份
function initYearMonthTime(value: DateValue[], mode = 'date', format: string, timeFormat = 'HH:mm:ss') {
export function initYearMonthTime(value: DateValue[], mode = 'date', format: string, timeFormat = 'HH:mm:ss') {
const defaultYearMonthTime = {
year: [dayjs().year(), dayjs().year()],
month: [dayjs().month(), dayjs().month()],
time: [dayjs().format(timeFormat), dayjs().format(timeFormat)],
};
if (mode === 'year') {
defaultYearMonthTime.year[1] += 10;
} else if (mode === 'month') {
} else if (mode === 'month' || mode === 'quarter') {
defaultYearMonthTime.year[1] += 1;
} else if (mode === 'date') {
} else if (mode === 'date' || mode === 'week') {
defaultYearMonthTime.month[1] += 1;
}

Expand All @@ -27,9 +27,9 @@ function initYearMonthTime(value: DateValue[], mode = 'date', format: string, ti
}

return {
year: value.map((v) => dayjs(v, format).year() || dayjs(v).year()),
month: value.map((v) => dayjs(v, format).month() || dayjs(v).month()),
time: value.map((v) => dayjs(v, format).format(timeFormat) || dayjs(v).format(timeFormat)),
year: value.map((v) => parseToDayjs(v, format).year()),
month: value.map((v) => parseToDayjs(v, format).month()),
time: value.map((v) => parseToDayjs(v, format).format(timeFormat)),
};
}

Expand Down
4 changes: 3 additions & 1 deletion src/date-picker/hooks/useTableData.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useLocaleReceiver } from '../../locale/LocalReceiver';
import { getWeeks, getYears, getMonths, flagActive } from '../../_common/js/date-picker/utils';
import { getWeeks, getQuarters, getYears, getMonths, flagActive } from '../../_common/js/date-picker/utils';
import type { SinglePanelProps } from '../panel/SinglePanel';

export interface TableDataProps extends SinglePanelProps {
Expand Down Expand Up @@ -48,6 +48,8 @@ export default function useTableData(props: TableDataProps) {
data = getWeeks({ year, month }, options);
} else if (mode === 'week') {
data = getWeeks({ year, month }, options);
} else if (mode === 'quarter') {
data = getQuarters(year, options);
} else if (mode === 'month') {
data = getMonths(year, options);
} else if (mode === 'year') {
Expand Down
4 changes: 3 additions & 1 deletion src/date-picker/panel/PanelContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export default function PanelContent(props: PanelContentProps) {

const { timeFormat } = getDefaultFormat({ mode, format, enableTimePicker });

const showTimePicker = enableTimePicker && mode === 'date';

const defaultTime = '00:00:00';

return (
Expand Down Expand Up @@ -85,7 +87,7 @@ export default function PanelContent(props: PanelContentProps) {
/>
</div>

{enableTimePicker && (
{showTimePicker && (
<div className={`${panelName}-time`}>
<div className={`${panelName}-time-viewer`}>{time || defaultTime}</div>
<TimePickerPanel
Expand Down
4 changes: 2 additions & 2 deletions src/date-picker/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface TdDatePickerProps {
* 选择器模式
* @default date
*/
mode?: 'year' | 'month' | 'week' | 'date';
mode?: 'year' | 'month' | 'quarter' | 'week' | 'date';
/**
* 占位符
*/
Expand Down Expand Up @@ -155,7 +155,7 @@ export interface TdDateRangePickerProps {
* 选择器模式
* @default date
*/
mode?: 'year' | 'month' | 'week' | 'date';
mode?: 'year' | 'month' | 'quarter' | 'week' | 'date';
/**
* 在开始日期选中之前,面板是否显示预选状态,即是否高亮预选日期
* @default true
Expand Down
2 changes: 2 additions & 0 deletions test/ssr/__snapshots__/ssr.test.js.snap

Large diffs are not rendered by default.