---
title: 开发文档
order: 3
category: pro
---

# PisellTimeRangeDisplay 组件开发文档

## 组件信息

**组件名称**：PisellTimeRangeDisplay

**组件版本**：1.0.0

**组件分类**：Pro Components / General

**开发状态**：开发中

**最后更新**：2026-02-04

---

## 组件描述

PisellTimeRangeDisplay 是 Pisell 2.0 组件库中专注于展示**时间区间 + 持续时间**的纯展示型 Pro
组件，用于在不同语言、时区与信息密度下，将开始时间（startAt）与结束时间（endAt）格式化为「时间区间 + 持续时间」的紧凑表达。

**核心价值**：

- 统一产品内所有时间区间的展示规则
- 降低用户对「开始 / 结束 / 持续多久」的理解成本
- 在列表、卡片、详情等不同密度场景下保持一致语义
- 为 Booking / Event / Order 等 Plus 组件提供稳定展示能力

**依赖组件**：PisellDateTimeDisplay（复用其时间/日期/星期格式化能力与类型）

**适用场景**：

- 预约时段、会议时间、营业时间
- 订单/活动起止时间
- 跨天/跨年时间区间展示

---

## 组件需求点罗列

### 功能需求

1. **核心数据**
  - startAt / endAt 为 dayjs 兼容值（Dayjs | string | number）
  - 同一天判定：按用户/展示所在时区的「自然日」判定（dayjs 默认本地时区）

2. **同一天（Same-day）**
  - 默认结构：HH:mm-HH:mm
  - 可选：显示具体日期（格式跟随 dateFormat）
  - 持续时间可参与字段排序，可放在中间（如 time → duration → date → weekday）

3. **跨天（Cross-day）**
  - 自动展开：展示起止日期/时间
  - 支持跨年展示

4. **持续时间（Duration）**
  - 单位：d h m s；示例：365d2h30m23s
  - 是否显示秒可配置，默认否

5. **布局与样式**
  - Horizontal / Vertical
  - 容器：背景、圆角、边框、阴影、padding、gap
  - 时间、日期、星期、持续时长文本：大小、粗细、颜色、行数、宽度
  - 对齐：左/中/右，默认居中

6. **格式化**
  - 时间/日期/星期格式复用 PisellDateTimeDisplay 的 timeFormat、dateFormat、weekdayFormat
  - 持续时长格式：durationFormat.showSeconds，默认 false

7. **字段显隐与排序**
  - 可显隐时间区间、日期、星期、持续时长
  - 可排序四类块：time（时间区间）、date、weekday、duration；同一天不显示 date/weekday 时仍占位参与排序

8. **自适应与小宽度**
  - 无固定断点，使用 CSS 自适应（flex 换行）
  - 同天时间区间拆为「开始时间」与「 - 结束时间」两段，窄时可折行
  - 建议「持续时长先折行」时使用 fieldOrder 将 duration 放最后，如 ['time', 'date', 'weekday', 'duration']

9. **i18n**
  - locale 透传 dayjs，日期/星期复用 PisellDateTimeDisplay 的 locale 行为
  - 未传 locale 时使用 getDayjsLocale()（i18n 当前语言：全局配置 / umi_locale）
  - 持续时长：locale 为 zh 时输出「天/时/分/秒」，否则 d/h/m/s

10. **插槽**
- 本期先跳过插槽功能

---

## 展示格式示例

| 场景     | 示例                                                          | 配置要点                                                                                                                                                      |
|--------|-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| 默认中文   | 10:15 - 10:45 今天 · 30分钟                                     | locale=zh-cn，默认 fieldOrder，showRelativeDay 默认 true                                                                                                        |
| 持续时间在前 | 30m · 10:15 - 10:45 Today                                   | fieldOrder=['duration','time','date']，locale=en                                                                                                           |
| 展示具体日期 | 10:15 - 10:45 Sat, 21 Mar, 2026 · 30m                       | dateFormat={ showRelativeDay: false, order: 'DMY', showYear: true }，weekdayFormat={ trailingComma: true }，fieldOrder=['time','weekday','date','duration'] |
| 跨天     | 10:15 Sat, 22 Jan - 11:30 Sun, 23 Jan · 1d2h30m             | 跨天自动：时间 星期, 日期（无年）                                                                                                                                        |
| 跨年     | 10:15 Sat, 22 Jan 2025 - 11:30 Sun, 23 Jan 2026 · 365d2h30m | 跨年自动带年                                                                                                                                                    |

---

## 组件 API

### Props 接口定义

见当前组件目录下 `types.ts`。要点如下：

- **startAt / endAt**：dayjs 兼容值（Dayjs | string | number），必填
- **textAlign**：'left' | 'center' | 'right'，默认 'center'；无 layout 配置，一行放不下时按块换行
- **fields**：showTimeRange、showDate、showWeekday、showDuration、fieldOrder
- **fieldOrder**：('time' | 'date' | 'weekday' | 'duration')[]，默认 ['time', 'date', 'weekday', 'duration']
  ；持续时间在前用 ['duration', 'time', 'date']
- **timeFormat / dateFormat / weekdayFormat**：与 PisellDateTimeDisplay 同结构，复用类型
- **durationFormat**：{ showSeconds?: boolean }，默认 false
- **showDateForSameDay**：同一天时是否显示具体日期，默认 true（日期默认展示）
- **containerStyle / timeStyle / dateStyle / weekdayStyle / durationStyle**：样式配置
- **locale**：dayjs locale；未传时使用 getDayjsLocale()（i18n 当前语言），日期/星期/持续时长均按 locale i18n（zh
  时持续时长为「天/时/分/秒」）
- **className / style / onClick**：通用属性

### 默认值说明

```
{
  textAlign: 'center',
  fields: {
    showTimeRange: true,
    showDate: true,
    showWeekday: true,
    showDuration: true,
    fieldOrder: ['time', 'duration', 'date', 'weekday']
  },
  timeFormat: { ... },   // 与 PisellDateTimeDisplay 一致
  dateFormat: { ... },
  weekdayFormat: { ... },
  durationFormat: { showSeconds: false },
  showDateForSameDay: true,
}
```

---

## 组件模块拆解

### 文件结构

```
pisellTimeRangeDisplay/
├── index.tsx
├── PisellTimeRangeDisplay.tsx
├── PisellTimeRangeDisplay.less
├── PisellTimeRangeDisplay.test.tsx
├── types.ts
├── components/
│   ├── index.tsx
│   ├── TimeRangeBlock.tsx    # 时间区间（HH:mm-HH:mm 或跨天起止）
│   ├── DateBlock.tsx         # 日期（复用 DateTimeDisplay 逻辑/工具）
│   ├── WeekdayBlock.tsx      # 星期（复用）
│   └── DurationBlock.tsx    # 持续时长（XdXhXmXs）
├── utils/
│   ├── index.ts
│   ├── parseTimeRange.ts     # 解析 startAt/endAt 为 Dayjs，同一天判定
│   ├── formatDuration.ts     # 格式化为 d/h/m/s 字符串
│   └── formatTime.ts / formatDate.ts / formatWeekday.ts  # 复用或委托 pisellDateTimeDisplay/utils
└── docs/
    ├── pisellTimeRangeDisplay.md
    ├── pisellTimeRangeDisplay.$tab-design.md
    ├── pisellTimeRangeDisplay.$tab-dev.md
    └── pisellTimeRangeDisplay.$tab-test.md
```

### 核心模块说明

#### 1. 主组件（PisellTimeRangeDisplay.tsx）

- 用 dayjs 解析 startAt/endAt，得到 start、end（含 locale）
- 判断 isSameDay（同一天）：start 与 end 在本地自然日是否同一天
- 根据 isSameDay 与 showDateForSameDay 决定是否渲染日期/星期块
- 计算 duration（end - start），交给 formatDuration
- 按 fieldOrder 依次渲染 time / date / weekday / duration 四类块；某块显隐由 fields 控制，不显的块占位不渲染内容
- 布局：无 layout 配置；flex 行 + flex-wrap，一行放不下时按块换行，块内不换行，换行后每行按 textAlign 居中/左/右

#### 2. TimeRangeBlock

- 同一天：HH:mm-HH:mm（使用 formatTime 或复用 pisellDateTimeDisplay 的 formatTime）
- 跨天：起止完整日期时间，格式由 timeFormat/dateFormat 决定

#### 3. DateBlock / WeekdayBlock

- 复用 pisellDateTimeDisplay 的 formatDate、formatWeekday 及展示方式（或直接复用其子组件传入单一日期的 dayjs）

#### 4. DurationBlock

- 接收 duration（毫秒或 dayjs diff），formatDuration 输出如 2h30m、1d2h30m23s（showSeconds 可控）

#### 5. utils/formatDuration.ts

- 输入：毫秒数（或 start/end 的 diff）、showSeconds
- 输出：如 "1d2h30m" 或 "1d2h30m23s"

#### 6. utils/parseTimeRange.ts

- 输入：startAt、endAt、locale
- 输出：{ start: Dayjs, end: Dayjs, isSameDay: boolean }（均在本地时区下判断自然日）

---

## 组件实现方案

### 技术选型

- React 18+
- dayjs（日期时间、diff、locale）
- 复用 @pisell/materials 内 PisellDateTimeDisplay 的
  utils（formatTime、formatDate、formatWeekday）及类型定义（TimeFormatConfig、DateFormatConfig、WeekdayFormatConfig 等）
- Less、BEM 类名（如 .pisell-time-range-display-xxx）

### 实现步骤

1. 定义 types.ts（含与 DateTimeDisplay 兼容的格式类型，可 import 部分类型）
2. 实现 utils：parseTimeRange、formatDuration；时间/日期/星期格式化复用 pisellDateTimeDisplay/utils
3. 实现子组件：TimeRangeBlock、DateBlock、WeekdayBlock、DurationBlock
4. 实现主组件：解析 startAt/endAt、计算 isSameDay 与 duration、按 fieldOrder 与 fields 渲染
5. 编写 Less，自适应换行不写死断点
6. index.tsx 导出组件与类型

---

## 组件组成与引用关系

```
┌─────────────────────────────────────────────────────────┐
│   PisellTimeRangeDisplay (主组件)                        │
│   - startAt / endAt 解析与 isSameDay 判定                │
│   - duration 计算                                        │
│   - fieldOrder 与 fields 控制                             │
│   - 布局 textAlign / 样式（按块换行）                      │
└───────────┬─────────────────────────────────────────────┘
            │
            ├──> parseTimeRange(startAt, endAt, locale)
            ├──> formatDuration(ms, showSeconds)
            ├──> formatTime / formatDate / formatWeekday (复用 pisellDateTimeDisplay/utils)
            │
            ├──> TimeRangeBlock (时间区间)
            ├──> DateBlock (日期)
            ├──> WeekdayBlock (星期)
            └──> DurationBlock (持续时长)
```

### 依赖关系

- **外部**：React、dayjs、dayjs/locale/*
- **内部**：types.ts、utils、components
- **复用**：PisellDateTimeDisplay 的 utils（formatTime、formatDate、formatWeekday）及类型

---

## 扩展性设计

- 后续可增加 timezone 属性（dayjs-timezone）以支持指定时区自然日判定
- 插槽（renderTimeRange、renderDuration 等）本期不做

---

## 开发注意事项

- 严格按 create-component-rule.mdc：TypeScript、命名导出、Less 类名前缀、不设 font-family、覆盖 antd 用 pisell-lowcode-xxx
- 同一天判定仅基于 dayjs 默认本地时区，不引入额外时区依赖
- 列表/循环场景下 key 稳定，避免索引 key
