@kne/react-pdf-sign 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -26
- package/dist/index.css +10 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +143 -88
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +114 -74
- package/dist/index.modern.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -20,13 +20,13 @@ npm i --save @kne/react-pdf-sign
|
|
|
20
20
|
|
|
21
21
|
## 核心特性
|
|
22
22
|
|
|
23
|
-
**直观的签名体验** -
|
|
23
|
+
**直观的签名体验** - 提供手写签名画板,用户可以通过鼠标或触摸设备自然地绘制签名,签名支持实时预览和调整。支持在签名画板上叠加自定义内容,如日期、文字等。
|
|
24
24
|
|
|
25
25
|
**灵活的定位控制** - 签名区域可以在 PDF 页面上自由拖拽、缩放和精确定位,支持保持比例缩放,确保签名的视觉效果。
|
|
26
26
|
|
|
27
27
|
**完整的 PDF 操作** - 基于 pdf-lib 和 react-pdf,支持多页 PDF 文档的浏览、签名定位和最终签名文件的生成。
|
|
28
28
|
|
|
29
|
-
**组件化设计** - 提供多个独立组件(PDFSign、PDFViewer、LocationLayer、useSignature
|
|
29
|
+
**组件化设计** - 提供多个独立组件(PDFSign、PDFViewer、LocationLayer、useSignature),开发者可以根据需求灵活组合使用。支持默认签名位置设置和位置变化回调,便于集成到现有业务流程。
|
|
30
30
|
|
|
31
31
|
**国际化支持** - 内置中英文语言包,支持多语言切换,适合国际化应用。
|
|
32
32
|
|
|
@@ -40,7 +40,7 @@ npm i --save @kne/react-pdf-sign
|
|
|
40
40
|
- 证书颁发系统
|
|
41
41
|
- 法律文件签署
|
|
42
42
|
|
|
43
|
-
该组件库简化了 PDF
|
|
43
|
+
该组件库简化了 PDF 签名的复杂实现,开发者只需要几行代码就能集成完整的签名功能,大大提升了开发效率。新增的签名叠加功能让签名更加丰富和个性化,满足各种业务场景需求。
|
|
44
44
|
|
|
45
45
|
### 示例
|
|
46
46
|
|
|
@@ -75,7 +75,15 @@ const BaseExample = () => {
|
|
|
75
75
|
</Button>
|
|
76
76
|
<Button
|
|
77
77
|
onClick={() => {
|
|
78
|
+
const { size } = ref.current.getLocation();
|
|
78
79
|
signatureModal({
|
|
80
|
+
mask: (
|
|
81
|
+
<Flex justify="flex-end" align="flex-end" style={{ height: '100%', width: '100%', padding: '10px', boxSizing: 'border-box' }}>
|
|
82
|
+
签字日期: {new Date().toLocaleDateString()}
|
|
83
|
+
</Flex>
|
|
84
|
+
),
|
|
85
|
+
width: size.width,
|
|
86
|
+
height: size.height,
|
|
79
87
|
onSuccess: file => {
|
|
80
88
|
setSign(URL.createObjectURL(file));
|
|
81
89
|
}
|
|
@@ -236,23 +244,46 @@ render(<BaseExample />);
|
|
|
236
244
|
|
|
237
245
|
```jsx
|
|
238
246
|
const { useSignature } = _ReactPdfSign;
|
|
239
|
-
const { Button } = antd;
|
|
247
|
+
const { Button, Flex } = antd;
|
|
248
|
+
|
|
249
|
+
const { useState } = React;
|
|
240
250
|
|
|
241
251
|
const BaseExample = () => {
|
|
252
|
+
const [result, setResult] = useState(null);
|
|
242
253
|
const modal = useSignature();
|
|
243
254
|
return (
|
|
244
|
-
<
|
|
245
|
-
<
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
<Flex vertical gap={12}>
|
|
256
|
+
{result && <img src={result} alt="result" style={{ width: '300px' }} />}
|
|
257
|
+
<Flex gap={8}>
|
|
258
|
+
<Button
|
|
259
|
+
onClick={() => {
|
|
260
|
+
modal({
|
|
261
|
+
onSuccess: file => {
|
|
262
|
+
console.log(file);
|
|
263
|
+
setResult(URL.createObjectURL(file));
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}}>
|
|
267
|
+
签名
|
|
268
|
+
</Button>
|
|
269
|
+
<Button
|
|
270
|
+
onClick={() => {
|
|
271
|
+
modal({
|
|
272
|
+
mask: (
|
|
273
|
+
<Flex justify="flex-end" align="flex-end" style={{ height: '100%', width: '100%', padding: '10px', boxSizing: 'border-box' }}>
|
|
274
|
+
签字日期: {new Date().toLocaleDateString()}
|
|
275
|
+
</Flex>
|
|
276
|
+
),
|
|
277
|
+
onSuccess: file => {
|
|
278
|
+
console.log(file);
|
|
279
|
+
setResult(URL.createObjectURL(file));
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}}>
|
|
283
|
+
带有日期模版的签名
|
|
284
|
+
</Button>
|
|
285
|
+
</Flex>
|
|
286
|
+
</Flex>
|
|
256
287
|
);
|
|
257
288
|
};
|
|
258
289
|
|
|
@@ -267,14 +298,17 @@ render(<BaseExample />);
|
|
|
267
298
|
|
|
268
299
|
主要的 PDF 签名组件,集成了 PDF 查看器和签名定位功能。
|
|
269
300
|
|
|
270
|
-
| 属性
|
|
271
|
-
|
|
272
|
-
| url
|
|
273
|
-
| signature
|
|
274
|
-
| width
|
|
275
|
-
| height
|
|
276
|
-
| padding
|
|
277
|
-
| placeholder
|
|
301
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
302
|
+
|----------------|----------|-------------------|-------------------|
|
|
303
|
+
| url | string | - | PDF 文件的 URL 地址 |
|
|
304
|
+
| signature | string | - | 签名图片的 URL 地址 |
|
|
305
|
+
| width | number | 200 | 签名区域的宽度 |
|
|
306
|
+
| height | number | 50 | 签名区域的高度 |
|
|
307
|
+
| padding | number | 8 | 签名区域变换器的内边距 |
|
|
308
|
+
| placeholder | string | '拖拽到签名位置' | 签名区域的占位文本 |
|
|
309
|
+
| filename | string | 'signed-document.pdf' | 生成签名PDF的文件名 |
|
|
310
|
+
| defaultLocation | object | - | 默认签名位置信息 |
|
|
311
|
+
| onChange | function | - | 签名位置变化回调函数 |
|
|
278
312
|
|
|
279
313
|
#### 实例方法
|
|
280
314
|
|
|
@@ -334,7 +368,8 @@ PDF 文档查看器组件,提供 PDF 页面浏览功能。
|
|
|
334
368
|
|------------|----------|-----------------|------------|
|
|
335
369
|
| filename | string | 'signature.png' | 签名文件名 |
|
|
336
370
|
| width | number | 200 | 签名画板宽度 |
|
|
337
|
-
| height | number |
|
|
371
|
+
| height | number | 80 | 签名画板高度 |
|
|
372
|
+
| mask | ReactNode | - | 签名画板叠加内容 |
|
|
338
373
|
| onSuccess | function | - | 签名完成回调 |
|
|
339
374
|
| modalProps | object | - | Modal 组件属性 |
|
|
340
375
|
|
|
@@ -343,4 +378,4 @@ PDF 文档查看器组件,提供 PDF 页面浏览功能。
|
|
|
343
378
|
| 参数 | 类型 | 默认值 | 说明 |
|
|
344
379
|
|--------|--------|-----|----------|
|
|
345
380
|
| width | number | 200 | 默认签名画板宽度 |
|
|
346
|
-
| height | number |
|
|
381
|
+
| height | number | 80 | 默认签名画板高度 |
|
package/dist/index.css
CHANGED
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
._6TDb- {
|
|
52
52
|
border: 1px solid #cccccc;
|
|
53
53
|
border-radius: 4px;
|
|
54
|
+
position: relative;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
._2CGF4 {
|
|
@@ -61,4 +62,13 @@
|
|
|
61
62
|
._kWe3k .ant-modal-confirm-paragraph {
|
|
62
63
|
max-width: unset;
|
|
63
64
|
}
|
|
65
|
+
|
|
66
|
+
._FSvLv {
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 0;
|
|
69
|
+
left: 0;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: 100%;
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
}
|
|
64
74
|
/*# sourceMappingURL=index.css.map */
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["style.module.scss"],"names":[],"mappings":"AAAA;EACE,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,WAAW;AACb;AACA;;EAEE,cAAc;AAChB;;AAEA;EACE,wEAAwE;AAC1E;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,WAAW;AACb;;AAEA;;EAEE,kBAAkB;EAClB,eAAe;EACf,qBAAqB;EACrB,WAAW;EACX,YAAY;EACZ,eAAe;EACf,YAAY;AACd;;AAEA;EACE,kBAAkB;EAClB,YAAY;EACZ,SAAS;EACT,2BAA2B;EAC3B,cAAc;EACd,0CAA0C;EAC1C,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,QAAQ;AACV;;AAEA;EACE,yBAAyB;EACzB,kBAAkB;AACpB;;AAEA;EACE,WAAW;EACX,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB","file":"index.css","sourcesContent":[".pdf-view-container {\n margin: 0 auto;\n position: relative;\n max-width: 1200px;\n width: 100%;\n}\n.pdf-view-container :global(.react-pdf__Page__canvas),\n.pdf-view-container :global(.textLayer) {\n margin: 0 auto;\n}\n\n.pdf-view {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n\n.pdf-view-children {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 10;\n}\n\n.pdf-view-page-control-left,\n.pdf-view-page-control-right {\n position: absolute;\n font-size: 30px;\n top: calc(50% - 19px);\n z-index: 10;\n padding: 8px;\n cursor: pointer;\n opacity: 0.3;\n}\n\n.pdf-view-page-control-current {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n color: #666666;\n background-color: rgba(255, 255, 255, 0.5);\n text-shadow: 0 0 8px white, 0 0 8px white;\n border-radius: 4px;\n}\n\n.pdf-view-page-control-right {\n right: 0;\n}\n\n.signature-container {\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n\n.signature-canvas {\n width: 100%;\n height: 100%;\n}\n\n.signature-modal :global .ant-modal-confirm-paragraph {\n max-width: unset;\n}"]}
|
|
1
|
+
{"version":3,"sources":["style.module.scss"],"names":[],"mappings":"AAAA;EACE,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,WAAW;AACb;AACA;;EAEE,cAAc;AAChB;;AAEA;EACE,wEAAwE;AAC1E;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,WAAW;AACb;;AAEA;;EAEE,kBAAkB;EAClB,eAAe;EACf,qBAAqB;EACrB,WAAW;EACX,YAAY;EACZ,eAAe;EACf,YAAY;AACd;;AAEA;EACE,kBAAkB;EAClB,YAAY;EACZ,SAAS;EACT,2BAA2B;EAC3B,cAAc;EACd,0CAA0C;EAC1C,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,QAAQ;AACV;;AAEA;EACE,yBAAyB;EACzB,kBAAkB;EAClB,kBAAkB;AACpB;;AAEA;EACE,WAAW;EACX,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,kBAAkB;EAClB,MAAM;EACN,OAAO;EACP,WAAW;EACX,YAAY;EACZ,oBAAoB;AACtB","file":"index.css","sourcesContent":[".pdf-view-container {\n margin: 0 auto;\n position: relative;\n max-width: 1200px;\n width: 100%;\n}\n.pdf-view-container :global(.react-pdf__Page__canvas),\n.pdf-view-container :global(.textLayer) {\n margin: 0 auto;\n}\n\n.pdf-view {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);\n}\n\n.pdf-view-children {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 10;\n}\n\n.pdf-view-page-control-left,\n.pdf-view-page-control-right {\n position: absolute;\n font-size: 30px;\n top: calc(50% - 19px);\n z-index: 10;\n padding: 8px;\n cursor: pointer;\n opacity: 0.3;\n}\n\n.pdf-view-page-control-current {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n color: #666666;\n background-color: rgba(255, 255, 255, 0.5);\n text-shadow: 0 0 8px white, 0 0 8px white;\n border-radius: 4px;\n}\n\n.pdf-view-page-control-right {\n right: 0;\n}\n\n.signature-container {\n border: 1px solid #cccccc;\n border-radius: 4px;\n position: relative;\n}\n\n.signature-canvas {\n width: 100%;\n height: 100%;\n}\n\n.signature-modal :global .ant-modal-confirm-paragraph {\n max-width: unset;\n}\n\n.signature-mask {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}"]}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var useImage = require('use-image');
|
|
|
15
15
|
var reactIntl = require('@kne/react-intl');
|
|
16
16
|
var pdfLib = require('pdf-lib');
|
|
17
17
|
var SignatureCanvas = require('react-signature-canvas');
|
|
18
|
+
var snapdom = require('@zumer/snapdom');
|
|
18
19
|
|
|
19
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
21
|
|
|
@@ -44,7 +45,7 @@ function _objectWithoutPropertiesLoose(r, e) {
|
|
|
44
45
|
return t;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
var style = {"pdf-view-container":"_RgZXN","pdf-view":"_PAju1","pdf-view-children":"_N11Pj","pdf-view-page-control-left":"_IbVpf","pdf-view-page-control-right":"_IIgqj","pdf-view-page-control-current":"_JW3CT","signature-container":"_6TDb-","signature-canvas":"_2CGF4","signature-modal":"_kWe3k"};
|
|
48
|
+
var style = {"pdf-view-container":"_RgZXN","pdf-view":"_PAju1","pdf-view-children":"_N11Pj","pdf-view-page-control-left":"_IbVpf","pdf-view-page-control-right":"_IIgqj","pdf-view-page-control-current":"_JW3CT","signature-container":"_6TDb-","signature-canvas":"_2CGF4","signature-modal":"_kWe3k","signature-mask":"_FSvLv"};
|
|
48
49
|
|
|
49
50
|
const _excluded$3 = ["numPages"];
|
|
50
51
|
const PDFViewer = _ref => {
|
|
@@ -183,7 +184,7 @@ const LocationLayer = withLocale(p => {
|
|
|
183
184
|
} = reactIntl.useIntl();
|
|
184
185
|
const {
|
|
185
186
|
width = 200,
|
|
186
|
-
height =
|
|
187
|
+
height = 80,
|
|
187
188
|
padding = 8,
|
|
188
189
|
stageWidth,
|
|
189
190
|
stageHeight,
|
|
@@ -198,6 +199,7 @@ const LocationLayer = withLocale(p => {
|
|
|
198
199
|
const [signatureImage] = useImage__default["default"](signature);
|
|
199
200
|
const groupRef = react.useRef();
|
|
200
201
|
const signRef = react.useRef();
|
|
202
|
+
const targetRef = react.useRef();
|
|
201
203
|
const transformerRef = react.useRef();
|
|
202
204
|
const computedSignLocation = () => {
|
|
203
205
|
const absolutePosition = signRef.current.absolutePosition();
|
|
@@ -229,8 +231,8 @@ const LocationLayer = withLocale(p => {
|
|
|
229
231
|
y: Math.round((stageHeight - height) / 2)
|
|
230
232
|
}
|
|
231
233
|
});
|
|
232
|
-
setIsInit(true);
|
|
233
234
|
}
|
|
235
|
+
setIsInit(true);
|
|
234
236
|
});
|
|
235
237
|
const themeColor = react.useMemo(() => {
|
|
236
238
|
const el = document.createElement('div');
|
|
@@ -245,7 +247,7 @@ const LocationLayer = withLocale(p => {
|
|
|
245
247
|
}, []);
|
|
246
248
|
react.useEffect(() => {
|
|
247
249
|
if (isInit) {
|
|
248
|
-
transformerRef.current.nodes([
|
|
250
|
+
transformerRef.current.nodes([targetRef.current]);
|
|
249
251
|
}
|
|
250
252
|
}, [isInit]);
|
|
251
253
|
if (!(isInit && value)) {
|
|
@@ -261,19 +263,22 @@ const LocationLayer = withLocale(p => {
|
|
|
261
263
|
draggable: true,
|
|
262
264
|
ref: groupRef,
|
|
263
265
|
onDragEnd: computedSignLocation,
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
266
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(reactKonva.Group, {
|
|
267
|
+
ref: targetRef,
|
|
268
|
+
onTransformEnd: computedSignLocation,
|
|
269
|
+
children: signatureImage ? /*#__PURE__*/jsxRuntime.jsx(reactKonva.Image, {
|
|
270
|
+
width: width,
|
|
271
|
+
height: height,
|
|
272
|
+
image: signatureImage,
|
|
273
|
+
cornerRadius: 8,
|
|
274
|
+
ref: signRef
|
|
275
|
+
}) : /*#__PURE__*/jsxRuntime.jsx(reactKonva.Rect, {
|
|
276
|
+
width: width,
|
|
277
|
+
height: height,
|
|
278
|
+
fill: "#f0f0f0",
|
|
279
|
+
cornerRadius: 8,
|
|
280
|
+
ref: signRef
|
|
281
|
+
})
|
|
277
282
|
}), /*#__PURE__*/jsxRuntime.jsx(reactKonva.Text, {
|
|
278
283
|
text: signatureImage ? '' : placeholder,
|
|
279
284
|
fontSize: 16,
|
|
@@ -295,8 +300,7 @@ const LocationLayer = withLocale(p => {
|
|
|
295
300
|
borderStroke: themeColor,
|
|
296
301
|
rotateAnchorStroke: themeColor,
|
|
297
302
|
anchorStroke: themeColor,
|
|
298
|
-
padding: padding
|
|
299
|
-
enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
|
|
303
|
+
padding: padding
|
|
300
304
|
})]
|
|
301
305
|
})
|
|
302
306
|
});
|
|
@@ -2507,7 +2511,46 @@ function isEqual(value, other) {
|
|
|
2507
2511
|
|
|
2508
2512
|
var isEqual_1 = isEqual;
|
|
2509
2513
|
|
|
2510
|
-
const
|
|
2514
|
+
const signPdfFile = function (pdfSignature) {
|
|
2515
|
+
try {
|
|
2516
|
+
const {
|
|
2517
|
+
x,
|
|
2518
|
+
y,
|
|
2519
|
+
page,
|
|
2520
|
+
width,
|
|
2521
|
+
height,
|
|
2522
|
+
signature,
|
|
2523
|
+
url,
|
|
2524
|
+
filename
|
|
2525
|
+
} = pdfSignature;
|
|
2526
|
+
return Promise.resolve(window.fetch(url)).then(function (response) {
|
|
2527
|
+
return Promise.resolve(response.arrayBuffer()).then(function (pdfBytes) {
|
|
2528
|
+
return Promise.resolve(pdfLib.PDFDocument.load(pdfBytes)).then(function (pdfDoc) {
|
|
2529
|
+
const pdfPage = pdfDoc.getPage(page - 1);
|
|
2530
|
+
return Promise.resolve(window.fetch(signature).then(res => res.arrayBuffer())).then(function (signatureBytes) {
|
|
2531
|
+
return Promise.resolve(pdfDoc.embedPng(signatureBytes)).then(function (signatureImageEmbed) {
|
|
2532
|
+
pdfPage.drawImage(signatureImageEmbed, {
|
|
2533
|
+
x,
|
|
2534
|
+
y,
|
|
2535
|
+
width,
|
|
2536
|
+
height
|
|
2537
|
+
});
|
|
2538
|
+
return Promise.resolve(pdfDoc.save()).then(function (modifiedPdfBytes) {
|
|
2539
|
+
return new window.File([modifiedPdfBytes], filename, {
|
|
2540
|
+
type: 'application/pdf'
|
|
2541
|
+
});
|
|
2542
|
+
});
|
|
2543
|
+
});
|
|
2544
|
+
});
|
|
2545
|
+
});
|
|
2546
|
+
});
|
|
2547
|
+
});
|
|
2548
|
+
} catch (e) {
|
|
2549
|
+
return Promise.reject(e);
|
|
2550
|
+
}
|
|
2551
|
+
};
|
|
2552
|
+
|
|
2553
|
+
const _excluded$1 = ["placeholder", "signature", "url", "width", "height", "padding", "filename", "defaultLocation", "onChange"];
|
|
2511
2554
|
const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
2512
2555
|
let {
|
|
2513
2556
|
placeholder,
|
|
@@ -2516,10 +2559,12 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
|
2516
2559
|
width,
|
|
2517
2560
|
height,
|
|
2518
2561
|
padding,
|
|
2519
|
-
filename = 'signed-document.pdf'
|
|
2562
|
+
filename = 'signed-document.pdf',
|
|
2563
|
+
defaultLocation,
|
|
2564
|
+
onChange
|
|
2520
2565
|
} = _ref,
|
|
2521
2566
|
props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
|
|
2522
|
-
const [location, setLocation] = react.useState({});
|
|
2567
|
+
const [location, setLocation] = react.useState(Object.assign({}, defaultLocation));
|
|
2523
2568
|
const [pdfProps, setPdfProps] = react.useState(null);
|
|
2524
2569
|
const {
|
|
2525
2570
|
formatMessage
|
|
@@ -2536,18 +2581,21 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
|
2536
2581
|
const scaleY = size.height / size.originalHeight;
|
|
2537
2582
|
const pdfX = Math.round(location.size.x / scaleX);
|
|
2538
2583
|
const pdfY = Math.round(size.originalHeight - location.size.y / scaleY);
|
|
2584
|
+
const signWidth = Math.round(location.size.width / scaleX);
|
|
2585
|
+
const signHeight = Math.round(location.size.height / scaleY);
|
|
2539
2586
|
return {
|
|
2540
2587
|
x: pdfX,
|
|
2541
|
-
y: pdfY -
|
|
2588
|
+
y: pdfY - signHeight,
|
|
2542
2589
|
page: currentPage,
|
|
2543
|
-
pageWidth: size.originalWidth,
|
|
2544
|
-
pageHeight: size.originalHeight,
|
|
2545
|
-
width:
|
|
2546
|
-
height:
|
|
2590
|
+
pageWidth: Math.round(size.originalWidth),
|
|
2591
|
+
pageHeight: Math.round(size.originalHeight),
|
|
2592
|
+
width: signWidth,
|
|
2593
|
+
height: signHeight,
|
|
2547
2594
|
signature,
|
|
2548
|
-
url
|
|
2595
|
+
url,
|
|
2596
|
+
filename
|
|
2549
2597
|
};
|
|
2550
|
-
}, [pdfProps, location, signature, url]);
|
|
2598
|
+
}, [pdfProps, location, signature, url, filename]);
|
|
2551
2599
|
const signPdf = react.useCallback(function () {
|
|
2552
2600
|
try {
|
|
2553
2601
|
if (!pdfProps) {
|
|
@@ -2555,37 +2603,7 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
|
2555
2603
|
id: 'loadingError'
|
|
2556
2604
|
}));
|
|
2557
2605
|
}
|
|
2558
|
-
|
|
2559
|
-
x,
|
|
2560
|
-
y,
|
|
2561
|
-
page,
|
|
2562
|
-
width,
|
|
2563
|
-
height,
|
|
2564
|
-
signature,
|
|
2565
|
-
url
|
|
2566
|
-
} = pdfSignature;
|
|
2567
|
-
return Promise.resolve(window.fetch(url)).then(function (response) {
|
|
2568
|
-
return Promise.resolve(response.arrayBuffer()).then(function (pdfBytes) {
|
|
2569
|
-
return Promise.resolve(pdfLib.PDFDocument.load(pdfBytes)).then(function (pdfDoc) {
|
|
2570
|
-
const pdfPage = pdfDoc.getPage(page - 1);
|
|
2571
|
-
return Promise.resolve(window.fetch(signature).then(res => res.arrayBuffer())).then(function (signatureBytes) {
|
|
2572
|
-
return Promise.resolve(pdfDoc.embedPng(signatureBytes)).then(function (signatureImageEmbed) {
|
|
2573
|
-
pdfPage.drawImage(signatureImageEmbed, {
|
|
2574
|
-
x,
|
|
2575
|
-
y,
|
|
2576
|
-
width,
|
|
2577
|
-
height
|
|
2578
|
-
});
|
|
2579
|
-
return Promise.resolve(pdfDoc.save()).then(function (modifiedPdfBytes) {
|
|
2580
|
-
return new window.File([modifiedPdfBytes], filename, {
|
|
2581
|
-
type: 'application/pdf'
|
|
2582
|
-
});
|
|
2583
|
-
});
|
|
2584
|
-
});
|
|
2585
|
-
});
|
|
2586
|
-
});
|
|
2587
|
-
});
|
|
2588
|
-
});
|
|
2606
|
+
return Promise.resolve(signPdfFile(pdfSignature));
|
|
2589
2607
|
} catch (e) {
|
|
2590
2608
|
return Promise.reject(e);
|
|
2591
2609
|
}
|
|
@@ -2596,6 +2614,13 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
|
2596
2614
|
getPdfSignature: () => pdfSignature,
|
|
2597
2615
|
sign: () => signPdf()
|
|
2598
2616
|
}));
|
|
2617
|
+
const handlerChange = useRefCallback__default["default"](onChange);
|
|
2618
|
+
react.useEffect(() => {
|
|
2619
|
+
handlerChange == null || handlerChange({
|
|
2620
|
+
pdfSignature,
|
|
2621
|
+
location
|
|
2622
|
+
});
|
|
2623
|
+
}, [pdfSignature, location, handlerChange]);
|
|
2599
2624
|
return /*#__PURE__*/jsxRuntime.jsx(PDFViewer, _extends({}, props, {
|
|
2600
2625
|
url: url,
|
|
2601
2626
|
children: _ref2 => {
|
|
@@ -2629,7 +2654,7 @@ const PDFSign = withLocale(/*#__PURE__*/react.forwardRef((_ref, ref) => {
|
|
|
2629
2654
|
}));
|
|
2630
2655
|
}));
|
|
2631
2656
|
|
|
2632
|
-
const _excluded = ["filename", "onSuccess"];
|
|
2657
|
+
const _excluded = ["filename", "onSuccess", "width", "height", "mask"];
|
|
2633
2658
|
const dataURLtoBlob = dataURL => {
|
|
2634
2659
|
let arr = dataURL.split(',');
|
|
2635
2660
|
// 注意base64的最后面中括号和引号是不转译的
|
|
@@ -2651,7 +2676,8 @@ const Signature = withLocale(_ref => {
|
|
|
2651
2676
|
onSuccess,
|
|
2652
2677
|
filename,
|
|
2653
2678
|
width,
|
|
2654
|
-
height
|
|
2679
|
+
height,
|
|
2680
|
+
mask = null
|
|
2655
2681
|
} = _ref;
|
|
2656
2682
|
const {
|
|
2657
2683
|
formatMessage
|
|
@@ -2660,22 +2686,27 @@ const Signature = withLocale(_ref => {
|
|
|
2660
2686
|
message
|
|
2661
2687
|
} = antd.App.useApp();
|
|
2662
2688
|
const signatureCanvasRef = react.useRef(null);
|
|
2689
|
+
const maskRef = react.useRef(null);
|
|
2663
2690
|
return /*#__PURE__*/jsxRuntime.jsxs(antd.Flex, {
|
|
2664
2691
|
vertical: true,
|
|
2665
2692
|
gap: 12,
|
|
2666
2693
|
className: classnames__default["default"](style['signature-modal-content'], 'signature-modal-content'),
|
|
2667
|
-
children: [/*#__PURE__*/jsxRuntime.
|
|
2694
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
2668
2695
|
className: classnames__default["default"](style['signature-container'], 'signature-container'),
|
|
2669
2696
|
style: {
|
|
2670
2697
|
width: '368px',
|
|
2671
2698
|
height: Math.round(height * 368 / width) + "px"
|
|
2672
2699
|
},
|
|
2673
|
-
children: /*#__PURE__*/jsxRuntime.jsx(
|
|
2700
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
2701
|
+
className: classnames__default["default"](style['signature-mask'], 'signature-mask'),
|
|
2702
|
+
ref: maskRef,
|
|
2703
|
+
children: mask
|
|
2704
|
+
}), /*#__PURE__*/jsxRuntime.jsx(SignatureCanvas__default["default"], {
|
|
2674
2705
|
ref: signatureCanvasRef,
|
|
2675
2706
|
canvasProps: {
|
|
2676
2707
|
className: classnames__default["default"](style['signature-canvas'], 'signature-canvas')
|
|
2677
2708
|
}
|
|
2678
|
-
})
|
|
2709
|
+
})]
|
|
2679
2710
|
}), /*#__PURE__*/jsxRuntime.jsxs(antd.Flex, {
|
|
2680
2711
|
justify: "flex-end",
|
|
2681
2712
|
align: "center",
|
|
@@ -2689,18 +2720,47 @@ const Signature = withLocale(_ref => {
|
|
|
2689
2720
|
})
|
|
2690
2721
|
}), /*#__PURE__*/jsxRuntime.jsx(antd.Button, {
|
|
2691
2722
|
type: "primary",
|
|
2692
|
-
onClick: ()
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2723
|
+
onClick: function () {
|
|
2724
|
+
try {
|
|
2725
|
+
function _temp2() {
|
|
2726
|
+
const file = new window.File([dataURLtoBlob(result)], filename, {
|
|
2727
|
+
type: 'image/png'
|
|
2728
|
+
});
|
|
2729
|
+
onClose();
|
|
2730
|
+
onSuccess(file);
|
|
2731
|
+
}
|
|
2732
|
+
if (signatureCanvasRef.current.isEmpty()) {
|
|
2733
|
+
message.error(formatMessage({
|
|
2734
|
+
id: 'signatureEmptyError'
|
|
2735
|
+
}));
|
|
2736
|
+
return Promise.resolve();
|
|
2737
|
+
}
|
|
2738
|
+
let result = signatureCanvasRef.current.toDataURL('image/png');
|
|
2739
|
+
const _temp = function () {
|
|
2740
|
+
if (mask) {
|
|
2741
|
+
return Promise.resolve(snapdom.snapdom.toPng(maskRef.current, {
|
|
2742
|
+
scale: 2
|
|
2743
|
+
})).then(function (maskPng) {
|
|
2744
|
+
const canvas = document.createElement('canvas');
|
|
2745
|
+
canvas.width = width * 2;
|
|
2746
|
+
canvas.height = height * 2;
|
|
2747
|
+
const ctx = canvas.getContext('2d');
|
|
2748
|
+
ctx.drawImage(maskPng, 0, 0, canvas.width, canvas.height);
|
|
2749
|
+
const resultImage = new Image();
|
|
2750
|
+
resultImage.src = result;
|
|
2751
|
+
return Promise.resolve(new Promise(resolve => {
|
|
2752
|
+
resultImage.onload = resolve;
|
|
2753
|
+
})).then(function () {
|
|
2754
|
+
ctx.drawImage(resultImage, 0, 0, canvas.width, canvas.height);
|
|
2755
|
+
result = canvas.toDataURL('image/png');
|
|
2756
|
+
});
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2759
|
+
}();
|
|
2760
|
+
return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
|
|
2761
|
+
} catch (e) {
|
|
2762
|
+
return Promise.reject(e);
|
|
2698
2763
|
}
|
|
2699
|
-
const file = new window.File([dataURLtoBlob(signatureCanvasRef.current.toDataURL('image/png'))], filename, {
|
|
2700
|
-
type: 'image/png'
|
|
2701
|
-
});
|
|
2702
|
-
onClose();
|
|
2703
|
-
onSuccess(file);
|
|
2704
2764
|
},
|
|
2705
2765
|
children: formatMessage({
|
|
2706
2766
|
id: 'signatureConfirmText'
|
|
@@ -2719,24 +2779,18 @@ const Title = withLocale(() => {
|
|
|
2719
2779
|
})
|
|
2720
2780
|
});
|
|
2721
2781
|
});
|
|
2722
|
-
const useSignature =
|
|
2782
|
+
const useSignature = () => {
|
|
2723
2783
|
const {
|
|
2724
|
-
|
|
2725
|
-
height
|
|
2726
|
-
} = Object.assign({}, {
|
|
2727
|
-
width: 200,
|
|
2728
|
-
height: 50
|
|
2729
|
-
}, props);
|
|
2730
|
-
const {
|
|
2731
|
-
modal,
|
|
2732
|
-
message
|
|
2784
|
+
modal
|
|
2733
2785
|
} = antd.App.useApp();
|
|
2734
|
-
react.useRef(null);
|
|
2735
2786
|
return props => {
|
|
2736
2787
|
const _Object$assign = Object.assign({}, props),
|
|
2737
2788
|
{
|
|
2738
2789
|
filename = 'signature.png',
|
|
2739
|
-
onSuccess
|
|
2790
|
+
onSuccess,
|
|
2791
|
+
width = 200,
|
|
2792
|
+
height = 80,
|
|
2793
|
+
mask
|
|
2740
2794
|
} = _Object$assign,
|
|
2741
2795
|
modalProps = _objectWithoutPropertiesLoose(_Object$assign, _excluded);
|
|
2742
2796
|
const modalApi = modal.info(Object.assign({}, {
|
|
@@ -2751,6 +2805,7 @@ const useSignature = props => {
|
|
|
2751
2805
|
content: /*#__PURE__*/jsxRuntime.jsx(Signature, {
|
|
2752
2806
|
width: width,
|
|
2753
2807
|
height: height,
|
|
2808
|
+
mask: mask,
|
|
2754
2809
|
filename: filename,
|
|
2755
2810
|
onSuccess: onSuccess,
|
|
2756
2811
|
onClose: () => {
|