• English
  • Demos

    Code Demo

    Basic Usage

    Issue 管理
    标题
    状态
    标签
    创建时间
    操作
    暂无数据
    暂无数据
    Query Table
    import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, Dropdown, message, Space, Tag } from 'antd';
    import { useRef } from 'react';
    import request from 'umi-request';
    export const waitTimePromise = async (time: number = 100) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(true);
        }, time);
      });
    };
    
    export const waitTime = async (time: number = 100) => {
      await waitTimePromise(time);
    };
    
    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>[] = [
      {
        dataIndex: 'index',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: '标题',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tooltip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
      },
      {
        disable: true,
        title: '状态',
        dataIndex: 'state',
        filters: true,
        onFilter: true,
        ellipsis: true,
        valueType: 'select',
        valueEnum: {
          all: { text: '超长'.repeat(50) },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
            disabled: true,
          },
          processing: {
            text: '处理中',
            status: 'Processing',
          },
        },
      },
      {
        disable: true,
        title: '标签',
        dataIndex: 'labels',
        search: false,
        formItemRender: (_, { defaultRender }) => {
          return defaultRender(_);
        },
        render: (_, record) => (
          <Space>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'created_at',
        valueType: 'date',
        sorter: true,
        search: false,
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        valueType: 'dateRange',
        hideInTable: true,
        search: {
          transform: (value) => {
            return {
              startTime: value[0],
              endTime: value[1],
            };
          },
        },
      },
      {
        title: '操作',
        valueType: 'option',
        key: 'option',
        render: (text, record, _, action) => [
          <a
            key="editable"
            onClick={() => {
              action?.startEditable?.(record.id);
            }}
          >
            编辑
          </a>,
          <a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
          <TableDropdown
            key="actionGroup"
            onSelect={() => action?.reload()}
            menus={[
              { key: 'copy', name: '复制' },
              { key: 'delete', name: '删除' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
      return (
        <ProTable<GithubIssueItem>
          columns={columns}
          actionRef={actionRef}
          cardBordered
          request={async (params) => {
            await waitTime(2000);
            return request<{
              data: GithubIssueItem[];
            }>('https://proapi.azurewebsites.net/github/issues', {
              params,
            });
          }}
          editable={{
            type: 'multiple',
          }}
          columnsState={{
            persistenceKey: 'pro-table-singe-demos',
            persistenceType: 'localStorage',
            defaultValue: {
              option: { fixed: 'right', disable: true },
            },
            onChange: () => {
              message.info('列设置已更新');
            },
          }}
          rowKey="id"
          search={{
            labelWidth: 'auto',
          }}
          options={{
            setting: {
              listsHeight: 400,
            },
          }}
          form={{
            syncToUrl: (values, type) => {
              if (type === 'get') {
                return {
                  ...values,
                  created_at: [values.startTime, values.endTime],
                };
              }
              return values;
            },
          }}
          pagination={{
            pageSize: 5,
            onChange: (page, pageSize) => {
              message.info(`第 ${page} 页${pageSize ? `,每页 ${pageSize} 条` : ''}`);
            },
          }}
          dateFormatter="string"
          headerTitle="Issue 管理"
          toolBarRender={() => [
            <Button
              key="button"
              icon={<PlusOutlined />}
              onClick={() => {
                actionRef.current?.reload();
              }}
              type="primary"
            >
              新建
            </Button>,
            <Dropdown
              key="menu"
              menu={{
                items: [
                  { label: '导入数据', key: 'import' },
                  { label: '导出数据', key: 'export' },
                  { label: '批量分配', key: 'assign' },
                ],
              }}
            >
              <Button>
                <EllipsisOutlined />
              </Button>
            </Dropdown>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    微服务应用列表
    应用名称
    容器数量
    状态负责人操作
    用户认证服务3已关闭书琰
    订单处理中心6运行中逄一
    支付网关9已上线期贤
    商品管理服务12异常玄霜
    物流追踪系统3已关闭怀渊
    • 第 1-5 条/总共 5 条
    • 1
    Table without Search Form
    import { DownOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import {
      createTableDataSource,
      DEMO_CREATOR_VALUE_ENUM,
      DEMO_STATUS_VALUE_ENUM,
    } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
      status: string;
      createdAt: number;
      memo: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        width: 120,
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '状态',
        width: 80,
        dataIndex: 'status',
        initialValue: 'all',
        valueEnum: DEMO_STATUS_VALUE_ENUM,
      },
      {
        title: '负责人',
        width: 80,
        dataIndex: 'creator',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        width: 180,
        key: 'option',
        valueType: 'option',
        render: () => [
          <a key="detail">详情</a>,
          <a key="log">日志</a>,
          <a key="monitor">监控</a>,
          <TableDropdown
            key="actionGroup"
            menus={[
              { key: 'restart', name: '重启' },
              { key: 'delete', name: '下线' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          dataSource={tableListDataSource}
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          columns={columns}
          search={false}
          dateFormatter="string"
          headerTitle="微服务应用列表"
          toolBarRender={() => [
            <Button key="log">查看日志</Button>,
            <Button key="export">
              导出数据
              <DownOutlined />
            </Button>,
            <Button type="primary" key="primary">
              部署应用
            </Button>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    应用管理
    排序
    应用名称
    负责人
    状态
    备注操作
    暂无数据
    暂无数据
    Using DataSource
    import { EllipsisOutlined, SearchOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, Dropdown, Input } from 'antd';
    
    import {
      createTableDataSource,
      DEMO_CREATOR_VALUE_ENUM,
      DEMO_STATUS_VALUE_ENUM,
    } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
      status: string;
      createdAt: number;
      progress: number;
      money: number;
      memo: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
      withProgress: true,
      withMoney: true,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '排序',
        dataIndex: 'index',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
        filterDropdown: () => (
          <div style={{ padding: 8 }}>
            <Input style={{ width: 188, marginBlockEnd: 8, display: 'block' }} />
          </div>
        ),
        filterIcon: (filtered) => (
          <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />
        ),
      },
      {
        title: '负责人',
        dataIndex: 'creator',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '状态',
        dataIndex: 'status',
        initialValue: 'all',
        filters: true,
        onFilter: true,
        valueEnum: DEMO_STATUS_VALUE_ENUM,
      },
      {
        title: '备注',
        dataIndex: 'memo',
        ellipsis: true,
        copyable: true,
      },
      {
        title: '操作',
        width: 180,
        key: 'option',
        valueType: 'option',
        render: () => [
          <a key="detail">详情</a>,
          <a key="log">日志</a>,
          <a key="monitor">监控</a>,
          <TableDropdown
            key="actionGroup"
            menus={[
              { key: 'restart', name: '重启' },
              { key: 'delete', name: '下线' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          search={{
            layout: 'vertical',
            defaultCollapsed: false,
          }}
          dateFormatter="string"
          toolbar={{
            title: '应用管理',
            tooltip: '管理所有已部署的微服务应用',
          }}
          toolBarRender={() => [
            <Button key="danger" danger>
              批量下线
            </Button>,
            <Button key="log">查看日志</Button>,
            <Button type="primary" key="primary">
              部署应用
            </Button>,
            <Dropdown
              key="menu"
              menu={{
                items: [
                  { label: '导入配置', key: 'import' },
                  { label: '导出配置', key: 'export' },
                  { label: '批量更新', key: 'batch' },
                ],
              }}
            >
              <Button>
                <EllipsisOutlined />
              </Button>
            </Dropdown>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    成员名称账号角色权限范围操作
    暂无数据
    暂无数据
    Table without ToolBar
    import { DownOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Avatar, Dropdown, Popconfirm, Space } from 'antd';
    import React from 'react';
    
    export type Member = {
      avatar: string;
      realName: string;
      nickName: string;
      email: string;
      outUserNo: string;
      phone: string;
      role: RoleType;
      permission?: string[];
    };
    
    export type RoleMapType = Record<
      string,
      {
        name: string;
        desc: string;
      }
    >;
    
    export type RoleType = 'admin' | 'operator';
    
    const RoleMap: RoleMapType = {
      admin: {
        name: '管理员',
        desc: '仅拥有指定项目的权限',
      },
      operator: {
        name: '操作员',
        desc: '拥有所有权限',
      },
    };
    
    const tableListDataSource: Member[] = [];
    
    const realNames = ['马巴巴', '测试', '测试2', '测试3'];
    const nickNames = ['巴巴', '测试', '测试2', '测试3'];
    const emails = [
      'baba@antfin.com',
      'test@antfin.com',
      'test2@antfin.com',
      'test3@antfin.com',
    ];
    const phones = ['12345678910', '10923456789', '109654446789', '109223346789'];
    const permissions = [[], ['权限点名称1', '权限点名称4'], ['权限点名称1'], []];
    
    for (let i = 0; i < 5; i += 1) {
      tableListDataSource.push({
        outUserNo: `${102047 + i}`,
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/upvrAjAPQX/Logo_Tech%252520UI.svg',
        role: i === 0 ? 'admin' : 'operator',
        realName: realNames[i % 4],
        nickName: nickNames[i % 4],
        email: emails[i % 4],
        phone: phones[i % 4],
        permission: permissions[i % 4],
      });
    }
    
    const MemberList: React.FC = () => {
      const renderRemoveUser = (text: string) => (
        <Popconfirm
          key="popconfirm"
          title={`确认${text}吗?`}
          okText="是"
          cancelText="否"
        >
          <a>{text}</a>
        </Popconfirm>
      );
    
      const columns: ProColumns<Member>[] = [
        {
          dataIndex: 'avatar',
          title: '成员名称',
          valueType: 'avatar',
          width: 150,
          render: (dom, record) => (
            <Space>
              <span>{dom}</span>
              {record.nickName}
            </Space>
          ),
        },
        {
          dataIndex: 'email',
          title: '账号',
          ellipsis: true,
          copyable: true,
          renderText: (_dom, row) => {
            return (
              <React.Fragment>
                <Avatar src={row.avatar} />
                {row.nickName}
              </React.Fragment>
            );
          },
        },
        {
          dataIndex: 'role',
          title: '角色',
          render: (_, record) => (
            <Dropdown
              menu={{
                items: [
                  {
                    label: '管理员',
                    key: 'admin',
                  },
                  {
                    label: '操作员',
                    key: 'operator',
                  },
                ],
              }}
            >
              <a>
                {RoleMap[record.role || 'admin'].name} <DownOutlined />
              </a>
            </Dropdown>
          ),
        },
        {
          dataIndex: 'permission',
          title: '权限范围',
          render: (_, record) => {
            const { role, permission = [] } = record;
            if (role === 'admin') {
              return '所有权限';
            }
            return permission && permission.length > 0
              ? permission.join('、')
              : '无';
          },
        },
        {
          title: '操作',
          dataIndex: 'x',
          valueType: 'option',
          render: (_, record) => {
            let node = renderRemoveUser('退出');
            if (record.role === 'admin') {
              node = renderRemoveUser('移除');
            }
            return [<a key="edit">编辑</a>, node];
          },
        },
      ];
    
      return (
        <ProTable<Member>
          columns={columns}
          request={(_params, _sorter, _filter) => {
            // 表单搜索项会从 params 传入,传递给后端接口。
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          rowKey="outUserNo"
          pagination={{
            showQuickJumper: true,
          }}
          toolBarRender={false}
          search={false}
        />
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 无标题 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>Dropdown</strong>: 下拉菜单组件
          </li>
          <li>
            <strong>Popconfirm</strong>: 气泡确认框组件
          </li>
          <li>
            <strong>Space</strong>: 间距组件
          </li>
          <li>
            <strong>无标题</strong>: 展示无标题功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>pagination</strong>: 分页配置
          </li>
          <li>
            <strong>toolBarRender</strong>: 工具栏渲染
          </li>
          <li>
            <strong>search</strong>: 搜索配置
          </li>
        </ul>
        <h4>无标题特点:</h4>
        <ul>
          <li>
            <strong>头像显示</strong>: 支持头像显示
          </li>
          <li>
            <strong>角色管理</strong>: 支持角色管理
          </li>
          <li>
            <strong>权限控制</strong>: 支持权限控制
          </li>
          <li>
            <strong>下拉菜单</strong>: 支持下拉菜单
          </li>
          <li>
            <strong>确认操作</strong>: 支持确认操作
          </li>
          <li>
            <strong>简洁布局</strong>: 支持简洁布局
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>成员管理</strong>: 成员管理系统
          </li>
          <li>
            <strong>权限管理</strong>: 权限管理功能
          </li>
          <li>
            <strong>用户列表</strong>: 用户列表展示
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <MemberList />
      </div>
    );
    

    Search filter type switch

    Use a segmented control to toggle search.filterType between the full query form (query) and lightweight filter (light).

    search.filterType 搜索栏类型:
    搜索栏类型切换
    应用名称负责人状态
    暂无数据
    暂无数据
    Search filter type switch
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Segmented } from 'antd';
    import { useState } from 'react';
    
    import {
      createTableDataSource,
      DEMO_CREATOR_VALUE_ENUM,
      DEMO_STATUS_VALUE_ENUM,
      FIXED_BASE_DATE,
    } from '../mockData';
    
    type TableListItem = {
      key: number;
      name: string;
      creator: string;
      status: string;
      createdAt: number;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '负责人',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '状态',
        dataIndex: 'status',
        valueEnum: DEMO_STATUS_VALUE_ENUM,
      },
      {
        title: '日期范围',
        dataIndex: 'startTime',
        valueType: 'dateRange',
        hideInTable: true,
        initialValue: [FIXED_BASE_DATE, FIXED_BASE_DATE.add(7, 'day')],
      },
    ];
    
    const Demo = () => {
      const [filterType, setFilterType] = useState<'query' | 'light'>('query');
    
      return (
        <div>
          <div style={{ marginBlockEnd: 16 }}>
            <span>search.filterType 搜索栏类型:</span>
            <Segmented
              value={filterType}
              onChange={(v) => setFilterType(v as any)}
              options={[
                { label: '查询表单 query', value: 'query' },
                { label: '轻量筛选 light', value: 'light' },
              ]}
            />
          </div>
          <ProTable<TableListItem>
            columns={columns}
            request={() =>
              Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              })
            }
            rowKey="key"
            search={{ filterType }}
            dateFormatter="string"
            headerTitle="搜索栏类型切换"
          />
        </div>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Search & Filter

    应用列表(无操作按钮)
    应用名称
    容器数量
    状态
    部署时间
    暂无数据
    暂无数据
    Query Table (No Buttons)
    import { DownOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import { createTableDataSource, DEMO_STATUS_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
      status: string;
      createdAt: number;
      memo: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        width: 120,
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '状态',
        width: 80,
        dataIndex: 'status',
        initialValue: 'all',
        valueEnum: DEMO_STATUS_VALUE_ENUM,
      },
      {
        title: '部署时间',
        tooltip: '最近一次部署的时间',
        width: 140,
        key: 'since',
        search: false,
        dataIndex: 'createdAt',
        valueType: 'date',
        sorter: (a, b) => a.createdAt - b.createdAt,
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          search={{
            optionRender: false,
            collapsed: false,
          }}
          dateFormatter="string"
          headerTitle="应用列表(无操作按钮)"
          toolBarRender={() => [
            <Button key="log">查看日志</Button>,
            <Button key="export">
              导出数据
              <DownOutlined />
            </Button>,
            <Button type="primary" key="primary">
              部署应用
            </Button>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    轻量筛选
    应用名称负责人
    暂无数据
    暂无数据
    Lightweight Filter
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    
    import {
      createTableDataSource,
      DEMO_CREATOR_VALUE_ENUM,
      FIXED_BASE_DATE,
    } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      creator: string;
      createdAt: number;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 1,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
        formItemProps: {},
      },
      {
        title: '日期范围',
        dataIndex: 'startTime',
        valueType: 'dateRange',
        hideInTable: true,
        initialValue: [FIXED_BASE_DATE, FIXED_BASE_DATE.add(1, 'day')],
      },
      {
        title: '负责人',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          headerTitle="轻量筛选"
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          options={false}
          search={{
            filterType: 'light',
          }}
          dateFormatter="string"
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    快速搜索服务
    序号服务名称
    暂无数据
    暂无数据
    Built-in keyWords Search
    import { ProTable } from '@ant-design/pro-components';
    
    type ServiceItem = {
      key: number;
      name: string;
      createdAt: number;
    };
    
    const SearchTable = () => (
      <ProTable<ServiceItem>
        columns={[
          {
            title: '序号',
            dataIndex: 'index',
            valueType: 'indexBorder',
          },
          {
            title: '服务名称',
            dataIndex: 'name',
            search: false,
          },
        ]}
        request={async (_params) => {
    
          return {
            data: [
              {
                key: 1,
                name: '用户认证服务',
                createdAt: 1705286400000,
              },
              {
                key: 2,
                name: '订单处理中心',
                createdAt: 1705200000000,
              },
              {
                key: 3,
                name: '支付网关',
                createdAt: 1705113600000,
              },
            ],
            total: 3,
            success: true,
          };
        }}
        search={false}
        rowKey="key"
        options={{
          search: true,
        }}
        headerTitle="快速搜索服务"
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <SearchTable />
      </div>
    );
    
    搜索选项自定义
    序号服务名称合同金额
    暂无数据
    暂无数据
    Custom Search Options
    import { PlusOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    type ServiceItem = {
      key: number;
      name: string;
      createdAt: number;
    };
    
    const columns: ProColumns<ServiceItem>[] = [
      {
        title: '序号',
        dataIndex: 'index',
        valueType: 'indexBorder',
      },
      {
        title: '服务名称',
        dataIndex: 'name',
      },
      {
        title: '合同金额',
        dataIndex: 'title',
        width: 100,
        valueType: 'money',
        renderText: () => '128000',
      },
    ];
    
    const Demo = () => (
      <ProTable<ServiceItem>
        columns={columns}
        request={async () => {
          return {
            data: [
              {
                key: 1,
                name: '企业版云服务套餐',
                createdAt: 1705286400000,
              },
            ],
            total: 1,
            success: true,
          };
        }}
        rowKey="key"
        dateFormatter="string"
        headerTitle="搜索选项自定义"
        search={{
          defaultCollapsed: false,
          labelWidth: 'auto',
          optionRender: (searchConfig, formProps, dom) => [
            ...dom.reverse(),
            <Button key="export" onClick={() => {}}>
              导出
            </Button>,
          ],
        }}
        toolBarRender={() => [
          <Button key="primary" type="primary">
            <PlusOutlined />
            新建
          </Button>,
        ]}
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    高级表格
    标题
    状态
    标签创建时间
    暂无数据
    暂无数据
    高级表格
    标题
    状态
    标签创建时间
    暂无数据
    暂无数据
    Required Query Form
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Space, Tag } from 'antd';
    
    type GithubIssueItem = {
      id: number;
      number: number;
      title: string;
      labels: {
        name: string;
        color: string;
      }[];
      state: string;
      comments: number;
      created_at: number;
      updated_at: number;
    };
    
    const columns: ProColumns<GithubIssueItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tooltip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: '30%',
      },
      {
        title: '状态',
        dataIndex: 'state',
        filters: true,
        onFilter: true,
        valueType: 'select',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        valueEnum: {
          all: { text: '全部', status: 'Default' },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
            disabled: true,
          },
          processing: {
            text: '解决中',
            status: 'Processing',
          },
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        search: false,
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        formItemRender: (_, { defaultRender }) => {
          return defaultRender(_);
        },
        render: (_, record) => (
          <Space>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'created_at',
        valueType: 'date',
        search: false,
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<GithubIssueItem>
            columns={columns}
            request={async () => ({
              success: true,
              data: [
                {
                  id: 624748504,
                  number: 6689,
                  title: '🐛 [BUG]yarn install命令 antd2.4.5会报错',
                  labels: [
                    {
                      name: 'bug',
                      color: 'error',
                    },
                  ],
                  state: 'open',
                  locked: false,
                  comments: 1,
                  created_at: 1590486176000,
                  updated_at: 1590487382000,
                  closed_at: null,
                  author_association: 'NONE',
                  user: 'shuyan',
                  avatar:
                    'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
                },
              ],
            })}
            rowKey="id"
            search={{
              labelWidth: 'auto',
            }}
            form={{
              ignoreRules: false,
            }}
            dateFormatter="string"
            headerTitle="高级表格"
          />
          <ProTable<GithubIssueItem>
            columns={columns}
            request={async () => ({
              success: true,
              data: [
                {
                  id: 624748504,
                  number: 6689,
                  title: '🐛 [BUG]yarn install命令 antd2.4.5会报错',
                  labels: [
                    {
                      name: 'bug',
                      color: 'error',
                    },
                  ],
                  state: 'open',
                  locked: false,
                  comments: 1,
                  created_at: 1590486176000,
                  updated_at: 1590487382000,
                  closed_at: null,
                  author_association: 'NONE',
                  user: 'shuyan',
                  avatar:
                    'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
                },
              ],
            })}
            rowKey="id"
            search={{
              labelWidth: 'auto',
            }}
            dateFormatter="string"
            headerTitle="高级表格"
          />
        </>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 开放规则 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>Space</strong>: 间距组件
          </li>
          <li>
            <strong>Tag</strong>: 标签组件
          </li>
          <li>
            <strong>开放规则</strong>: 展示开放规则功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>search</strong>: 搜索配置
          </li>
          <li>
            <strong>form</strong>: 表单配置
          </li>
          <li>
            <strong>dateFormatter</strong>: 日期格式化
          </li>
          <li>
            <strong>headerTitle</strong>: 表格标题
          </li>
        </ul>
        <h4>开放规则特点:</h4>
        <ul>
          <li>
            <strong>表单验证</strong>: 支持表单验证
          </li>
          <li>
            <strong>必填校验</strong>: 支持必填校验
          </li>
          <li>
            <strong>标签显示</strong>: 支持标签显示
          </li>
          <li>
            <strong>复制功能</strong>: 支持复制功能
          </li>
          <li>
            <strong>省略号显示</strong>: 支持省略号显示
          </li>
          <li>
            <strong>状态过滤</strong>: 支持状态过滤
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>表单验证</strong>: 表单验证需求
          </li>
          <li>
            <strong>数据校验</strong>: 数据校验功能
          </li>
          <li>
            <strong>规则配置</strong>: 规则配置需求
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Try to use initialValue to solve the problem, required fields are more frustrating.

    Search Form Customization

    When the built-in form items don't meet our basic needs, we need to customize the default components, which we can use with fieldProps and formItemRender.

    fieldProps can pass the props through and set the select style and multi-select issues.

    formItemRender does the rewriting logic, passing in item and props for rendering, but note that we have to assign value and onChange to the props, otherwise the form won't get the parameters.

    formItemRender: (
      _,
      { type, defaultRender, formItemProps, fieldProps, ...rest },
      form,
    ) => {
      if (type === 'form') {
        return null;
      }
      const status = form.getFieldValue('state');
      if (status !== 'open') {
        return <Input {...fieldProps} placeholder="Please enter" />;
      }
      return defaultRender(_);
    };

    The definition of formItemRender, the exact value of which can be seen by opening the console.

     formItemRender?: (
        item: ProColumns<T>,
        config: {
          value?: any;
          onSelect?: (value: any) => void;
          type: ProTableTypes;
          defaultRender: (newItem: ProColumns<any>) => JSX.Element | null;
        },
        form: FormInstance,
      ) => JSX.Element | false | null;
    动态联动搜索栏
    序号服务名称查询周期
    暂无数据
    暂无数据
    Dynamic Linkage Search
    import { PlusOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button, Input, Select } from 'antd';
    import React, { useEffect, useState } from 'react';
    
    type ServiceItem = {
      key: number;
      name: string;
      createdAt: number;
    };
    
    const MySelect: React.FC<{
      state: {
        type: number;
      };
      value?: string;
      onChange?: (value: string) => void;
    }> = (props) => {
      const { state } = props;
    
      const [innerOptions, setOptions] = useState<
        {
          label: React.ReactNode;
          value: number;
        }[]
      >([]);
    
      useEffect(() => {
        const { type } = state || {};
        if (type === 2) {
          setOptions([
            { label: '星期一', value: 1 },
            { label: '星期二', value: 2 },
          ]);
        } else {
          setOptions([
            { label: '一月', value: 1 },
            { label: '二月', value: 2 },
          ]);
        }
      }, [JSON.stringify(state)]);
    
      return (
        <Select
          options={innerOptions}
          value={props.value}
          onChange={props.onChange}
        />
      );
    };
    
    const Demo = () => {
      const columns: ProColumns<ServiceItem>[] = [
        {
          title: '序号',
          dataIndex: 'index',
          valueType: 'indexBorder',
        },
        {
          title: '服务名称',
          dataIndex: 'name',
        },
        {
          title: '动态表单',
          key: 'direction',
          hideInTable: true,
          dataIndex: 'direction',
          formItemRender: (
            item,
            { type, defaultRender: _defaultRender, ...rest },
            form,
          ) => {
            if (type === 'form') {
              return null;
            }
            const stateType = form.getFieldValue('state');
            if (stateType === 3) {
              return <Input />;
            }
            if (stateType === 4) {
              return null;
            }
            return (
              <MySelect
                {...rest}
                state={{
                  type: stateType,
                }}
              />
            );
          },
        },
        {
          title: '查询周期',
          dataIndex: 'state',
          initialValue: 1,
          valueType: 'select',
          request: async () => [
            { label: '按月', value: 1 },
            { label: '按周', value: 2 },
            { label: '自定义', value: 3 },
            { label: '不展示', value: 4 },
          ],
        },
      ];
    
      return (
        <ProTable<ServiceItem>
          columns={columns}
          request={async (_params) => {
    
            return {
              data: [
                {
                  key: 1,
                  name: '用户认证服务',
                  createdAt: 1705286400000,
                  state: 'closed',
                },
              ],
              total: 1,
              success: true,
            };
          }}
          rowKey="key"
          tableLayout="fixed"
          dateFormatter="string"
          headerTitle="动态联动搜索栏"
          search={{
            defaultCollapsed: false,
            optionRender: (searchConfig, formProps, dom) => [
              ...dom.reverse(),
              <Button
                key="export"
                onClick={() => {
                  const _values = searchConfig?.form?.getFieldsValue();
    
                }}
              >
                导出
              </Button>,
            ],
          }}
          toolBarRender={() => [
            <Button key="new" type="primary">
              <PlusOutlined />
              新建
            </Button>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    表单赋值
    应用名称部署时间
    暂无数据
    暂无数据
    Manipulating Query Forms with formRef
    import type { ProColumns, ProFormInstance } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button } from 'antd';
    import { useRef, useState } from 'react';
    
    export type TableListItem = {
      key: number;
      name: string;
    };
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        key: 'name',
      },
      {
        title: '部署时间',
        key: 'since',
        dataIndex: 'createdAt',
        valueType: 'date',
      },
    ];
    
    const Demo = () => {
      const ref = useRef<ProFormInstance>();
      const [collapsed, setCollapsed] = useState(false);
    
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={() =>
            Promise.resolve({
              data: [
                {
                  key: 1,
                  name: '用户认证服务',
                  createdAt: 1705286400000,
                },
              ],
              total: 1,
              success: true,
            })
          }
          rowKey="key"
          pagination={{
            showSizeChanger: true,
          }}
          search={{
            collapsed,
            onCollapse: setCollapsed,
          }}
          formRef={ref}
          toolBarRender={() => [
            <Button
              key="set"
              onClick={() => {
                if (ref.current) {
                  ref.current.setFieldsValue({
                    name: '支付网关',
                  });
                }
              }}
            >
              赋值
            </Button>,
            <Button
              key="submit"
              onClick={() => {
                if (ref.current) {
                  ref.current.submit();
                }
              }}
            >
              提交
            </Button>,
          ]}
          options={false}
          dateFormatter="string"
          headerTitle="表单赋值"
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Why you should not manually wire value / onChange

    Fields wrapped by ProTable's search Form get value (or valuePropName) and onChange (or trigger) injected — the Form owns the synchronization. Practically:

    • Do not rely on component onChange for aggregation (use Form onValuesChange instead). You may still subscribe to onChange when needed.
    • Do not control values with raw value / defaultValue on widgets; defaults belong in Form initialValues. initialValues is not reactive — use setFieldsValue.
    • Prefer form.setFieldsValue over scattering useState.

    Why does defaultValue look ignored?

    Child fields are switched to controlled mode, so standalone defaultValue will not behave as usual. Prefer Form initialValues (via search.defaultCollapsed/form configs as documented) or imperative updates through formRef.

    Table Features

    游标分页仅显示「上一页 / 下一页」,适合无法或不需要获取总条数的场景。 request 返回的 nextToken 会被自动传入下一次请求。
    ID名称状态部门创建时间
    评分
    暂无数据
    暂无数据
    Cursor pagination
    import { ProTable } from '@ant-design/pro-components';
    import { Typography } from 'antd';
    
    type Row = {
      id: number;
      name: string;
      status: 'active' | 'closed' | 'pending';
      department: string;
      createdAt: string;
      score: number;
    };
    
    const departments = ['技术部', '产品部', '设计部', '运营部', '市场部'];
    const statuses: Row['status'][] = ['active', 'closed', 'pending'];
    const names = [
      'Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon',
      'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa',
      'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron',
      'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon',
      'Phi', 'Chi', 'Psi', 'Omega', 'Nova',
      'Apex', 'Zenith', 'Vertex', 'Nexus', 'Pulse',
    ];
    
    const rows: Row[] = names.map((name, index) => ({
      id: index + 1,
      name,
      status: statuses[index % 3],
      department: departments[index % 5],
      createdAt: new Date(2026, 0, index + 1).toISOString().split('T')[0],
      score: Math.floor(Math.random() * 40) + 60,
    }));
    
    export default () => (
      <>
        <Typography.Paragraph type="secondary">
          游标分页仅显示「上一页 / 下一页」,适合无法或不需要获取总条数的场景。
          request 返回的 nextToken 会被自动传入下一次请求。
        </Typography.Paragraph>
        <ProTable<Row>
          rowKey="id"
          search={false}
          options={false}
          columns={[
            { title: 'ID', dataIndex: 'id', width: 64 },
            { title: '名称', dataIndex: 'name' },
            {
              title: '状态',
              dataIndex: 'status',
              valueEnum: {
                active: { text: '启用', status: 'Success' },
                closed: { text: '关闭', status: 'Default' },
                pending: { text: '待处理', status: 'Processing' },
              },
            },
            { title: '部门', dataIndex: 'department' },
            { title: '创建时间', dataIndex: 'createdAt', valueType: 'date' },
            {
              title: '评分',
              dataIndex: 'score',
              sorter: (a, b) => a.score - b.score,
              render: (_, row) => (
                <Typography.Text type={row.score >= 80 ? 'success' : 'warning'}>
                  {row.score}
                </Typography.Text>
              ),
            },
          ]}
          pagination={{ type: 'cursor', pageSize: 5 }}
          request={async (
            // 第一个参数 params 包含分页信息
            // 游标分页模式下会传入 nextToken
            params: {
              pageSize?: number;
              current?: number;
              nextToken?: string;
            },
          ) => {
            const index = Number(params.nextToken ?? 0);
            return {
              success: true,
              data: rows.slice(index, index + 5),
              nextToken: index + 5 < rows.length ? String(index + 5) : undefined,
            };
          }}
        />
      </>
    );
    
    批量操作
    已选 1 项取消选择
    容器总数: 0 个
    请求总量: 0 次
    应用名称
    容器数量
    请求量部署进度负责人
    部署时间
    备注操作
    用户认证服务35678
    24%
    书琰2024-01-15核心服务,承载全站用户登录与鉴权
    订单处理中心66912
    41%
    逄一2024-01-14日均处理订单量 50 万+,高峰期需要关注性能
    支付网关98146
    期贤2024-01-13对接微信、支付宝等第三方支付渠道
    商品管理服务129380
    玄霜2024-01-12负责全品类商品的增删改查及上下架管理
    物流追踪系统310614
    92%
    怀渊2024-01-11接入顺丰、中通等多家物流运力
    Batch Operations
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button, DatePicker, Space, Table } from 'antd';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../mockData';
    
    const { RangePicker } = DatePicker;
    
    const ProcessMap = {
      close: 'normal',
      running: 'active',
      online: 'success',
      error: 'exception',
    } as const;
    
    export type TableListItem = {
      key: number;
      name: string;
      progress: number;
      containers: number;
      callNumber: number;
      creator: string;
      status: string;
      createdAt: number;
      memo: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 50,
      withProgress: true,
      withCallNumber: true,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        width: 140,
        dataIndex: 'name',
        fixed: 'left',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        width: 100,
        dataIndex: 'containers',
        align: 'right',
        search: false,
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '请求量',
        width: 100,
        align: 'right',
        dataIndex: 'callNumber',
      },
      {
        title: '部署进度',
        dataIndex: 'progress',
        valueType: (item) => ({
          type: 'progress',
          status: ProcessMap[item.status as 'close'],
        }),
      },
      {
        title: '负责人',
        width: 100,
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '部署时间',
        width: 140,
        key: 'since',
        dataIndex: 'createdAt',
        valueType: 'date',
        sorter: (a, b) => a.createdAt - b.createdAt,
        formItemRender: () => {
          return <RangePicker />;
        },
      },
      {
        title: '备注',
        dataIndex: 'memo',
        ellipsis: true,
        copyable: true,
        search: false,
      },
      {
        title: '操作',
        width: 80,
        key: 'option',
        valueType: 'option',
        fixed: 'right',
        render: () => [<a key="detail">详情</a>],
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          rowSelection={{
            selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
            defaultSelectedRowKeys: [1],
          }}
          tableAlertRender={({
            selectedRowKeys,
            selectedRows,
            onCleanSelected,
          }) => {
    
            return (
              <Space size={24}>
                <span>
                  已选 {selectedRowKeys.length} 项
                  <a style={{ marginInlineStart: 8 }} onClick={onCleanSelected}>
                    取消选择
                  </a>
                </span>
                <span>{`容器总数: ${selectedRows.reduce(
                  (pre, item) => pre + (item?.containers ?? 0),
                  0,
                )} 个`}</span>
                <span>{`请求总量: ${selectedRows.reduce(
                  (pre, item) => pre + (item?.callNumber ?? 0),
                  0,
                )} 次`}</span>
              </Space>
            );
          }}
          tableAlertOptionRender={() => {
            return (
              <Space size={16}>
                <a>批量重启</a>
                <a>批量下线</a>
                <a>导出数据</a>
              </Space>
            );
          }}
          dataSource={tableListDataSource}
          scroll={{ x: 1300 }}
          options={false}
          search={false}
          pagination={{
            pageSize: 5,
          }}
          rowKey="key"
          headerTitle="批量操作"
          toolBarRender={() => [<Button key="export">导出报表</Button>]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    应用部署记录
    应用名称状态
    容器数量
    负责人
    暂无数据
    暂无数据
    Nested Tables
    import { DownOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button, Tag } from 'antd';
    
    import {
      DEMO_APP_NAMES,
      DEMO_CREATORS,
      DEMO_CREATOR_VALUE_ENUM,
      FIXED_BASE_TIMESTAMP,
    } from '../mockData';
    
    export type Status = {
      color: string;
      text: string;
    };
    
    const statusMap: Record<string, Status> = {
      0: {
        color: 'blue',
        text: '部署中',
      },
      1: {
        color: 'green',
        text: '运行正常',
      },
      2: {
        color: 'volcano',
        text: '性能告警',
      },
      3: {
        color: 'red',
        text: '运行异常',
      },
      4: {
        color: '',
        text: '待部署',
      },
    };
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
      status: Status;
      createdAt: number;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 5 },
      (_, i) => ({
        key: i,
        name: DEMO_APP_NAMES[i % DEMO_APP_NAMES.length],
        containers: ((i * 3 + 2) % 12) + 1,
        creator: DEMO_CREATORS[i % DEMO_CREATORS.length],
        status: statusMap[String(i % 5)],
        createdAt: FIXED_BASE_TIMESTAMP - i * 86400000,
      }),
    );
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        width: 140,
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '状态',
        width: 120,
        dataIndex: 'status',
        render: (_, record) => (
          <Tag color={record.status.color}>{record.status.text}</Tag>
        ),
      },
      {
        title: '容器数量',
        width: 100,
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '负责人',
        width: 100,
        dataIndex: 'creator',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
    ];
    
    const expandedRowRender = () => {
      const data = [
        {
          key: 0,
          date: '2024-01-15 08:30:00',
          name: '版本发布 v2.3.1',
          upgradeNum: '已更新 3 个实例',
        },
        {
          key: 1,
          date: '2024-01-14 16:20:00',
          name: '配置变更 - 数据库连接池',
          upgradeNum: '已更新 5 个实例',
        },
        {
          key: 2,
          date: '2024-01-13 10:15:00',
          name: '扩容 - 新增 2 个节点',
          upgradeNum: '已更新 2 个实例',
        },
      ];
      return (
        <ProTable
          columns={[
            { title: '操作时间', dataIndex: 'date', key: 'date' },
            { title: '变更内容', dataIndex: 'name', key: 'name' },
            { title: '更新状态', dataIndex: 'upgradeNum', key: 'upgradeNum' },
            {
              title: '操作',
              dataIndex: 'operation',
              key: 'operation',
              valueType: 'option',
              render: () => [<a key="rollback">回滚</a>, <a key="detail">详情</a>],
            },
          ]}
          headerTitle={false}
          search={false}
          options={false}
          dataSource={data}
          pagination={false}
        />
      );
    };
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          expandable={{ expandedRowRender }}
          search={false}
          dateFormatter="string"
          headerTitle="应用部署记录"
          options={false}
          toolBarRender={() => [
            <Button key="log">查看日志</Button>,
            <Button key="export">
              导出数据
              <DownOutlined />
            </Button>,
            <Button key="primary" type="primary">
              部署应用
            </Button>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    标题状态标签创建时间评分更新时间操作
    Issue 标题 1未解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 2已解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 3未解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 4已解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 5未解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 6已解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 7未解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Issue 标题 8已解决bug2026-09-26 10:00:00
    2026-09-26 10:00:00
    Fixed Selection Column
    /**
     * title: 固定选择列
     * description: 选择列使用 `fixed: 'start'` 固定后,配合其他固定列横向滚动时,表头勾选框不应被相邻固定列遮挡。
     */
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Table, Tag } from 'antd';
    
    type IssueItem = {
      key: number;
      title: string;
      labels: { name: string; color: string }[];
      state: string;
      createdAt: string;
      rate: number;
    };
    
    const columns: ProColumns<IssueItem>[] = [
      { title: '标题', dataIndex: 'title', width: 160, fixed: 'start' },
      {
        title: '状态',
        dataIndex: 'state',
        width: 100,
        valueType: 'select',
        valueEnum: {
          open: { text: '未解决', status: 'Error' },
          closed: { text: '已解决', status: 'Success' },
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 140,
        search: false,
        render: (_, record) => (
          <span>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </span>
        ),
      },
      {
        title: '创建时间',
        dataIndex: 'createdAt',
        width: 160,
        valueType: 'dateTime',
      },
      { title: '评分', dataIndex: 'rate', width: 160, valueType: 'rate' },
      {
        title: '更新时间',
        dataIndex: 'createdAt',
        width: 160,
        valueType: 'dateTime',
      },
      {
        title: '操作',
        dataIndex: 'option',
        valueType: 'option',
        width: 120,
        fixed: 'end',
      },
    ];
    
    const dataSource: IssueItem[] = Array.from({ length: 8 }).map((_, i) => ({
      key: i,
      title: `Issue 标题 ${i + 1}`,
      labels: [{ name: 'bug', color: 'error' }],
      state: i % 2 === 0 ? 'open' : 'closed',
      createdAt: '2026-09-26 10:00:00',
      rate: 4,
    }));
    
    export default () => (
      <ProTable<IssueItem>
        columns={columns}
        dataSource={dataSource}
        rowKey="key"
        search={false}
        toolBarRender={false}
        pagination={false}
        scroll={{ x: 1200 }}
        rowSelection={{
          fixed: 'start',
          selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
        }}
      />
    );
    
    服务器 IPCPU内存磁盘
    暂无数据
    暂无数据
    10.0.1.100
    时间点执行日志操作
    暂无数据
    暂无数据
    Left-Right Structure
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProCard, ProTable } from '@ant-design/pro-components';
    import type { BadgeProps } from 'antd';
    import { Badge, Button } from 'antd';
    import React, { useEffect, useState } from 'react';
    
    import { FIXED_BASE_TIMESTAMP } from '../mockData';
    
    type LogItem = {
      createdAtRange?: number[];
      createdAt: number;
      code: string;
    };
    
    type ServerDetailProps = {
      ip: string;
    };
    
    const ServerDetail: React.FC<ServerDetailProps> = (props) => {
      const { ip } = props;
      const [logDataSource, setLogDataSource] = useState<LogItem[]>([]);
    
      const columns: ProColumns<LogItem>[] = [
        {
          title: '时间点',
          key: 'createdAt',
          dataIndex: 'createdAt',
          valueType: 'dateTime',
        },
        {
          title: '执行日志',
          key: 'code',
          width: 80,
          dataIndex: 'code',
          valueType: 'code',
        },
        {
          title: '操作',
          key: 'option',
          width: 80,
          valueType: 'option',
          render: () => [<a key="alert">告警</a>],
        },
      ];
    
      useEffect(() => {
        const source = [];
        for (let i = 0; i < 15; i += 1) {
          source.push({
            createdAt: FIXED_BASE_TIMESTAMP - (i * 500 + 100),
            code: `const healthCheck = async (host) => {
              const res = await fetch(host + '/health');
              return { status: res.status, latency: res.headers.get('x-latency') };
            };`,
            key: i,
          });
        }
    
        setLogDataSource(source);
      }, [ip]);
    
      return (
        <ProTable<LogItem>
          columns={columns}
          dataSource={logDataSource}
          pagination={{
            pageSize: 3,
            showSizeChanger: false,
          }}
          rowKey="key"
          toolBarRender={false}
          search={false}
        />
      );
    };
    
    type statusType = BadgeProps['status'];
    
    const valueEnum: statusType[] = ['success', 'error', 'processing', 'default'];
    
    export type ServerItem = {
      ip?: string;
      cpu?: number | string;
      mem?: number | string;
      disk?: number | string;
      status: statusType;
    };
    
    const serverListDataSource: ServerItem[] = [];
    
    for (let i = 0; i < 10; i += 1) {
      serverListDataSource.push({
        ip: `10.0.${Math.floor(i / 3) + 1}.${(i * 11 + 100) % 256}`,
        cpu: ((i * 7 + 15) % 60) + 10,
        mem: ((i * 13 + 25) % 50) + 20,
        status: valueEnum[i % 4],
        disk: ((i * 11 + 30) % 40) + 15,
      });
    }
    
    type ServerListProps = {
      ip: string;
      onChange: (id: string) => void;
    };
    
    const ServerList: React.FC<ServerListProps> = (props) => {
      const { onChange } = props;
    
      const columns: ProColumns<ServerItem>[] = [
        {
          title: '服务器 IP',
          key: 'ip',
          dataIndex: 'ip',
          render: (_, item) => {
            return <Badge status={item.status} text={item.ip} />;
          },
        },
        {
          title: 'CPU',
          key: 'cpu',
          dataIndex: 'cpu',
          valueType: {
            type: 'percent',
            precision: 0,
          },
        },
        {
          title: '内存',
          key: 'mem',
          dataIndex: 'mem',
          valueType: {
            type: 'percent',
            precision: 0,
          },
        },
        {
          title: '磁盘',
          key: 'disk',
          dataIndex: 'disk',
          valueType: {
            type: 'percent',
            precision: 0,
          },
        },
      ];
      return (
        <ProTable<ServerItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: serverListDataSource,
              total: serverListDataSource.length,
              success: true,
            });
          }}
          rowKey="ip"
          toolbar={{
            search: {
              onSearch: (value) => {
                alert(value);
              },
            },
            actions: [
              <Button key="add" type="primary">
                添加节点
              </Button>,
            ],
          }}
          options={false}
          pagination={false}
          search={false}
          onRow={(record) => {
            return {
              onClick: () => {
                if (record.ip) {
                  onChange(record.ip);
                }
              },
            };
          }}
        />
      );
    };
    
    const Demo: React.FC = () => {
      const [ip, setIp] = useState('10.0.1.100');
      return (
        <ProCard split="vertical">
          <ProCard colSpan="384px" ghost>
            <ServerList onChange={(cIp) => setIp(cIp)} ip={ip} />
          </ProCard>
          <ProCard title={ip}>
            <ServerDetail ip={ip} />
          </ProCard>
        </ProCard>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    上次更新时间:10:00:00
    序号
    状态
    部署进度时间
    创建时间更新时间
    暂无数据
    暂无数据
    Table Polling
    import { LoadingOutlined, ReloadOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button } from 'antd';
    import dayjs from 'dayjs';
    import { useState } from 'react';
    
    import {
      DEMO_STATUS_VALUE_ENUM,
      DEMO_VALUE_ENUM,
      FIXED_BASE_TIMESTAMP,
    } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: string;
      updatedAt: number;
      createdAt: number;
      progress: number;
      money: number;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 2 },
      (_, i) => ({
        key: i,
        name: i === 0 ? '用户认证服务' : '支付网关',
        status: DEMO_VALUE_ENUM[(i % 4) as keyof typeof DEMO_VALUE_ENUM],
        updatedAt: FIXED_BASE_TIMESTAMP - (i * 500 + 100),
        createdAt: FIXED_BASE_TIMESTAMP - (i * 1000 + 200),
        money: ((i * 3456 + 7890) % 50000) * 100,
        progress: ((i * 17 + 23) % 100) + 1,
      }),
    );
    
    const timeAwait = (waitTime: number): Promise<void> =>
      new Promise((res) =>
        window.setTimeout(() => {
          res();
        }, waitTime),
      );
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '序号',
        dataIndex: 'index',
        valueType: 'index',
        width: 80,
      },
      {
        title: '状态',
        dataIndex: 'status',
        initialValue: 'all',
        filters: true,
        onFilter: true,
        valueEnum: DEMO_STATUS_VALUE_ENUM,
      },
      {
        title: '部署进度',
        key: 'progress',
        dataIndex: 'progress',
        valueType: (item) => ({
          type: 'progress',
          status: item.status !== 'error' ? 'active' : 'exception',
        }),
      },
      {
        title: '时间',
        key: 'since',
        children: [
          {
            title: '创建时间',
            key: 'createdAt',
            dataIndex: 'createdAt',
            valueType: 'date',
          },
          {
            title: '更新时间',
            key: 'updatedAt',
            dataIndex: 'updatedAt',
            valueType: 'date',
          },
        ],
      },
    ];
    
    const Demo = () => {
      const [time, setTime] = useState(() => FIXED_BASE_TIMESTAMP);
      const [polling, setPolling] = useState<number>(2000);
      return (
        <ProTable<TableListItem>
          columns={columns}
          rowKey="key"
          pagination={{
            showSizeChanger: true,
          }}
          polling={polling}
          request={async () => {
            await timeAwait(2000);
            setTime(FIXED_BASE_TIMESTAMP);
            return {
              data: tableListDataSource,
              success: true,
              total: tableListDataSource.length,
            };
          }}
          dateFormatter="string"
          headerTitle={`上次更新时间:${dayjs(time).format('HH:mm:ss')}`}
          toolBarRender={() => [
            <Button
              key="polling"
              type="primary"
              onClick={() => {
                if (polling) {
                  setPolling(0);
                  return;
                }
                setPolling(2000);
              }}
            >
              {polling ? <LoadingOutlined /> : <ReloadOutlined />}
              {polling ? '停止轮询' : '开始轮询'}
            </Button>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    日期格式化为字符串
    服务名称部署时间
    暂无数据
    暂无数据
    日期格式化为数字
    服务名称部署时间
    暂无数据
    暂无数据
    使用自定义函数进行日期格式化
    服务名称部署时间
    暂无数据
    暂无数据
    dateFormatter - Date Formatting
    import type { ProColumns, ProFormInstance } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { useRef, useState } from 'react';
    
    export type TableListItem = {
      key: number;
      name: string;
      createdAt: string;
    };
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '服务名称',
        dataIndex: 'name',
        initialValue: '用户认证服务',
      },
      {
        title: '部署时间',
        dataIndex: 'createdAt',
        valueType: 'date',
        initialValue: '2024-01-15',
      },
    ];
    
    const mockData = {
      key: 1,
      name: '用户认证服务',
      createdAt: '2024-01-15',
    };
    
    const Demo = () => {
      const ref = useRef<ProFormInstance>();
      const [collapsed, setCollapsed] = useState(false);
    
      return (
        <>
          <ProTable<TableListItem>
            style={{
              margin: '16px',
            }}
            columns={columns}
            request={(_params) => {
    
              return Promise.resolve({
                data: [mockData],
                total: 1,
                success: true,
              });
            }}
            rowKey="key"
            pagination={{
              showSizeChanger: true,
            }}
            search={{
              collapsed,
              onCollapse: setCollapsed,
            }}
            formRef={ref}
            options={false}
            dateFormatter="string"
            headerTitle="日期格式化为字符串"
          />
    
          <ProTable<TableListItem>
            style={{
              margin: '16px',
            }}
            columns={columns}
            request={(_params) => {
    
              return Promise.resolve({
                data: [mockData],
                total: 1,
                success: true,
              });
            }}
            rowKey="key"
            pagination={{
              showSizeChanger: true,
            }}
            search={{
              collapsed,
              onCollapse: setCollapsed,
            }}
            formRef={ref}
            options={false}
            dateFormatter="number"
            headerTitle="日期格式化为数字"
          />
          <ProTable<TableListItem>
            style={{
              margin: '16px',
            }}
            columns={columns}
            request={(_params) => {
    
              return Promise.resolve({
                data: [mockData],
                total: 1,
                success: true,
              });
            }}
            rowKey="key"
            pagination={{
              showSizeChanger: true,
            }}
            search={{
              collapsed,
              onCollapse: setCollapsed,
            }}
            formRef={ref}
            options={false}
            dateFormatter={(value, _valueType) => {
    
              return value.format('YYYY-MM-DD HH:mm:ss');
            }}
            headerTitle="使用自定义函数进行日期格式化"
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Toolbar Customization

    Configure toolbar rendering using the toolbar property extension.

    应用名称负责人
    状态
    容器数量
    操作
    暂无数据
    暂无数据
    Toolbar Customization
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { Badge, Button } from 'antd';
    import React, { useState } from 'react';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      status: string;
      creator: string;
      createdAt: number;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '负责人',
        dataIndex: 'creator',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '状态',
        dataIndex: 'status',
        initialValue: 'all',
        filters: true,
        onFilter: true,
        valueEnum: {
          all: { text: '全部', status: 'Default' },
          close: { text: '待发布', status: 'Default' },
          running: { text: '发布中', status: 'Processing' },
          online: { text: '发布成功', status: 'Success' },
          error: { text: '发布失败', status: 'Error' },
        },
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: (_, record) => [
          record.status === 'close' && <a key="publish">发布</a>,
          (record.status === 'running' || record.status === 'online') && (
            <a key="stop">停用</a>
          ),
          record.status === 'error' && <a key="republish">重新发布</a>,
          <a
            key="monitor"
            style={
              record.status === 'running'
                ? {
                    color: 'rgba(0,0,0,.25)',
                    cursor: 'not-allowed',
                  }
                : {}
            }
          >
            监控
          </a>,
        ],
      },
    ];
    
    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>('tab1');
    
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={(params, sorter, filter) => {
            console.log(params, sorter, filter);
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          toolbar={{
            filter: (
              <LightFilter>
                <ProFormDatePicker name="startdate" label="部署日期" />
              </LightFilter>
            ),
            menu: {
              type: 'tab',
              activeKey: activeKey,
              items: [
                {
                  key: 'tab1',
                  label: <span>应用{renderBadge(99, activeKey === 'tab1')}</span>,
                },
                {
                  key: 'tab2',
                  label: <span>项目{renderBadge(30, activeKey === 'tab2')}</span>,
                },
                {
                  key: 'tab3',
                  label: <span>文档{renderBadge(12, activeKey === 'tab3')}</span>,
                },
              ],
              onChange: (key) => {
                setActiveKey(key as string);
              },
            },
            actions: [
              <Button key="primary" type="primary">
                新建应用
              </Button>,
            ],
          }}
          rowKey="key"
          pagination={{
            showQuickJumper: true,
          }}
          search={false}
          dateFormatter="string"
          options={{
            setting: {
              draggable: true,
              checkable: true,
              checkedReset: false,
              extra: [<a key="confirm">确认</a>],
            },
          }}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    实例数0
    负责人书琰
    关联项目智慧零售平台
    创建时间2024-01-10
    上线时间2024-01-15
    自定义表格主体
    序号更新时间部署进度
    暂无数据
    暂无数据
    Table Body Customization
    import { MailOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Card, Descriptions, Menu } from 'antd';
    import { useState } from 'react';
    
    import { FIXED_BASE_TIMESTAMP } from '../mockData';
    
    const waitTime = (time: number = 100) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(true);
        }, time);
      });
    };
    
    export type TableListItem = {
      key: number;
      name: string;
      createdAt: number;
      progress: number;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 2 },
      (_, i) => ({
        key: i,
        name: i === 0 ? '用户认证服务' : '支付网关',
        createdAt: FIXED_BASE_TIMESTAMP - (i * 1000 + 200),
        progress: ((i * 17 + 23) % 100) + 1,
      }),
    );
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '序号',
        dataIndex: 'index',
        valueType: 'index',
        width: 80,
      },
      {
        title: '更新时间',
        key: 'since2',
        dataIndex: 'createdAt',
        valueType: 'date',
      },
      {
        title: '部署进度',
        dataIndex: 'progress',
        valueType: 'progress',
      },
    ];
    
    const Demo = () => {
      const [key, setKey] = useState('1');
    
      return (
        <ProTable<TableListItem>
          columns={columns}
          rowKey="key"
          pagination={{
            showSizeChanger: true,
          }}
          tableRender={(_, dom) => (
            <div
              style={{
                display: 'flex',
                width: '100%',
              }}
            >
              <Menu
                onSelect={(e) => setKey(e.key as string)}
                style={{ width: 256 }}
                defaultSelectedKeys={['1']}
                defaultOpenKeys={['sub1']}
                mode="inline"
                items={[
                  {
                    key: 'sub1',
                    label: (
                      <span>
                        <MailOutlined />
                        <span>服务管理</span>
                      </span>
                    ),
                    children: [
                      {
                        type: 'group',
                        key: 'g1',
                        label: '核心服务',
                        children: [
                          { key: '1', label: '用户认证服务' },
                          { key: '2', label: '订单处理中心' },
                        ],
                      },
                      {
                        type: 'group',
                        key: 'g2',
                        label: '基础设施',
                        children: [
                          { key: '3', label: '支付网关' },
                          { key: '4', label: '消息推送平台' },
                        ],
                      },
                    ],
                  },
                ]}
              />
              <div
                style={{
                  flex: 1,
                }}
              >
                {dom}
              </div>
            </div>
          )}
          tableExtraRender={(_, data) => (
            <Card>
              <Descriptions size="small" column={3}>
                <Descriptions.Item label="实例数">{data.length}</Descriptions.Item>
                <Descriptions.Item label="负责人">书琰</Descriptions.Item>
                <Descriptions.Item label="关联项目">
                  <a>智慧零售平台</a>
                </Descriptions.Item>
                <Descriptions.Item label="创建时间">2024-01-10</Descriptions.Item>
                <Descriptions.Item label="上线时间">2024-01-15</Descriptions.Item>
              </Descriptions>
            </Card>
          )}
          params={{
            key,
          }}
          request={async () => {
            await waitTime(200);
            return {
              success: true,
              data: tableListDataSource,
            };
          }}
          dateFormatter="string"
          headerTitle="自定义表格主体"
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Card Table

    For branded layouts you can bend the defaults: configure the outer card via cardProps (often cardProps.title for the heading) and put primary actions in headerTitle (see demo).

    业务定制
    应用名称
    容器数量
    创建者操作
    暂无数据
    暂无数据

    ProTable 卡片标题 Props 说明:

    • ProTable: 专业表格组件
    • 卡片标题: 展示卡片标题功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • cardProps: 卡片属性配置
    • headerTitle: 表格标题
    • rowKey: 行键
    • search: 搜索配置

    卡片标题特点:

    • 卡片包装: 支持卡片包装
    • 自定义标题: 支持自定义标题
    • 请求处理: 支持请求处理
    • 简洁配置: 简洁的配置方式

    使用场景:

    • 业务定制: 业务定制需求
    • 卡片展示: 卡片展示功能
    • 数据管理: 数据管理系统
    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            cardProps={{ title: '业务定制', variant: 'outlined' }}
            headerTitle={
              <Button
                key="primary"
                type="primary"
                onClick={() => {
                  alert('add');
                }}
              >
                添加
              </Button>
            }
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 卡片标题 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>卡片标题</strong>: 展示卡片标题功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>cardProps</strong>: 卡片属性配置
              </li>
              <li>
                <strong>headerTitle</strong>: 表格标题
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>卡片标题特点:</h4>
            <ul>
              <li>
                <strong>卡片包装</strong>: 支持卡片包装
              </li>
              <li>
                <strong>自定义标题</strong>: 支持自定义标题
              </li>
              <li>
                <strong>请求处理</strong>: 支持请求处理
              </li>
              <li>
                <strong>简洁配置</strong>: 简洁的配置方式
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>业务定制</strong>: 业务定制需求
              </li>
              <li>
                <strong>卡片展示</strong>: 卡片展示功能
              </li>
              <li>
                <strong>数据管理</strong>: 数据管理系统
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Value Type Examples

    valueType - Date

    日期类型展示
    创建时间日期区间时间区间更新日期更新距今关闭时间操作
    暂无数据
    暂无数据
    import { ProTable } from '@ant-design/pro-components';
    
    import { DEMO_VALUE_ENUM, FIXED_BASE_TIMESTAMP } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: string;
      updatedAt: number;
      createdAt: number;
      progress: number;
      money: number;
      percent: number | string;
      createdAtRange: number[];
      code: string;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 2 },
      (_, i) => ({
        key: i,
        name: i === 0 ? '用户认证服务' : '支付网关',
        status: DEMO_VALUE_ENUM[(i % 4) as keyof typeof DEMO_VALUE_ENUM],
        updatedAt: FIXED_BASE_TIMESTAMP - (i * 500 + 100),
        createdAt: FIXED_BASE_TIMESTAMP - (i * 1000 + 200),
        createdAtRange: [
          FIXED_BASE_TIMESTAMP - (i * 1000 + 300),
          FIXED_BASE_TIMESTAMP - (i * 1000 + 400),
        ],
        money: ((i * 3456 + 7890) % 50000) * 100,
        progress: ((i * 17 + 23) % 100) + 1,
        percent:
          i % 2 === 0
            ? ((i + 1) * 10 + 0.123).toFixed(3)
            : -((i + 1) * 10 + 0.456).toFixed(2),
        code: `const healthCheck = async (host) => {
      const res = await fetch(host + '/health');
      return { status: res.status };
    };`,
      }),
    );
    
    const Demo = () => (
      <ProTable<TableListItem>
        columns={[
          {
            title: '创建时间',
            key: 'since',
            dataIndex: 'createdAt',
            valueType: 'dateTime',
          },
          {
            title: '日期区间',
            key: 'dateRange',
            dataIndex: 'createdAtRange',
            valueType: 'dateRange',
          },
          {
            title: '时间范围',
            key: 'dateTimeRangeCustom',
            dataIndex: 'dateTimeRange',
            hideInTable: true,
            valueType: 'dateTimeRange',
            fieldProps: {},
            formItemRender: (_, { type, defaultRender }) => {
              if (type === 'form') {
                return null;
              }
              return defaultRender(_);
            },
          },
          {
            title: '时间区间',
            key: 'dateTimeRange',
            dataIndex: 'createdAtRange',
            valueType: 'dateTimeRange',
            search: {
              transform: (value: any) => ({
                startTime: value[0],
                endTime: value[1],
              }),
            },
          },
          {
            title: '更新日期',
            key: 'since2',
            dataIndex: 'createdAt',
            valueType: 'date',
          },
          {
            title: '更新距今',
            key: 'since4',
            dataIndex: 'createdAt',
            valueType: 'fromNow',
          },
          {
            title: '关闭时间',
            key: 'since3',
            dataIndex: 'updatedAt',
            valueType: 'time',
          },
          {
            title: '操作',
            key: 'option',
            width: 120,
            valueType: 'option',
            render: (_, row, index, action) => [
              <a
                key="edit"
                onClick={() => {
                  action?.startEditable(row.key);
                }}
              >
                编辑
              </a>,
            ],
          },
        ]}
        request={() => {
          return Promise.resolve({
            total: 200,
            data: tableListDataSource,
            success: true,
          });
        }}
        rowKey="key"
        headerTitle="日期类型展示"
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    valueType - Numeric

    数值类型展示
    部署进度合同金额请求量响应时间CPU 占用操作
    暂无数据
    暂无数据
    import { ProTable } from '@ant-design/pro-components';
    
    import { DEMO_VALUE_ENUM, FIXED_BASE_TIMESTAMP } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: string;
      updatedAt: number;
      createdAt: number;
      progress: number;
      money: number;
      percent: number | string;
      createdAtRange: number[];
      code: string;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 2 },
      (_, i) => ({
        key: i,
        name: i === 0 ? '用户认证服务' : '支付网关',
        status: DEMO_VALUE_ENUM[(i % 4) as keyof typeof DEMO_VALUE_ENUM],
        updatedAt: FIXED_BASE_TIMESTAMP - (i * 500 + 100),
        createdAt: FIXED_BASE_TIMESTAMP - (i * 1000 + 200),
        createdAtRange: [
          FIXED_BASE_TIMESTAMP - (i * 1000 + 300),
          FIXED_BASE_TIMESTAMP - (i * 1000 + 400),
        ],
        money: ((i * 3456 + 7890) % 50000) * 100,
        progress: ((i * 17 + 23) % 100) + 1,
        percent:
          i % 2 === 0
            ? ((i + 1) * 10 + 0.123).toFixed(3)
            : -((i + 1) * 10 + 0.456).toFixed(2),
        code: `const healthCheck = async (host) => {
      const res = await fetch(host + '/health');
      return { status: res.status };
    };`,
      }),
    );
    
    const Demo = () => (
      <ProTable<TableListItem>
        columns={[
          {
            title: '部署进度',
            key: 'progress',
            dataIndex: 'progress',
            valueType: (item) => ({
              type: 'progress',
              status: item.status !== 'error' ? 'active' : 'exception',
            }),
            width: 200,
          },
          {
            title: '合同金额',
            dataIndex: 'money',
            valueType: 'money',
            width: 150,
          },
          {
            title: '请求量',
            dataIndex: 'money',
            key: 'digit',
            valueType: 'digit',
            width: 150,
          },
          {
            title: '响应时间',
            dataIndex: 'money',
            key: 'second',
            valueType: 'second',
            width: 150,
          },
          {
            title: 'CPU 占用',
            key: 'percent',
            width: 120,
            dataIndex: 'percent',
            valueType: () => ({
              type: 'percent',
            }),
          },
          {
            title: '操作',
            key: 'option',
            width: 120,
            valueType: 'option',
            render: (_, row, index, action) => [
              <a
                key="edit"
                onClick={() => {
                  action?.startEditable(row.key);
                }}
              >
                编辑
              </a>,
            ],
          },
        ]}
        request={() => {
          return Promise.resolve({
            total: 200,
            data: tableListDataSource,
            success: true,
          });
        }}
        rowKey="key"
        headerTitle="数值类型展示"
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    valueType - Style

    多值类型展示
    序号border 序号部署脚本负责人架构图操作
    暂无数据
    暂无数据
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Space } from 'antd';
    import dayjs from 'dayjs';
    
    import { DEMO_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: string | number;
      updatedAt: number;
      createdAt: number;
      progress: number;
      money: number;
      percent: number | string;
      createdAtRange: number[];
      code: string;
      avatar: string;
      image: string;
    };
    
    const baseTime = dayjs('2024-01-15 10:30:00').valueOf();
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 2 },
      (_, i) => ({
        key: i,
        avatar:
          'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
        image:
          'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
        name: i === 0 ? '用户认证服务' : '支付网关',
        status: DEMO_VALUE_ENUM[(i % 4) as keyof typeof DEMO_VALUE_ENUM],
        updatedAt: baseTime - (i * 500 + 100),
        createdAt: baseTime - (i * 1000 + 200),
        createdAtRange: [baseTime - (i * 1000 + 300), baseTime - (i * 1000 + 400)],
        money: ((i * 3456 + 7890) % 50000) * 100,
        progress: ((i * 17 + 23) % 100) + 1,
        percent:
          i % 2 === 0
            ? ((i + 1) * 10 + 0.123).toFixed(3)
            : -((i + 1) * 10 + 0.456).toFixed(2),
        code: `const healthCheck = async (host) => {
      const res = await fetch(host + '/health');
      return { status: res.status };
    };`,
      }),
    );
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '序号',
        dataIndex: 'index',
        valueType: 'index',
      },
      {
        title: 'border 序号',
        dataIndex: 'index',
        key: 'indexBorder',
        valueType: 'indexBorder',
      },
      {
        title: '部署脚本',
        key: 'code',
        width: 120,
        dataIndex: 'code',
        valueType: 'code',
      },
      {
        title: '负责人',
        dataIndex: 'avatar',
        key: 'avatar',
        valueType: 'avatar',
        width: 150,
        render: (dom) => (
          <Space>
            <span>{dom}</span>
            <a
              href="https://github.com/ant-design"
              target="_blank"
              rel="noopener noreferrer"
            >
              书琰
            </a>
          </Space>
        ),
      },
      {
        title: '架构图',
        dataIndex: 'image',
        key: 'image',
        valueType: 'image',
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: (_, row, index, action) => [
          <a
            key="edit"
            onClick={() => {
              action?.startEditable(row.key);
            }}
          >
            编辑
          </a>,
        ],
      },
    ];
    
    const Demo = () => (
      <ProTable<TableListItem>
        columns={columns}
        request={() => {
          return Promise.resolve({
            total: 200,
            data: tableListDataSource,
            success: true,
          });
        }}
        rowKey="key"
        headerTitle="多值类型展示"
      />
    );
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    valueType - Selection

    枚举类型 valueType 切换
    状态列类型:
    应用名称状态(下拉选择 select)优先级(select)技术栈(cascader)所属部门(treeSelect)操作
    暂无数据
    暂无数据
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Radio, Space } from 'antd';
    import { useState } from 'react';
    
    /** 服务状态枚举 */
    const statusEnum = {
      all: { text: '全部', status: 'Default' },
      running: { text: '运行中', status: 'Processing' },
      online: { text: '已上线', status: 'Success' },
      error: { text: '异常', status: 'Error' },
    };
    
    /** 优先级枚举 */
    const priorityEnum = {
      urgent: { text: '紧急', status: 'Error' },
      high: { text: '高', status: 'Warning' },
      medium: { text: '中', status: 'Processing' },
      low: { text: '低', status: 'Default' },
    };
    
    /** 技术栈级联选项 */
    const techStackOptions = [
      {
        label: '前端',
        value: 'frontend',
        children: [
          { label: 'React', value: 'react' },
          { label: 'Vue', value: 'vue' },
          { label: 'Angular', value: 'angular' },
        ],
      },
      {
        label: '后端',
        value: 'backend',
        children: [
          { label: 'Java', value: 'java' },
          { label: 'Go', value: 'go' },
          { label: 'Node.js', value: 'nodejs' },
        ],
      },
      {
        label: '基础设施',
        value: 'infra',
        children: [
          { label: 'Kubernetes', value: 'k8s' },
          { label: 'Docker', value: 'docker' },
          { label: 'Terraform', value: 'terraform' },
        ],
      },
    ];
    
    /** 部门树形选项 */
    const departmentOptions = [
      {
        label: '技术研发部',
        value: 'tech',
        children: [
          { label: '前端开发组', value: 'tech-fe' },
          { label: '后端开发组', value: 'tech-be' },
          { label: '测试保障组', value: 'tech-qa' },
        ],
      },
      {
        label: '产品设计部',
        value: 'product',
        children: [
          { label: '产品策划组', value: 'product-pm' },
          { label: 'UX 设计组', value: 'product-ux' },
        ],
      },
    ];
    
    type ValueTypeKey =
      | 'select'
      | 'radio'
      | 'radioButton'
      | 'checkbox'
      | 'cascader'
      | 'treeSelect';
    
    const VALUE_TYPE_OPTIONS: { label: string; value: ValueTypeKey }[] = [
      { label: '下拉选择 select', value: 'select' },
      { label: '单选 radio', value: 'radio' },
      { label: '单选按钮 radioButton', value: 'radioButton' },
      { label: '多选 checkbox', value: 'checkbox' },
      { label: '级联 cascader', value: 'cascader' },
      { label: '树形 treeSelect', value: 'treeSelect' },
    ];
    
    export type TableListItem = {
      key: number;
      name: string;
      status: string;
      priority: string;
      techStack: string[];
      department: string[];
    };
    
    const tableListDataSource: TableListItem[] = [
      {
        key: 0,
        name: '用户认证服务',
        status: 'running',
        priority: 'high',
        techStack: ['frontend', 'react'],
        department: ['tech-fe'],
      },
      {
        key: 1,
        name: '订单处理中心',
        status: 'online',
        priority: 'urgent',
        techStack: ['backend', 'java'],
        department: ['tech-be'],
      },
      {
        key: 2,
        name: '支付网关',
        status: 'error',
        priority: 'medium',
        techStack: ['backend', 'go'],
        department: ['tech-be'],
      },
    ];
    
    const Demo = () => {
      const [statusType, setStatusType] = useState<ValueTypeKey>('select');
    
      const columns: ProColumns<TableListItem>[] = [
        {
          title: '应用名称',
          dataIndex: 'name',
          width: 140,
          search: false,
        },
        {
          title: `状态(${VALUE_TYPE_OPTIONS.find((o) => o.value === statusType)?.label})`,
          dataIndex: 'status',
          valueType: statusType,
          initialValue: statusType === 'checkbox' ? ['all'] : 'all',
          width: 160,
          valueEnum: statusEnum,
        },
        {
          title: '优先级(select)',
          dataIndex: 'priority',
          valueType: 'select',
          width: 120,
          valueEnum: priorityEnum,
        },
        {
          title: '技术栈(cascader)',
          key: 'techStack',
          dataIndex: 'techStack',
          width: 160,
          valueType: 'cascader',
          fieldProps: {
            options: techStackOptions,
          },
        },
        {
          title: '所属部门(treeSelect)',
          key: 'department',
          dataIndex: 'department',
          width: 180,
          valueType: 'treeSelect',
          fieldProps: {
            options: departmentOptions,
            showSearch: true,
            filterTreeNode: true,
            multiple: true,
            treeNodeFilterProp: 'label',
          },
        },
        {
          title: '操作',
          key: 'option',
          width: 80,
          valueType: 'option',
          render: (_, row, index, action) => [
            <a
              key="edit"
              onClick={() => {
                action?.startEditable(row.key);
              }}
            >
              编辑
            </a>,
          ],
        },
      ];
    
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={() => {
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          search={{
            defaultCollapsed: false,
            span: 12,
            labelWidth: 'auto',
          }}
          editable={{
            type: 'multiple',
          }}
          rowKey="key"
          headerTitle="枚举类型 valueType 切换"
          toolBarRender={() => [
            <Space key="switch">
              <span>状态列类型:</span>
              <Radio.Group
                optionType="button"
                size="small"
                value={statusType}
                onChange={(e) => setStatusType(e.target.value)}
                options={VALUE_TYPE_OPTIONS}
              />
            </Space>,
          ]}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Custom valueType

    自定义 valueType
    链接标签操作
    暂无数据
    暂无数据

    ProTable 自定义值类型 Props 说明:

    • ProTable: 专业表格组件
    • ProProvider: 专业提供者组件
    • Input: 输入框组件
    • Tag: 标签组件
    • 自定义值类型: 展示自定义值类型功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • rowKey: 行键
    • headerTitle: 表格标题

    自定义值类型特点:

    • valueTypeMap: 值类型映射
    • 自定义渲染: 支持自定义渲染
    • 表单项渲染: 支持表单项渲染
    • 链接类型: 支持链接类型
    • 标签类型: 支持标签类型
    • 可编辑: 支持可编辑功能

    使用场景:

    • 自定义展示: 自定义展示需求
    • 特殊数据类型: 特殊数据类型处理
    • 业务定制: 业务定制需求
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProProvider, ProTable } from '@ant-design/pro-components';
    import type { InputRef } from 'antd';
    import { Input, Space, Tag } from 'antd';
    import React, { useContext, useRef, useState } from 'react';
    
    import { DEMO_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: {
        label: string | number;
        value: number;
      }[];
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 5 },
      (_, i) => ({
        key: i,
        name: `用户认证服务-${i}`,
        status: [
          {
            value: (i * 3 + 1) % 10,
            label: DEMO_VALUE_ENUM[(i % 4) as keyof typeof DEMO_VALUE_ENUM],
          },
          {
            value: (i * 5 + 2) % 10,
            label: DEMO_VALUE_ENUM[((i + 1) % 4) as keyof typeof DEMO_VALUE_ENUM],
          },
        ],
      }),
    );
    
    const TagList: React.FC<{
      value?: {
        key: string;
        label: string;
      }[];
      onChange?: (
        value: {
          key: string;
          label: string;
        }[],
      ) => void;
    }> = ({ value, onChange }) => {
      const ref = useRef<InputRef | null>(null);
      const [newTags, setNewTags] = useState<
        {
          key: string;
          label: string;
        }[]
      >([]);
      const [inputValue, setInputValue] = useState<string>('');
    
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(e.target.value);
      };
    
      const handleInputConfirm = () => {
        let tempsTags = [...(value || [])];
        if (
          inputValue &&
          tempsTags.filter((tag) => tag.label === inputValue).length === 0
        ) {
          tempsTags = [
            ...tempsTags,
            { key: `new-${tempsTags.length}`, label: inputValue },
          ];
        }
        onChange?.(tempsTags);
        setNewTags([]);
        setInputValue('');
      };
    
      return (
        <Space>
          {(value || []).concat(newTags).map((item) => (
            <Tag key={item.key}>{item.label}</Tag>
          ))}
          <Input
            ref={ref}
            type="text"
            size="small"
            style={{ width: 78 }}
            value={inputValue}
            onChange={handleInputChange}
            onBlur={handleInputConfirm}
            onPressEnter={handleInputConfirm}
          />
        </Space>
      );
    };
    
    const columns: ProColumns<TableListItem, 'link' | 'tags'>[] = [
      {
        title: '链接',
        dataIndex: 'name',
        valueType: 'link',
      },
      {
        title: '标签',
        dataIndex: 'status',
        key: 'status',
        valueType: 'tags',
      },
      {
        title: '操作',
        key: 'option',
        valueType: 'option',
        render: (_, row, index, action) => [
          <a
            key="a"
            onClick={() => {
              action?.startEditable(row.key);
            }}
          >
            编辑
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      const values = useContext(ProProvider);
      return (
        <>
          <ProProvider.Provider
            value={{
              ...values,
              valueTypeMap: {
                link: {
                  render: (text) => <a>{text}</a>,
                  formItemRender: (text, props) => (
                    <Input placeholder="请输入链接" {...props?.fieldProps} />
                  ),
                },
                tags: {
                  render: (text) => {
                    return (
                      <>
                        {[text].flat(1).map((item) => (
                          <Tag key={item.value}>{item.label}</Tag>
                        ))}
                      </>
                    );
                  },
                  formItemRender: (text, props) => (
                    <TagList {...props} {...props?.fieldProps} />
                  ),
                },
              },
            }}
          >
            <ProTable<TableListItem, Record<string, any>, 'link' | 'tags'>
              columns={columns}
              request={() => {
                return Promise.resolve({
                  total: 200,
                  data: tableListDataSource,
                  success: true,
                });
              }}
              rowKey="key"
              headerTitle="自定义 valueType"
            />
          </ProProvider.Provider>
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 自定义值类型 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>ProProvider</strong>: 专业提供者组件
              </li>
              <li>
                <strong>Input</strong>: 输入框组件
              </li>
              <li>
                <strong>Tag</strong>: 标签组件
              </li>
              <li>
                <strong>自定义值类型</strong>: 展示自定义值类型功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>headerTitle</strong>: 表格标题
              </li>
            </ul>
            <h4>自定义值类型特点:</h4>
            <ul>
              <li>
                <strong>valueTypeMap</strong>: 值类型映射
              </li>
              <li>
                <strong>自定义渲染</strong>: 支持自定义渲染
              </li>
              <li>
                <strong>表单项渲染</strong>: 支持表单项渲染
              </li>
              <li>
                <strong>链接类型</strong>: 支持链接类型
              </li>
              <li>
                <strong>标签类型</strong>: 支持标签类型
              </li>
              <li>
                <strong>可编辑</strong>: 支持可编辑功能
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>自定义展示</strong>: 自定义展示需求
              </li>
              <li>
                <strong>特殊数据类型</strong>: 特殊数据类型处理
              </li>
              <li>
                <strong>业务定制</strong>: 业务定制需求
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Internationalization

    ProTable ships default strings for the toolbar/query area. Below is the shape of messages overridable through createIntl; pair it with antd ConfigProvider locale exactly as shown in intl.tsx.

    export const proTableIntlShape = {
      tableForm: {
        search: 'Query',
        reset: 'Reset',
        submit: 'Submit',
        collapsed: 'Expand',
        expand: 'Collapse',
        inputPlaceholder: 'Please enter',
        selectPlaceholder: 'Please select',
      },
      alert: { clear: 'Clear' },
      tableToolBar: {
        leftPin: 'Pin to left',
        rightPin: 'Pin to right',
        noPin: 'Unpinned',
        leftFixedTitle: 'Fixed the left',
        rightFixedTitle: 'Fixed the right',
        noFixedTitle: 'Not Fixed',
        reset: 'Reset',
        columnDisplay: 'Column Display',
        columnSetting: 'Settings',
        fullScreen: 'Full Screen',
        exitFullScreen: 'Exit Full Screen',
        reload: 'Refresh',
        density: 'Density',
        densityDefault: 'Default',
        densityLarger: 'Larger',
        densityMiddle: 'Middle',
        densitySmall: 'Compact',
      },
    };
    国际化示例
    zhCNIntl
    indexTitleMoney
    暂无数据
    暂无数据
    Internationalization
    import { PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button, ConfigProvider, Select, Space } from 'antd';
    import caESIntl from 'antd/locale/ca_ES';
    import enGBIntl from 'antd/locale/en_GB';
    import enUSIntl from 'antd/locale/en_US';
    import esESIntl from 'antd/locale/es_ES';
    import frFRIntl from 'antd/locale/fr_FR';
    import itITIntl from 'antd/locale/it_IT';
    import jaJPIntl from 'antd/locale/ja_JP';
    import msMYIntl from 'antd/locale/ms_MY';
    import ptBRIntl from 'antd/locale/pt_BR';
    import ruRUIntl from 'antd/locale/ru_RU';
    import srRSIntl from 'antd/locale/sr_RS';
    import thTHIntl from 'antd/locale/th_TH';
    import viVNIntl from 'antd/locale/vi_VN';
    import zhCNIntl from 'antd/locale/zh_CN';
    import zhTWIntl from 'antd/locale/zh_TW';
    import dayjs from 'dayjs';
    import { useRef, useState } from 'react';
    
    const intlMap = {
      zhCNIntl,
      enUSIntl,
      enGBIntl,
      viVNIntl,
      itITIntl,
      jaJPIntl,
      esESIntl,
      caESIntl,
      ruRUIntl,
      srRSIntl,
      msMYIntl,
      zhTWIntl,
      frFRIntl,
      ptBRIntl,
      thTHIntl,
    };
    
    type GithubIssueItem = {
      key: number;
      name: string;
      createdAt: number;
    };
    
    const columns: ProColumns<GithubIssueItem>[] = [
      {
        title: 'index',
        dataIndex: 'index',
        valueType: 'indexBorder',
      },
      {
        title: 'Title',
        dataIndex: 'name',
      },
      {
        title: 'Money',
        dataIndex: 'title',
        width: 100,
        order: 1,
        valueType: 'money',
        renderText: () => '128000',
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
      const [intl, setIntl] = useState('zhCNIntl');
      return (
        <ConfigProvider locale={intlMap[intl as 'zhCNIntl']}>
          <ProTable<GithubIssueItem>
            columns={columns}
            actionRef={actionRef}
            request={async () => {
              return {
                data: [
                  {
                    key: 1,
                    name: '企业版云服务套餐',
                    createdAt: 1705286400000,
                  },
                ],
                total: 1,
                success: true,
              };
            }}
            rowKey="key"
            rowSelection={{}}
            search={{
              labelWidth: 'auto',
            }}
            dateFormatter="string"
            headerTitle={
              <Space>
                <span>国际化示例</span>
                <Select<string>
                  variant="borderless"
                  value={intl}
                  onChange={(value) => {
                    dayjs.locale(intlMap[value as 'zhCNIntl'].locale);
                    setIntl(value);
                  }}
                  options={Object.keys(intlMap).map((value) => ({
                    value,
                    label: value,
                  }))}
                />
              </Space>
            }
            toolBarRender={() => [
              <Button key="new" type="primary">
                <PlusOutlined />
                新建
              </Button>,
            ]}
          />
        </ConfigProvider>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    RTL (النسخة العربية)

    RTL means right-to-left.

    نموذج احترافي
    العنوان
    الحالة
    التسميةالتشغيل
    لا توجد بيانات
    لا توجد بيانات
    import { PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, ConfigProvider, Space, Tag } from 'antd';
    import arEGIntl from 'antd/locale/ar_EG';
    import { useRef } from 'react';
    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>[] = [
      {
        dataIndex: 'index',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: 'العنوان',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tooltip: 'سيتم تقليص العنوان في حال كان طويل جدًا',
        formItemProps: {
          rules: [
            {
              required: true,
              message: 'هذا الحقل مطلوب',
            },
          ],
        },
        width: '30%',
        search: false,
      },
      {
        title: 'الحالة',
        dataIndex: 'state',
        initialValue: 'open',
        filters: true,
        onFilter: true,
        valueEnum: {
          all: { text: 'الكل', status: 'Default' },
          open: {
            text: 'غير محلولة',
            status: 'Error',
          },
          closed: {
            text: 'تم حلها',
            status: 'Success',
          },
          processing: {
            text: 'نعمل عليها',
            status: 'Processing',
          },
        },
      },
      {
        title: 'التسمية',
        dataIndex: 'labels',
        render: (_, record) => (
          <Space>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: 'التشغيل',
        valueType: 'option',
        render: (text, record, _, action) => [
          <a href={record.url} target="_blank" rel="noopener noreferrer" key="link">
            رابط
          </a>,
          <a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
          <TableDropdown
            key="actionGroup"
            onSelect={() => action?.reload()}
            menus={[
              { key: 'copy', name: 'نسخ' },
              { key: 'delete', name: 'حذف' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
    
      return (
        <ConfigProvider locale={arEGIntl} direction="rtl">
          <ProTable<GithubIssueItem>
            columns={columns}
            actionRef={actionRef}
            request={async (params = {} as Record<string, any>) =>
              request<{
                data: GithubIssueItem[];
              }>('https://proapi.azurewebsites.net/github/issues', {
                params,
              })
            }
            pagination={{
              pageSize: 5,
            }}
            rowKey="id"
            search={{
              labelWidth: 'auto',
            }}
            dateFormatter="string"
            headerTitle="نموذج احترافي"
            toolBarRender={() => [
              <Button key="button" icon={<PlusOutlined />} type="primary">
                جديد
              </Button>,
            ]}
          />
        </ConfigProvider>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable RTL 表格 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>TableDropdown</strong>: 表格下拉菜单组件
          </li>
          <li>
            <strong>ConfigProvider</strong>: 配置提供者组件
          </li>
          <li>
            <strong>Button</strong>: 按钮组件
          </li>
          <li>
            <strong>Space</strong>: 间距组件
          </li>
          <li>
            <strong>Tag</strong>: 标签组件
          </li>
          <li>
            <strong>RTL表格</strong>: 展示RTL表格功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>actionRef</strong>: 操作引用
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>pagination</strong>: 分页配置
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>search</strong>: 搜索配置
          </li>
          <li>
            <strong>dateFormatter</strong>: 日期格式化
          </li>
          <li>
            <strong>headerTitle</strong>: 表格标题
          </li>
          <li>
            <strong>toolBarRender</strong>: 工具栏渲染
          </li>
        </ul>
        <h4>RTL表格特点:</h4>
        <ul>
          <li>
            <strong>RTL支持</strong>: 支持RTL布局
          </li>
          <li>
            <strong>阿拉伯语</strong>: 支持阿拉伯语
          </li>
          <li>
            <strong>国际化</strong>: 支持国际化
          </li>
          <li>
            <strong>方向控制</strong>: 支持方向控制
          </li>
          <li>
            <strong>本地化</strong>: 支持本地化
          </li>
          <li>
            <strong>多语言</strong>: 支持多语言
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>阿拉伯语应用</strong>: 阿拉伯语应用需求
          </li>
          <li>
            <strong>RTL布局</strong>: RTL布局需求
          </li>
          <li>
            <strong>国际化系统</strong>: 国际化系统
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Theme

    Dark Theme / Compact Theme
    import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import {
      Button,
      ConfigProvider,
      Dropdown,
      message,
      Space,
      Tag,
      theme,
    } from 'antd';
    import { useRef } from 'react';
    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>[] = [
      {
        dataIndex: 'index',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: '标题',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tooltip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
      },
      {
        disable: true,
        title: '状态',
        dataIndex: 'state',
        filters: true,
        onFilter: true,
        ellipsis: true,
        valueType: 'select',
        valueEnum: {
          all: { text: '超长'.repeat(50) },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
            disabled: true,
          },
          processing: {
            text: '解决中',
            status: 'Processing',
          },
        },
      },
      {
        disable: true,
        title: '标签',
        dataIndex: 'labels',
        search: false,
        formItemRender: (_, { defaultRender }) => {
          return defaultRender(_);
        },
        render: (_, record) => (
          <Space>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'created_at',
        valueType: 'date',
        sorter: true,
        search: false,
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        valueType: 'dateRange',
        hideInTable: true,
        search: {
          transform: (value) => {
            return {
              startTime: value[0],
              endTime: value[1],
            };
          },
        },
      },
      {
        title: '操作',
        valueType: 'option',
        key: 'option',
        render: (text, record, _, action) => [
          <a
            key="editable"
            onClick={() => {
              action?.startEditable?.(record.id);
            }}
          >
            编辑
          </a>,
          <a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
          <TableDropdown
            key="actionGroup"
            onSelect={() => action?.reload()}
            menus={[
              { key: 'copy', name: '复制' },
              { key: 'delete', name: '删除' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
      const themeConfig = {
        token: {
          colorPrimary: 'red',
          borderRadius: 4,
        },
        algorithm: [theme.darkAlgorithm, theme.compactAlgorithm],
      };
      return (
        <div
          style={{
            backgroundColor: 'hsl(218,22%,7%)',
          }}
        >
          <ConfigProvider theme={themeConfig}>
            <ProTable<GithubIssueItem>
              columns={columns}
              actionRef={actionRef}
              cardBordered
              request={async (params) => {
                return request<{
                  data: GithubIssueItem[];
                }>('https://proapi.azurewebsites.net/github/issues', {
                  params,
                });
              }}
              editable={{
                type: 'multiple',
              }}
              columnsState={{
                persistenceKey: 'pro-table-singe-demos',
                persistenceType: 'localStorage',
                onChange: () => {
                  message.info('列设置已更新');
                },
              }}
              rowKey="id"
              search={{
                labelWidth: 'auto',
              }}
              options={{
                setting: {
                  listsHeight: 400,
                },
              }}
              form={{
                // 由于配置了 transform,提交的参数与定义的不同这里需要转化一下
                syncToUrl: (values, type) => {
                  if (type === 'get') {
                    return {
                      ...values,
                      created_at: [values.startTime, values.endTime],
                    };
                  }
                  return values;
                },
              }}
              pagination={{
                pageSize: 5,
                onChange: (page, pageSize) => {
                  message.info(`第 ${page} 页${pageSize ? `,每页 ${pageSize} 条` : ''}`);
                },
              }}
              dateFormatter="string"
              headerTitle="高级表格"
              toolBarRender={() => [
                <Button key="button" icon={<PlusOutlined />} type="primary">
                  新建
                </Button>,
                <Dropdown
                  key="menu"
                  menu={{
                    items: [
                      {
                        label: '1st item',
                        key: '1',
                      },
                      {
                        label: '2nd item',
                        key: '2',
                      },
                      {
                        label: '3rd item',
                        key: '3',
                      },
                    ],
                  }}
                >
                  <Button>
                    <EllipsisOutlined />
                  </Button>
                </Dropdown>,
              ]}
            />
          </ConfigProvider>
        </div>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 主题 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>TableDropdown</strong>: 表格下拉菜单组件
          </li>
          <li>
            <strong>ConfigProvider</strong>: 配置提供者组件
          </li>
          <li>
            <strong>Button</strong>: 按钮组件
          </li>
          <li>
            <strong>Dropdown</strong>: 下拉菜单组件
          </li>
          <li>
            <strong>Space</strong>: 间距组件
          </li>
          <li>
            <strong>Tag</strong>: 标签组件
          </li>
          <li>
            <strong>theme</strong>: 主题配置
          </li>
          <li>
            <strong>主题</strong>: 展示主题功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>actionRef</strong>: 操作引用
          </li>
          <li>
            <strong>cardBordered</strong>: 卡片边框
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>editable</strong>: 可编辑配置
          </li>
          <li>
            <strong>columnsState</strong>: 列状态配置
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>search</strong>: 搜索配置
          </li>
          <li>
            <strong>options</strong>: 选项配置
          </li>
          <li>
            <strong>form</strong>: 表单配置
          </li>
          <li>
            <strong>pagination</strong>: 分页配置
          </li>
          <li>
            <strong>dateFormatter</strong>: 日期格式化
          </li>
          <li>
            <strong>headerTitle</strong>: 表格标题
          </li>
          <li>
            <strong>toolBarRender</strong>: 工具栏渲染
          </li>
        </ul>
        <h4>主题特点:</h4>
        <ul>
          <li>
            <strong>暗色主题</strong>: 支持暗色主题
          </li>
          <li>
            <strong>紧凑算法</strong>: 支持紧凑算法
          </li>
          <li>
            <strong>自定义颜色</strong>: 支持自定义颜色
          </li>
          <li>
            <strong>主题配置</strong>: 支持主题配置
          </li>
          <li>
            <strong>算法组合</strong>: 支持算法组合
          </li>
          <li>
            <strong>背景色</strong>: 支持背景色
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>主题定制</strong>: 主题定制需求
          </li>
          <li>
            <strong>暗色模式</strong>: 暗色模式应用
          </li>
          <li>
            <strong>品牌定制</strong>: 品牌定制需求
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Custom Error Boundaries

    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Button, Result, Switch } from 'antd';
    import type { ErrorInfo } from 'react';
    import React, { useState } from 'react';
    
    class CustomBoundary extends React.Component<
      Record<string, any>,
      { hasError: boolean; errorInfo: string }
    > {
      state = { hasError: false, errorInfo: '' };
    
      static getDerivedStateFromError(error: Error) {
        return { hasError: true, errorInfo: error.message };
      }
    
      componentDidCatch(error: any, errorInfo: ErrorInfo) {
        // You can also log the error to an error reporting service
        console.error(error, errorInfo);
      }
    
      render() {
        if (this.state.hasError) {
          // You can render any custom fallback UI
          return (
            <Result
              icon={
                <img
                  width={256}
                  src="https://gw.alipayobjects.com/zos/antfincdn/zIgkN%26mpMZ/shibaizhuangtaizuo.png"
                />
              }
              style={{
                height: '100%',
                background: '#fff',
              }}
              title="错误处理"
              extra={
                <>
                  <div
                    style={{
                      maxWidth: 620,
                      textAlign: 'start',
                      backgroundColor: 'rgba(255,229,100,0.3)',
                      borderInlineStartColor: '#ffe564',
                      borderInlineStartWidth: '9px',
                      borderInlineStartStyle: 'solid',
                      padding: '20px 45px 20px 26px',
                      margin: 'auto',
                      marginBlockEnd: '30px',
                      marginBlockStart: '20px',
                    }}
                  >
                    <p>注意</p>
                    <p>
                      错误边界<strong>无法</strong>捕获以下场景中产生的错误:
                    </p>
                    <ul
                      style={{
                        listStyle: 'none',
                      }}
                    >
                      <li>
                        事件处理(
                        <a href="https://zh-hans.reactjs.org/docs/error-boundaries.html#how-about-event-handlers#how-about-event-handlers">
                          了解更多
                        </a>
                        )
                      </li>
                      <li>
                        异步代码(例如 <code>setTimeout</code> 或{' '}
                        <code>requestAnimationFrame</code> 回调函数)
                      </li>
                      <li>服务端渲染</li>
                      <li>它自身抛出来的错误(并非它的子组件)</li>
                    </ul>
                  </div>
                  <Button
                    danger
                    type="primary"
                    onClick={() => {
                      window.location.reload();
                    }}
                  >
                    刷新页面
                  </Button>
                </>
              }
            />
          );
        }
        return this.props.children;
      }
    }
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const ErrorTrigger = () => {
      // default to throw error for snapshot test
      const [error, setError] = useState<boolean>(true);
      if (error) throw new Error('渲染发生了错误');
      return (
        <Button
          danger
          type="primary"
          onClick={() => {
            setError(true);
          }}
        >
          触发错误
        </Button>
      );
    };
    
    const Demo = () => {
      const [custom, setCustom] = useState(true);
      return (
        <>
          <Switch
            checkedChildren="使用自定义错误边界"
            unCheckedChildren="使用默认错误边界"
            checked={custom}
            onChange={(checked) => setCustom(checked)}
          />
          <ProTable<TableListItem>
            columns={columns}
            request={(_params, _sorter, _filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            ErrorBoundary={custom ? CustomBoundary : undefined}
            headerTitle={<ErrorTrigger />}
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 错误边界 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>Switch</strong>: 开关组件
              </li>
              <li>
                <strong>Result</strong>: 结果组件
              </li>
              <li>
                <strong>Button</strong>: 按钮组件
              </li>
              <li>
                <strong>错误边界</strong>: 展示错误边界功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>ErrorBoundary</strong>: 错误边界配置
              </li>
              <li>
                <strong>headerTitle</strong>: 表格标题
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>错误边界特点:</h4>
            <ul>
              <li>
                <strong>自定义边界</strong>: 支持自定义错误边界
              </li>
              <li>
                <strong>错误捕获</strong>: 支持错误捕获
              </li>
              <li>
                <strong>错误处理</strong>: 支持错误处理
              </li>
              <li>
                <strong>容错机制</strong>: 支持容错机制
              </li>
              <li>
                <strong>错误展示</strong>: 支持错误展示
              </li>
              <li>
                <strong>错误恢复</strong>: 支持错误恢复
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>错误处理</strong>: 错误处理需求
              </li>
              <li>
                <strong>稳定性保证</strong>: 稳定性保证
              </li>
              <li>
                <strong>用户体验</strong>: 用户体验优化
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    Disable Error Boundary
    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            ErrorBoundary={false}
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 错误边界 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>错误边界</strong>: 展示错误边界功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>ErrorBoundary</strong>: 错误边界配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>错误边界特点:</h4>
            <ul>
              <li>
                <strong>错误捕获</strong>: 支持错误捕获
              </li>
              <li>
                <strong>错误处理</strong>: 支持错误处理
              </li>
              <li>
                <strong>容错机制</strong>: 支持容错机制
              </li>
              <li>
                <strong>禁用边界</strong>: 支持禁用错误边界
              </li>
              <li>
                <strong>异常处理</strong>: 支持异常处理
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>错误处理</strong>: 错误处理需求
              </li>
              <li>
                <strong>稳定性保证</strong>: 稳定性保证
              </li>
              <li>
                <strong>用户体验</strong>: 用户体验优化
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    高级表格
    序号
    标题
    状态
    标签操作
    暂无数据
    暂无数据
    import { PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, ConfigProvider, Space, Tag } from 'antd';
    import { useRef } from 'react';
    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: 'index',
        valueType: 'indexBorder',
      },
      {
        title: '标题',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tooltip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: '30%',
        search: false,
      },
      {
        title: '状态',
        dataIndex: 'state',
        initialValue: 'open',
        filters: true,
        valueType: 'select',
        valueEnum: {
          all: { text: '全部', status: 'Default' },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
          },
          processing: {
            text: '解决中',
            status: 'Processing',
          },
        },
        width: '10%',
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: '10%',
        render: (_, row) => (
          <Space>
            {row.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '操作',
        valueType: 'option',
        render: (text, row, _, action) => [
          <a href={row.url} target="_blank" rel="noopener noreferrer" key="link">
            链路
          </a>,
          <a href={row.url} target="_blank" rel="noopener noreferrer" key="warning">
            报警
          </a>,
          <a href={row.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
          <TableDropdown
            key="actionGroup"
            onSelect={() => action?.reload()}
            menus={[
              { key: 'copy', name: '复制' },
              { key: 'delete', name: '删除' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
    
      return (
        <ConfigProvider prefixCls="qixian">
          <ProTable<GithubIssueItem>
            columns={columns}
            pagination={{
              showQuickJumper: true,
            }}
            actionRef={actionRef}
            request={async (params = {} as Record<string, any>) =>
              request<{
                data: GithubIssueItem[];
              }>('https://proapi.azurewebsites.net/github/issues', {
                params,
              })
            }
            rowKey="id"
            dateFormatter="string"
            headerTitle="高级表格"
            toolBarRender={() => [
              <Button key="3" type="primary">
                <PlusOutlined />
                新建
              </Button>,
            ]}
          />
        </ConfigProvider>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable ConfigProvider Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>TableDropdown</strong>: 表格下拉菜单组件
          </li>
          <li>
            <strong>ConfigProvider</strong>: 配置提供者组件
          </li>
          <li>
            <strong>配置提供者</strong>: 展示配置提供者功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>pagination</strong>: 分页配置
          </li>
          <li>
            <strong>actionRef</strong>: 操作引用
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>dateFormatter</strong>: 日期格式化
          </li>
          <li>
            <strong>headerTitle</strong>: 表格标题
          </li>
          <li>
            <strong>toolBarRender</strong>: 工具栏渲染
          </li>
        </ul>
        <h4>配置提供者特点:</h4>
        <ul>
          <li>
            <strong>前缀定制</strong>: 支持前缀定制
          </li>
          <li>
            <strong>全局配置</strong>: 支持全局配置
          </li>
          <li>
            <strong>主题定制</strong>: 支持主题定制
          </li>
          <li>
            <strong>国际化</strong>: 支持国际化配置
          </li>
          <li>
            <strong>样式隔离</strong>: 支持样式隔离
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>多套主题</strong>: 多套主题系统
          </li>
          <li>
            <strong>样式隔离</strong>: 样式隔离需求
          </li>
          <li>
            <strong>全局配置</strong>: 全局配置管理
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    col without dataIndexnormal col
    1
    • 第 1-1 条/总共 1 条
    • 1
    高级表格
    标题
    序号状态标签创建时间创建时间操作
    🐛 [BUG]yarn install命令 antd2.4.5会报错
    1
    未解决
    bug
    2020-05-262020-05-26T09:42:56Z
    🐛 [BUG]无法创建工程npm create umi
    2
    未解决
    bug
    2020-05-262020-05-26T08:19:22Z
    🧐 [问题] build 后还存在 es6 的代码(Umi@2.13.13)
    3
    未解决
    question
    2020-05-262020-05-26T07:54:25Z
    • 第 1-3 条/总共 3 条
    • 1
    import { PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, ConfigProvider, Input, Space, Tag } from 'antd';
    import { useRef } from 'react';
    
    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 nestedColumns = [
      {
        title: 'col without dataIndex',
        key: 'expand',
      },
      {
        title: 'normal col',
        dataIndex: 'key',
      },
    ];
    
    const nestedData = [
      {
        key: 1,
        children: [
          {
            key: 11,
          },
        ],
      },
    ];
    
    const columns: ProColumns<GithubIssueItem>[] = [
      {
        title: '序号',
        dataIndex: 'index',
        valueType: 'indexBorder',
      },
      {
        title: '标题',
        dataIndex: 'title',
        fixed: 'left',
        order: 1,
        copyable: true,
        ellipsis: true,
        hideInForm: true,
        tooltip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: '30%',
      },
      {
        title: '状态',
        dataIndex: 'state',
        initialValue: 'all',
        copyable: true,
        ellipsis: true,
        onFilter: true,
        valueType: 'select',
        order: 2,
        fieldProps: {
          noStyle: true,
        },
        valueEnum: {
          all: { text: '全部', status: 'Default' },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
          },
          processing: {
            text: '解决中',
            status: 'Processing',
          },
        },
        width: '10%',
      },
      {
        title: '动态表单',
        key: 'direction',
        hideInTable: true,
        dataIndex: 'direction',
        formItemProps: {
          noStyle: true,
        },
        ignoreFormItem: true,
        formItemRender: () => {
          return <Input />;
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: '10%',
        order: -1,
        colSize: 1.5,
        formItemProps: {
          noStyle: true,
        },
        formItemRender: (_, { defaultRender }) => defaultRender(_),
        render: (_, record) => (
          <Space>
            {record.labels.map(({ name, color }) => (
              <Tag color={color} key={name}>
                {name}
              </Tag>
            ))}
          </Space>
        ),
      },
      {
        title: '创建时间',
        key: 'since',
        dataIndex: 'created_at',
        valueType: 'date',
        width: '20%',
        copyable: true,
        ellipsis: true,
        render: (value) => {
          return {
            children: value,
            props: { colSpan: 2 },
          };
        },
      },
      {
        title: '创建时间',
        key: 'since',
        dataIndex: 'created_at',
        // @ts-ignore
        valueType: () => undefined,
        width: '20%',
      },
      {
        title: '操作',
        valueType: 'option',
        fixed: 'right',
        render: (text, record, _, action) => [
          <a href={record.url} target="_blank" rel="noopener noreferrer" key="view">
            查看
          </a>,
          <TableDropdown
            key="actionGroup"
            onSelect={() => action?.reload()}
            menus={[
              { key: 'copy', name: '复制' },
              { key: 'delete', name: '删除' },
            ]}
          />,
        ],
      },
    ];
    
    const Demo = () => {
      const actionRef = useRef<ActionType>();
      const staticTableActionRef = useRef<ActionType>();
    
      return (
        <ConfigProvider prefixCls="canvas">
          <ProTable<GithubIssueItem>
            columns={columns}
            pagination={{
              showQuickJumper: true,
            }}
            actionRef={actionRef}
            request={async () => ({
              data: [],
            })}
            type="form"
            rowKey="id"
            dateFormatter="string"
            headerTitle="高级表格"
            toolBarRender={() => [
              <Button key="3" type="primary">
                <PlusOutlined />
                新建
              </Button>,
            ]}
          />
          <ProTable columns={nestedColumns} dataSource={nestedData} />
          <ProTable<GithubIssueItem>
            columns={columns}
            actionRef={staticTableActionRef}
            dataSource={[
              {
                id: 624748504,
                number: 6689,
                title: '🐛 [BUG]yarn install命令 antd2.4.5会报错',
                labels: [{ name: 'bug', color: 'error' }],
                state: 'open',
                comments: 1,
                created_at: '2020-05-26T09:42:56Z',
                updated_at: '2020-05-26T10:03:02Z',
                url: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
              },
              {
                id: 624691229,
                number: 6688,
                title: '🐛 [BUG]无法创建工程npm create umi',
                labels: [{ name: 'bug', color: 'error' }],
                state: 'open',
                comments: 0,
                created_at: '2020-05-26T08:19:22Z',
                updated_at: '2020-05-26T08:19:22Z',
                url: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
              },
              {
                id: 624674790,
                number: 6685,
                title: '🧐 [问题] build 后还存在 es6 的代码(Umi@2.13.13)',
                labels: [{ name: 'question', color: 'success' }],
                state: 'open',
                comments: 0,
                created_at: '2020-05-26T07:54:25Z',
                updated_at: '2020-05-26T07:54:25Z',
                url: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
              },
            ]}
            pagination={{
              pageSize: 5,
            }}
            rowKey="id"
            dateFormatter="string"
            headerTitle="高级表格"
            toolBarRender={() => [
              <Button key="3" type="primary">
                <PlusOutlined />
                新建
              </Button>,
            ]}
          />
        </ConfigProvider>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 单表格测试 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>TableDropdown</strong>: 表格下拉菜单组件
          </li>
          <li>
            <strong>ConfigProvider</strong>: 配置提供者组件
          </li>
          <li>
            <strong>Button</strong>: 按钮组件
          </li>
          <li>
            <strong>Input</strong>: 输入框组件
          </li>
          <li>
            <strong>Space</strong>: 间距组件
          </li>
          <li>
            <strong>Tag</strong>: 标签组件
          </li>
          <li>
            <strong>单表格测试</strong>: 展示单表格测试功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>pagination</strong>: 分页配置
          </li>
          <li>
            <strong>actionRef</strong>: 操作引用
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>type</strong>: 表格类型
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>dateFormatter</strong>: 日期格式化
          </li>
          <li>
            <strong>headerTitle</strong>: 表格标题
          </li>
          <li>
            <strong>toolBarRender</strong>: 工具栏渲染
          </li>
          <li>
            <strong>dataSource</strong>: 数据源
          </li>
        </ul>
        <h4>单表格测试特点:</h4>
        <ul>
          <li>
            <strong>表单模式</strong>: 支持表单模式
          </li>
          <li>
            <strong>嵌套表格</strong>: 支持嵌套表格
          </li>
          <li>
            <strong>静态数据</strong>: 支持静态数据
          </li>
          <li>
            <strong>动态表单</strong>: 支持动态表单
          </li>
          <li>
            <strong>固定列</strong>: 支持固定列
          </li>
          <li>
            <strong>自定义渲染</strong>: 支持自定义渲染
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>测试验证</strong>: 测试验证需求
          </li>
          <li>
            <strong>复杂表单</strong>: 复杂表单功能
          </li>
          <li>
            <strong>开发调试</strong>: 开发调试工具
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Extra demos

    Column state (columnsState), custom column-setting icon, and contentWords-style items.

    动态列状态
    排序停机信息
    应用名称
    状态部署时间备注
    暂无数据
    暂无数据
    Controlled columnsState
    import { QuestionCircleOutlined, SearchOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    import { Input, Tooltip } from 'antd';
    import { useState } from 'react';
    
    import {
      DEMO_APP_NAMES,
      DEMO_CREATORS,
      FIXED_BASE_TIMESTAMP,
    } from '../mockData';
    
    const valueEnum: Record<string, string> = {
      0: 'close',
      1: 'running',
    };
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
      status: string;
      createdAt: number;
      progress: number;
      money: number;
      memo: string;
      statusText: string;
    };
    
    const tableListDataSource: TableListItem[] = Array.from(
      { length: 5 },
      (_, i) => ({
        key: i,
        name: DEMO_APP_NAMES[i % DEMO_APP_NAMES.length],
        containers: ((i * 3 + 2) % 12) + 1,
        creator: DEMO_CREATORS[i % DEMO_CREATORS.length],
        status: valueEnum[String(i % 2)],
        createdAt: FIXED_BASE_TIMESTAMP - i * 86400000,
        money: ((i * 3456 + 7890) % 50000) * 100,
        progress: ((i * 17 + 23) % 100) + 1,
        memo:
          i % 2 === 1
            ? '核心服务,承载全站用户登录与鉴权,高峰期需要关注性能指标'
            : '日常运维中,当前运行状态正常',
        statusText: i % 2 === 0 ? '已关闭,等待重新部署' : '运行中,CPU 占用 35%',
      }),
    );
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
        filterDropdown: () => (
          <div style={{ padding: 8 }}>
            <Input style={{ width: 188, marginBottom: 8, display: 'block' }} />
          </div>
        ),
        filterIcon: (filtered) => (
          <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />
        ),
      },
      {
        title: '状态',
        dataIndex: 'status',
        initialValue: 'close',
        valueType: 'radioButton',
        valueEnum: {
          close: { text: '已关闭', status: 'Default' },
          running: { text: '运行中', status: 'Processing' },
        },
      },
      {
        title: (
          <>
            部署时间
            <Tooltip placement="top" title="最近一次部署的时间">
              <QuestionCircleOutlined style={{ marginLeft: 4 }} />
            </Tooltip>
          </>
        ),
        width: 140,
        key: 'since',
        dataIndex: 'createdAt',
        valueType: 'date',
      },
      {
        title: '备注',
        dataIndex: 'memo',
        ellipsis: true,
        copyable: true,
      },
    ];
    
    const Demo = () => {
      const [currentStatus, setCurrentStatus] = useState<string>('close');
    
      const closeColumns: ProColumns<TableListItem>[] = [
        {
          title: '排序',
          dataIndex: 'index',
          valueType: 'indexBorder',
          width: 48,
        },
        {
          title: '停机信息',
          dataIndex: 'statusText',
        },
        ...columns,
      ];
    
      const runningColumns: ProColumns<TableListItem>[] = [
        {
          title: '排序',
          dataIndex: 'index',
          valueType: 'indexBorder',
          width: 48,
        },
        {
          title: '运行信息',
          dataIndex: 'statusText',
        },
        ...columns,
      ];
      return (
        <ProTable<TableListItem>
          columns={currentStatus === 'close' ? closeColumns : runningColumns}
          request={() => {
            return Promise.resolve({
              data: tableListDataSource,
              total: tableListDataSource.length,
              success: true,
            });
          }}
          rowKey="key"
          search={{
            layout: 'vertical',
            defaultCollapsed: false,
          }}
          onSubmit={({ status }) => {
            setCurrentStatus(status);
          }}
          columnsState={{
            persistenceKey: `table_dynamic_status_${currentStatus}`,
            persistenceType: 'sessionStorage',
          }}
          dateFormatter="string"
          toolbar={{
            title: '动态列状态',
            tooltip: '根据状态切换动态显示不同列',
          }}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    User First NameUser Last NameID
    暂无数据
    暂无数据
    Custom column setting icon
    import type { ProColumns } from '@ant-design/pro-components';
    import { ProTable } from '@ant-design/pro-components';
    
    const HeartSvg = () => (
      <svg width="1em" height="1em" fill="currentColor" viewBox="0 0 1024 1024">
        <path d="M923 283.6c-13.4-31.1-32.6-58.9-56.9-82.8-24.3-23.8-52.5-42.4-84-55.5-32.5-13.5-66.9-20.3-102.4-20.3-49.3 0-97.4 13.5-139.2 39-10 6.1-19.5 12.8-28.5 20.1-9-7.3-18.5-14-28.5-20.1-41.8-25.5-89.9-39-139.2-39-35.5 0-69.9 6.8-102.4 20.3-31.4 13-59.7 31.7-84 55.5-24.4 23.9-43.5 51.7-56.9 82.8-13.9 32.3-21 66.6-21 101.9 0 33.3 6.8 68 20.3 103.3 11.3 29.5 27.5 60.1 48.2 91 32.8 48.9 77.9 99.9 133.9 151.6 92.8 85.7 184.7 144.9 188.6 147.3l23.7 15.2c10.5 6.7 24 6.7 34.5 0l23.7-15.2c3.9-2.5 95.7-61.6 188.6-147.3 56-51.7 101.1-102.7 133.9-151.6 20.7-30.9 37-61.5 48.2-91 13.5-35.3 20.3-70 20.3-103.3 0.1-35.3-7-69.6-20.9-101.9z" />
      </svg>
    );
    
    export type TableListItem = {
      id: number;
      name: string;
      lastName: string;
    };
    const tableListDataSource: TableListItem[] = [];
    
    for (let i = 0; i < 2; i += 1) {
      tableListDataSource.push({
        id: i,
        name: `John ${i}`,
        lastName: `Doe ${i}`,
      });
    }
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: 'User First Name',
        dataIndex: 'name',
      },
      {
        title: 'User Last Name',
        dataIndex: 'surname',
      },
      {
        title: 'ID',
        dataIndex: 'id',
      },
    ];
    
    const Demo = () => {
      return (
        <ProTable<TableListItem>
          columns={columns}
          request={() => Promise.resolve(tableListDataSource)}
          options={{
            search: true,
            setting: {
              children: <HeartSvg />,
            },
          }}
          rowKey="id"
          search={false}
        />
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 列设置自定义图标 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>列设置自定义图标</strong>: 展示列设置自定义图标功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
          <li>
            <strong>options</strong>: 选项配置
          </li>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>search</strong>: 搜索配置
          </li>
        </ul>
        <h4>列设置自定义图标特点:</h4>
        <ul>
          <li>
            <strong>自定义图标</strong>: 支持自定义图标
          </li>
          <li>
            <strong>列设置</strong>: 支持列设置功能
          </li>
          <li>
            <strong>搜索功能</strong>: 支持搜索功能
          </li>
          <li>
            <strong>SVG图标</strong>: 支持SVG图标
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>界面定制</strong>: 界面定制需求
          </li>
          <li>
            <strong>用户体验</strong>: 用户体验优化
          </li>
          <li>
            <strong>品牌展示</strong>: 品牌展示需求
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    问题标注
    暂无数据
    暂无数据
    Custom content search fields
    import { ProColumns, ProTable } from '@ant-design/pro-components';
    
    type ContentWordsItem = {
      id: string;
      problemCause: string;
    };
    
    const getData = () => {
      const arr = Array.from({ length: 100 }).map((_, idx) => ({
        id: (idx + 1).toString(),
        problemCause: 'problemCause',
      }));
      return arr;
    };
    
    const Demo = () => {
      const columns: ProColumns<ContentWordsItem>[] = [
        {
          disable: true,
          title: '问题标注',
          dataIndex: 'problemCause',
          editable: false,
          onFilter: false,
          ellipsis: true,
          search: true,
          valueType: 'select',
          width: 180,
        },
      ];
    
      return (
        <div>
          <ProTable<ContentWordsItem>
            rowKey="id"
            columns={columns}
            request={async () => {
              const data = getData();
              return {
                data: data,
                total: data.length,
                success: true,
              };
            }}
          />
        </div>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>ProTable 内容词项 Props 说明:</h4>
        <ul>
          <li>
            <strong>ProTable</strong>: 专业表格组件
          </li>
          <li>
            <strong>内容词项</strong>: 展示内容词项功能
          </li>
        </ul>
        <h4>ProTable 配置:</h4>
        <ul>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>request</strong>: 请求函数
          </li>
        </ul>
        <h4>列配置特点:</h4>
        <ul>
          <li>
            <strong>disable</strong>: 禁用状态
          </li>
          <li>
            <strong>title</strong>: 列标题
          </li>
          <li>
            <strong>dataIndex</strong>: 数据索引
          </li>
          <li>
            <strong>editable</strong>: 可编辑状态
          </li>
          <li>
            <strong>onFilter</strong>: 过滤功能
          </li>
          <li>
            <strong>ellipsis</strong>: 省略号显示
          </li>
          <li>
            <strong>search</strong>: 搜索功能
          </li>
          <li>
            <strong>valueType</strong>: 值类型
          </li>
          <li>
            <strong>width</strong>: 列宽度
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>内容管理</strong>: 内容管理系统
          </li>
          <li>
            <strong>词汇标注</strong>: 词汇标注功能
          </li>
          <li>
            <strong>数据展示</strong>: 数据展示需求
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    List ToolBar

    Customize the table toolbar area.

    Examples

    这里是标题
    这里是子标题
    应用名称
    容器数量
    创建者操作
    暂无数据
    暂无数据

    ProTable 基础工具栏 Props 说明:

    • ProTable: 专业表格组件
    • LightFilter: 轻量过滤器组件
    • ProFormDatePicker: 专业表单日期选择器组件
    • 基础工具栏: 展示基础工具栏功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • toolbar: 工具栏配置
    • rowKey: 行键
    • search: 搜索配置

    基础工具栏特点:

    • 标题和子标题: 支持标题和子标题
    • 搜索功能: 支持搜索功能
    • 过滤器: 支持过滤器
    • 操作按钮: 支持操作按钮
    • 设置选项: 支持设置选项

    使用场景:

    • 数据管理: 数据管理系统
    • 列表展示: 列表展示功能
    • 操作工具: 操作工具集合
    Basic Usage
    import {
      EllipsisOutlined,
      FullscreenOutlined,
      SettingOutlined,
    } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import { createTableDataSource } from '../../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueEnum: {
          all: { text: '全部' },
          书琰: { text: '书琰' },
          逄一: { text: '逄一' },
          期贤: { text: '期贤' },
          玄霜: { text: '玄霜' },
          怀渊: { text: '怀渊' },
        },
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            toolbar={{
              title: '这里是标题',
              subTitle: '这里是子标题',
              tooltip: '这是一个段描述',
              search: {
                onSearch: (value: string) => {
                  alert(value);
                },
              },
              filter: (
                <LightFilter>
                  <ProFormDatePicker name="startdate" label="响应日期" />
                </LightFilter>
              ),
              actions: [
                <Button
                  key="key"
                  type="primary"
                  onClick={() => {
                    alert('add');
                  }}
                >
                  添加
                </Button>,
              ],
              settings: [
                {
                  icon: <SettingOutlined />,
                  tooltip: '设置',
                },
                {
                  icon: <FullscreenOutlined />,
                  tooltip: '全屏',
                },
              ],
            }}
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 基础工具栏 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>LightFilter</strong>: 轻量过滤器组件
              </li>
              <li>
                <strong>ProFormDatePicker</strong>: 专业表单日期选择器组件
              </li>
              <li>
                <strong>基础工具栏</strong>: 展示基础工具栏功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>toolbar</strong>: 工具栏配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>基础工具栏特点:</h4>
            <ul>
              <li>
                <strong>标题和子标题</strong>: 支持标题和子标题
              </li>
              <li>
                <strong>搜索功能</strong>: 支持搜索功能
              </li>
              <li>
                <strong>过滤器</strong>: 支持过滤器
              </li>
              <li>
                <strong>操作按钮</strong>: 支持操作按钮
              </li>
              <li>
                <strong>设置选项</strong>: 支持设置选项
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>数据管理</strong>: 数据管理系统
              </li>
              <li>
                <strong>列表展示</strong>: 列表展示功能
              </li>
              <li>
                <strong>操作工具</strong>: 操作工具集合
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    应用名称
    容器数量
    创建者操作
    暂无数据
    暂无数据

    ProTable 无标题工具栏 Props 说明:

    • ProTable: 专业表格组件
    • LightFilter: 轻量过滤器组件
    • ProFormDatePicker: 专业表单日期选择器组件
    • 无标题工具栏: 展示无标题工具栏功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • toolbar: 工具栏配置
    • rowKey: 行键
    • search: 搜索配置

    无标题工具栏特点:

    • 简洁布局: 简洁的布局设计
    • 搜索功能: 支持搜索功能
    • 过滤器: 支持过滤器
    • 操作按钮: 支持操作按钮
    • 无标题: 无标题显示

    使用场景:

    • 简洁界面: 简洁界面需求
    • 嵌入式表格: 嵌入式表格展示
    • 空间节省: 空间节省需求
    No Title
    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        width: 120,
        valueType: 'option',
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            toolbar={{
              search: {
                onSearch: (value: string) => {
                  alert(value);
                },
              },
              filter: (
                <LightFilter>
                  <ProFormDatePicker name="startdate" label="响应日期" />
                </LightFilter>
              ),
              actions: [
                <Button
                  key="primary"
                  type="primary"
                  onClick={() => {
                    alert('add');
                  }}
                >
                  添加
                </Button>,
              ],
            }}
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 无标题工具栏 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>LightFilter</strong>: 轻量过滤器组件
              </li>
              <li>
                <strong>ProFormDatePicker</strong>: 专业表单日期选择器组件
              </li>
              <li>
                <strong>无标题工具栏</strong>: 展示无标题工具栏功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>toolbar</strong>: 工具栏配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>无标题工具栏特点:</h4>
            <ul>
              <li>
                <strong>简洁布局</strong>: 简洁的布局设计
              </li>
              <li>
                <strong>搜索功能</strong>: 支持搜索功能
              </li>
              <li>
                <strong>过滤器</strong>: 支持过滤器
              </li>
              <li>
                <strong>操作按钮</strong>: 支持操作按钮
              </li>
              <li>
                <strong>无标题</strong>: 无标题显示
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>简洁界面</strong>: 简洁界面需求
              </li>
              <li>
                <strong>嵌入式表格</strong>: 嵌入式表格展示
              </li>
              <li>
                <strong>空间节省</strong>: 空间节省需求
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    两行的情况
    应用名称
    容器数量
    创建者操作
    暂无数据
    暂无数据
    );

    ProTable 多行工具栏 Props 说明:

    • ProTable: 专业表格组件
    • LightFilter: 轻量过滤器组件
    • ProFormDatePicker: 专业表单日期选择器组件
    • Dropdown: 下拉菜单组件
    • 多行工具栏: 展示多行工具栏功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • headerTitle: 表格标题
    • toolbar: 工具栏配置
    • rowKey: 行键
    • search: 搜索配置

    多行工具栏特点:

    • 多行布局: 支持多行布局
    • 搜索功能: 支持搜索功能
    • 过滤器: 支持过滤器
    • 下拉菜单: 支持下拉菜单
    • 操作按钮: 支持操作按钮

    使用场景:

    • 复杂操作: 复杂操作需求
    • 空间利用: 空间利用优化
    • 功能丰富: 功能丰富的表格
    Double Row Layout
    import { DownOutlined, EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { Button, Dropdown } from 'antd';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        valueType: 'option',
        width: 120,
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            headerTitle="两行的情况"
            toolbar={{
              multipleLine: true,
              search: {
                onSearch: (value: string) => {
                  alert(value);
                },
              },
              filter: (
                <LightFilter>
                  <ProFormDatePicker name="startdate" label="响应日期" />
                </LightFilter>
              ),
              actions: [
                <Dropdown
                  key="overlay"
                  menu={{
                    items: [
                      {
                        label: '菜单',
                        key: '1',
                      },
                      {
                        label: '列表',
                        key: '2',
                      },
                      {
                        label: '表单',
                        key: '3',
                      },
                    ],
                    onClick: () => alert('menu click'),
                  }}
                >
                  <Button>
                    移动自
                    <DownOutlined
                      style={{
                        marginInlineStart: 8,
                      }}
                    />
                  </Button>
                </Dropdown>,
                <Button
                  key="add"
                  type="primary"
                  onClick={() => {
                    alert('add');
                  }}
                >
                  添加
                </Button>,
              ],
            }}
            rowKey="key"
            search={false}
          />
          );
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 多行工具栏 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>LightFilter</strong>: 轻量过滤器组件
              </li>
              <li>
                <strong>ProFormDatePicker</strong>: 专业表单日期选择器组件
              </li>
              <li>
                <strong>Dropdown</strong>: 下拉菜单组件
              </li>
              <li>
                <strong>多行工具栏</strong>: 展示多行工具栏功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>headerTitle</strong>: 表格标题
              </li>
              <li>
                <strong>toolbar</strong>: 工具栏配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>多行工具栏特点:</h4>
            <ul>
              <li>
                <strong>多行布局</strong>: 支持多行布局
              </li>
              <li>
                <strong>搜索功能</strong>: 支持搜索功能
              </li>
              <li>
                <strong>过滤器</strong>: 支持过滤器
              </li>
              <li>
                <strong>下拉菜单</strong>: 支持下拉菜单
              </li>
              <li>
                <strong>操作按钮</strong>: 支持操作按钮
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>复杂操作</strong>: 复杂操作需求
              </li>
              <li>
                <strong>空间利用</strong>: 空间利用优化
              </li>
              <li>
                <strong>功能丰富</strong>: 功能丰富的表格
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    标签
    名称状态
    容器数量
    创建人操作
    暂无数据
    暂无数据
    );

    ProTable 标签工具栏 Props 说明:

    • ProTable: 专业表格组件
    • LightFilter: 轻量过滤器组件
    • ProFormDatePicker: 专业表单日期选择器组件
    • 标签工具栏: 展示标签工具栏功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • toolbar: 工具栏配置
    • rowKey: 行键
    • search: 搜索配置

    标签工具栏特点:

    • 标签切换: 支持标签切换
    • 多行布局: 支持多行布局
    • 过滤器: 支持过滤器
    • 动态列: 支持动态列配置
    • 状态管理: 支持状态管理

    使用场景:

    • 分类展示: 分类展示需求
    • 多视图切换: 多视图切换功能
    • 数据分组: 数据分组管理
    With Tabs
    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { useState } from 'react';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      status: number;
      containers: number;
      creator: string;
    };
    
    const baseData = createTableDataSource({
      count: 5,
    }) as unknown as TableListItem[];
    const tableListDataSource = baseData.map((item, i) => ({
      ...item,
      status: i % 2,
    }));
    
    const columnsMap: Record<string, ProColumns<TableListItem>[]> = {
      tab1: [
        {
          title: '名称',
          dataIndex: 'name',
          render: (_) => <a>{_}</a>,
        },
        {
          title: '状态',
          key: 'status1',
          dataIndex: 'status',
          valueType: 'select',
          request: () =>
            Promise.resolve([
              {
                label: '成功',
                value: 1,
              },
              {
                label: '失败',
                value: 0,
              },
            ]),
        },
        {
          title: '容器数量',
          dataIndex: 'containers',
          align: 'right',
          sorter: (a, b) => a.containers - b.containers,
        },
        {
          title: '创建人',
          dataIndex: 'creator',
          valueType: 'select',
          valueEnum: DEMO_CREATOR_VALUE_ENUM,
        },
        {
          title: '操作',
          key: 'option',
          valueType: 'option',
          width: 120,
          render: () => [
            <a key="link">链路</a>,
            <a key="warn">报警</a>,
            <a key="more">
              <EllipsisOutlined />
            </a>,
          ],
        },
      ],
      tab2: [
        {
          title: '应用名称',
          dataIndex: 'name',
          render: (_) => <a>{_}</a>,
        },
        {
          title: '状态',
          key: 'status2',
          dataIndex: 'status',
          valueType: 'select',
          request: () =>
            Promise.resolve([
              {
                label: '启用',
                value: 1,
              },
              {
                label: '停用',
                value: 0,
              },
            ]),
        },
        {
          title: '创建者',
          dataIndex: 'creator',
          valueType: 'select',
          valueEnum: DEMO_CREATOR_VALUE_ENUM,
        },
        {
          title: '操作',
          key: 'option',
          valueType: 'option',
          width: 120,
          render: () => [
            <a key="link">链路</a>,
            <a key="warn">报警</a>,
            <a key="more">
              <EllipsisOutlined />
            </a>,
          ],
        },
      ],
    };
    
    const Demo = () => {
      const [activeKey, setActiveKey] = useState<string>('tab1');
    
      return (
        <>
          <ProTable<TableListItem>
            columns={columnsMap[activeKey]}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            toolbar={{
              title: '标签',
              multipleLine: true,
              filter: (
                <LightFilter>
                  <ProFormDatePicker name="startdate" label="响应日期" />
                </LightFilter>
              ),
              tabs: {
                activeKey,
                onChange: (key) => setActiveKey(key as string),
                items: [
                  {
                    key: 'tab1',
                    tab: '标签一',
                  },
                  {
                    key: 'tab2',
                    tab: '标签二',
                  },
                ],
              },
            }}
            rowKey="key"
            search={false}
          />
          );
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 标签工具栏 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>LightFilter</strong>: 轻量过滤器组件
              </li>
              <li>
                <strong>ProFormDatePicker</strong>: 专业表单日期选择器组件
              </li>
              <li>
                <strong>标签工具栏</strong>: 展示标签工具栏功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>toolbar</strong>: 工具栏配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>标签工具栏特点:</h4>
            <ul>
              <li>
                <strong>标签切换</strong>: 支持标签切换
              </li>
              <li>
                <strong>多行布局</strong>: 支持多行布局
              </li>
              <li>
                <strong>过滤器</strong>: 支持过滤器
              </li>
              <li>
                <strong>动态列</strong>: 支持动态列配置
              </li>
              <li>
                <strong>状态管理</strong>: 支持状态管理
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>分类展示</strong>: 分类展示需求
              </li>
              <li>
                <strong>多视图切换</strong>: 多视图切换功能
              </li>
              <li>
                <strong>数据分组</strong>: 数据分组管理
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    应用名称
    容器数量
    创建者操作
    暂无数据
    暂无数据

    ProTable 菜单工具栏 Props 说明:

    • ProTable: 专业表格组件
    • LightFilter: 轻量过滤器组件
    • ProFormDatePicker: 专业表单日期选择器组件
    • 菜单工具栏: 展示菜单工具栏功能

    ProTable 配置:

    • columns: 列配置
    • request: 请求函数
    • toolbar: 工具栏配置
    • rowKey: 行键
    • search: 搜索配置

    菜单工具栏特点:

    • 标签菜单: 支持标签菜单
    • 搜索功能: 支持搜索功能
    • 过滤器: 支持过滤器
    • 操作按钮: 支持操作按钮
    • 菜单切换: 支持菜单切换

    使用场景:

    • 分类管理: 分类管理系统
    • 标签切换: 标签切换功能
    • 多视图展示: 多视图展示需求
    Title Dropdown Menu
    import { EllipsisOutlined } from '@ant-design/icons';
    import type { ProColumns } from '@ant-design/pro-components';
    import {
      LightFilter,
      ProFormDatePicker,
      ProTable,
    } from '@ant-design/pro-components';
    import { Button } from 'antd';
    
    import { createTableDataSource, DEMO_CREATOR_VALUE_ENUM } from '../../mockData';
    
    export type TableListItem = {
      key: number;
      name: string;
      containers: number;
      creator: string;
    };
    
    const tableListDataSource = createTableDataSource({
      count: 5,
    }) as TableListItem[];
    
    const columns: ProColumns<TableListItem>[] = [
      {
        title: '应用名称',
        dataIndex: 'name',
        render: (_) => <a>{_}</a>,
      },
      {
        title: '容器数量',
        dataIndex: 'containers',
        align: 'right',
        sorter: (a, b) => a.containers - b.containers,
      },
      {
        title: '创建者',
        dataIndex: 'creator',
        valueType: 'select',
        valueEnum: DEMO_CREATOR_VALUE_ENUM,
      },
      {
        title: '操作',
        key: 'option',
        valueType: 'option',
        width: 120,
        render: () => [
          <a key="link">链路</a>,
          <a key="warn">报警</a>,
          <a key="more">
            <EllipsisOutlined />
          </a>,
        ],
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <ProTable<TableListItem>
            columns={columns}
            request={(params, sorter, filter) => {
              // 表单搜索项会从 params 传入,传递给后端接口。
              console.log(params, sorter, filter);
              return Promise.resolve({
                data: tableListDataSource,
                total: tableListDataSource.length,
                success: true,
              });
            }}
            toolbar={{
              search: {
                onSearch: (value) => {
                  alert(value);
                },
              },
              filter: (
                <LightFilter>
                  <ProFormDatePicker name="startdate" label="响应日期" />
                </LightFilter>
              ),
              actions: [
                <Button
                  key="primary"
                  type="primary"
                  onClick={() => {
                    alert('add');
                  }}
                >
                  添加
                </Button>,
              ],
              menu: {
                type: 'tab',
                items: [
                  {
                    label: '全部事项',
                    key: 'all',
                  },
                  {
                    label: '已办事项',
                    key: 'done',
                  },
                  {
                    key: 'tab1',
                    label: <span>应用</span>,
                  },
                  {
                    key: 'tab2',
                    label: <span>项目</span>,
                  },
                  {
                    key: 'tab3',
                    label: <span>文章</span>,
                  },
                  {
                    key: 'tab4',
                    label: <span>文章1</span>,
                  },
                  {
                    key: 'tab5',
                    label: <span>文章2</span>,
                  },
                  {
                    key: 'tab6',
                    label: <span>文章3</span>,
                  },
                ],
                onChange: (activeKey) => {
                  console.log('activeKey', activeKey);
                },
              },
            }}
            rowKey="key"
            search={false}
          />
          <div
            style={{
              marginTop: '20px',
              padding: '20px',
              backgroundColor: '#f5f5f5',
              borderRadius: '6px',
            }}
          >
            <h4>ProTable 菜单工具栏 Props 说明:</h4>
            <ul>
              <li>
                <strong>ProTable</strong>: 专业表格组件
              </li>
              <li>
                <strong>LightFilter</strong>: 轻量过滤器组件
              </li>
              <li>
                <strong>ProFormDatePicker</strong>: 专业表单日期选择器组件
              </li>
              <li>
                <strong>菜单工具栏</strong>: 展示菜单工具栏功能
              </li>
            </ul>
            <h4>ProTable 配置:</h4>
            <ul>
              <li>
                <strong>columns</strong>: 列配置
              </li>
              <li>
                <strong>request</strong>: 请求函数
              </li>
              <li>
                <strong>toolbar</strong>: 工具栏配置
              </li>
              <li>
                <strong>rowKey</strong>: 行键
              </li>
              <li>
                <strong>search</strong>: 搜索配置
              </li>
            </ul>
            <h4>菜单工具栏特点:</h4>
            <ul>
              <li>
                <strong>标签菜单</strong>: 支持标签菜单
              </li>
              <li>
                <strong>搜索功能</strong>: 支持搜索功能
              </li>
              <li>
                <strong>过滤器</strong>: 支持过滤器
              </li>
              <li>
                <strong>操作按钮</strong>: 支持操作按钮
              </li>
              <li>
                <strong>菜单切换</strong>: 支持菜单切换
              </li>
            </ul>
            <h4>使用场景:</h4>
            <ul>
              <li>
                <strong>分类管理</strong>: 分类管理系统
              </li>
              <li>
                <strong>标签切换</strong>: 标签切换功能
              </li>
              <li>
                <strong>多视图展示</strong>: 多视图展示需求
              </li>
            </ul>
          </div>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    EditableProTable inside ProForm

    关联题库操作
    暂无数据
    暂无数据
    Editable table with column validation in ProForm
    import type {
      ActionType,
      EditableFormInstance,
      ProColumns,
      ProFormInstance,
    } from '@ant-design/pro-components';
    import { EditableProTable, ProCard, ProForm } from '@ant-design/pro-components';
    import React, { useRef, useState } from 'react';
    
    type DataSourceType = {
      id: React.Key;
      associate?: string;
    };
    
    const defaultData: DataSourceType[] = [];
    
    const Demo = () => {
      const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(() => []);
      const formRef = useRef<ProFormInstance<any>>();
      const actionRef = useRef<ActionType>();
      const editableFormRef = useRef<EditableFormInstance>();
      const columns: ProColumns<DataSourceType>[] = [
        {
          title: '关联题库',
          dataIndex: 'associate',
          valueType: 'text',
          ellipsis: true,
          formItemProps: {
            rules: [{ required: true, message: 'Required' }],
          },
        },
        {
          title: '操作',
          valueType: 'option',
          render: (_, row) => [
            <a
              key="delete"
              onClick={() => {
                const tableDataSource = formRef.current?.getFieldValue(
                  'table',
                ) as DataSourceType[];
                formRef.current?.setFieldsValue({
                  table: tableDataSource.filter((item) => item.id !== row?.id),
                });
              }}
            >
              移除
            </a>,
            <a
              key="edit"
              onClick={() => {
                actionRef.current?.startEditable(row.id);
              }}
            >
              编辑
            </a>,
          ],
        },
      ];
    
      return (
        <ProCard>
          <div
            style={{
              maxWidth: 800,
              margin: 'auto',
            }}
          >
            <ProForm<{
              table: DataSourceType[];
            }>
              formRef={formRef}
              initialValues={{
                table: defaultData,
              }}
            >
              <EditableProTable<DataSourceType>
                rowKey="id"
                scroll={{
                  x: true,
                }}
                editableFormRef={editableFormRef}
                controlled
                actionRef={actionRef}
                formItemProps={{
                  label: '题库编辑',
                }}
                maxLength={10}
                name="table"
                columns={columns}
                recordCreatorProps={{
                  record: (index) => {
                    return { id: index + 1 };
                  },
                }}
                editable={{
                  type: 'multiple',
                  editableKeys,
                  onChange: setEditableRowKeys,
                }}
              />
            </ProForm>
          </div>
        </ProCard>
      );
    
      <div
        style={{
          marginTop: '20px',
          padding: '20px',
          backgroundColor: '#f5f5f5',
          borderRadius: '6px',
        }}
      >
        <h4>EditableProTable 规则 Props 说明:</h4>
        <ul>
          <li>
            <strong>EditableProTable</strong>: 可编辑专业表格组件
          </li>
          <li>
            <strong>ProCard</strong>: 专业卡片组件
          </li>
          <li>
            <strong>ProForm</strong>: 专业表单组件
          </li>
          <li>
            <strong>编辑规则</strong>: 展示编辑规则功能
          </li>
        </ul>
        <h4>EditableProTable 配置:</h4>
        <ul>
          <li>
            <strong>rowKey</strong>: 行键
          </li>
          <li>
            <strong>scroll</strong>: 滚动配置
          </li>
          <li>
            <strong>editableFormRef</strong>: 可编辑表单引用
          </li>
          <li>
            <strong>controlled</strong>: 受控模式
          </li>
          <li>
            <strong>actionRef</strong>: 操作引用
          </li>
          <li>
            <strong>formItemProps</strong>: 表单项属性
          </li>
          <li>
            <strong>maxLength</strong>: 最大长度
          </li>
          <li>
            <strong>name</strong>: 字段名称
          </li>
          <li>
            <strong>columns</strong>: 列配置
          </li>
          <li>
            <strong>recordCreatorProps</strong>: 记录创建属性
          </li>
          <li>
            <strong>editable</strong>: 可编辑配置
          </li>
        </ul>
        <h4>编辑规则特点:</h4>
        <ul>
          <li>
            <strong>表单验证</strong>: 支持表单验证
          </li>
          <li>
            <strong>必填校验</strong>: 支持必填校验
          </li>
          <li>
            <strong>多行编辑</strong>: 支持多行编辑
          </li>
          <li>
            <strong>动态添加</strong>: 支持动态添加
          </li>
          <li>
            <strong>行内编辑</strong>: 支持行内编辑
          </li>
          <li>
            <strong>数据控制</strong>: 支持数据控制
          </li>
        </ul>
        <h4>使用场景:</h4>
        <ul>
          <li>
            <strong>数据编辑</strong>: 数据编辑需求
          </li>
          <li>
            <strong>表单管理</strong>: 表单管理系统
          </li>
          <li>
            <strong>配置管理</strong>: 配置管理功能
          </li>
        </ul>
      </div>;
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );