最近要实现一个签合同的需求 需要前端实现合同展示、增加签名及公章、生成合同
诉求: 不允许用户随意更改复制文案
网上搜到的方法
canvas生产pdf 但会出现页面被截断情况,所以研究了一下 react-pdf 和 @react-pdf/renderer,很好用~
@react-pdf/renderer
它会提供自带的元素,可以自定义样式,生成你想要的pdf
pdf内容
import { Document, Page, Text, StyleSheet, View, Image } from '@react-pdf/renderer';
// 自定义字体
Font.register({
family: 'Oswald',
src: 'https://64a478.ttf'
});
const styles = StyleSheet.create({
body: {
paddingTop: 60,
paddingLeft: 40,
paddingRight: 40,
paddingBottom: 30,
fontFamily: 'Oswald'
},
title: {
fontSize: 14,
textAlign: 'center',
marginBottom: 30,
},
subtitle: {
fontSize: 14,
textAlign: 'center',
marginTop: 20,
marginBottom: 20,
},
introduce: {
fontSize: 12,
lineHeight: 1.6,
},
graph: {
fontSize: 12,
lineHeight: 1.6,
wrap: true,
fontWeight: 'thin',
color: 'rgba(0,0,0,.8)',
},
graphText: {
fontWeight: 'bold',
textDecoration: 'underline',
color: '#000',
},
signImg: {
width: '80px',
height: '80px',
position: 'absolute',
left: 0,
top: 0,
zIndex: 2
},
pageNumber: {
position: 'absolute',
fontSize: 12,
bottom: 30,
left: 0,
right: 0,
textAlign: 'center',
color: 'grey',
},
});
const Content = (name?: string) => {
return <Document>
<Page size="A4" style={styles.body} >
<Text style={styles.title}>BBBBB</Text>
<Text style={styles.introduce}>This Agreement.</Text>
<Text style={styles.subtitle}>AAAAAAa</Text>
<Text style={styles.graph}>
<Text style={styles.graphText}>加粗文案 </Text><Text>当前文案在一行内</Text>
</Text>
<Image
style={styles.signImg}
src="https:xxxxx.jpg"
/>
{name ? <Text>{name}</Text> : <></>}
<Text style={styles.pageNumber} render={({ pageNumber, totalPages }) => (
`${pageNumber} / ${totalPages}`
)} fixed />
</Page>
</Document>
}
export default Content
pdf展示
hooks方式生成pdf连接和blob文件
import Content from './Content'; const [instance] = usePDF({ document: Content('xiaoming') }); // instance // loading/url/blob/error
- DOM渲染
iframe方式展示,iframe底色无法更改,对于样式要求较高的不太适用
import { PDFViewer } from '@react-pdf/renderer'; import Content from './Content'; const App = () => ( <PDFViewer> <Content /> </PDFViewer> ); ReactDOM.render(<App />, document.getElementById('root'));
react-pdf
pdf链接渲染展示pdf,解决@react-pdf/renderer样式问题,可以通过第一种方式生成的blob地址或url渲染import React, { useState } from "react"; import { Document, Page, pdfjs } from 'react-pdf'; // 6版本会报错,且此方法无法解决 需要使用5版本 // "Error: Setting up fake worker failed: "Cannot read properties of undefined (reading 'WorkerMessageHandler')". pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; const PdfView = ({ url, loadSuccess, loadError }: any) => { const [numPages, setNumPages] = useState(null); function onDocumentLoadSuccess({ numPages: nextNumPages }: any) { setNumPages(nextNumPages); loadSuccess?.() } // 页面会渲染2层 有一层的文案可被选中 renderTextLayer设为false return url ? <Document file={url} onLoadSuccess={onDocumentLoadSuccess} onLoadError={loadError} options={options} > {Array.from(new Array(numPages), (el, index) => ( <Page className="contract-content-pdf-page" width={800} key={`page_${index + 1}`} renderTextLayer={false} pageNumber={index + 1} /> ))} </Document> : <></> } export default PdfView
这两个包结合应该可以实现不同场景不同需求的pdf文档需求~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。