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

﻿# PisellRating 组件开发文档

## 1 组件信息

### 1.1 基本信息

- **组件名称**：PisellRating
- **组件版本**：V1.0.0
- **组件分类**：表单输入 / 数据展示
- **开发状态**：已完成
- **最后更新**：2026-01-26
- **设计稿链接
  **：https://www.figma.com/design/pM8Ho6d7kCMv9vIBvFHUlj/Pisell-2.0-Component-Library?node-id=12756-77363&m=dev

### 1.2 组件描述

PisellRating 是基于 Ant Design Rate 组件开发的评分组件，支持只读、编辑、禁用三种状态模式。组件使用星级图标提供直观的评分交互体验，支持半星评分、自定义图标、评分描述等功能。

## 2 需求点罗列

### 2.1 功能需求

#### 核心功能

- ✅ 支持三种状态：只读态、编辑态、禁用态
- ✅ 支持受控和非受控两种使用模式
- ✅ 基于 Ant Design Rate 组件封装
- ✅ 使用 @pisell/utils 的 getDisplayState 辅助函数

#### 评分特有功能

- ✅ 星级评分（默认 5 星）
- ✅ 半星评分（allowHalf）
- ✅ 清除评分（allowClear）
- ✅ 自定义图标（character）
- ✅ 评分描述（tooltips）

#### 展示功能

- ✅ 显示数值文本（showValue）
- ✅ 显示评分人数（showCount）
- ✅ 自定义星星尺寸
- ✅ 自定义星星颜色

#### 交互功能

- ✅ 点击评分
- ✅ 悬停预览
- ✅ 键盘导航（左右箭头）
- ✅ 悬停回调

### 2.2 非功能需求

- ✅ TypeScript 类型定义完整
- ✅ 代码注释使用 JSDoc 规范
- ✅ 性能优化（React.memo）
- ✅ 无障碍访问支持（ARIA）

## 3 组件 API

### 3.1 Props 定义

#### 核心属性

| 属性名          | 类型                      | 默认值    | 必填 | 说明         |
|--------------|-------------------------|--------|----|------------|
| mode         | 'read' \| 'edit'        | 'edit' | 否  | 显示模式       |
| disabled     | boolean                 | false  | 否  | 是否禁用       |
| value        | number                  | -      | 否  | 当前评分值（受控）  |
| defaultValue | number                  | -      | 否  | 默认评分值（非受控） |
| onChange     | (value: number) => void | -      | 否  | 评分变更回调     |

#### 评分配置

| 属性名        | 类型        | 默认值        | 必填 | 说明            |
|------------|-----------|------------|----|---------------|
| count      | number    | 5          | 否  | 星星数量          |
| max        | number    | 5          | 否  | 最大评分值（同count） |
| allowHalf  | boolean   | false      | 否  | 是否允许半星评分      |
| allowClear | boolean   | true       | 否  | 是否允许清除评分      |
| character  | ReactNode | StarFilled | 否  | 自定义字符         |
| tooltips   | string[]  | -          | 否  | 评分描述文本数组      |

#### 展示配置

| 属性名             | 类型      | 默认值     | 必填 | 说明        |
|-----------------|---------|---------|----|-----------|
| showValue       | boolean | false   | 否  | 是否显示数值文本  |
| showCount       | boolean | false   | 否  | 是否显示评分人数  |
| reviewCount     | number  | -       | 否  | 评分人数      |
| size            | number  | 20      | 否  | 星星尺寸（px）  |
| color           | string  | #fadb14 | 否  | 星星颜色（已选中） |
| unselectedColor | string  | #d9d9d9 | 否  | 星星颜色（未选中） |

#### 事件回调

| 属性名           | 类型                      | 说明        |
|---------------|-------------------------|-----------|
| onHoverChange | (value: number) => void | 悬停评分值变化回调 |
| onFocus       | () => void              | 聚焦回调      |
| onBlur        | () => void              | 失焦回调      |

#### 样式类名

| 属性名        | 类型                  | 说明      |
|------------|---------------------|---------|
| className  | string              | 自定义类名   |
| style      | React.CSSProperties | 自定义样式   |
| aria-label | string              | ARIA 标签 |
| id         | string              | HTML ID |

## 4 组件模块拆解

### 4.1 目录结构

```
pisellRating/
├── index.tsx                        # 导出文件
├── PisellRating.tsx                 # 组件主文件（单文件实现）
├── PisellRating.less                # 样式文件
├── PisellRating.test.tsx            # 单元测试
├── PisellRating.stories.tsx         # Storybook 故事
├── types.ts                         # 类型定义
└── docs/                            # 文档
    ├── pisellRating.md                      # 使用文档
    ├── pisellRating.$tab-design.md          # 设计文档
    ├── pisellRating.$tab-dev.md             # 开发文档（本文档）
    └── pisellRating.$tab-test.md            # 测试文档
```

**注意**：PisellRating 采用单文件实现，不拆分子组件，因为逻辑较简单，且主要依赖 Ant Design Rate 组件。

### 4.2 组件职责

#### 主组件（PisellRating.tsx）

- 统筹组件渲染逻辑
- 使用 getDisplayState 计算显示状态
- 将 mode 和 disabled 映射到 Rate 组件的 disabled 属性
- 处理额外的展示元素（数值文本、评分人数）

## 5 组件实现方案

### 5.1 技术栈

- React 18+
- TypeScript
- Ant Design 5.x（Rate 组件）
- Less（样式）
- 公共逻辑来自 @pisell/utils（getDisplayState）

### 5.2 核心实现

#### 5.2.1 主组件实现

```
import React from 'react';
import { Rate } from 'antd';
import { getDisplayState } from '@pisell/utils';
import type { PisellRatingProps } from './types';
import './PisellRating.less';

/**
 * PisellRating 评分组件
 */
export const PisellRating: React.FC<PisellRatingProps> = (props) => {
  const {
    mode = 'edit',
    disabled = false,
    value,
    defaultValue,
    onChange,
    count,
    max = count ?? 5,
    allowHalf = false,
    allowClear = true,
    character,
    tooltips,
    showValue = false,
    showCount = false,
    reviewCount,
    size = 20,
    color = '#fadb14',
    unselectedColor = '#d9d9d9',
    onHoverChange,
    onFocus,
    onBlur,
    className,
    style,
    'aria-label': ariaLabel,
    id,
  } = props;

  // 计算显示状态
  const displayState = getDisplayState(mode, disabled);

  // 只读态和禁用态都映射为 disabled
  const isReadOnly = displayState === 'read';
  const isDisabled = displayState === 'disabled';

  // 组合样式
  const rateStyle: React.CSSProperties = {
    fontSize: size,
    color: color,
    ...style,
  };

  return (
    <div
      className={`pisell-rating pisell-rating-${displayState} ${className || ''}`}
      id={id}
    >
      <Rate
        value={value}
        defaultValue={defaultValue}
        onChange={onChange}
        onHoverChange={onHoverChange}
        onFocus={onFocus}
        onBlur={onBlur}
        count={max}
        allowHalf={allowHalf}
        allowClear={allowClear}
        character={character}
        tooltips={tooltips}
        disabled={isReadOnly || isDisabled}
        style={rateStyle}
        aria-label={ariaLabel}
      />
      
      {/* 显示数值文本 */}
      {showValue && value !== undefined && (
        <span className="pisell-rating-value" style={{ marginLeft: 8 }}>
          {value.toFixed(allowHalf ? 1 : 0)}
        </span>
      )}
      
      {/* 显示评分人数 */}
      {showCount && reviewCount !== undefined && (
        <span className="pisell-rating-count" style={{ marginLeft: 8, color: '#999' }}>
          ({reviewCount} 人评价)
        </span>
      )}
    </div>
  );
};

// 性能优化：使用 memo 避免不必要的重渲染
export default React.memo(PisellRating, (prevProps, nextProps) => {
  return (
    prevProps.value === nextProps.value &&
    prevProps.mode === nextProps.mode &&
    prevProps.disabled === nextProps.disabled
  );
});
```

#### 5.2.2 样式实现

```
.pisell-rating {
  display: inline-flex;
  align-items: center;
  
  &-value {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.85);
  }
  
  &-count {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.45);
  }
  
  // 禁用态
  &-disabled {
    opacity: 0.4;
    cursor: not-allowed;
    
    .ant-rate {
      pointer-events: none;
    }
  }
  
  // 只读态
  &-read {
    .ant-rate {
      pointer-events: none;
    }
  }
}
```

## 6 组件组成与引用

### 6.1 依赖的外部组件和工具

| 组件/工具           | 来源            | 用途       |
|-----------------|---------------|----------|
| Rate            | antd          | 星级评分组件   |
| getDisplayState | @pisell/utils | 状态计算（复用） |

### 6.2 组件结构图

```
PisellRating（单文件实现）
├── Rate (antd) - 星级评分
├── span - 数值文本（可选）
└── span - 评分人数（可选）
```

### 6.3 与 PisellNumber 的关系

PisellRating 虽然概念上基于 PisellNumber，但在实现上是独立的：

**继承的概念**：

- 数值管理（value/onChange）
- 三种状态模式
- 受控/非受控模式

**不同之处**：

- 不使用 InputNumber，而是使用 Rate 组件
- 不需要拆分子组件（EditView/ReadOnlyView）
- 交互方式完全不同（点击图标 vs 输入数字）

## 7 扩展性设计

### 7.1 通用性

- 基于成熟的 Ant Design Rate 组件
- 支持自定义图标和配置
- 不绑定业务逻辑
- 支持自定义样式

### 7.2 可扩展点

1. **自定义图标**：通过 character 配置不同图标（星星/爱心/笑脸等）
2. **自定义星星数量**：通过 max 配置（3星/5星/10星等）
3. **自定义样式**：通过 size、color 配置
4. **评分描述**：通过 tooltips 配置各评分级别的文本

## 8 性能优化

### 8.1 优化策略

1. **React.memo**：避免不必要的重渲染
2. **单文件实现**：减少组件层级和文件数量
3. **直接使用 Rate**：充分利用 Ant Design 优化

### 8.2 性能指标

- 首次渲染：< 16ms
- 重渲染：< 8ms
- 内存占用：< 500KB

## 9 开发注意事项

### 9.1 代码规范

1. 使用 TypeScript 严格模式
2. 所有函数添加 JSDoc 注释
3. 遵循 ESLint 和 Prettier 规则
4. 复用 @pisell/utils 中的公共逻辑

### 9.2 关键实现点

1. **状态映射**：
  - read mode → Rate disabled=true
  - disabled → Rate disabled=true
  - edit mode → Rate disabled=false

2. **值的精度**：
  - allowHalf=false：整数值（1, 2, 3, 4, 5）
  - allowHalf=true：0.5 倍数（0.5, 1, 1.5, 2, ..., 5）

3. **数值文本显示**：
  - allowHalf=true：显示一位小数（4.5）
  - allowHalf=false：显示整数（4）

4. **count vs max**：
  - count 和 max 作用相同（星星数量）
  - 优先使用 max（与 PisellNumber 保持一致）
  - count 用于向后兼容

### 9.3 与 Ant Design Rate 的映射

| PisellRating Props     | Ant Design Rate Props | 说明                  |
|------------------------|-----------------------|---------------------|
| mode='read' / disabled | disabled=true         | 只读态和禁用态都使用 disabled |
| max / count            | count                 | 星星数量                |
| onChange               | onChange              | 评分变更回调              |
| onHoverChange          | onHoverChange         | 悬停回调                |
| tooltips               | tooltips              | 评分描述                |

## 10 总结

PisellRating 是一个简洁高效的评分组件，直接基于 Ant Design Rate 组件实现，不需要复杂的状态管理和子组件拆分。组件通过简单的
props 映射，将三态模式（只读/编辑/禁用）映射到 Rate 的 disabled 属性，同时提供额外的展示功能（数值文本、评分人数）。

**核心优势**：

- ✅ 基于成熟的 Ant Design Rate 组件
- ✅ 简洁的单文件实现
- ✅ 完整的交互体验（点击/悬停/键盘）
- ✅ 灵活的自定义配置（图标/颜色/尺寸）
- ✅ 与 Pisell 组件体系一致的 API 风格（mode/disabled）
- ✅ 支持半星评分和评分描述
