-
Notifications
You must be signed in to change notification settings - Fork 358
feat(calendar): add function to support setting start or end of range separately #2347
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
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
3cc9a25
feat(calendar): calendar组件公用逻辑新增最小年份常量
shumuuu c9d98aa
feat(calendar): calendar组件公用逻辑新增日历显示范围相关类型
shumuuu 373ad06
feat(calendar): calendar组件公用逻辑新增日历范围相关工具函数
shumuuu e698acb
fix(calendar): 更名rangeFromTo函数为handleRange以解决与主仓库函数重名的问题
shumuuu 9ee523c
fix(calendar): handleRange函数返回类型漏了null
shumuuu f36a812
test(calendar): 新增createDefaultCurDate和handleRange的测试案例并提升覆盖率至100%
shumuuu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // 最小年份 | ||
| export const MIN_YEAR = 1970; | ||
|
|
||
| export default { | ||
| MIN_YEAR, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| export type CalendarValue = string | Date; | ||
|
|
||
| /** | ||
| * 日历的显示范围 | ||
| */ | ||
| export interface CalendarRange { | ||
| from: CalendarValue; | ||
| to: CalendarValue; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import dayjs from 'dayjs'; | ||
|
|
||
| import type { CalendarRange, CalendarValue } from './types'; | ||
| import { MIN_YEAR } from './consts'; | ||
|
|
||
| /** | ||
| * 根据当前时间创建一个默认日期 | ||
| * @returns 当前日期的dayjs对象 | ||
| */ | ||
| export const createDefaultCurDate = (): dayjs.Dayjs => dayjs(dayjs().format('YYYY-MM-DD')); | ||
|
|
||
| /** | ||
| * 处理`range`参数输入值并生成日历范围 | ||
| * @param range 用于设置日历的年月份显示范围,[范围开始,范围结束] | ||
| * @returns 处理完成的日历范围 | ||
| */ | ||
| export const handleRange = ( | ||
| range?: Array<CalendarValue> | ||
| ): { from: CalendarValue; to: CalendarValue } | null => { | ||
shumuuu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // 检查范围边界 | ||
| const parseRangeBoundary = ( | ||
| value: CalendarRange['from'] | CalendarRange['to'] | null | undefined | ||
| ) => { | ||
| if (value === undefined || value === null) { | ||
| return null; | ||
| } | ||
| const parsed = dayjs(value); | ||
| if (!parsed.isValid()) { | ||
| return null; | ||
| } | ||
| return { | ||
| parsed, // dayjs 对象 | ||
| original: value as CalendarRange['from'] | CalendarRange['to'], // 原始值 | ||
| }; | ||
| }; | ||
|
|
||
| if (!range || range.length < 2) { | ||
shumuuu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return null; | ||
| } | ||
| const [v1, v2] = range; | ||
| const start = parseRangeBoundary(v1); | ||
| const end = parseRangeBoundary(v2); | ||
|
|
||
| if (!start && !end) { | ||
| return null; | ||
| } | ||
|
|
||
| // 未指定边界上/下限时使用默认值 | ||
| const fallback = ( | ||
| edge: 'from' | 'to' | ||
| ): { parsed: dayjs.Dayjs; original: string } => { | ||
| let fallbackParsed = dayjs(MIN_YEAR); | ||
shumuuu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (edge === 'to') { | ||
| fallbackParsed = createDefaultCurDate(); | ||
| } | ||
| return { | ||
| parsed: fallbackParsed, | ||
| original: fallbackParsed.format('YYYY-MM-DD'), | ||
| }; | ||
| }; | ||
|
|
||
| let fromBoundary = start ?? fallback('from'); | ||
| let toBoundary = end ?? fallback('to'); | ||
|
|
||
| if (fromBoundary.parsed.isAfter(toBoundary.parsed)) { | ||
| [fromBoundary, toBoundary] = [toBoundary, fromBoundary]; // 当前一项日期大于后一项时交换两值以确保边界逻辑正确 | ||
| } | ||
|
|
||
| return { | ||
| from: fromBoundary.original, | ||
| to: toBoundary.original, | ||
| }; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| import { describe, it, expect } from "vitest"; | ||
| import dayjs from "dayjs"; | ||
| import { createDefaultCurDate, handleRange } from "../../../js/calendar/utils"; | ||
|
|
||
| describe("utils", () => { | ||
| describe("createDefaultCurDate", () => { | ||
| it("返回当前日期的dayjs对象且日期格式为YYYY-MM-DD", () => { | ||
| const result = createDefaultCurDate(); | ||
| expect(result).toBeDefined(); | ||
| expect(result.isValid()).toBe(true); | ||
| const formatted = result.format("YYYY-MM-DD"); | ||
| const expected = dayjs().format("YYYY-MM-DD"); | ||
| expect(formatted).toBe(expected); | ||
| }); | ||
| }); | ||
|
|
||
| describe("handleRange", () => { | ||
| // 场景1: 传入非列表值/传入列表值少于两项/传入列表值的两项均非日期格式 | ||
| it("传入 undefined 返回 null", () => { | ||
| const result = handleRange(undefined); | ||
| expect(result).toBeNull(); | ||
| }); | ||
|
|
||
| it("传入 null 返回 null", () => { | ||
| const result = handleRange(null); | ||
| expect(result).toBeNull(); | ||
| }); | ||
|
|
||
| it("传入非列表值返回 null", () => { | ||
| const result = handleRange("not-a-array"); | ||
| expect(result).toBeNull(); | ||
| }); | ||
|
|
||
| it("传入长度小于2的列表返回 null", () => { | ||
| expect(handleRange([])).toBeNull(); | ||
| expect(handleRange(["2024-01-15"])).toBeNull(); | ||
| }); | ||
|
|
||
| it("传入长度为2且两项均非日期格式的列表返回 null", () => { | ||
| expect(handleRange([null, undefined])).toBeNull(); | ||
| expect(handleRange(["abc", "not-a-date"])).toBeNull(); | ||
| }); | ||
|
|
||
| // 场景2: 传入列表值的两项中有一项符合日期格式,另一项不符合 | ||
| it("传入第一项为非日期格式且第二项为日期的列表,第一项使用默认值处理", () => { | ||
| const result = handleRange(["abc", "2024-01-15"]); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBe("1970-01-01"); | ||
| expect(result.to).toBe("2024-01-15"); | ||
| }); | ||
|
|
||
| it("传入第一项为日期且第二项为非日期格式的列表,第二项使用默认值处理", () => { | ||
| const result = handleRange(["2024-01-15", "not-a-date"]); | ||
| const today = dayjs().format("YYYY-MM-DD"); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBe("2024-01-15"); | ||
| expect(result.to).toBe(today); | ||
| }); | ||
|
|
||
| // 场景3: 传入列表值的两项均符合日期格式 | ||
| it("传入两项均为日期列表且第一项日期早于第二项日期,原样返回", () => { | ||
| const result = handleRange(["2024-01-15", "2024-12-31"]); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBe("2024-01-15"); | ||
| expect(result.to).toBe("2024-12-31"); | ||
| }); | ||
|
|
||
| it("传入两项均为日期列表且第一项日期不早于第二项日期,交换两项后返回", () => { | ||
| const result = handleRange(["2024-12-31", "2024-01-15"]); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBe("2024-01-15"); | ||
| expect(result.to).toBe("2024-12-31"); | ||
| }); | ||
|
|
||
| it("处理传入两项为Date格式的列表", () => { | ||
| const date1 = new Date("2024-01-15"); | ||
| const date2 = new Date("2024-12-31"); | ||
| const result = handleRange([date1, date2]); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBeInstanceOf(Date); | ||
| expect(result.to).toBeInstanceOf(Date); | ||
| expect(result.from.getTime()).toBe(new Date("2024-01-15").getTime()); | ||
| expect(result.to.getTime()).toBe(new Date("2024-12-31").getTime()); | ||
| }); | ||
|
|
||
| it("处理传入一项字符串格式日期另一项为Date格式的列表", () => { | ||
| const date1 = new Date("2024-01-15"); | ||
| const result = handleRange([date1, "2024-12-31"]); | ||
| expect(result).not.toBeNull(); | ||
| // Date object is returned as-is, string is returned as string | ||
| expect(result.from).toBeInstanceOf(Date); | ||
| expect(result.to).toBe("2024-12-31"); | ||
| expect(result.from.getTime()).toBe(new Date("2024-01-15").getTime()); | ||
| }); | ||
|
|
||
| it("传入两项均为日期且处于同一天的列表,原样返回", () => { | ||
| const result = handleRange(["2024-01-15", "2024-01-15"]); | ||
| expect(result).not.toBeNull(); | ||
| expect(result.from).toBe("2024-01-15"); | ||
| expect(result.to).toBe("2024-01-15"); | ||
| }); | ||
| }); | ||
| }); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.