@toolspack/ttd-common 1.1.4 → 1.1.6

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.
@@ -1,649 +1,649 @@
1
- <template>
2
- <div class="cfca-pdf">
3
- <!-- isIE -->
4
- <template v-if="isIE">
5
- <div class="cfca-pdf-wrapper" :style="{visibility: visible}">
6
- <div
7
- :class="{'cfca-left': true, 'active': active==='left', 'disabled': pageNo <= 1}"
8
- @click="GoToPrevPage()"
9
- >
10
- <span class="el-icon-arrow-left"></span>
11
- </div>
12
- <div class="cfca-content">
13
- <div class="cfca-page">
14
- <div class="fl cfca-title">
15
- <h2>{{title}}</h2>
16
- </div>
17
- <div class="fr">
18
- {{pageNo}}/{{pageCount}}
19
- <span class="di">第</span>
20
- <el-input
21
- class="page-num"
22
- size="mini"
23
- v-model="inputPage"
24
- @keyup.enter.native="GoToPage"
25
- @change="GoToPage"
26
- ></el-input>页
27
- </div>
28
- </div>
29
- <div class="cfca-object" ref="PDFCtrlPlaceHolder">
30
- <div class="obj-wrapper" @dragenter="onDragEnter" @dragover="onDragOver" @drop="onDrop">
31
- <template v-if="this.idstr">
32
- <!-- 拖动签章,Object 的事件(NotifyClickPoint)只能用id 来绑定 -->
33
- <object
34
- :id="'PDFCtrl' + this.idstr"
35
- ref="pdfCtrl"
36
- class="PDFCtrlObject"
37
- :tabindex="0"
38
- :codebase="publicPath + codebase"
39
- style="position: relative; z-Index:1"
40
- classid="clsid:6F60FE31-F827-4295-8AC4-775EF7478A6A"
41
- width="100%"
42
- height="100%"
43
- >
44
- <param name="wmode" value="transparent" />
45
- <param name="showToolbar" value="false" />
46
- </object>
47
- </template>
48
- <template v-else>
49
- <object
50
- ref="pdfCtrl"
51
- class="PDFCtrlObject"
52
- :tabindex="0"
53
- :codebase="publicPath + codebase"
54
- style="position: relative; z-Index:1"
55
- classid="clsid:6F60FE31-F827-4295-8AC4-775EF7478A6A"
56
- width="100%"
57
- height="100%"
58
- >
59
- <param name="wmode" value="transparent" />
60
- <param name="showToolbar" value="false" />
61
- </object>
62
- </template>
63
- </div>
64
- </div>
65
- <div class="cfca-control">
66
- <slot></slot>
67
- </div>
68
- </div>
69
- <div
70
- :class="{'cfca-right': true, 'active': active==='right', 'disabled': pageNo >= pageCount}"
71
- @click="GoToNextPage()"
72
- >
73
- <span class="el-icon-arrow-right"></span>
74
- </div>
75
- <!-- HTML toolbar -->
76
- <!--<tr class="fontSize3" align="center" height="23" bgcolor="#E8E8E8">-->
77
- <!--<td width="40" class="fakehlink" @click="GoToFirstPage()">首页</td>-->
78
- <!--<td width="60" class="fakehlink" @click="GoToPrevPage()">上一页</td>-->
79
- <!--<td width="60" class="fakehlink" @click="GoToNextPage()">下一页</td>-->
80
- <!--<td width="40" class="fakehlink" @click="GoToLastPage()">尾页</td>-->
81
- <!--<td width="80" class="fakehlink" @click="GetPageNo()">页码信息</td>-->
82
- <!--<td width="60" class="fakehlink" @click="GoToPage" align="right">跳转到页</td>-->
83
- <!--<td width="60">-->
84
- <!--: <input type="text" id="PageNo" style="width: 45px" onkeydown='if(event.keyCode===13){this.GoToPage()}' onkeyup="value=this.value.replace(/\D+/g,'')"/>-->
85
- <!--</td>-->
86
- <!--<td width="30"></td>-->
87
- <!--<td width="70" class="fakehlink" @click="ZoomTo(-2)">适合宽度</td>-->
88
- <!--<td width="70" class="fakehlink" @click="ZoomTo(-1)">单页模式</td>-->
89
- <!--<td width="30"></td>-->
90
- <!--<td width="45" class="fakehlink" @click="ZoomOut()">缩小</td>-->
91
- <!--<td width="45" class="fakehlink" @click="ZoomIn()">放大</td>-->
92
- <!--</tr>-->
93
- </div>
94
- </template>
95
- <template v-else>
96
- <div
97
- class="red"
98
- style="height: 350px; padding: 20px ;position: relative; margin-bottom: 20px"
99
- >
100
- 提示:当前浏览器不支持控件预览,请切换IE浏览器进行查看
101
- <!--提示:出于安全性与监管要求考虑且CFCA控件只能够支持IE浏览器,请切换IE浏览器进行查看-->
102
- <div class="tc" style="position: absolute;bottom: 0;left: 0;right: 0;">
103
- <slot></slot>
104
- </div>
105
- </div>
106
- </template>
107
- </div>
108
- </template>
109
- <script>
110
- // import config from {};
111
- import { getUrl } from '../utils'
112
-
113
- export default {
114
- name: 'cfca-pdf',
115
- props: {
116
- action: {
117
- type: String, // 签章完毕,上传文件地址,仅展示pdf 无需传
118
- default: '',
119
- },
120
- pdfurl: {
121
- type: String,
122
- default: '',
123
- },
124
- visible: {
125
- type: [String, Boolean],
126
- default: 'visible',
127
- },
128
- title: {
129
- type: String,
130
- default: '',
131
- },
132
- image: {
133
- type: String,
134
- default: '',
135
- },
136
- idstr: {
137
- type: [String, Number],
138
- },
139
- },
140
- data() {
141
- let codebase = '';
142
- if (window.navigator.cpuClass === 'x86') {
143
- codebase = 'TrustSignPDFPlugin.ttd.x86.cab#version=3,2,1,4';
144
- } else {
145
- codebase = 'TrustSignPDFPlugin.ttd.x64.cab#version=3,2,1,4';
146
- }
147
- return {
148
- publicPath: 'https://wsp.totodi.com/cfca_plug/', // 为了获取public下的静态文件
149
- PDFCtrl: '',
150
- codebase,
151
- active: '',
152
- inputPage: '',
153
- isIE:
154
- navigator.appName.indexOf('Internet') >= 0
155
- || navigator.appVersion.indexOf('Trident') >= 0,
156
- pageNo: 1,
157
- pageCount: 1,
158
- };
159
- },
160
- beforeDestroy() {
161
- // CloseFile 未执行完毕,销毁页面 导致页面崩溃,
162
- // CloseFile 必须执行完毕才能销毁 实例 所以 CloseFile在 dialog的close 方法里执行,页面的在router个beforeRouteLeave里执行
163
- console.log('--cfca-pdf-beforeDestroy')
164
- },
165
- async beforeRouteLeave(to, from, next) {
166
- // 子组件不会触发这个方法
167
- console.log('-cfca--beforeRouteLeave---')
168
- await this.CloseFile()
169
- next()
170
- },
171
- mounted() {
172
- if (this.isIE) {
173
- this.OnLoad();
174
- console.log(`cfca mounted =${ this.pdfurl}`)
175
- if (this.pdfurl) {
176
- // console.log('cfca mounted this.pdfurl==' + this.pdfurl)
177
- // 这里的 setTimeout 必须存在,否则 补充协议签署时,会看不到pdf
178
- // PDFCtrl 没有初始化完毕 ($nextTick 不行 必须用setTimeout)
179
-
180
- // this.$nextTick(this.OpenFile)
181
- setTimeout(this.OpenFile, 100);
182
- }
183
- }
184
- },
185
- methods: {
186
- OnLoad() {
187
- if (this.PDFCtrl) {
188
- return false;
189
- }
190
- if (this.isIE) {
191
- // 使用refs 拿到的元素 不能ukey签章
192
- this.PDFCtrl = this.$refs.pdfCtrl;
193
- if (!this.PDFCtrl) {
194
- console.log('使用id 加载this.PDFCtrl ');
195
- this.PDFCtrl = window[`PDFCtrl${ this.idstr}`]
196
- }
197
- // console.log('加载this.PDFCtrl ', this.PDFCtrl)
198
- // 将OnClickPoint事件放入 全局函数
199
- window.OnClickPoint = this.OnClickPoint;
200
- } else {
201
- // alert('请使用 IE 浏览器!')
202
- return false;
203
- }
204
- },
205
- OpenFile(src) {
206
- src = src || this.pdfurl;
207
- if (!src) {
208
- alert('未发现pdf资源路径!');
209
- return false;
210
- }
211
- try {
212
- console.log(`OpenFile--src--${ src}`);
213
- this.PDFCtrl.OpenWebFile(encodeURI(src));
214
- this.PDFCtrl = this.$refs.pdfCtrl;
215
- setTimeout(() => {
216
- this.PDFCtrl.ZoomTo(-1);
217
- this.GetPageNo();
218
- }, 100);
219
- } catch (e) {
220
- if (this.PDFCtrl.GetLastErrorDesc) {
221
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
222
- alert(LastErrorDesc + e);
223
- }
224
- }
225
- },
226
- sleep(ms) {
227
- return new Promise((resolve) => setTimeout(resolve, ms))
228
- },
229
- CloseFile() {
230
- try {
231
- if (this.pdfurl && this.PDFCtrl) {
232
- console.log('CloseFile---')
233
- this.PDFCtrl.CloseFile();
234
- // await this.sleep(1000)
235
- }
236
- } catch (e) {
237
- console.log('CloseFile error--', e);
238
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
239
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
240
- alert(LastErrorDesc + e);
241
- }
242
- }
243
- },
244
-
245
- onDragEnter(event) {
246
- this.$emit('cfcaDragEnter', event);
247
- },
248
- onDragOver(event) {
249
- event.preventDefault();
250
- this.$emit('cfcaDragOver', event);
251
- },
252
- onDrop(event) {
253
- this.$emit('cfcaDrop', event);
254
- },
255
- // Page operations
256
-
257
- GoToFirstPage() {
258
- try {
259
- this.PDFCtrl.GoToFirstPage();
260
- } catch (e) {
261
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
262
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
263
- alert(LastErrorDesc + e);
264
- }
265
- }
266
- },
267
-
268
- GoToLastPage() {
269
- try {
270
- this.PDFCtrl.GoToLastPage();
271
- } catch (e) {
272
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
273
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
274
- alert(LastErrorDesc + e);
275
- }
276
- }
277
- },
278
- GoToPrevPage() {
279
- this.active = 'left';
280
- const me = this;
281
- try {
282
- this.PDFCtrl.GoToPrevPage();
283
- this.inputPage = ''
284
- setTimeout(() => {
285
- me.GetPageNo();
286
- }, 100);
287
- } catch (e) {
288
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
289
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
290
- alert(LastErrorDesc + e);
291
- }
292
- }
293
- },
294
-
295
- GoToNextPage() {
296
- this.active = 'right';
297
- const me = this;
298
- try {
299
- this.PDFCtrl.GoToNextPage();
300
- this.inputPage = ''
301
- setTimeout(() => {
302
- me.GetPageNo();
303
- }, 100);
304
- } catch (e) {
305
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
306
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
307
- alert(LastErrorDesc + e);
308
- }
309
- }
310
- },
311
-
312
- GetPageNo() {
313
- try {
314
- this.pageNo = this.PDFCtrl.GetCurrentPageNo();
315
- this.pageCount = this.PDFCtrl.GetPageCount();
316
- } catch (e) {
317
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
318
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
319
- alert(LastErrorDesc + e);
320
- }
321
- }
322
- },
323
-
324
- GoToPage() {
325
- const me = this;
326
- try {
327
- const pageNo = this.inputPage.replace(/\D/, '');
328
- if (pageNo === '') {
329
- alert('请输入页码!');
330
- return;
331
- }
332
- this.PDFCtrl.GoToPage(pageNo);
333
- setTimeout(() => {
334
- me.GetPageNo();
335
- }, 100);
336
- } catch (e) {
337
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
338
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
339
- alert(LastErrorDesc + e);
340
- }
341
- }
342
- },
343
-
344
- // Zoom operations
345
- ZoomTo(factor) {
346
- try {
347
- this.PDFCtrl.ZoomTo(factor);
348
- } catch (e) {
349
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
350
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
351
- alert(LastErrorDesc + e);
352
- }
353
- }
354
- },
355
-
356
- ZoomOut() {
357
- try {
358
- this.PDFCtrl.ZoomOut();
359
- } catch (e) {
360
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
361
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
362
- alert(LastErrorDesc + e);
363
- }
364
- }
365
- },
366
- ZoomIn() {
367
- try {
368
- this.PDFCtrl.ZoomIn();
369
- } catch (e) {
370
- if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
371
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
372
- alert(LastErrorDesc + e);
373
- }
374
- }
375
- },
376
- // 把章合到pdf 中去, 拖动签使用的
377
- OnClickPoint(nPageNo, x, y) {
378
- console.log('OnClickPoint--', `nPageNo=${nPageNo}, x=${x}, y=${y}`);
379
- try {
380
- console.log('image2=', this.image)
381
- if (this.image) {
382
- this.PDFCtrl.SignFile_Image(nPageNo, x, y, this.image)
383
- } else {
384
- this.PDFCtrl.SignFile_KeyImage(nPageNo, x, y);
385
- }
386
- this.$emit('cfca-point', nPageNo, x, y)
387
- } catch (e) {
388
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
389
- alert(LastErrorDesc + e);
390
- }
391
- },
392
-
393
- // 外部打开dialog 调用
394
- openDialog(url) {
395
- if (this.isIE) {
396
- console.log(' openDialog---');
397
- // 外部dialog 这里需要使用延时,否则pdf 还未初始化完毕
398
- setTimeout(() => {
399
- this.OpenFile(url);
400
- }, 350);
401
- }
402
- },
403
- getUkeyImage() {
404
- const version = this.PDFCtrl.GetVersion()
405
- console.log(version)
406
- this.PDFCtrl.SetPKCS11Module('UyeePKCS11.Enterprise.dll|UlanPKCS11.Enterprise.dll|UlanPKCS11.dll|CFCA_UKEY_P11.dll')
407
- if (version === '3.2.1.7') {
408
- // 获取版本号报错 (必须升级到3.2.1.7)
409
- return this.PDFCtrl.ReadKeyImage();
410
- }
411
- alert(`客户端签章控件[v=${version}],需要升级!`)
412
- },
413
- GetCertInfo(InfoTypeID) {
414
- // '证书持有者CN:\t' + PDFCtrl.GetSignCertInfo('SubjectCN') +
415
- // '\n证书持有者DN:\t' + PDFCtrl.GetSignCertInfo('SubjectDN') +
416
- // '\n证书颁发者DN:\t' + PDFCtrl.GetSignCertInfo('IssuerDN') +
417
- // '\n证书序列号:\t' + PDFCtrl.GetSignCertInfo('SerialNumber') +
418
- // '\n起始有效期:\t' + PDFCtrl.GetSignCertInfo('ValidFrom') +
419
- // '\n截止有效期:\t' + PDFCtrl.GetSignCertInfo('ValidTo') +
420
- // '\n起始有效期UTC:\t' + PDFCtrl.GetSignCertInfo('UTCValidFrom') +
421
- // '\n截止有效期UTC:\t' + PDFCtrl.GetSignCertInfo('UTCValidTo') +
422
- // '\n证书算法:\t\t' + PDFCtrl.GetSignCertInfo('CertAlgorithm') +
423
- // '\n证书内容:\n' + PDFCtrl.GetSignCertInfo('CertContent');
424
- InfoTypeID = InfoTypeID || 'SubjectDN'
425
- try {
426
- const InfoContent = this.PDFCtrl.GetSignCertInfo(InfoTypeID)
427
- // Opera浏览器,NPAPI函数执行结果为false时,不能触发异常,需要自己判断返回值。
428
- if (!InfoContent) {
429
- const errorDesc = this.PDFCtrl.GetLastErrorDesc()
430
- alert(errorDesc)
431
- return
432
- }
433
- return InfoContent
434
- } catch (e) {
435
- console.log('GetCertInfo :', e)
436
- const errorDesc = this.PDFCtrl.GetLastErrorDesc()
437
- alert(errorDesc + e)
438
- }
439
- },
440
- /* */
441
- selectSignCert(serialNo) {
442
- // 使用PDFCtrl.GetSignCertInfo 会报错, 必须在选完证书才能调用
443
- // let subjectDN1 = this.PDFCtrl.GetSignCertInfo('SubjectCN')
444
- // let issuerDN1 = this.PDFCtrl.GetSignCertInfo('IssuerDN')
445
- // const certSN1 = this.PDFCtrl.GetSignCertInfo('SerialNumber')
446
- // console.log('PDFCtrl, subjectDN1', subjectDN1)
447
- // console.log('PDFCtrl, issuerDN1', issuerDN1)
448
- // console.log('PDFCtrl, certSN1', certSN1)
449
- try {
450
- // 序列号等数据,通过 验签工具包,或者 签章工具包,都可以获取
451
- const subjectDN = '';// this.PDFCtrl.GetSignCertInfo('SubjectCN')
452
- const issuerDN = 'CFCA ACS ';// this.PDFCtrl.GetSignCertInfo('IssuerDN')
453
- const certSN = serialNo || '';// this.PDFCtrl.GetSignCertInfo('SerialNumber')
454
-
455
- console.log('证书序列号,精确匹配', certSN)
456
- this.PDFCtrl.SelectSignCert(subjectDN, issuerDN, `${certSN}`, '')
457
- // 添加一个设置服务器时间戳的方法
458
- this.PDFCtrl.SetTimestampServer('http://210.74.41.195/timestamp')
459
- return true
460
- } catch (e) {
461
- console.log('PDFCtrl.SelectSignCert ', e)
462
- alert(`选择证书失败!${e}`)
463
- return false
464
- }
465
- },
466
- UploadFile() {
467
- try {
468
- let response = this.PDFCtrl.UploadCurrentFile(this.action);
469
- // 这里是同步的, 这个方法会在返回数据后才继续往后走
470
- response = JSON.parse(response);
471
- if (response.code === 0) {
472
- return response.data.list[0];
473
- }
474
- return ''
475
- } catch (e) {
476
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
477
- console.log('PDFCtrl 文件上传:', LastErrorDesc)
478
- alert(`PDFCtrl 文件上传:${LastErrorDesc}${e}`);
479
- }
480
- return false
481
- },
482
- signFileKeyImage(item, image) {
483
- // 将印章内的图片合成到pdf中,此处使用PDFCtrl在 引用该组件的view内
484
- const certSN = this.PDFCtrl.GetSignCertInfo('SerialNumber')
485
- console.log(`-signFileKeyImage--certSN-${ certSN}`, item)
486
-
487
- try {
488
- // 套印是 已左下角为原定, ukey 签署是以左上角未原点,并且,图像是图像的中心点 140/1.5/2 = 47
489
- let lacotionX = ''; let lacotionY = '';
490
- if (item.height) {
491
- lacotionX = Number(item.X) + 47
492
- lacotionY = Number(item.height) - Number(item.Y) - 47
493
- } else {
494
- // 于静 的签章标签,是未经处理的(无需Y轴颠倒),所以处理方式,和江湖的不一样,
495
- lacotionX = Number(item.X) + 47
496
- lacotionY = Number(item.Y) - 47
497
- }
498
-
499
- console.log(` 参数 pageIndex = ${ item.pageIndex} x = ${ lacotionX} Y = ${ lacotionY}`)
500
- console.log(`signFileKeyImage: image=${image}`)
501
-
502
- // this.PDFCtrl.SignFile_KeyImage(item.pageIndex, lacotionX, lacotionY)
503
- if (image) {
504
- this.PDFCtrl.SignFile_Image(item.pageIndex, lacotionX, lacotionY, image)
505
- } else {
506
- this.PDFCtrl.SignFile_KeyImage(item.pageIndex, lacotionX, lacotionY)
507
- }
508
- console.log('SignFile_KeyImage 成功')
509
- return true
510
- } catch (e) {
511
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc()
512
- console.log('signFileKeyImage', e)
513
- alert(`${LastErrorDesc} ${e}`)
514
- return false
515
- }
516
- },
517
- // 用3.2.1.7 的api 写的一印多签, 调研阶段,暂时不得用
518
- multipleSign7(labels, fileOss, serialNo, image, isOffset) {
519
- for (let index = 0; index < labels.length; index++) {
520
- const item = labels[index]
521
- if (typeof isOffset === 'number') {
522
- // 印章统一向下偏移
523
- item.Y -= isOffset
524
- }
525
- try {
526
- let lacotionX = ''; let lacotionY = '';
527
- if (item.height) {
528
- lacotionX = Number(item.X) + 47
529
- lacotionY = Number(item.height) - Number(item.Y) - 47
530
- } else {
531
- // 于静 的 签章标签,是未经处理的(无需Y轴颠倒),所以处理方式,和江湖的不一样,
532
- lacotionX = Number(item.X) + 47
533
- lacotionY = Number(item.Y) - 47
534
- }
535
- this.PDFCtrl.AddSignaturePosition(item.pageIndex, lacotionX, lacotionY)
536
- // console.log(`参数 pageIndex = ${ label.pageIndex} x = ${ lacotionX} Y = ${ lacotionY}`)
537
- return true
538
- } catch (e) {
539
- const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc()
540
- console.log(' multipleSign7', e)
541
- alert(LastErrorDesc + e)
542
- }
543
- }
544
- // 如果服务端图片 传进来就用,没有用ukey图片,无需单独再获取
545
- if (image) {
546
- this.PDFCtrl.SignFile_Image(image)
547
- } else {
548
- this.PDFCtrl.SignFile_KeyImage()
549
- }
550
- },
551
- // 用3.2.1.5 的api 写的一印多签
552
- multipleSign5(labels, fileOss, serialNo, image, isOffset) {
553
- console.log('multipleSign 循环签的begin ', serialNo)
554
- const serialNoBegin = this.PDFCtrl.GetSignCertInfo('SerialNumber')
555
- console.log('serialNoBegin ', serialNoBegin)
556
- let result = ''
557
-
558
- // image 为 服务端印章图片
559
- // 获取ukey 中的图片 (每次都要输密码,不利于一印多签)
560
- // 3.2.1.5的插件没有获取图片的方法
561
-
562
- for (let index = 0; index < labels.length; index++) {
563
- const item = labels[index]
564
- console.log('item=', item)
565
- if (typeof isOffset === 'number') {
566
- // 印章统一向下偏移
567
- item.Y -= isOffset
568
- }
569
- // this.$message.success(`签署 [${text}] 位于第${label.pageIndex}页的位置,[总共:${index + 1}/${labels.length}个位置]`)
570
- if (index > 0) {
571
- const serialNoAgain = this.PDFCtrl.GetSignCertInfo('SerialNumber')
572
- console.log('本次获得的序列号serialNoAgain:', serialNoAgain)
573
- if (serialNoBegin !== serialNoAgain) {
574
- alert('签署过程中,请不要更换ukey!')
575
- return false
576
- }
577
- console.log('serialNo=', serialNo)
578
-
579
- result = result && this.signFileKeyImage((item), image)
580
- console.log(`iterateSign 签章结果${ index }-------`, result)
581
- } else {
582
- console.log('第一个章,不用验签', index)
583
- result = this.signFileKeyImage((item), image)
584
- console.log('iterateSign 签章结果', result)
585
- }
586
- // 如果签署失败,直接跳出循环
587
- if (!result) {
588
- return false
589
- }
590
- }
591
- console.log('multipleSign 签章的结果', result)
592
- return result
593
- },
594
- // 循环调用签章(一印多签) fileOss 没用,可以传空
595
- multipleSign(labels, fileOss, serialNo, image, isOffset = 0) {
596
- if (!image) {
597
- this.PDFCtrl.SetPKCS11Module('UyeePKCS11.Enterprise.dll|UlanPKCS11.Enterprise.dll|UlanPKCS11.dll|CFCA_UKEY_P11.dll')
598
- }
599
- if (this.PDFCtrl.AddSignaturePosition) {
600
- console.log('新版插件')
601
- return this.multipleSign7(labels, fileOss, serialNo, image, isOffset)
602
- }
603
- return this.multipleSign5(labels, fileOss, serialNo, image, isOffset)
604
- },
605
- GetSignatureInfo() {
606
- // 查询文件上的,签章信息, 据此验证,一印多签,是否签署成功
607
- const count = this.PDFCtrl.GetSignatureCount();
608
- const signatureList = []
609
- for (let i = 0; i < count; i++) {
610
- const signature = this.PDFCtrl.VerifySignature(i);
611
- const result = signature.GetSignCertInfo('SerialNumber');
612
- signatureList.push({
613
- SerialNumber: result,
614
- })
615
- }
616
- return signatureList
617
- },
618
- },
619
- watch: {
620
- pdfurl(val, oldval) {
621
- this.inputPage = 1
622
- if (this.isIE && val) {
623
- if (this.PDFCtrl) {
624
- console.log('cfca watch pdfurl==');
625
- if (oldval) {
626
- if (oldval !== val) {
627
- console.log('cfca watch oldval==', oldval);
628
- // 这里不先CloseFile, PDF控件没反应
629
- // beforeRouterLeve 不会在子组件触发,
630
- // 同一个页面被 这个判断打开第二个PDF时,关闭第一个 ,否则在签署多个文件时,切换文件,并未打开新文件
631
- this.CloseFile()
632
- setTimeout(this.OpenFile, 100);
633
- }
634
- } else {
635
- // 如果这里不用延时,pdf会加载失败
636
- setTimeout(this.OpenFile, 100);
637
- }
638
- } else {
639
- console.log('cfca watch PDFCtrl 未加载 ');
640
- }
641
- }
642
- },
643
- },
644
- };
645
- </script>
646
-
647
- <style lang="less">
648
- @import "./cfca-pdf.less";
649
- </style>
1
+ <template>
2
+ <div class="cfca-pdf">
3
+ <!-- isIE -->
4
+ <template v-if="isIE">
5
+ <div class="cfca-pdf-wrapper" :style="{visibility: visible}">
6
+ <div
7
+ :class="{'cfca-left': true, 'active': active==='left', 'disabled': pageNo <= 1}"
8
+ @click="GoToPrevPage()"
9
+ >
10
+ <span class="el-icon-arrow-left"></span>
11
+ </div>
12
+ <div class="cfca-content">
13
+ <div class="cfca-page">
14
+ <div class="fl cfca-title">
15
+ <h2>{{title}}</h2>
16
+ </div>
17
+ <div class="fr">
18
+ {{pageNo}}/{{pageCount}}
19
+ <span class="di">第</span>
20
+ <el-input
21
+ class="page-num"
22
+ size="mini"
23
+ v-model="inputPage"
24
+ @keyup.enter.native="GoToPage"
25
+ @change="GoToPage"
26
+ ></el-input>页
27
+ </div>
28
+ </div>
29
+ <div class="cfca-object" ref="PDFCtrlPlaceHolder">
30
+ <div class="obj-wrapper" @dragenter="onDragEnter" @dragover="onDragOver" @drop="onDrop">
31
+ <template v-if="this.idstr">
32
+ <!-- 拖动签章,Object 的事件(NotifyClickPoint)只能用id 来绑定 -->
33
+ <object
34
+ :id="'PDFCtrl' + this.idstr"
35
+ ref="pdfCtrl"
36
+ class="PDFCtrlObject"
37
+ :tabindex="0"
38
+ :codebase="publicPath + codebase"
39
+ style="position: relative; z-Index:1"
40
+ classid="clsid:6F60FE31-F827-4295-8AC4-775EF7478A6A"
41
+ width="100%"
42
+ height="100%"
43
+ >
44
+ <param name="wmode" value="transparent" />
45
+ <param name="showToolbar" value="false" />
46
+ </object>
47
+ </template>
48
+ <template v-else>
49
+ <object
50
+ ref="pdfCtrl"
51
+ class="PDFCtrlObject"
52
+ :tabindex="0"
53
+ :codebase="publicPath + codebase"
54
+ style="position: relative; z-Index:1"
55
+ classid="clsid:6F60FE31-F827-4295-8AC4-775EF7478A6A"
56
+ width="100%"
57
+ height="100%"
58
+ >
59
+ <param name="wmode" value="transparent" />
60
+ <param name="showToolbar" value="false" />
61
+ </object>
62
+ </template>
63
+ </div>
64
+ </div>
65
+ <div class="cfca-control">
66
+ <slot></slot>
67
+ </div>
68
+ </div>
69
+ <div
70
+ :class="{'cfca-right': true, 'active': active==='right', 'disabled': pageNo >= pageCount}"
71
+ @click="GoToNextPage()"
72
+ >
73
+ <span class="el-icon-arrow-right"></span>
74
+ </div>
75
+ <!-- HTML toolbar -->
76
+ <!--<tr class="fontSize3" align="center" height="23" bgcolor="#E8E8E8">-->
77
+ <!--<td width="40" class="fakehlink" @click="GoToFirstPage()">首页</td>-->
78
+ <!--<td width="60" class="fakehlink" @click="GoToPrevPage()">上一页</td>-->
79
+ <!--<td width="60" class="fakehlink" @click="GoToNextPage()">下一页</td>-->
80
+ <!--<td width="40" class="fakehlink" @click="GoToLastPage()">尾页</td>-->
81
+ <!--<td width="80" class="fakehlink" @click="GetPageNo()">页码信息</td>-->
82
+ <!--<td width="60" class="fakehlink" @click="GoToPage" align="right">跳转到页</td>-->
83
+ <!--<td width="60">-->
84
+ <!--: <input type="text" id="PageNo" style="width: 45px" onkeydown='if(event.keyCode===13){this.GoToPage()}' onkeyup="value=this.value.replace(/\D+/g,'')"/>-->
85
+ <!--</td>-->
86
+ <!--<td width="30"></td>-->
87
+ <!--<td width="70" class="fakehlink" @click="ZoomTo(-2)">适合宽度</td>-->
88
+ <!--<td width="70" class="fakehlink" @click="ZoomTo(-1)">单页模式</td>-->
89
+ <!--<td width="30"></td>-->
90
+ <!--<td width="45" class="fakehlink" @click="ZoomOut()">缩小</td>-->
91
+ <!--<td width="45" class="fakehlink" @click="ZoomIn()">放大</td>-->
92
+ <!--</tr>-->
93
+ </div>
94
+ </template>
95
+ <template v-else>
96
+ <div
97
+ class="red"
98
+ style="height: 350px; padding: 20px ;position: relative; margin-bottom: 20px"
99
+ >
100
+ 提示:当前浏览器不支持控件预览,请切换IE浏览器进行查看
101
+ <!--提示:出于安全性与监管要求考虑且CFCA控件只能够支持IE浏览器,请切换IE浏览器进行查看-->
102
+ <div class="tc" style="position: absolute;bottom: 0;left: 0;right: 0;">
103
+ <slot></slot>
104
+ </div>
105
+ </div>
106
+ </template>
107
+ </div>
108
+ </template>
109
+ <script>
110
+ // import config from {};
111
+ import { getUrl } from '../utils'
112
+
113
+ export default {
114
+ name: 'cfca-pdf',
115
+ props: {
116
+ action: {
117
+ type: String, // 签章完毕,上传文件地址,仅展示pdf 无需传
118
+ default: '',
119
+ },
120
+ pdfurl: {
121
+ type: String,
122
+ default: '',
123
+ },
124
+ visible: {
125
+ type: [String, Boolean],
126
+ default: 'visible',
127
+ },
128
+ title: {
129
+ type: String,
130
+ default: '',
131
+ },
132
+ image: {
133
+ type: String,
134
+ default: '',
135
+ },
136
+ idstr: {
137
+ type: [String, Number],
138
+ },
139
+ },
140
+ data() {
141
+ let codebase = '';
142
+ if (window.navigator.cpuClass === 'x86') {
143
+ codebase = 'TrustSignPDFPlugin.ttd.x86.cab#version=3,2,1,4';
144
+ } else {
145
+ codebase = 'TrustSignPDFPlugin.ttd.x64.cab#version=3,2,1,4';
146
+ }
147
+ return {
148
+ publicPath: 'https://wsp.totodi.com/cfca_plug/', // 为了获取public下的静态文件
149
+ PDFCtrl: '',
150
+ codebase,
151
+ active: '',
152
+ inputPage: '',
153
+ isIE:
154
+ navigator.appName.indexOf('Internet') >= 0
155
+ || navigator.appVersion.indexOf('Trident') >= 0,
156
+ pageNo: 1,
157
+ pageCount: 1,
158
+ };
159
+ },
160
+ beforeDestroy() {
161
+ // CloseFile 未执行完毕,销毁页面 导致页面崩溃,
162
+ // CloseFile 必须执行完毕才能销毁 实例 所以 CloseFile在 dialog的close 方法里执行,页面的在router个beforeRouteLeave里执行
163
+ console.log('--cfca-pdf-beforeDestroy')
164
+ },
165
+ async beforeRouteLeave(to, from, next) {
166
+ // 子组件不会触发这个方法
167
+ console.log('-cfca--beforeRouteLeave---')
168
+ await this.CloseFile()
169
+ next()
170
+ },
171
+ mounted() {
172
+ if (this.isIE) {
173
+ this.OnLoad();
174
+ console.log(`cfca mounted =${ this.pdfurl}`)
175
+ if (this.pdfurl) {
176
+ // console.log('cfca mounted this.pdfurl==' + this.pdfurl)
177
+ // 这里的 setTimeout 必须存在,否则 补充协议签署时,会看不到pdf
178
+ // PDFCtrl 没有初始化完毕 ($nextTick 不行 必须用setTimeout)
179
+
180
+ // this.$nextTick(this.OpenFile)
181
+ setTimeout(this.OpenFile, 100);
182
+ }
183
+ }
184
+ },
185
+ methods: {
186
+ OnLoad() {
187
+ if (this.PDFCtrl) {
188
+ return false;
189
+ }
190
+ if (this.isIE) {
191
+ // 使用refs 拿到的元素 不能ukey签章
192
+ this.PDFCtrl = this.$refs.pdfCtrl;
193
+ if (!this.PDFCtrl) {
194
+ console.log('使用id 加载this.PDFCtrl ');
195
+ this.PDFCtrl = window[`PDFCtrl${ this.idstr}`]
196
+ }
197
+ // console.log('加载this.PDFCtrl ', this.PDFCtrl)
198
+ // 将OnClickPoint事件放入 全局函数
199
+ window.OnClickPoint = this.OnClickPoint;
200
+ } else {
201
+ // alert('请使用 IE 浏览器!')
202
+ return false;
203
+ }
204
+ },
205
+ OpenFile(src) {
206
+ src = src || this.pdfurl;
207
+ if (!src) {
208
+ alert('未发现pdf资源路径!');
209
+ return false;
210
+ }
211
+ try {
212
+ console.log(`OpenFile--src--${ src}`);
213
+ this.PDFCtrl.OpenWebFile(encodeURI(src));
214
+ this.PDFCtrl = this.$refs.pdfCtrl;
215
+ setTimeout(() => {
216
+ this.PDFCtrl.ZoomTo(-1);
217
+ this.GetPageNo();
218
+ }, 100);
219
+ } catch (e) {
220
+ if (this.PDFCtrl.GetLastErrorDesc) {
221
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
222
+ alert(LastErrorDesc + e);
223
+ }
224
+ }
225
+ },
226
+ sleep(ms) {
227
+ return new Promise((resolve) => setTimeout(resolve, ms))
228
+ },
229
+ CloseFile() {
230
+ try {
231
+ if (this.pdfurl && this.PDFCtrl) {
232
+ console.log('CloseFile---')
233
+ this.PDFCtrl.CloseFile();
234
+ // await this.sleep(1000)
235
+ }
236
+ } catch (e) {
237
+ console.log('CloseFile error--', e);
238
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
239
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
240
+ alert(LastErrorDesc + e);
241
+ }
242
+ }
243
+ },
244
+
245
+ onDragEnter(event) {
246
+ this.$emit('cfcaDragEnter', event);
247
+ },
248
+ onDragOver(event) {
249
+ event.preventDefault();
250
+ this.$emit('cfcaDragOver', event);
251
+ },
252
+ onDrop(event) {
253
+ this.$emit('cfcaDrop', event);
254
+ },
255
+ // Page operations
256
+
257
+ GoToFirstPage() {
258
+ try {
259
+ this.PDFCtrl.GoToFirstPage();
260
+ } catch (e) {
261
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
262
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
263
+ alert(LastErrorDesc + e);
264
+ }
265
+ }
266
+ },
267
+
268
+ GoToLastPage() {
269
+ try {
270
+ this.PDFCtrl.GoToLastPage();
271
+ } catch (e) {
272
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
273
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
274
+ alert(LastErrorDesc + e);
275
+ }
276
+ }
277
+ },
278
+ GoToPrevPage() {
279
+ this.active = 'left';
280
+ const me = this;
281
+ try {
282
+ this.PDFCtrl.GoToPrevPage();
283
+ this.inputPage = ''
284
+ setTimeout(() => {
285
+ me.GetPageNo();
286
+ }, 100);
287
+ } catch (e) {
288
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
289
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
290
+ alert(LastErrorDesc + e);
291
+ }
292
+ }
293
+ },
294
+
295
+ GoToNextPage() {
296
+ this.active = 'right';
297
+ const me = this;
298
+ try {
299
+ this.PDFCtrl.GoToNextPage();
300
+ this.inputPage = ''
301
+ setTimeout(() => {
302
+ me.GetPageNo();
303
+ }, 100);
304
+ } catch (e) {
305
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
306
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
307
+ alert(LastErrorDesc + e);
308
+ }
309
+ }
310
+ },
311
+
312
+ GetPageNo() {
313
+ try {
314
+ this.pageNo = this.PDFCtrl.GetCurrentPageNo();
315
+ this.pageCount = this.PDFCtrl.GetPageCount();
316
+ } catch (e) {
317
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
318
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
319
+ alert(LastErrorDesc + e);
320
+ }
321
+ }
322
+ },
323
+
324
+ GoToPage() {
325
+ const me = this;
326
+ try {
327
+ const pageNo = this.inputPage.replace(/\D/, '');
328
+ if (pageNo === '') {
329
+ alert('请输入页码!');
330
+ return;
331
+ }
332
+ this.PDFCtrl.GoToPage(pageNo);
333
+ setTimeout(() => {
334
+ me.GetPageNo();
335
+ }, 100);
336
+ } catch (e) {
337
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
338
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
339
+ alert(LastErrorDesc + e);
340
+ }
341
+ }
342
+ },
343
+
344
+ // Zoom operations
345
+ ZoomTo(factor) {
346
+ try {
347
+ this.PDFCtrl.ZoomTo(factor);
348
+ } catch (e) {
349
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
350
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
351
+ alert(LastErrorDesc + e);
352
+ }
353
+ }
354
+ },
355
+
356
+ ZoomOut() {
357
+ try {
358
+ this.PDFCtrl.ZoomOut();
359
+ } catch (e) {
360
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
361
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
362
+ alert(LastErrorDesc + e);
363
+ }
364
+ }
365
+ },
366
+ ZoomIn() {
367
+ try {
368
+ this.PDFCtrl.ZoomIn();
369
+ } catch (e) {
370
+ if (this.PDFCtrl && this.PDFCtrl.GetLastErrorDesc) {
371
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
372
+ alert(LastErrorDesc + e);
373
+ }
374
+ }
375
+ },
376
+ // 把章合到pdf 中去, 拖动签使用的
377
+ OnClickPoint(nPageNo, x, y) {
378
+ console.log('OnClickPoint--', `nPageNo=${nPageNo}, x=${x}, y=${y}`);
379
+ try {
380
+ console.log('image2=', this.image)
381
+ if (this.image) {
382
+ this.PDFCtrl.SignFile_Image(nPageNo, x, y, this.image)
383
+ } else {
384
+ this.PDFCtrl.SignFile_KeyImage(nPageNo, x, y);
385
+ }
386
+ this.$emit('cfca-point', nPageNo, x, y)
387
+ } catch (e) {
388
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
389
+ alert(LastErrorDesc + e);
390
+ }
391
+ },
392
+
393
+ // 外部打开dialog 调用
394
+ openDialog(url) {
395
+ if (this.isIE) {
396
+ console.log(' openDialog---');
397
+ // 外部dialog 这里需要使用延时,否则pdf 还未初始化完毕
398
+ setTimeout(() => {
399
+ this.OpenFile(url);
400
+ }, 350);
401
+ }
402
+ },
403
+ getUkeyImage() {
404
+ const version = this.PDFCtrl.GetVersion()
405
+ console.log(version)
406
+ this.PDFCtrl.SetPKCS11Module('UyeePKCS11.Enterprise.dll|UlanPKCS11.Enterprise.dll|UlanPKCS11.dll|CFCA_UKEY_P11.dll')
407
+ if (version === '3.2.1.7') {
408
+ // 获取版本号报错 (必须升级到3.2.1.7)
409
+ return this.PDFCtrl.ReadKeyImage();
410
+ }
411
+ alert(`客户端签章控件[v=${version}],需要升级!`)
412
+ },
413
+ GetCertInfo(InfoTypeID) {
414
+ // '证书持有者CN:\t' + PDFCtrl.GetSignCertInfo('SubjectCN') +
415
+ // '\n证书持有者DN:\t' + PDFCtrl.GetSignCertInfo('SubjectDN') +
416
+ // '\n证书颁发者DN:\t' + PDFCtrl.GetSignCertInfo('IssuerDN') +
417
+ // '\n证书序列号:\t' + PDFCtrl.GetSignCertInfo('SerialNumber') +
418
+ // '\n起始有效期:\t' + PDFCtrl.GetSignCertInfo('ValidFrom') +
419
+ // '\n截止有效期:\t' + PDFCtrl.GetSignCertInfo('ValidTo') +
420
+ // '\n起始有效期UTC:\t' + PDFCtrl.GetSignCertInfo('UTCValidFrom') +
421
+ // '\n截止有效期UTC:\t' + PDFCtrl.GetSignCertInfo('UTCValidTo') +
422
+ // '\n证书算法:\t\t' + PDFCtrl.GetSignCertInfo('CertAlgorithm') +
423
+ // '\n证书内容:\n' + PDFCtrl.GetSignCertInfo('CertContent');
424
+ InfoTypeID = InfoTypeID || 'SubjectDN'
425
+ try {
426
+ const InfoContent = this.PDFCtrl.GetSignCertInfo(InfoTypeID)
427
+ // Opera浏览器,NPAPI函数执行结果为false时,不能触发异常,需要自己判断返回值。
428
+ if (!InfoContent) {
429
+ const errorDesc = this.PDFCtrl.GetLastErrorDesc()
430
+ alert(errorDesc)
431
+ return
432
+ }
433
+ return InfoContent
434
+ } catch (e) {
435
+ console.log('GetCertInfo :', e)
436
+ const errorDesc = this.PDFCtrl.GetLastErrorDesc()
437
+ alert(errorDesc + e)
438
+ }
439
+ },
440
+ /* */
441
+ selectSignCert(serialNo) {
442
+ // 使用PDFCtrl.GetSignCertInfo 会报错, 必须在选完证书才能调用
443
+ // let subjectDN1 = this.PDFCtrl.GetSignCertInfo('SubjectCN')
444
+ // let issuerDN1 = this.PDFCtrl.GetSignCertInfo('IssuerDN')
445
+ // const certSN1 = this.PDFCtrl.GetSignCertInfo('SerialNumber')
446
+ // console.log('PDFCtrl, subjectDN1', subjectDN1)
447
+ // console.log('PDFCtrl, issuerDN1', issuerDN1)
448
+ // console.log('PDFCtrl, certSN1', certSN1)
449
+ try {
450
+ // 序列号等数据,通过 验签工具包,或者 签章工具包,都可以获取
451
+ const subjectDN = '';// this.PDFCtrl.GetSignCertInfo('SubjectCN')
452
+ const issuerDN = 'CFCA ACS ';// this.PDFCtrl.GetSignCertInfo('IssuerDN')
453
+ const certSN = serialNo || '';// this.PDFCtrl.GetSignCertInfo('SerialNumber')
454
+
455
+ console.log('证书序列号,精确匹配', certSN)
456
+ this.PDFCtrl.SelectSignCert(subjectDN, issuerDN, `${certSN}`, '')
457
+ // 添加一个设置服务器时间戳的方法
458
+ this.PDFCtrl.SetTimestampServer('http://210.74.41.195/timestamp')
459
+ return true
460
+ } catch (e) {
461
+ console.log('PDFCtrl.SelectSignCert ', e)
462
+ alert(`选择证书失败!${e}`)
463
+ return false
464
+ }
465
+ },
466
+ UploadFile() {
467
+ try {
468
+ let response = this.PDFCtrl.UploadCurrentFile(this.action);
469
+ // 这里是同步的, 这个方法会在返回数据后才继续往后走
470
+ response = JSON.parse(response);
471
+ if (response.code === 0) {
472
+ return response.data.list[0];
473
+ }
474
+ return ''
475
+ } catch (e) {
476
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc();
477
+ console.log('PDFCtrl 文件上传:', LastErrorDesc)
478
+ alert(`PDFCtrl 文件上传:${LastErrorDesc}${e}`);
479
+ }
480
+ return false
481
+ },
482
+ signFileKeyImage(item, image) {
483
+ // 将印章内的图片合成到pdf中,此处使用PDFCtrl在 引用该组件的view内
484
+ const certSN = this.PDFCtrl.GetSignCertInfo('SerialNumber')
485
+ console.log(`-signFileKeyImage--certSN-${ certSN}`, item)
486
+
487
+ try {
488
+ // 套印是 已左下角为原定, ukey 签署是以左上角未原点,并且,图像是图像的中心点 140/1.5/2 = 47
489
+ let lacotionX = ''; let lacotionY = '';
490
+ if (item.height) {
491
+ lacotionX = Number(item.X) + 47
492
+ lacotionY = Number(item.height) - Number(item.Y) - 47
493
+ } else {
494
+ // 于静 的签章标签,是未经处理的(无需Y轴颠倒),所以处理方式,和江湖的不一样,
495
+ lacotionX = Number(item.X) + 47
496
+ lacotionY = Number(item.Y) - 47
497
+ }
498
+
499
+ console.log(` 参数 pageIndex = ${ item.pageIndex} x = ${ lacotionX} Y = ${ lacotionY}`)
500
+ console.log(`signFileKeyImage: image=${image}`)
501
+
502
+ // this.PDFCtrl.SignFile_KeyImage(item.pageIndex, lacotionX, lacotionY)
503
+ if (image) {
504
+ this.PDFCtrl.SignFile_Image(item.pageIndex, lacotionX, lacotionY, image)
505
+ } else {
506
+ this.PDFCtrl.SignFile_KeyImage(item.pageIndex, lacotionX, lacotionY)
507
+ }
508
+ console.log('SignFile_KeyImage 成功')
509
+ return true
510
+ } catch (e) {
511
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc()
512
+ console.log('signFileKeyImage', e)
513
+ alert(`${LastErrorDesc} ${e}`)
514
+ return false
515
+ }
516
+ },
517
+ // 用3.2.1.7 的api 写的一印多签, 调研阶段,暂时不得用
518
+ multipleSign7(labels, fileOss, serialNo, image, isOffset) {
519
+ for (let index = 0; index < labels.length; index++) {
520
+ const item = labels[index]
521
+ if (typeof isOffset === 'number') {
522
+ // 印章统一向下偏移
523
+ item.Y -= isOffset
524
+ }
525
+ try {
526
+ let lacotionX = ''; let lacotionY = '';
527
+ if (item.height) {
528
+ lacotionX = Number(item.X) + 47
529
+ lacotionY = Number(item.height) - Number(item.Y) - 47
530
+ } else {
531
+ // 于静 的 签章标签,是未经处理的(无需Y轴颠倒),所以处理方式,和江湖的不一样,
532
+ lacotionX = Number(item.X) + 47
533
+ lacotionY = Number(item.Y) - 47
534
+ }
535
+ this.PDFCtrl.AddSignaturePosition(item.pageIndex, lacotionX, lacotionY)
536
+ // console.log(`参数 pageIndex = ${ label.pageIndex} x = ${ lacotionX} Y = ${ lacotionY}`)
537
+ return true
538
+ } catch (e) {
539
+ const LastErrorDesc = this.PDFCtrl.GetLastErrorDesc()
540
+ console.log(' multipleSign7', e)
541
+ alert(LastErrorDesc + e)
542
+ }
543
+ }
544
+ // 如果服务端图片 传进来就用,没有用ukey图片,无需单独再获取
545
+ if (image) {
546
+ this.PDFCtrl.SignFile_Image(image)
547
+ } else {
548
+ this.PDFCtrl.SignFile_KeyImage()
549
+ }
550
+ },
551
+ // 用3.2.1.5 的api 写的一印多签
552
+ multipleSign5(labels, fileOss, serialNo, image, isOffset) {
553
+ console.log('multipleSign 循环签的begin ', serialNo)
554
+ const serialNoBegin = this.PDFCtrl.GetSignCertInfo('SerialNumber')
555
+ console.log('serialNoBegin ', serialNoBegin)
556
+ let result = ''
557
+
558
+ // image 为 服务端印章图片
559
+ // 获取ukey 中的图片 (每次都要输密码,不利于一印多签)
560
+ // 3.2.1.5的插件没有获取图片的方法
561
+
562
+ for (let index = 0; index < labels.length; index++) {
563
+ const item = labels[index]
564
+ console.log('item=', item)
565
+ if (typeof isOffset === 'number') {
566
+ // 印章统一向下偏移
567
+ item.Y -= isOffset
568
+ }
569
+ // this.$message.success(`签署 [${text}] 位于第${label.pageIndex}页的位置,[总共:${index + 1}/${labels.length}个位置]`)
570
+ if (index > 0) {
571
+ const serialNoAgain = this.PDFCtrl.GetSignCertInfo('SerialNumber')
572
+ console.log('本次获得的序列号serialNoAgain:', serialNoAgain)
573
+ if (serialNoBegin !== serialNoAgain) {
574
+ alert('签署过程中,请不要更换ukey!')
575
+ return false
576
+ }
577
+ console.log('serialNo=', serialNo)
578
+
579
+ result = result && this.signFileKeyImage((item), image)
580
+ console.log(`iterateSign 签章结果${ index }-------`, result)
581
+ } else {
582
+ console.log('第一个章,不用验签', index)
583
+ result = this.signFileKeyImage((item), image)
584
+ console.log('iterateSign 签章结果', result)
585
+ }
586
+ // 如果签署失败,直接跳出循环
587
+ if (!result) {
588
+ return false
589
+ }
590
+ }
591
+ console.log('multipleSign 签章的结果', result)
592
+ return result
593
+ },
594
+ // 循环调用签章(一印多签) fileOss 没用,可以传空
595
+ multipleSign(labels, fileOss, serialNo, image, isOffset = 0) {
596
+ if (!image) {
597
+ this.PDFCtrl.SetPKCS11Module('UyeePKCS11.Enterprise.dll|UlanPKCS11.Enterprise.dll|UlanPKCS11.dll|CFCA_UKEY_P11.dll')
598
+ }
599
+ if (this.PDFCtrl.AddSignaturePosition) {
600
+ console.log('新版插件')
601
+ return this.multipleSign7(labels, fileOss, serialNo, image, isOffset)
602
+ }
603
+ return this.multipleSign5(labels, fileOss, serialNo, image, isOffset)
604
+ },
605
+ GetSignatureInfo() {
606
+ // 查询文件上的,签章信息, 据此验证,一印多签,是否签署成功
607
+ const count = this.PDFCtrl.GetSignatureCount();
608
+ const signatureList = []
609
+ for (let i = 0; i < count; i++) {
610
+ const signature = this.PDFCtrl.VerifySignature(i);
611
+ const result = signature.GetSignCertInfo('SerialNumber');
612
+ signatureList.push({
613
+ SerialNumber: result,
614
+ })
615
+ }
616
+ return signatureList
617
+ },
618
+ },
619
+ watch: {
620
+ pdfurl(val, oldval) {
621
+ this.inputPage = 1
622
+ if (this.isIE && val) {
623
+ if (this.PDFCtrl) {
624
+ console.log('cfca watch pdfurl==');
625
+ if (oldval) {
626
+ if (oldval !== val) {
627
+ console.log('cfca watch oldval==', oldval);
628
+ // 这里不先CloseFile, PDF控件没反应
629
+ // beforeRouterLeve 不会在子组件触发,
630
+ // 同一个页面被 这个判断打开第二个PDF时,关闭第一个 ,否则在签署多个文件时,切换文件,并未打开新文件
631
+ this.CloseFile()
632
+ setTimeout(this.OpenFile, 100);
633
+ }
634
+ } else {
635
+ // 如果这里不用延时,pdf会加载失败
636
+ setTimeout(this.OpenFile, 100);
637
+ }
638
+ } else {
639
+ console.log('cfca watch PDFCtrl 未加载 ');
640
+ }
641
+ }
642
+ },
643
+ },
644
+ };
645
+ </script>
646
+
647
+ <style lang="less">
648
+ @import "./cfca-pdf.less";
649
+ </style>