---
nav:
  title: 组件
  order: 1
group:
  title: 基础组件
  order: 1
title: PisellGridPro
order: 1
category: pro
---

# PisellGridPro 页面布局

PisellGridPro 是后台管理系统的标准页面布局组件，提供统一的页头、工具栏、数据卡片、内容区与页脚结构，便于快速搭建规范一致的列表页、统计页与详情页。

## 何时使用

- 需要标准后台页面结构（标题栏 + 工具栏 + 内容区 + 底栏）
- 列表页、数据统计页、详情页、工作台等需统一布局规范
- 希望主内容区单独滚动、其余区域固定

## 设计理念

在后台管理系统中，大部分页面都遵循相似的布局结构：顶部标题栏、工具栏、数据概览、主内容区、底部操作栏。PisellGridPro 将这些常见的布局模块进行了标准化封装，提供了以下能力:

- **标准化布局**：统一的页面结构，保证视觉一致性
- **灵活组合**：各个子组件可按需使用，支持灵活布局
- **开箱即用**：内置常用布局模式，减少重复代码
- **响应式设计**：自适应不同屏幕尺寸
- **高度可定制**：支持自定义样式和内容

## 布局结构

```
┌─────────────────────────────────────────────┐
│  Header                                     │
│  (标题、徽章、副标题、操作按钮)                │
├─────────────────────────────────────────────┤
│  PisellToolBar                              │
│  (标签页、筛选器、排序等)                      │
├─────────────────────────────────────────────┤
│  DataCard                                   │
│  (统计数据卡片)                               │
├─────────────────────────────────────────────┤
│  PisellGridView                             │
│  (主内容区，自带滚动)                          │
│                                             │
│                                             │
├─────────────────────────────────────────────┤
│  Footer                                     │
│  (底部操作栏、分页等)                          │
└─────────────────────────────────────────────┘
```

## 核心子组件

### PisellGridPro.Header - 页头组件

页面顶部标题栏，包含标题、徽章、副标题和操作按钮。

### PisellToolBar - 工具栏组件

灵活的工具栏组件，支持标签页和四个位置的内容区域。需从 `@pisell/materials` 单独引入 **PisellToolBar** 使用。

### PisellGridPro.DataCard - 数据卡片组件

用于展示统计数据的卡片组件，支持趋势显示。

### PisellGridView - 内容视图组件

主内容区域，内置滚动能力。需从 `@pisell/materials` 单独引入 **PisellGridView** 使用。

### PisellGridPro.Footer - 页脚组件

页面底部操作栏。

## 基础使用

### 简单页面布局

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView } from '@pisell/materials';

export default () => {
  return (
    <PisellGridPro>
      <PisellGridPro.Header title="页面标题" />
      <PisellGridView>
        <div>主内容区域</div>
      </PisellGridView>
    </PisellGridPro>
  );
};
```

### 完整页面布局

```tsx
import React from 'react';
import { PisellGridPro, PisellToolBar, PisellGridView } from '@pisell/materials';
import { Button, Badge } from 'antd';

export default () => {
  return (
    <PisellGridPro>
      {/* 页头 */}
      <PisellGridPro.Header
        title="订单管理"
        badge={<Badge count={5} />}
        subTitle="管理所有订单信息"
        actionsList={
          <>
            <Button type="primary">创建订单</Button>
            <Button>导出</Button>
          </>
        }
      />

      {/* 工具栏 */}
      <PisellToolBar
        topLeft={<div>筛选器</div>}
        topRight={<div>排序</div>}
        bottomLeft={<div>批量操作</div>}
        bottomRight={<div>视图切换</div>}
      />

      {/* 数据卡片 */}
      <PisellGridPro.DataCard
        dataItems={[
          {
            key: '1',
            title: '总订单数',
            value: '1,234',
            compareValue: '+12%',
            trend: 'up',
          },
          {
            key: '2',
            title: '待处理',
            value: '56',
            compareValue: '-5',
            trend: 'down',
          },
        ]}
      />

      {/* 内容区 */}
      <PisellGridView>
        <div>订单列表内容</div>
      </PisellGridView>

      {/* 页脚 */}
      <PisellGridPro.Footer>
        <div>分页组件</div>
      </PisellGridPro.Footer>
    </PisellGridPro>
  );
};
```

### 带标签页的布局

```tsx
import React from 'react';
import { PisellGridPro, PisellToolBar, PisellGridView } from '@pisell/materials';
import { Tabs } from 'antd';

export default () => {
  return (
    <PisellGridPro>
      <PisellGridPro.Header title="商品管理" />

      <PisellToolBar
        tabs={
          <Tabs
            items={[
              { key: '1', label: '全部商品' },
              { key: '2', label: '已上架' },
              { key: '3', label: '已下架' },
            ]}
          />
        }
        topRight={<div>搜索框</div>}
      />

      <PisellGridView>
        <div>商品列表</div>
      </PisellGridView>
    </PisellGridPro>
  );
};
```

### 数据统计页面

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => {
  const statsData = [
    {
      key: 'revenue',
      title: '总收入',
      value: '$45,231',
      compareValue: '+20%',
      trend: 'up' as const,
      comparePrefix: '较上月',
    },
    {
      key: 'orders',
      title: '订单数',
      value: '2,340',
      compareValue: '+180',
      trend: 'up' as const,
    },
    {
      key: 'customers',
      title: '新客户',
      value: '573',
      compareValue: '-12',
      trend: 'down' as const,
    },
    {
      key: 'conversion',
      title: '转化率',
      value: '68.2%',
      compareValue: '+2.5%',
      trend: 'up' as const,
    },
  ];

  return (
    <PisellGridPro>
      <PisellGridPro.Header title="数据概览" subTitle="实时数据统计" />

      <PisellGridPro.DataCard dataItems={statsData} />

      <PisellGridView>
        <div>图表内容</div>
      </PisellGridView>
    </PisellGridPro>
  );
};
```

### 可点击的数据卡片

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';
import { message } from 'antd';

export default () => {
  const handleCardClick = (cardKey: string) => {
    message.info(`点击了 ${cardKey} 卡片`);
  };

  return (
    <PisellGridPro>
      <PisellGridPro.Header title="业务概览" />

      <PisellGridPro.DataCard
        dataItems={[
          {
            key: 'total',
            title: '总销售额',
            value: '$126,560',
            compareValue: '+12.5%',
            trend: 'up',
            onClick: () => handleCardClick('总销售额'),
          },
          {
            key: 'today',
            title: '今日销售',
            value: '$8,846',
            compareValue: '+8.2%',
            trend: 'up',
            onClick: () => handleCardClick('今日销售'),
          },
        ]}
      />

      <PisellGridView>
        <div>详细内容</div>
      </PisellGridView>
    </PisellGridPro>
  );
};
```

## API

### PisellGridPro Props

| 参数      | 说明       | 类型            | 默认值 | 必填 |
| --------- | ---------- | --------------- | ------ | ---- |
| className | 自定义类名 | `string`        | -      | ❌   |
| style     | 自定义样式 | `CSSProperties` | -      | ❌   |
| children  | 子组件     | `ReactNode`     | -      | ✅   |

### Header Props

| 参数        | 说明           | 类型            | 默认值 | 必填 |
| ----------- | -------------- | --------------- | ------ | ---- |
| title       | 页面标题       | `ReactNode`     | -      | ❌   |
| badge       | 标题旁边的徽章 | `ReactNode`     | -      | ❌   |
| subTitle    | 副标题         | `ReactNode`     | -      | ❌   |
| actionsList | 右侧操作按钮   | `ReactNode`     | -      | ❌   |
| className   | 自定义类名     | `string`        | -      | ❌   |
| style       | 自定义样式     | `CSSProperties` | -      | ❌   |

### PisellToolBar Props

| 参数        | 说明         | 类型            | 默认值 | 必填 |
| ----------- | ------------ | --------------- | ------ | ---- |
| tabs        | 标签页内容   | `ReactNode`     | -      | ❌   |
| topLeft     | 顶部左侧内容 | `ReactNode`     | -      | ❌   |
| topRight    | 顶部右侧内容 | `ReactNode`     | -      | ❌   |
| bottomLeft  | 底部左侧内容 | `ReactNode`     | -      | ❌   |
| bottomRight | 底部右侧内容 | `ReactNode`     | -      | ❌   |
| className   | 自定义类名   | `string`        | -      | ❌   |
| style       | 自定义样式   | `CSSProperties` | -      | ❌   |

### DataCard Props

| 参数      | 说明             | 类型             | 默认值 | 必填 |
| --------- | ---------------- | ---------------- | ------ | ---- |
| dataItems | 统计卡片数据列表 | `StatCardItem[]` | `[]`   | ❌   |
| className | 自定义类名       | `string`         | -      | ❌   |
| style     | 自定义样式       | `CSSProperties`  | -      | ❌   |

### StatCardItem

| 参数          | 说明             | 类型             | 默认值       | 必填 |
| ------------- | ---------------- | ---------------- | ------------ | ---- |
| key           | 唯一标识         | `string`         | -            | ✅   |
| title         | 卡片标题         | `ReactNode`      | -            | ✅   |
| value         | 主要数值         | `ReactNode`      | -            | ✅   |
| compareValue  | 对比数值         | `ReactNode`      | -            | ❌   |
| trend         | 对比趋势         | `'up' \| 'down'` | -            | ❌   |
| comparePrefix | 对比前缀文本     | `string`         | `'v.s. pre'` | ❌   |
| showCompare   | 是否显示对比信息 | `boolean`        | `true`       | ❌   |
| onClick       | 点击回调         | `() => void`     | -            | ❌   |
| className     | 自定义类名       | `string`         | -            | ❌   |
| style         | 自定义样式       | `CSSProperties`  | -            | ❌   |

### PisellGridView Props

| 参数      | 说明       | 类型            | 默认值 | 必填 |
| --------- | ---------- | --------------- | ------ | ---- |
| className | 自定义类名 | `string`        | -      | ❌   |
| style     | 自定义样式 | `CSSProperties` | -      | ❌   |
| children  | 子组件     | `ReactNode`     | -      | ✅   |

### Footer Props

| 参数      | 说明       | 类型            | 默认值 | 必填 |
| --------- | ---------- | --------------- | ------ | ---- |
| className | 自定义类名 | `string`        | -      | ❌   |
| style     | 自定义样式 | `CSSProperties` | -      | ❌   |
| children  | 子组件     | `ReactNode`     | -      | ✅   |

## 典型应用场景

### 1. 列表页面

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="用户列表" />
    <PisellToolBar
      topLeft={<div>搜索栏</div>}
      topRight={<div>筛选</div>}
    />
    <PisellGridView>
      <div>用户表格</div>
    </PisellGridView>
    <PisellGridPro.Footer>
      <div>分页</div>
    </PisellGridPro.Footer>
  </PisellGridPro>
);
```

### 2. 数据统计页面

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

const statsData = [
  { key: '1', title: '销售额', value: '¥12,345', compareValue: '+10%', trend: 'up' as const },
];

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="销售统计" />
    <PisellGridPro.DataCard dataItems={statsData} />
    <PisellGridView>
      <div>图表区域</div>
    </PisellGridView>
  </PisellGridPro>
);
```

### 3. 详情页面

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';
import { Button } from 'antd';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header
      title="订单详情"
      actionsList={<Button>编辑</Button>}
    />
    <PisellGridView>
      <div>订单详情内容</div>
    </PisellGridView>
    <PisellGridPro.Footer>
      <Button>取消</Button>
      <Button type="primary">保存</Button>
    </PisellGridPro.Footer>
  </PisellGridPro>
);
```

### 4. 工作台页面

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';
import { Tabs } from 'antd';

const tabItems = [
  { key: '1', label: '概览' },
  { key: '2', label: '任务' },
];
const dashboardData = [
  { key: '1', title: '今日任务', value: '8', compareValue: '2 待办', trend: 'up' as const },
];

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="工作台" subTitle="欢迎回来" />
    <PisellGridPro.DataCard dataItems={dashboardData} />
    <PisellToolBar tabs={<Tabs items={tabItems} />} />
    <PisellGridView>
      <div>工作台内容</div>
    </PisellGridView>
  </PisellGridPro>
);
```

## 样式定制

### 自定义主容器样式

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro
    style={{
      background: '#f5f5f5',
      padding: '0 32px',
    }}
  >
    <PisellGridPro.Header title="页面标题" />
    <PisellGridView>
      <div>内容</div>
    </PisellGridView>
  </PisellGridPro>
);
```

### 自定义子组件样式

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header
      className="custom-header"
      style={{ borderBottom: '2px solid #1890ff' }}
      title="自定义样式"
    />
    <PisellGridView style={{ background: '#fff', padding: '24px' }}>
      <div>内容</div>
    </PisellGridView>
  </PisellGridPro>
);
```

### 自定义数据卡片样式

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="数据概览" />
    <PisellGridPro.DataCard
      dataItems={[
        {
          key: '1',
          title: '自定义样式',
          value: '1,234',
          style: {
            background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
            color: '#fff',
          },
        },
      ]}
    />
    <PisellGridView>
      <div>内容</div>
    </PisellGridView>
  </PisellGridPro>
);
```

## 扩展开发

如果你需要开发新的布局模式或扩展现有功能，请参考：

- [设计文档](./PisellGridPro.$tab-design.md)
- [开发文档](./PisellGridPro.$tab-dev.md)

## 注意事项

1. **布局顺序**: 建议按照 Header → PisellToolBar → DataCard → PisellGridView → Footer 的顺序使用子组件
2. **高度控制**: PisellGridPro 默认占满视口高度（100vh），PisellGridView 会自动占据剩余空间
3. **滚动区域**: 只有 PisellGridView 内部可滚动，其他组件固定不滚动
4. **性能优化**: PisellGridView 使用 PisellScrollView，会自动处理滚动性能问题
5. **响应式**: 组件支持响应式布局，会自动适配不同屏幕尺寸
6. **可选组件**: 所有子组件都是可选的，可以按需组合使用

## 最佳实践

### 1. 统一布局规范

在团队中统一使用 PisellGridPro 作为页面布局基础，保证视觉一致性。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

// Good: 统一的布局结构
export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="页面标题" />
    <PisellGridView>内容</PisellGridView>
  </PisellGridPro>
);
```

### 2. 合理使用数据卡片

数据卡片适合展示关键指标，建议 3–6 个核心指标，不宜过多。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="数据概览" />
    <PisellGridPro.DataCard
      dataItems={[
        { key: '1', title: '总收入', value: '$45,231' },
        { key: '2', title: '订单数', value: '2,340' },
        { key: '3', title: '转化率', value: '68.2%' },
      ]}
    />
    <PisellGridView>
      <div>内容</div>
    </PisellGridView>
  </PisellGridPro>
);
```

### 3. 灵活使用 ToolBar

ToolBar 提供 tabs、topLeft、topRight、bottomLeft、bottomRight，可合理分配搜索、筛选、操作按钮等。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';
import { Button } from 'antd';

export default () => (
  <PisellToolBar
    topLeft={<div>搜索 / 筛选</div>}
    topRight={<Button type="primary">创建</Button>}
    bottomLeft={<div>批量操作</div>}
    bottomRight={<div>视图切换</div>}
  />
);
```

### 4. 页脚用于固定操作

Footer 适合放置分页、批量操作确认等固定在底部的元素。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro.Footer>
    <div style={{ display: 'flex', justifyContent: 'space-between' }}>
      <div>已选择 10 项</div>
      <div>分页组件</div>
    </div>
  </PisellGridPro.Footer>
);
```

### 5. PisellGridView 内容区域的组织

PisellGridView 内放主要业务内容，保持简洁；可与 Table、列表等配合使用。

```tsx
import React from 'react';
import { PisellGridView } from '@pisell/materials';
import { Table } from 'antd';

const data = [
  { key: '1', name: '示例一', count: 1 },
  { key: '2', name: '示例二', count: 2 },
];
const columns = [
  { title: '名称', dataIndex: 'name' },
  { title: '数量', dataIndex: 'count' },
];

export default () => (
  <PisellGridView>
    <Table dataSource={data} columns={columns} />
  </PisellGridView>
);
```

## 常见问题

### 1. 如何实现全屏布局？

PisellGridPro 默认就是全屏布局（100vh）。

### 2. 如何让某个子组件占据剩余空间？

View 组件会自动占据剩余空间，无需额外配置。

### 3. 如何隐藏某个子组件？

直接不渲染该子组件即可。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro>
    <PisellGridPro.Header title="标题" />
    {/* 不需要 ToolBar 就不渲染 */}
    <PisellGridView>内容</PisellGridView>
  </PisellGridPro>
);
```

### 4. 如何自定义内边距？

通过 `style` 属性设置。

```tsx
import React from 'react';
import { PisellGridPro, PisellGridView, PisellToolBar } from '@pisell/materials';

export default () => (
  <PisellGridPro style={{ padding: '0 32px' }}>
    <PisellGridPro.Header title="标题" />
    <PisellGridView>内容</PisellGridView>
  </PisellGridPro>
);
```

### 5. DataCard 为空时会怎样？

当 `dataItems` 为空数组时，DataCard 不渲染任何内容。
