Skip to content

refactor: calendar #2983

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 5 commits into from
Feb 13, 2025
Merged

Conversation

xiaoyatong
Copy link
Collaborator

@xiaoyatong xiaoyatong commented Feb 11, 2025

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • fork仓库代码是否为最新避免文件冲突
  • Files changed 没有 package.json lock 等无关文件

Summary by CodeRabbit

  • 样式
    • 优化了日历组件中禁用日期的显示效果,使视觉状态更统一、直观。
  • 重构
    • 调整了日期处理逻辑,提高了组件的响应速度和稳定性。
    • 精简了部分日历配置选项,简化了日历设置流程。
    • 通过直接导入工具函数,增强了代码的模块化和可读性。
  • 测试
    • 增强了日历组件的测试覆盖率,验证了各种属性和用户交互的正确性。

Copy link

coderabbitai bot commented Feb 11, 2025

Walkthrough

此次变更对日历组件及相关工具函数进行了重构和样式调整。具体修改包括:

  • 在样式文件中调整了禁用状态的类结构;
  • 在多个组件内将对日期的处理由使用统一的 Utils 对象替换为直接引入具体方法;
  • 移除了 Demo 中的部分配置属性;
  • 将工具函数模块化,直接导出各个独立函数。
    所有修改均未改变原有的业务逻辑,仅调整了实现和调用方式。

Changes

文件 变更摘要
src/packages/calendar/calendar.scss 修改禁用状态样式:移除 .nut-calendar-day-choose-disabled,新增 .nut-calendar-day-choose .nut-calendar-day-disabled,并隐藏当前选中日信息。
src/packages/calendar/calendar.taro.tsx
src/packages/calendar/calendar.tsx
替换 Utils.getDay(0/365) 为直接导入的 getDateString(0/365),更新相应的 import 语句。
src/packages/calendar/demos/taro/demo1.tsx 移除 Calendar 组件的 showTitlecloseIcon 属性。
src/packages/calendar/utils.tsx
src/packages/calendarcard/utils.ts
替换对 Utils 对象的调用为直接导入特定工具函数(如 isEqualdate2StrgetNumTwoBitgetMonthPreDaygetMonthDays)。
src/packages/calendaritem/calendaritem.taro.tsx
src/packages/calendaritem/calendaritem.tsx
更换工具函数调用为直接导入具体方法;重命名 chooseDayhandleDayClick;简化 getMonthData 参数。
src/utils/date.ts Utils 对象中的各方法重构为独立导出函数(如 isLeapYeargetWhatDaygetMonthPreDaygetMonthDaysgetNumTwoBitdate2StrgetDateStringcompareDateisEqualgetMonthWeekgetYearWeekgetWeekDateformatResultDate)。

Sequence Diagram(s)

sequenceDiagram
    participant 用户 as 用户
    participant 日历 as CalendarItem
    participant 工具 as 工具函数

    用户->>日历: 点击日期
    日历->>工具: 调用 getDateString / compareDate / getNumTwoBit 等
    工具-->>日历: 返回日期数据
    日历->>日历: 更新状态并重新渲染
Loading

Suggested reviewers

  • oasis-cloud
  • Alex-huxiyang

Poem

嘎吱嘎吱跳小兔,
代码林中轻步走;
样式调整如花开,
工具函数精心筹;
改变虽小心欢笑,
程序世界梦成舟。
🐰✨


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the 2.x Target branch 2.x label Feb 11, 2025
Copy link

codecov bot commented Feb 11, 2025

Codecov Report

Attention: Patch coverage is 86.63102% with 50 lines in your changes missing coverage. Please review.

Project coverage is 85.56%. Comparing base (343116f) to head (a20d16e).
Report is 2 commits behind head on next.

Files with missing lines Patch % Lines
src/utils/date.ts 79.71% 28 Missing ⚠️
src/packages/calendaritem/calendaritem.tsx 90.09% 22 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #2983      +/-   ##
==========================================
+ Coverage   84.19%   85.56%   +1.36%     
==========================================
  Files         267      267              
  Lines       18099    18000      -99     
  Branches     2665     2726      +61     
==========================================
+ Hits        15238    15401     +163     
+ Misses       2856     2596     -260     
+ Partials        5        3       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (8)
src/packages/calendaritem/calendaritem.taro.tsx (5)

194-205: 优化 getMonthData 的月份遍历逻辑
该方法在循环生成月份时调用了 getPreMonthDates, getDaysStatus 并动态计算 cssHeight,请确认极端场景(例如跨年、多年跨度)能正确生成完整列表,以及考虑性能开销。

Also applies to: 210-211, 218-228


370-402: 在 renderCurrentDate 中处理多类型逻辑时注意可读性
switch 分支较多,各 case 均会调用 handleDayClick。若后续需求增加,建议进一步拆分或封装,便于维护与测试。


421-423: scrollTop 赋值后立刻 setScrollTop
目前逻辑简单明了,如需在不同生命周期插入插桩逻辑,可酌情封装滚动管理函数。


496-497: 平滑滚动后立即强制对齐
这两段逻辑在平滑滚动后将滚动条位置校正到准确位置,如对滚动体验有新需求,应考虑进一步的滚动缓冲方案。

Also applies to: 502-503


547-572: getClasses 内部判断分支较多
分支逻辑包含多种状态合并判断,可考虑在分支体内拆分出更多辅助函数,便于今后维护。

src/utils/date.ts (1)

49-70: 建议加强类型安全性

getMonthDays 函数的实现可以更加类型安全:

  • 参数类型使用 string 过于宽松
  • 数组访问使用 as any 不够安全

建议如下改进:

-export const getMonthDays = (year: string, month: string): number => {
+export const getMonthDays = (year: string, month: string): number => {
+  const monthNum = parseInt(month.replace(/^0/, ''))
+  if (isNaN(monthNum) || monthNum < 1 || monthNum > 12) {
+    throw new Error('Invalid month')
+  }
   if (/^0/.test(month)) {
     month = month.split('')[1]
   }
-  return (
-    [
-      0,
-      31,
-      isLeapYear(Number(year)) ? 29 : 28,
-      31,
-      30,
-      31,
-      30,
-      31,
-      31,
-      30,
-      31,
-      30,
-      31,
-    ] as number[]
-  )[month as any]
+  const monthDays = [
+    0,
+    31,
+    isLeapYear(Number(year)) ? 29 : 28,
+    31,
+    30,
+    31,
+    30,
+    31,
+    31,
+    30,
+    31,
+    30,
+    31,
+  ]
+  return monthDays[monthNum]
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 51-52: src/utils/date.ts#L51-L52
Added lines #L51 - L52 were not covered by tests

src/packages/calendaritem/calendaritem.tsx (2)

201-242: 建议拆分复杂的日期处理逻辑

getMonthData 函数较为复杂,建议拆分为更小的函数以提高可维护性:

  • 日期计算逻辑
  • 滚动位置计算逻辑
  • 月份数据组装逻辑

需要我帮你重构这部分代码吗?


607-683: 建议优化日期选择逻辑

chooseDay 函数包含了多个日期选择模式的处理逻辑,建议:

  • 将不同模式的处理逻辑拆分为独立函数
  • 使用策略模式处理不同的选择类型
  • 添加详细的单元测试

需要我帮你重构这部分代码吗?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 649-649: src/packages/calendaritem/calendaritem.tsx#L649
Added line #L649 was not covered by tests


[warning] 657-658: src/packages/calendaritem/calendaritem.tsx#L657-L658
Added lines #L657 - L658 were not covered by tests


[warning] 661-661: src/packages/calendaritem/calendaritem.tsx#L661
Added line #L661 was not covered by tests


[warning] 668-669: src/packages/calendaritem/calendaritem.tsx#L668-L669
Added lines #L668 - L669 were not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9c6822 and d4a51a0.

📒 Files selected for processing (9)
  • src/packages/calendar/calendar.scss (1 hunks)
  • src/packages/calendar/calendar.taro.tsx (2 hunks)
  • src/packages/calendar/calendar.tsx (2 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 (16 hunks)
  • src/utils/date.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • src/packages/calendar/demos/taro/demo1.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/packages/calendaritem/calendaritem.tsx

[warning] 294-294: src/packages/calendaritem/calendaritem.tsx#L294
Added line #L294 was not covered by tests


[warning] 297-297: src/packages/calendaritem/calendaritem.tsx#L297
Added line #L297 was not covered by tests


[warning] 312-312: src/packages/calendaritem/calendaritem.tsx#L312
Added line #L312 was not covered by tests


[warning] 314-314: src/packages/calendaritem/calendaritem.tsx#L314
Added line #L314 was not covered by tests


[warning] 328-328: src/packages/calendaritem/calendaritem.tsx#L328
Added line #L328 was not covered by tests


[warning] 330-330: src/packages/calendaritem/calendaritem.tsx#L330
Added line #L330 was not covered by tests


[warning] 333-333: src/packages/calendaritem/calendaritem.tsx#L333
Added line #L333 was not covered by tests


[warning] 491-491: src/packages/calendaritem/calendaritem.tsx#L491
Added line #L491 was not covered by tests


[warning] 493-493: src/packages/calendaritem/calendaritem.tsx#L493
Added line #L493 was not covered by tests


[warning] 585-586: src/packages/calendaritem/calendaritem.tsx#L585-L586
Added lines #L585 - L586 were not covered by tests


[warning] 649-649: src/packages/calendaritem/calendaritem.tsx#L649
Added line #L649 was not covered by tests


[warning] 657-658: src/packages/calendaritem/calendaritem.tsx#L657-L658
Added lines #L657 - L658 were not covered by tests


[warning] 661-661: src/packages/calendaritem/calendaritem.tsx#L661
Added line #L661 was not covered by tests


[warning] 668-669: src/packages/calendaritem/calendaritem.tsx#L668-L669
Added lines #L668 - L669 were not covered by tests

src/utils/date.ts

[warning] 51-52: src/utils/date.ts#L51-L52
Added lines #L51 - L52 were not covered by tests


[warning] 132-146: src/utils/date.ts#L132-L146
Added lines #L132 - L146 were not covered by tests


[warning] 148-159: src/utils/date.ts#L148-L159
Added lines #L148 - L159 were not covered by tests


[warning] 161-169: src/utils/date.ts#L161-L169
Added lines #L161 - L169 were not covered by tests


[warning] 172-172: src/utils/date.ts#L172
Added line #L172 was not covered by tests


[warning] 174-174: src/utils/date.ts#L174
Added line #L174 was not covered by tests


[warning] 176-181: src/utils/date.ts#L176-L181
Added lines #L176 - L181 were not covered by tests


[warning] 183-183: src/utils/date.ts#L183
Added line #L183 was not covered by tests


[warning] 185-185: src/utils/date.ts#L185
Added line #L185 was not covered by tests


[warning] 187-190: src/utils/date.ts#L187-L190
Added lines #L187 - L190 were not covered by tests


[warning] 193-197: src/utils/date.ts#L193-L197
Added lines #L193 - L197 were not covered by tests

src/packages/calendar/utils.tsx

[warning] 12-12: src/packages/calendar/utils.tsx#L12
Added line #L12 was not covered by tests


[warning] 28-28: src/packages/calendar/utils.tsx#L28
Added line #L28 was not covered by tests


[warning] 32-32: src/packages/calendar/utils.tsx#L32
Added line #L32 was not covered by tests


[warning] 37-37: src/packages/calendar/utils.tsx#L37
Added line #L37 was not covered by tests

🪛 Biome (1.9.4)
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] 582-583: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[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)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (24)
src/packages/calendaritem/calendaritem.taro.tsx (14)

8-18: 直接导入各日期工具函数,提升可读性与可维护性
这些改动通过精细化引入 getDay, compareDate 等工具函数,减少对通用 Utils 对象的依赖,有利于 tree-shaking 并让职责更清晰。


81-82: 注意默认日期范围是否符合业务需求
当前将 startDate 默认设为 getDay(0)endDate 默认设为 getDay(365),可能在特定业务场景下并不合理;需要确认是否涵盖了所需的日期跨度。


116-116: 解构 value 属性
从 props 中解构 value 并无逻辑问题,但需要注意其与其它默认值逻辑 (defaultValue) 的兼容性。


140-141: 统一前缀常量便于后续样式维护
使用 classPrefixdayPrefix 提升可维护性,这种形式在日后统一维护样式类名时更灵活。


158-159: 确认回退逻辑是否适用
回退到 getDay(0)getDay(365) 的逻辑可能在极端场景下不满足需求,建议验证是否需要增加更灵活的处理方式。


404-406: getter 函数命名清晰,此处实现简单
getMonthsPanel 直接返回 monthsPanel.current,代码可读性尚可。


408-410: 保持函数式访问 monthsRef,便于后续扩展
getMonthsRef 同理,返回 ref 变量,设计合理。


429-436: getMonthNum 边界处理
当计算结果为非正数时,以 1 作为默认值能避免异常,但可能导致逻辑与上层预期不符,建议进一步确认需求或加异常提示。


438-452: initData 逻辑集中
initData 中一次性调用获取月份数据、默认数据、索引与渲染,流程清晰;但逻辑量大,如后期扩展可能需考虑拆分为更细函数。


473-475: compareDate 判断区间逻辑需仔细验证
if (compareDate(date, propStartDate)) date = propStartDate 以及 else if (!compareDate(date, propEndDate)) date = propEndDate 的对比条件较易混淆,请确保与业务预期一致。


509-509: monthsViewScroll 函数的计算逻辑较复杂
需仔细测试当月数较多、首次/末次滚动时的定位是否准确;也可考虑通过观察者的方式实时更新 current

Also applies to: 519-519, 521-521, 522-522


539-545: isDisable 函数根据 day.type 与 compareDate 判断
如果存在更多禁用逻辑(如法定节假日、特殊日期等),需在此统一扩展;也要注意性能影响。


667-667: classPrefix 赋值保持一致风格
此处与上文命名风格相同,易于维护,推荐继续保持。


674-674: headerClasses 使用 classNames
结合 popupshowTitle 等条件,简洁表达多重 class 状态,写法可读性较好。

🧰 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/utils.tsx (2)

1-1: 从 Utils 转为直接导入函数
此变更提升了模块化与可维护性,减少冗余依赖。


12-12: 缺少单测覆盖
新增/修改的行 (12, 28, 32, 37) 未被测试覆盖,建议添加相关测试用例,确保边界情况(空数组、日期字符串格式不一致等)得到验证。

Also applies to: 28-28, 32-32, 37-37

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 12-12: src/packages/calendar/utils.tsx#L12
Added line #L12 was not covered by tests

src/packages/calendarcard/utils.ts (2)

1-1: 直接导入 getMonthPreDay 与 getMonthDays
避免从 Utils 拖入不必要的函数,能更好地控制包体积与维护责任。


32-32: 确保 off-by-one 情况得到正确处理
getPrevMonthDaysgetCurrentMonthDays 等函数中,需防范首日或最后一天越界的情况,建议在测试中验证当月天数不满 30 天、跨月份边缘等情形。

Also applies to: 38-38, 54-54

src/packages/calendar/calendar.tsx (1)

4-4: 代码重构改进了模块化!

Utils 对象的方法改为直接导入具体函数是一个很好的改进:

  • 提高了代码的可维护性
  • 支持了更好的 tree-shaking
  • 使依赖关系更加明确

Also applies to: 47-48

src/packages/calendar/calendar.taro.tsx (1)

4-4: 保持了与 React 版本的一致性!

Taro 版本的改动与 React 版本保持一致,这很好:

  • 统一了代码风格
  • 保持了两个版本的同步性
  • 便于后续维护

Also applies to: 47-48

src/utils/date.ts (2)

1-7: 代码模块化改进值得肯定!

将工具函数从 Utils 对象拆分为独立导出的函数是很好的改进:

  • 支持更好的 tree-shaking
  • 提高了代码的可维护性
  • 使依赖关系更加清晰

294-294: 需要补充测试用例

代码覆盖率报告显示多个新增的日期处理逻辑缺少测试覆盖:

  • 日期比较逻辑
  • 周处理逻辑
  • 格式化逻辑

建议添加相应的单元测试用例。需要我帮你生成测试代码吗?

Also applies to: 297-297, 312-312, 314-314, 328-328, 330-330, 333-333, 491-491, 493-493, 585-586, 649-649, 657-658, 661-661, 668-669

src/packages/calendaritem/calendaritem.tsx (1)

7-18: 导入优化提高了代码清晰度!

直接导入所需的工具函数而不是使用 Utils 对象:

  • 使依赖关系更加明确
  • 便于代码分析和优化
  • 支持更好的 tree-shaking
src/packages/calendar/calendar.scss (1)

197-204: 代码结构优化得当!

将禁用状态的样式移至 choose 类下作为子类是个很好的改进,这样的组织结构更加清晰和符合逻辑。

建议验证在所有状态下样式表现是否一致,特别是:

  • 日期选择时的禁用状态
  • 范围选择时的禁用状态
  • RTL模式下的禁用状态
✅ Verification successful

🏁 Script executed:

#!/bin/bash
# 检查样式变更是否影响其他组件
rg -l "nut-calendar.*disabled" 

Length of output: 243


代码修改结构和样式一致性均符合预期!

通过搜索结果我们发现:

  • 测试文件(如 src/packages/calendar/__tests__/__snapshots__/calendar.spec.tsx.snapsrc/packages/calendarcard/__tests__/calendarcard.spec.tsx)以及 demo 文件中均检测到相关的 disabled 样式引用,说明该样式被各处使用,并且经过调整后命名结构更清晰;
  • 虽然目前没有发现明显问题,但依然建议开发者在不同场景下(如日期选择、范围选择和 RTL 模式)进行手动验证,确保视觉表现与预期一致。

Copy link

@coderabbitai coderabbitai bot left a 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/calendaritem/calendaritem.taro.tsx (1)

589-642: 🛠️ Refactor suggestion

优化 handleDayClick 中的 switch 语句结构

switch 语句中的变量声明需要使用代码块来避免作用域泄漏问题。同时建议对重复的日期处理逻辑进行抽象。

建议按如下方式修改:

 switch (type) {
-  case 'week':
-    // eslint-disable-next-line no-case-declarations
-    const weekArr = getWeekDate(y, m, `${day.day}`, firstDayOfWeek)
+  case 'week': {
+    const weekArr = getWeekDate(y, m, `${day.day}`, firstDayOfWeek)
     if (compareDate(weekArr[0], propStartDate)) {
       weekArr[0] = propStartDate
     }
     if (compareDate(propEndDate, weekArr[1])) {
       weekArr[1] = propEndDate
     }
     ;(currentDate as string[]).splice(0, currentDate.length, ...weekArr)
     state.currDateArray = [
       formatResultDate(weekArr[0]),
       formatResultDate(weekArr[1]),
     ]
     break
+  }
🧰 Tools
🪛 Biome (1.9.4)

[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)

🧹 Nitpick comments (3)
src/packages/calendaritem/calendaritem.tsx (3)

414-425: 建议优化月份计算逻辑

当前的月份计算方法可以更简洁。

建议重构为:

-  const getMonthNum = () => {
-    let monthNum = Number(endDates[1]) - Number(startDates[1])
-    const yearNum = Number(endDates[0]) - Number(startDates[0])
-    if (yearNum > 0) {
-      monthNum += 12 * yearNum
-    }
-    if (monthNum <= 0) {
-      monthNum = 1
-    }
-    setMonthsNum(monthNum)
-    return monthNum
-  }
+  const getMonthNum = () => {
+    const monthNum = Math.max(
+      1,
+      (Number(endDates[0]) - Number(startDates[0])) * 12 +
+      Number(endDates[1]) - Number(startDates[1])
+    )
+    setMonthsNum(monthNum)
+    return monthNum
+  }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 418-419: src/packages/calendaritem/calendaritem.tsx#L418-L419
Added lines #L418 - L419 were not covered by tests


[warning] 421-422: src/packages/calendaritem/calendaritem.tsx#L421-L422
Added lines #L421 - L422 were not covered by tests


528-534: 建议优化禁用日期判断逻辑

isDisable 函数的实现可以更简洁。

建议重构为:

-  const isDisable = (day: CalendarDay, month: CalendarMonthInfo) => {
-    if (day.type !== 'active') return true
-    const dateStr = getCurrDate(day, month)
-    if (compareDate(dateStr, propStartDate)) return true
-    if (compareDate(propEndDate, dateStr)) return true
-    return false
-  }
+  const isDisable = (day: CalendarDay, month: CalendarMonthInfo) => {
+    if (day.type !== 'active') return true
+    const dateStr = getCurrDate(day, month)
+    return compareDate(dateStr, propStartDate) || compareDate(propEndDate, dateStr)
+  }

711-774: 建议将渲染逻辑拆分为更小的组件

renderItem 和 renderPanel 函数包含了大量的渲染逻辑,建议将它们拆分为独立的组件以提高可维护性。

建议:

  1. 创建 CalendarDay 组件处理日期项渲染
  2. 创建 CalendarMonth 组件处理月份面板渲染
  3. 将相关的样式和逻辑移至这些组件中

需要我提供具体的组件拆分示例吗?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d4a51a0 and 635f37b.

📒 Files selected for processing (2)
  • src/packages/calendaritem/calendaritem.taro.tsx (15 hunks)
  • src/packages/calendaritem/calendaritem.tsx (15 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
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: codecov/patch
src/packages/calendaritem/calendaritem.tsx

[warning] 268-269: src/packages/calendaritem/calendaritem.tsx#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 271-271: src/packages/calendaritem/calendaritem.tsx#L271
Added line #L271 was not covered by tests


[warning] 273-273: src/packages/calendaritem/calendaritem.tsx#L273
Added line #L273 was not covered by tests


[warning] 282-284: src/packages/calendaritem/calendaritem.tsx#L282-L284
Added lines #L282 - L284 were not covered by tests


[warning] 286-287: src/packages/calendaritem/calendaritem.tsx#L286-L287
Added lines #L286 - L287 were not covered by tests


[warning] 293-293: src/packages/calendaritem/calendaritem.tsx#L293
Added line #L293 was not covered by tests


[warning] 298-299: src/packages/calendaritem/calendaritem.tsx#L298-L299
Added lines #L298 - L299 were not covered by tests


[warning] 307-307: src/packages/calendaritem/calendaritem.tsx#L307
Added line #L307 was not covered by tests


[warning] 309-309: src/packages/calendaritem/calendaritem.tsx#L309
Added line #L309 was not covered by tests


[warning] 311-313: src/packages/calendaritem/calendaritem.tsx#L311-L313
Added lines #L311 - L313 were not covered by tests


[warning] 316-316: src/packages/calendaritem/calendaritem.tsx#L316
Added line #L316 was not covered by tests


[warning] 367-371: src/packages/calendaritem/calendaritem.tsx#L367-L371
Added lines #L367 - L371 were not covered by tests


[warning] 373-373: src/packages/calendaritem/calendaritem.tsx#L373
Added line #L373 was not covered by tests


[warning] 375-379: src/packages/calendaritem/calendaritem.tsx#L375-L379
Added lines #L375 - L379 were not covered by tests


[warning] 381-383: src/packages/calendaritem/calendaritem.tsx#L381-L383
Added lines #L381 - L383 were not covered by tests


[warning] 385-385: src/packages/calendaritem/calendaritem.tsx#L385
Added line #L385 was not covered by tests


[warning] 392-393: src/packages/calendaritem/calendaritem.tsx#L392-L393
Added lines #L392 - L393 were not covered by tests


[warning] 418-419: src/packages/calendaritem/calendaritem.tsx#L418-L419
Added lines #L418 - L419 were not covered by tests


[warning] 421-422: src/packages/calendaritem/calendaritem.tsx#L421-L422
Added lines #L421 - L422 were not covered by tests


[warning] 463-463: src/packages/calendaritem/calendaritem.tsx#L463
Added line #L463 was not covered by tests


[warning] 465-465: src/packages/calendaritem/calendaritem.tsx#L465
Added line #L465 was not covered by tests


[warning] 508-508: src/packages/calendaritem/calendaritem.tsx#L508
Added line #L508 was not covered by tests


[warning] 510-511: src/packages/calendaritem/calendaritem.tsx#L510-L511
Added lines #L510 - L511 were not covered by tests


[warning] 541-544: src/packages/calendaritem/calendaritem.tsx#L541-L544
Added lines #L541 - L544 were not covered by tests


[warning] 546-549: src/packages/calendaritem/calendaritem.tsx#L546-L549
Added lines #L546 - L549 were not covered by tests


[warning] 551-553: src/packages/calendaritem/calendaritem.tsx#L551-L553
Added lines #L551 - L553 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: lint
🔇 Additional comments (5)
src/packages/calendaritem/calendaritem.tsx (3)

7-18: 代码重构改进了模块化!

将工具函数从 Utils 对象改为直接导入的方式提高了代码的可维护性和tree-shaking能力。


267-278: 需要增加单元测试覆盖率

这段处理单选模式的逻辑缺少测试覆盖。建议添加以下场景的测试用例:

  • 空日期的处理
  • 日期范围验证
  • 边界条件处理

我可以帮您生成相关的单元测试代码。需要我为您创建测试用例吗?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 268-269: src/packages/calendaritem/calendaritem.tsx#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 271-271: src/packages/calendaritem/calendaritem.tsx#L271
Added line #L271 was not covered by tests


[warning] 273-273: src/packages/calendaritem/calendaritem.tsx#L273
Added line #L273 was not covered by tests


282-289: 多选模式的日期验证逻辑需要测试覆盖

range、multiple 和 week 模式的日期验证逻辑都缺少测试覆盖。这些是关键的业务逻辑,需要完整的测试用例确保正确性。

我可以帮您编写这些模式的测试用例,包括:

  • 范围选择的边界测试
  • 多选的重复选择测试
  • 周选择的跨月份测试
    需要我提供具体实现吗?

Also applies to: 293-324

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 282-284: src/packages/calendaritem/calendaritem.tsx#L282-L284
Added lines #L282 - L284 were not covered by tests


[warning] 286-287: src/packages/calendaritem/calendaritem.tsx#L286-L287
Added lines #L286 - L287 were not covered by tests

src/packages/calendaritem/calendaritem.taro.tsx (2)

1-19: 优化了工具函数的导入方式!

将 Utils 对象导入改为直接导入具体函数的方式有助于实现更好的 tree-shaking,可以减小最终的包体积。


725-788: 代码结构优化得当!

将 renderItem 和 renderPanel 提取为独立函数提高了代码的可读性和可维护性,使组件结构更加清晰。

let date = new Date()
const diff = i * (1000 * 60 * 60 * 24)
date = new Date(date.getTime() + diff)
return date2Str(date)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在 getDay 方法中理解 date2Str 方法,容易让人认为是把时间转为: Wed Feb 12 2025 10:05:58 GMT+0800 (中国标准时间) 。实际上 date2Str 方法是将年月日进行 join 操作。

@oasis-cloud oasis-cloud requested a review from irisSong February 12, 2025 02:33
@github-actions github-actions bot added the action:review This PR needs more reviews (less than 2 approvals) label Feb 13, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (9)
src/packages/calendar/demos/taro/demo10.tsx (1)

59-59: 建议统一日期格式化方法的使用

在同一行代码中混合使用了 date2StrgetDateString 两个不同的日期格式化方法,建议统一使用 getDateString 来保持一致性。

-    const date = [date2Str(new Date()), getDateString(6)]
+    const date = [getDateString(0), getDateString(6)]
src/utils/date.ts (3)

90-99: 建议完善 getDateString 函数的文档注释

函数的 JSDoc 注释中参数描述不够清晰,建议补充更详细的说明。

 /**
  * 返回日期格式字符串
- * @param {Number} 0返回今天的日期、1返回明天的日期,2返回后天得日期,依次类推
+ * @param {number} offset - 日期偏移量:0表示今天,1表示明天,2表示后天,以此类推
  * @return {string} '2014-12-31'
+ * @example
+ * getDateString(0) // 返回今天的日期,如:'2025-02-14'
+ * getDateString(1) // 返回明天的日期,如:'2025-02-15'
  */

115-119: 建议简化 isEqual 函数的实现

当前实现中重复调用了 replace 方法,可以简化代码提高可读性。

 export const isEqual = (date1: string, date2: string): boolean => {
-  const startTime = new Date((date1 || '').replace(/-/g, '/')).getTime()
-  const endTime = new Date(date2.replace(/-/g, '/')).getTime()
-  return startTime === endTime
+  return date1 === date2
 }

179-185: 建议优化 formatResultDate 函数的返回类型

函数返回一个混合类型的数组,建议使用 TypeScript 接口定义返回类型以提高代码的类型安全性。

+interface FormattedDate {
+  year: string
+  month: string
+  day: string
+  fullDate: string
+  dayOfWeek: string
+}
+
-export const formatResultDate = (date: string) => {
+export const formatResultDate = (date: string): FormattedDate => {
   const [year, month, day] = [...date.split('-')]
   const formatterDay = getNumTwoBit(Number(day))
   const formatterDate = `${year}-${month}-${day}`
   const dayOfWeek = getWhatDay(Number(year), Number(month), Number(day))
-  return [year, month, formatterDay, formatterDate, dayOfWeek]
+  return {
+    year,
+    month,
+    day: formatterDay,
+    fullDate: formatterDate,
+    dayOfWeek
+  }
 }
src/packages/calendaritem/calendaritem.tsx (3)

528-534: 建议优化 isDisable 函数的实现

当前实现包含多个条件判断,可以通过合并条件来简化代码。

 const isDisable = (day: CalendarDay, month: CalendarMonthInfo) => {
-  if (day.type !== 'active') return true
   const dateStr = getCurrDate(day, month)
-  if (compareDate(dateStr, propStartDate)) return true
-  if (compareDate(propEndDate, dateStr)) return true
-  return false
+  return day.type !== 'active' || 
+         compareDate(dateStr, propStartDate) || 
+         compareDate(propEndDate, dateStr)
 }

711-760: 建议将 renderItem 函数拆分为更小的组件

当前的 renderItem 函数过于复杂,包含了大量的条件渲染逻辑。建议将其拆分为更小的、可复用的组件以提高可维护性。

建议创建以下子组件:

  • DayContent:渲染日期内容
  • DayTopInfo:渲染顶部信息
  • DayBottomInfo:渲染底部信息
  • DayRangeInfo:渲染范围选择信息

762-773: 建议优化 renderPanel 的性能

当前实现在每次渲染时都会重新创建月份面板。建议使用 React.memo 来优化性能。

+const MonthPanel = React.memo(({ month, key }: { month: any; key: number }) => {
+  return (
+    <div className={`${classPrefix}-month`} key={key}>
+      <div className={`${classPrefix}-month-title`}>{month.title}</div>
+      <div className={`${classPrefix}-days`}>
+        {month.monthData.map((day: CalendarDay, i: number) =>
+          renderItem(month, day, i)
+        )}
+      </div>
+    </div>
+  )
+})
+
 const renderPanel = (month: any, key: number) => {
-  return (
-    <div className={`${classPrefix}-month`} key={key}>
-      <div className={`${classPrefix}-month-title`}>{month.title}</div>
-      <div className={`${classPrefix}-days`}>
-        {month.monthData.map((day: CalendarDay, i: number) =>
-          renderItem(month, day, i)
-        )}
-      </div>
-    </div>
-  )
+  return <MonthPanel month={month} key={key} />
 }
src/packages/calendaritem/calendaritem.taro.tsx (2)

179-184: 建议优化状态管理的类型安全性

当前的状态管理可以通过以下方式改进:

  1. usePropsValue 的泛型参数添加更具体的类型约束
  2. 考虑使用 useMemo 缓存计算结果以提高性能
-  const [currentDate, setCurrentDate] = usePropsValue<CalendarValue>({
+  const [currentDate, setCurrentDate] = usePropsValue<CalendarValue[]>({
     value,
     defaultValue: resetDefaultValue(),
-    finalValue: [],
+    finalValue: [] as CalendarValue[],
     onChange: (val) => {},
   })

731-780: 建议优化渲染性能和错误处理

渲染逻辑可以通过以下方式改进:

  1. 使用 React.memo 优化子组件重渲染
  2. 添加错误边界处理组件异常
  3. 考虑将 renderItem 抽取为独立组件

建议将 renderItem 重构为独立组件:

const CalendarDayItem = React.memo(({ 
  day, 
  month, 
  onDayClick 
}: CalendarDayItemProps) => {
  const startTip = isStartTip(day, month)
  const endTip = isEndTip(day, month)
  // ... 渲染逻辑
})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 635f37b and c8478c1.

📒 Files selected for processing (7)
  • src/packages/calendar/calendar.taro.tsx (2 hunks)
  • src/packages/calendar/calendar.tsx (2 hunks)
  • src/packages/calendar/demos/h5/demo10.tsx (2 hunks)
  • src/packages/calendar/demos/taro/demo10.tsx (2 hunks)
  • src/packages/calendaritem/calendaritem.taro.tsx (15 hunks)
  • src/packages/calendaritem/calendaritem.tsx (15 hunks)
  • src/utils/date.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/packages/calendar/calendar.tsx
  • src/packages/calendar/calendar.taro.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/calendaritem/calendaritem.taro.tsx

[error] 680-681: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 681-682: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: codecov/patch
src/packages/calendaritem/calendaritem.tsx

[warning] 268-269: src/packages/calendaritem/calendaritem.tsx#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 271-271: src/packages/calendaritem/calendaritem.tsx#L271
Added line #L271 was not covered by tests


[warning] 273-273: src/packages/calendaritem/calendaritem.tsx#L273
Added line #L273 was not covered by tests


[warning] 282-284: src/packages/calendaritem/calendaritem.tsx#L282-L284
Added lines #L282 - L284 were not covered by tests


[warning] 286-287: src/packages/calendaritem/calendaritem.tsx#L286-L287
Added lines #L286 - L287 were not covered by tests


[warning] 293-293: src/packages/calendaritem/calendaritem.tsx#L293
Added line #L293 was not covered by tests


[warning] 298-299: src/packages/calendaritem/calendaritem.tsx#L298-L299
Added lines #L298 - L299 were not covered by tests


[warning] 307-307: src/packages/calendaritem/calendaritem.tsx#L307
Added line #L307 was not covered by tests


[warning] 309-309: src/packages/calendaritem/calendaritem.tsx#L309
Added line #L309 was not covered by tests


[warning] 311-313: src/packages/calendaritem/calendaritem.tsx#L311-L313
Added lines #L311 - L313 were not covered by tests


[warning] 316-316: src/packages/calendaritem/calendaritem.tsx#L316
Added line #L316 was not covered by tests


[warning] 367-371: src/packages/calendaritem/calendaritem.tsx#L367-L371
Added lines #L367 - L371 were not covered by tests


[warning] 373-373: src/packages/calendaritem/calendaritem.tsx#L373
Added line #L373 was not covered by tests


[warning] 375-379: src/packages/calendaritem/calendaritem.tsx#L375-L379
Added lines #L375 - L379 were not covered by tests


[warning] 381-383: src/packages/calendaritem/calendaritem.tsx#L381-L383
Added lines #L381 - L383 were not covered by tests


[warning] 385-385: src/packages/calendaritem/calendaritem.tsx#L385
Added line #L385 was not covered by tests


[warning] 392-393: src/packages/calendaritem/calendaritem.tsx#L392-L393
Added lines #L392 - L393 were not covered by tests


[warning] 418-419: src/packages/calendaritem/calendaritem.tsx#L418-L419
Added lines #L418 - L419 were not covered by tests


[warning] 421-422: src/packages/calendaritem/calendaritem.tsx#L421-L422
Added lines #L421 - L422 were not covered by tests


[warning] 463-463: src/packages/calendaritem/calendaritem.tsx#L463
Added line #L463 was not covered by tests


[warning] 465-465: src/packages/calendaritem/calendaritem.tsx#L465
Added line #L465 was not covered by tests


[warning] 508-508: src/packages/calendaritem/calendaritem.tsx#L508
Added line #L508 was not covered by tests


[warning] 510-511: src/packages/calendaritem/calendaritem.tsx#L510-L511
Added lines #L510 - L511 were not covered by tests


[warning] 541-544: src/packages/calendaritem/calendaritem.tsx#L541-L544
Added lines #L541 - L544 were not covered by tests


[warning] 546-549: src/packages/calendaritem/calendaritem.tsx#L546-L549
Added lines #L546 - L549 were not covered by tests


[warning] 551-553: src/packages/calendaritem/calendaritem.tsx#L551-L553
Added lines #L551 - L553 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (2)
src/packages/calendar/demos/h5/demo10.tsx (1)

56-56: 建议统一日期格式化方法的使用

在同一行代码中混合使用了 date2StrgetDateString 两个不同的日期格式化方法,建议统一使用 getDateString 来保持一致性。

-    const date = [date2Str(new Date()), getDateString(6)]
+    const date = [getDateString(0), getDateString(6)]
src/packages/calendaritem/calendaritem.taro.tsx (1)

7-19: 导入优化值得称赞!

将 Utils 对象替换为具体函数的直接导入是一个很好的改进:

  • 有助于实现更好的 tree-shaking
  • 提高了代码的可读性和可维护性

Comment on lines +268 to +313
return defaultData
}
if (compareDate(currentDate, propStartDate)) {
defaultData = [...splitDate(propStartDate)]
} else if (!compareDate(currentDate, propEndDate)) {
defaultData = [...splitDate(propEndDate)]
} else {
defaultData = [...splitDate(currentDate)]
}
return defaultData
}

if (Array.isArray(currentDate) && currentDate.length) {
// 日期转化为数组,限制初始日期。判断时间范围
if (type === 'range') {
if (compareDate(currentDate[0], propStartDate)) {
currentDate[0] = propStartDate
}
if (propEndDate && Utils.compareDate(propEndDate, currentDate[1])) {
currentDate.splice(1, 1, propEndDate)
if (compareDate(propEndDate, currentDate[1])) {
currentDate[1] = propEndDate
}
defaultData = [
...splitDate(currentDate[0]),
...splitDate(currentDate[1]),
]
}
} else if (type === 'multiple' && Array.isArray(currentDate)) {
if (currentDate.length > 0) {
} else if (type === 'multiple') {
const defaultArr = [] as string[]
const obj: Record<string, unknown> = {}
currentDate.forEach((item: string) => {
if (
propStartDate &&
!Utils.compareDate(item, propStartDate) &&
propEndDate &&
!Utils.compareDate(propEndDate, item)
!compareDate(item, propStartDate) &&
!compareDate(propEndDate, item)
) {
if (!Object.hasOwnProperty.call(obj, item)) {
defaultArr.push(item)
obj[item] = item
}
}
})
currentDate.splice(0) && currentDate.push(...defaultArr)
currentDate.splice(0, currentDate.length, ...defaultArr)
defaultData = [...splitDate(defaultArr[0])]
}
} else if (type === 'week' && Array.isArray(currentDate)) {
if (currentDate.length > 0) {
} else if (type === 'week') {
const [y, m, d] = splitDate(currentDate[0])
const weekArr = Utils.getWeekDate(y, m, d, firstDayOfWeek)
currentDate.splice(0) && currentDate.push(...weekArr)
if (propStartDate && Utils.compareDate(currentDate[0], propStartDate)) {
const weekArr = getWeekDate(y, m, d, firstDayOfWeek)
currentDate.splice(0, currentDate.length, ...weekArr)
if (compareDate(currentDate[0], propStartDate)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

需要增加测试覆盖率

根据静态分析工具的提示,这段代码缺少测试覆盖。建议添加单元测试以确保日期选择逻辑的正确性,特别是对于不同类型(single、range、multiple、week)的日期选择场景。


🏁 Script executed:

#!/bin/bash
# 查找现有的测试文件
fd -t f -e test.tsx -e spec.tsx calendaritem

Length of output: 46


测试覆盖率不足 —— 请增加单元测试

目前在文件 src/packages/calendaritem/calendaritem.tsx 中针对日期选择的逻辑(包括 single、range、multiple、week 四种类型)未发现相应的单元测试。建议补充以下内容以覆盖不同场景:

  • 为单个日期选择(single)场景增加测试案例,确认默认返回逻辑正确。
  • 为区间选择(range)情况编写测试,确保起始和结束日期符合预期边界值。
  • 为多选(multiple)场景增加测试,验证去重逻辑及数组处理结果。
  • 为星期选择(week)场景编写测试,以验证使用 getWeekDate 生成正确日期数组的逻辑。

请补充相应的测试文件并确保 CI 流程中测试覆盖率符合要求。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 268-269: src/packages/calendaritem/calendaritem.tsx#L268-L269
Added lines #L268 - L269 were not covered by tests


[warning] 271-271: src/packages/calendaritem/calendaritem.tsx#L271
Added line #L271 was not covered by tests


[warning] 273-273: src/packages/calendaritem/calendaritem.tsx#L273
Added line #L273 was not covered by tests


[warning] 282-284: src/packages/calendaritem/calendaritem.tsx#L282-L284
Added lines #L282 - L284 were not covered by tests


[warning] 286-287: src/packages/calendaritem/calendaritem.tsx#L286-L287
Added lines #L286 - L287 were not covered by tests


[warning] 293-293: src/packages/calendaritem/calendaritem.tsx#L293
Added line #L293 was not covered by tests


[warning] 298-299: src/packages/calendaritem/calendaritem.tsx#L298-L299
Added lines #L298 - L299 were not covered by tests


[warning] 307-307: src/packages/calendaritem/calendaritem.tsx#L307
Added line #L307 was not covered by tests


[warning] 309-309: src/packages/calendaritem/calendaritem.tsx#L309
Added line #L309 was not covered by tests


[warning] 311-313: src/packages/calendaritem/calendaritem.tsx#L311-L313
Added lines #L311 - L313 were not covered by tests

Comment on lines +579 to 656
currentDate.splice(hasIndex, 1)
state.currDateArray.splice(hasIndex, 1)
} else {
currentDate.push(newDate)
state.currDateArray.push([...days])
}
} else {
currentDate.push(newDate)
state.currDateArray = [[...days]]
}
})
if (isFirst) {
state.currDateArray.push([...days])
} else if (hasIndex !== '') {
;(currentDate as string[]).splice(hasIndex, 1)
state.currDateArray.splice(hasIndex, 1)
} else {
;(currentDate as string[]).push(days[3])
state.currDateArray.push([...days])
}
} else {
;(currentDate as string[]).push(days[3])
state.currDateArray = [[...days]]
break
}
} else if (type === 'range') {
const curDataLength = Object.values(currentDate).length
if (curDataLength === 2 || curDataLength === 0) {
Array.isArray(currentDate) &&
currentDate.splice(0) &&
currentDate.push(days[3])
state.currDateArray = [[...days]]
} else if (Utils.compareDate(currentDate[0], days[3])) {
Array.isArray(currentDate) && currentDate.push(days[3])
state.currDateArray = [...state.currDateArray, [...days]]
} else {
Array.isArray(currentDate) && currentDate.unshift(days[3])
state.currDateArray = [[...days], ...state.currDateArray]
case 'range': {
if (Array.isArray(currentDate)) {
if (currentDate.length === 2 || currentDate.length === 0) {
currentDate.splice(0, currentDate.length, newDate)
state.currDateArray = [[...days]]
} else if (compareDate(currentDate[0], newDate)) {
currentDate.push(newDate)
state.currDateArray = [...state.currDateArray, [...days]]
} else {
currentDate.unshift(newDate)
state.currDateArray = [[...days], ...state.currDateArray]
}
}
break
}
} else if (type === 'week') {
const weekArr = Utils.getWeekDate(y, m, `${day.day}`, firstDayOfWeek)
if (propStartDate && Utils.compareDate(weekArr[0], propStartDate)) {
weekArr.splice(0, 1, propStartDate)
case 'week': {
const weekArr = getWeekDate(y, m, `${day.day}`, firstDayOfWeek)
if (compareDate(weekArr[0], propStartDate)) {
weekArr[0] = propStartDate
}
if (compareDate(propEndDate, weekArr[1])) {
weekArr[1] = propEndDate
}
;(currentDate as string[]).splice(0, currentDate.length, ...weekArr)
state.currDateArray = [
formatResultDate(weekArr[0]),
formatResultDate(weekArr[1]),
]
break
}
if (propEndDate && Utils.compareDate(propEndDate, weekArr[1])) {
weekArr.splice(1, 1, propEndDate)
default: {
setCurrentDate(newDate)
state.currDateArray = [...days]
break
}
Array.isArray(currentDate) &&
currentDate.splice(0) &&
currentDate.push(...weekArr)
state.currDateArray = [
Utils.formatResultDate(weekArr[0]),
Utils.formatResultDate(weekArr[1]),
]
} else {
setCurrentDate(days[3])
state.currDateArray = [...days]
}

if (!isFirst) {
onDayClick && onDayClick(state.currDateArray)
if (autoBackfill || !popup) {
confirm()
}
}

setMonthsData(monthsData.slice())
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议重构 handleDayClick 函数以提高可维护性

当前函数过于复杂,建议:

  1. 将不同类型的日期处理逻辑拆分为独立的函数
  2. 添加错误处理和边界条件检查
  3. 使用 early return 模式优化代码结构

建议将每种类型的处理逻辑抽取为单独的函数,例如:

const handleMultipleSelect = (newDate: string, days: string[]) => {
  // 处理 multiple 类型的选择逻辑
}

const handleRangeSelect = (newDate: string, days: string[]) => {
  // 处理 range 类型的选择逻辑
}

const handleWeekSelect = (newDate: string, days: string[]) => {
  // 处理 week 类型的选择逻辑
}

@oasis-cloud oasis-cloud requested review from Miles-hxy and removed request for irisSong February 13, 2025 09:59
@github-actions github-actions bot added action:merge This PR has received sufficient approvals (2+ approvals) and is ready to merge and removed action:review This PR needs more reviews (less than 2 approvals) labels Feb 13, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
src/packages/calendar/demos/h5/demo4.tsx (2)

16-20: 建议加强类型安全性和日期验证

当前实现存在以下可以改进的地方:

  1. chooseData 参数使用 any 类型,缺乏类型安全性
  2. 没有对日期格式进行验证
  3. 缺少错误处理机制

建议进行如下改进:

-  const setChooseValue = (chooseData: any) => {
+  interface DateData {
+    [index: number]: string[];
+  }
+  
+  const setChooseValue = (chooseData: DateData) => {
+    try {
+      if (!Array.isArray(chooseData) || chooseData.length < 2) {
+        throw new Error('无效的日期数据格式');
+      }
       const dateArr = [...[chooseData[0][3], chooseData[1][3]]]
+      // 验证日期格式
+      if (!dateArr.every(date => /^\d{4}-\d{2}-\d{2}$/.test(date))) {
+        throw new Error('无效的日期格式');
+      }
       setDate([...dateArr])
-      console.log('choosevalue', chooseData, [...dateArr])
+    } catch (error) {
+      console.error('日期选择错误:', error);
+      // 可以添加用户提示
+    }
   }

32-33: 建议优化日期范围配置

当前日期范围是硬编码的,这可能会限制组件的复用性。建议将日期范围作为可配置项,以提高组件的灵活性。

建议通过以下方式改进:

  1. 将日期范围提取为组件属性或环境配置:
+  const DEFAULT_START_DATE = '2025-01-01'
+  const DEFAULT_END_DATE = '2026-09-10'
+
   const Demo4 = () => {
+    const [startDate] = useState(DEFAULT_START_DATE)
+    const [endDate] = useState(DEFAULT_END_DATE)
     // ...
     <Calendar
       visible={isVisible}
       defaultValue={date}
       type="week"
-      startDate="2025-01-01"
-      endDate="2026-09-10"
+      startDate={startDate}
+      endDate={endDate}
       // ...
     />
  1. 或者根据当前日期动态计算合理的日期范围:
const getDefaultDateRange = () => {
  const today = new Date();
  const startDate = new Date(today.getFullYear(), 0, 1);  // 当年开始
  const endDate = new Date(today.getFullYear() + 1, 11, 31);  // 下年结束
  return {
    startDate: startDate.toISOString().split('T')[0],
    endDate: endDate.toISOString().split('T')[0],
  };
};
src/packages/calendar/__tests__/calendar.spec.tsx (3)

7-53: 建议增强单选模式的测试覆盖率

测试用例已经验证了基本功能,但建议添加以下场景的测试:

  1. 日期选择后的值是否正确
  2. 边界日期(startDate/endDate)的选择限制
  3. 自定义文本的渲染验证

建议添加如下测试代码:

 test('single prop', async () => {
   const onConfirm = vi.fn()
+  const onSelect = vi.fn()
   const { container, rerender } = render(
     <Calendar
       visible
       title="test"
       defaultValue="2022-03-18"
       startDate="2022-01-01"
       endDate="2022-12-31"
       startText="start"
       endText="end"
       confirmText="confirm"
       onConfirm={onConfirm}
+      onSelect={onSelect}
     />
   )
+  // 验证自定义文本
+  const startTextEl = container.querySelector('.start-text')
+  expect(startTextEl.textContent).toBe('start')
+
+  // 验证日期选择
+  const dateEl = container.querySelectorAll('.nut-calendar-day')[5]
+  fireEvent.click(dateEl)
+  expect(onSelect).toHaveBeenCalledWith('2022-01-05')

100-127: 建议增强自定义渲染插槽的测试

当前测试用例使用了快照测试和简单的 DOM 检查。建议添加更具体的断言来验证自定义渲染的内容:

  1. 验证顶部自定义按钮的点击事件
  2. 验证自定义日期渲染的具体内容
  3. 验证日期上下方自定义内容的条件渲染

建议添加如下测试代码:

 test('should render slot correctly', async () => {
+  const onHeaderButtonClick = vi.fn()
   const renderHeaderButtons = () => (
-    <div className="d_div"> 最近七天</div>
+    <div className="d_div" onClick={onHeaderButtonClick}> 最近七天</div>
   )
   // ... 其他代码保持不变
   
   const topSlot = container.querySelector('.nut-calendar-header-buttons') as HTMLElement
   const viewArea = container.querySelector('.viewArea') as HTMLElement
   expect(topSlot.innerHTML).toContain('<div class="d_div"> 最近七天</div>')
   expect(viewArea.innerHTML).toMatchSnapshot()
+  
+  // 验证顶部按钮点击
+  const headerButton = container.querySelector('.d_div')
+  fireEvent.click(headerButton)
+  expect(onHeaderButtonClick).toHaveBeenCalled()
+  
+  // 验证自定义日期渲染
+  const customDay = container.querySelector('.nut-calendar-day:nth-child(10)')
+  expect(customDay).toHaveTextContent('custom10')
+  expect(customDay).toHaveTextContent('复盘')
+  expect(customDay).toHaveTextContent('上旬')

129-156: 建议优化点击事件测试助手函数

当前的测试助手函数实现了基本功能,但建议进行以下优化:

  1. 支持自定义点击回调的验证
  2. 支持多次点击的场景
  3. 添加错误处理

建议按如下方式优化代码:

 const testClickEvent = (
   type: CalendarType,
   startDate: string,
   endDate: string,
   offset: number,
   expected: string,
   defaultValue: string | string[] = '2025-01-03',
+  validateCallback?: (result: any) => void,
+  clickCount: number = 1
 ) => {
   const onDayClick = vi.fn()
   const { container } = render(
     <Calendar
       visible
       type={type}
       defaultValue={defaultValue}
       startDate={startDate}
       endDate={endDate}
       onDayClick={onDayClick}
     />
   )
+  try {
     const calendarMonthDay =
       container.querySelectorAll('.nut-calendar-day')[offset]
-    fireEvent.click(calendarMonthDay)
+    for (let i = 0; i < clickCount; i++) {
+      fireEvent.click(calendarMonthDay)
+    }
     expect(onDayClick).toBeCalled()
+    if (validateCallback) {
+      validateCallback(onDayClick.mock.calls)
+    }
     const start = container.querySelectorAll(
       '.nut-calendar-day-active .nut-calendar-day-day'
     )[0]
     expect(start.innerHTML).toBe(expected)
+  } catch (error) {
+    throw new Error(`测试点击事件失败: ${error.message}`)
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8478c1 and a20d16e.

⛔ Files ignored due to path filters (1)
  • src/packages/calendar/__tests__/__snapshots__/calendar.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • src/packages/calendar/__tests__/calendar.spec.tsx (2 hunks)
  • src/packages/calendar/demos/h5/demo3.tsx (1 hunks)
  • src/packages/calendar/demos/h5/demo4.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/packages/calendar/demos/h5/demo3.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (2)
src/packages/calendar/__tests__/calendar.spec.tsx (2)

4-4: 类型导入变更正确!

从类型文件中导入 CalendarDayCalendarType 类型定义,增强了测试用例的类型安全性。


87-98: 弹窗属性测试正确!

测试用例正确验证了 popup 属性对弹窗显示的控制。

@@ -16,6 +16,7 @@ const Demo4 = () => {
const setChooseValue = (chooseData: any) => {
const dateArr = [...[chooseData[0][3], chooseData[1][3]]]
setDate([...dateArr])
console.log('choosevalue', chooseData, [...dateArr])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议移除调试日志语句

考虑到此 PR 的主要目标是优化包大小,建议移除 console.log 调试语句。在生产环境中保留调试日志不仅会增加包体积,还可能泄露敏感信息。

建议应用以下修改:

-    console.log('choosevalue', chooseData, [...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.

Suggested change
console.log('choosevalue', chooseData, [...dateArr])

Comment on lines +71 to 85
test('range prop', async () => {
const { container } = render(
<Calendar
visible
showSubTitle={false}
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="range"
title="test"
defaultValue={['2024-12-16', '2025-04-01']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
/>
)

const curMonth2 = container.querySelectorAll('.nut-calendar-sub-title')

expect(curMonth2.length).toBe(0)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议增强日期范围选择的测试

当前仅使用快照测试不足以验证日期范围选择的完整功能。建议添加以下测试场景:

  1. 验证起始日期选择
  2. 验证结束日期选择
  3. 验证日期范围限制
  4. 验证跨月选择场景

建议添加如下测试代码:

 test('range prop', async () => {
+  const onSelect = vi.fn()
   const { container } = render(
     <Calendar
       visible
       type="range"
       title="test"
       defaultValue={['2024-12-16', '2025-04-01']}
       startDate="2025-01-01"
       endDate="2025-3-31"
       firstDayOfWeek={1}
+      onSelect={onSelect}
     />
   )
   const viewArea = container.querySelector('.viewArea') as HTMLElement
   expect(viewArea.innerHTML).toMatchSnapshot()
+  
+  // 验证起始日期选择
+  const startDate = container.querySelectorAll('.nut-calendar-day')[5]
+  fireEvent.click(startDate)
+  
+  // 验证结束日期选择
+  const endDate = container.querySelectorAll('.nut-calendar-day')[10]
+  fireEvent.click(endDate)
+  expect(onSelect).toHaveBeenCalledWith(['2025-01-05', '2025-01-10'])
📝 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.

Suggested change
test('range prop', async () => {
const { container } = render(
<Calendar
visible
showSubTitle={false}
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="range"
title="test"
defaultValue={['2024-12-16', '2025-04-01']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
/>
)
const curMonth2 = container.querySelectorAll('.nut-calendar-sub-title')
expect(curMonth2.length).toBe(0)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
})
test('range prop', async () => {
const onSelect = vi.fn()
const { container } = render(
<Calendar
visible
type="range"
title="test"
defaultValue={['2024-12-16', '2025-04-01']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
onSelect={onSelect}
/>
)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
// 验证起始日期选择
const startDate = container.querySelectorAll('.nut-calendar-day')[5]
fireEvent.click(startDate)
// 验证结束日期选择
const endDate = container.querySelectorAll('.nut-calendar-day')[10]
fireEvent.click(endDate)
expect(onSelect).toHaveBeenCalledWith(['2025-01-05', '2025-01-10'])
})

Comment on lines +55 to +69
test('week prop', async () => {
const { container } = render(
<Calendar
visible
showSubTitle
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="week"
title="test"
defaultValue={['2025-02-16']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
/>
)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议完善周选择模式的测试

当前仅使用快照测试可能无法充分验证周选择的功能正确性。建议添加以下测试项:

  1. 验证选择后的日期范围是否为完整的一周
  2. 验证 firstDayOfWeek 属性是否正确影响了周起始日
  3. 验证跨月周选择的场景

建议添加如下测试代码:

 test('week prop', async () => {
+  const onSelect = vi.fn()
   const { container } = render(
     <Calendar
       visible
       type="week"
       title="test"
       defaultValue={['2025-02-16']}
       startDate="2025-01-01"
       endDate="2025-3-31"
       firstDayOfWeek={1}
+      onSelect={onSelect}
     />
   )
   const viewArea = container.querySelector('.viewArea') as HTMLElement
   expect(viewArea.innerHTML).toMatchSnapshot()
+  
+  // 验证周选择
+  const dateEl = container.querySelectorAll('.nut-calendar-day')[10]
+  fireEvent.click(dateEl)
+  expect(onSelect).toHaveBeenCalledWith(['2025-02-10', '2025-02-16'])
+  
+  // 验证周起始日
+  const weekDays = container.querySelectorAll('.nut-calendar-week-day')
+  expect(weekDays[0].textContent).toBe('一')
📝 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.

Suggested change
test('week prop', async () => {
const { container } = render(
<Calendar
visible
showSubTitle
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="week"
title="test"
defaultValue={['2025-02-16']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
/>
)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
})
test('week prop', async () => {
const onSelect = vi.fn()
const { container } = render(
<Calendar
visible
type="week"
title="test"
defaultValue={['2025-02-16']}
startDate="2025-01-01"
endDate="2025-3-31"
firstDayOfWeek={1}
onSelect={onSelect}
/>
)
const viewArea = container.querySelector('.viewArea') as HTMLElement
expect(viewArea.innerHTML).toMatchSnapshot()
// 验证周选择
const dateEl = container.querySelectorAll('.nut-calendar-day')[10]
fireEvent.click(dateEl)
expect(onSelect).toHaveBeenCalledWith(['2025-02-10', '2025-02-16'])
// 验证周起始日
const weekDays = container.querySelectorAll('.nut-calendar-week-day')
expect(weekDays[0].textContent).toBe('一')
})

Comment on lines 158 to 229
test('select event when click item', () => {
testClickEvent('single', '2025-01-01', '2025-12-31', 3, '1')
})

test('week select event when click item', () => {
testClickEvent('week', '2025-01-01', '2025-01-31', 15, '12', ['2025-01-04'])
testClickEvent('week', '2025-01-01', '2025-01-31', 4, '1', ['2025-01-27'])
testClickEvent('week', '2025-01-01', '2025-01-31', 30, '26')
})

test('multiple select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="multiple"
defaultValue={['2025-01-01']}
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)

const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
const start1 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start1.innerHTML).toBe('1')

const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start2 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[1]
expect(start2.innerHTML).toBe('13')

const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[16]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const start3 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[2]
expect(start3.innerHTML).toBe('14')
})

test('choose event when click item', async () => {
const onConfirm = vi.fn()
test('range select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
onConfirm={onConfirm}
type="range"
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)

const calendarConfirmBtn = container.querySelectorAll(
'.calendar-confirm-btn'
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start.innerHTML).toBe('13')

fireEvent.click(calendarConfirmBtn)
expect(onConfirm).toBeCalled()
const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[20]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const next = container.querySelectorAll(
'.nut-calendar-day-choose .nut-calendar-day-day'
)[0]
expect(next.innerHTML).toBe('14')
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议添加边界场景测试

当前的选择模式测试覆盖了基本场景,建议添加以下边界场景的测试:

  1. 选择起始日期前的日期
  2. 选择结束日期后的日期
  3. 跨月份选择的场景
  4. 重复选择同一天的场景
  5. 取消选择的场景

建议为每种选择模式添加如下测试场景:

 test('multiple select event when click item', () => {
   // ... 现有代码保持不变
+  
+  // 测试选择限制
+  const disabledDay = container.querySelectorAll('.nut-calendar-day-disabled')[0]
+  fireEvent.click(disabledDay)
+  expect(onDayClick).not.toHaveBeenCalledWith(expect.stringContaining('2024'))
+  
+  // 测试重复选择
+  fireEvent.click(calendarMonthDay)
+  const activeItems = container.querySelectorAll('.nut-calendar-day-active')
+  expect(activeItems.length).toBe(2) // 重复选择应该取消选中状态
 })

 test('range select event when click item', () => {
   // ... 现有代码保持不变
+  
+  // 测试跨月选择
+  const nextMonthButton = container.querySelector('.nut-calendar-next')
+  fireEvent.click(nextMonthButton)
+  const nextMonthDay = container.querySelectorAll('.nut-calendar-day')[5]
+  fireEvent.click(nextMonthDay)
+  expect(onDayClick).toHaveBeenCalledWith(expect.stringContaining('2025-02'))
 })
📝 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.

Suggested change
test('select event when click item', () => {
testClickEvent('single', '2025-01-01', '2025-12-31', 3, '1')
})
test('week select event when click item', () => {
testClickEvent('week', '2025-01-01', '2025-01-31', 15, '12', ['2025-01-04'])
testClickEvent('week', '2025-01-01', '2025-01-31', 4, '1', ['2025-01-27'])
testClickEvent('week', '2025-01-01', '2025-01-31', 30, '26')
})
test('multiple select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
type="multiple"
defaultValue={['2025-01-01']}
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
const start1 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start1.innerHTML).toBe('1')
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start2 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[1]
expect(start2.innerHTML).toBe('13')
const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[16]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const start3 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[2]
expect(start3.innerHTML).toBe('14')
})
test('choose event when click item', async () => {
const onConfirm = vi.fn()
test('range select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
defaultValue="2022-03-18"
startDate="2022-01-01"
endDate="2022-12-31"
onConfirm={onConfirm}
type="range"
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)
const calendarConfirmBtn = container.querySelectorAll(
'.calendar-confirm-btn'
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start.innerHTML).toBe('13')
fireEvent.click(calendarConfirmBtn)
expect(onConfirm).toBeCalled()
const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[20]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const next = container.querySelectorAll(
'.nut-calendar-day-choose .nut-calendar-day-day'
)[0]
expect(next.innerHTML).toBe('14')
})
test('select event when click item', () => {
testClickEvent('single', '2025-01-01', '2025-12-31', 3, '1')
})
test('week select event when click item', () => {
testClickEvent('week', '2025-01-01', '2025-01-31', 15, '12', ['2025-01-04'])
testClickEvent('week', '2025-01-01', '2025-01-31', 4, '1', ['2025-01-27'])
testClickEvent('week', '2025-01-01', '2025-01-31', 30, '26')
})
test('multiple select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
type="multiple"
defaultValue={['2025-01-01']}
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)
const start1 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start1.innerHTML).toBe('1')
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start2 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[1]
expect(start2.innerHTML).toBe('13')
const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[16]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const start3 = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[2]
expect(start3.innerHTML).toBe('14')
// 测试选择限制
const disabledDay = container.querySelectorAll('.nut-calendar-day-disabled')[0]
fireEvent.click(disabledDay)
expect(onDayClick).not.toHaveBeenCalledWith(expect.stringContaining('2024'))
// 测试重复选择
fireEvent.click(calendarMonthDay)
const activeItems = container.querySelectorAll('.nut-calendar-day-active')
expect(activeItems.length).toBe(2) // 重复选择应该取消选中状态
})
test('range select event when click item', () => {
const onDayClick = vi.fn()
const { container } = render(
<Calendar
visible
type="range"
startDate="2025-01-01"
endDate="2025-06-31"
onDayClick={onDayClick}
/>
)
const calendarMonthDay = container.querySelectorAll('.nut-calendar-day')[15]
fireEvent.click(calendarMonthDay)
expect(onDayClick).toBeCalled()
const start = container.querySelectorAll(
'.nut-calendar-day-active .nut-calendar-day-day'
)[0]
expect(start.innerHTML).toBe('13')
const calendarMonthDay2 = container.querySelectorAll('.nut-calendar-day')[20]
fireEvent.click(calendarMonthDay2)
expect(onDayClick).toBeCalled()
const next = container.querySelectorAll(
'.nut-calendar-day-choose .nut-calendar-day-day'
)[0]
expect(next.innerHTML).toBe('14')
// 测试跨月选择
const nextMonthButton = container.querySelector('.nut-calendar-next')
fireEvent.click(nextMonthButton)
const nextMonthDay = container.querySelectorAll('.nut-calendar-day')[5]
fireEvent.click(nextMonthDay)
expect(onDayClick).toHaveBeenCalledWith(expect.stringContaining('2025-02'))
})

@oasis-cloud oasis-cloud merged commit ec6b708 into jdf2e:next Feb 13, 2025
6 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Feb 13, 2025
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.x Target branch 2.x action:merge This PR has received sufficient approvals (2+ approvals) and is ready to merge size/XXL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants