• 中文
  • ProList - 高级列表

    ProList 基于 ProTable 实现,可以认为是 ProTable 的一个特例,将数据以列表的形式展现。API 设计上更像 Table,使得 Table 和 List 的切换变得更加容易。

    何时使用

    当你需要一个标准的列表展现,或需要在列表和表格之间灵活切换时,ProList 是不二选择。

    代码演示

    Issue 回归场景

    等待请求完成
    暂无数据
    暂无数据
    • 第 0-0 条/总共 0 条
    • 1
    展示控制与实时分页状态
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProCard, ProList } from '@ant-design/pro-components';
    import { Alert, Button, Space, Typography } from 'antd';
    import { useRef, useState } from 'react';
    
    type Item = { id: number; title: string; description: string };
    
    const columns: ProColumns<Item>[] = [
      { dataIndex: 'title', title: '标题', listSlot: 'title' },
      { dataIndex: 'description', title: '说明', listSlot: 'description' },
      {
        title: '操作',
        listSlot: 'actions',
        render: () => [<a key="edit">编辑</a>],
      },
    ];
    
    export default () => {
      const actionRef = useRef<ActionType>();
      const [pageInfo, setPageInfo] = useState('等待请求完成');
    
      return (
        <ProCard direction="column" ghost gutter={[0, 16]}>
          <Alert
            type="info"
            showIcon
            message="ProList 展示与实时分页状态"
            description="覆盖操作区 hover、grid itemRender gutter 及 actionRef.pageInfo。"
          />
          <ProList<Item>
            actionRef={actionRef}
            rowKey="id"
            columns={columns}
            showActions="hover"
            grid={{ column: 2, gutter: [16, 24] }}
            pagination={{ pageSize: 2 }}
            request={async () => ({
              success: true,
              total: 42,
              data: [
                { id: 1, title: '项目 A', description: '悬停显示操作区' },
                { id: 2, title: '项目 B', description: '卡片间距保持一致' },
              ],
            })}
            itemRender={(item, index, defaultDom) => (
              <ProCard title={`自定义 itemRender ${index + 1}`}>
                {defaultDom}
              </ProCard>
            )}
            toolBarRender={() => [
              <Space key="page-info">
                <Button
                  onClick={() =>
                    setPageInfo(JSON.stringify(actionRef.current?.pageInfo))
                  }
                >
                  读取 pageInfo
                </Button>
                <Typography.Text code>{pageInfo}</Typography.Text>
              </Space>,
            ]}
          />
        </ProCard>
      );
    };
    

    枚举属性切换

    通过 Segmented 分段选择器切换 itemLayout、variant、split 属性。

    itemLayout 列表项方向:
    variant 外观变体:
    split 分割线:
    项目列表枚举切换

    智慧零售平台

    面向线下门店的数字化经营解决方案
    开发中 85%

    Ant Design Pro

    开箱即用的中台前端解决方案
    已上线 100%

    云原生微服务框架

    基于 K8s 的微服务开发与治理框架
    测试中 92%

    数据可视化引擎

    企业级数据看板与图表分析工具
    开发中 60%
    枚举属性切换
    import { ProList } from '@ant-design/pro-components';
    import { Button, Progress, Segmented, Space, Tag } from 'antd';
    import { useState } from 'react';
    
    type ProjectItem = {
      title: string;
      avatar: string;
      description: string;
      progress: number;
      status: string;
    };
    
    const dataSource: ProjectItem[] = [
      {
        title: '智慧零售平台',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '面向线下门店的数字化经营解决方案',
        progress: 85,
        status: '开发中',
      },
      {
        title: 'Ant Design Pro',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '开箱即用的中台前端解决方案',
        progress: 100,
        status: '已上线',
      },
      {
        title: '云原生微服务框架',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '基于 K8s 的微服务开发与治理框架',
        progress: 92,
        status: '测试中',
      },
      {
        title: '数据可视化引擎',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '企业级数据看板与图表分析工具',
        progress: 60,
        status: '开发中',
      },
    ];
    
    const Demo = () => {
      const [itemLayout, setItemLayout] = useState<'horizontal' | 'vertical'>(
        'horizontal',
      );
      const [variant, setVariant] = useState<'outlined' | 'borderless' | 'filled'>(
        'borderless',
      );
      const [split, setSplit] = useState(true);
    
      return (
        <div
          style={{
            background: '#ddd',
            padding: 24,
          }}
        >
          <Space
            orientation="vertical"
            size={12}
            style={{
              width: '100%',
              marginBlockEnd: 16,
              padding: 16,
              background: '#ddd',
              border: '1px solid #f0f0f0',
              borderRadius: 8,
            }}
          >
            <Space>
              <span>itemLayout 列表项方向:</span>
              <Segmented
                value={itemLayout}
                onChange={(v) => setItemLayout(v as any)}
                options={[
                  { label: '水平 horizontal', value: 'horizontal' },
                  { label: '垂直 vertical', value: 'vertical' },
                ]}
              />
            </Space>
            <Space>
              <span>variant 外观变体:</span>
              <Segmented
                value={variant}
                onChange={(v) => setVariant(v as any)}
                options={[
                  { label: '线框 outlined', value: 'outlined' },
                  { label: '填充 filled', value: 'filled' },
                  { label: '无边框 borderless', value: 'borderless' },
                ]}
              />
            </Space>
            <Space>
              <span>split 分割线:</span>
              <Segmented
                value={split ? 'true' : 'false'}
                onChange={(v) => setSplit(v === 'true')}
                options={[
                  { label: '有分割线', value: 'true' },
                  { label: '无分割线', value: 'false' },
                ]}
              />
            </Space>
          </Space>
    
          <ProList<ProjectItem>
            headerTitle="项目列表枚举切换"
            itemLayout={itemLayout}
            variant={variant}
            split={split}
            dataSource={dataSource}
            rowKey="title"
            toolBarRender={() => [
              <Button key="new" type="primary">
                新建项目
              </Button>,
            ]}
            columns={[
              { dataIndex: 'title', listSlot: 'title' },
              { dataIndex: 'avatar', listSlot: 'avatar' },
              { dataIndex: 'description', listSlot: 'description' },
              {
                listSlot: 'content',
                render: (_, record) => (
                  <div style={{ width: 200 }}>
                    <div>
                      {record.status}{' '}
                      <Tag
                        color={record.progress === 100 ? 'success' : 'processing'}
                      >
                        {record.progress}%
                      </Tag>
                    </div>
                    <Progress percent={record.progress} showInfo={false} />
                  </div>
                ),
              },
              {
                listSlot: 'actions',
                render: () => [
                  <a key="view">查看</a>,
                  <a key="edit">编辑</a>,
                  <a key="archive">归档</a>,
                ],
              },
            ]}
          />
        </div>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    基本使用

    项目列表
    书琰

    Ant Design Pro
    进行中

    开箱即用的中台前端/设计解决方案
    React
    TypeScript
    Ant Design
    逄一

    ProComponents
    进行中

    专业级别的中后台组件库
    React
    Components
    期贤

    UmiJS
    进行中

    插件化的企业级前端应用框架
    Framework
    React
    玄霜

    Ant Design Mobile
    待启动

    移动端设计规范和组件库
    Mobile
    React
    怀渊

    Ant Design Charts
    已归档

    简单好用的 React 图表库
    Charts
    Visualization
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Avatar, Space, Tag } from 'antd';
    
    type ProjectItem = {
      id: string;
      name: string;
      description: string;
      status: 'active' | 'archived' | 'pending';
      owner: {
        name: string;
        avatar: string;
      };
      tags: string[];
      updatedAt: string;
    };
    
    const statusMap = {
      active: { text: '进行中', color: 'success' },
      archived: { text: '已归档', color: 'default' },
      pending: { text: '待启动', color: 'warning' },
    };
    
    const dataSource: ProjectItem[] = [
      {
        id: '1',
        name: 'Ant Design Pro',
        description: '开箱即用的中台前端/设计解决方案',
        status: 'active',
        owner: {
          name: '书琰',
          avatar:
            'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
        },
        tags: ['React', 'TypeScript', 'Ant Design'],
        updatedAt: '2024-02-09',
      },
      {
        id: '2',
        name: 'ProComponents',
        description: '专业级别的中后台组件库',
        status: 'active',
        owner: {
          name: '逄一',
          avatar:
            'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        },
        tags: ['React', 'Components'],
        updatedAt: '2024-02-08',
      },
      {
        id: '3',
        name: 'UmiJS',
        description: '插件化的企业级前端应用框架',
        status: 'active',
        owner: {
          name: '期贤',
          avatar:
            'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
        },
        tags: ['Framework', 'React'],
        updatedAt: '2024-02-07',
      },
      {
        id: '4',
        name: 'Ant Design Mobile',
        description: '移动端设计规范和组件库',
        status: 'pending',
        owner: {
          name: '玄霜',
          avatar:
            'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        },
        tags: ['Mobile', 'React'],
        updatedAt: '2024-02-06',
      },
      {
        id: '5',
        name: 'Ant Design Charts',
        description: '简单好用的 React 图表库',
        status: 'archived',
        owner: {
          name: '怀渊',
          avatar:
            'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
        },
        tags: ['Charts', 'Visualization'],
        updatedAt: '2024-02-05',
      },
    ];
    
    const columns: ProColumns<ProjectItem>[] = [
      {
        title: '项目名称',
        dataIndex: 'name',
        listSlot: 'title',
      },
      {
        title: '描述',
        dataIndex: 'description',
        listSlot: 'description',
      },
      {
        title: '负责人',
        dataIndex: ['owner', 'avatar'],
        listSlot: 'avatar',
        render: (_, record) => (
          <Avatar src={record.owner.avatar} alt={record.owner.name} />
        ),
      },
      {
        title: '状态',
        dataIndex: 'status',
        listSlot: 'subTitle',
        render: (_, record) => (
          <Tag color={statusMap[record.status].color}>
            {statusMap[record.status].text}
          </Tag>
        ),
      },
      {
        title: '标签',
        dataIndex: 'tags',
        listSlot: 'content',
        render: (_, record) => (
          <Space size={4} wrap>
            {record.tags.map((tag) => (
              <Tag key={tag}>{tag}</Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '操作',
        listSlot: 'actions',
        render: () => [<a key="view">查看</a>, <a key="edit">编辑</a>],
      },
    ];
    
    export default () => (
      <ProList<ProjectItem>
        columns={columns}
        dataSource={dataSource}
        rowKey="id"
        headerTitle="项目列表"
        tooltip="这是一个基础的列表示例,展示了 ProList 的基本用法"
      />
    );
    

    使用 columns + listSlot(推荐)

    通过 columns 配合 listSlot 属性,可以和 ProTable 共用同一份列配置。listSlot 指定该列映射到列表项的哪个插槽(如 title、avatar、description 等)。

    columns API(与 ProTable 兼容)

    智慧零售平台
    技术专栏
    设计语言

    Ant Design
    Ant Design
    可视化

    云原生微服务框架
    云原生

    数据可视化引擎
    可视化

    /**
     * 使用 columns + listSlot 的新 API,与 ProTable 兼容
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Button, Space, Tag } from 'antd';
    import type { Key } from 'react';
    import { useState } from 'react';
    
    type DataItem = {
      id: string;
      name: string;
      image: string;
      desc: string;
      labels: string[];
    };
    
    const dataSource: DataItem[] = [
      {
        id: '1',
        name: '智慧零售平台',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: 'Ant Design, a design language for background applications, is refined by Ant UED Team',
        labels: ['技术专栏', '设计语言'],
      },
      {
        id: '2',
        name: 'Ant Design',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '企业级数据看板与可视化分析工具,开箱即用的图表方案',
        labels: ['Ant Design', '可视化'],
      },
      {
        id: '3',
        name: '云原生微服务框架',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '基于 K8s 的微服务开发与治理框架,支持服务注册与发现',
        labels: ['云原生'],
      },
      {
        id: '4',
        name: '数据可视化引擎',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '面向企业级中后台的数据可视化解决方案',
        labels: ['可视化'],
      },
    ];
    
    /**
     * 同一份 columns 可同时用于 ProTable 和 ProList
     * ProTable 忽略 listSlot,ProList 使用 listSlot 映射到列表项的各个部分
     */
    const columns: ProColumns<DataItem>[] = [
      {
        title: '名称',
        dataIndex: 'name',
        listSlot: 'title',
      },
      {
        dataIndex: 'image',
        listSlot: 'avatar',
        search: false,
      },
      {
        title: '标签',
        dataIndex: 'labels',
        listSlot: 'subTitle',
        search: false,
        render: (_, row) => (
          <Space size={8}>
            {row.labels?.map((label) => (
              <Tag color="blue" key={label}>
                {label}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '描述',
        dataIndex: 'desc',
        listSlot: 'description',
        search: false,
      },
      {
        title: '操作',
        listSlot: 'actions',
        search: false,
        render: () => [<a key="edit">编辑</a>, <a key="delete">删除</a>],
      },
    ];
    
    const Demo = () => {
      const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
    
      return (
        <ProList<DataItem>
          rowKey="id"
          headerTitle="columns API(与 ProTable 兼容)"
          toolBarRender={() => [
            <Button key="add" type="primary">
              新建
            </Button>,
          ]}
          columns={columns}
          expandable={{
            expandedRowKeys,
            onExpandedRowsChange: setExpandedRowKeys,
          }}
          dataSource={dataSource}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    卡片列表(columns + listSlot)

    卡片列表(columns API)
    ProTable
    稳定版
    高级表格组件,支持搜索、筛选、排序等功能
    表格组件 • 125.0K 下载 • ⭐ 4.8
    ProForm
    稳定版
    高级表单组件,简化表单开发流程
    表单组件 • 98.0K 下载 • ⭐ 4.9
    ProLayout
    稳定版
    开箱即用的中后台布局方案
    布局组件 • 156.0K 下载 • ⭐ 4.7
    ProCard
    稳定版
    可分割的卡片组件,支持多种布局
    卡片组件 • 67.0K 下载 • ⭐ 4.6
    ProDescriptions
    稳定版
    高级描述列表组件,支持编辑和请求
    描述列表 • 45.0K 下载 • ⭐ 4.5
    ProList
    稳定版
    高级列表组件,支持多种展示模式
    列表组件 • 52.0K 下载 • ⭐ 4.7
    ProSkeleton
    测试版
    高级骨架屏组件,更好的加载体验
    骨架屏 • 34.0K 下载 • ⭐ 4.4
    ProField
    稳定版
    统一的字段渲染组件
    字段组件 • 28.0K 下载 • ⭐ 4.3
    • 第 1-8 条/总共 8 条
    • 1
    /**
     * 卡片模式使用 columns + listSlot,推荐使用新的 columns API
     * actions 在卡片模式下默认渲染到 extra 位置
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Alert, Tag } from 'antd';
    
    type DataItem = {
      id: string;
      title: string;
      category: string;
      description: string;
      avatar: string;
      downloads: number;
      rating: number;
      status: 'stable' | 'beta' | 'deprecated';
    };
    
    const statusConfig = {
      stable: { text: '稳定版', color: 'success' },
      beta: { text: '测试版', color: 'processing' },
      deprecated: { text: '已废弃', color: 'default' },
    };
    
    const data: DataItem[] = [
      {
        id: '1',
        title: 'ProTable',
        category: '表格组件',
        description: '高级表格组件,支持搜索、筛选、排序等功能',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/upvrAjAPQX/Logo_Tech%252520UI.svg',
        downloads: 125000,
        rating: 4.8,
        status: 'stable',
      },
      {
        id: '2',
        title: 'ProForm',
        category: '表单组件',
        description: '高级表单组件,简化表单开发流程',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        downloads: 98000,
        rating: 4.9,
        status: 'stable',
      },
      {
        id: '3',
        title: 'ProLayout',
        category: '布局组件',
        description: '开箱即用的中后台布局方案',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        downloads: 156000,
        rating: 4.7,
        status: 'stable',
      },
      {
        id: '4',
        title: 'ProCard',
        category: '卡片组件',
        description: '可分割的卡片组件,支持多种布局',
        avatar: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        downloads: 67000,
        rating: 4.6,
        status: 'stable',
      },
      {
        id: '5',
        title: 'ProDescriptions',
        category: '描述列表',
        description: '高级描述列表组件,支持编辑和请求',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/upvrAjAPQX/Logo_Tech%252520UI.svg',
        downloads: 45000,
        rating: 4.5,
        status: 'stable',
      },
      {
        id: '6',
        title: 'ProList',
        category: '列表组件',
        description: '高级列表组件,支持多种展示模式',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        downloads: 52000,
        rating: 4.7,
        status: 'stable',
      },
      {
        id: '7',
        title: 'ProSkeleton',
        category: '骨架屏',
        description: '高级骨架屏组件,更好的加载体验',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        downloads: 34000,
        rating: 4.4,
        status: 'beta',
      },
      {
        id: '8',
        title: 'ProField',
        category: '字段组件',
        description: '统一的字段渲染组件',
        avatar: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        downloads: 28000,
        rating: 4.3,
        status: 'stable',
      },
    ];
    
    export default () => {
      const columns: ProColumns<DataItem>[] = [
        {
          title: '组件名称',
          dataIndex: 'title',
          listSlot: 'title',
        },
        {
          title: '状态',
          dataIndex: 'status',
          listSlot: 'subTitle',
          render: (_, record) => (
            <Tag color={statusConfig[record.status].color}>
              {statusConfig[record.status].text}
            </Tag>
          ),
        },
        {
          title: '图标',
          dataIndex: 'avatar',
          listSlot: 'avatar',
        },
        {
          title: '内容',
          listSlot: 'content',
          render: (_, record) => (
            <div style={{ flex: 1 }}>
              <div style={{ marginBottom: 8 }}>{record.description}</div>
              <div style={{ color: '#999', fontSize: 12 }}>
                {record.category} • {(record.downloads / 1000).toFixed(1)}K 下载 •
                ⭐ {record.rating}
              </div>
            </div>
          ),
        },
        {
          title: '操作',
          listSlot: 'actions',
          render: () => [<a key="install">安装</a>, <a key="docs">文档</a>],
        },
      ];
    
      return (
        <div
          style={{
            backgroundColor: '#eee',
            margin: -24,
            padding: 24,
          }}
        >
          <Alert
            title="推荐使用 columns + listSlot API"
            description="新的 columns API 与 ProTable 保持一致,通过 listSlot 指定数据在列表项中的位置。相比 metas API 更加灵活和易于维护。"
            type="info"
            showIcon
            style={{ marginBottom: 16 }}
          />
    
          <ProList<DataItem>
            pagination={{ defaultPageSize: 8, showSizeChanger: false }}
            rowSelection={{}}
            grid={{ gutter: 16, column: 2 }}
            columns={columns}
            headerTitle="卡片列表(columns API)"
            dataSource={data}
          />
        </div>
      );
    };
    

    网格配置

    配置面板
    列数 (column): 2
    123456
    间距 (gutter): 8px
    0816243248
    显示边框:
    幽灵模式:
    边框:
    Grid 布局示例
    Analytics Pro
    运行中
    企业级数据分析平台,支持多维度数据分析和可视化展示
    数据分析 • 1,280 用户
    Cloud Storage
    运行中
    安全可靠的企业云存储服务,支持文件同步和共享
    云存储 • 3,450 用户
    Task Manager
    运行中
    高效的任务和项目管理工具,支持团队协作和进度跟踪
    项目管理 • 2,150 用户
    Email Suite
    测试中
    专业的企业邮件服务,支持大附件和邮件加密
    企业邮箱 • 890 用户
    Video Conference
    运行中
    高清视频会议系统,支持屏幕共享和实时字幕
    视频会议 • 5,200 用户
    HR System
    运行中
    一体化人力资源管理系统,涵盖招聘、考勤、薪酬等
    人力资源 • 1,560 用户
    CRM Platform
    运行中
    智能客户关系管理平台,助力销售业绩提升
    客户关系 • 2,890 用户
    Finance Suite
    运行中
    专业的财务管理系统,支持多币种和自动对账
    财务管理 • 1,120 用户
    Workflow Engine
    测试中
    灵活的工作流引擎,支持可视化流程设计
    流程引擎 • 670 用户
    Knowledge Base
    运行中
    企业知识管理系统,支持全文检索和智能推荐
    知识库 • 1,940 用户
    Security Center
    运行中
    企业安全管理中心,实时监控和威胁检测
    安全中心 • 780 用户
    API Gateway
    测试中
    统一的 API 网关服务,支持流量控制和监控
    接口网关 • 450 用户
    • 第 1-12 条/总共 12 条
    • 1
    import { ProList } from '@ant-design/pro-components';
    import { Alert, Card, Col, Row, Segmented, Slider, Switch, Tag } from 'antd';
    import { useState } from 'react';
    
    const apps = [
      {
        id: '1',
        name: 'Analytics Pro',
        category: '数据分析',
        description: '企业级数据分析平台,支持多维度数据分析和可视化展示',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        status: 'active',
        users: 1280,
      },
      {
        id: '2',
        name: 'Cloud Storage',
        category: '云存储',
        description: '安全可靠的企业云存储服务,支持文件同步和共享',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        status: 'active',
        users: 3450,
      },
      {
        id: '3',
        name: 'Task Manager',
        category: '项目管理',
        description: '高效的任务和项目管理工具,支持团队协作和进度跟踪',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        status: 'active',
        users: 2150,
      },
      {
        id: '4',
        name: 'Email Suite',
        category: '企业邮箱',
        description: '专业的企业邮件服务,支持大附件和邮件加密',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        status: 'beta',
        users: 890,
      },
      {
        id: '5',
        name: 'Video Conference',
        category: '视频会议',
        description: '高清视频会议系统,支持屏幕共享和实时字幕',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        status: 'active',
        users: 5200,
      },
      {
        id: '6',
        name: 'HR System',
        category: '人力资源',
        description: '一体化人力资源管理系统,涵盖招聘、考勤、薪酬等',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        status: 'active',
        users: 1560,
      },
      {
        id: '7',
        name: 'CRM Platform',
        category: '客户关系',
        description: '智能客户关系管理平台,助力销售业绩提升',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        status: 'active',
        users: 2890,
      },
      {
        id: '8',
        name: 'Finance Suite',
        category: '财务管理',
        description: '专业的财务管理系统,支持多币种和自动对账',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        status: 'active',
        users: 1120,
      },
      {
        id: '9',
        name: 'Workflow Engine',
        category: '流程引擎',
        description: '灵活的工作流引擎,支持可视化流程设计',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        status: 'beta',
        users: 670,
      },
      {
        id: '10',
        name: 'Knowledge Base',
        category: '知识库',
        description: '企业知识管理系统,支持全文检索和智能推荐',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',
        status: 'active',
        users: 1940,
      },
      {
        id: '11',
        name: 'Security Center',
        category: '安全中心',
        description: '企业安全管理中心,实时监控和威胁检测',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/youdaoyun.png',
        status: 'active',
        users: 780,
      },
      {
        id: '12',
        name: 'API Gateway',
        category: '接口网关',
        description: '统一的 API 网关服务,支持流量控制和监控',
        icon: 'https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg',
        status: 'beta',
        users: 450,
      },
    ];
    
    const statusMap: Record<string, { text: string; color: string }> = {
      active: { text: '运行中', color: 'success' },
      beta: { text: '测试中', color: 'processing' },
    };
    
    const data = apps.map((app) => ({
      id: app.id,
      title: app.name,
      subTitle: (
        <Tag color={statusMap[app.status].color}>{statusMap[app.status].text}</Tag>
      ),
      actions: [<a key="view">打开</a>, <a key="settings">设置</a>],
      avatar: app.icon,
      content: (
        <div>
          <div>{app.description}</div>
          <div style={{ color: '#999', fontSize: 12, marginTop: 8 }}>
            {app.category} • {app.users.toLocaleString()} 用户
          </div>
        </div>
      ),
    }));
    
    export default () => {
      const [column, setColumn] = useState<number>(2);
      const [gutter, setGutter] = useState<number>(8);
      const [bordered, setBordered] = useState<boolean>(true);
      const [ghost, setGhost] = useState<boolean>(false);
    
      return (
        <div style={{ padding: 24, backgroundColor: '#f5f5f5' }}>
          <Alert
            title="Grid 布局配置"
            description="ProList 使用 CSS Grid 实现网格布局,支持自定义列数和间距。通过 grid 属性配置,可以实现响应式的卡片网格布局。"
            type="info"
            showIcon
            style={{ marginBottom: 24 }}
          />
    
          <Card title="配置面板" style={{ marginBottom: 24 }}>
            <Row gutter={[24, 24]}>
              <Col xs={24} md={12}>
                <div>
                  <div style={{ marginBottom: 8, fontWeight: 500 }}>
                    列数 (column): {column}
                  </div>
                  <Slider
                    min={1}
                    max={6}
                    value={column}
                    onChange={setColumn}
                    marks={{
                      1: '1',
                      2: '2',
                      3: '3',
                      4: '4',
                      5: '5',
                      6: '6',
                    }}
                  />
                </div>
              </Col>
    
              <Col xs={24} md={12}>
                <div>
                  <div style={{ marginBottom: 8, fontWeight: 500 }}>
                    间距 (gutter): {gutter}px
                  </div>
                  <Slider
                    min={0}
                    max={48}
                    step={4}
                    value={gutter}
                    onChange={setGutter}
                    marks={{
                      0: '0',
                      8: '8',
                      16: '16',
                      24: '24',
                      32: '32',
                      48: '48',
                    }}
                  />
                </div>
              </Col>
    
              <Col xs={24} md={8}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontWeight: 500 }}>显示边框:</span>
                  <Switch checked={bordered} onChange={setBordered} />
                </div>
              </Col>
    
              <Col xs={24} md={8}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontWeight: 500 }}>幽灵模式:</span>
                  <Switch checked={ghost} onChange={setGhost} />
                </div>
              </Col>
    
              <Col xs={24} md={8}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontWeight: 500 }}>边框:</span>
                  <Segmented
                    value={bordered ? 'bordered' : 'borderless'}
                    onChange={(v) => setBordered(v === 'bordered')}
                    options={[
                      { label: '有边框', value: 'bordered' },
                      { label: '无边框', value: 'borderless' },
                    ]}
                  />
                </div>
              </Col>
            </Row>
    
            <Alert
              title="代码示例"
              description={
                <pre style={{ margin: 0, fontSize: 12 }}>
                  {`<ProList
      grid={{ gutter: ${gutter}, column: ${column} }}
      itemCardProps={{ bordered: ${bordered}, ghost: ${ghost} }}
      ...
    />`}
                </pre>
              }
              type="success"
              style={{ marginTop: 24 }}
            />
          </Card>
    
          <ProList<any>
            grid={{ gutter, column }}
            itemCardProps={{
              bordered,
              ghost,
            }}
            ghost={ghost}
            pagination={{
              defaultPageSize: 12,
              showSizeChanger: true,
              pageSizeOptions: ['6', '12', '18', '24'],
            }}
            columns={[
              { dataIndex: 'title', listSlot: 'title' },
              { dataIndex: 'subTitle', listSlot: 'subTitle' },
              { dataIndex: 'avatar', listSlot: 'avatar' },
              { dataIndex: 'content', listSlot: 'content' },
              { dataIndex: 'actions', listSlot: 'actions' },
            ]}
            headerTitle="Grid 布局示例"
            tooltip="使用 CSS Grid 实现的响应式卡片布局"
            dataSource={data}
          />
        </div>
      );
    };
    

    表格/列表一键切换

    同一份 columns 同时传给 ProTable 和 ProList,通过切换组件即可在表格和列表视图之间无缝切换。

    列表视图

    智慧零售平台
    技术专栏
    设计语言

    2024-01-15

    Ant Design
    Ant Design

    2024-02-20

    云原生微服务框架
    云原生
    可视化

    2024-03-10
    /**
     * 同一份 columns 同时用于 ProTable 和 ProList,一键切换视图
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList, ProTable } from '@ant-design/pro-components';
    import { Radio, Space, Tag } from 'antd';
    import { useState } from 'react';
    
    type DataItem = {
      id: string;
      name: string;
      avatar: string;
      status: 'open' | 'closed' | 'processing';
      labels: string[];
      updatedAt: string;
    };
    
    const dataSource: DataItem[] = [
      {
        id: '1',
        name: '智慧零售平台',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        status: 'open',
        labels: ['技术专栏', '设计语言'],
        updatedAt: '2024-01-15',
      },
      {
        id: '2',
        name: 'Ant Design',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        status: 'processing',
        labels: ['Ant Design'],
        updatedAt: '2024-02-20',
      },
      {
        id: '3',
        name: '云原生微服务框架',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        status: 'closed',
        labels: ['云原生', '可视化'],
        updatedAt: '2024-03-10',
      },
    ];
    
    /**
     * 这份 columns 同时用于 ProTable 和 ProList
     * - ProTable 渲染为表格列
     * - ProList 通过 listSlot 映射到列表项各部分
     */
    const columns: ProColumns<DataItem>[] = [
      {
        title: '名称',
        dataIndex: 'name',
        listSlot: 'title',
      },
      {
        title: '头像',
        dataIndex: 'avatar',
        listSlot: 'avatar',
        search: false,
        hideInTable: true,
      },
      {
        title: '标签',
        dataIndex: 'labels',
        listSlot: 'subTitle',
        search: false,
        render: (_, row) => (
          <Space size={4}>
            {row.labels?.map((label) => (
              <Tag color="blue" key={label}>
                {label}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '状态',
        dataIndex: 'status',
        valueType: 'select',
        valueEnum: {
          open: { text: '未解决', status: 'Error' },
          closed: { text: '已解决', status: 'Success' },
          processing: { text: '处理中', status: 'Processing' },
        },
      },
      {
        title: '更新时间',
        dataIndex: 'updatedAt',
        valueType: 'date',
        search: false,
        listSlot: 'description',
      },
      {
        title: '操作',
        listSlot: 'actions',
        search: false,
        render: () => [<a key="edit">编辑</a>, <a key="delete">删除</a>],
      },
    ];
    
    export default () => {
      const [viewMode, setViewMode] = useState<'list' | 'table'>('list');
    
      return (
        <div style={{ padding: 24 }}>
          <Radio.Group
            value={viewMode}
            onChange={(e) => setViewMode(e.target.value)}
            style={{ marginBottom: 16 }}
            optionType="button"
            buttonStyle="solid"
            options={[
              { label: '列表视图', value: 'list' },
              { label: '表格视图', value: 'table' },
            ]}
          />
          {viewMode === 'list' ? (
            <ProList<DataItem>
              rowKey="id"
              headerTitle="列表视图"
              columns={columns}
              dataSource={dataSource}
            />
          ) : (
            <ProTable<DataItem>
              rowKey="id"
              headerTitle="表格视图"
              columns={columns}
              dataSource={dataSource}
              search={false}
              pagination={false}
            />
          )}
        </div>
      );
    };
    

    搜索列表(columns + request)

    搜索列表(columns API)
    暂无数据
    暂无数据
    • 第 0-0 条/总共 0 条
    • 1
    /**
     * columns API 配合 request 和搜索表单
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Button, Space, Tag } from 'antd';
    import request from 'umi-request';
    
    type GithubIssueItem = {
      url: string;
      id: number;
      number: number;
      title: string;
      labels: {
        name: string;
        color: string;
      }[];
      state: string;
      comments: number;
      created_at: string;
      updated_at: string;
      closed_at?: string;
    };
    
    const columns: ProColumns<GithubIssueItem>[] = [
      {
        title: '用户',
        dataIndex: 'user',
        listSlot: 'title',
      },
      {
        dataIndex: 'avatar',
        listSlot: 'avatar',
        search: false,
      },
      {
        dataIndex: 'title',
        listSlot: 'description',
        search: false,
      },
      {
        dataIndex: 'labels',
        listSlot: 'subTitle',
        search: false,
        render: (_, row) => (
          <Space size={8}>
            {row.labels?.map((label: { name: string }) => (
              <Tag color="blue" key={label.name}>
                {label.name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        listSlot: 'actions',
        search: false,
        render: (_, row) => [
          <a href={row.url} target="_blank" rel="noopener noreferrer" key="link">
            链路
          </a>,
          <a href={row.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
        ],
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum: {
          all: { text: '全部', status: 'Default' },
          open: { text: '未解决', status: 'Error' },
          closed: { text: '已解决', status: 'Success' },
        },
      },
    ];
    
    const Demo = () => (
      <ProList<GithubIssueItem>
        toolBarRender={() => [
          <Button key="add" type="primary">
            新建
          </Button>,
        ]}
        search={{ filterType: 'light' }}
        rowKey="id"
        headerTitle="搜索列表(columns API)"
        request={async (params = {} as Record<string, any>) =>
          request<{ data: GithubIssueItem[] }>(
            'https://proapi.azurewebsites.net/github/issues',
            { params },
          )
        }
        pagination={{ pageSize: 5 }}
        columns={columns}
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    可编辑列表(columns)

    可编辑列表(columns API)

    智慧零售平台
    Ant Design
    可视化

    我是一条测试的描述

    Ant Design
    Ant Design
    可视化

    我是一条测试的描述

    云原生微服务框架
    Ant Design
    可视化

    我是一条测试的描述
    /**
     * columns API 配合可编辑列表
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Space, Tag } from 'antd';
    import { useState } from 'react';
    
    const defaultData = [
      {
        id: '1',
        name: '智慧零售平台',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
      {
        id: '2',
        name: 'Ant Design',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
      {
        id: '3',
        name: '云原生微服务框架',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
    ];
    
    type DataItem = (typeof defaultData)[number];
    
    const columns: ProColumns<DataItem>[] = [
      {
        title: '名称',
        dataIndex: 'name',
        listSlot: 'title',
      },
      {
        dataIndex: 'image',
        listSlot: 'avatar',
        editable: false,
      },
      {
        title: '描述',
        dataIndex: 'desc',
        listSlot: 'description',
      },
      {
        listSlot: 'subTitle',
        search: false,
        editable: false,
        render: () => (
          <Space size={8}>
            <Tag color="blue">Ant Design</Tag>
            <Tag color="#5BD8A6">可视化</Tag>
          </Space>
        ),
      },
      {
        listSlot: 'actions',
        search: false,
        render: (_, row, __, action) => [
          <a
            onClick={() => {
              action?.startEditable(row.id);
            }}
            key="edit"
          >
            编辑
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      const [dataSource, setDataSource] = useState<DataItem[]>(defaultData);
      return (
        <ProList<DataItem>
          rowKey="id"
          headerTitle="可编辑列表(columns API)"
          dataSource={dataSource}
          editable={{
            onSave: async (key, record, originRow) => {
              console.log(key, record, originRow);
              return true;
            },
          }}
          onDataSourceChange={setDataSource}
          columns={columns}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    编辑列表

    基础列表

    智慧零售平台
    Ant Design
    可视化

    我是一条测试的描述

    Ant Design
    Ant Design
    可视化

    我是一条测试的描述

    云原生微服务框架
    Ant Design
    可视化

    我是一条测试的描述

    数据可视化引擎
    Ant Design
    可视化

    我是一条测试的描述
    import { ProList } from '@ant-design/pro-components';
    import { Space, Tag } from 'antd';
    import { useState } from 'react';
    
    const defaultData = [
      {
        id: '1',
        name: '智慧零售平台',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
      {
        id: '2',
        name: 'Ant Design',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
      {
        id: '3',
        name: '云原生微服务框架',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
      {
        id: '4',
        name: '数据可视化引擎',
        image:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        desc: '我是一条测试的描述',
      },
    ];
    
    type DataItem = (typeof defaultData)[number];
    
    const Demo = () => {
      const [dataSource, setDataSource] = useState<DataItem[]>(defaultData);
      return (
        <ProList<DataItem>
          rowKey="id"
          headerTitle="基础列表"
          dataSource={dataSource}
          editable={{
            onSave: async (_key, _record, _originRow) => {
    
              return true;
            },
          }}
          onDataSourceChange={setDataSource}
          columns={[
            { dataIndex: 'name', listSlot: 'title' },
            { dataIndex: 'image', listSlot: 'avatar', editable: false },
            { dataIndex: 'desc', listSlot: 'description' },
            {
              listSlot: 'subTitle',
              render: () => (
                <Space size={8}>
                  <Tag color="blue">Ant Design</Tag>
                  <Tag color="#5BD8A6">可视化</Tag>
                </Space>
              ),
            },
            {
              listSlot: 'actions',
              render: (text, row, index, action) => [
                <a
                  onClick={() => {
                    action?.startEditable(row.id);
                  }}
                  key="link"
                >
                  编辑
                </a>,
              ],
            },
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    带工具栏的列表

    全部实验室99
    我创建的实验室32

    实验名称1

    系统性的沉淀B端知识体系
    模型数
    2903
    指标数
    3720
    实验状态
    成功

    实验名称2

    系统性的沉淀B端知识体系
    模型数
    2904
    指标数
    3721
    实验状态
    成功

    实验名称3

    系统性的沉淀B端知识体系
    模型数
    2905
    指标数
    3722
    实验状态
    成功
    import type { ActionType } from '@ant-design/pro-components';
    import { ProList } from '@ant-design/pro-components';
    import { Badge, Button } from 'antd';
    import React, { useRef, useState } from 'react';
    
    const dataSource = [
      {
        name: '实验名称1',
        desc: '系统性的沉淀B端知识体系',
        content: [
          {
            label: '模型数',
            value: 2903,
          },
          {
            label: '指标数',
            value: 3720,
          },
          {
            label: '实验状态',
            value: '成功',
            status: 'success',
          },
        ],
      },
      {
        name: '实验名称2',
        desc: '系统性的沉淀B端知识体系',
        content: [
          {
            label: '模型数',
            value: 2904,
          },
          {
            label: '指标数',
            value: 3721,
          },
          {
            label: '实验状态',
            value: '成功',
            status: 'success',
          },
        ],
      },
      {
        name: '实验名称3',
        desc: '系统性的沉淀B端知识体系',
        content: [
          {
            label: '模型数',
            value: 2905,
          },
          {
            label: '指标数',
            value: 3722,
          },
          {
            label: '实验状态',
            value: '成功',
            status: 'success',
          },
        ],
      },
    ];
    
    const renderBadge = (count: number, active = false) => {
      return (
        <Badge
          count={count}
          style={{
            marginBlockStart: -2,
            marginInlineStart: 4,
            color: active ? '#1890FF' : '#999',
            backgroundColor: active ? '#E6F7FF' : '#eee',
          }}
        />
      );
    };
    
    const Demo = () => {
      const [activeKey, setActiveKey] = useState<React.Key | undefined>('tab1');
      const action = useRef<ActionType>();
      return (
        <ProList<any>
          rowKey="name"
          actionRef={action}
          dataSource={dataSource}
          editable={{}}
          columns={[
            {
              dataIndex: 'name',
              listSlot: 'title',
              valueType: 'select',
              fieldProps: {
                showSearch: true,
                placement: 'bottomRight',
                options: [{ label: '实验名称1', value: '实验名称1' }],
              },
            },
            { dataIndex: 'desc', listSlot: 'description' },
            {
              dataIndex: 'content',
              listSlot: 'content',
              render: (text) => (
                <div
                  key="label"
                  style={{ display: 'flex', justifyContent: 'space-around' }}
                >
                  {(text as any[]).map((t) => (
                    <div key={t.label}>
                      <div>{t.label}</div>
                      <div>
                        {t.status === 'success' && (
                          <span
                            style={{
                              display: 'inline-block',
                              width: 8,
                              height: 8,
                              borderRadius: '50%',
                              backgroundColor: '#52c41a',
                              marginInlineEnd: 8,
                            }}
                          />
                        )}
                        {t.value}
                      </div>
                    </div>
                  ))}
                </div>
              ),
            },
            {
              listSlot: 'actions',
              render: (text, row) => [
                <a
                  key="edit"
                  onClick={() => action.current?.startEditable(row.name)}
                >
                  编辑
                </a>,
                <a key="copy">复制</a>,
                <a key="delete">删除</a>,
              ],
            },
          ]}
          toolbar={{
            menu: {
              activeKey,
              items: [
                {
                  key: 'tab1',
                  label: (
                    <span>全部实验室{renderBadge(99, activeKey === 'tab1')}</span>
                  ),
                },
                {
                  key: 'tab2',
                  label: (
                    <span>
                      我创建的实验室{renderBadge(32, activeKey === 'tab2')}
                    </span>
                  ),
                },
              ],
              onChange(key) {
                setActiveKey(key);
              },
            },
            search: {
              onSearch: (value: string) => {
                alert(value);
              },
            },
            actions: [
              <Button type="primary" key="primary">
                新建实验
              </Button>,
            ],
          }}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    支持展开的列表

    支持展开的列表

    智慧零售平台
    Ant Design
    可视化

    Ant Design
    Ant Design
    可视化

    云原生微服务框架
    Ant Design
    可视化

    数据可视化引擎
    Ant Design
    可视化

    import { ProList } from '@ant-design/pro-components';
    import { Button, Progress, Space, Tag } from 'antd';
    import type { Key } from 'react';
    import { useState } from 'react';
    
    const dataSource = [
      {
        title: '智慧零售平台',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: 'Ant Design',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: '云原生微服务框架',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: '数据可视化引擎',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
    ];
    
    const Demo = () => {
      const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
    
      return (
        <ProList<{ title: string }>
          rowKey="title"
          headerTitle="支持展开的列表"
          toolBarRender={() => {
            return [
              <Button key="3" type="primary">
                新建
              </Button>,
            ];
          }}
          expandable={{ expandedRowKeys, onExpandedRowsChange: setExpandedRowKeys }}
          dataSource={dataSource}
          columns={[
            { dataIndex: 'title', listSlot: 'title' },
            {
              listSlot: 'subTitle',
              render: () => (
                <Space size={8}>
                  <Tag color="blue">Ant Design</Tag>
                  <Tag color="#5BD8A6">可视化</Tag>
                </Space>
              ),
            },
            {
              listSlot: 'description',
              render: () => '面向企业级中后台的设计解决方案',
            },
            { dataIndex: 'avatar', listSlot: 'avatar' },
            {
              listSlot: 'content',
              render: () => (
                <div
                  style={{
                    minWidth: 200,
                    flex: 1,
                    display: 'flex',
                    justifyContent: 'flex-end',
                  }}
                >
                  <div
                    style={{
                      width: '200px',
                    }}
                  >
                    <div>发布中</div>
                    <Progress percent={80} />
                  </div>
                </div>
              ),
            },
            {
              listSlot: 'actions',
              render: () => <a key="invite">邀请</a>,
            },
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    支持选中的列表

    支持选中的列表

    智慧零售平台

    面向企业级中后台的设计解决方案
    发布中
    80%
    邀请

    Ant Design

    面向企业级中后台的设计解决方案
    发布中
    80%
    邀请

    云原生微服务框架

    面向企业级中后台的设计解决方案
    发布中
    80%
    邀请

    数据可视化引擎

    面向企业级中后台的设计解决方案
    发布中
    80%
    邀请
    import { ProList } from '@ant-design/pro-components';
    import { Button, Progress } from 'antd';
    import type { Key } from 'react';
    import { useState } from 'react';
    
    const dataSource = [
      {
        title: '智慧零售平台',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: 'Ant Design',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: '云原生微服务框架',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
      {
        title: '数据可视化引擎',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
      },
    ];
    
    const Demo = () => {
      const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
      const rowSelection = {
        selectedRowKeys,
        onChange: (keys: Key[]) => setSelectedRowKeys(keys),
      };
    
      return (
        <ProList<{ title: string }>
          toolBarRender={() => {
            return [
              <Button key="3" type="primary">
                新建
              </Button>,
            ];
          }}
          columns={[
            { dataIndex: 'title', listSlot: 'title' },
            {
              listSlot: 'description',
              render: () => '面向企业级中后台的设计解决方案',
            },
            { dataIndex: 'avatar', listSlot: 'avatar' },
            {
              listSlot: 'content',
              render: () => (
                <div
                  style={{
                    width: '200px',
                  }}
                >
                  <div>发布中</div>
                  <Progress percent={80} />
                </div>
              ),
            },
            {
              listSlot: 'actions',
              render: () => [
                <a key="init">邀请</a>,
                <Button key="publish" type="text">
                  发布
                </Button>,
              ],
            },
          ]}
          rowKey="title"
          headerTitle="支持选中的列表"
          rowSelection={rowSelection}
          dataSource={dataSource}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    查询列表

    基础列表
    暂无数据
    暂无数据
    • 第 0-0 条/总共 0 条
    • 1
    import { ProList } from '@ant-design/pro-components';
    import { Button, Space, Tag } from 'antd';
    import request from 'umi-request';
    
    type GithubIssueItem = {
      url: string;
      id: number;
      number: number;
      title: string;
      labels: {
        name: string;
        color: string;
      }[];
      state: string;
      comments: number;
      created_at: string;
      updated_at: string;
      closed_at?: string;
    };
    
    const Demo = () => (
      <ProList<GithubIssueItem>
        toolBarRender={() => {
          return [
            <Button key="3" type="primary">
              新建
            </Button>,
          ];
        }}
        search={{}}
        rowKey="name"
        headerTitle="基础列表"
        request={async (params = {} as Record<string, any>) =>
          request<{
            data: GithubIssueItem[];
          }>('https://proapi.azurewebsites.net/github/issues', {
            params,
          })
        }
        pagination={{
          pageSize: 5,
        }}
        columns={[
          { dataIndex: 'user', listSlot: 'title', title: '用户' },
          { dataIndex: 'avatar', listSlot: 'avatar', search: false },
          { dataIndex: 'title', listSlot: 'description', search: false },
          {
            dataIndex: 'labels',
            listSlot: 'subTitle',
            search: false,
            render: (_, row) => (
              <Space size={0}>
                {row.labels?.map((label: { name: string }) => (
                  <Tag color="blue" key={label.name}>
                    {label.name}
                  </Tag>
                ))}
              </Space>
            ),
          },
          {
            listSlot: 'actions',
            search: false,
            render: (text, row) => [
              <a
                href={row.url}
                target="_blank"
                rel="noopener noreferrer"
                key="link"
              >
                详情
              </a>,
              <a
                href={row.url}
                target="_blank"
                rel="noopener noreferrer"
                key="view"
              >
                查看
              </a>,
            ],
          },
          {
            title: '状态',
            dataIndex: 'status',
            valueType: 'select',
            valueEnum: {
              all: { text: '全部', status: 'Default' },
              open: { text: '未解决', status: 'Error' },
              closed: { text: '已解决', status: 'Success' },
              processing: { text: '解决中', status: 'Processing' },
            },
          },
        ]}
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    带筛选和异步请求的列表

    基础列表
    暂无数据
    暂无数据
    • 第 0-0 条/总共 0 条
    • 1
    import { ProList } from '@ant-design/pro-components';
    import { Button, Space, Tag } from 'antd';
    import request from 'umi-request';
    
    type GithubIssueItem = {
      url: string;
      id: number;
      number: number;
      title: string;
      labels: {
        name: string;
        color: string;
      }[];
      state: string;
      comments: number;
      created_at: string;
      updated_at: string;
      closed_at?: string;
    };
    
    const Demo = () => (
      <ProList<GithubIssueItem>
        toolBarRender={() => {
          return [
            <Button key="3" type="primary">
              新建
            </Button>,
          ];
        }}
        search={{
          filterType: 'light',
        }}
        rowKey="name"
        headerTitle="基础列表"
        request={async (params = {} as Record<string, any>) =>
          request<{
            data: GithubIssueItem[];
          }>('https://proapi.azurewebsites.net/github/issues', {
            params,
          })
        }
        pagination={{
          pageSize: 5,
        }}
        columns={[
          { dataIndex: 'user', listSlot: 'title', title: '用户' },
          { dataIndex: 'avatar', listSlot: 'avatar', search: false },
          { dataIndex: 'title', listSlot: 'description', search: false },
          {
            dataIndex: 'labels',
            listSlot: 'subTitle',
            search: false,
            render: (_, row) => (
              <Space size={8}>
                {row.labels?.map((label: { name: string }) => (
                  <Tag color="blue" key={label.name}>
                    {label.name}
                  </Tag>
                ))}
              </Space>
            ),
          },
          {
            listSlot: 'actions',
            search: false,
            render: (text, row) => [
              <a
                href={row.url}
                target="_blank"
                rel="noopener noreferrer"
                key="link"
              >
                详情
              </a>,
              <a
                href={row.url}
                target="_blank"
                rel="noopener noreferrer"
                key="view"
              >
                查看
              </a>,
            ],
          },
          {
            title: '状态',
            dataIndex: 'status',
            valueType: 'select',
            valueEnum: {
              all: { text: '全部', status: 'Default' },
              open: { text: '未解决', status: 'Error' },
              closed: { text: '已解决', status: 'Success' },
              processing: { text: '解决中', status: 'Processing' },
            },
          },
        ]}
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    大小和分割线

    大小:
    default
    分割线:
    有


    大小和分割线

    智慧零售平台

    Ant Design Pro

    云原生微服务框架

    数据可视化引擎

    import { ProList } from '@ant-design/pro-components';
    import { Button, Progress, Select, Tag } from 'antd';
    import type { Key } from 'react';
    import { useState } from 'react';
    
    type ProjectItem = {
      title: string;
      avatar: string;
      description: string;
      progress: number;
      status: string;
    };
    
    const dataSource: ProjectItem[] = [
      {
        title: '智慧零售平台',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '面向线下门店的数字化经营解决方案',
        progress: 85,
        status: '开发中',
      },
      {
        title: 'Ant Design Pro',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '开箱即用的中台前端解决方案',
        progress: 100,
        status: '已上线',
      },
      {
        title: '云原生微服务框架',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '基于 K8s 的微服务开发与治理框架',
        progress: 92,
        status: '测试中',
      },
      {
        title: '数据可视化引擎',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        description: '企业级数据看板与图表分析工具',
        progress: 60,
        status: '开发中',
      },
    ];
    
    const Demo = () => {
      const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
      const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
      const [size, setSize] = useState<'small' | 'default' | 'large' | undefined>(
        'default',
      );
      const [split, setSplit] = useState<0 | 1>(1);
      const rowSelection = {
        selectedRowKeys,
        onChange: (keys: Key[]) => setSelectedRowKeys(keys),
      };
    
      return (
        <>
          大小:
          <Select<string>
            value={size}
            onChange={(value) => setSize(value as any)}
            options={['small', 'default', 'large'].map((selectSize) => ({
              value: selectSize,
              label: selectSize,
            }))}
          />{' '}
          分割线:
          <Select<0 | 1>
            value={split}
            onChange={(value) => setSplit(value)}
            options={[
              { value: 1, label: '有' },
              { value: 0, label: '无' },
            ]}
          />{' '}
          <br />
          <br />
          <ProList<ProjectItem>
            size={size}
            split={split === 1}
            toolBarRender={() => {
              return [
                <Button key="new" type="primary">
                  新建
                </Button>,
              ];
            }}
            columns={[
              { dataIndex: 'title', listSlot: 'title' },
              { dataIndex: 'description', listSlot: 'description' },
              { dataIndex: 'avatar', listSlot: 'avatar' },
              {
                listSlot: 'content',
                render: (_, record) => (
                  <div
                    style={{
                      minWidth: 200,
                      flex: 1,
                      display: 'flex',
                      justifyContent: 'flex-end',
                    }}
                  >
                    <div style={{ width: 200 }}>
                      <div>
                        {record.status}{' '}
                        <Tag
                          color={record.progress === 100 ? 'success' : 'processing'}
                        >
                          {record.progress}%
                        </Tag>
                      </div>
                      <Progress percent={record.progress} showInfo={false} />
                    </div>
                  </div>
                ),
              },
              {
                listSlot: 'actions',
                render: () => [<a key="invite">邀请</a>],
              },
            ]}
            expandable={{
              expandedRowKeys,
              defaultExpandAllRows: false,
              onExpandedRowsChange: setExpandedRowKeys,
            }}
            rowKey="title"
            headerTitle="大小和分割线"
            rowSelection={rowSelection}
            dataSource={dataSource}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    竖排样式

    竖排样式

    智慧零售平台

    技术专栏
    设计语言
    云原生
    面向企业级中后台的数据可视化解决方案,以最小的接入成本提供丰富的图表类型与交互能力,助力业务快速搭建数据看板与分析报表。
    1561562
    logo

    Ant Design

    技术专栏
    设计语言
    云原生
    面向企业级中后台的数据可视化解决方案,以最小的接入成本提供丰富的图表类型与交互能力,助力业务快速搭建数据看板与分析报表。
    1561562
    logo

    云原生微服务框架

    技术专栏
    设计语言
    云原生
    面向企业级中后台的数据可视化解决方案,以最小的接入成本提供丰富的图表类型与交互能力,助力业务快速搭建数据看板与分析报表。
    1561562
    logo

    数据可视化引擎

    技术专栏
    设计语言
    云原生
    面向企业级中后台的数据可视化解决方案,以最小的接入成本提供丰富的图表类型与交互能力,助力业务快速搭建数据看板与分析报表。
    1561562
    logo
    import { LikeOutlined, MessageOutlined, StarOutlined } from '@ant-design/icons';
    import { ProList } from '@ant-design/pro-components';
    import { Button, Space, Tag } from 'antd';
    import React from 'react';
    
    const IconText = ({ icon, text }: { icon: any; text: string }) => (
      <span>
        {React.createElement(icon, { style: { marginInlineEnd: 8 } })}
        {text}
      </span>
    );
    
    const dataSource = [
      {
        title: '智慧零售平台',
      },
      {
        title: 'Ant Design',
      },
      {
        title: '云原生微服务框架',
      },
      {
        title: '数据可视化引擎',
      },
    ];
    
    const Demo = () => {
      return (
        <ProList<{ title: string }>
          toolBarRender={() => {
            return [
              <Button key="3" type="primary">
                新建
              </Button>,
            ];
          }}
          itemLayout="vertical"
          rowKey="id"
          headerTitle="竖排样式"
          dataSource={dataSource}
          columns={[
            { dataIndex: 'title', listSlot: 'title' },
            {
              listSlot: 'description',
              render: () => (
                <Space orientation="horizontal">
                  <Tag>技术专栏</Tag>
                  <Tag>设计语言</Tag>
                  <Tag>云原生</Tag>
                </Space>
              ),
            },
            {
              listSlot: 'actions',
              render: () => [
                <IconText icon={StarOutlined} text="156" key="star" />,
                <IconText icon={LikeOutlined} text="156" key="like" />,
                <IconText icon={MessageOutlined} text="2" key="message" />,
              ],
            },
            {
              listSlot: 'aside',
              render: () => (
                <img
                  width={272}
                  alt="logo"
                  src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png"
                />
              ),
            },
            {
              listSlot: 'content',
              render: () => (
                <div>
                  面向企业级中后台的数据可视化解决方案,以最小的接入成本提供丰富的图表类型与交互能力,助力业务快速搭建数据看板与分析报表。
                </div>
              ),
            },
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    一些预设的模式

    预设的列状态

    智慧零售平台(top)
    技术专栏

    Ant Design Pro(inline)
    技术专栏

    云原生微服务框架(new)
    技术专栏

    数据可视化引擎
    技术专栏

    import { EllipsisOutlined } from '@ant-design/icons';
    import { ProList } from '@ant-design/pro-components';
    import { Button, Progress, Tag } from 'antd';
    import React, { Key, useState } from 'react';
    
    const types = ['top', 'inline', 'new'];
    const data = [
      '智慧零售平台(top)',
      'Ant Design Pro(inline)',
      '云原生微服务框架(new)',
      '数据可视化引擎',
    ].map((item, index) => ({
      title: item,
      subTitle: <Tag color="#5BD8A6">技术专栏</Tag>,
      actions: [
        <a key="invite">邀请</a>,
        <a key="operate">操作</a>,
        <a key="rest">
          <EllipsisOutlined />
        </a>,
      ],
      description: (
        <div>
          <div>top 会有小角标</div>
          <div>inline 标题字体是 normal</div>
          <div>new 会有一个入场动画</div>
        </div>
      ),
      type: types[index],
      avatar:
        'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
      content: (
        <div
          style={{
            flex: 1,
            display: 'flex',
            justifyContent: 'flex-end',
          }}
        >
          <div
            style={{
              width: 200,
            }}
          >
            <div>发布中</div>
            <Progress percent={80} />
          </div>
        </div>
      ),
    }));
    
    const Demo = () => {
      const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
      const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
      const rowSelection = {
        selectedRowKeys,
        onChange: (keys: Key[]) => setSelectedRowKeys(keys),
      };
      const [dataSource, setDataSource] = useState<any[]>([...data] as any[]);
    
      return (
        <>
          <ProList<{
            title: string;
            subTitle: React.JSX.Element;
            actions: React.JSX.Element[];
            description: React.JSX.Element;
            type?: 'top' | 'inline' | 'new';
            avatar: string;
            children: React.JSX.Element;
          }>
            columns={[
              { dataIndex: 'title', listSlot: 'title' },
              { dataIndex: 'subTitle', listSlot: 'subTitle' },
              { dataIndex: 'type', listSlot: 'type' },
              { dataIndex: 'description', listSlot: 'description' },
              { dataIndex: 'avatar', listSlot: 'avatar' },
              { dataIndex: 'content', listSlot: 'content' },
              { dataIndex: 'actions', listSlot: 'actions' },
            ]}
            toolBarRender={() => [
              <Button
                key="3"
                type="primary"
                onClick={() => {
                  setDataSource([...data.map((item) => ({ ...item }))]);
                  setTimeout(() => {
                    const list = [...data.map((item) => ({ ...item }))];
                    list[1].type = 'new';
                    setDataSource(list);
                  }, 0);
                }}
              >
                刷新
              </Button>,
            ]}
            rowKey="id"
            headerTitle="预设的列状态"
            rowSelection={rowSelection}
            dataSource={dataSource}
            expandable={{
              expandedRowKeys,
              onExpandedRowsChange: setExpandedRowKeys,
            }}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    翻页

    翻页

    智慧零售平台
    技术专栏

    发布中
    80%

    Ant Design Pro
    技术专栏

    发布中
    80%

    云原生微服务框架
    技术专栏

    发布中
    80%

    数据可视化引擎
    技术专栏

    发布中
    80%

    智能客服系统
    技术专栏

    发布中
    80%
    • 第 1-5 条/总共 7 条
    • 1
    • 2
    import { EllipsisOutlined } from '@ant-design/icons';
    import { ProList } from '@ant-design/pro-components';
    import { Progress, Tag } from 'antd';
    
    const data = [
      '智慧零售平台',
      'Ant Design Pro',
      '云原生微服务框架',
      '数据可视化引擎',
      '智能客服系统',
      'DevOps 工具链',
      '统一权限管理中心',
    ].map((item) => ({
      title: item,
      subTitle: <Tag color="#5BD8A6">技术专栏</Tag>,
      actions: [
        <a key="invite">邀请</a>,
        <a key="operate">操作</a>,
        <a key="rest">
          <EllipsisOutlined />
        </a>,
      ],
      avatar:
        'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
      content: (
        <div
          style={{
            flex: 1,
            display: 'flex',
            justifyContent: 'flex-end',
          }}
        >
          <div
            style={{
              width: 200,
            }}
          >
            <div>发布中</div>
            <Progress percent={80} />
          </div>
        </div>
      ),
    }));
    
    const Demo = () => {
      return (
        <ProList<any>
          pagination={{
            defaultPageSize: 5,
            showSizeChanger: true,
          }}
          columns={[
            { dataIndex: 'title', listSlot: 'title' },
            { dataIndex: 'subTitle', listSlot: 'subTitle' },
            { dataIndex: 'type', listSlot: 'type' },
            { dataIndex: 'avatar', listSlot: 'avatar' },
            { dataIndex: 'content', listSlot: 'content' },
            { dataIndex: 'actions', listSlot: 'actions' },
          ]}
          headerTitle="翻页"
          dataSource={data}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    自定义列表项(itemRender)

    通过 itemRender 自定义每一项的渲染,可基于默认内容 defaultDom(React.ReactElement)进行包装或完全自定义。

    帆软 SSO
    FineReport 是一款用于报表制作、分析和展示的软件,支持数据填报与可视化大屏。
    泛微 E9 SSO
    泛微 E9 是一款成熟的协同办公软件,以流程管理、知识管理为核心。
    销售易
    SAML (Security Assertion Markup Language) 是一种用于身份认证与授权的标准协议。
    import { ProList } from '@ant-design/pro-components';
    import { Avatar, theme } from 'antd';
    
    const APPLICATIONS = [
      {
        id: '1',
        title: '帆软 SSO',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
        description:
          'FineReport 是一款用于报表制作、分析和展示的软件,支持数据填报与可视化大屏。',
      },
      {
        id: '2',
        title: '泛微 E9 SSO',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
        description:
          '泛微 E9 是一款成熟的协同办公软件,以流程管理、知识管理为核心。',
      },
      {
        id: '3',
        title: '销售易',
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
        description:
          'SAML (Security Assertion Markup Language) 是一种用于身份认证与授权的标准协议。',
      },
    ];
    
    type AppItem = (typeof APPLICATIONS)[0];
    
    export default () => {
      const { token } = theme.useToken();
      return (
        <div
          style={{
            backgroundColor: token.colorBgLayout,
            margin: -24,
            padding: 64,
          }}
        >
          <ProList<AppItem>
            rowKey="id"
            split
            grid={{
              xs: 1,
              sm: 2,
              md: 2,
              lg: 4,
              xl: 4,
              xxl: 4,
              gutter: [16, 16],
            }}
            pagination={false}
            columns={[
              { dataIndex: 'title', listSlot: 'title' },
              { dataIndex: 'avatar', listSlot: 'avatar' },
              { dataIndex: 'description', listSlot: 'description' },
            ]}
            dataSource={APPLICATIONS}
            toolbar={{
              menu: {
                type: 'tab',
                items: [
                  { key: 'all', label: '全部应用' },
                  { key: 'dev', label: '开发类' },
                  { key: 'ops', label: '运维类' },
                  { key: 'office', label: '办公类' },
                ],
              },
            }}
            itemRender={(item) => (
              <div
                style={{
                  width: '100%',
                  minWidth: 0,
                  boxSizing: 'border-box',
                  borderRadius: 8,
                  padding: 24,
                  height: '100%',
                  cursor: 'pointer',
                  boxShadow: '0 1px 2px rgba(0,0,0,0.03)',
                  background: token.colorBgContainer,
                }}
                tabIndex={0}
              >
                <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
                  <Avatar
                    src={item.avatar}
                    shape="square"
                    size={48}
                    style={{ flexShrink: 0 }}
                  />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div
                      style={{
                        fontWeight: 600,
                        fontSize: 16,
                        marginBottom: 4,
                      }}
                    >
                      {item.title}
                    </div>
                    <div
                      style={{
                        color: token.colorTextSecondary,
                        fontSize: 14,
                        lineHeight: 1.5,
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        display: '-webkit-box',
                        WebkitLineClamp: 2,
                        WebkitBoxOrient: 'vertical',
                      }}
                    >
                      {item.description}
                    </div>
                  </div>
                </div>
              </div>
            )}
          />
        </div>
      );
    };
    

    API

    ProList 基于 ProTable 封装,支持两种列配置方式:

    • columns + listSlot(推荐):与 ProTable 共用相同的 columns 数组,通过 listSlot 指定每列映射到列表项的哪个插槽位置。同一份 columns 可同时用于 ProTable 和 ProList,便于在表格和列表之间切换。
    • metas(已废弃):旧的配置方式,使用对象的键名来映射列表项的各个部分。仍可正常使用,但推荐迁移到 columns + listSlot。

    其余 API 与 ProTable 相同。

    request

    request 是 ProList 最重要的 API,与 ProTable 用法一致。request 会接收一个对象,对象中必须要有 data 和 success,如果需要手动分页 total 也是必需的。request 会接管 loading 的设置,同时在查询表单查询时和 params 参数发生修改时重新执行。

    <ProList<DataType, Params>
      params={params}
      request={async (params, sort, filter) => {
        const msg = await myQuery({
          page: params.current,
          pageSize: params.pageSize,
        });
        return {
          data: msg.result,
          success: true,
          total: msg.total,
        };
      }}
    />

    ProList

    属性描述类型默认值
    columns列配置,与 ProTable 相同,通过 listSlot 指定列表项插槽,详见 columns 配置ProColumns<T>[]-
    metas已废弃 列表项配置,详见 Metas 配置,推荐使用 columns + listSlotMetas-
    dataSource与 antd 相同的配置,ProList 推荐使用 request 来加载T[]-
    request获取 dataSource 的方法(params: U & { pageSize?: number; current?: number; keyword?: string }, sort: Record<string, SortOrder>, filter: Record<string, FilterValue>) => Promise<{ data: T[]; success?: boolean; total?: number }>-
    params用于 request 查询的额外参数,一旦变化会触发重新加载U-
    postData对通过 request 获取的数据进行处理(data: T[]) => T[]-
    defaultData默认的数据T[]-
    onDataSourceChange数据发生改变时触发(dataSource: T[]) => void-
    actionRefTable action 的引用,便于自定义触发React.Ref<ActionType | undefined>-
    formRef可以获取到查询表单的 form 实例,用于一些灵活的配置TableFormItem<T>['formRef']-
    rowKey行的 key,一般是行 id,未设置时依次尝试 item.key、行索引keyof T | (item: T) => React.Key-
    headerTitle左上角的 titleReactNode-
    tooltip标题旁边的 tooltipstring | LabelTooltipType-
    loading是否加载中boolean | { spinning?: boolean }false
    split是否有分割线booleantrue
    variant列表外观变体'outlined' | 'borderless' | 'filled''borderless'
    showActions何时展示操作区(actions),'hover' 时悬浮或聚焦列表项才显示'hover' | 'always''always'
    showExtra何时展示附属内容(aside 插槽映射的 extra 区域),'hover' 时悬浮列表项才显示,CardList 模式下不生效'hover' | 'always''always'
    footer列表底部ReactNode-
    grid栅格配置,开启后以卡片模式渲染ListGridType-
    itemLayout列表项布局方向'horizontal' | 'vertical''horizontal'
    locale国际化配置{ emptyText?: ReactNode }-
    pagination分页器的配置,current 和 pageSize 会被 request 接管PaginationConfig | falsefalse
    rowSelection选择项配置TableProps<T>['rowSelection'] & { alwaysShowAlert?: boolean } | falsefalse
    expandable与 antd 相同的配置object | false-
    onRow与 antd 相同的配置,用户传入 grid 属性时列表以卡片模式渲染,此事件不触发,请使用 onItemfunction(record, index)-
    onItem与 antd 相同的配置,在所有类型点击某个项目都会触发该事件function(record, index)-
    itemRender自定义列表项渲染,defaultDom 为默认列表项元素,可基于其包装或完全自定义(item: T, index: number, defaultDom: React.ReactElement) => ReactNode-
    rowClassName自定义列表行的类名string | (item: T, index: number) => string-
    itemHeaderRender自定义每一列的 header,与 itemRender 不同的是,它会保留多选和展开收起((item: T, index: number, defaultDom: JSX.Element | null) => ReactNode) | false-
    itemTitleRender自定义每一列的 title 渲染((item: T, index: number, defaultDom: JSX.Element | null) => ReactNode) | false-
    itemCardProps自定义卡片列表的 props,只在卡片列表下生效CheckCardProps-
    toolBarRender渲染工具栏,支持返回一个 dom 数组,会自动增加 margin-rightToolBarProps<T>['toolBarRender'] | false-
    search是否显示搜索表单,传入对象时为搜索表单的配置false | SearchConfigfalse
    onLoad数据加载完成后触发,会多次触发(dataSource: T[]) => void-
    onLoadingChangeloading 被修改时触发,一般是网络请求导致的(loading: boolean | SpinProps | undefined) => void-
    onRequestError数据加载失败时触发(error: Error) => void-
    onSubmit提交表单时触发(params: U) => void-
    onReset重置表单时触发() => void-
    cardProps外面卡片的设置ProCardProps | false-
    editable可编辑列表的相关配置,详见 可编辑表格RowEditableConfig<T>-
    manualRequest是否需要手动触发首次请求booleanfalse
    ghost幽灵模式,即是否取消区域的 paddingbooleanfalse
    dateFormatter转化 dayjs 格式数据为特定类型,false 不做转化"string" | "number" | ((value: dayjs.Dayjs, valueType: string) => string | number) | false"string"
    ErrorBoundary自带了错误处理功能,防止白屏,ErrorBoundary=false 关闭默认错误边界React.ComponentClass<any, any> | false内置 ErrorBoundary

    ActionRef 手动触发

    有时我们要手动触发 ProList 的 reload 等操作,可以使用 actionRef,用法与 ProTable ActionRef 完全一致。

    方法描述类型
    reload刷新列表,如果传入 true 则重置页码(resetPageIndex?: boolean) => Promise<void>
    reloadAndRest刷新并清空,页码也会重置,不包括表单() => Promise<void>
    reset重置到默认值,包括表单() => void
    clearSelected清空选中项() => void
    startEditable开始编辑行(rowKey: Key) => boolean
    cancelEditable取消编辑行(rowKey: Key) => boolean
    const ref = useRef<ActionType>();
    
    <ProList actionRef={ref} />;
    
    // 刷新
    ref.current?.reload();
    
    // 刷新并清空,页码也会重置,不包括表单
    ref.current?.reloadAndRest();
    
    // 重置到默认值,包括表单
    ref.current?.reset();
    
    // 清空选中项
    ref.current?.clearSelected();

    columns 配置(推荐)

    同一份 columns 可以同时用于 ProTable(表格视图)和 ProList(列表视图),ProTable 会忽略 listSlot 属性,ProList 使用 listSlot 将数据映射到列表项的各个插槽位置。没有 listSlot 的列不会渲染到列表项中,但仍会参与搜索表单的生成。

    ProList 扩展的列属性

    属性描述类型默认值
    listSlot指定该列映射到列表项的哪个插槽位置'title' | 'subTitle' | 'avatar' | 'description' | 'content' | 'actions' | 'aside' | 'type'-

    其余列属性与 ProTable 的 ProColumns 完全一致(dataIndex、valueType、render、search、valueEnum 等),详见 ProTable columns。

    listSlot 插槽说明

    插槽值说明默认 valueType
    title列表项标题text
    subTitle列表项副标题text
    avatar列表项头像avatar
    description列表项描述textarea
    content列表项内容区域text
    actions列表项操作区option
    aside列表项附属内容,通常展示在右侧(如图片、进度条等非交互内容)text
    type列表项类型('new' | 'top' | 'inline')text

    使用示例

    import type { ProColumns } from '@ant-design/pro-components';
    
    // 同一份 columns 可同时用于 ProTable 和 ProList
    const columns: ProColumns<DataItem>[] = [
      { title: '名称', dataIndex: 'name', listSlot: 'title' },
      { dataIndex: 'avatar', listSlot: 'avatar', search: false },
      { dataIndex: 'desc', listSlot: 'description', search: false },
      {
        title: '标签',
        dataIndex: 'labels',
        listSlot: 'subTitle',
        search: false,
        render: (_, row) => <Tag>{row.label}</Tag>,
      },
      {
        title: '操作',
        listSlot: 'actions',
        search: false,
        render: (_, row) => [<a key="edit">编辑</a>],
      },
      {
        title: '状态',
        dataIndex: 'status',
        valueType: 'select',
        valueEnum: { open: { text: '未解决' }, closed: { text: '已解决' } },
        // 没有 listSlot,不渲染到列表项中,仅用于搜索
      },
    ];
    
    <ProList columns={columns} />  // 列表视图
    <ProTable columns={columns} /> // 表格视图

    Metas 配置(已废弃)

    已废弃:metas 仍可正常使用,但推荐迁移到 columns + listSlot。详见下方从 metas 迁移到 columns 指引。

    Metas 使用对象的键名来映射列表项各个部分(标题、头像、描述等)对应的数据字段。

    Metas.[Meta] 通用 API

    属性描述类型默认值
    dataIndex数据在数据项中对应的路径,支持通过数组查询嵌套路径string | string[]-
    title标题ReactNode-
    valueType值的类型,和 ProTable 一致,会生成不同的渲染器valueType'text'
    render自定义渲染函数(text: ReactNode, record: T, index: number) => ReactNode | ReactNode[]-
    valueEnum值的枚举,会自动转化把值当成 key 来取出要显示的内容valueEnum-
    search配置列的搜索相关,false 为隐藏boolean | { transform: (value: any) => any }-
    editable在编辑列表中是否可编辑boolean | (text: any, record: T, index: number) => boolean-
    fieldProps查询表单的 props,会透传给表单项(form, config) => Record | Record-
    formItemProps传递给 Form.Item 的配置(form, config) => formItemProps | formItemProps-
    formItemRender渲染查询表单的输入组件(item, { type, defaultRender, formItemProps, fieldProps, ...rest }, form) => ReactNode-
    keyReact 的 keyReact.Key-

    Metas.type

    对应 dataSource 的字段类型为 'new' | 'top' | 'inline'。

    属性描述类型默认值
    dataIndex--'type'

    Metas.title

    属性描述类型默认值
    dataIndex--'title'

    Metas.subTitle

    属性描述类型默认值
    dataIndex--'subTitle'

    Metas.description

    属性描述类型默认值
    dataIndex--'description'

    Metas.avatar

    属性描述类型默认值
    dataIndex--'avatar'

    Metas.actions

    属性描述类型默认值
    dataIndex--'actions'

    Metas.content

    属性描述类型默认值
    dataIndex--'content'

    metas 中仅支持 type、title、subTitle、description、avatar、content、actions 这些键。旧文档中的 Metas.extra 并不存在于类型定义中,右侧附属内容请使用 columns 的 listSlot: 'aside'(内部映射到列表项的 extra 区域)。

    批量操作

    与 ProTable 相同,批量操作需要设置 rowSelection 来开启。详见 ProTable 批量操作。

    属性描述类型默认值
    alwaysShowAlert总是展示 alert,默认无选择不展示(rowSelection 内置属性)boolean-
    tableAlertRender自定义批量操作工具栏左侧信息区域,false 时不显示({ selectedRowKeys: Key[], selectedRows: T[], onCleanSelected: () => void }) => ReactNode) | false-
    tableAlertOptionRender自定义批量操作工具栏右侧选项区域,false 时不显示({ selectedRowKeys: Key[], selectedRows: T[], onCleanSelected: () => void }) => ReactNode) | false-

    搜索表单

    ProList 会根据 columns 或 metas 中配置了 search 的字段来生成搜索表单,用法与 ProTable 搜索表单 一致。

    从 metas 迁移到 columns

    metas 已废弃,推荐迁移到 columns + listSlot。迁移规则非常简单:将 metas 对象的每个键值对转换为 columns 数组中的一个元素,键名对应 listSlot,值的属性直接展开到列配置中。

    迁移对照表

    metas 写法columns 写法
    title: { dataIndex: 'name' }{ dataIndex: 'name', listSlot: 'title' }
    avatar: { dataIndex: 'img' }{ dataIndex: 'img', listSlot: 'avatar' }
    description: { dataIndex: 'desc' }{ dataIndex: 'desc', listSlot: 'description' }
    content: {}{ dataIndex: 'content', listSlot: 'content' }
    extra: { render: ... }{ listSlot: 'aside', render: ... }
    status: { title: '状态', valueType: 'select', ... }{ title: '状态', dataIndex: 'status', valueType: 'select', ... }

    完整示例

    迁移前(metas):

    <ProList
      metas={{
        title: { dataIndex: 'name', title: '名称' },
        avatar: { dataIndex: 'avatar', search: false },
        description: { dataIndex: 'desc', search: false },
        subTitle: {
          dataIndex: 'labels',
          render: (_, row) => <Tag>{row.label}</Tag>,
          search: false,
        },
        actions: {
          render: (_, row) => [<a key="edit">编辑</a>],
          search: false,
        },
        status: {
          title: '状态',
          valueType: 'select',
          valueEnum: { open: { text: '未解决' }, closed: { text: '已解决' } },
        },
      }}
    />

    迁移后(columns + listSlot):

    <ProList
      columns={[
        { title: '名称', dataIndex: 'name', listSlot: 'title' },
        { dataIndex: 'avatar', listSlot: 'avatar', search: false },
        { dataIndex: 'desc', listSlot: 'description', search: false },
        {
          dataIndex: 'labels',
          listSlot: 'subTitle',
          render: (_, row) => <Tag>{row.label}</Tag>,
          search: false,
        },
        {
          listSlot: 'actions',
          render: (_, row) => [<a key="edit">编辑</a>],
          search: false,
        },
        {
          title: '状态',
          dataIndex: 'status',
          valueType: 'select',
          valueEnum: { open: { text: '未解决' }, closed: { text: '已解决' } },
        },
      ]}
    />

    提示:迁移后的 columns 可以直接传给 ProTable 使用,实现列表和表格视图的一键切换。