Skip to content

Conversation

irisSong
Copy link
Collaborator

@irisSong irisSong commented Feb 27, 2025

先review datepicker重构在review这个

Summary by CodeRabbit

  • New Features

    • 新增“日期选择器视图”组件,扩展数据录入功能,支持多种日期格式和跨平台应用。
    • 新增演示组件,展示日期选择的多种用法和效果。
  • Refactor

    • 优化日期选择逻辑,提升组件的可维护性和性能。
  • Documentation

    • 补充并完善了中英文及繁体文档,提供详细的使用指导与示例。
  • Tests

    • 增加多场景测试,确保日期选择功能稳定可靠。

Copy link

coderabbitai bot commented Feb 27, 2025

Walkthrough

此次 PR 对日期选择器相关功能进行了扩展和重构。配置文件中调整了“Col”组件的格式,并在“数据录入”部分新增了 DatePickerView 组件。多个日期选择器组件中引入了新的依赖(如 isEqual 和 classNames),重构了组件实现(从 FunctionComponent 转为 forwardRef 形式),并优化了状态管理与日期比较逻辑。同时,还增加了针对 DatePickerView 的测试用例、演示示例以及详细的文档说明。

Changes

文件路径 变更说明
src/config.json 调整 "Col" 组件格式;在数据录入部分新增 DatePickerView 组件
src/packages/datepicker/datepicker.taro.tsx
src/packages/datepicker/datepicker.tsx
引入 isEqual 与 classNames;修改日期比较逻辑;重构组件为 forwardRef 形式,更新状态管理
src/packages/datepickerview/__test__/datepickerview.spec.tsx 新增 DatePickerView 组件的测试用例
src/packages/datepickerview/datepickerview.scss 新增 .nut-datepickerview CSS 样式
src/packages/datepickerview/datepickerview.taro.tsx
src/packages/datepickerview/datepickerview.tsx
新增 DatePickerView 组件(分别支持 Taro 与 React 版本),使用 hooks 管理状态
src/packages/datepickerview/demo.taro.tsx
src/packages/datepickerview/demo.tsx
src/packages/datepickerview/demos/h5/demo1.tsx
src/packages/datepickerview/demos/h5/demo2.tsx
src/packages/datepickerview/demos/taro/demo1.tsx
src/packages/datepickerview/demos/taro/demo2.tsx
新增多平台日期选择器演示示例及自定义 hook 示例
src/packages/datepickerview/doc.md
src/packages/datepickerview/doc.en-US.md
src/packages/datepickerview/doc.taro.md
src/packages/datepickerview/doc.zh-TW.md
新增 DatePickerView 组件文档,详细说明 props、用法及示例
src/packages/datepickerview/index.taro.ts
src/packages/datepickerview/index.ts
src/packages/datepickerview/types.ts
新增组件导出文件及类型定义,提供 DatePickerViewProps 接口

Sequence Diagram(s)

sequenceDiagram
    participant U as 用户
    participant DP as DatePickerView
    participant HC as 日期比较逻辑
    participant HO as onChange回调
    U->>DP: 选择日期
    DP->>HC: 执行 handleDateComparison/handleChange
    HC-->>DP: 返回比较结果
    DP->>HO: 触发 onChange 事件
    HO-->>U: 更新页面显示
Loading

Possibly related PRs

  • feat: pickerview #2986: 该 PR 引入了 PickerView 组件,同时修改了 src/config.json 中相同区域,与本次新增 DatePickerView 存在代码层面的联系。
  • refactor: datepicker #3023: 此 PR 涉及 DatePicker 组件的变更,直接与本次新增 DatePickerView 组件相关,二者在日期选择功能上有直接联系。
  • refactor: picker #2990: 此 PR 同样在 src/config.json 中新增组件并调整了 Picker 组件的部分声明,和本次变更有较强的代码关联性。

Suggested reviewers

  • oasis-cloud
  • Alex-huxiyang

Poem

我是小兔蹦蹦跳,
新增组件似花绽放娇。
代码重构轻如风,
格式调整齐心协奏。
测试文档齐上阵,
我跳跃间庆祝更新跑! 🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
  • @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 action:review This PR needs more reviews (less than 2 approvals) 3.x Target branch 3.x labels Feb 27, 2025
Copy link

codecov bot commented Feb 27, 2025

Codecov Report

Attention: Patch coverage is 93.37748% with 10 lines in your changes missing coverage. Please review.

Project coverage is 86.12%. Comparing base (c5f27c5) to head (e14d223).
Report is 6 commits behind head on feat_v3.x.

Files with missing lines Patch % Lines
src/packages/datepickerview/datepickerview.tsx 92.95% 10 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           feat_v3.x    #3026      +/-   ##
=============================================
+ Coverage      86.05%   86.12%   +0.06%     
=============================================
  Files            281      283       +2     
  Lines          18255    18401     +146     
  Branches        2749     2768      +19     
=============================================
+ Hits           15709    15847     +138     
- Misses          2541     2549       +8     
  Partials           5        5              

☔ 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: 3

🧹 Nitpick comments (26)
src/packages/picker/types.ts (1)

17-42: PickerProps 接口定义

完整定义了 Picker 组件的属性接口,包括必要的数据属性、交互行为和回调函数。特别是:

  1. 通过继承 BasicComponent 并排除 children 属性,然后在最后再添加 children 的方式,使类型定义更加灵活。
  2. 对于 popupProps 的处理,使用 Partial 和 Omit 组合排除了可能与父级属性冲突的字段。
  3. 回调函数类型定义清晰,参数类型明确。

建议:

  • 考虑为 defaultValuevalue 添加更详细的类型注释,说明它们与 options 的对应关系
  • children 类型使用 any 不太严谨,建议使用 React.ReactNode 或更具体的类型
-  children?: any
+  children?: React.ReactNode
src/packages/datepickerview/types.ts (1)

8-31: DatePickerViewProps 接口设计全面

接口设计全面,包含了日期选择器视图组件所需的所有关键属性:

  • 值控制(value/defaultValue)
  • 日期类型配置(多种格式选项)
  • 显示和步进控制
  • 日期范围限制
  • 格式化和过滤函数
  • 事件回调

建议为必选和可选属性添加明确的注释,以提高代码的可维护性。

src/packages/form/demos/h5/demo7.tsx (1)

121-153: 日期选择器实现合理,但可考虑提取公共样式

日期选择器的实现逻辑清晰,功能完整。初始值设置、事件处理和显示格式都很合理。

不过,这里的Cell样式与第98-116行的Picker组件中的Cell样式完全相同。可以考虑将这些共同样式提取为一个常量或辅助函数,以减少代码重复。

-  <Cell
-    style={{
-      padding: 0,
-      '--nutui-cell-divider-border-bottom': '0',
-    }}
-    className="nutui-cell--clickable"
-    title={
-      value
-        ? new Date(value).toLocaleDateString()
-        : 'Please select'
-    }
-    extra={<ArrowRight />}
-    align="center"
-  />
+  <Cell
+    style={commonCellStyle}
+    className="nutui-cell--clickable"
+    title={
+      value
+        ? new Date(value).toLocaleDateString()
+        : 'Please select'
+    }
+    extra={<ArrowRight />}
+    align="center"
+  />

同时在文件顶部添加:

const commonCellStyle = {
  padding: 0,
  '--nutui-cell-divider-border-bottom': '0',
}
src/packages/datepickerview/demo.taro.tsx (1)

1-38: 组件结构良好,但混合了View和h2标签

这个新的DatePickerViewDemo组件结构清晰,国际化实现得当。支持中文简体、繁体和英文三种语言,满足多语言需求。

但在第29行使用了Taro的<View className="h2">,而第31行却直接使用了HTML的<h2>标签。建议为了保持一致性,统一使用Taro的组件:

- <View className="h2">{translated.basic}</View>
+ <View className="h2">{translated.basic}</View>
  <Demo1 />
- <h2>{translated.mmdd}</h2>
+ <View className="h2">{translated.mmdd}</View>

这样可以确保在各平台(特别是小程序环境)下的兼容性和一致性。

src/packages/picker/__tests__/picker.spec.tsx (1)

177-199: 测试中的异步处理可以优化

根据之前的学习经验,在React组件测试中应避免使用带有固定延迟的setTimeout。建议使用act()包装异步状态更新,并使用waitFor()进行断言,这样可以使测试更稳定可靠。

虽然当前测试用例可以工作,但可以考虑采用更现代的异步测试方法。

 const PenderContent = () => {
   const [asyncColumns, setasyncColumns] = useState([])

-  setTimeout(() => {
-    setasyncColumns(simpleColumns)
-  }, 100)
+  React.useEffect(() => {
+    const timer = setTimeout(() => {
+      setasyncColumns(simpleColumns)
+    }, 100)
+    return () => clearTimeout(timer)
+  }, [])

   return (
     <Picker
       visible
src/packages/datepickerview/demos/h5/demo2.tsx (2)

21-31: 日期范围限制实现合理,但可优化描述一致性

DatePickerView组件的配置合理,限制了开始和结束时间,并提供了适当的默认值。

不过,组件的标题"限制开始结束时间"与实际操作有关,但Cell的description使用的只是选中的日期值,可能会让用户困惑。建议将标题与描述信息更加一致,或者在描述中也反映出日期范围的信息。


9-17: 日期格式化可以使用统一工具函数

当前代码直接使用了Date原生方法来格式化月份和日期,但这种方式可能导致不同地区的显示差异。考虑使用专门的日期格式化工具或函数,确保一致的日期表示。

此外,月份需要+1处理(因为getMonth()返回0-11),这种逻辑在多处使用时容易出错。建议封装成工具函数。

- const [desc, setDesc] = useState(
-   `${defaultValue.getMonth() + 1}-${defaultValue.getDate()}`
- )
+ // 可以在项目中创建一个日期工具文件
+ const formatMonthDay = (date) => {
+   return `${date.getMonth() + 1}-${date.getDate()}`
+ }
+ 
+ const [desc, setDesc] = useState(formatMonthDay(defaultValue))
src/packages/datepickerview/demo.tsx (1)

6-52: 代码结构清晰,但可考虑增加更多演示案例

组件演示代码结构清晰,很好地使用了国际化特性。不过,根据 demo.tsx 的内容,虽然有标题 {translated.showAll},但似乎没有对应的演示组件展示"选择年月日时分"功能,也缺少其他在翻译文本中定义的功能(如时间选择、格式化选项等)的演示。

建议添加更多的演示案例来展示 DatePickerView 的所有功能,特别是已经在翻译文本中定义但尚未展示的功能。

src/packages/datepickerview/demos/taro/demo2.tsx (1)

9-33: 代码实现合理,建议优化日期处理方式

当前实现能够正确展示限制开始结束时间的功能,但日期处理方式可以进一步优化:

  1. 使用更安全的日期格式化方法,避免直接拼接字符串
  2. 考虑添加边界条件的处理,如无效日期的情况

建议考虑使用日期格式化库(如 date-fns)或自定义格式化函数来处理日期显示:

-  const [desc, setDesc] = useState(
-    `${defaultValue.getMonth() + 1}-${defaultValue.getDate()}`
-  )
+  const formatDate = (date: Date) => {
+    return `${date.getMonth() + 1}-${date.getDate()}` 
+  }
+  const [desc, setDesc] = useState(formatDate(defaultValue))

另外,建议为 Cell 组件的 title 添加国际化支持,使其与 demo.tsx 中的翻译保持一致。

src/packages/datepicker/demos/h5/demo1.tsx (1)

37-51: 处理函数归一化优化

handleConfirm 函数很好地通过高阶函数实现了处理函数的归一化,但有一个问题:

在第 41-43 行中硬编码了特定日期的比较逻辑 isEqual(values, ['2026', '02', '21']),这种方式不够灵活。

建议:

- if (isEqual(values, ['2026', '02', '21'])) {
-   setValue('2026/03/22')
-   setDesc('2026年03月22日')
- } else {
+ if (setValue) {
    setValue(values.join('/'))
    setDesc(options.map((option) => option.label).join(''))
- }

或者将这个特殊的日期处理逻辑抽离成配置项,增强代码的可维护性和灵活性。

src/packages/datepickerview/__test__/datepickerview.spec.tsx (1)

22-114: 日期范围和格式化函数测试

全面测试了 startDateendDate 属性,以及不同日期类型的渲染。格式化函数测试覆盖了所有日期类型。

建议增加断言验证格式化后的文本内容是否符合预期,而不仅仅是执行重新渲染。

// 在 formatter 测试中添加以下断言
const yearItems = container.querySelectorAll('.nut-pickerview-list')[0].querySelectorAll('.nut-pickerview-roller-item');
expect(yearItems[0]).toHaveTextContent(/\d+/); // 验证年份格式
src/packages/datepickerview/demos/h5/demo1.tsx (2)

11-21: 自定义 Hook 返回默认日期和描述,功能简洁明了。
useDatePicker 能够将传入的初始日期转换为字符串并进行基础格式化,易于使用。若需国际化或更复杂的日期处理,可考虑参数化 formatter。


36-51: onChange 回调中的特殊处理逻辑可进一步抽象。
判断 ['2026', '02', '26'] 这种硬编码逻辑可以通过在 Hook 中或外部常量管理来提升可维护性,并避免散落在业务层的 magic numbers。

src/packages/datepickerview/demos/taro/demo1.tsx (1)

36-51: 使用相同的 onChange 回调逻辑,多端逻辑统一。
同样建议将硬编码的特殊日期逻辑抽离到常量或配置,防止未来业务扩展时出现维护问题。

src/packages/datepicker/types.ts (1)

11-56: DatePickerProps 定义全面,涵盖多种日期模式与回调函数。

  • 支持 type 区分多种日期、时间格式为组件提供了灵活性。
  • formatterfilter 让开发者能在生成候选项时进行自定义处理,契合常见业务场景。
  • 建议在注释中注明各属性的默认值或适用范围,以方便团队后续维护。
src/packages/datepickerview/datepickerview.tsx (3)

73-77: 借助 usePropsValue 管理内部状态,减少受控与非受控两套逻辑的重复。
这种状态管理方式在复杂表单场景中易扩展,如需加强对同步/异步更新的控制,可在后续进一步优化。


79-99: handleDateComparison 缺少测试覆盖,且逻辑存在潜在的时区问题。

  1. 静态分析提示此处未被测试,可补充单元测试以验证异常用例。
  2. 若部署地区存在时区差异,新旧日期的精细比较可受时区影响。

如需自动化脚本来查找测试文件并新增测试用例,可提出请求。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 89-96: src/packages/datepickerview/datepickerview.tsx#L89-L96
Added lines #L89 - L96 were not covered by tests


169-181: 仅在 pickerOptions.length 大于 0 时渲染 PickerView
此写法能够避免空数据导致渲染出错,但若 pickerOptions 为空时,是否给予用户提示或 fallback 视图可酌情考虑。

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

154-155: 移除或替换 console.log 日志以避免生产环境中多余输出。
这里使用了 console.log(new Date(selectedDate).toLocaleDateString()),在生产环境中可能会造成无用的打印。若需保留调试信息,建议使用条件日志或调试工具。


117-152: 建议将大型逻辑拆分以提升可维护性。
generatePickerColumns 函数体量较大,且包含多层级逻辑生成代码。可考虑将部分业务逻辑拆分到更小的函数中,从而提升可读性和后续维护性。

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

129-176: 与 Taro 同名文件的组件重复度较高,建议提取公共逻辑。
DatePicker 与 Taro 版本逻辑基本一致,包含许多相似处理函数及状态管理,后期维护会面临双处修改的风险。可将公共函数或 Hook 提取到独立模块中,减少重复代码并提升可维护性。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 133-133: src/packages/datepicker/datepicker.tsx#L133
Added line #L133 was not covered by tests


[warning] 139-141: src/packages/datepicker/datepicker.tsx#L139-L141
Added lines #L139 - L141 were not covered by tests

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

114-114: 变量命名避免与判断逻辑重名。
行 114 与行 133-134 中将局部变量命名为 isEqual,易与其他相同命名逻辑混淆。建议更改为更具描述性的变量名,例如 datesAreEqual

Also applies to: 133-134


129-176: 抽离公共逻辑,减少 Taro 与非 Taro 版本之间的重复。
InternalPicker 几乎与普通版相同,重复更新会提高出错概率。建议把重复部分封装到公共工具函数或 Hook 中,提高复用性。

src/packages/datepicker/utils.ts (3)

66-67: 考虑秒和分的关系

在返回边界值对象时,maxSecondsminSeconds被设置为与分钟相同的值。这种实现可能是有意为之,但可能会导致用户混淆。建议考虑是否需要单独处理秒数,或者在注释中更清楚地说明这种关系。

-    [`${type}Seconds`]: minute, // 返回秒数(与分钟相同)
+    [`${type}Seconds`]: boundary.getSeconds(), // 返回实际的秒数

或者保持现状但更新注释:

-    [`${type}Seconds`]: minute, // 返回秒数(与分钟相同)
+    [`${type}Seconds`]: minute, // 目前秒数与分钟相同,简化处理

80-81: 增强日期有效性检查

当前的检查方式是if (!selected) return [],但这种检查可能不足以捕获所有无效日期情况,如Invalid Date。建议使用更严格的日期验证。

-  const selected = new Date(selectedDate)
-  if (!selected) return []
+  const selected = new Date(selectedDate)
+  if (!selected || isNaN(selected.getTime())) return []

131-132: 增强日期有效性检查

与前面的函数类似,这里只检查了selectedDate是否为假值,但没有检查日期是否有效。对于无效日期(例如NaN),可能需要额外的验证。

-  if (!selectedDate) return 0
+  if (!selectedDate || isNaN(date.getTime())) return 0
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2db1df1 and 3c3e865.

⛔ Files ignored due to path filters (1)
  • src/packages/datepickerview/__test__/__snapshots__/datepickerview.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (48)
  • src/config.json (2 hunks)
  • src/packages/calendar/demos/h5/demo6.tsx (2 hunks)
  • src/packages/calendar/demos/taro/demo6.tsx (2 hunks)
  • src/packages/datepicker/__test__/datepicker.spec.tsx (1 hunks)
  • src/packages/datepicker/datepicker.taro.tsx (5 hunks)
  • src/packages/datepicker/datepicker.tsx (5 hunks)
  • src/packages/datepicker/demos/h5/demo1.tsx (3 hunks)
  • src/packages/datepicker/demos/h5/demo2.tsx (1 hunks)
  • src/packages/datepicker/demos/h5/demo8.tsx (4 hunks)
  • src/packages/datepicker/demos/taro/demo1.tsx (3 hunks)
  • src/packages/datepicker/demos/taro/demo2.tsx (1 hunks)
  • src/packages/datepicker/demos/taro/demo8.tsx (2 hunks)
  • src/packages/datepicker/doc.en-US.md (1 hunks)
  • src/packages/datepicker/doc.md (1 hunks)
  • src/packages/datepicker/doc.taro.md (1 hunks)
  • src/packages/datepicker/doc.zh-TW.md (1 hunks)
  • src/packages/datepicker/index.taro.ts (1 hunks)
  • src/packages/datepicker/index.ts (1 hunks)
  • src/packages/datepicker/types.taro.ts (1 hunks)
  • src/packages/datepicker/types.ts (1 hunks)
  • src/packages/datepicker/utils.ts (1 hunks)
  • src/packages/datepickerview/__test__/datepickerview.spec.tsx (1 hunks)
  • src/packages/datepickerview/datepickerview.scss (1 hunks)
  • src/packages/datepickerview/datepickerview.taro.tsx (1 hunks)
  • src/packages/datepickerview/datepickerview.tsx (1 hunks)
  • src/packages/datepickerview/demo.taro.tsx (1 hunks)
  • src/packages/datepickerview/demo.tsx (1 hunks)
  • src/packages/datepickerview/demos/h5/demo1.tsx (1 hunks)
  • src/packages/datepickerview/demos/h5/demo2.tsx (1 hunks)
  • src/packages/datepickerview/demos/taro/demo1.tsx (1 hunks)
  • src/packages/datepickerview/demos/taro/demo2.tsx (1 hunks)
  • src/packages/datepickerview/doc.md (1 hunks)
  • src/packages/datepickerview/index.taro.ts (1 hunks)
  • src/packages/datepickerview/index.ts (1 hunks)
  • src/packages/datepickerview/types.ts (1 hunks)
  • src/packages/form/demos/h5/demo7.tsx (2 hunks)
  • src/packages/form/demos/taro/demo7.tsx (2 hunks)
  • src/packages/picker/__tests__/picker.spec.tsx (2 hunks)
  • src/packages/picker/index.taro.ts (1 hunks)
  • src/packages/picker/index.ts (1 hunks)
  • src/packages/picker/picker.taro.tsx (3 hunks)
  • src/packages/picker/picker.tsx (1 hunks)
  • src/packages/picker/types.taro.ts (1 hunks)
  • src/packages/picker/types.ts (1 hunks)
  • src/packages/popover/demos/h5/demo4-1.tsx (2 hunks)
  • src/packages/popover/demos/h5/demo4.tsx (3 hunks)
  • src/packages/popover/demos/taro/demo4-1.tsx (3 hunks)
  • src/packages/popover/demos/taro/demo4.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/packages/datepickerview/datepickerview.scss
  • src/packages/datepickerview/index.taro.ts
  • src/packages/datepickerview/index.ts
  • src/packages/datepicker/index.taro.ts
🧰 Additional context used
🧠 Learnings (1)
src/packages/picker/__tests__/picker.spec.tsx (1)
Learnt from: xiaoyatong
PR: jdf2e/nutui-react#2990
File: src/packages/pickerview/__test__/pickerview.spec.tsx:0-0
Timestamp: 2025-02-25T02:21:32.906Z
Learning: In React component tests, avoid using setTimeout with fixed delays. Instead, use act() to wrap async state updates and waitFor() for assertions, which makes tests more stable and reliable.
🪛 GitHub Check: codecov/patch
src/packages/datepickerview/datepickerview.tsx

[warning] 89-96: src/packages/datepickerview/datepickerview.tsx#L89-L96
Added lines #L89 - L96 were not covered by tests


[warning] 161-162: src/packages/datepickerview/datepickerview.tsx#L161-L162
Added lines #L161 - L162 were not covered by tests

src/packages/datepicker/utils.ts

[warning] 115-115: src/packages/datepicker/utils.ts#L115
Added line #L115 was not covered by tests


[warning] 147-147: src/packages/datepicker/utils.ts#L147
Added line #L147 was not covered by tests


[warning] 243-244: src/packages/datepicker/utils.ts#L243-L244
Added lines #L243 - L244 were not covered by tests


[warning] 283-284: src/packages/datepicker/utils.ts#L283-L284
Added lines #L283 - L284 were not covered by tests


[warning] 287-288: src/packages/datepicker/utils.ts#L287-L288
Added lines #L287 - L288 were not covered by tests

src/packages/datepicker/datepicker.tsx

[warning] 98-99: src/packages/datepicker/datepicker.tsx#L98-L99
Added lines #L98 - L99 were not covered by tests


[warning] 101-102: src/packages/datepicker/datepicker.tsx#L101-L102
Added lines #L101 - L102 were not covered by tests


[warning] 133-133: src/packages/datepicker/datepicker.tsx#L133
Added line #L133 was not covered by tests


[warning] 139-141: src/packages/datepicker/datepicker.tsx#L139-L141
Added lines #L139 - L141 were not covered by tests

🪛 markdownlint-cli2 (0.17.2)
src/packages/datepickerview/doc.md

33-33: Link fragments should be valid
null

(MD051, link-fragments)


34-34: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)

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

2-8: 导入 PickerValue 类型用于类型安全

PickerValue 类型的导入增强了代码的类型安全性,这与 DatePicker 组件的重构保持一致。


41-41: 更新函数参数类型以增强类型安全

confirm 函数的参数类型从 (string | number)[] 更新为 PickerValue[],提高了类型安全性并与组件 API 的重构保持一致。


44-45: 属性访问从 text 更新为 label

将选项属性从 option.text 更新为 option.label,与 Picker 组件的 API 变更保持同步。


48-49: 属性访问从 text 更新为 label

将选项属性从 option.text 更新为 option.label,与 Picker 组件的 API 变更保持同步。

src/packages/calendar/demos/taro/demo6.tsx (4)

7-7: 导入 PickerValue 类型用于类型安全

在 Taro 版本中导入 PickerValue 类型,确保与 H5 版本保持一致性,增强类型安全。


37-37: 更新函数参数类型以增强类型安全

confirm 函数的参数类型从 (string | number)[] 更新为 PickerValue[],与 H5 版本保持一致,提高了类型安全性。


40-41: 属性访问从 text 更新为 label

将选项属性从 option.text 更新为 option.label,确保与 Picker 组件的 API 变更和 H5 版本保持一致。


44-45: 属性访问从 text 更新为 label

将选项属性从 option.text 更新为 option.label,确保与 Picker 组件的 API 变更和 H5 版本保持一致。

src/packages/popover/demos/taro/demo4.tsx (4)

3-8: 更新导入引用和类型使用,确保类型安全

将单独的导入语句合并成一个块导入,并添加了PickerOnChangeCallbackParameter类型导入,有助于提高代码的类型安全性和一致性。


16-30: 列选项结构更新为使用label和value属性

将选项结构从使用text属性更改为使用label属性,保持了与其他Picker组件实现的一致性。这样的更改有助于统一API设计和提高代码可维护性。


60-60: 更新onConfirm回调中的属性引用

option.text更改为option.label,与列选项结构的更改保持一致。


64-67: 改进onChange回调参数解构和类型安全

使用PickerOnChangeCallbackParameter类型和解构selectedOptions参数替代之前直接使用PickerOption[]类型的方式,增强了类型安全性并使代码更加清晰。使用可选链操作符?.和类型断言也提高了代码的健壮性。

src/packages/popover/demos/h5/demo4.tsx (4)

2-7: 组织导入并添加必要的类型

将单独的导入语句合并成一个块导入,并添加了PickerOnChangeCallbackParameter类型,与其他文件保持一致。


15-29: 统一Picker选项的数据结构

将选项结构从使用text属性更改为使用label属性,保持整个组件库中Picker组件API的一致性。


59-59: 更新onConfirm回调中的属性引用

option.text更改为option.label,与新的选项结构保持一致。


63-66: 改进onChange处理函数的类型安全性

使用PickerOnChangeCallbackParameter类型和解构语法,提高了代码的可读性和类型安全性。使用可选链操作符?.和类型断言增强了代码的健壮性。

src/packages/popover/demos/h5/demo4-1.tsx (4)

2-8: 整合导入并添加必要的类型

将导入语句合并为一个块导入,并添加了PickerOnChangeCallbackParameter类型导入,与其他组件保持一致的导入风格。


17-25: 统一Picker选项的数据结构格式

将选项结构从使用text属性更改为使用label属性,保持了与库中其他Picker实现的一致性。这种统一的API设计有助于提高开发体验和代码可维护性。


63-63: 更新onConfirm回调中的属性访问

option.text更改为option.label,与新的选项结构保持一致。


67-70: 增强onChange处理函数的类型安全性和可读性

使用PickerOnChangeCallbackParameter类型和解构selectedOptions参数,使代码更加类型安全和易于理解。使用可选链操作符和类型断言增强了代码的健壮性。

src/packages/popover/demos/taro/demo4-1.tsx (4)

3-9: 优化导入结构并引入类型声明

将导入语句组织为一个块导入,并添加了PickerOnChangeCallbackParameter类型导入,提高了代码的一致性和类型安全性。


19-29: 统一Picker选项的数据结构

将选项结构从使用text属性更改为使用label属性,与其他Picker组件保持一致。这种统一的API设计有助于降低学习成本并提高代码可维护性。


67-67: 更新onConfirm回调中的属性引用

option.text更改为option.label,与新的选项结构保持一致。


71-74: 提高onChange处理函数的类型安全性和可读性

使用PickerOnChangeCallbackParameter类型和解构语法替代之前直接使用数组类型的方式,提高了代码的类型安全性和可读性。使用可选链操作符和类型断言增强了代码的健壮性。

src/packages/picker/index.ts (1)

3-3: 类型导入路径更新

PickerProps 类型的导入路径从 './picker' 改为 './types',提高了代码组织性,使类型定义更加集中和规范。

src/packages/picker/index.taro.ts (1)

3-3: 类型导入路径更新

PickerProps 类型的导入路径从 './picker.taro' 改为 './types.taro',与非 Taro 版本保持一致的类型管理方式,增强了代码结构的一致性。

src/packages/picker/types.taro.ts (1)

1-8: Taro 平台的 PickerProps 类型定义

新增的 Taro 平台特定类型定义文件,通过继承 Web 版本的 PickerProps 并重新定义 popupProps,解决了平台特定属性的差异。使用 TypeScript 的 Omit 和 Partial 类型工具有效地定制了组件属性。

特别注意:确保 popupProps 的类型定义与 Taro 平台的 Popup 组件行为保持一致,避免在运行时出现属性类型不匹配的问题。

src/packages/picker/types.ts (1)

1-9: 类型导入和依赖

导入了必要的类型定义,包括 PopupProps、BasicComponent 以及 PickerView 相关类型。组件类型拆分和重用的方式符合最佳实践。

src/packages/picker/picker.taro.tsx (5)

17-17: 在 Taro 环境下引入 Popup 组件的优化做法
此处导入 Popup 的写法看上去与其他 Taro 组件一致,不存在功能或兼容性问题。


22-22: 使用 ComponentDefaults 统一管理默认属性
导入 ComponentDefaults 有助于在此组件内复用全局默认属性,避免重复定义。


24-24: 从单独文件引入 PickerProps 更具可维护性
PickerProps 独立到 ./types.taro 文件,有利于解耦与统一管理属性类型。


143-147: TS 类型注释能提高点击事件的可读性和安全性
通过声明 (e: { stopPropagation: () => void }) 明确事件对象结构,能减少潜在的类型错误并提升开发体验。


153-157: 同理为确认按钮添加类型注释
与取消按钮的做法一致,这里的类型注释可确保事件处理逻辑更安全、易读。

src/packages/picker/picker.tsx (3)

16-16: 引入 Popup 以提供基础弹窗功能
此处使用 @/packages/popup/index 保持了与非 Taro 版本组件的结构一致性,便于在 Web 环境中统一管理弹窗交互。


21-21: 在组件中应用全局默认属性
@/utils/typings 中导入的 ComponentDefaults 同样适用于此文件,强化了全局一致性。


22-22: 扩展自定义类型并导出至其他组件
{ PickerActions, PickerProps, PickerRef } 的集中导入,为组件之间的类型共享提供了便利,有助于可维护性。

src/packages/datepicker/types.taro.ts (1)

1-18: 类型定义看起来很清晰

这个新的 DatePickerProps 类型定义通过 Omit 和 Partial 的组合使用,有效地控制了可以通过 pickerProps 传递的属性。这种方法可以确保某些特定的属性(如 defaultValuevalue 等)不会被意外覆盖,同时保持类型安全。

这种类型定义的设计模式使得组件间的属性传递更加安全和可控。

src/packages/datepicker/demos/taro/demo8.tsx (4)

16-16: 时间格式更新

默认描述字符串现在包含了固定的时间 "06:00",与下面状态变量的更新保持一致。


18-22: 状态描述格式优化

desc 状态变量的初始化已更改为使用中文字符(年、月、日、时)作为格式,使显示更加本地化和用户友好。


33-51: 函数重命名保持一致性

formatter 函数(之前可能命名为 formatter1)保持了相同的逻辑,但名称更具描述性,与组件 API 保持一致。


55-55: 标题更新符合功能变化

Cell 组件的标题从"选择时分秒"更新为"选择年月日时",更准确地反映了当前 demo 的功能,与 type="datehour" 保持一致。

src/packages/datepicker/__test__/datepicker.spec.tsx (1)

4-4:

✅ Verification successful

导入方式变更

DatePicker 的导入方式从命名导入更改为默认导入,这表明 DatePicker 组件的导出方式在其源文件中已更改。请确保此更改与 datepicker.ts 文件中的导出方式一致。

如果 datepicker.ts 文件中的导出语法已相应更新为默认导出,那么这个更改是正确的。


🏁 Script executed:

#!/bin/bash
# 检查 DatePicker 组件的导出方式
echo "检查 DatePicker 的导出方式:"
grep -A 5 "export " src/packages/datepicker/datepicker.tsx

Length of output: 137


结果确认:DatePicker 导出方式正确

经过验证,src/packages/datepicker/datepicker.tsx 中确实使用了 export default DatePicker 进行导出,因此在 src/packages/datepicker/__test__/datepicker.spec.tsx 中使用默认导入方式(即 import DatePicker from '../datepicker')是正确的。不需要做任何修改。

src/packages/datepicker/doc.taro.md (1)

102-102:

✅ Verification successful

API 文档更新

filter 属性的类型签名已更新,从处理单个选项 (option: PickerOption) 改为处理选项数组 (options: PickerOptions)。这一变化使 API 更加一致,并且与 demo8.tsx 中的实际用法相匹配。

请确保所有相关的文档文件(如 doc.md、doc.en-US.md 等)也进行了相应的更新,以保持文档的一致性。


🏁 Script executed:

#!/bin/bash
# 检查其他文档文件中 filter 属性的描述是否一致
echo "检查其他文档文件中的 filter 属性描述:"
grep -A 1 "filter" src/packages/datepicker/doc.*.md

Length of output: 1078


已验证:API 文档更新一致,无需额外修改

  • 已确认 src/packages/datepicker/doc.en-US.mdsrc/packages/datepicker/doc.taro.md 以及 src/packages/datepicker/doc.zh-TW.md 中关于 filter 属性的签名均更新为 (type: string, options: PickerOptions) => PickerOptions,同时描述均表明通过该函数对选项数组进行过滤,与 demo8.tsx 中的实际使用一致。
  • 请检查其他相关文档(例如 doc.md,若存在此文件)是否也保持相同步骤更新以确保全站统一。
src/packages/datepicker/demos/taro/demo2.tsx (1)

27-30: 改进日期选择器的动态范围设置

将固定日期改为动态日期是一个很好的改进,这样使得示例代码更实用且与当前日期相关。使用 defaultValue 的年份来设置 endDate 保证了开始和结束日期之间有合理的关系。

以下几点值得注意:

  1. 使用当前日期作为 startDate 可以确保用户只能选择今天及以后的日期
  2. endDate 设置为当年的 7 月 1 日提供了一个合理的日期范围
  3. 使用已定义的 defaultValue 变量保持了代码的一致性
src/packages/datepicker/doc.zh-TW.md (1)

102-102: 更新了过滤函数的类型签名,提高了一致性

filter 属性的类型签名从处理单个选项 (type: string, option: PickerOption) => PickerOption[] 更改为处理选项集合 (type: string, options: PickerOptions) => PickerOptions,这是一个重要的 API 变更。

此更改表明 filter 函数现在可以一次性处理和返回整个选项集合,而不是单个选项,这提高了组件的灵活性和功能性。确保在使用此组件时更新相应的回调函数实现。

请检查文档中的所有示例代码是否已更新以匹配此 API 变更,特别是 demo8.tsx 中的过滤选项示例。

src/packages/datepicker/demos/h5/demo2.tsx (1)

29-31: 改进日期选择器的动态范围设置

与 Taro 版本一致,H5 版本的示例也采用了动态日期设置,这是一个良好的实践。此更改使得示例更加实用,并确保在任何时间查看时都具有相关性。

代码中值得注意的几点:

  1. 动态设置 startDate 为当前日期,确保选择范围始终是最新的
  2. endDate 限制为当年的 7 月 1 日,提供了更实际的日期范围展示
  3. 使用预先定义的 defaultValue 变量增强了代码的可读性和一致性
src/packages/datepicker/doc.md (1)

102-102:

✅ Verification successful

更新了过滤函数的类型签名,增强了处理能力

filter 属性的类型签名从 (type: string, option: PickerOption) => PickerOption[] 更改为 (type: string, options: PickerOptions) => PickerOptions,这是一个重要的 API 变更。

这一变更提高了 filter 函数的能力,现在它可以批量处理选项集合,而不是单独处理每个选项,可能会带来更高的性能和更灵活的过滤逻辑实现。请确保更新所有使用此组件的代码,特别是自定义过滤函数的实现。

需要确认这一变更是否与其他相关文档(如 API 参考、示例代码等)保持一致,特别是 demo8.tsx 中的过滤选项示例是否已适配新的 API。


🏁 Script executed:

#!/bin/bash
# 检查相关示例代码中的 filter 函数实现
grep -r "filter" --include="*.tsx" src/packages/datepicker/demos

Length of output: 642


确认 API 签名更新 – 示例代码验证通过

经过验证,src/packages/datepicker/demos/taro/demo8.tsxsrc/packages/datepicker/demos/h5/demo8.tsx 中的 filter 函数均已更新为新签名 (type: string, options: PickerOptions) => PickerOptions,此变更已正确反映在示例代码中。请确保所有其他使用该组件的代码同步更新此 API 变更。

src/packages/datepicker/doc.en-US.md (1)

92-92: 类型签名更改更加符合实际用例

filter 属性类型已从处理单个选项更新为处理选项集合,这种变更更加符合实际使用场景。在日期选择器中,过滤通常应用于一组选项而非单个选项。

- | filter | Option filter | `(type: string, option: PickerOption) => PickerOption[]` | `-` |
+ | filter | Option filter | `(type: string, options: PickerOptions) => PickerOptions` | `-` |
src/packages/form/demos/taro/demo7.tsx (2)

15-15: 引入新组件

正确导入了 DatePicker 组件,与其他表单组件导入保持一致。


121-153: DatePicker 表单项实现良好

Form.Item 结合 DatePicker 组件的实现遵循了与现有 Picker 相同的模式,保持了 API 设计的一致性。getValueFromEvent 函数正确处理了日期转换,而 onClick 处理程序恰当地打开了日期选择器。Cell 组件的渲染也处理了有值和无值的两种情况。

src/packages/datepickerview/types.ts (2)

1-7: 导入依赖项定义清晰

从 utils/typings 和 pickerview/types 正确导入了所需的类型定义,为新组件提供了必要的基础类型支持。


24-25: 确保格式化和过滤函数的一致性

注意到 formatter 函数接收单个 option 参数,而 filter 函数接收 options 集合参数。确保这种设计是有意的,并与 DatePicker 组件中相应的参数类型保持一致。

src/packages/datepicker/index.ts (1)

1-3:

❓ Verification inconclusive

重构模块导入导出方式

DatePicker 组件的导入方式从命名导入更改为默认导入,同时 DatePickerProps 类型的导出源从 './datepicker' 更改为 './types'。这种重构改进了代码组织,将类型定义分离到专门的类型文件中。

确保这一变更已在所有引用 DatePicker 和 DatePickerProps 的地方进行了同步更新,以避免潜在的导入错误。


🏁 Script executed:

#!/bin/bash
# 检查是否有任何地方仍在使用旧的导入方式
rg "import.*DatePicker.*from.*'@nutui/nutui.*datepicker'" --type tsx --type ts

Length of output: 114


请注意更新所有引用 DatePicker 和 DatePickerProps 的地方

  • 文件 src/packages/datepicker/index.ts 的修改内容:

    • 将 DatePicker 组件的导入方式从命名导入更改为默认导入
    • 将 DatePickerProps 类型的导出源从 './datepicker' 更改为 './types'
  • 请确保整个代码库中所有引用 DatePicker 及 DatePickerProps 的地方也同步做了相应调整,以免因导入方式不一致而导致运行错误。

  • 附加说明:原有的 ripgrep 命令在检查 .tsx 文件中旧的导入方式时出现了 “unrecognized file type: tsx” 错误。建议使用下面的新命令进行验证:

    rg "import.*DatePicker.*from.*'@nutui/nutui.*datepicker'" -g "*.ts" -g "*.tsx"
src/packages/form/demos/h5/demo7.tsx (1)

15-15: 导入新组件以增强表单功能

导入DatePicker组件以扩展表单的日期选择能力,与现有表单组件保持一致。

src/packages/picker/__tests__/picker.spec.tsx (2)

5-5: 引入PickerOptions类型增强类型系统

引入PickerOptions类型是一个好的改进,这为组件间共享类型定义提供了基础。


17-17: 类型更新提高了灵活性

将PickerOption接口中的children类型从PickerOption[]更新为PickerOptions增加了类型系统的灵活性和一致性。这种变更有助于统一多级选择器的类型定义。

src/packages/datepicker/demos/taro/demo1.tsx (2)

10-21: 良好的代码重构,提取了日期处理逻辑

将日期处理逻辑提取到 useDatePicker 自定义钩子中是一个很好的做法,增强了代码的可重用性和可维护性。


37-52: 硬编码的特定日期条件需要重新考虑

handleConfirm 函数中包含了一个特定日期条件检查:isEqual(values, ['2026', '02', '21']),这看起来像是硬编码的测试条件。在生产代码中应避免此类硬编码条件,除非有明确的业务需求。

这个特定日期条件是否有特殊的业务意义?如果是为了测试或示例目的,建议添加注释说明,或者考虑使用更通用的逻辑。

  if (setValue) {
-    if (isEqual(values, ['2026', '02', '21'])) {
-      setValue('2026/03/22')
-      setDesc('2026年03月22日')
-    } else {
      setValue(values.join('/'))
      setDesc(options.map((option) => option.label).join(''))
-    }
  } else {
src/packages/datepicker/demos/h5/demo1.tsx (3)

10-21: 自定义 Hook 提高了代码复用性

创建了 useDatePicker 自定义 Hook 来抽象日期对象处理逻辑,这是一个很好的实践,能够简化组件代码并提高复用性。


24-36: 默认日期初始化逻辑优化

使用自定义 Hook 替代内联的日期处理逻辑,代码结构更加清晰。


66-70: 使用新的处理函数简化了组件配置

使用 handleConfirm 函数替代原来的回调处理,简化了组件配置并保持了一致性。

src/packages/datepickerview/__test__/datepickerview.spec.tsx (3)

7-20: 中文显示测试用例

正确测试了 showChinese 属性是否正常工作,确保年份标签显示正确。


116-130: 时间步进设置测试

验证了 minuteStep 属性正确限制了分钟选项的数量,测试逻辑清晰。


132-153: 时间过滤功能测试

测试验证了过滤功能能够正确过滤小时选项。使用了模拟函数来实现过滤逻辑,测试方法得当。

src/config.json (2)

226-236: 代码格式优化

Col 组件的配置格式已优化,提高了代码的一致性和可读性。


644-656: 新增 DatePickerView 组件配置

新增了 DatePickerView 组件的配置,完善了数据录入类组件体系。配置项定义清晰,包含了版本、名称、类型、中文名等必要信息。

src/packages/datepicker/demos/h5/demo8.tsx (5)

16-16: 默认时间调整

将默认时间从 "00:00" 修改为 "06:00",更符合实际使用场景。


18-22: 改进了日期描述格式

使用中文年月日时格式,增强了本地化显示效果,提高了用户体验。


33-33: 函数命名优化

formatter1 重命名为 formatter,使函数名更具描述性和一致性。


55-55: 更新了单元格标题

将标题从"选择时分秒"更新为"选择年月日时",更准确地反映了日期选择器的实际功能。


66-66: 更新格式化函数引用

更新了 DatePicker 组件的 formatter 属性以使用重命名后的函数,保持了代码一致性。

src/packages/datepickerview/demos/h5/demo1.tsx (4)

1-10: 导入依赖合理,使用方式规范。
引入了 DatePickerViewCellGroup 等组件以及 react-fast-compare 库,整体符合 React 及 NutUI 的使用规范。


55-63: 非受控用法示例清晰,适合快速上手。
使用 defaultValueonChange 搭配展示,示例简单易懂,无明显问题。


65-74: 受控用法演示得当,且使用 useState 来同步更新。
当开发者需要手动控制值的改变和展示时,这种用法是非常直观的示例。


79-79: 默认导出组件符合通用的组件导出惯例。
若项目无特殊要求,此方式可无缝地被其他模块或路由引入。

src/packages/datepickerview/demos/taro/demo1.tsx (5)

1-10: 与 H5 版本保持一致的导入和依赖结构。
强调了 Taro 版组件的差异性通过包名区分,结构清晰。


11-21: 自定义 Hook 提供相同的默认日期与格式化逻辑。
解决多端复用层面的日期初始化需求,避免重复代码。若后续需要更多功能,可考虑封装进一步的配置选项。


55-63: 非受控示例与 H5 版本示例一致,无明显问题。
代码结构统一、便于跨端理解和对比。


65-74: 受控示例同样设计合理,调用方式简明。
兼容 Taro 环境的使用场景,示例易读无不当之处。


79-79: 默认导出符合多端组件常用模式。
能直接被其他页面或组件引用,降低二次封装的难度。

src/packages/datepicker/types.ts (2)

1-3: 类型导入结构良好。
BasicComponentPickerPropsPickerOptionsPickerValue 等类型的引用清晰可控,避免了冗余。


5-9: 定义 DatePickerRef 及其对应功能方法,接口设计简洁易用。
openclose 方法命名直观,可与外层业务流程自然衔接。

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

5-8: 基于 PickerView 进行二次封装,合理利用其导出的类型与基础功能。
对上层进行日期特化,满足多种日期场景需求,无不当之处。


153-163: 检测 selectedDate 改变时的 useEffect 未在测试中覆盖。
可在测试用例中模拟 selectedDate 发生变化并断言相关行为,确保组件在日期变化时能正确触发副作用。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 161-162: src/packages/datepickerview/datepickerview.tsx#L161-L162
Added lines #L161 - L162 were not covered by tests

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

98-102: 为以下行添加单元测试以提升覆盖率。
静态分析工具指出第 98-99 行、101-102 行、133 行以及 139-141 行缺少测试覆盖。建议编写相应用例,以确保对开启、关闭、确认逻辑以及 isEqual 比较逻辑的正确性进行验证。

Also applies to: 133-133, 139-141

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 98-99: src/packages/datepicker/datepicker.tsx#L98-L99
Added lines #L98 - L99 were not covered by tests


[warning] 101-102: src/packages/datepicker/datepicker.tsx#L101-L102
Added lines #L101 - L102 were not covered by tests

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

98-105: 为 Taro 版本的打开/关闭逻辑和取消操作添加测试。
actions 中的 openclose 方法(行 99-104)以及 handleCancel(行 140-143)尚未看到相应的测试验证。可考虑补充测试用例,确保 Taro 环境下的显示与隐藏逻辑正确无误。

Also applies to: 140-144

src/packages/datepicker/utils.ts (3)

243-244: 考虑为未覆盖的代码路径添加测试

静态分析显示这部分代码没有被测试覆盖。当valuenull或不是有效日期时,代码将使用startDate作为默认值。建议添加测试用例来覆盖这种情况。

可以添加如下测试用例:

test('formatValue应当在值为null或无效时使用startDate', () => {
  const startDate = new Date(2023, 0, 1);
  const endDate = new Date(2023, 11, 31);
  
  // 测试null值
  expect(formatValue(null, startDate, endDate)).toBe(startDate.getTime());
  
  // 测试无效日期
  const invalidDate = new Date('invalid');
  expect(formatValue(invalidDate, startDate, endDate)).toBe(startDate.getTime());
});
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 243-244: src/packages/datepicker/utils.ts#L243-L244
Added lines #L243 - L244 were not covered by tests


283-288: 特殊日期格式处理的测试覆盖

静态分析表明,处理"month-day"和"year-month"格式的代码分支未被测试覆盖。这些分支处理日期格式的特殊情况,确保正确的日期构造。建议添加相应的测试用例。

可以为这些特殊格式添加测试:

test('handlePickerValueChange应正确处理month-day格式', () => {
  // 模拟month-day格式的选择
  const selectedOptions = [...];
  const selectedValue = ['05', '15']; // 5月15日
  const defaultDate = new Date(2023, 0, 1);
  
  let resultDate = null;
  const handleDateComparison = (date) => {
    resultDate = date;
  };
  
  handlePickerValueChange(
    selectedOptions,
    selectedValue,
    0,
    'month-day',
    defaultDate,
    handleDateComparison
  );
  
  // 验证年份是否正确使用了defaultDate的年份
  expect(resultDate.getFullYear()).toBe(2023);
  expect(resultDate.getMonth()).toBe(4); // 5月
  expect(resultDate.getDate()).toBe(15);
});

// 同样可以添加year-month格式的测试
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 283-284: src/packages/datepicker/utils.ts#L283-L284
Added lines #L283 - L284 were not covered by tests


[warning] 287-288: src/packages/datepicker/utils.ts#L287-L288
Added lines #L287 - L288 were not covered by tests


1-337: 总体代码质量评价

代码整体结构清晰,函数命名规范,注释详尽,职责划分明确。大多数函数都有完整的JSDoc注释,这对于维护和使用非常有帮助。这些实用函数很好地封装了日期选择和处理的复杂逻辑,提高了组件的可复用性和可维护性。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 115-115: src/packages/datepicker/utils.ts#L115
Added line #L115 was not covered by tests


[warning] 147-147: src/packages/datepicker/utils.ts#L147
Added line #L147 was not covered by tests


[warning] 243-244: src/packages/datepicker/utils.ts#L243-L244
Added lines #L243 - L244 were not covered by tests


[warning] 283-284: src/packages/datepicker/utils.ts#L283-L284
Added lines #L283 - L284 were not covered by tests


[warning] 287-288: src/packages/datepicker/utils.ts#L287-L288
Added lines #L287 - L288 were not covered by tests

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

🧹 Nitpick comments (1)
src/packages/datepickerview/doc.md (1)

31-48: 标题命名建议调整
Props 部分当前标题为“## DatePicker”,建议修改为“## DatePickerView”以确保文档中组件名称的一致性,避免造成混淆。

以下是建议的 diff 修正:

-## DatePicker
+## DatePickerView

此外,Props 表格整体说明详尽,每个属性的描述、类型以及默认值均已明确,文档格式符合 Markdown 规范。

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3c3e865 and 29a6b47.

📒 Files selected for processing (5)
  • src/config.json (2 hunks)
  • src/packages/datepickerview/doc.en-US.md (1 hunks)
  • src/packages/datepickerview/doc.md (1 hunks)
  • src/packages/datepickerview/doc.taro.md (1 hunks)
  • src/packages/datepickerview/doc.zh-TW.md (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/packages/datepickerview/doc.taro.md
  • src/packages/datepickerview/doc.zh-TW.md
  • src/packages/datepickerview/doc.en-US.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/config.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (4)
src/packages/datepickerview/doc.md (4)

1-4: 整体介绍清晰
文件开头的标题“DatePickerView 日期选择器视图”以及简短描述“时间选择器,支持日期、年月、时分等维度。”较好地传达了组件的基本功能。建议若后续有更多细节(例如支持的特定用例或限制)可在后续版本中补充说明。


5-10: 引入部分语法正确
“引入”部分使用了 TypeScript 代码块展示了如何导入组件,写法简洁清晰,路径正确且易于理解。


11-20: 示例代码部分——选择日期
示例代码通过 demo 块展示了如何使用组件,能够快速帮助用户理解基本用法。代码块及 demo 语法正确,建议保留现有结构。


21-29: 示例代码部分——选择月日
说明文字详细解释了如何通过 type 属性控制日期类型的选择,demo 块使用得当。可以考虑在后续版本中增加其它类型的示例以覆盖更多场景,但当前版本已具备基本说明。

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 (4)
src/packages/datepickerview/datepickerview.tsx (1)

168-180: 条件渲染合理,但可补充空数组或空值时的兜底逻辑。

使用 pickerOptions.length && <PickerView ...> 可以避免空数据时渲染 PickerView。但若初始化或异常情况下数据为空时,是否需要展示占位或提示用户?可根据业务需求添加相应的处理。

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

169-180: 有条件地渲染 PickerView,需考虑空数据场景。

pickerOptions.length 不为 0 时才渲染 PickerView,能有效避免空数组渲染。但若默认选项为空或异步获取导致为空——此时是否需要给用户提示,或展示空态占位?可视业务需求酌情优化。

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

179-214: 生成选择器列优化

generatePickerColumns 函数使用工具函数生成日期选择器的列数据,代码结构清晰。

但有一点需要注意:在回调函数中直接修改并设置 pickerValue 数组,可能会导致状态更新不可预测。建议使用函数式更新或者创建新数组后再设置状态。

建议优化状态更新方式:

- pickerValue[columnIndex] = options[selectedIndex]?.value
- setPickerValue([...pickerValue])
+ setPickerValue(prevValue => {
+   const newValue = [...prevValue]
+   newValue[columnIndex] = options[selectedIndex]?.value
+   return newValue
+ })
src/packages/datepicker/datepicker.taro.tsx (1)

227-247: Taro 特定的渲染实现

使用 Taro 的 View 组件替代标准 HTML 的 div,并使用字符串连接方式添加类名,而不是使用 cls 变量。建议统一使用前面定义的 cls 变量来保持代码一致性。

为了保持代码风格一致性,建议使用前面定义的 cls 变量:

- <View className={`nut-datepicker ${className}`} style={style} {...rest}>
+ <View className={cls} style={style} {...rest}>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 29a6b47 and dd4d13b.

📒 Files selected for processing (7)
  • src/packages/calendar/demos/h5/demo6.tsx (2 hunks)
  • src/packages/calendar/demos/taro/demo6.tsx (2 hunks)
  • src/packages/datepicker/datepicker.taro.tsx (5 hunks)
  • src/packages/datepicker/datepicker.tsx (5 hunks)
  • src/packages/datepicker/index.taro.ts (1 hunks)
  • src/packages/datepickerview/datepickerview.taro.tsx (1 hunks)
  • src/packages/datepickerview/datepickerview.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/packages/datepicker/index.taro.ts
🔇 Additional comments (33)
src/packages/calendar/demos/h5/demo6.tsx (2)

2-9: 已引入更明确的类型定义,增强类型安全。

引入 PickerValuePickerOptions 后,可以更好地约束时间/日期选择的参数类型。当前改动符合类型安全需求,并与后续逻辑搭配合理。


42-47: 确认函数入参类型更新,注意与组件调用保持一致。

confirm 函数的参数从原本的 (string | number)[]any[] 更改为 PickerValue[]PickerOptions,对齐了新类型定义,逻辑更加清晰。但是建议在调用端也检查一下,以确保调用方传入的类型与这里定义的参数保持一致,避免后期出现类型不匹配问题。

src/packages/calendar/demos/taro/demo6.tsx (2)

7-8: 类型引入与 H5 版本对齐,增加一致性。

PickerValuePickerOptions 的导入与 H5 版本保持一致,利于跨端维护和代码阅读性。


38-50: 更新 confirm 函数参数类型,确保跨端一致性。

confirm 函数的参数类型做了与 H5 端一致的更新,并将选项处理切换至 option.label,能够更直观地处理选择结果。建议在实际使用中验证是否存在对旧类型的依赖,以及在业务逻辑中是否有相应的兼容处理。

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

24-32: 默认属性范围合理,但需注意日期区间有效性。

使用当前年份前后 10 年设置 startDateendDate 通常足够通用,但实际业务场景中需确保日期区间能满足需求,同时避免过大区间产生性能开销。


79-98: 对比日期并触发 onChange 回调的实现合理。

handleDateComparison 核心逻辑是判断日期是否变化,不再重复调用 setState,同时适时调用 onChange。实现思路清晰。但要注意:在高频率场景(如快速滑动)下,尽量避免多次重复渲染,可在调优时关注性能瓶颈。

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

25-33: 默认属性可满足通用需求,建议结合业务场景调整。

与 Web 版本相同的默认属性设置(前后 10 年区间)非常通用,但仍需根据具体项目需求评估是否需要减少或扩大区间,避免用户滚动过量日期选项。


80-99: 比较并触发 onChange 的逻辑实现清晰。

方法 handleDateComparison 先判断日期合法性并使用 isDate 校验,再比较新旧值并调用 onChange 传出。用途明确,可读性高。

src/packages/datepicker/datepicker.tsx (16)

1-6: 导入依赖项更新

组件从普通函数组件变更为使用 ForwardRefRenderFunctionuseImperativeHandle,这是一个很好的改进,现在组件可以通过 ref 暴露方法,增强了与父组件的交互能力。


20-23: 导入工具函数和类型优化

./utils 导入的工具函数使代码更加模块化,提高了可维护性。将类型定义分离到 ./types 文件中也是一个良好的实践,这样便于类型的复用和管理。


38-41: 组件定义方式优化

使用 ForwardRefRenderFunction 类型定义内部组件,并指定 DatePickerRef 作为 ref 类型,Partial<DatePickerProps> 作为 props 类型,使得类型更加明确和安全。


61-62: 添加 children 属性支持

新增了对 children 属性的支持,使组件更加灵活,可以通过函数子组件方式传递和使用选中的日期。


80-82: 类名定义和样式优化

将类名前缀定义为常量并使用 classNames 工具函数来处理类名,这样使得类名管理更加清晰和灵活。


86-91: 状态管理优化

使用 usePropsValue 钩子管理受控组件的值,并在格式化值时传入 startDateendDate 参数。这种方式更加符合 React 的数据流模式,使组件既可以作为受控组件也可以作为非受控组件使用。


93-94: 内部日期状态管理

新增 innerDate 状态用于内部处理,与 selectedDate 分离,使状态管理更加清晰。当用户在选择过程中,修改的是 innerDate,只有确认后才会更新 selectedDate


95-99: 可见性状态管理优化

使用 usePropsValue 钩子管理组件的可见性状态,使组件可以受控也可以非受控。


101-110: 暴露命令式方法

通过 actions 对象和 useImperativeHandle 钩子,暴露了 openclose 方法给父组件使用,使组件更加灵活,能够通过 ref 直接控制。


112-131: 日期比较处理逻辑优化

handleDateComparison 函数现在正确地比较新日期与当前选择的日期,并只在必要时更新 innerDate,避免不必要的重渲染。需要确保时间戳比较是准确的,考虑到不同时区可能存在的影响。

确保在不同时区下日期比较的准确性,特别是当应用部署在国际环境中时。


133-139: 确认日期比较逻辑

handleConfirmDateComparison 函数只在确认操作时更新 selectedDate,这符合典型的日期选择器交互模式,用户可以在最终确认前预览选择。


141-149: 取消和关闭操作处理

取消操作时将 innerDate 重置为 selectedDate,关闭时设置 innerVisible 为 false,这些处理都符合日期选择器的预期行为。


151-177: 确认和变更事件处理

通过 handleConfirmhandleChange 函数处理确认和变更事件,使用条件判断 innerVisible && 确保只在选择器可见时处理变更事件,这是一个很好的优化。

但是,当 innerVisible 为 false 时,handleChange 函数不会执行,这可能会导致在某些特殊情况下(如通过程序设置值)无法正确触发变更事件,请确认这是否符合预期。

确认在选择器不可见时是否需要处理变更事件的情况。


216-224: Effect 钩子依赖优化

Effect 钩子的依赖数组包含了所有必要的依赖项,确保状态更新和副作用执行的一致性。


225-246: 渲染逻辑优化

渲染逻辑增加了对函数子组件的支持,并且条件渲染 Picker 组件,确保只有当 pickerOptions 有长度时才渲染,这是一个很好的优化。使用 Fragment (<>) 包裹多个元素也是符合 React 的最佳实践。


249-252: 组件导出方式更新

使用 React.forwardRef 包装 InternalPicker 并默认导出,符合 React 的最佳实践,使组件能够接收和处理 ref。

src/packages/datepicker/datepicker.taro.tsx (9)

1-6: 导入依赖项更新

与标准版本相同,Taro 版本的组件也从普通函数组件变更为使用 ForwardRefRenderFunctionuseImperativeHandle,提高了组件的灵活性和交互能力。


22-24: 类型导入优化

从 Taro 特定的类型文件导入 DatePickerProps,同时从通用类型文件导入 DatePickerActionsDatePickerRef,这种区分方式有助于管理平台特定的差异。


40-43: 组件定义方式统一

Taro 版本的组件定义方式与标准版本保持一致,使用 ForwardRefRenderFunction 类型定义内部组件,保证了代码风格和接口的一致性。


63-64: 添加 children 属性支持

与标准版本一致,Taro 版本也添加了对 children 属性的支持,保持了两个平台实现的一致性。


82-84: 类名定义和样式优化

与标准版本相同的类名处理方式,使用 classNames 工具函数处理类名,保持了一致的风格。


88-93: 状态管理优化

使用 usePropsValue 钩子管理受控组件的值,与标准版本保持一致,确保了跨平台的行为一致性。


97-101: 可见性状态管理一致性

与标准版本一致的可见性状态管理,确保 Taro 版本的行为与标准版本相同。


103-112: 暴露命令式方法

通过相同的机制暴露 openclose 方法,保持了 API 的一致性。


251-254: 组件导出方式统一

与标准版本一致的导出方式,使用 React.forwardRef 包装 InternalPicker 并默认导出。

Comment on lines +153 to +162
if (
!isEqual(
new Date(selectedDate)?.getTime(),
new Date(selectedDate)?.getTime()
)
) {
setSelectedDate(selectedDate)
}
}, [selectedDate])

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

逻辑判断恒为 false,可能导致状态无法更新。

在此处使用 !isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime()) 比较的是同一个表达式,结果一定是 false。若本意是对比新旧日期,请确保传入两个不同的值,例如保存旧值或传入下一次更新的时间,以正确触发后续流程。

- if (!isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime())) {
+ // 示例:假设需要对比 prevSelectedDate 和当前 selectedDate
+ if (!isEqual(prevSelectedDate?.getTime(), new Date(selectedDate)?.getTime())) {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +153 to +162
useEffect(() => {
if (
!isEqual(
new Date(selectedDate)?.getTime(),
new Date(selectedDate)?.getTime()
)
) {
setSelectedDate(selectedDate)
}
}, [selectedDate])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

比较同一表达式将导致判断永远为 false。

!isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime()) 比较了相同的时间值。若期望对比更新前与更新后的值,需保持两个不同的引用或记录上一次的数值,否则无法触发更新逻辑。

- if (!isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime())) {
+ // 请确保此处对比新旧值一致
+ if (!isEqual(prevSelectedDate?.getTime(), new Date(selectedDate)?.getTime())) {

Committable suggestion skipped: line range outside the PR's diff.

src/config.json Outdated
"name": "数据录入",
"enName": "dataentry",
"packages": [
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

可以放在 datepicker 后边~ 如果分包超过大小时,可以把上边的最后一个移到这里-dateentry 下~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

可以放在 datepicker 后边~ 如果分包超过大小时,可以把上边的最后一个移到这里-dateentry 下~
已修改

}

const classPrefix = 'nut-datepicker'
const cls = classNames(classPrefix, className)
Copy link
Collaborator

Choose a reason for hiding this comment

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

cls 没有用到~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

cls 没有用到~

已修改

basic: '选择日期',
mmdd: '选择月日',
showAll: '选择年月日时分',
time: '选择时分秒',
Copy link
Collaborator

Choose a reason for hiding this comment

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

后边用不到的可以删掉~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

后边用不到的可以删掉~

已修改

<Demo1 />
<h2>{translated.mmdd}</h2>
<Demo2 />
<h2>{translated.showAll}</h2>
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里没有demo,可以删掉~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

这里没有demo,可以删掉~
已修改

<Cell title="显示中文-非受控" description={desc1} />
<Cell>
<DatePickerView
defaultValue={new Date(defaultValue1)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

demo的数据类型有不一致的情况~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

demo的数据类型有不一致的情况~
已修改

@irisSong irisSong requested a review from xiaoyatong March 5, 2025 02:39
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

♻️ Duplicate comments (1)
src/packages/datepickerview/datepickerview.tsx (1)

153-162: ⚠️ Potential issue

修复无效的日期比较逻辑

这段代码存在逻辑问题,当前的条件 !isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime()) 比较的是同一个表达式,结果总是 false,导致 setSelectedDate(selectedDate) 永远不会执行。

  useEffect(() => {
-    if (
-      !isEqual(
-        new Date(selectedDate)?.getTime(),
-        new Date(selectedDate)?.getTime()
-      )
-    ) {
-      setSelectedDate(selectedDate)
-    }
+    // 如果需要在 selectedDate 变化时执行某些操作,可以直接在此处理
+    // 例如:可以在此同步更新其他状态或执行副作用
  }, [selectedDate])

如果需要保留对 selectedDate 的检查和处理,建议使用 useRef 跟踪先前的值并进行比较:

+ const prevSelectedDateRef = useRef<number>(0);
+
  useEffect(() => {
+    // 只有当日期实际发生变化时才更新
+    if (prevSelectedDateRef.current !== selectedDate) {
+      // 执行必要的更新操作
+      prevSelectedDateRef.current = selectedDate;
+    }
-    if (
-      !isEqual(
-        new Date(selectedDate)?.getTime(),
-        new Date(selectedDate)?.getTime()
-      )
-    ) {
-      setSelectedDate(selectedDate)
-    }
  }, [selectedDate])
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 159-160: src/packages/datepickerview/datepickerview.tsx#L159-L160
Added lines #L159 - L160 were not covered by tests

🧹 Nitpick comments (4)
src/packages/datepickerview/demos/h5/demo1.tsx (2)

36-50: 改进 handleChange 函数的类型安全和可读性

handleChange 函数的实现比较复杂,建议进行重构以提高可读性和类型安全性。当前实现中存在以下几个问题:

  1. 针对特定日期的硬编码处理(isEqual(value, ['2026', '02', '26']))缺乏注释说明其用途
  2. 函数嵌套和条件分支较多,可读性不高

建议进行以下优化:

-  const handleChange =
-    (setDesc: (desc: string) => void, setValue?: (value: string) => void) =>
-    (selectedOptions: PickerOptions, value: PickerValue[]) => {
-      if (setValue) {
-        if (isEqual(value, ['2026', '02', '26'])) {
-          setValue('2026/03/22')
-          setDesc('2026年03月22日')
-        } else {
-          setValue(value.join('/'))
-          setDesc(selectedOptions.map((option) => option.label).join(''))
-        }
-      } else {
-        setDesc(selectedOptions.map((option) => option.label).join(''))
-      }
-    }
+  // 创建一个处理日期选择变化的高阶函数
+  const handleChange =
+    (setDesc: (desc: string) => void, setValue?: (value: string) => void) =>
+    (selectedOptions: PickerOptions, value: PickerValue[]) => {
+      // 根据选项生成描述文本
+      const newDesc = selectedOptions.map((option) => option.label).join('')
+      
+      // 非受控模式下只更新描述
+      if (!setValue) {
+        setDesc(newDesc)
+        return
+      }
+      
+      // 受控模式下处理特殊情况(演示用例)
+      if (isEqual(value, ['2026', '02', '26'])) {
+        // 特殊日期处理:当用户选择2026年2月26日时,自动调整到3月22日
+        setValue('2026/03/22')
+        setDesc('2026年03月22日')
+      } else {
+        // 正常情况:更新值和描述
+        setValue(value.join('/'))
+        setDesc(newDesc)
+      }
+    }

68-68: 确保日期格式转换的一致性

value 变量是通过 value.join('/') 形成的字符串,传入 new Date() 构造函数可能导致不同浏览器或平台有不同的解析结果。

建议使用更可靠的日期解析方法:

-            value={new Date(value)}
+            value={new Date(value.split('/')[0], parseInt(value.split('/')[1]) - 1, value.split('/')[2])}

或者更好的方式是保持状态为日期对象而非字符串:

-  const [value, setValue] = useState(defaultValue2)
+  const [value, setValue] = useState(new Date(defaultValue2))
-  const handleChange =
-    (setDesc: (desc: string) => void, setValue?: (value: string) => void) =>
+  const handleChange =
+    (setDesc: (desc: string) => void, setValue?: (value: Date) => void) =>
     (selectedOptions: PickerOptions, value: PickerValue[]) => {
       if (setValue) {
         if (isEqual(value, ['2026', '02', '26'])) {
-          setValue('2026/03/22')
+          setValue(new Date(2026, 2, 22)) // 注意月份从0开始,3月是2
           setDesc('2026年03月22日')
         } else {
-          setValue(value.join('/'))
+          setValue(new Date(parseInt(value[0]), parseInt(value[1]) - 1, parseInt(value[2])))
           setDesc(selectedOptions.map((option) => option.label).join(''))
         }
       } else {
         setDesc(selectedOptions.map((option) => option.label).join(''))
       }
     }
src/packages/datepickerview/datepickerview.tsx (2)

34-36: 考虑使用 forwardRef 代替 FunctionComponent

当前组件使用 FunctionComponent 类型,但考虑到组件库的一致性和复杂表单组件的需求,建议使用 React.forwardRef 转发引用,这样可以使外部组件访问这个组件内部的 DOM 元素。

-export const DatePickerView: FunctionComponent<Partial<DatePickerViewProps>> = (
-  props
-) => {
+export const DatePickerView = React.forwardRef<
+  HTMLDivElement,
+  Partial<DatePickerViewProps> & React.HTMLAttributes<HTMLDivElement>
+>((props, ref) => {

同时更新组件的返回语句:

  return (
-    <div className={cls} style={style}>
+    <div className={cls} style={style} ref={ref}>
      {pickerOptions.length && (
        <PickerView

169-178: 添加空数据处理和加载状态

pickerOptions.length 为 0 时,组件不渲染任何内容,这可能导致用户体验问题,特别是在数据加载过程中。

  return (
    <div className={cls} style={style}>
-      {pickerOptions.length && (
+      {pickerOptions.length ? (
        <PickerView
          value={pickerValue}
          options={pickerOptions}
          onChange={({ selectedOptions, value, index }) => {
            handleChange(selectedOptions, value, index)
          }}
          threeDimensional={threeDimensional}
        />
+      ) : (
+        <div className={`${classPrefix}-empty`}>
+          {/* 可以添加加载指示器或空状态提示 */}
+          <span>{locale.common?.loading || '加载中...'}</span>
+        </div>
       )}
    </div>
  )
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 12da798 and e14d223.

📒 Files selected for processing (6)
  • src/packages/datepickerview/datepickerview.taro.tsx (1 hunks)
  • src/packages/datepickerview/datepickerview.tsx (1 hunks)
  • src/packages/datepickerview/demos/h5/demo1.tsx (1 hunks)
  • src/packages/datepickerview/demos/h5/demo2.tsx (1 hunks)
  • src/packages/datepickerview/demos/taro/demo1.tsx (1 hunks)
  • src/packages/datepickerview/demos/taro/demo2.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/packages/datepickerview/demos/h5/demo2.tsx
  • src/packages/datepickerview/demos/taro/demo2.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/packages/datepickerview/datepickerview.tsx

[warning] 88-95: src/packages/datepickerview/datepickerview.tsx#L88-L95
Added lines #L88 - L95 were not covered by tests


[warning] 159-160: src/packages/datepickerview/datepickerview.tsx#L159-L160
Added lines #L159 - L160 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (7)
src/packages/datepickerview/demos/h5/demo1.tsx (1)

58-58: 修复 defaultValue 数据类型不一致问题

传给 DatePickerView 的 defaultValue 属性需要是 Date 类型,但直接使用 new Date(defaultValue1) 将字符串转换为日期对象可能导致浏览器兼容性问题或不一致的解析结果。

src/packages/datepickerview/demos/taro/demo1.tsx (3)

36-50: 改进 handleChange 函数的类型安全和可读性

handleChange 函数的实现比较复杂,建议进行重构以提高可读性和类型安全性。当前实现中存在以下几个问题:

  1. 针对特定日期的硬编码处理(isEqual(value, ['2026', '02', '26']))缺乏注释说明其用途
  2. 函数嵌套和条件分支较多,可读性不高

58-58: 修复 defaultValue 数据类型不一致问题

传给 DatePickerView 的 defaultValue 属性需要是 Date 类型,但直接使用 new Date(defaultValue1) 将字符串转换为日期对象可能导致浏览器兼容性问题或不一致的解析结果。


68-68: 确保日期格式转换的一致性

value 变量是通过 value.join('/') 形成的字符串,传入 new Date() 构造函数可能导致不同浏览器或平台有不同的解析结果。

src/packages/datepickerview/datepickerview.taro.tsx (3)

35-37: 考虑使用 forwardRef 代替 FunctionComponent

当前组件使用 FunctionComponent 类型,但考虑到组件库的一致性和复杂表单组件的需求,建议使用 React.forwardRef 转发引用。


74-78: 完善日期格式化逻辑和错误处理

当前的日期格式化缺少错误处理,如果 props.valuedefaultValue 是无效日期,可能会导致运行时错误。


153-162: 修复无效的日期比较逻辑

这段代码存在逻辑问题,当前的条件 !isEqual(new Date(selectedDate)?.getTime(), new Date(selectedDate)?.getTime()) 比较的是同一个表达式,结果总是 false,导致 setSelectedDate(selectedDate) 永远不会执行。

Comment on lines +73 to +78
const [selectedDate, setSelectedDate] = usePropsValue<number>({
value: props.value && formatValue(props.value, startDate, endDate),
defaultValue: defaultValue && formatValue(defaultValue, startDate, endDate),
finalValue: 0,
})

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

完善日期格式化逻辑和错误处理

当前的日期格式化缺少错误处理,如果 props.valuedefaultValue 是无效日期,可能会导致运行时错误。

  const [selectedDate, setSelectedDate] = usePropsValue<number>({
-    value: props.value && formatValue(props.value, startDate, endDate),
-    defaultValue: defaultValue && formatValue(defaultValue, startDate, endDate),
+    value: props.value && isDate(props.value) ? formatValue(props.value, startDate, endDate) : undefined,
+    defaultValue: defaultValue && isDate(defaultValue) ? formatValue(defaultValue, startDate, endDate) : formatValue(new Date(), startDate, endDate),
    finalValue: 0,
  })
📝 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 [selectedDate, setSelectedDate] = usePropsValue<number>({
value: props.value && formatValue(props.value, startDate, endDate),
defaultValue: defaultValue && formatValue(defaultValue, startDate, endDate),
finalValue: 0,
})
const [selectedDate, setSelectedDate] = usePropsValue<number>({
value: props.value && isDate(props.value) ? formatValue(props.value, startDate, endDate) : undefined,
defaultValue: defaultValue && isDate(defaultValue) ? formatValue(defaultValue, startDate, endDate) : formatValue(new Date(), startDate, endDate),
finalValue: 0,
})

Comment on lines +79 to +98
const handleDateComparison = (
newDate: Date | null,
selectedOptions: PickerOptions,
index: number
) => {
if (newDate && isDate(newDate)) {
if (!isEqual(new Date(selectedDate)?.getTime(), newDate?.getTime())) {
setSelectedDate(formatValue(newDate, startDate, endDate))
onChange?.(
selectedOptions,
[
String(newDate.getFullYear()),
padZero(newDate.getMonth() + 1),
padZero(newDate.getDate()),
],
index
)
}
}
}
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

改进 handleDateComparison 函数并添加测试覆盖

该函数是组件的关键部分,但缺少测试覆盖。同时,可以优化日期比较逻辑,使其更清晰。

  const handleDateComparison = (
    newDate: Date | null,
    selectedOptions: PickerOptions,
    index: number
  ) => {
    if (newDate && isDate(newDate)) {
-      if (!isEqual(new Date(selectedDate)?.getTime(), newDate?.getTime())) {
+      const currentDate = new Date(selectedDate);
+      const isNewDateDifferent = 
+        !currentDate || 
+        currentDate.getFullYear() !== newDate.getFullYear() || 
+        currentDate.getMonth() !== newDate.getMonth() || 
+        currentDate.getDate() !== newDate.getDate();
+        
+      if (isNewDateDifferent) {
        setSelectedDate(formatValue(newDate, startDate, endDate))
        onChange?.(
          selectedOptions,
          [
            String(newDate.getFullYear()),
            padZero(newDate.getMonth() + 1),
            padZero(newDate.getDate()),
          ],
          index
        )
      }
    }
  }

建议添加测试用例覆盖此函数的不同场景:


🏁 Script executed:

#!/bin/bash
# 检查 DatePickerView 组件的测试覆盖率
fd "datepickerview.spec" -e tsx --exec cat {}

Length of output: 3720


主题:改进 handleDateComparison 函数及增加单独测试覆盖

  • 已更新日期比较逻辑,将原有 isEqual 调用替换为基于年、月、日的明确比较,使得逻辑更清晰易懂。
  • 当前测试主要覆盖了整个 DatePickerView 组件的行为,但未单独对 handleDateComparison 函数进行充分测试。建议新增针对该函数的单元测试,覆盖以下场景:
    • selectedDatenull 或格式无效时的处理;
    • 比较新日期与当前日期相同时不触发更新;
    • 新日期与当前日期不同时正确调用 setSelectedDateonChange
  const handleDateComparison = (
    newDate: Date | null,
    selectedOptions: PickerOptions,
    index: number
  ) => {
    if (newDate && isDate(newDate)) {
-      if (!isEqual(new Date(selectedDate)?.getTime(), newDate?.getTime())) {
+      const currentDate = new Date(selectedDate);
+      const isNewDateDifferent = 
+        !currentDate || 
+        currentDate.getFullYear() !== newDate.getFullYear() || 
+        currentDate.getMonth() !== newDate.getMonth() || 
+        currentDate.getDate() !== newDate.getDate();
+        
+      if (isNewDateDifferent) {
        setSelectedDate(formatValue(newDate, startDate, endDate))
        onChange?.(
          selectedOptions,
          [
            String(newDate.getFullYear()),
            padZero(newDate.getMonth() + 1),
            padZero(newDate.getDate()),
          ],
          index
        )
      }
    }
  }
📝 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 handleDateComparison = (
newDate: Date | null,
selectedOptions: PickerOptions,
index: number
) => {
if (newDate && isDate(newDate)) {
if (!isEqual(new Date(selectedDate)?.getTime(), newDate?.getTime())) {
setSelectedDate(formatValue(newDate, startDate, endDate))
onChange?.(
selectedOptions,
[
String(newDate.getFullYear()),
padZero(newDate.getMonth() + 1),
padZero(newDate.getDate()),
],
index
)
}
}
}
const handleDateComparison = (
newDate: Date | null,
selectedOptions: PickerOptions,
index: number
) => {
if (newDate && isDate(newDate)) {
const currentDate = new Date(selectedDate);
const isNewDateDifferent =
!currentDate ||
currentDate.getFullYear() !== newDate.getFullYear() ||
currentDate.getMonth() !== newDate.getMonth() ||
currentDate.getDate() !== newDate.getDate();
if (isNewDateDifferent) {
setSelectedDate(formatValue(newDate, startDate, endDate))
onChange?.(
selectedOptions,
[
String(newDate.getFullYear()),
padZero(newDate.getMonth() + 1),
padZero(newDate.getDate()),
],
index
)
}
}
}
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 88-95: src/packages/datepickerview/datepickerview.tsx#L88-L95
Added lines #L88 - L95 were not covered by tests

@xiaoyatong xiaoyatong merged commit 3ce43c6 into jdf2e:feat_v3.x Mar 5, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Target branch 3.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.

2 participants