大多都是有依赖于 Rc-Trigger 基础包, 所以也是需要列入需要研究的工具包
几乎所有的 antd 组件均是依赖了底层的 rc-components 组件, DatePicker 依赖的是 Picker, 不得不说底层实现是真的麻烦, 兼容了多种模式
自定义 panelRender 失效

rc-picker

内置依赖工具包

目录

  1. src
  2. ├── generate # 主要为了兼容多种日期工具包
  3. ├── moment
  4. ├── dayjs
  5. └── dateFns
  6. ├── hooks
  7. ├── useCellClassName # 动态设置单元格 classname
  8. ├── useHoverValue # 动态获取 hover 单元格的值
  9. ├── usePickerInput #
  10. ├── useRangeDisabled # 动态处理单元格是否需要禁用
  11. ├── useRangeViewDates # 动态获取视图显示日期单元格
  12. ├── useTextValueMapping #
  13. └── useValueTexts # 动态设置回填日期
  14. ├── locale # 国际化
  15. ├── panels # 面板
  16. ├── DatePanel # 日期
  17. ├── DatetimePanel # 日期 + 时间
  18. ├── DecadePanel # 日历
  19. ├── MonthPanel # 月份
  20. ├── QuarterPanel # 季度
  21. ├── TimePanel # 时间 基于 ul li 实现
  22. ├── WeekPanel # 周
  23. ├── YearPanel # 年
  24. ├── Header # 通用 Header 包含 上一年 / 上个月 + 下个月 / 下一年操作
  25. └── PanelBody # 通用 Body 渲染 基于 table
  26. ├── PickerPanel # 纯日期面板(通过 picker 类型渲染不同的 Panel)
  27. ├── PickerTrigger # 封装
  28. ├── Picker # PickerTrigger + PickerPanel
  29. ├── RangePicker # 带 Trigger 的日期范围
  30. └── utils

结合目录不难看出已经包含了日常所用的功能, 个别需求需要将 Range 部分进行扩展, 可以参考 PickerPanel 扣出来 RangePanel(TODO)

流程

1222.png
那么对于 Antd 的配置

工具

提供一些在组件内通用的判断 / 渲染工具 如 isSameDate(是否同年同月同日)
日期筛选器 - 图2

  1. getViewDate: 获取当前第一个面板展示时间
  2. getClosingViewDate: 获取第二个面板的展示时间
  3. isSame
    1. isSameDate: 是否为同一天
    2. isSameTime: 是否为同一个时间段
    3. isSameWeek: 是否为同一周
    4. isSameMonth: 是否为同一月
    5. isSameQuarter: 是否为同一个季度

uiUtils

  • elementContains: 判断触发事件的节点是否为其中之一, 用于 isClickOutside, document.activeElement

    Hooks

  1. useMergedState: 用于处理 value & defaultValue 以及提供 set 方法
  2. useCellClassName: 用于处理不同状态下需要添加的 className
  3. useHoverValue: 在Range模式下 hover 的值范围
  4. usePickerInput: 处理 Input 不同的状态
  5. useRangeDisabled: 处理 Range 模式下的日期是否禁选
  6. useTextValueMapping:
  7. useValueTexts:

    日期

    为了更好的兼容更多的第三方日期工具方法, 提供了一个类似适配器模式的工具 在 generateConfig 目录下, 支持 dayjs / moment / date-fns 三种(npm 工具包分析工具: npm-unpkg)

  8. date-fns: Github 提供较为全面通过 JS 操作日期的工具函数, 按照工具功能进行分类

  • getYear
  • getMonth: 0 ~ 11
  • getDay: 获取指定日期在当前周的第几天 0 ~ 6, 0 表示周天
  • getDate: 获取指定日期在当前月的第几天 1 ~ 31
  • getHours: 指定日期的小时数 0 ~ 23(24小时制)
  • getMinutes: 指定日期的分钟数 0 ~ 59(60进制)
  • getSeconds: 指定日期的秒数 0 ~ 59(60进制)
  • getMilliseconds: 指定日期的毫秒数, 指从 1970年 0时0分0秒之后, 0 ~ 999 (1000 ms === 1s)
  • getTime: 返回事件的格林威治时间数值 等于 Date 对象的 valueOf 方法 ```typescript export type GenerateConfig = { // 获取类 / 获取周对应天 —> getDay */ getWeekDay: (value: DateType) => number; / 指定日期的秒 / getSecond: (value: DateType) => number; /** 指定日期分钟数 / getMinute: (value: DateType) => number; / 指定日期小时数 */ getHour: (value: DateType) => number; / 指定月份中指定天 / getDate: (value: DateType) => number; /** 指定月份: 0 ~ 11 / getMonth: (value: DateType) => number; / 指定时间的年份 */ getYear: (value: DateType) => number; / 当前时间 / getNow: () => DateType; /** 指定日期 格式化(YYYY-MM-DD)字符串 / getFixedDate: (fixed: string) => DateType; /* 当前月最后一天 / getEndDate: (value: DateType) => DateType;

    // 设置类 / 设置指定日期的年份 负数等于 subtract */ addYear: (value: DateType, diff: number) => DateType; / 设置指定日期月份的日期 负数同于 subtract / addMonth: (value: DateType, diff: number) => DateType; /** 设置以指定日期为基础的日期 负数同于 subtract / addDate: (value: DateType, diff: number) => DateType; / 设置指定日期的年份 */ setYear: (value: DateType, year: number) => DateType; / 设置指定日期的月份 / setMonth: (value: DateType, month: number) => DateType; /** 设置指定日期的日期 / setDate: (value: DateType, date: number) => DateType; / 设置指定日期的小时 */ setHour: (value: DateType, hour: number) => DateType; / 设置指定日期的分钟 / setMinute: (value: DateType, minute: number) => DateType; /** 设置指定日期的秒数 / setSecond: (value: DateType, second: number) => DateType;

    // 对比类 / 判断 date1 是否在 date2日期前 */ isAfter: (date1: DateType, date2: DateType) => boolean; / 校验是否为有效的日期格式 */ isValidate: (date: DateType) => boolean;

    locale: { / 指定语言环境中一周的第一天 */ getWeekFirstDay: (locale: string) => number; / 指定语言环境中一周第一天在当前月的日期 / getWeekFirstDate: (locale: string, value: DateType) => DateType; /** 获取一年中的第几周 / getWeek: (locale: string, value: DateType) => number;

    /* / format: (locale: string, date: DateType, format: string) => string;

    /* Should only return validate date instance / parse: (locale: string, text: string, formats: string[]) => DateType | null;

    / 获取每周的缩写: 天 一 二 三 四 五 六 */ getShortWeekDays?: (locale: string) => string[]; / 获取每年月份的缩写 全部 */ getShortMonths?: (locale: string) => string[]; }; };

  1. 更多可参考 [moment 语言环境](https://momentjs.com/docs/#/i18n/changing-locale/) 以 moment 为例
  2. ```typescript
  3. // ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
  4. const monthsShort = moment().locale('zh_CN').localeData().monthsShort();
  5. // ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
  6. const months = moment().locale('zh_CN').localeData().months();
  7. // ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  8. const weekdays = moment().locale('zh_CN').localeData().weekdays();
  9. // ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  10. const weekdaysShort = moment().locale('zh_CN').localeData().weekdaysShort();
  11. // ['日', '一', '二', '三', '四', '五', '六']
  12. const weekdaysMin = moment().locale('zh_CN').localeData().weekdaysMin()

其他相关

  1. Intl.DateTimeFormat: 根据语言格式化日期和时间的对象的构造器
  2. Intl: 国际化 API命名空间, 提供精确的字符串对比, 数值格式化 和 日期时间格式化

以上仅仅是关于适配三方日期工具包统一方法, 还包含其他的如 isSameDate isSameTime 等方法, 也正是因为在日期中返回的值范围有些从 0 开始 在渲染时通常为了便于阅读和保持统一会补全两位(leftPad 类似于 padStart)

单元格: 支持自定义渲染 dateRender


依赖

内部依赖了以下工具为基础包

统一共用

名称 描述 备注
Header 统一头部定义
PanelBody 动态计算并生成行 和 列 当 pickMode=’date’ 时展示星期
DatePanel 仅日期
DateTimePanel 日期 + 时间
MonthPanel 月份面板
QuarterPanel 季度面板
TimePanel 时间面板
WeekPanel 星期面板
YearPanel 年份面板

其中每一个 Panel 都包含独立的 Header 和 Body 配置, 不同的 pickMode 展示不同, 有些包含月份操作, 有些不包含, 根据 PickerPanel 结合 pickMode 动态渲染
Trigger

  1. input
  2. suffix
  3. clear
  • getCellDateDisabled: 判断是否添加 disabled 样式, 若选择日期前

    Arco

    TODO

    rc-picker
  1. 支持 RangePanel 纯面板支持

ant-design:

  1. 支持纯面板模式: 若无法支持 则单独组件支持

hoverChange: hover 时是否修改result 结果展示


参考

图图

日期筛选器 - 图3

思路

拆分

  1. 快捷面板
    1. hover: 设置面板区域
    2. click: 点击设置值
  2. 结果区
    1. 开始 ~ 结束 时间
    2. 前置节点: 如果在快捷筛选区内 则展示
  3. 面板区
    1. 自定义面板
    2. 选中 / hover 样式
  4. 输入区
    1. 清空: 1. 关闭面板 2. 清空值 3. 触发 blur
    2. change: 触发后设置面板中的值