Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(calendar): add viewmode #2985

Open
wants to merge 19 commits into
base: next
Choose a base branch
from

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

此次改动对日历组件进行了扩展和重构。主要新增了 viewMode 属性(支持 "day"、"month"、"quarter"),相应地调整了日历渲染逻辑,通过条件选择渲染 CalendarItemCalendarViewModeItem。同时,样式文件新增和调整了多个类(如 &-shrink&-weeknumber.shrink 等),并整合了禁用状态的样式。此外,还新增了多个日期工具函数、演示组件以及文档与类型说明,整体提升了组件的配置能力和视觉表现。

Changes

文件 变更摘要
src/packages/calendar/calendar.scss
src/packages/calendar/calendarviewmode.scss
新增导入 calendarviewmode.scss,添加 &-shrink&-weeknumber&-index.shrink 等样式类;移除 &-choose-disabled 并合并至新的 &-disabled 类。
src/packages/calendar/calendar.taro.tsx
src/packages/calendar/calendar.tsx
更新 Calendar 组件,新增属性 viewModevalueshowMonthNumberonItemClick;基于 viewMode 条件渲染 CalendarItemCalendarViewModeItem;更新日期函数调用。
src/packages/calendar/calendarviewmodeitem.taro.tsx
src/packages/calendar/calendarviewmodeitem.tsx
新增 CalendarViewModeItem 组件及相关类型,通过 React hooks 管理状态,实现月和季度视图的滚动与选择功能。
src/packages/calendaritem/calendaritem.taro.tsx
src/packages/calendaritem/calendaritem.tsx
为 CalendarItem 组件新增 showMonthNumber 属性,调整 Header 和 Panel 渲染逻辑以支持周号显示,以及优化当日提示显示。
src/utils/date.ts 新增多项日期工具函数:计算周数(getWeekOfYeargetTotalWeeksInYear)、获取前/后月份和季度(getPreMonthsgetMonthsgetQuartersgetPreQuartersgetNextQuarters)、以及格式化月份和季度(formatMonthformatQuartergetQuarter)。
src/styles/variables.scss 新增变量 $calendar-panel-item-width,用于指定日历面板项宽度,可通过 CSS 变量自定义。
src/packages/calendar/demo.taro.tsx
src/packages/calendar/demo.tsx
src/packages/calendar/demos/h5/*
src/packages/calendar/demos/taro/*
更新演示组件:移除旧 demo(如 Demo1~Demo11),新增 Demo101、Demo102、Demo103 等,调整部分样式(如高度变化、移除 showTitlecloseIcon)以及更新翻译条目。
src/packages/calendar/doc.en-US.md
src/packages/calendar/doc.md
src/packages/calendar/doc.taro.md
src/packages/calendar/doc.zh-TW.md
文档中新增 viewMode 属性说明,详细描述其支持的模式及默认值设置。
src/packages/calendar/types.ts
src/packages/configprovider/types.ts
新增接口 CalendarMonthCalendarQuarter ,并在配置类型中扩展了 nutuiCalendarPanelItemWidth 变量。

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 回调
Loading

Possibly related PRs

  • refactor: calendar #2983: 与删除 &-choose-disabled 类并新增 &-disabled 类的改动密切相关,对样式调整存在直接联系。

Suggested reviewers

  • Alex-huxiyang
  • oasis-cloud

Poem

我是一只蹦跳的小兔子,
在代码花园里寻觅新奇,
日历多视图闪烁如星,
样式更新如春风拂面,
每行代码都似甜美胡萝卜,
欢庆改动,跃动不停!
(\_/) ʕ·ᴥ·ʔ

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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

@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: 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

📥 Commits

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

📒 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: **引入新组件以支持多视图模式 **
这两行导入了 CalendarViewModeItemgetDay 方法,用于在日历中支持新的多视图模式和替换原有的日期工具函数,没有发现明显问题。


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 的设置 **
startDateendDate 赋值为 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%

src/packages/calendar/calendarviewmodeitem.tsx Outdated Show resolved Hide resolved
src/packages/calendaritem/calendaritem.taro.tsx Outdated Show resolved Hide resolved
src/packages/calendaritem/calendaritem.taro.tsx Outdated Show resolved Hide resolved
src/packages/calendar/calendarviewmodeitem.taro.tsx Outdated Show resolved Hide resolved
src/packages/calendar/calendarviewmodeitem.taro.tsx Outdated Show resolved Hide resolved
src/utils/date.ts Outdated Show resolved Hide resolved
src/packages/calendar/calendarviewmode.scss Outdated Show resolved Hide resolved
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/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

📥 Commits

Reviewing files that changed from the base of the PR and between 831fb9e and 19f7397.

📒 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行已定义,这里重复定义可能导致样式冲突。

建议合并这两处样式定义或使用不同的类名。

src/packages/calendar/calendarviewmodeitem.tsx Outdated Show resolved Hide resolved
@xiaoyatong xiaoyatong marked this pull request as draft February 12, 2025 02:36
Copy link

codecov bot commented Feb 12, 2025

Codecov Report

Attention: Patch coverage is 72.91667% with 156 lines in your changes missing coverage. Please review.

Project coverage is 85.13%. Comparing base (ec6b708) to head (d8a0a6c).

Files with missing lines Patch % Lines
src/packages/calendar/calendarviewmodeitem.tsx 69.86% 113 Missing ⚠️
src/utils/date.ts 68.14% 36 Missing ⚠️
src/packages/calendaritem/calendaritem.tsx 74.07% 7 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

@xiaoyatong xiaoyatong marked this pull request as ready for review February 13, 2025 06:59
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: 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 组件代码几乎完全相同,建议:

  1. 提取共享的逻辑到一个公共的 hooks 文件中
  2. 只在组件中保留平台特定的实现

建议创建一个共享的 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: 优化回调函数的类型定义和实现

需要改进以下几点:

  1. 添加具体的类型定义而不是使用 any
  2. 移除生产环境中的 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: 明确数组类型定义

monthsDatamonthsNum 的类型定义不够明确。

-  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: 周数显示样式结构清晰

周数显示的样式结构合理,但建议:

  1. 考虑添加响应式布局支持
  2. 使用变量控制关键尺寸

建议添加以下变量:

+$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

📥 Commits

Reviewing files that changed from the base of the PR and between 19f7397 and 04ed29a.

📒 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: 类型定义清晰且结构合理!

新增的 CalendarMonthCalendarQuarter 接口定义明确,与现有的类型定义保持一致的风格。

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 实现收缩模式的布局合理。

Comment on lines +25 to +26
value={date}
defaultValue={date}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

建议添加日期格式验证

对于 valuedefaultValue 的日期字符串,建议添加格式验证以确保符合 'YYYY-MM' 格式。


🌐 Web query:

如何在 React TypeScript 中验证日期字符串格式?

💡 Result:

在 React TypeScript 中验证日期字符串格式可通过以下方法实现,结合类型校验和运行时验证:

核心实现步骤

  1. 定义模板字面量类型
    通过 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}`;
  2. 创建品牌类型增强安全性
    通过交叉类型添加品牌标识:

    type Brand<T, B> = T & { __brand: B };
    type ValidDateString = Brand<RawDateString, 'ValidDate'>;
  3. 编写验证函数(含正则+实际日期校验)

    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>
  );
};

关键优化点

  1. 双重验证机制

    • 正则表达式 /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[0-9]|3[1])$/ 确保格式正确[1][7]
    • new Date() + ISO 转换验证实际日期有效性[4][7]
  2. 类型谓词函数
    使用 str is ValidDateString 类型谓词,可在条件判断后自动收窄类型[1]

  3. 错误边界处理
    组件中包含明确的校验状态反馈,支持实时验证[8]

备选方案对比

方法 优点 缺点
Zod库校验 Schema声明式,支持复杂校验逻辑 需额外依赖安装
Moment.js 内置日期有效性检查 包体积较大,已不推荐使用
Date原生对象 零依赖 时区处理需要额外注意

建议在需要国际化的项目中使用 date-fns + Zod 组合方案,常规项目采用本文的轻量级实现即可[5][8]。

Citations:


请为传入的日期字符串添加格式验证

在文件 src/packages/calendar/demos/h5/demo102.tsx 第 25-26 行,将 date 直接用于 valuedefaultValue 时,并没有验证日期字符串是否符合预期的 'YYYY-MM' 格式。为防止数据格式不正确导致潜在意外,建议在将数据传递给组件之前添加日期格式验证。

建议的实现方式:

  • 使用正则表达式进行轻量级的运行时格式校验,例如:
    const isValidYearMonth = (str: string): boolean =>
      /^\d{4}-(0[1-9]|1[0-2])$/.test(str);
  • 如果需要更严格的校验,可以考虑结合 TypeScript 模板字面量类型及品牌类型,来在静态层面和运行时实现双重验证(参见 “如何在 React TypeScript 中验证日期字符串格式” 的实现方案)。

请根据项目实际需求调整并加入相应的校验代码,以确保传入组件的日期数据始终符合预期格式。

Comment on lines +26 to +27
value={date}
defaultValue={date}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

建议添加季度格式验证

对于 valuedefaultValue 的季度字符串,建议添加格式验证以确保符合 '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 行,目前对传入的 valuedefaultValue (季度字符串)没有进行格式验证。执行脚本后未发现现成的季度格式验证函数,因此建议新增一个专门用于验证季度字符串格式的函数,确保其符合 'YYYY-Q[1-4]' 的格式要求。

  • 请在使用季度字符串之前调用此验证函数,避免格式错误。
  • 若有类似验证需求的场景,可考虑统一调用该验证逻辑,以保障全局一致性。

Comment on lines +7 to +12
const setChooseValue = (chooseData: any) => {
const dateArr = chooseData.map((item: any) => {
return item[3]
})
setDate([...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

改进类型安全性和数据处理逻辑

当前实现存在以下问题:

  1. 使用 any 类型降低了代码的类型安全性
  2. 直接访问数组索引 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.

Suggested change
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)
}

src/packages/calendar/demo.tsx Outdated Show resolved Hide resolved
src/packages/calendar/demo.taro.tsx Outdated Show resolved Hide resolved
src/packages/calendar/calendar.tsx Outdated Show resolved Hide resolved
src/utils/date.ts Outdated Show resolved Hide resolved
</div>
</div>
)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

防止潜在的空指针异常

在访问 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

src/packages/calendar/calendarviewmodeitem.tsx Outdated Show resolved Hide resolved
@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: 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: 优化组件属性传递逻辑

当前代码在 CalendarViewModeItemCalendarItem 中存在大量重复的属性传递。建议提取共同属性以提高代码可维护性。

建议重构如下:

+ 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: 建议提取魔法数字为命名常量并添加输入验证。

建议进行以下改进:

  1. 将 86400000 提取为模块级别的命名常量
  2. 添加对 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: 建议重构月份操作函数以减少代码重复。

getPreMonthsgetMonths 函数有很多重复代码。建议:

  1. 将 type 参数定义为字面量联合类型
  2. 合并这两个函数为一个更通用的函数
+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: 建议改进函数的可读性和可维护性。

建议进行以下改进:

  1. 添加更详细的函数文档说明,包括参数和返回值的类型说明
  2. 使用更具描述性的变量名
  3. 添加对输入参数的验证
+/**
+ * 计算指定年份的所有周信息
+ * @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: 建议重构季度相关函数以提高代码复用。

建议进行以下改进:

  1. 将季度验证逻辑提取为共享函数
  2. 合并相似的季度计算函数
  3. 添加类型定义以增强类型安全性
+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

📥 Commits

Reviewing files that changed from the base of the PR and between 04ed29a and 0fdd3e7.

📒 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: 代码看起来不错!

格式化函数实现简洁,使用了合适的字符串处理方法。

src/packages/calendar/calendar.taro.tsx Outdated Show resolved Hide resolved
Comment on lines 153 to 154
children={children}
type={type}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要修正 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)

src/packages/calendar/calendar.tsx Outdated Show resolved Hide resolved
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: 5

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0fdd3e7 and 14b86d8.

⛔ 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)
Copy link

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: '季度' }
Copy link

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.

Suggested change
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
Copy link

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.

Suggested change
onPageChange: (data: any) => void
onPageChange: (data: [number, number, string]) => void

Comment on lines +280 to +293
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 {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

防止内存泄漏

滚动动画的 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)
+      }
+    }
+  }, [])

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: 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 tests

src/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

📥 Commits

Reviewing files that changed from the base of the PR and between 14b86d8 and d8a0a6c.

⛔ 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]}`}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复索引类型错误并保证 viewMode 不为 undefined
在使用 \${item[viewMode]}`units[viewMode]时,若viewModeundefined,或 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.

Suggested change
{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,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 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.

Suggested change
year: new Date().getFullYear,
year: new Date().getFullYear(),


useEffect(() => {
initData()
}, [])
Copy link

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'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要修正 viewMode 属性的类型定义。

viewMode 属性在接口中被定义为必需属性,但在 defaultProps 中提供了默认值。这种不一致可能会导致 TypeScript 类型检查错误。

建议修改接口定义,将属性标记为可选:

- viewMode?: 'day' | 'month' | 'quarter'
+ viewMode?: 'day' | 'month' | 'quarter'

Also applies to: 47-47

Comment on lines +87 to +100
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()
})
Copy link

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

Comment on lines +150 to +156
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)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要增加测试覆盖率。

新增的日期工具函数缺少测试覆盖,特别是 getWeekOfYeargetTotalWeeksInYear 这些复杂的计算函数。建议添加单元测试以确保函数在各种场景下的正确性。

需要我帮你生成这些函数的单元测试用例吗?测试用例应该包括:

  • 常规输入
  • 边界条件(年初、年末)
  • 闰年情况
  • 无效输入

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)}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复类型错误

构建失败显示存在类型不匹配的问题:

  1. viewMode 可能为 undefined
  2. 使用 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'.

Comment on lines +260 to +262
useEffect(() => {
initData()
}, [])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 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.

Suggested change
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

Comment on lines +97 to +102
const [innerValue, setInnerValue] = usePropsValue({
value,
defaultValue,
finalValue: [],
onChange: (val) => {},
})
Copy link

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 的类型应该与 valuedefaultValue 保持一致。

  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.

Suggested change
const [innerValue, setInnerValue] = usePropsValue({
value,
defaultValue,
finalValue: [],
onChange: (val) => {},
})
const [innerValue, setInnerValue] = usePropsValue({
value,
defaultValue,
finalValue: '' as CalendarValue,
onChange: (val) => {
props.onChange?.(val)
},
})

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:review This PR needs more reviews (less than 2 approvals) size/XXL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant