---
title: 设计文档
order: 2
category: pro
---

﻿# PisellCurrency 组件设计文档

## 组件概述

PisellCurrency 是基于 PisellNumber 派生的货币组件，专门用于处理价格、费用、金额等货币相关的数值场景。它继承了 PisellNumber
的所有基础能力，并在此基础上添加了货币符号、千分位分隔等货币特有的语义化扩展。

**设计原则**：

- 基于 PisellNumber 组件进行扩展
- 使用 Ant Design InputNumber 作为底层控件
- 参考 PisellSingleLineText 架构，采用三态视图
- 使用 @pisell/utils 中的公共状态管理逻辑
- 符合财务规范的格式化展示

**Figma 设计链接**：
https://www.figma.com/design/pM8Ho6d7kCMv9vIBvFHUlj/Pisell-2.0-Component-Library?node-id=12754-76304&m=dev

---

## 核心功能

### 1. 继承 PisellNumber 的基础能力

- 三种交互状态（只读/编辑/禁用）
- 数值校验（范围、精度）
- 受控和非受控模式
- 筛选与排序能力

### 2. 货币特有功能

**货币符号**：

- 支持自定义货币符号（¥、$、€、£ 等）
- 符号位置可配置（前置或后置）
- 可选择是否显示符号

**千分位分隔符**：

- 默认启用千分位分隔符
- 符合财务规范的格式化展示
- 例：`¥1,234.56`

**精度控制**：

- 默认保留 2 位小数（符合货币规范）
- 可自定义精度

**负数处理**：

- 支持负数输入（如退款、负债）
- 可配置是否允许负数

---

## 接口定义

### Props 属性

继承 PisellNumber 的所有属性，并扩展以下货币特有属性：

| 属性名                  | 类型                                | 默认值        | 说明                        |
|----------------------|-----------------------------------|------------|---------------------------|
| **继承自 PisellNumber** | -                                 | -          | -                         |
| `mode`               | `'read' \| 'edit'`                | `'edit'`   | 显示模式                      |
| `disabled`           | `boolean`                         | `false`    | 是否禁用                      |
| `value`              | `number \| null`                  | -          | 当前值（受控）                   |
| `defaultValue`       | `number \| null`                  | -          | 默认值（非受控）                  |
| `onChange`           | `(value: number \| null) => void` | -          | 值变更回调                     |
| `min`                | `number`                          | -          | 最小值                       |
| `max`                | `number`                          | -          | 最大值                       |
| `precision`          | `number`                          | `2`        | 小数精度（货币默认2位）              |
| **货币特有属性**           | -                                 | -          | -                         |
| `currencySymbol`     | `string`                          | `'¥'`      | 货币符号                      |
| `symbolPosition`     | `'before' \| 'after'`             | `'before'` | 符号位置（前置/后置）               |
| `showSymbol`         | `boolean`                         | `true`     | 是否显示货币符号                  |
| `useGrouping`        | `boolean`                         | `true`     | 是否使用千分位分隔符                |
| `allowNegative`      | `boolean`                         | `true`     | 是否允许负数                    |
| `currencyCode`       | `string`                          | -          | 货币代码（如 'CNY', 'USD'）用于国际化 |

---

## 组件架构

### 文件结构

```
pisellCurrency/
├── index.tsx                        # 组件导出
├── PisellCurrency.tsx               # 组件主入口
├── PisellCurrency.less              # 组件样式
├── PisellCurrency.test.tsx          # 单元测试
├── PisellCurrency.stories.tsx       # Storybook 示例
├── types.ts                         # TypeScript 类型定义
├── components/                      # 子组件
│   ├── ReadOnlyView.tsx            # 只读态视图
│   ├── EditView.tsx                # 编辑态视图
│   └── DisabledView.tsx            # 禁用态视图
├── utils/                           # 工具函数
│   ├── index.ts                    # 工具函数导出
│   ├── currencyFormatter.ts        # 货币格式化
│   └── currencyValidator.ts        # 货币验证
└── docs/                            # 文档
    ├── pisellCurrency.md           # 组件使用文档
    ├── pisellCurrency.$tab-design.md   # 设计文档（本文件）
    ├── pisellCurrency.$tab-dev.md      # 开发文档
    └── pisellCurrency.$tab-test.md     # 测试文档
```

### 技术实现

**格式化系统**：

```
数值 → 基础数值格式化（精度、取整）→ 千分位分隔 → 添加货币符号 → 最终显示
```

**示例**：

```
输入值: 6999.99
处理流程:
1. 精度处理: 6999.99 (precision: 2)
2. 千分位: 6,999.99 (useGrouping: true)
3. 添加符号: ¥6,999.99 (currencySymbol: '¥', symbolPosition: 'before')
```

---

## 使用示例

### 1. 基础货币显示

```
import { PisellCurrency } from '@pisell/components';

// 人民币
<PisellCurrency
  value={6999.99}
  currencySymbol="¥"
/>
// 显示: ¥6,999.99

// 美元
<PisellCurrency
  value={1234.56}
  currencySymbol="$"
/>
// 显示: $1,234.56

// 欧元（后置符号）
<PisellCurrency
  value={999.99}
  currencySymbol="€"
  symbolPosition="after"
/>
// 显示: 999.99€
```

### 2. 价格表管理

```
import { PisellCurrency } from '@pisell/components';
import { Table } from 'antd';

const productData = [
  { id: 1, name: '笔记本电脑', price: 6999.99 },
  { id: 2, name: '无线鼠标', price: 129.5 },
];

function PriceManagementTable() {
  const columns = [
    { title: '商品名称', dataIndex: 'name' },
    {
      title: '单价',
      dataIndex: 'price',
      render: (value: number) => (
        <PisellCurrency
          mode="read"
          value={value}
          currencySymbol="¥"
        />
      ),
      sorter: (a, b) => a.price - b.price,
    },
  ];

  return <Table dataSource={productData} columns={columns} />;
}
```

### 3. 表单中编辑价格

```
function PriceEditForm() {
  const [price, setPrice] = useState<number>(0);

  return (
    <Form>
      <Form.Item label="商品价格" required>
        <PisellCurrency
          value={price}
          onChange={setPrice}
          currencySymbol="¥"
          min={0}
          max={999999.99}
          placeholder="请输入价格"
          required
          validateTrigger="both"
        />
      </Form.Item>
    </Form>
  );
}
```

### 4. 不显示货币符号（仅格式化）

```
<PisellCurrency
  value={1234.56}
  showSymbol={false}
  useGrouping
/>
// 显示: 1,234.56
```

### 5. 禁止负数（如商品价格）

```
<PisellCurrency
  value={price}
  onChange={setPrice}
  currencySymbol="¥"
  allowNegative={false}
  min={0}
/>
```

### 6. 允许负数（如退款金额）

```
<PisellCurrency
  value={refundAmount}
  onChange={setRefundAmount}
  currencySymbol="¥"
  allowNegative
  max={0}
/>
// 可以输入负数，如：-¥150.00
```

---

## 格式化规则

### 货币符号位置

**前置（默认）**：

```
¥1,234.56
$999.99
```

**后置**：

```
1,234.56€
999.99₽
```

### 千分位分隔符

```
无千分位: 1234567.89
有千分位: 1,234,567.89
```

### 精度处理

```
输入: 1234.567
precision: 2 → 1,234.57 (四舍五入)
precision: 0 → 1,235 (整数)
precision: 3 → 1,234.567
```

---

## 视觉规范

### 只读态

- 货币符号和数值整体作为文本展示
- 默认颜色：`rgba(0, 0, 0, 0.85)`
- 支持自定义字体样式

### 编辑态

- 使用 InputNumber 组件
- 货币符号可以通过 `addonBefore` 或 `addonAfter` 显示
- 输入时自动格式化（千分位）

### 禁用态

- 40% 透明度
- 背景色：`#f5f5f5`

---

## 国际化支持

### 货币代码（可选）

```
<PisellCurrency
  value={1234.56}
  currencySymbol="$"
  currencyCode="USD"
/>

<PisellCurrency
  value={1234.56}
  currencySymbol="¥"
  currencyCode="CNY"
/>
```

### 常用货币符号

| 货币  | 符号 | 代码  | 位置     |
|-----|----|-----|--------|
| 人民币 | ¥  | CNY | before |
| 美元  | $  | USD | before |
| 欧元  | €  | EUR | after  |
| 英镑  | £  | GBP | before |
| 日元  | ¥  | JPY | before |
| 韩元  | ₩  | KRW | before |
| 卢布  | ₽  | RUB | after  |

---

## 性能优化

1. 继承 PisellNumber 的优化策略
2. 格式化函数使用 useMemo 缓存
3. 大量数据表格中使用 React.memo

---

## 最佳实践

1. **语义正确**：所有金额、价格场景必须使用 PisellCurrency，不要用 PisellNumber
2. **精度设置**：货币默认 2 位小数，除非特殊需求（如虚拟货币可能更多位）
3. **范围限制**：合理设置 min/max，防止无效金额提交
4. **负数场景**：明确业务场景是否允许负数（价格不允许，退款允许）
