Bootstrap

Ant Deign Pro - ProTable - 高级表格 通用打印组件

ProTable - 高级表格

ProTable 的诞生是为了解决项目中需要写很多 table 的样板代码的问题,所以在其中做了封装了很多常用的逻辑。这些封装可以简单的分类为预设行为与预设逻辑。

依托于 ProForm 的能力,ProForm 拥有多种形态,可以切换查询表单类型,设置变形成为一个简单的 Form 表单,执行新建等功能。

但是没有打印功能。所以自己写了个通用打印组件。

 

components/FrPrint/index.less

.backgroud {
  width: 100%;
  height: 700px;
  //background-color: rgb(66, 66, 66);
}

components/FrPrint/index.tsx

import React, { useRef } from 'react';
import { Modal } from 'antd';
import { useReactToPrint } from "react-to-print";
import csstyle from "./index.less";
import moment from 'moment';
import ProTable from '@ant-design/pro-table';
import { WaterMark } from '@ant-design/pro-layout';
import { useModel } from 'umi';

export type FormValueType = {
  target?: string;
  template?: string;
  type?: string;
  time?: string;
  frequency?: string;
};

export type UpdateFrPrintProps = {
  title?: string;
  subTitle?: string;
  columns: any[];
  dataSource: any[];
  onCancel: (flag?: boolean, formVals?: FormValueType) => void;
  printModalVisible: boolean;

};
/**
 * ProTable - 高级表格 通用打印模块
 */
const FrPrint: React.FC<UpdateFrPrintProps> = (props) => {
  const { initialState } = useModel('@@initialState');
  const componentRef = useRef();
  const handlePrint = useReactToPrint({
    content: () => (componentRef.current != undefined) ? componentRef.current : null,
    onBeforeGetContent: () => (props.onCancel())
  });
  //console.log('columns', props.columns);

  const date = moment().format('YYYY-MM-DD HH:mm:ss').toString();
  return (
    <Modal
      width="80%"
      centered
      destroyOnClose
      title={false}
      visible={props.printModalVisible}
      okText="打印"
      onCancel={() => {
        props.onCancel();
      }}
      onOk={() => {
        handlePrint();//打印
      }}
      keyboard={true}
    >

      <div className={csstyle.backgroud} ref={componentRef}>
        <WaterMark content={initialState?.currentUser?.name}>
          <div style={{ padding: 30 }}>
            <div style={{ width: '100%', textAlign: "center", color: '#aaaaaa' }}>西藏大麦 · Dmart</div>
            <h3 style={{ width: '100%', textAlign: "center" }}>{props.title}</h3>
            <h4>{props.subTitle}</h4>
            {/* 普通 Table columns 不支持 valueType 属性
              <Table className={csstyle.table} columns={props.columns} dataSource={props.dataSource} pagination={false} bordered size="small" /> 
          */}
            <ProTable<any>
              columns={props.columns}
              dataSource={props.dataSource}
              rowKey="key"
              pagination={false}
              search={false}
              toolBarRender={false}
              bordered size="small"

            />
            <div style={{ width: '100%', paddingTop: 30, textAlign: "center", color: '#aaaaaa', fontSize: 10 }}>打印日期:{date}</div>
          </div>
        </WaterMark>
      </div>

    </Modal >

  );
};

export default FrPrint;

调用方法

1.引用模块

import FrPrint from "../components/FrPrint";

2.ProTable toolBarRender属性中设置打印按钮

toolBarRender={() => [
          <Button key="out">
            导出
          </Button>,
          /// 设置打印按钮 
          <Button key="out"
            onClick={() => handlePrintModalVisible(true)}
          >打印
          </Button>
        ]}

3.PageContainer中加入组件

    {/* 调用打印模块 */}
      <FrPrint
        title={tableName}
        subTitle={paramsText}
        columns={columns}
        dataSource={[...selectedRowsState, sumRow]}
        onCancel={() => {
          handlePrintModalVisible(false);
        }}
        printModalVisible={printModalVisible}
      />

完整调用Demo

regionSum/index.tsx

import React, { useState } from 'react';
import { Button } from 'antd';
import { PageContainer } from '@ant-design/pro-layout';
import type { ProColumns } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { getList } from './service';
import type { TableListItem } from './data';
import FrPrint from "../components/FrPrint";
import restyle from '../style.less';

const TableList: React.FC = () => {
  const [sortState, setSortState] = useState<boolean>(false);
  const [printModalVisible, handlePrintModalVisible] = useState<boolean>(false);
  const [paramsText, setParamsText] = useState<string>('');
  const [selectedRowsState, setSelectedRows] = useState<TableListItem[]>([]);
  const [sumRow, setSumRow] = useState<TableListItem>();
  const tableName = "区域销售汇总";

  /** 查询表单 */
  const query: ProColumns<TableListItem>[] = [
    {
      title: '日期区间',
      key: 'dateRange',
      dataIndex: 'createdAtRange',
      valueType: 'dateRange',
      hideInTable: true,
      //initialValue: [moment(), moment().add(1, 'day')],
      initialValue: ['2021-01-01', '2021-01-31'],
    }
  ]
  /** 表格列设置 */
  const columns: ProColumns<TableListItem>[] = [
    {
      title: '销售区域',
      dataIndex: 'Region',
      hideInSearch: true,
    },
    {
      title: '实销金额',
      dataIndex: 'SSS',
      align: 'right',
      valueType: 'money',
      hideInSearch: true,
      sorter: (a, b) => a.SSS - b.SSS,
    },
    {
      title: '毛利金额',
      dataIndex: 'SML',
      align: 'right',
      valueType: 'money',
      hideInSearch: true,
      sorter: (a, b) => a.SML - b.SML,
    },
    {
      title: '毛利率',
      dataIndex: 'MLL',
      align: 'right',
      valueType: 'percent',
      hideInSearch: true,
      sorter: (a, b) => a.MLL - b.MLL,
    },
  ];
  /** 表格列含查询表单 */
  const proColumns: ProColumns<TableListItem>[] = [
    ...query,
    ...columns
  ];
  return (
    <PageContainer
      header={{
        breadcrumb: {},
      }}>

      <ProTable<TableListItem>
        headerTitle={tableName}
        toolBarRender={() => [
          <Button key="out">
            导出
          </Button>,
          /// 设置打印按钮 
          <Button key="out"
            onClick={() => handlePrintModalVisible(true)}
          >打印
          </Button>
        ]}
        pagination={false}
        size="small"
        rowKey="key"
        search={{
          labelWidth: 120,
        }}
        request={getList}
        onSubmit={(params) => {
          //console.log('onSubmit.params', params);
          let tmp: string = "";
          if (params.dateRange != undefined && params.dateRange.length == 2) {
            tmp += '  日期区间:' + params.dateRange[0] + " - " + params.dateRange[1]
          }
          setParamsText(tmp)
        }}
        onChange={(pagination, filters, sorter, extra) => {
          if (Object.keys(extra).length > 0) {
            console.log("onChange.extra", extra);
            setSortState(true);//标记为排序操作状态
            setSelectedRows(extra.currentDataSource);
          }
        }}
        onDataSourceChange={(data) => {
          console.log('onDataSourceChange.data', data);
          //如果是排序操作,则不处理数据
          if (!sortState) {
            setSelectedRows(data);//获取表格数据
            ///-------------------------计算汇总-----------------------------
            let totalSSS: number = 0;
            let totalSML: number = 0;
            data.forEach(({ SSS, SML }) => {
              totalSSS += Number(SSS);
              totalSML += Number(SML);
            });
            const totalMll = totalSSS == 0 ? 0 : Number(totalSML / totalSSS * 100)
            const totalRow: TableListItem = { 'Region': '合计', 'SSS': totalSSS, 'SML': totalSML, 'MLL': totalMll }
            setSumRow(totalRow);//获取合计行数据
          }
        }}
        columns={proColumns}
        columnsState={{
          onChange: (value) => {
            console.log('column state', value);
          },
        }}
        ///增加合计行
        summary={() => {
          return sumRow != undefined ? (
            <ProTable.Summary.Row className={restyle.totleRow}>
              <ProTable.Summary.Cell index={0}>合计:</ProTable.Summary.Cell>
              <ProTable.Summary.Cell index={1}>
                <span className={restyle.totle}>{(sumRow.SSS).toFixed(2)}</span>
              </ProTable.Summary.Cell>
              <ProTable.Summary.Cell index={2}>
                <span className={restyle.totle}>{(sumRow.SML).toFixed(2)}</span>
              </ProTable.Summary.Cell>
              <ProTable.Summary.Cell index={3}>
                <span className={restyle.totle}>{(sumRow.MLL).toFixed(2)}%</span>
              </ProTable.Summary.Cell>
            </ProTable.Summary.Row>
          ) : '';
        }}
      />
      {/* 调用打印模块 */}
      <FrPrint
        title={tableName}
        subTitle={paramsText}
        columns={columns}
        dataSource={[...selectedRowsState, sumRow]}
        onCancel={() => {
          handlePrintModalVisible(false);
        }}
        printModalVisible={printModalVisible}
      />
    </PageContainer >
  );
};
export default TableList;

;