对于打印可定制样式的出货单这种需求,我们可以使用 [https://www.npmjs.com/package/react-to-print](https://www.npmjs.com/package/react-to-print)
这个库来实现。
该库会打印出被创建的React组件,支持css样式的创建。
首先我们引入这个库 npm install --save react-to-print
使用方法非常简单,传入一个触发按钮Icon,再把要打印的组件传入进去就好了,我们使用ref.current传递。其他api可以参考官方文档。
import ReactToPrint from 'react-to-print';
import { PrinterOutlined } from '@ant-design/icons';
const popupContentRef = useRef(null);
<ReactToPrint
trigger={() => <PrinterOutlined />}
content={() => popupContentRef.current}
></ReactToPrint>
<div
ref={popupContentRef}
id="popupContentRef"
className={myStyles.printWrapper}
></div>
注意:打印页面可以有单独的css@media print
控制:
:global {
@media print {
html,
body {
height: initial !important;
overflow: initial !important;
-webkit-print-color-adjust: exact;
}
}
}
可以实现的效果为:
打印多页:
完整代码如下:
import React, { useRef } from 'react';
import myStyles from './index.module.less';
import ReactToPrint from 'react-to-print';
import { PrinterOutlined } from '@ant-design/icons';
const PrintComponent: React.FC = () => {
const popupContentRef = useRef(null);
function generateItems(count: number) {
return Array.from({ length: count }, (_, i) => ({
id: i + 1,
name: `产品${i + 1}`,
quantity: Math.floor(Math.random() * 5) + 1, // 随机数量
price: Math.floor(Math.random() * 100) + 10, // 随机价格
}));
}
// 示例:生成10条数据
const items = generateItems(10);
const totalAmount = items.reduce(
(total, item) => total + item.quantity * item.price,
0
);
return (
<div className={myStyles.wrapper}>
打印出货单测试
<div>
<ReactToPrint
trigger={() => <PrinterOutlined />}
content={() => popupContentRef.current}
></ReactToPrint>
</div>
<div
ref={popupContentRef}
id="popupContentRef"
className={myStyles.printWrapper}
>
<div style={styles.container}>
<h1 style={styles.title}>出货单</h1>
<table style={styles.table}>
<thead>
<tr>
<th style={styles.th}>商品</th>
<th style={styles.th}>数量</th>
<th style={styles.th}>单价</th>
<th style={styles.th}>总价</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.id}>
<td style={styles.td}>{item.name}</td>
<td style={styles.td}>{item.quantity}</td>
<td style={styles.td}>
{item.price.toFixed(2)}
</td>
<td style={styles.td}>
{(item.quantity * item.price).toFixed(
2
)}
</td>
</tr>
))}
</tbody>
</table>
<div style={styles.total}>
<strong>总价: {totalAmount.toFixed(2)}</strong>
</div>
</div>
</div>
</div>
);
};
const styles = {
container: {
maxWidth: '600px',
margin: '20px auto',
padding: '20px',
border: '1px solid #ccc',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
color: 'red',
} as React.CSSProperties,
title: {
textAlign: 'center',
marginBottom: '20px',
} as React.CSSProperties,
table: {
width: '100%',
borderCollapse: 'collapse',
marginBottom: '20px',
} as React.CSSProperties,
th: {
borderBottom: '1px solid #ddd',
padding: '10px',
textAlign: 'left',
} as React.CSSProperties,
td: {
borderBottom: '1px solid #ddd',
padding: '10px',
textAlign: 'left',
} as React.CSSProperties,
total: {
textAlign: 'right',
fontSize: '18px',
} as React.CSSProperties,
};
export default PrintComponent;