-
Notifications
You must be signed in to change notification settings - Fork 269
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(calendar): add viewmode #2985
base: next
Are you sure you want to change the base?
Conversation
Walkthrough此次改动对日历组件进行了扩展和重构。主要新增了 Changes
Sequence Diagram(s)sequenceDiagram
participant U as 用户
participant C as 日历组件
participant CI as CalendarItem
participant CV as CalendarViewModeItem
U->>C: 触发点击或选择事件
alt viewMode 为 "day"
C->>CI: 渲染日视图 (CalendarItem)
else viewMode 为 "month" 或 "quarter"
C->>CV: 渲染月/季度视图 (CalendarViewModeItem)
end
C->>U: 执行 onItemClick 回调
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (15)
src/packages/calendar/calendar.tsx (2)
142-175
: **避免以 props.children 方式注入内容 **
在第 148 行使用了children={children}
,根据静态分析建议,通常在 React 中直接以<CalendarViewModeItem>{children}</CalendarViewModeItem>
方式传递子元素更为规范,避免通过children
属性显式传递。若组件需要更多灵活性,可考虑保留,但建议优化:-<CalendarViewModeItem - ref={calendarRef} - ... - children={children} /> +<CalendarViewModeItem + ref={calendarRef} + ... +> + {children} +</CalendarViewModeItem>🧰 Tools
🪛 Biome (1.9.4)
[error] 148-148: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
176-205
: **同理,避免显式传递 children **
与上面相同,第 180 行也通过children={children}
来注入内容。可考虑使用 JSX 包裹方式来渲染子元素,以更符合 React 规范并提高可读性。-<CalendarItem - ref={calendarRef} - ... - children={children} /> +<CalendarItem + ref={calendarRef} + ... +> + {children} +</CalendarItem>🧰 Tools
🪛 Biome (1.9.4)
[error] 180-180: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendarviewmodeitem.tsx (3)
429-448
: **switch 语句中的局部变量作用域 **
静态分析提示在 switch 中声明的变量可能会被其他 case 使用,为避免作用域冲突,可考虑在 case 内添加大括号或提取局部变量到外部,增强可维护性。🧰 Tools
🪛 Biome (1.9.4)
[error] 443-444: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
602-607
: **使用可选链以简化安全访问 **
静态分析建议在访问对象属性时,可使用“可选链”语法?.
,以避免某些空值情况导致的报错:someObj?.property🧰 Tools
🪛 Biome (1.9.4)
[error] 602-607: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
607-608
: **同理,使用可选链 **
同一位置可继续使用可选链,减少安全判断的重复逻辑。🧰 Tools
🪛 Biome (1.9.4)
[error] 607-608: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendaritem/calendaritem.tsx (2)
264-278
: **针对 single 模式的默认日期逻辑 **
在此进行单个日期的默认值设定时,判断条件较多,可进一步拆分成辅助函数,提升可读性与后续扩展。
566-609
: **抽离 handleDayClick 函数简化交互 **
此处集中处理多类型的日期选择逻辑;如果后续功能增多,可以继续拆分单选、多选、范围等逻辑到各自独立的函数,以简化条件判断。src/packages/calendaritem/calendaritem.taro.tsx (4)
81-82
: 默认属性中使用 getDay(0) 和 getDay(365)
可以考虑在注释中说明数字 365 的含义,提升可维护性。
194-194
: 新增 getMonthData 方法
建议在方法周边添加注释,注明其返回格式与用途,便于后期维护。
210-210
: 硬编码高度数值
建议提取成常量或写在配置处,便于维护和后续修改。- const cssHeight = 39 + (days.length > 35 ? 384 : 320) + const BASE_HEIGHT = 39 + const EXTENDED_HEIGHT = 384 + const DEFAULT_HEIGHT = 320 + const cssHeight = BASE_HEIGHT + (days.length > 35 ? EXTENDED_HEIGHT : DEFAULT_HEIGHT)
370-402
: renderCurrentDate 函数的多分支逻辑
这里有多个类型判断(range、week、multiple 等),建议完善单元测试覆盖,避免遗漏交互情形。src/packages/calendar/calendarviewmodeitem.taro.tsx (1)
81-82
: 默认 startDate 与 endDate 使用 getDay
可考虑在注释或文档中解释 365 的含义,让维护者更快理解。src/utils/date.ts (2)
301-301
: 移除调试日志!开发环境的 console.log 语句不应该提交到代码库中。
- console.log('firstDayOfWeek', firstDayOfWeek, firstDayOfYear.getDay())
340-345
: 移除注释掉的测试代码!这些被注释掉的测试代码应该被移除,保持代码整洁。
-// // 计算 2025 和 2026 年的总周数 -// const weeksIn2025 = getTotalWeeksInYear(2025); -// const weeksIn2026 = getTotalWeeksInYear(2026); -// // console.log(`2025 年有 ${weeksIn2025} 周`); -// // console.log(`2026 年有 ${weeksIn2026} 周`);src/packages/calendar/calendarviewmode.scss (1)
28-30
: 建议使用更通用的滚动条隐藏方式!当前只隐藏了 webkit 浏览器的滚动条,建议添加其他浏览器的兼容性支持。
::-webkit-scrollbar { display: none; } +/* Firefox */ +* { + scrollbar-width: none; +} +/* IE and Edge */ +* { + -ms-overflow-style: none; +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/packages/calendar/calendar.scss
(2 hunks)src/packages/calendar/calendar.taro.tsx
(2 hunks)src/packages/calendar/calendar.tsx
(4 hunks)src/packages/calendar/calendarviewmode.scss
(1 hunks)src/packages/calendar/calendarviewmodeitem.taro.tsx
(1 hunks)src/packages/calendar/calendarviewmodeitem.tsx
(1 hunks)src/packages/calendar/demos/h5/demo1.tsx
(0 hunks)src/packages/calendar/demos/taro/demo1.tsx
(0 hunks)src/packages/calendar/utils.tsx
(2 hunks)src/packages/calendarcard/utils.ts
(3 hunks)src/packages/calendaritem/calendaritem.taro.tsx
(15 hunks)src/packages/calendaritem/calendaritem.tsx
(15 hunks)src/styles/variables.scss
(1 hunks)src/utils/date.ts
(4 hunks)
💤 Files with no reviewable changes (2)
- src/packages/calendar/demos/h5/demo1.tsx
- src/packages/calendar/demos/taro/demo1.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendar.tsx
[error] 148-148: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 180-180: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendarviewmodeitem.tsx
[error] 179-180: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 443-444: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 451-452: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 458-458: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 595-596: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 602-607: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 607-608: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendarviewmodeitem.taro.tsx
[error] 239-240: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 299-299: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 301-301: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 317-318: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 319-320: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 632-633: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 655-657: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 674-675: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 675-676: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendaritem/calendaritem.taro.tsx
[error] 299-299: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 301-301: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 317-318: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 319-320: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 632-633: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 674-675: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 675-676: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 GitHub Check: build
src/packages/calendar/calendarviewmodeitem.tsx
[failure] 212-212:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 214-214:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 217-217:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
🪛 GitHub Actions: CI
src/packages/calendar/calendarviewmodeitem.tsx
[error] 212-212: Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
🪛 GitHub Check: lint
src/packages/calendar/calendarviewmodeitem.taro.tsx
[warning] 456-456:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
[warning] 465-465:
React Hook useEffect has missing dependencies: 'resetDefaultValue' and 'setCurrentDate'. Either include them or remove the dependency array
🔇 Additional comments (44)
src/packages/calendar/calendar.tsx (5)
4-5
: **引入新组件以支持多视图模式 **
这两行导入了CalendarViewModeItem
和getDay
方法,用于在日历中支持新的多视图模式和替换原有的日期工具函数,没有发现明显问题。
12-12
: **新增 viewMode 属性 **
在CalendarProps
中为viewMode
定义了'week' | 'month' | 'quarter'
,可增强组件的可扩展性与灵活度。
44-44
: **默认值设置为 'quarter' **
此处设置了viewMode: 'quarter'
作为默认值,保证组件在未显式传递值时也有可用的默认视图模式。
50-51
: **替换 Utils.getDay 为 getDay **
用getDay(0)
与getDay(365)
代替旧的工具函数,逻辑清晰,无明显功能风险。
83-83
: **在 props 中解构 viewMode **src/packages/calendar/calendarviewmodeitem.tsx (3)
1-5
: **新增组件 CalendarViewModeItem **
引入了独立组件CalendarViewModeItem
并扩展了对应类型与默认属性,为日历提供周、月、季度多种查看模式,整体结构清晰。
38-65
: **属性定义全面且易扩展 **
新增的CalendarViewModeItemProps
包含了多种可配置项,并融合了PopupProps
,可满足多种日历场景需求。
451-452
: **修复类型警告以通过 CI **
此处同样存在声明变量后可能被其他 case 访问的问题或类型冲突。你可在 switch case 内部使用块级作用域,或者根据逻辑提取到函数外部。🧰 Tools
🪛 Biome (1.9.4)
[error] 451-452: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
src/packages/calendaritem/calendaritem.tsx (8)
7-7
: **移除 Utils 并使用更明确的工具函数 **
以getDay
等单一函数替代之前的Utils
命名空间,让逻辑和可维护性更直观。
80-81
: **默认 startDate/endDate 的设置 **
将startDate
和endDate
赋值为getDay(0)
与getDay(365)
,与其他文件改动统一,便于维护。
192-200
: **在 getMonthData 中替换 compareDate 和 getMonthDays **
改用新的工具方法替换之前的 Utils 调用,功能上无明显问题,维护性更好。
216-217
: **处理传入日期区间的边界校验 **
此处调用!compareDate(...)
进行范围判断,建议注意起止日期相等或逆序等特殊情况,避免出现日期超出范围仍被加入的风险。
528-534
: **新增 isDisable 校验 **
添加了对不可点击日期的逻辑判断,并与组件的时间区间限制衔接合理。
537-563
: **整合校验逻辑并返回对应类名 **
为日历单元格生成对应的禁用、选中等状态类名,逻辑较清晰,且与disableDate
函数相结合。
711-759
: **渲染日历单元格的细粒度控制 **
使用renderItem
独立渲染每个日期格子,支持自定义插槽和多种提示信息,结构清晰。无明显缺陷。
762-773
: **分解 renderPanel 以实现月份级渲染 **
将每个月的渲染封装为renderPanel
,结合renderItem
进一步提升了代码可读性和可维护性。src/packages/calendaritem/calendaritem.taro.tsx (9)
8-19
: 导入多个日期工具函数的方式不错
这有助于增强可读性并减少命名空间依赖,整体实现良好。
116-116
: 在 props 解构中增加 value
此变更逻辑清晰,不存在明显风险。
158-159
: 初始化 propStartDate 和 propEndDate
目前的写法易读性较好,未发现隐患。
202-204
: 使用展开运算符获取日期数组
该写法简洁明了,与 date 工具函数结合度较好。
218-221
: compareDate 条件判断
建议再次确认 compareDate 的比较逻辑,如果日期相等也需要特殊处理,请确保无漏失。
228-228
: 向 monthData 推入新月度信息
此处操作符合整体逻辑,暂未发现明显问题。
455-456
: useEffect 缺少对 initData 的依赖
如果 initData 内会使用到组件中随时变化的状态或参数,建议将其加入依赖数组,以确保逻辑同步。
464-465
: useEffect 缺少对 resetDefaultValue 与 setCurrentDate 的依赖
请确认这两个函数是否会改变,若变化则需要放入依赖,防止出现状态不同步问题。
674-675
: 关于可选链提示
此处没有明显理由使用可选链,推测是误报,可暂时忽略。🧰 Tools
🪛 Biome (1.9.4)
[error] 674-675: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendarviewmodeitem.taro.tsx (7)
1-19
: 批量引入日期工具方法
此做法可提升可读性,方便日后维护与模块化。
158-159
: 对 propStartDate 和 propEndDate 进行可选赋值
当前实现逻辑正常,无额外风险。
239-240
: 静态分析建议改为可选链
如需防范 currentMonthsData 为空的情况,可使用可选链,但若本逻辑保证其始终存在,可保持现状。🧰 Tools
🪛 Biome (1.9.4)
[error] 239-240: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
455-456
: useEffect 未包含 initData
若 initData 内部使用了外部状态,请将其加入依赖,防止运行结果与预期不符。🧰 Tools
🪛 GitHub Check: lint
[warning] 456-456:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
465-465
: useEffect 未包含 resetDefaultValue 和 setCurrentDate
同理,需要确认这些函数是否变化,如包含外部状态,需将其放入依赖列表。🧰 Tools
🪛 GitHub Check: lint
[warning] 465-465:
React Hook useEffect has missing dependencies: 'resetDefaultValue' and 'setCurrentDate'. Either include them or remove the dependency array
655-657
: 改用可选链的提示
可根据实际场景决定,若确实需要对链式属性进行安全访问,可加,否则视为误报。🧰 Tools
🪛 Biome (1.9.4)
[error] 655-657: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
674-676
: 再次提醒使用可选链
若本处数据结构已保证安全,可忽略此提示。🧰 Tools
🪛 Biome (1.9.4)
[error] 674-675: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 675-676: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/utils.tsx (7)
1-1
: 拆分并直接引入 isEqual、date2Str、getNumTwoBit
此改动有助于减少对大型工具对象的依赖,促进模块化。
12-12
: 在 isMultiple 中调用 isEqual
逻辑直观,能有效判定目标日期相等性。
20-20
: 通过 isEqual 比较当前日期与今日
方法简洁易懂,满足功能需求。
24-24
: 生成当前选中日期字符串
拼接字符串时使用 getNumTwoBit,有效保证日的两位格式。
28-28
: isStart 函数
通过 isEqual 判断开始日期,符合直觉。
32-32
: isEnd 函数
同理,结尾日期比较逻辑与 isStart 保持一致。
37-37
: isStartAndEnd 函数
当开始时间与结束时间相等时返回 true,逻辑无误。src/packages/calendarcard/utils.ts (1)
1-1
: 代码重构改进了模块化!将
Utils
命名空间替换为直接导入函数的方式,使代码结构更清晰,依赖关系更明确。src/packages/calendar/calendar.taro.tsx (1)
47-48
: 代码更新与工具函数重构保持一致!将
Utils.getDay
替换为直接导入的getDay
函数,保持了代码的一致性。src/packages/calendar/calendar.scss (2)
2-2
: 导入语句添加正确!新增的
calendarviewmode.scss
导入语句与视图模式功能相关,遵循了样式文件导入的最佳实践。
197-205
: 样式结构优化合理!将禁用状态样式移至
choose
类下是个很好的重构:
- 提高了样式的组织性和可维护性
- 保持了原有的样式属性
- 遵循了 BEM 命名规范
src/styles/variables.scss (1)
948-951
: 变量定义规范合理!新增的日历面板项宽度变量:
- 遵循了项目的变量命名规范
- 使用 CSS 自定义属性实现更好的定制性
- 提供了合理的默认值 24.28%
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/packages/calendar/calendarviewmodeitem.tsx (1)
212-218
:⚠️ Potential issue修复类型不匹配问题
compareDate
函数期望接收 string 类型参数,但这里传入的是CalendarValue
类型。建议修改为:
- if (compareDate(currentDate, propStartDate)) { + if (compareDate(currentDate as string, propStartDate)) { defaultData = [...splitDate(propStartDate)] - } else if (!compareDate(currentDate, propEndDate)) { + } else if (!compareDate(currentDate as string, propEndDate)) { defaultData = [...splitDate(propEndDate)] } else { defaultData = [...splitDate(currentDate)] }🧰 Tools
🪛 GitHub Check: build
[failure] 212-212:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 214-214:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 217-217:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.🪛 GitHub Actions: CI
[error] 212-212: Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
🧹 Nitpick comments (6)
src/packages/calendar/calendarviewmodeitem.tsx (4)
155-155
: 移除调试日志代码中存在多个 console.log 语句,这些不应该出现在生产代码中。
建议移除这些调试日志:
- console.log('propStartDate', propStartDate, propEndDate, endDate)
- console.log('month', month, endMonth)
Also applies to: 393-393
319-322
: 完善周数据获取逻辑
getWeeksData
函数目前返回空数组,需要实现获取可用周数的逻辑。是否需要我帮助实现这个函数的具体逻辑?我可以提供一个基于日期范围计算可用周数的实现方案。
441-461
: 优化 switch 语句结构switch 语句中的变量声明可能会导致作用域问题。
建议将每个 case 块用大括号包裹:
switch (viewMode) { case 'week': { - // eslint-disable-next-line no-case-declarations const weeks = getWeeksData() setPanelDate({ ...panelDate, weeks }) break + } case 'month': { - // eslint-disable-next-line no-case-declarations const months = getMonthsData() setPanelDate({ ...panelDate, months: months as any }) break + } case 'quarter': { - // eslint-disable-next-line no-case-declarations const quarters = getQuartersData() setPanelDate({ ...panelDate, quarters: quarters as any }) break + } default: break }🧰 Tools
🪛 Biome (1.9.4)
[error] 455-455: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
505-520
: 优化滚动动画实现当前的滚动动画使用 setInterval 实现,建议使用更现代的方案。
建议使用 requestAnimationFrame 实现平滑滚动:
- let flag = 0 - const interval = setInterval(() => { - flag++ - if (monthsRef.current) { - const offset = distance / 10 - monthsRef.current.scrollTop += offset - } - if (flag >= 10) { - clearInterval(interval) - if (monthsRef.current) { - monthsRef.current.scrollTop = currTop - } - } - }, 40) + const startTime = performance.now() + const duration = 400 // 动画持续时间(毫秒) + + const animate = (currentTime: number) => { + const elapsed = currentTime - startTime + const progress = Math.min(elapsed / duration, 1) + + if (monthsRef.current) { + monthsRef.current.scrollTop = currTop - distance + distance * progress + } + + if (progress < 1) { + requestAnimationFrame(animate) + } + } + + requestAnimationFrame(animate)src/packages/calendar/calendarviewmode.scss (2)
125-125
: 避免使用 !important多处使用了
!important
声明,这可能导致样式难以维护和覆盖。建议通过提高选择器优先级来替代
!important
:- color: $color-primary-text !important; + .nut-calendar-viewmode .nut-calendar-viewmode-item-active { + color: $color-primary-text; + } - color: $calendar-disable-color !important; + .nut-calendar-viewmode .nut-calendar-viewmode-item-prev, + .nut-calendar-viewmode .nut-calendar-viewmode-item-next { + color: $calendar-disable-color; + }Also applies to: 134-134
160-162
: 避免使用硬编码的 !important
.nut-calendar-popup .nut-popup-title-right
选择器使用了硬编码的!important
。建议通过提高选择器优先级来替代:
- .nut-calendar-popup .nut-popup-title-right { - top: 7px !important; - } + .nut-calendar-popup.nut-popup .nut-popup-title-right { + top: 7px; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/packages/calendar/calendarviewmode.scss
(1 hunks)src/packages/calendar/calendarviewmodeitem.tsx
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendarviewmodeitem.tsx
[error] 179-180: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 455-455: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 459-463: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 470-470: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 604-607: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 615-615: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 615-618: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 GitHub Check: build
src/packages/calendar/calendarviewmodeitem.tsx
[failure] 212-212:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 214-214:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
[failure] 217-217:
Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
🪛 GitHub Actions: CI
src/packages/calendar/calendarviewmodeitem.tsx
[error] 212-212: Argument of type 'CalendarValue' is not assignable to parameter of type 'string'.
🔇 Additional comments (1)
src/packages/calendar/calendarviewmode.scss (1)
91-93
: 重复的类名定义
.nut-calendar-viewmode-content
类在第53行已定义,这里重复定义可能导致样式冲突。建议合并这两处样式定义或使用不同的类名。
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## next #2985 +/- ##
==========================================
- Coverage 85.52% 85.13% -0.40%
==========================================
Files 267 268 +1
Lines 18000 18529 +529
Branches 2723 2779 +56
==========================================
+ Hits 15395 15775 +380
- Misses 2602 2751 +149
Partials 3 3 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🔭 Outside diff range comments (2)
src/packages/calendaritem/calendaritem.tsx (2)
446-448
:⚠️ Potential issue修复 useEffect 依赖项
useEffect 缺少 initData 依赖项。
useEffect(() => { initData() - }, []) + }, [initData])注意:由于 initData 依赖了很多状态和属性,建议使用 useCallback 来优化:
const initData = useCallback(() => { // 现有实现... }, [startDates, endDates, currentDate, type, firstDayOfWeek])
286-337
: 🛠️ Refactor suggestion优化 switch 语句中的变量作用域
switch 语句中的变量声明应该使用块级作用域,以防止变量泄漏。
switch (type) { case 'range': + { // 现有实现... + } break case 'multiple': + { const defaultArr = [] as string[] const obj: Record<string, unknown> = {} // 现有实现... + } break case 'week': + { const [y, m, d] = splitDate(currentDate[0]) const weekArr = getWeekDate(y, m, d, firstDayOfWeek) // 现有实现... + } break default: break }
♻️ Duplicate comments (2)
src/packages/calendar/calendar.taro.tsx (1)
153-153
: 🛠️ Refactor suggestion避免使用 children prop。
根据 React 最佳实践,应该使用 JSX 元素传递子组件而不是通过 prop。
Also applies to: 172-172
🧰 Tools
🪛 Biome (1.9.4)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendarviewmodeitem.taro.tsx (1)
241-256
: 🛠️ Refactor suggestion使用块作用域限制 switch case 中的变量
在 switch 语句中声明的变量可能会泄漏到其他 case。建议使用块作用域来限制变量的访问范围。
switch (viewMode) { case 'month': + { const months = getMonthsData() setPanelDate({ ...panelDate, months: months as any }) + } break case 'quarter': + { const quarters = getQuartersData() setPanelDate({ ...panelDate, quarters: quarters as any }) + } break default: break }🧰 Tools
🪛 Biome (1.9.4)
[error] 251-252: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🧹 Nitpick comments (17)
src/packages/calendar/demos/h5/demo102.tsx (1)
7-10
: 建议移除生产环境中的控制台日志
select
函数中的console.log
应在生产环境中移除。const select = (param: string) => { - console.log('select', param) setDate(param) }
src/packages/calendar/demos/taro/demo102.tsx (1)
1-34
: 建议提取共享代码H5 和 Taro 版本的 Demo2 组件代码几乎完全相同,建议:
- 提取共享的逻辑到一个公共的 hooks 文件中
- 只在组件中保留平台特定的实现
建议创建一个共享的 hook:
// hooks/useCalendarMonth.ts import { useState } from 'react' export const useCalendarMonth = (initialDate: string) => { const [date, setDate] = useState(initialDate) const select = (param: string) => { setDate(param) } return { date, select, } }然后在组件中使用:
const Demo2 = () => { const { date, select } = useCalendarMonth('2025-02') return ( <div className="test-calendar-wrapper" style={{...}}> <Calendar viewMode="month" showTitle={false} value={date} defaultValue={date} startDate="2023-09-12" endDate="2027-10-19" onItemClick={select} /> </div> ) }src/packages/calendar/demos/h5/demo101.tsx (2)
5-5
: 移除未使用的变量变量
d
被声明但从未使用。-const d = new Date()
8-11
: 建议移除生产环境中的控制台日志
select
函数中的console.log
应在生产环境中移除。const select = (param: string) => { - console.log('select quarter', param) setDate(param) }
src/packages/calendar/demos/taro/demo101.tsx (2)
6-6
: 建议使用标准的日期格式建议使用标准的 ISO 日期格式而不是自定义的季度格式,以提高代码的可维护性和兼容性。
-const [date, setDate] = useState('2026-Q2') +const [date, setDate] = useState('2026-04-01')
8-11
: 优化回调函数的类型定义和实现需要改进以下几点:
- 添加具体的类型定义而不是使用
any
- 移除生产环境中的 console.log
-const select = (param: string) => { - console.log('select quarter', param) +const select = (selectedDate: string) => { setDate(param) }src/packages/calendar/demo.taro.tsx (1)
35-37
: 新功能的翻译键命名需要更加语义化。建议将翻译键命名改为更具语义化的格式,例如:
ees99933
->calendar_quarter_panel
e2s99933
->calendar_month_panel
e4s99933
->calendar_week_number
src/packages/calendar/calendar.tsx (1)
196-196
: 使用可选链操作符。为了更好的代码风格,建议使用可选链操作符:
-onDayClick && onDayClick(param) +onDayClick?.(param)🧰 Tools
🪛 Biome (1.9.4)
[error] 196-196: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/utils/date.ts (1)
361-368
: 优化季度计算逻辑。建议添加输入验证并使用更简洁的实现:
export const getQuarter = (month: number): number => { + if (!Number.isInteger(month)) { + throw new Error('月份必须为整数') + } if (month < 1 || month > 12) { throw new Error('月份必须在 1 到 12 之间') } - // 计算季度 - const quarter = Math.floor((month - 1) / 3) + 1 - return quarter + return Math.ceil(month / 3) }src/packages/calendar/calendarviewmodeitem.taro.tsx (1)
245-246
: 移除调试代码请移除生产环境中的 console.log 语句。
- console.log('monthts', months, panelDate) ... - console.log('quarters', quarters, panelDate)Also applies to: 251-252
src/packages/calendar/calendarviewmodeitem.tsx (1)
87-88
: 明确数组类型定义
monthsData
和monthsNum
的类型定义不够明确。- const [monthsData] = useState<any[]>([]) - const [monthsNum] = useState<number>(0) + const [monthsData] = useState<CalendarMonthInfo[]>([]) + const [monthsNum] = useState<number>(0)src/packages/calendaritem/calendaritem.taro.tsx (2)
512-516
: 优化滚动性能滚动事件处理函数可能会频繁触发,建议使用节流来优化性能。
+import { throttle } from '@/utils/throttle' -const monthsViewScroll = (e: any) => { +const monthsViewScroll = throttle((e: any) => { if (monthsData.length <= 1) return const scrollTop = (e.target as HTMLElement).scrollTop Taro.getEnv() === 'WEB' && setScrollTop(scrollTop) // 其余实现... -} +}, 16)
592-645
: 重构 switch 语句结构switch 语句过长且复杂,建议将各个 case 的逻辑抽取为独立函数。
+const handleMultipleSelection = (newDate: string, days: any[]) => { + if (Array.isArray(currentDate)) { + if (currentDate.length > 0) { + // multiple 类型的处理逻辑 + } + } +} +const handleRangeSelection = (newDate: string, days: any[]) => { + if (Array.isArray(currentDate)) { + // range 类型的处理逻辑 + } +} switch (type) { case 'multiple': - // 当前的 multiple 实现 + handleMultipleSelection(newDate, days) break case 'range': - // 当前的 range 实现 + handleRangeSelection(newDate, days) break // 其他 case... }🧰 Tools
🪛 Biome (1.9.4)
[error] 635-636: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
src/packages/calendar/doc.en-US.md (1)
109-109
: 建议完善英文文档说明英文版本的
viewMode
属性说明过于简单,建议补充以下内容:
- 各个视图模式(日、月、季度)的具体功能说明
- 不同模式下的使用场景
建议修改为:
-| viewMode `v2.7.9` | view mode | `day` \| `month` \| `quarter` | `day` | +| viewMode `v2.7.9` | Panel display mode, supports different calendar views: daily view (day), monthly overview (month), or quarterly view (quarter) | `day` \| `month` \| `quarter` | `day` |src/packages/calendar/calendar.scss (3)
67-69
: 建议优化收缩模式的内边距当前使用固定的
padding-left: 10%
可能在不同屏幕尺寸下表现不一致。建议使用更灵活的方式:
- padding-left: 10%; + padding-left: var(--nutui-calendar-shrink-padding, 10%);
119-133
: 周数显示样式结构清晰周数显示的样式结构合理,但建议:
- 考虑添加响应式布局支持
- 使用变量控制关键尺寸
建议添加以下变量:
+$calendar-weeknumber-width: 35% !default; +$calendar-weeknumber-font-size: 14px !default; &-weeknumber { - width: 35%; + width: $calendar-weeknumber-width; &-index { // ... - font-size: 14px; + font-size: $calendar-weeknumber-font-size; // ... } }
218-225
: 禁用状态样式优化禁用状态的样式处理合理,建议添加过渡效果提升交互体验。
&-disabled { + transition: background-color 0.3s, color 0.3s; background-color: $calendar-choose-disable-background-color; color: $calendar-disable-color !important;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
src/packages/calendar/calendar.scss
(4 hunks)src/packages/calendar/calendar.taro.tsx
(8 hunks)src/packages/calendar/calendar.tsx
(8 hunks)src/packages/calendar/calendarviewmode.scss
(1 hunks)src/packages/calendar/calendarviewmodeitem.taro.tsx
(1 hunks)src/packages/calendar/calendarviewmodeitem.tsx
(1 hunks)src/packages/calendar/demo.taro.tsx
(5 hunks)src/packages/calendar/demo.tsx
(5 hunks)src/packages/calendar/demos/h5/demo101.tsx
(1 hunks)src/packages/calendar/demos/h5/demo102.tsx
(1 hunks)src/packages/calendar/demos/h5/demo103.tsx
(1 hunks)src/packages/calendar/demos/h5/demo11.tsx
(1 hunks)src/packages/calendar/demos/taro/demo101.tsx
(1 hunks)src/packages/calendar/demos/taro/demo102.tsx
(1 hunks)src/packages/calendar/demos/taro/demo103.tsx
(1 hunks)src/packages/calendar/demos/taro/demo11.tsx
(1 hunks)src/packages/calendar/doc.en-US.md
(1 hunks)src/packages/calendar/doc.md
(1 hunks)src/packages/calendar/doc.taro.md
(1 hunks)src/packages/calendar/doc.zh-TW.md
(1 hunks)src/packages/calendar/types.ts
(1 hunks)src/packages/calendaritem/calendaritem.taro.tsx
(17 hunks)src/packages/calendaritem/calendaritem.tsx
(18 hunks)src/packages/configprovider/types.ts
(1 hunks)src/utils/date.ts
(4 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/packages/calendar/demos/h5/demo11.tsx
- src/packages/calendar/demos/taro/demo11.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/packages/calendar/calendarviewmode.scss
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendarviewmodeitem.tsx
[error] 114-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 251-252: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 266-267: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 367-370: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendarviewmodeitem.taro.tsx
[error] 114-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 251-252: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 266-267: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 367-370: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendaritem/calendaritem.taro.tsx
[error] 302-302: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 304-304: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 320-321: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 322-323: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 635-636: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 677-678: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 678-679: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendar.tsx
[error] 196-196: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 172-172: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendar.taro.tsx
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 172-172: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🪛 GitHub Check: lint
src/packages/calendar/calendarviewmodeitem.tsx
[warning] 263-263:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
src/packages/calendar/calendarviewmodeitem.taro.tsx
[warning] 263-263:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
🪛 GitHub Actions: CI
src/packages/calendaritem/calendaritem.tsx
[error] 409-409: TypeError: Cannot read properties of null (reading 'clientHeight')
🔇 Additional comments (10)
src/packages/configprovider/types.ts (1)
320-320
: 新增日历面板项宽度的 CSS 变量名称变量命名规范且清晰地表达了其用途,与现有的命名约定保持一致。
src/packages/calendar/types.ts (1)
6-14
: 类型定义清晰且结构合理!新增的
CalendarMonth
和CalendarQuarter
接口定义明确,与现有的类型定义保持一致的风格。src/packages/calendar/demos/taro/demo101.tsx (1)
23-31
: 验证日期范围的合理性请确认起始日期和结束日期的设置是否合理,当前跨度接近5年。
src/packages/calendar/demos/taro/demo103.tsx (1)
7-12
: 存在与 H5 版本相同的问题此代码段存在与 H5 版本相同的类型安全性和数据处理问题。
src/packages/calendar/demo.tsx (1)
118-123
: 代码结构清晰新增的演示代码组织结构清晰,功能分类合理。
src/packages/calendar/doc.md (1)
109-109
: 新属性文档完善且清晰!
viewMode
属性的文档说明完整,包含了版本号标记、类型定义和默认值。src/packages/calendar/doc.zh-TW.md (1)
109-109
: 繁體中文文檔翻譯準確!
viewMode
屬性的繁體中文文檔與其他語言版本保持一致,翻譯準確。src/packages/calendar/doc.taro.md (1)
109-109
: Taro 版本文档同步更新完成!
viewMode
属性在 Taro 版本中的文档说明完整,与其他版本保持一致。src/packages/calendar/calendar.scss (2)
1-2
: 样式文件拆分合理!将视图模式相关样式拆分到单独的文件中,有助于代码组织和维护。
229-231
: 收缩模式样式简洁明确使用
display: flex
实现收缩模式的布局合理。
value={date} | ||
defaultValue={date} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
建议添加日期格式验证
对于 value
和 defaultValue
的日期字符串,建议添加格式验证以确保符合 'YYYY-MM' 格式。
🌐 Web query:
如何在 React TypeScript 中验证日期字符串格式?
💡 Result:
在 React TypeScript 中验证日期字符串格式可通过以下方法实现,结合类型校验和运行时验证:
核心实现步骤
-
定义模板字面量类型
通过 TypeScript 的模板字面量类型限定日期格式:type YYYY = `${number}${number}${number}${number}` type MM = `0${1|2|3|4|5|6|7|8|9}` | `1${0|1|2}` type DD = `${0|1|2}${number}` | `3${0|1}` type RawDateString = `${YYYY}-${MM}-${DD}`;
-
创建品牌类型增强安全性
通过交叉类型添加品牌标识:type Brand<T, B> = T & { __brand: B }; type ValidDateString = Brand<RawDateString, 'ValidDate'>;
-
编写验证函数(含正则+实际日期校验)
const isValidDate = (str: string): str is ValidDateString => { // 格式验证 if (!/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/.test(str)) return false; // 实际日期验证 const date = new Date(str); return !isNaN(date.getTime()) && date.toISOString().slice(0,10) === str; };
完整示例组件
import { useState } from 'react';
const DateValidator = () => {
const [input, setInput] = useState('');
const [isValid, setIsValid] = useState(false);
const validateDate = (value: string) => {
setInput(value);
setIsValid(isValidDate(value));
};
return (
<div>
<input
type="text"
value={input}
onChange={(e) => validateDate(e.target.value)}
placeholder="YYYY-MM-DD"
/>
{isValid ?
<p style={{color: 'green'}}>✓ 有效日期</p> :
<p style={{color: 'red'}}>× 无效日期格式</p>}
</div>
);
};
关键优化点
-
双重验证机制
- 正则表达式
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[0-9]|3[1])$/
确保格式正确[1][7] new Date()
+ ISO 转换验证实际日期有效性[4][7]
- 正则表达式
-
类型谓词函数
使用str is ValidDateString
类型谓词,可在条件判断后自动收窄类型[1] -
错误边界处理
组件中包含明确的校验状态反馈,支持实时验证[8]
备选方案对比
方法 | 优点 | 缺点 |
---|---|---|
Zod库校验 | Schema声明式,支持复杂校验逻辑 | 需额外依赖安装 |
Moment.js | 内置日期有效性检查 | 包体积较大,已不推荐使用 |
Date原生对象 | 零依赖 | 时区处理需要额外注意 |
建议在需要国际化的项目中使用 date-fns + Zod 组合方案,常规项目采用本文的轻量级实现即可[5][8]。
Citations:
- 1: https://juejin.cn/post/7089616842221682724
- 2: https://blog.csdn.net/e295166319/article/details/87974243
- 3: https://blog.csdn.net/qq_37904209/article/details/104983810
- 4: https://developer.aliyun.com/article/1240764
- 5: https://developer.aliyun.com/article/1600323
- 6: https://www.cnblogs.com/momo798/p/17151903.html
- 7: https://wenku.csdn.net/answer/87dffdc97c85422387302cb87dfc2e22
- 8: https://my.oschina.net/emacs_8524933/blog/16583230
- 9: https://developer.aliyun.com/article/910463
- 10: https://juejin.cn/post/6844903649907310605
请为传入的日期字符串添加格式验证
在文件 src/packages/calendar/demos/h5/demo102.tsx
第 25-26 行,将 date
直接用于 value
和 defaultValue
时,并没有验证日期字符串是否符合预期的 'YYYY-MM'
格式。为防止数据格式不正确导致潜在意外,建议在将数据传递给组件之前添加日期格式验证。
建议的实现方式:
- 使用正则表达式进行轻量级的运行时格式校验,例如:
const isValidYearMonth = (str: string): boolean => /^\d{4}-(0[1-9]|1[0-2])$/.test(str);
- 如果需要更严格的校验,可以考虑结合 TypeScript 模板字面量类型及品牌类型,来在静态层面和运行时实现双重验证(参见 “如何在 React TypeScript 中验证日期字符串格式” 的实现方案)。
请根据项目实际需求调整并加入相应的校验代码,以确保传入组件的日期数据始终符合预期格式。
value={date} | ||
defaultValue={date} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
建议添加季度格式验证
对于 value
和 defaultValue
的季度字符串,建议添加格式验证以确保符合 'YYYY-Q[1-4]' 格式。
建议运行以下脚本来验证当前代码库中是否已有相关的验证函数:
🏁 Script executed:
#!/bin/bash
# 搜索是否存在日期格式验证相关的函数
rg -i "validate.*date|date.*format|quarter.*format" src/
Length of output: 2176
添加季度格式验证
在文件 src/packages/calendar/demos/h5/demo101.tsx
的第 26-27 行,目前对传入的 value
与 defaultValue
(季度字符串)没有进行格式验证。执行脚本后未发现现成的季度格式验证函数,因此建议新增一个专门用于验证季度字符串格式的函数,确保其符合 'YYYY-Q[1-4]'
的格式要求。
- 请在使用季度字符串之前调用此验证函数,避免格式错误。
- 若有类似验证需求的场景,可考虑统一调用该验证逻辑,以保障全局一致性。
const setChooseValue = (chooseData: any) => { | ||
const dateArr = chooseData.map((item: any) => { | ||
return item[3] | ||
}) | ||
setDate([...dateArr]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
改进类型安全性和数据处理逻辑
当前实现存在以下问题:
- 使用
any
类型降低了代码的类型安全性 - 直接访问数组索引
item[3]
容易导致运行时错误
建议如下改进:
-const setChooseValue = (chooseData: any) => {
- const dateArr = chooseData.map((item: any) => {
- return item[3]
- })
- setDate([...dateArr])
+interface DateItem {
+ date: string;
+ [key: string]: any;
+}
+const setChooseValue = (chooseData: DateItem[]) => {
+ const dateArr = chooseData.map(item => item.date)
+ setDate(dateArr)
+}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const setChooseValue = (chooseData: any) => { | |
const dateArr = chooseData.map((item: any) => { | |
return item[3] | |
}) | |
setDate([...dateArr]) | |
} | |
interface DateItem { | |
date: string; | |
[key: string]: any; | |
} | |
const setChooseValue = (chooseData: DateItem[]) => { | |
const dateArr = chooseData.map(item => item.date) | |
setDate(dateArr) | |
} |
</div> | ||
</div> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
防止潜在的空指针异常
在访问 DOM 元素之前应该先进行空值检查。
- return monthsPanel.current as HTMLDivElement
+ if (!monthsPanel.current) {
+ throw new Error('monthsPanel is not initialized')
+ }
+ return monthsPanel.current
同样的问题也存在于 getMonthsRef
方法。
Also applies to: 422-422
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (8)
src/packages/calendar/calendar.taro.tsx (1)
73-73
: 建议改进回调函数的默认实现空的回调函数实现可能会导致调试困难。建议添加开发环境下的警告信息。
- onItemClick: () => {}, + onItemClick: (param: string) => { + if (process.env.NODE_ENV !== 'production') { + console.warn('NutCalendar: onItemClick callback is not implemented'); + } + },src/packages/calendar/calendar.tsx (3)
149-198
: 优化组件属性传递逻辑当前代码在
CalendarViewModeItem
和CalendarItem
中存在大量重复的属性传递。建议提取共同属性以提高代码可维护性。建议重构如下:
+ const commonProps = { + ref: calendarRef, + style, + className, + type, + title: title || locale.calendaritem.title, + defaultValue, + startDate, + endDate, + showTitle, + scrollAnimation, + renderDay, + onPageChange: yearMonthChange, + } return ( <> {viewMode !== 'day' ? ( <CalendarViewModeItem - ref={calendarRef} - style={style} - className={className} - type={type} - title={title || locale.calendaritem.title} - defaultValue={defaultValue} - startDate={startDate} - endDate={endDate} - showTitle={showTitle} - scrollAnimation={scrollAnimation} - renderDay={renderDay} - onPageChange={yearMonthChange} + {...commonProps} viewMode={viewMode} value={value} onItemClick={onItemClick} > {children} </CalendarViewModeItem> ) : ( <CalendarItem - ref={calendarRef} - style={style} - className={className} - type={type} - title={title || locale.calendaritem.title} - defaultValue={defaultValue} - startDate={startDate} - endDate={endDate} - showTitle={showTitle} - scrollAnimation={scrollAnimation} - renderDay={renderDay} - onPageChange={yearMonthChange} + {...commonProps} autoBackfill={autoBackfill} showSubTitle={showSubTitle} showMonthNumber={showMonthNumber} // ... 其他特定属性 > {children} </CalendarItem> )} </> )🧰 Tools
🪛 Biome (1.9.4)
[error] 196-196: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 172-172: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
196-196
: 优化事件处理器的条件检查当前的条件检查可以使用可选链操作符来简化。
建议修改如下:
- onDayClick={(param) => onDayClick && onDayClick(param)} + onDayClick={(param) => onDayClick?.(param)}🧰 Tools
🪛 Biome (1.9.4)
[error] 196-196: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
206-206
: 建议添加条件判断的注释说明当前代码中
popup
组件仅在viewMode === 'day'
时显示,但缺少相关说明。建议添加注释解释这个设计决策的原因,以帮助其他开发者理解。建议添加如下注释:
+ // 仅在日视图模式下显示弹出层,月度和季度视图直接渲染在页面中 {popup && viewMode === 'day' ? (
src/utils/date.ts (4)
150-156
: 建议提取魔法数字为命名常量并添加输入验证。建议进行以下改进:
- 将 86400000 提取为模块级别的命名常量
- 添加对 time 参数的输入验证
+const ONE_DAY_IN_MS = 86400000 // 24 * 60 * 60 * 1000 + export const getWeekOfYear = (time: number) => { + if (isNaN(time) || !Number.isFinite(time)) { + throw new Error('Invalid timestamp') + } - const oneDayTime = 86400000 // 24 * 60 * 60 * 1000 const startOfYear = new Date(new Date(time).getFullYear(), 0, 1) // 举例1/1共计多少天 - const days = Math.round((time - startOfYear.valueOf()) / oneDayTime) + const days = Math.round((time - startOfYear.valueOf()) / ONE_DAY_IN_MS) return Math.ceil((days + (startOfYear.getDay() + 1)) / 7) }
257-286
: 建议重构月份操作函数以减少代码重复。
getPreMonths
和getMonths
函数有很多重复代码。建议:
- 将 type 参数定义为字面量联合类型
- 合并这两个函数为一个更通用的函数
+type MonthType = 'prev' | 'curr' | 'next' + -export const getPreMonths = (type: string, year: number, month: number) => { - const preMonth = +month - 1 - const months = Array.from(Array(preMonth), (v, k) => { - return { - year, - month: k + 1, - type, - } - }) - return months -} - -export const getMonths = ( - type: string, - year: number, - month: number, - endMonth: number = 12 -) => { - const nextMonth = endMonth - month + 1 - const months = Array.from(Array(nextMonth), (v, k) => { - return { - year, - month: k + month, - type, - } - }) - return months -} +export const getMonthRange = ( + type: MonthType, + year: number, + startMonth: number, + endMonth: number = 12 +) => { + if (startMonth < 1 || startMonth > 12 || endMonth < 1 || endMonth > 12) { + throw new Error('Month must be between 1 and 12') + } + const count = endMonth - startMonth + 1 + return Array.from(Array(count), (_, k) => ({ + year, + month: k + startMonth, + type, + })) +}
289-329
: 建议改进函数的可读性和可维护性。建议进行以下改进:
- 添加更详细的函数文档说明,包括参数和返回值的类型说明
- 使用更具描述性的变量名
- 添加对输入参数的验证
+/** + * 计算指定年份的所有周信息 + * @param year 年份 + * @param firstDayOfWeek 一周的第一天(0-6,0 表示周日) + * @returns 包含每周起止日期的数组 + */ export const getTotalWeeksInYear = (year: number, firstDayOfWeek?: number) => { + if (!Number.isInteger(year)) { + throw new Error('Year must be an integer') + } + if (firstDayOfWeek !== undefined && (firstDayOfWeek < 0 || firstDayOfWeek > 6)) { + throw new Error('First day of week must be between 0 and 6') + } const weeks = [] const firstDayOfYear = new Date(year, 0, 1) firstDayOfWeek = firstDayOfWeek || firstDayOfYear.getDay() - console.log('firstDayOfWeek', firstDayOfWeek, firstDayOfYear.getDay())
346-400
: 建议重构季度相关函数以提高代码复用。建议进行以下改进:
- 将季度验证逻辑提取为共享函数
- 合并相似的季度计算函数
- 添加类型定义以增强类型安全性
+type QuarterType = 'prev' | 'curr' | 'next' + +interface Quarter { + year: number + quarter: number + type: QuarterType +} + +const validateMonth = (month: number): void => { + if (month < 1 || month > 12) { + throw new Error('月份必须在 1 到 12 之间') + } +} + export const getQuarter = (month: number): number => { - if (month < 1 || month > 12) { - throw new Error('月份必须在 1 到 12 之间') - } + validateMonth(month) return Math.floor((month - 1) / 3) + 1 } + +export const getQuarterRange = ( + type: QuarterType, + year: number, + startMonth: number, + endMonth: number = 12, + step: number = 3 +): Quarter[] => { + validateMonth(startMonth) + validateMonth(endMonth) + const quarters: Quarter[] = [] + for (let month = startMonth; month <= endMonth; month += step) { + quarters.push({ + year, + quarter: getQuarter(month), + type, + }) + } + return quarters +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/packages/calendar/calendar.taro.tsx
(9 hunks)src/packages/calendar/calendar.tsx
(9 hunks)src/packages/calendaritem/calendaritem.taro.tsx
(6 hunks)src/packages/calendaritem/calendaritem.tsx
(9 hunks)src/utils/date.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/packages/calendaritem/calendaritem.taro.tsx
- src/packages/calendaritem/calendaritem.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendar.taro.tsx
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 172-172: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendar.tsx
[error] 196-196: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 172-172: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (4)
src/packages/calendar/calendar.taro.tsx (1)
206-206
: Popup 条件渲染的逻辑优化正确添加
viewMode === 'day'
的条件判断很合理,确保只在日视图模式下显示弹出层。src/packages/calendar/calendar.tsx (1)
153-153
: 避免使用 children prop 传递子组件Also applies to: 172-172
🧰 Tools
🪛 Biome (1.9.4)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/utils/date.ts (2)
294-294
: 移除调试代码。请移除 console.log 语句。
331-337
: 代码看起来不错!格式化函数实现简洁,使用了合适的字符串处理方法。
children={children} | ||
type={type} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要修正 children 属性的传递方式
直接通过 prop 传递 children 不符合 React 的最佳实践。
建议修改如下:
- <CalendarViewModeItem
- children={children}
+ <CalendarViewModeItem>
+ {children}
...
- />
+ </CalendarViewModeItem>
- <CalendarItem
- children={children}
+ <CalendarItem>
+ {children}
...
- />
+ </CalendarItem>
Also applies to: 172-173
🧰 Tools
🪛 Biome (1.9.4)
[error] 153-153: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/packages/calendar/__tests__/__snapshots__/calendar.spec.tsx.snap
is excluded by!**/*.snap
📒 Files selected for processing (1)
src/packages/calendar/calendarviewmodeitem.tsx
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendarviewmodeitem.tsx
[error] 114-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 251-252: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 266-267: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 367-370: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
case 'month': | ||
// eslint-disable-next-line no-case-declarations | ||
const months = getMonthsData() | ||
console.log('monthts', months, panelDate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
移除调试用的 console.log 语句
生产环境代码中不应该保留 console.log 语句。
- console.log('monthts', months, panelDate)
- console.log('quarters', quarters, panelDate)
Also applies to: 251-251
} | ||
|
||
const renderItem = (item: any, index: number) => { | ||
const units = { week: '周', month: '月', quarter: '季度' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
使用本地化文本
硬编码的中文文本应该使用本地化系统,以支持多语言。
- const units = { week: '周', month: '月', quarter: '季度' }
+ const units = {
+ week: locale.calendaritem.week,
+ month: locale.calendaritem.month,
+ quarter: locale.calendaritem.quarter
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const units = { week: '周', month: '月', quarter: '季度' } | |
const units = { | |
week: locale.calendaritem.week, | |
month: locale.calendaritem.month, | |
quarter: locale.calendaritem.quarter | |
} |
scrollAnimation: boolean | ||
renderDay: (date: CalendarDay) => string | JSX.Element | ||
onItemClick: (data: string) => void | ||
onPageChange: (data: any) => void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
改进 onPageChange 回调函数的类型定义
onPageChange
的参数类型定义为 any
过于宽松,建议定义具体的类型以提高代码的类型安全性。
- onPageChange: (data: any) => void
+ onPageChange: (data: [number, number, string]) => void
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
onPageChange: (data: any) => void | |
onPageChange: (data: [number, number, string]) => void |
const interval = setInterval(() => { | ||
flag++ | ||
if (monthsRef.current) { | ||
const offset = distance / 10 | ||
monthsRef.current.scrollTop += offset | ||
} | ||
if (flag >= 10) { | ||
clearInterval(interval) | ||
if (monthsRef.current) { | ||
monthsRef.current.scrollTop = currTop | ||
} | ||
} | ||
}, 40) | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
防止内存泄漏
滚动动画的 interval 在组件卸载时需要清理,否则可能导致内存泄漏。建议使用 useEffect 清理定时器。
+ const intervalRef = useRef<NodeJS.Timeout>()
const scrollToDate = (date: string) => {
// ...
- const interval = setInterval(() => {
+ intervalRef.current = setInterval(() => {
// ...
- clearInterval(interval)
+ clearInterval(intervalRef.current)
}
}, 40)
// ...
}
+ useEffect(() => {
+ return () => {
+ if (intervalRef.current) {
+ clearInterval(intervalRef.current)
+ }
+ }
+ }, [])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
♻️ Duplicate comments (1)
src/packages/calendar/calendar.tsx (1)
171-171
: 🛠️ Refactor suggestion避免使用 children prop。
根据 React 最佳实践,应该使用 JSX 元素传递子组件而不是通过 prop。
建议修改如下:
-<CalendarItem children={children} ... /> +<CalendarItem>{children}</CalendarItem>🧰 Tools
🪛 Biome (1.9.4)
[error] 171-171: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🧹 Nitpick comments (6)
src/packages/calendar/calendarviewmodeitem.taro.tsx (1)
119-119
: 使用可选链简化调用
目前通过onPageChange && onPageChange(...)
进行函数调用,可以改用可选链onPageChange?.(...)
,代码更简洁,并符合现代 TypeScript/JavaScript 语法风格。- onPageChange && onPageChange([year, month, `${year}-${month}`]) + onPageChange?.([year, month, `${year}-${month}`])🧰 Tools
🪛 Biome (1.9.4)
[error] 119-120: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendar.tsx (1)
195-195
: 使用可选链操作符。为了提高代码的健壮性,建议使用可选链操作符。
建议修改如下:
-onDayClick && onDayClick(param) +onDayClick?.(param)🧰 Tools
🪛 Biome (1.9.4)
[error] 195-195: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/__tests__/calendar.spec.tsx (1)
87-143
: 建议增加错误处理的测试用例。当前的测试用例只覆盖了正常流程,建议添加错误处理的测试用例,如无效的 viewMode 值、无效的日期范围等。
需要我帮你生成这些额外的测试用例吗?
src/utils/date.ts (2)
151-151
: 建议提取魔法数字为命名常量。代码中存在多个魔法数字,如
86400000
(一天的毫秒数)。建议将这些数字提取为命名常量以提高代码可读性。建议添加以下常量:
+const MS_PER_DAY = 86400000; // 24 * 60 * 60 * 1000 +const DAYS_PER_WEEK = 7; +const MONTHS_PER_QUARTER = 3;Also applies to: 289-326
🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 151-152: src/utils/date.ts#L151-L152
Added lines #L151 - L152 were not covered by tests
343-350
: 建议增强错误处理。
getQuarter
函数的错误处理可以更加完善,建议添加输入参数的类型检查。建议修改如下:
export const getQuarter = (month: number): number => { + if (!Number.isInteger(month)) { + throw new Error('月份必须是整数'); + } if (month < 1 || month > 12) { throw new Error('月份必须在 1 到 12 之间') } const quarter = Math.floor((month - 1) / 3) + 1 return quarter }🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 345-346: src/utils/date.ts#L345-L346
Added lines #L345 - L346 were not covered by testssrc/packages/calendar/calendarviewmodeitem.tsx (1)
111-162
: 增加单元测试覆盖率代码覆盖率报告显示多个关键功能缺少测试覆盖,包括:
- 日期滚动功能
- 点击处理逻辑
- 状态更新逻辑
建议添加相应的单元测试以确保代码质量。需要我帮您生成这些功能的单元测试代码吗?
Also applies to: 266-298, 301-325, 332-334, 339-347, 368-369, 440-440
🧰 Tools
🪛 Biome (1.9.4)
[error] 114-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 GitHub Check: codecov/patch
[warning] 111-116: src/packages/calendar/calendarviewmodeitem.tsx#L111-L116
Added lines #L111 - L116 were not covered by tests
[warning] 120-139: src/packages/calendar/calendarviewmodeitem.tsx#L120-L139
Added lines #L120 - L139 were not covered by tests
[warning] 142-143: src/packages/calendar/calendarviewmodeitem.tsx#L142-L143
Added lines #L142 - L143 were not covered by tests
[warning] 146-147: src/packages/calendar/calendarviewmodeitem.tsx#L146-L147
Added lines #L146 - L147 were not covered by tests
[warning] 150-151: src/packages/calendar/calendarviewmodeitem.tsx#L150-L151
Added lines #L150 - L151 were not covered by tests
[warning] 153-153: src/packages/calendar/calendarviewmodeitem.tsx#L153
Added line #L153 was not covered by tests
[warning] 155-162: src/packages/calendar/calendarviewmodeitem.tsx#L155-L162
Added lines #L155 - L162 were not covered by tests
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/packages/calendar/__tests__/__snapshots__/calendar.spec.tsx.snap
is excluded by!**/*.snap
📒 Files selected for processing (8)
src/packages/calendar/__tests__/calendar.spec.tsx
(1 hunks)src/packages/calendar/calendar.taro.tsx
(9 hunks)src/packages/calendar/calendar.tsx
(9 hunks)src/packages/calendar/calendarviewmodeitem.taro.tsx
(1 hunks)src/packages/calendar/calendarviewmodeitem.tsx
(1 hunks)src/packages/calendar/demo.taro.tsx
(5 hunks)src/packages/calendar/demo.tsx
(5 hunks)src/utils/date.ts
(2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendar/calendarviewmodeitem.taro.tsx
[error] 119-120: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 370-371: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/calendar/calendar.tsx
[error] 195-195: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 171-171: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendar.taro.tsx
[error] 171-171: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendarviewmodeitem.tsx
[error] 114-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 366-367: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 GitHub Check: build
src/packages/calendar/calendarviewmodeitem.taro.tsx
[failure] 401-401:
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
[failure] 405-405:
Type 'undefined' cannot be used as an index type.
[failure] 405-405:
Type 'undefined' cannot be used as an index type.
src/packages/calendar/calendarviewmodeitem.tsx
[failure] 397-397:
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
[failure] 401-401:
Type 'undefined' cannot be used as an index type.
[failure] 401-401:
Type 'undefined' cannot be used as an index type.
🪛 GitHub Check: lint
src/packages/calendar/calendarviewmodeitem.taro.tsx
[warning] 268-268:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
src/packages/calendar/calendarviewmodeitem.tsx
[warning] 262-262:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
🪛 GitHub Actions: CI
src/packages/calendar/calendarviewmodeitem.taro.tsx
[error] 401-401: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
🪛 GitHub Check: codecov/patch
src/utils/date.ts
[warning] 151-152: src/utils/date.ts#L151-L152
Added lines #L151 - L152 were not covered by tests
[warning] 154-156: src/utils/date.ts#L154-L156
Added lines #L154 - L156 were not covered by tests
[warning] 290-292: src/utils/date.ts#L290-L292
Added lines #L290 - L292 were not covered by tests
[warning] 294-296: src/utils/date.ts#L294-L296
Added lines #L294 - L296 were not covered by tests
[warning] 299-300: src/utils/date.ts#L299-L300
Added lines #L299 - L300 were not covered by tests
[warning] 303-307: src/utils/date.ts#L303-L307
Added lines #L303 - L307 were not covered by tests
[warning] 310-314: src/utils/date.ts#L310-L314
Added lines #L310 - L314 were not covered by tests
[warning] 316-319: src/utils/date.ts#L316-L319
Added lines #L316 - L319 were not covered by tests
[warning] 322-323: src/utils/date.ts#L322-L323
Added lines #L322 - L323 were not covered by tests
[warning] 325-326: src/utils/date.ts#L325-L326
Added lines #L325 - L326 were not covered by tests
[warning] 345-346: src/utils/date.ts#L345-L346
Added lines #L345 - L346 were not covered by tests
[warning] 376-378: src/utils/date.ts#L376-L378
Added lines #L376 - L378 were not covered by tests
src/packages/calendar/calendarviewmodeitem.tsx
[warning] 111-116: src/packages/calendar/calendarviewmodeitem.tsx#L111-L116
Added lines #L111 - L116 were not covered by tests
[warning] 120-139: src/packages/calendar/calendarviewmodeitem.tsx#L120-L139
Added lines #L120 - L139 were not covered by tests
[warning] 142-143: src/packages/calendar/calendarviewmodeitem.tsx#L142-L143
Added lines #L142 - L143 were not covered by tests
[warning] 146-147: src/packages/calendar/calendarviewmodeitem.tsx#L146-L147
Added lines #L146 - L147 were not covered by tests
[warning] 150-151: src/packages/calendar/calendarviewmodeitem.tsx#L150-L151
Added lines #L150 - L151 were not covered by tests
[warning] 153-153: src/packages/calendar/calendarviewmodeitem.tsx#L153
Added line #L153 was not covered by tests
[warning] 155-162: src/packages/calendar/calendarviewmodeitem.tsx#L155-L162
Added lines #L155 - L162 were not covered by tests
[warning] 255-255: src/packages/calendar/calendarviewmodeitem.tsx#L255
Added line #L255 was not covered by tests
[warning] 266-298: src/packages/calendar/calendarviewmodeitem.tsx#L266-L298
Added lines #L266 - L298 were not covered by tests
[warning] 301-325: src/packages/calendar/calendarviewmodeitem.tsx#L301-L325
Added lines #L301 - L325 were not covered by tests
[warning] 332-332: src/packages/calendar/calendarviewmodeitem.tsx#L332
Added line #L332 was not covered by tests
[warning] 334-334: src/packages/calendar/calendarviewmodeitem.tsx#L334
Added line #L334 was not covered by tests
[warning] 339-339: src/packages/calendar/calendarviewmodeitem.tsx#L339
Added line #L339 was not covered by tests
[warning] 341-347: src/packages/calendar/calendarviewmodeitem.tsx#L341-L347
Added lines #L341 - L347 were not covered by tests
[warning] 368-369: src/packages/calendar/calendarviewmodeitem.tsx#L368-L369
Added lines #L368 - L369 were not covered by tests
[warning] 440-440: src/packages/calendar/calendarviewmodeitem.tsx#L440
Added line #L440 was not covered by tests
🔇 Additional comments (14)
src/packages/calendar/calendarviewmodeitem.taro.tsx (1)
92-93
: 确认monthsData
状态的更新逻辑
monthsData
使用useState([])
初始化,但在代码中并未看到后续对该状态的赋值或更新,仅在滚动事件与其他函数中被引用。这样可能导致后续逻辑依赖空数据,需确认是否缺少更新逻辑或需移除不必要的引用。您可搜索项目中对
setMonthsData
的使用或查看该状态是否是设计遗留。如果需要帮助排查或补充更新逻辑,请告知。src/packages/calendar/demo.tsx (3)
15-17
: 新增 Demo 组件导入
这三行导入语句正确引入了 Demo 组件,从命名与结构上看都较为合理,并有助于在示例中呈现更多展示场景。
32-34
: 新增翻译键值对
成功在中文与英文环境中添加了“季度面板”、“月面板”、“展示周号”对应的翻译,有助于更好地展示多语言特性。
118-123
: 添加新案例标题与组件
通过在示例中增加显示季度面板、月面板、周号的对应章节与示例,便于用户直观理解viewMode
属性的功能,整体结构清晰。src/packages/calendar/demo.taro.tsx (3)
18-20
: 在 Taro 端导入新的 Demo
与 H5 端保持一致,在 Taro 环境下同样导入了三个新的学生案例(Demo101/102/103),对多端保持一致性很有必要。
35-37
: 新增翻译键值对
同样在 Taro 端的多语言配置中增加了“季度面板”、“月面板”、“展示周号”,与 H5 端对齐,便于跨端使用。
123-128
: 新增演示内容
新增了演示页面示例,展示季度模式、月模式与周号模式,能让用户更好地理解与使用这些新特性。src/packages/calendar/calendar.taro.tsx (2)
12-12
: 需要修正 viewMode 属性的类型定义。
viewMode
属性在接口中被定义为必需属性,但在defaultProps
中提供了默认值。这种不一致可能会导致 TypeScript 类型检查错误。Also applies to: 47-47
171-171
: 避免使用 children prop。根据 React 最佳实践,应该使用 JSX 元素传递子组件而不是通过 prop。
🧰 Tools
🪛 Biome (1.9.4)
[error] 171-171: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/packages/calendar/calendarviewmodeitem.tsx (5)
38-38
: 改进 onPageChange 回调函数的类型定义
onPageChange
的参数类型定义为any
过于宽松,建议使用更具体的类型以提高代码的类型安全性。
80-83
: 避免硬编码年份初始状态中硬编码了年份 2025,这可能导致在未来出现问题。建议使用当前年份作为初始值。
244-244
: 移除调试用的 console.log 语句生产环境代码中不应该保留 console.log 语句。
Also applies to: 251-251
279-292
: 防止内存泄漏滚动动画的 interval 在组件卸载时需要清理,否则可能导致内存泄漏。
389-389
: 使用本地化文本硬编码的中文文本应该使用本地化系统,以支持多语言。
key={index} | ||
> | ||
<div className={`${classPrefix}-item-${item.type}`}> | ||
{renderDay ? renderDay(item) : `${item[viewMode]}${units[viewMode]}`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复索引类型错误并保证 viewMode
不为 undefined
在使用 \
${item[viewMode]}`和
units[viewMode]时,若
viewMode为
undefined,或
item[viewMode]未定义,会导致类型报错与运行时错误。确保
viewMode` 存在并取值合法,否则需要提供降级逻辑或默认值。
可参考以下示例进行修复,使用空值合并运算符保证类型安全:
- {renderDay ? renderDay(item) : `${item[viewMode]}${units[viewMode]}`}
+ {
+ renderDay
+ ? renderDay(item)
+ : `${item[viewMode ?? 'month']}${units[viewMode ?? 'month']}`
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
{renderDay ? renderDay(item) : `${item[viewMode]}${units[viewMode]}`} | |
{ | |
renderDay | |
? renderDay(item) | |
: `${item[viewMode ?? 'month']}${units[viewMode ?? 'month']}` | |
} |
🧰 Tools
🪛 GitHub Check: build
[failure] 405-405:
Type 'undefined' cannot be used as an index type.
[failure] 405-405:
Type 'undefined' cannot be used as an index type.
const [panelDate, setPanelDate] = useState({ | ||
months: [ | ||
{ | ||
year: new Date().getFullYear, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复 getFullYear
调用的错误
此处少了函数调用的圆括号,new Date().getFullYear
仅是对函数的引用而非其返回值,导致获取到的是函数而不是年份数值,应该使用 new Date().getFullYear()
。一旦忽略该调用,会在后续逻辑中导致无效的年份数据。
请使用以下代码完成修复:
- year: new Date().getFullYear,
+ year: new Date().getFullYear(),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
year: new Date().getFullYear, | |
year: new Date().getFullYear(), |
|
||
useEffect(() => { | ||
initData() | ||
}, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
为 useEffect
增加 initData
依赖或移除依赖数组
此处的 useEffect
中调用了 initData
却未将其加入依赖数组,若 initData
在外层发生变化,将不会触发此副作用,可能导致渲染不同步或数据不一致。建议在依赖数组中添加 initData
或者在确保 initData
永不变化时移除全部依赖。
若需验证是否在其他地方动态修改了 initData
,可使用以下脚本:
🏁 Script executed:
#!/bin/bash
# 在整个仓库中搜索所有对 initData 的引用,查看是否发生了重赋值或变更
rg 'initData'
Length of output: 1186
修复建议:调整 useEffect 的依赖数组
在文件 src/packages/calendar/calendarviewmodeitem.taro.tsx
中,当前 useEffect 的依赖数组为空(即 }, [])
),但却在其内部调用了本地定义的 initData
函数。根据全仓库的搜索结果可见,initData
在多个文件中均以本地函数形式定义,并非外部传入或动态变更。不过,由于在组件中每次渲染时都会重新创建这个函数,直接忽略其变化可能导致副作用不符合预期。
建议:
- 若希望 useEffect 正确响应 initData 更新:请将
initData
添加到依赖数组,同时建议用useCallback
包裹initData
以确保其函数引用稳定,从而避免频繁触发副作用。 - 若 initData 本身不会依赖外部变量且只需执行一次:可在 useEffect 内部直接定义该逻辑,或明确注释说明 initData 永不变化,从而移除整个依赖数组。
请参考上述建议,确保副作用能与数据变化保持同步。
🧰 Tools
🪛 GitHub Check: lint
[warning] 268-268:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
import { getDateString } from '@/utils/date' | ||
import { useConfig } from '@/packages/configprovider' | ||
import type { CalendarDay, CalendarType, CalendarRef } from './types' | ||
import { ComponentDefaults } from '@/utils/typings' | ||
|
||
export interface CalendarProps { | ||
type?: CalendarType | ||
viewMode?: 'day' | 'month' | 'quarter' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要修正 viewMode 属性的类型定义。
viewMode
属性在接口中被定义为必需属性,但在 defaultProps
中提供了默认值。这种不一致可能会导致 TypeScript 类型检查错误。
建议修改接口定义,将属性标记为可选:
- viewMode?: 'day' | 'month' | 'quarter'
+ viewMode?: 'day' | 'month' | 'quarter'
Also applies to: 47-47
test('viewmode prop', async () => { | ||
const onItemClick = vi.fn() | ||
const { container } = render( | ||
<Calendar | ||
viewMode="quarter" | ||
defaultValue="2025-Q1" | ||
startDate="2025-01-01" | ||
endDate="2025-3-31" | ||
onItemClick={onItemClick} | ||
/> | ||
) | ||
const viewArea = container.querySelector('.viewArea') as HTMLElement | ||
expect(viewArea.innerHTML).toMatchSnapshot() | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
测试用例命名需要更具描述性。
当前有多个测试用例使用相同的名称 'viewmode prop',这会降低测试的可维护性和可读性。建议为每个测试用例使用更具描述性的名称,以反映其具体测试内容。
建议修改如下:
-test('viewmode prop', async () => {
+test('should render calendar in quarter view with onItemClick', async () => {
-test('viewmode prop', async () => {
+test('should render calendar in quarter view without onItemClick', async () => {
-test('viewmode prop', async () => {
+test('should render calendar in month view with onItemClick', async () => {
-test('viewmode prop', async () => {
+test('should render calendar in month view with extended date range', async () => {
Also applies to: 102-113, 115-128, 130-143
export const getWeekOfYear = (time: number) => { | ||
const oneDayTime = 86400000 // 24 * 60 * 60 * 1000 | ||
const startOfYear = new Date(new Date(time).getFullYear(), 0, 1) | ||
// 举例1/1共计多少天 | ||
const days = Math.round((time - startOfYear.valueOf()) / oneDayTime) | ||
return Math.ceil((days + (startOfYear.getDay() + 1)) / 7) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要增加测试覆盖率。
新增的日期工具函数缺少测试覆盖,特别是 getWeekOfYear
和 getTotalWeeksInYear
这些复杂的计算函数。建议添加单元测试以确保函数在各种场景下的正确性。
需要我帮你生成这些函数的单元测试用例吗?测试用例应该包括:
- 常规输入
- 边界条件(年初、年末)
- 闰年情况
- 无效输入
Also applies to: 289-326
🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 151-152: src/utils/date.ts#L151-L152
Added lines #L151 - L152 were not covered by tests
[warning] 154-156: src/utils/date.ts#L154-L156
Added lines #L154 - L156 were not covered by tests
item.type, | ||
getClasses(item) | ||
)} | ||
onClick={() => handleItemClick(viewMode, item)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复类型错误
构建失败显示存在类型不匹配的问题:
viewMode
可能为 undefined- 使用 undefined 作为索引类型
- onClick={() => handleItemClick(viewMode, item)}
+ onClick={() => handleItemClick(viewMode || 'month', item)}
- {renderDay ? renderDay(item) : `${item[viewMode]}${units[viewMode]}`}
+ {renderDay ? renderDay(item) : `${item[viewMode || 'month']}${units[viewMode || 'month']}`}
Also applies to: 401-401
🧰 Tools
🪛 GitHub Check: build
[failure] 397-397:
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
useEffect(() => { | ||
initData() | ||
}, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修复 useEffect 的依赖项警告
useEffect 的依赖数组中缺少 initData
,这可能导致组件在某些情况下不会正确更新。
useEffect(() => {
initData()
- }, [])
+ }, [initData])
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
useEffect(() => { | |
initData() | |
}, []) | |
useEffect(() => { | |
initData() | |
}, [initData]) |
🧰 Tools
🪛 GitHub Check: lint
[warning] 262-262:
React Hook useEffect has a missing dependency: 'initData'. Either include it or remove the dependency array
const [innerValue, setInnerValue] = usePropsValue({ | ||
value, | ||
defaultValue, | ||
finalValue: [], | ||
onChange: (val) => {}, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
完善 usePropsValue 的类型定义和回调实现
onChange
回调函数目前是空实现,建议完善其功能。同时,finalValue
的类型应该与 value
和 defaultValue
保持一致。
const [innerValue, setInnerValue] = usePropsValue({
value,
defaultValue,
- finalValue: [],
- onChange: (val) => {},
+ finalValue: '' as CalendarValue,
+ onChange: (val) => {
+ props.onChange?.(val)
+ },
})
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const [innerValue, setInnerValue] = usePropsValue({ | |
value, | |
defaultValue, | |
finalValue: [], | |
onChange: (val) => {}, | |
}) | |
const [innerValue, setInnerValue] = usePropsValue({ | |
value, | |
defaultValue, | |
finalValue: '' as CalendarValue, | |
onChange: (val) => { | |
props.onChange?.(val) | |
}, | |
}) |
🤔 这个变动的性质是?
🔗 相关 Issue
💡 需求背景和解决方案
☑️ 请求合并前的自查清单
Summary by CodeRabbit
新功能
样式
文档