---
nav:
  title: 组件
  order: 1
group:
  title: General
  order: 1
title: PisellPhone
order: 1
category: pro
---

# PisellPhone 电话号码组件

电话号码输入/展示组件，支持国家码选择、自动格式化、格式校验和移动端拨号功能。

## 何时使用

- 需要输入电话号码的场景
- 需要支持多国电话号码
- 需要自动格式化电话号码
- 需要移动端拨号功能
- 需要号码脱敏显示

## 代码演示

### 基础用法

默认为中国手机号输入。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return <PisellPhone placeholder="请输入手机号" />;
};
```

### 国家码选择

显示国家码选择器，支持24个常见国家。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      showCountrySelector
      placeholder="请输入电话号码"
    />
  );
};
```

### 过滤显示国家

只显示指定的国家。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      showCountrySelector
      availableCountryCodes={['+86', '+852', '+1', '+44']}
      placeholder="请输入电话号码"
    />
  );
};
```

### 常用国家置顶

常用国家显示在列表顶部。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      showCountrySelector
      commonCountryCodes={['+86', '+1']}
      placeholder="请输入电话号码"
    />
  );
};
```

### 只读态 - 格式化显示

展示格式化的电话号码。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      mode="read"
      value="13800000000"
      countryCode="+86"
    />
  );
};
```

### 只读态 - 拨号功能

移动端可点击拨号。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      mode="read"
      value="13800000000"
      countryCode="+86"
      enableDial
      showDialIcon
      onDial={(phone) => {
        console.log('拨号:', phone);
      }}
    />
  );
};
```

### 号码脱敏

隐私保护，显示脱敏后的号码。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      {/* 中间脱敏 */}
      <PisellPhone
        mode="read"
        value="13800000000"
        enableMasking
        maskPattern="middle"
      />

      {/* 末尾脱敏 */}
      <PisellPhone
        mode="read"
        value="13800000000"
        enableMasking
        maskPattern="last"
      />
    </div>
  );
};
```

### 必填校验

设置必填项。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      placeholder="请输入手机号（必填）"
      required
      validateTrigger="onBlur"
    />
  );
};
```

### 格式校验

自动校验电话号码格式。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      placeholder="请输入手机号"
      countryCode="+86"
      validateFormat
      validateTrigger="onChange"
    />
  );
};
```

### 自定义校验

添加自定义校验逻辑。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <PisellPhone
      placeholder="请输入手机号"
      customValidator={(phone, countryCode) => {
        if (countryCode === '+86' && !phone.startsWith('1')) {
          return '中国手机号必须以1开头';
        }
        return true;
      }}
      validateTrigger="onChange"
    />
  );
};
```

### 多国号码

展示不同国家的号码格式。

```tsx
import { PisellPhone } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      <PisellPhone mode="read" value="13800000000" countryCode="+86" />
      <PisellPhone mode="read" value="5551234567" countryCode="+1" />
      <PisellPhone mode="read" value="2012345678" countryCode="+44" />
      <PisellPhone mode="read" value="12345678" countryCode="+852" />
    </div>
  );
};
```

## API

### Props

| 参数                    | 说明          | 类型                                                          | 默认值         |
|-----------------------|-------------|-------------------------------------------------------------|-------------|
| mode                  | 状态模式        | `'read' \| 'edit'`                                          | `'edit'`    |
| disabled              | 是否禁用        | `boolean`                                                   | `false`     |
| value                 | 电话号码（不含国家码） | `string`                                                    | -           |
| defaultValue          | 默认值         | `string`                                                    | -           |
| countryCode           | 当前国家码       | `string`                                                    | `'+86'`     |
| defaultCountryCode    | 默认国家码       | `string`                                                    | `'+86'`     |
| showCountrySelector   | 显示国家码选择器    | `boolean`                                                   | `true`      |
| availableCountryCodes | 可用国家码列表（过滤） | `string[]`                                                  | 全部24个       |
| commonCountryCodes    | 常用国家码（置顶）   | `string[]`                                                  | -           |
| countryCodes          | 完全自定义国家码列表  | `CountryCode[]`                                             | 预设24个       |
| onCountryCodeChange   | 国家码变更回调     | `(code: string) => void`                                    | -           |
| autoFormat            | 是否自动格式化     | `boolean`                                                   | `true`      |
| formatRule            | 格式化规则       | `'mobile' \| 'landline' \| 'auto'`                          | `'auto'`    |
| separator             | 格式化分隔符      | `string`                                                    | `' '`       |
| enableDial            | 启用拨号（移动端）   | `boolean`                                                   | `true`      |
| showDialIcon          | 显示拨号图标      | `boolean`                                                   | `false`     |
| onDial                | 拨号回调        | `(phone: string) => void`                                   | -           |
| enableMasking         | 启用脱敏（只读态）   | `boolean`                                                   | `false`     |
| maskPattern           | 脱敏模式        | `'middle' \| 'last' \| 'custom'`                            | `'middle'`  |
| customMask            | 自定义脱敏函数     | `(phone: string) => string`                                 | -           |
| showFlag              | 显示国旗图标（只读态） | `boolean`                                                   | `true`      |
| placeholder           | 占位文本        | `string`                                                    | `'请输入电话号码'` |
| required              | 是否必填        | `boolean`                                                   | `false`     |
| validateFormat        | 是否校验格式      | `boolean`                                                   | `true`      |
| customValidator       | 自定义校验函数     | `(phone: string, countryCode: string) => boolean \| string` | -           |
| validateTrigger       | 校验触发时机      | `'onChange' \| 'onBlur' \| 'both'`                          | `'onBlur'`  |

### CountryCode 类型

```typescript
interface CountryCode {
  code: string;           // 国家码，如 '+86'
  name: string;           // 国家名称，如 '中国'
  flag: string;           // 国旗 emoji，如 '🇨🇳'
  format?: string;        // 号码格式
  maxLength: number;      // 最大长度
  pattern: RegExp;        // 校验正则
}
```

## 核心功能说明

### 国家码配置系统

**预设24个常见国家**：

- 🇨🇳 中国、🇭🇰 香港、🇲🇴 澳门、🇹🇼 台湾、🇯🇵 日本、🇰🇷 韩国、🇸🇬 新加坡...等

**4种配置方式**：

1. **默认**：显示全部24个
   ```
   <PisellPhone />
   ```

2. **过滤**：只显示指定国家
   ```
   <PisellPhone availableCountryCodes={['+86', '+1']} />
   ```

3. **置顶**：常用国家置顶
   ```
   <PisellPhone commonCountryCodes={['+86', '+1']} />
   ```

4. **自定义**：完全覆盖
   ```
   <PisellPhone countryCodes={customList} />
   ```

### 自动格式化

根据国家码自动应用不同格式：

- 🇨🇳 中国：138 0000 0000
- 🇺🇸 美国：(555) 123-4567
- 🇬🇧 英国：1234 567 8900

### 格式校验

自动校验长度和格式：

- 🇨🇳 中国：11位，1开头
- 🇺🇸 美国：10位
- 校验失败自动提示

### 拨号功能

移动端可点击拨号：

- 自动检测移动设备
- 使用 tel: 协议
- 号码带下划线可点击样式

### 号码脱敏

保护用户隐私：

- 中间脱敏：138****0000
- 末尾脱敏：1380000****

## 常见问题

### 如何只显示中国和美国？

```
<PisellPhone availableCountryCodes={['+86', '+1']} />
```

### 如何禁用自动格式化？

```
<PisellPhone autoFormat={false} />
```

### 如何隐藏国家码选择器？

```
<PisellPhone showCountrySelector={false} countryCode="+86" />
```

### 如何监听国家码变化？

```
<PisellPhone
  onCountryCodeChange={(code) => {
    console.log('国家码变更为:', code);
  }}
/>
```

### 如何自定义脱敏规则？

```
<PisellPhone
  mode="read"
  enableMasking
  maskPattern="custom"
  customMask={(phone) => {
    // 只显示前3位
    return phone.slice(0, 3) + '*******';
  }}
/>
```

## 注意事项

1. **只保留数字**：输入时自动移除非数字字符
2. **格式化不影响值**：onChange 回调中的 value 是格式化后的
3. **拨号仅移动端**：PC 端不显示拨号功能
4. **国家码与号码分离**：value 不包含国家码
5. **maxLength 自动设置**：根据国家码自动调整

## 设计规范

继承 Input 组件的设计规范（基于 Figma）：

- 高度：48px
- 圆角：8px
- 边框：1px solid #D0D5DD
- 内边距：12px 16px

## 相关组件

- [PisellSingleLineText](../pisellSingleLineText/pisellSingleLineText.md) - 单行文本组件
- [PisellLongText](../pisellLongText/pisellLongText.md) - 长文本组件
- [PisellEmail](../pisellEmail/pisellEmail.md) - 邮箱地址组件
- [PisellUrl](../pisellUrl/pisellUrl.md) - URL 链接组件
