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

# PisellLongText 长文本组件

多行文本输入/展示组件，支持只读、编辑、禁用三种状态模式，提供展开/折叠功能、自动高度调整和完整的校验框架。

## 何时使用

- 需要多行文本输入的场景（产品描述、用户评论、备注等）
- 需要展示较长的文本内容
- 需要展开/折叠功能来优化空间利用
- 需要自动调整输入框高度
- 需要表单校验功能

## 代码演示

### 基础用法

最简单的用法，默认为3行的多行输入框。

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

export default () => {
  return <PisellLongText placeholder="请输入内容" />;
};
```

### 受控模式

通过 `value` 和 `onChange` 控制输入值。

```tsx
import { PisellLongText } from '@pisell/materials';
import { useState } from 'react';

export default () => {
  const [value, setValue] = useState('');

  return (
    <PisellLongText
      value={value}
      onChange={(newValue) => setValue(newValue)}
      placeholder="请输入产品描述"
      rows={4}
    />
  );
};
```

### 只读态

使用 `mode="read"` 展示多行文本内容。

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

export default () => {
  return (
    <PisellLongText
      mode="read"
      value="产品名称：示例产品
产品描述：这是一个优质的产品
产品特性：功能强大、简单易用
使用说明：按照说明书操作"
    />
  );
};
```

### 展开/折叠功能（核心）

只读态下，超出指定行数时显示展开按钮。

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

export default () => {
  const longText = `第1行：产品介绍
第2行：产品特性说明
第3行：使用方法详解
第4行：注意事项提醒
第5行：售后服务承诺
第6行：联系方式`;

  return (
    <PisellLongText
      mode="read"
      value={longText}
      maxLines={3}
      enableExpand
      expandText="查看更多"
      collapseText="收起"
    />
  );
};
```

### 自动高度调整

编辑态下，根据内容自动调整输入框高度。

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

export default () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      {/* 完全自动 */}
      <PisellLongText
        autoSize
        placeholder="输入内容，高度完全自动调整"
      />

      {/* 限定范围 */}
      <PisellLongText
        autoSize={{ minRows: 3, maxRows: 8 }}
        placeholder="高度在3-8行之间自动调整"
      />

      {/* 使用 minRows 和 maxRows */}
      <PisellLongText
        minRows={3}
        maxRows={6}
        placeholder="设置 minRows 和 maxRows 自动生效"
      />
    </div>
  );
};
```

### 字数统计

显示当前输入的字符数。

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

export default () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      {/* 编辑态字数统计 */}
      <PisellLongText
        placeholder="请输入内容"
        maxLength={500}
        showCount
      />

      {/* 只读态字数统计 */}
      <PisellLongText
        mode="read"
        value="这是一段测试文本\n包含多行内容"
        showWordCount
      />
    </div>
  );
};
```

### 必填校验

通过 `required` 属性设置必填项。

```tsx
import { PisellLongText } from '@pisell/materials';
import { useState } from 'react';

export default () => {
  const [value, setValue] = useState('');

  return (
    <PisellLongText
      value={value}
      onChange={setValue}
      required
      placeholder="请输入内容（必填）"
      validateTrigger="onBlur"
    />
  );
};
```

### 长度校验

限制输入的最小和最大长度。

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

export default () => {
  return (
    <PisellLongText
      placeholder="请输入 20-500 个字符"
      minLength={20}
      maxLength={500}
      showCount
      validateTrigger="onChange"
    />
  );
};
```

### 自定义校验（段落数量限制）

使用自定义校验函数限制段落数量。

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

export default () => {
  const validator = (value: string) => {
    const lines = value.split('\n').filter((l) => l.trim());
    if (lines.length > 10) {
      return '内容不能超过10段';
    }
    return true;
  };

  return (
    <PisellLongText
      placeholder="请输入内容（最多10段）"
      validator={validator}
      validateTrigger="onChange"
    />
  );
};
```

### 回车事件（支持 Ctrl+Enter）

监听回车键，支持判断是否按下 Ctrl。

```tsx
import { PisellLongText } from '@pisell/materials';
import { message } from 'antd';

export default () => {
  const handlePressEnter = (e: React.KeyboardEvent) => {
    if (e.ctrlKey) {
      message.success('Ctrl+Enter 提交');
    } else {
      message.info('Enter 换行');
    }
  };

  return (
    <PisellLongText
      placeholder="Enter 换行，Ctrl+Enter 提交"
      onPressEnter={handlePressEnter}
    />
  );
};
```

### 展开回调

监听展开/收起状态变化。

```tsx
import { PisellLongText } from '@pisell/materials';
import { useState } from 'react';

export default () => {
  const [expanded, setExpanded] = useState(false);

  return (
    <div>
      <PisellLongText
        mode="read"
        value="第1行\n第2行\n第3行\n第4行\n第5行"
        maxLines={3}
        onExpand={(isExpanded) => {
          setExpanded(isExpanded);
          console.log('展开状态:', isExpanded);
        }}
      />
      <p style={{ marginTop: '8px', color: '#667085' }}>
        当前状态：{expanded ? '已展开' : '已收起'}
      </p>
    </div>
  );
};
```

### 组合使用

组合多种功能使用。

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

export default () => {
  return (
    <PisellLongText
      placeholder="请输入产品详细描述"
      autoSize={{ minRows: 4, maxRows: 12 }}
      maxLength={1000}
      showCount
      allowClear
      required
      minLength={50}
      validateTrigger="both"
    />
  );
};
```

## API

### Props

| 参数                   | 说明            | 类型                                                  | 默认值         |
|----------------------|---------------|-----------------------------------------------------|-------------|
| mode                 | 状态模式          | `'read' \| 'edit'`                                  | `'edit'`    |
| disabled             | 是否禁用          | `boolean`                                           | `false`     |
| value                | 输入值（受控模式）     | `string`                                            | -           |
| defaultValue         | 默认值（非受控模式）    | `string`                                            | -           |
| placeholder          | 占位文本          | `string`                                            | -           |
| rows                 | 编辑态默认行数       | `number`                                            | `3`         |
| minRows              | 编辑态最小行数       | `number`                                            | -           |
| maxRows              | 编辑态最大行数       | `number`                                            | -           |
| autoSize             | 自动高度调整        | `boolean \| { minRows?: number; maxRows?: number }` | `false`     |
| maxLines             | 只读态最大显示行数     | `number`                                            | `3`         |
| enableExpand         | 是否启用展开功能（只读态） | `boolean`                                           | `true`      |
| expandText           | 展开按钮文案        | `string`                                            | `'展开'`      |
| collapseText         | 收起按钮文案        | `string`                                            | `'收起'`      |
| expandButtonPosition | 展开按钮位置        | `'bottom' \| 'inline'`                              | `'bottom'`  |
| showWordCount        | 显示字数统计（只读态）   | `boolean`                                           | `false`     |
| maxLength            | 最大长度          | `number`                                            | -           |
| showCount            | 显示字数统计（编辑态）   | `boolean`                                           | `false`     |
| allowClear           | 是否显示清空按钮      | `boolean`                                           | `false`     |
| autoFocus            | 是否自动聚焦        | `boolean`                                           | `false`     |
| fontSize             | 字号（只读态）       | `string \| number`                                  | `16`        |
| fontWeight           | 字重（只读态）       | `string \| number`                                  | `500`       |
| color                | 文本颜色（只读态）     | `string`                                            | `'#101828'` |
| lineHeight           | 行高（只读态）       | `string \| number`                                  | `1.5`       |
| required             | 是否必填          | `boolean`                                           | `false`     |
| minLength            | 最小长度          | `number`                                            | -           |
| pattern              | 正则校验          | `string \| RegExp`                                  | -           |
| validator            | 自定义校验函数       | `(value: string) => boolean \| string`              | -           |
| validateTrigger      | 校验触发时机        | `'onChange' \| 'onBlur' \| 'both'`                  | `'onBlur'`  |
| errorMessage         | 自定义错误提示       | `string`                                            | -           |
| onChange             | 值变化回调         | `(value: string) => void`                           | -           |
| onBlur               | 失焦回调          | `(value: string) => void`                           | -           |
| onFocus              | 聚焦回调          | `() => void`                                        | -           |
| onPressEnter         | 回车键回调（传递事件对象） | `(e: React.KeyboardEvent) => void`                  | -           |
| onExpand             | 展开/收起回调       | `(expanded: boolean) => void`                       | -           |
| onValidate           | 校验回调          | `(isValid: boolean, errors: string[]) => void`      | -           |
| className            | 自定义类名         | `string`                                            | -           |
| style                | 自定义样式         | `CSSProperties`                                     | -           |

## 核心功能说明

### 展开/折叠功能

只读态下的核心功能，用于优化长文本的空间利用。

**工作原理**：

1. 根据换行符 `\n` 计算行数
2. 当行数超过 `maxLines` 时显示展开按钮
3. 点击"展开"显示全部内容
4. 点击"收起"恢复截断显示

**配置项**：

- `maxLines`：最大显示行数（默认3）
- `enableExpand`：是否启用展开功能（默认true）
- `expandText`：展开按钮文案（默认"展开"）
- `collapseText`：收起按钮文案（默认"收起"）
- `onExpand`：展开/收起回调

### 自动高度调整

编辑态下的重要功能，根据输入内容自动调整输入框高度。

**三种配置方式**：

1. **boolean**：完全自动
   ```
   <PisellLongText autoSize />
   ```

2. **对象**：限定范围
   ```
   <PisellLongText autoSize={{ minRows: 3, maxRows: 8 }} />
   ```

3. **minRows + maxRows**：自动生效
   ```
   <PisellLongText minRows={3} maxRows={6} />
   // 等同于 autoSize={{ minRows: 3, maxRows: 6 }}
   ```

### 字数统计

支持编辑态和只读态两种字数统计方式。

**编辑态**（showCount）：

- 显示 "当前字数 / 最大字数"
- 位于输入框右下角
- 需要配合 `maxLength` 使用

**只读态**（showWordCount）：

- 显示 "当前字数 字"
- 位于文本下方右对齐
- 不需要 maxLength

## 常见问题

### 如何实现产品描述输入？

```
<PisellLongText
  placeholder="请输入产品详细描述"
  autoSize={{ minRows: 4, maxRows: 12 }}
  maxLength={1000}
  showCount
  allowClear
  required
  minLength={50}
/>
```

### 如何限制段落数量？

```
<PisellLongText
  placeholder="请输入内容（最多10段）"
  validator={(value) => {
    const lines = value.split('\n').filter((l) => l.trim());
    if (lines.length > 10) {
      return '内容不能超过10段';
    }
    return true;
  }}
  validateTrigger="onChange"
/>
```

### 如何实现 Ctrl+Enter 提交？

```
<PisellLongText
  placeholder="Enter 换行，Ctrl+Enter 提交"
  onPressEnter={(e) => {
    if (e.ctrlKey) {
      // 提交逻辑
      console.log('提交');
    }
  }}
/>
```

### 如何在只读态隐藏展开按钮？

```
<PisellLongText
  mode="read"
  value={longText}
  maxLines={3}
  enableExpand={false}
/>
```

### 如何设置固定行数（不自动调整）？

```
<PisellLongText
  rows={5}
  placeholder="固定5行高度"
/>
```

不设置 `autoSize`、`minRows`、`maxRows` 即可。

### autoSize、minRows、maxRows 的优先级？

优先级顺序：

1. `autoSize`（如果设置）
2. `minRows` + `maxRows`（自动转为 autoSize）
3. `rows`（固定行数）

```
// 优先级1：autoSize 优先
<PisellLongText autoSize={{ minRows: 3, maxRows: 8 }} rows={5} />
// 结果：使用 autoSize，忽略 rows

// 优先级2：minRows/maxRows 生效
<PisellLongText minRows={3} maxRows={6} rows={5} />
// 结果：转为 autoSize={{ minRows: 3, maxRows: 6 }}，忽略 rows

// 优先级3：rows 生效
<PisellLongText rows={5} />
// 结果：固定5行高度
```

### 如何监听展开/收起状态？

```
<PisellLongText
  mode="read"
  value={longText}
  maxLines={3}
  onExpand={(isExpanded) => {
    console.log('当前状态:', isExpanded ? '已展开' : '已收起');
  }}
/>
```

## 与 PisellSingleLineText 的区别

| 功能           | SingleLineText | LongText                  | 说明            |
|--------------|----------------|---------------------------|---------------|
| 输入组件         | Input          | TextArea                  | 单行 vs 多行      |
| 前后缀/标签       | ✅              | ❌                         | 长文本不需要        |
| 行数控制         | ❌              | ✅ rows, minRows, maxRows  | 多行特有          |
| 自动高度         | ❌              | ✅ autoSize                | 多行特有          |
| 展开/折叠        | ❌              | ✅ maxLines, enableExpand  | 只读态特有         |
| 展示变体         | ✅              | ❌ text/link/badge/tag     | 单行特有          |
| 字数统计         | showCount      | showCount + showWordCount | 长文本支持只读态统计    |
| onPressEnter | 回调 value       | 回调事件对象                    | 支持 Ctrl+Enter |

## 注意事项

1. **保留换行和空格**：只读态使用 `whiteSpace: 'pre-wrap'`，会保留用户输入的所有换行符和空格
2. **展开/折叠基于行数**：根据换行符 `\n` 计算行数，不是根据视觉高度
3. **自动高度需要内容**：首次渲染时，autoSize 根据 defaultValue 或 value 计算高度
4. **maxLength 会限制输入**：TextArea 组件会阻止超出长度的输入
5. **onPressEnter 传递事件对象**：可以通过 `e.ctrlKey`、`e.shiftKey` 等判断组合键

## 设计规范

### 编辑态（基于 Figma 设计）

- 圆角：8px
- 边框：1px solid #D0D5DD
- 内边距：12px 14px（注意：水平14px，比 Input 小2px）
- 字体：16px / 1.5
- 占位符颜色：#667085
- 默认行数：3行

### 只读态

- 字体：16px / Regular (400)
- 颜色：#101828
- 行高：1.5 (24px)
- 保留换行：whiteSpace: 'pre-wrap'

### 禁用态

- 背景色：#F9FAFB
- 文本颜色：#98A2B3
- 透明度：40%

## 相关组件

- [PisellSingleLineText](../pisellSingleLineText/pisellSingleLineText.md) - 单行文本组件
- [PisellPhone](../pisellPhone/pisellPhone.md) - 电话号码组件
- [PisellEmail](../pisellEmail/pisellEmail.md) - 邮箱地址组件
- [PisellUrl](../pisellUrl/pisellUrl.md) - URL 链接组件
