dompdf.js 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.
@@ -1,936 +1,936 @@
1
- // ==UserScript==
2
- // @name HTML2PDF 网页元素转PDF
3
- // @namespace http://tampermonkey.net/
4
- // @version 1.0
5
- // @description 在任意网站添加按钮,选择页面元素并生成PDF
6
- // @author You
7
- // @match *://*/*
8
- // @grant none
9
- // @require file:///D:/project-code/html2pdf/dist/html2pdf.js
10
- // @require file:///D:/project-code/html2pdf/examples/SourceHanSansSC-Normal-Min-normal.js
11
- // ==/UserScript==
12
-
13
- (function () {
14
- 'use strict';
15
-
16
- // 全局变量
17
- let isSelecting = false;
18
- let selectedElement = null;
19
- let overlay = null;
20
- let controlPanel = null;
21
-
22
- // 创建控制面板
23
- function createControlPanel() {
24
- const panel = document.createElement('div');
25
- panel.id = 'html2pdf-control-panel';
26
- panel.style.cssText = `
27
- position: fixed;
28
- top: 20px;
29
- right: 20px;
30
- z-index: 10000;
31
- font-family: 'Arial', sans-serif;
32
- transition: all 0.3s ease;
33
- display: flex;
34
- flex-direction: column;
35
- align-items: flex-end;
36
- `;
37
-
38
- // 创建主面板内容(默认隐藏)
39
- const panelContent = document.createElement('div');
40
- panelContent.id = 'html2pdf-panel-content';
41
- panelContent.style.cssText = `
42
- background: linear-gradient(145deg, #0F1C2E, #1E2A45);
43
- border: 1px solid #3A86FF;
44
- border-radius: 10px;
45
- padding: 15px;
46
- box-shadow: 0 4px 20px rgba(0,0,0,0.4), 0 0 15px rgba(58, 134, 255, 0.4);
47
- color: #e1e1e1;
48
- min-width: 220px;
49
- display: none;
50
- backdrop-filter: blur(5px);
51
- margin-top: 10px;
52
- `;
53
-
54
- panelContent.innerHTML = `
55
- <div style="
56
- margin-bottom: 15px;
57
- font-weight: bold;
58
- color: #5EEAD4;
59
- font-size: 16px;
60
- display: flex;
61
- align-items: center;
62
- justify-content: space-between;
63
- ">
64
- <span>HTML2PDF 工具</span>
65
- <div style="
66
- width: 40px;
67
- height: 4px;
68
- background: linear-gradient(90deg, #5EEAD4, #3A86FF);
69
- border-radius: 2px;
70
- box-shadow: 0 0 8px rgba(94, 234, 212, 0.6);
71
- "></div>
72
- </div>
73
- <button id="select-element-btn" style="
74
- width: 100%;
75
- padding: 8px 12px;
76
- margin-bottom: 10px;
77
- background: linear-gradient(90deg, #3A86FF, #5E60CE);
78
- color: white;
79
- border: none;
80
- border-radius: 6px;
81
- cursor: pointer;
82
- font-size: 14px;
83
- box-shadow: 0 2px 10px rgba(58, 134, 255, 0.4);
84
- transition: all 0.2s ease;
85
- ">选择元素</button>
86
- <button id="generate-pdf-btn" style="
87
- width: 100%;
88
- padding: 8px 12px;
89
- margin-bottom: 10px;
90
- background: linear-gradient(90deg, #5EEAD4, #38BDF8);
91
- color: white;
92
- border: none;
93
- border-radius: 6px;
94
- cursor: pointer;
95
- font-size: 14px;
96
- box-shadow: 0 2px 10px rgba(94, 234, 212, 0.4);
97
- opacity: 0.5;
98
- transition: all 0.2s ease;
99
- margin-left:0;
100
- text-shadow: 0 1px 2px rgba(0,0,0,0.3);
101
- " disabled>生成PDF</button>
102
- <button id="close-panel-btn" style="
103
- width: 100%;
104
- padding: 6px 12px;
105
- background: linear-gradient(90deg, #F72585, #7209B7);
106
- color: white;
107
- border: none;
108
- border-radius: 6px;
109
- cursor: pointer;
110
- font-size: 12px;
111
- box-shadow: 0 2px 10px rgba(247, 37, 133, 0.4);
112
- transition: all 0.2s ease;
113
- margin-left: 0;
114
- text-shadow: 0 1px 2px rgba(0,0,0,0.3);
115
- ">关闭</button>
116
- <div id="selected-info" style="
117
- margin-top: 10px;
118
- padding: 10px;
119
- background: rgba(14, 23, 38, 0.6);
120
- border-radius: 6px;
121
- font-size: 12px;
122
- color: #e1e1e1;
123
- display: none;
124
- border-left: 3px solid #5EEAD4;
125
- box-shadow: 0 2px 8px rgba(0,0,0,0.2) inset;
126
- "></div>
127
- `;
128
-
129
- // 创建触发按钮(默认显示)
130
- const triggerButton = document.createElement('div');
131
- triggerButton.id = 'html2pdf-trigger-button';
132
- triggerButton.style.cssText = `
133
- width: 50px;
134
- height: 50px;
135
- border-radius: 50%;
136
- background: linear-gradient(145deg, #3A86FF, #5E60CE);
137
- box-shadow: 0 4px 15px rgba(58, 134, 255, 0.5), 0 0 20px rgba(58, 134, 255, 0.3);
138
- cursor: pointer;
139
- display: flex;
140
- align-items: center;
141
- justify-content: center;
142
- transition: all 0.3s ease;
143
- position: relative;
144
- overflow: hidden;
145
- `;
146
-
147
- // 添加PDF图标
148
- triggerButton.innerHTML = `
149
- <div style="
150
- color: white;
151
- font-size: 20px;
152
- font-weight: bold;
153
- text-shadow: 0 1px 2px rgba(0,0,0,0.3);
154
- ">PDF</div>
155
- <div style="
156
- position: absolute;
157
- width: 100%;
158
- height: 100%;
159
- border-radius: 50%;
160
- border: 2px solid rgba(94, 234, 212, 0.4);
161
- animation: pulse 2s infinite;
162
- "></div>
163
- `;
164
-
165
- // 添加脉冲动画样式
166
- const style = document.createElement('style');
167
- style.textContent = `
168
- @keyframes pulse {
169
- 0% {
170
- transform: scale(1);
171
- opacity: 0.8;
172
- }
173
- 70% {
174
- transform: scale(1.1);
175
- opacity: 0;
176
- }
177
- 100% {
178
- transform: scale(1);
179
- opacity: 0;
180
- }
181
- }
182
- #select-element-btn:hover, #generate-pdf-btn:not([disabled]):hover, #close-panel-btn:hover {
183
- transform: translateY(-2px);
184
- box-shadow: 0 4px 15px rgba(0,0,0,0.3);
185
- filter: brightness(1.1);
186
- }
187
- #html2pdf-trigger-button:hover {
188
- transform: scale(1.05);
189
- box-shadow: 0 4px 20px rgba(58, 134, 255, 0.6), 0 0 30px rgba(58, 134, 255, 0.4);
190
- }
191
- .html2pdf-highlight {
192
- outline: 3px solid #5EEAD4 !important;
193
- outline-offset: 2px !important;
194
- box-shadow: 0 0 15px rgba(94, 234, 212, 0.4) !important;
195
- }
196
- `;
197
- document.head.appendChild(style);
198
-
199
- // 将触发按钮和面板内容添加到主面板
200
- panel.appendChild(triggerButton);
201
- panel.appendChild(panelContent);
202
- document.body.appendChild(panel);
203
-
204
- // 添加触发按钮点击事件
205
- triggerButton.addEventListener('click', () => {
206
- const content = document.getElementById('html2pdf-panel-content');
207
- if (content.style.display === 'none') {
208
- content.style.display = 'block';
209
- triggerButton.style.transform = 'scale(0.9)';
210
- } else {
211
- content.style.display = 'none';
212
- triggerButton.style.transform = 'scale(1)';
213
- }
214
- });
215
-
216
- return panel;
217
- }
218
-
219
- // 创建选择覆盖层
220
- function createOverlay() {
221
- const overlay = document.createElement('div');
222
- overlay.id = 'html2pdf-overlay';
223
- overlay.style.cssText = `
224
- position: fixed;
225
- top: 0;
226
- left: 0;
227
- width: 100%;
228
- height: 100%;
229
- background: rgba(0, 123, 186, 0.1);
230
- z-index: 9999;
231
- cursor: crosshair;
232
- pointer-events: none;
233
- `;
234
- document.body.appendChild(overlay);
235
- return overlay;
236
- }
237
-
238
- // 高亮元素
239
- function highlightElement(element) {
240
- // 移除之前的高亮
241
- const prevHighlight = document.querySelector('.html2pdf-highlight');
242
- if (prevHighlight) {
243
- prevHighlight.classList.remove('html2pdf-highlight');
244
- }
245
-
246
- // 添加高亮样式
247
- if (element && element !== document.body) {
248
- element.classList.add('html2pdf-highlight');
249
-
250
- // 添加高亮CSS
251
- if (!document.querySelector('#html2pdf-highlight-style')) {
252
- const style = document.createElement('style');
253
- style.id = 'html2pdf-highlight-style';
254
- // style.textContent = `
255
- // .html2pdf-highlight {
256
- // outline: 3px solid #007cba !important;
257
- // outline-offset: 2px !important;
258
- // }
259
- // `;
260
- document.head.appendChild(style);
261
- }
262
- }
263
- }
264
-
265
- // 高亮元素
266
- function highlightElement(element) {
267
- // 移除之前的高亮
268
- const prevHighlight = document.querySelector('.html2pdf-highlight');
269
- if (prevHighlight) {
270
- prevHighlight.classList.remove('html2pdf-highlight');
271
- }
272
-
273
- // 添加高亮样式
274
- if (element && element !== document.body) {
275
- element.classList.add('html2pdf-highlight');
276
-
277
- // 添加高亮CSS
278
- if (!document.querySelector('#html2pdf-highlight-style')) {
279
- const style = document.createElement('style');
280
- style.id = 'html2pdf-highlight-style';
281
- style.textContent = `
282
- .html2pdf-highlight {
283
- outline: 3px solid #007cba !important;
284
- outline-offset: 2px !important;
285
-
286
- }
287
- `;
288
- document.head.appendChild(style);
289
- }
290
- }
291
- }
292
-
293
- // 开始选择模式
294
- function startSelection() {
295
- isSelecting = true;
296
- overlay = createOverlay();
297
- document.body.style.cursor = 'crosshair';
298
-
299
- // 更新按钮状态
300
- const selectBtn = document.getElementById('select-element-btn');
301
- selectBtn.textContent = '取消选择';
302
- selectBtn.style.background = '#dc3545';
303
-
304
- // 添加事件监听
305
- document.addEventListener('mouseover', onMouseOver);
306
- document.addEventListener('click', onElementClick);
307
- document.addEventListener('keydown', onKeyDown);
308
- }
309
-
310
- // 停止选择模式
311
- function stopSelection() {
312
- isSelecting = false;
313
- document.body.style.cursor = '';
314
-
315
- if (overlay) {
316
- overlay.remove();
317
- overlay = null;
318
- }
319
-
320
- // 更新按钮状态
321
- const selectBtn = document.getElementById('select-element-btn');
322
- selectBtn.textContent = '选择元素';
323
- selectBtn.style.background = 'linear-gradient(90deg, #4cc9f0, #4361ee)';
324
-
325
- // 移除事件监听
326
- document.removeEventListener('mouseover', onMouseOver);
327
- document.removeEventListener('click', onElementClick);
328
- document.removeEventListener('keydown', onKeyDown);
329
- }
330
-
331
- // 鼠标悬停事件
332
- function onMouseOver(e) {
333
- if (!isSelecting) return;
334
- e.preventDefault();
335
-
336
- const element = e.target;
337
- if (element !== controlPanel && !controlPanel.contains(element)) {
338
- highlightElement(element);
339
- }
340
- }
341
-
342
- // 元素点击事件
343
- function onElementClick(e) {
344
- if (!isSelecting) return;
345
- e.preventDefault();
346
- e.stopPropagation();
347
-
348
- const element = e.target;
349
- if (element !== controlPanel && !controlPanel.contains(element)) {
350
- selectedElement = element;
351
- stopSelection();
352
- updateSelectedInfo(element);
353
- enablePdfGeneration();
354
- }
355
- }
356
-
357
- // 键盘事件(ESC取消选择)
358
- function onKeyDown(e) {
359
- if (e.key === 'Escape' && isSelecting) {
360
- stopSelection();
361
- }
362
- }
363
-
364
- // 更新选中元素信息
365
- function updateSelectedInfo(element) {
366
- const info = document.getElementById('selected-info');
367
- const tagName = element.tagName.toLowerCase();
368
- const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
369
- const id = element.id ? `#${element.id}` : '';
370
-
371
- // info.innerHTML = `
372
- // <strong>已选择元素:</strong><br>
373
- // 标签: ${tagName}${id}${className}<br>
374
- // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
375
- // ${element.parentElement && element.parentElement !== document.body ?
376
- // `<button id="select-parent-btn" style="
377
- // margin-top: 8px;
378
- // padding: 4px 8px;
379
- // background: linear-gradient(90deg, #5E60CE, #7209B7);
380
- // color: white;
381
- // border: none;
382
- // border-radius: 4px;
383
- // cursor: pointer;
384
- // font-size: 12px;
385
- // box-shadow: 0 2px 6px rgba(94, 96, 206, 0.4);
386
- // transition: all 0.2s ease;
387
- // display: block;
388
- // width: 100%;
389
- // ">选择父元素</button>` :
390
- // ''
391
- // }
392
- // `;
393
- info.style.display = 'block';
394
-
395
- // 如果有父元素且不是body,添加选择父元素按钮事件
396
- // if (element.parentElement && element.parentElement !== document.body) {
397
- // document.getElementById('select-parent-btn').addEventListener('click', () => {
398
- // selectParentElement(element);
399
- // });
400
- // }
401
- }
402
-
403
- // 选择父元素
404
- // function selectParentElement(element) {
405
- // if (element && element.parentElement && element.parentElement !== document.body) {
406
- // // 更新选中元素为父元素
407
- // selectedElement = element.parentElement;
408
-
409
- // // 高亮显示父元素
410
- // highlightElement(selectedElement);
411
-
412
- // // 更新选中信息
413
- // updateSelectedInfo(selectedElement);
414
- // }
415
- // }
416
-
417
- // 启用PDF生成按钮
418
- function enablePdfGeneration() {
419
- const pdfBtn = document.getElementById('generate-pdf-btn');
420
- pdfBtn.disabled = false;
421
- pdfBtn.style.opacity = '1';
422
- }
423
-
424
- // 生成PDF
425
- async function generatePDF() {
426
- if (!selectedElement) {
427
- alert('请先选择要转换的元素');
428
- return;
429
- }
430
-
431
- try {
432
- // 显示加载状态
433
- const pdfBtn = document.getElementById('generate-pdf-btn');
434
- const originalText = pdfBtn.textContent;
435
- pdfBtn.textContent = '生成中...';
436
- pdfBtn.disabled = true;
437
-
438
- // 使用html2canvas截图
439
- html2pdf(selectedElement, {
440
- useCORS: true,
441
- scale: 1,
442
- fontConfig: {
443
- fontFamily: 'SourceHanSansCN-Medium',
444
- fontBase64: window.fontBase64, //
445
- fontUrl: '',
446
- fontWeight: 400,
447
- fontStyle: 'normal'
448
- },
449
- }).then(function (canvas) {
450
- const link = document.createElement('a');
451
- link.download = 'output.png';
452
- link.href = canvas.toDataURL('image/png');
453
- link.click();
454
- // 恢复按钮状态
455
- pdfBtn.textContent = originalText;
456
- pdfBtn.disabled = false;
457
-
458
- alert('PDF生成成功!');
459
- }).catch(function (err) {
460
- console.log('creacterr', err);
461
-
462
- });;
463
-
464
-
465
-
466
-
467
-
468
- } catch (error) {
469
- console.error('PDF生成失败:', error);
470
- alert('PDF生成失败,请检查控制台错误信息');
471
-
472
- // 恢复按钮状态
473
- const pdfBtn = document.getElementById('generate-pdf-btn');
474
- pdfBtn.textContent = '生成PDF';
475
- pdfBtn.disabled = false;
476
- }
477
- }
478
-
479
-
480
- // 关闭面板
481
- function closePanel() {
482
- if (isSelecting) {
483
- stopSelection();
484
- }
485
-
486
- // 移除高亮
487
- const highlight = document.querySelector('.html2pdf-highlight');
488
- if (highlight) {
489
- highlight.classList.remove('html2pdf-highlight');
490
- }
491
-
492
- // 移除样式
493
- const style = document.querySelector('#html2pdf-highlight-style');
494
- if (style) {
495
- style.remove();
496
- }
497
-
498
- // 移除面板
499
- if (controlPanel) {
500
- controlPanel.remove();
501
- controlPanel = null;
502
- }
503
-
504
- selectedElement = null;
505
- }
506
-
507
- // 初始化
508
- function init() {
509
- // 等待页面加载完成
510
- if (document.readyState === 'loading') {
511
- document.addEventListener('DOMContentLoaded', init);
512
- return;
513
- }
514
-
515
- // 创建控制面板
516
- controlPanel = createControlPanel();
517
-
518
- // 绑定事件
519
- document.getElementById('select-element-btn').addEventListener('click', () => {
520
- if (isSelecting) {
521
- stopSelection();
522
- } else {
523
- startSelection();
524
- }
525
- });
526
-
527
- document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
528
- document.getElementById('close-panel-btn').addEventListener('click', closePanel);
529
-
530
- // 让面板可拖拽
531
- let isDragging = false;
532
- let dragOffset = {
533
- x: 0,
534
- y: 0
535
- };
536
-
537
- controlPanel.addEventListener('mousedown', (e) => {
538
- if (e.target.tagName !== 'BUTTON') {
539
- isDragging = true;
540
- dragOffset.x = e.clientX - controlPanel.offsetLeft;
541
- dragOffset.y = e.clientY - controlPanel.offsetTop;
542
- controlPanel.style.cursor = 'move';
543
- }
544
- });
545
-
546
- document.addEventListener('mousemove', (e) => {
547
- if (isDragging) {
548
- controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
549
- controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
550
- controlPanel.style.right = 'auto';
551
- }
552
- });
553
-
554
- document.addEventListener('mouseup', () => {
555
- isDragging = false;
556
- controlPanel.style.cursor = '';
557
- });
558
-
559
- console.log('HTML2PDF 用户脚本已加载');
560
- }
561
-
562
- // 启动脚本
563
- init();
564
-
565
- })();
566
-
567
-
568
-
569
- // (function () {
570
- // 'use strict';
571
-
572
- // // 全局变量
573
- // let isSelecting = false;
574
- // let selectedElement = null;
575
- // let overlay = null;
576
- // let controlPanel = null;
577
-
578
- // // 创建控制面板
579
- // function createControlPanel() {
580
- // const panel = document.createElement('div');
581
- // panel.id = 'dompdf-control-panel';
582
- // panel.style.cssText = `
583
- // position: fixed;
584
- // top: 20px;
585
- // right: 20px;
586
- // z-index: 10000;
587
- // background: #fff;
588
- // border: 2px solid #007cba;
589
- // border-radius: 8px;
590
- // padding: 15px;
591
- // box-shadow: 0 4px 12px rgba(0,0,0,0.15);
592
- // font-family: Arial, sans-serif;
593
- // min-width: 200px;
594
- // `;
595
-
596
- // panel.innerHTML = `
597
- // <div style="margin-bottom: 10px; font-weight: bold; color: #333;">dompdf 工具</div>
598
- // <button id="select-element-btn" style="
599
- // width: 100%;
600
- // padding: 8px 12px;
601
- // margin-bottom: 8px;
602
- // background: #007cba;
603
- // color: white;
604
- // border: none;
605
- // border-radius: 4px;
606
- // cursor: pointer;
607
- // font-size: 14px;
608
- // ">选择元素</button>
609
- // <button id="generate-pdf-btn" style="
610
- // width: 100%;
611
- // padding: 8px 12px;
612
- // margin-bottom: 8px;
613
- // background: #28a745;
614
- // color: white;
615
- // border: none;
616
- // border-radius: 4px;
617
- // cursor: pointer;
618
- // font-size: 14px;
619
- // opacity: 0.5;
620
- // margin-left:0
621
- // " disabled>生成PDF</button>
622
- // <button id="close-panel-btn" style="
623
- // width: 100%;
624
- // padding: 6px 12px;
625
- // background: #dc3545;
626
- // color: white;
627
- // border: none;
628
- // border-radius: 4px;
629
- // cursor: pointer;
630
- // font-size: 12px;
631
- // margin - left: 0
632
- // ">关闭</button>
633
- // <div id="selected-info" style="
634
- // margin-top: 10px;
635
- // padding: 8px;
636
- // background: #f8f9fa;
637
- // border-radius: 4px;
638
- // font-size: 12px;
639
- // color: #666;
640
- // display: none;
641
- // "></div>
642
- // `;
643
-
644
- // document.body.appendChild(panel);
645
- // return panel;
646
- // }
647
-
648
- // // 创建选择覆盖层
649
- // function createOverlay() {
650
- // const overlay = document.createElement('div');
651
- // overlay.id = 'dompdf-overlay';
652
- // overlay.style.cssText = `
653
- // position: fixed;
654
- // top: 0;
655
- // left: 0;
656
- // width: 100%;
657
- // height: 100%;
658
- // background: rgba(0, 123, 186, 0.1);
659
- // z-index: 9999;
660
- // cursor: crosshair;
661
- // pointer-events: none;
662
- // `;
663
- // document.body.appendChild(overlay);
664
- // return overlay;
665
- // }
666
-
667
- // // 高亮元素
668
- // function highlightElement(element) {
669
- // // 移除之前的高亮
670
- // const prevHighlight = document.querySelector('.dompdf-highlight');
671
- // if (prevHighlight) {
672
- // prevHighlight.classList.remove('dompdf-highlight');
673
- // }
674
-
675
- // // 添加高亮样式
676
- // if (element && element !== document.body) {
677
- // element.classList.add('dompdf-highlight');
678
-
679
- // // 添加高亮CSS
680
- // if (!document.querySelector('#dompdf-highlight-style')) {
681
- // const style = document.createElement('style');
682
- // style.id = 'dompdf-highlight-style';
683
- // style.textContent = `
684
- // .dompdf-highlight {
685
- // outline: 3px solid #007cba !important;
686
- // outline-offset: 2px !important;
687
-
688
- // }
689
- // `;
690
- // document.head.appendChild(style);
691
- // }
692
- // }
693
- // }
694
-
695
- // // 开始选择模式
696
- // function startSelection() {
697
- // isSelecting = true;
698
- // overlay = createOverlay();
699
- // document.body.style.cursor = 'crosshair';
700
-
701
- // // 更新按钮状态
702
- // const selectBtn = document.getElementById('select-element-btn');
703
- // selectBtn.textContent = '取消选择';
704
- // selectBtn.style.background = '#dc3545';
705
-
706
- // // 添加事件监听
707
- // document.addEventListener('mouseover', onMouseOver);
708
- // document.addEventListener('click', onElementClick);
709
- // document.addEventListener('keydown', onKeyDown);
710
- // }
711
-
712
- // // 停止选择模式
713
- // function stopSelection() {
714
- // isSelecting = false;
715
- // document.body.style.cursor = '';
716
-
717
- // if (overlay) {
718
- // overlay.remove();
719
- // overlay = null;
720
- // }
721
-
722
- // // 更新按钮状态
723
- // const selectBtn = document.getElementById('select-element-btn');
724
- // selectBtn.textContent = '选择元素';
725
- // selectBtn.style.background = '#007cba';
726
-
727
- // // 移除事件监听
728
- // document.removeEventListener('mouseover', onMouseOver);
729
- // document.removeEventListener('click', onElementClick);
730
- // document.removeEventListener('keydown', onKeyDown);
731
- // }
732
-
733
- // // 鼠标悬停事件
734
- // function onMouseOver(e) {
735
- // if (!isSelecting) return;
736
- // e.preventDefault();
737
-
738
- // const element = e.target;
739
- // if (element !== controlPanel && !controlPanel.contains(element)) {
740
- // highlightElement(element);
741
- // }
742
- // }
743
-
744
- // // 元素点击事件
745
- // function onElementClick(e) {
746
- // if (!isSelecting) return;
747
- // e.preventDefault();
748
- // e.stopPropagation();
749
-
750
- // const element = e.target;
751
- // if (element !== controlPanel && !controlPanel.contains(element)) {
752
- // selectedElement = element;
753
- // stopSelection();
754
- // updateSelectedInfo(element);
755
- // enablePdfGeneration();
756
- // }
757
- // }
758
-
759
- // // 键盘事件(ESC取消选择)
760
- // function onKeyDown(e) {
761
- // if (e.key === 'Escape' && isSelecting) {
762
- // stopSelection();
763
- // }
764
- // }
765
-
766
- // // 更新选中元素信息
767
- // function updateSelectedInfo(element) {
768
- // const info = document.getElementById('selected-info');
769
- // const tagName = element.tagName.toLowerCase();
770
- // const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
771
- // const id = element.id ? `#${element.id}` : '';
772
-
773
- // info.innerHTML = `
774
- // <strong>已选择元素:</strong><br>
775
- // 标签: ${tagName}${id}${className}<br>
776
- // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
777
- // `;
778
- // info.style.display = 'block';
779
- // }
780
-
781
- // // 启用PDF生成按钮
782
- // function enablePdfGeneration() {
783
- // const pdfBtn = document.getElementById('generate-pdf-btn');
784
- // pdfBtn.disabled = false;
785
- // pdfBtn.style.opacity = '1';
786
- // }
787
-
788
- // // 生成PDF
789
- // async function generatePDF() {
790
- // if (!selectedElement) {
791
- // alert('请先选择要转换的元素');
792
- // return;
793
- // }
794
-
795
- // try {
796
- // // 显示加载状态
797
- // const pdfBtn = document.getElementById('generate-pdf-btn');
798
- // const originalText = pdfBtn.textContent;
799
- // pdfBtn.textContent = '生成中...';
800
- // pdfBtn.disabled = true;
801
-
802
- // // 使用html2canvas截图
803
- // dompdf(selectedElement, {
804
- // useCORS: true,
805
- // scale: 1,
806
- // fontConfig: {
807
- // fontFamily: 'SourceHanSansCN-Medium',
808
- // fontBase64: window.fontBase64, //
809
- // fontUrl: '',
810
- // fontWeight: 400,
811
- // fontStyle: 'normal'
812
- // },
813
- // }).then(function (blob) {
814
- // const url = URL.createObjectURL(blob);
815
- // const a = document.createElement('a');
816
- // a.href = url;
817
- // a.download = "example.pdf";
818
- // document.body.appendChild(a);
819
- // a.click();
820
-
821
- // // 清理
822
- // setTimeout(() => {
823
- // document.body.removeChild(a);
824
- // URL.revokeObjectURL(url);
825
- // }, 100);
826
- // // 恢复按钮状态
827
- // pdfBtn.textContent = originalText;
828
- // pdfBtn.disabled = false;
829
-
830
- // alert('PDF生成成功!');
831
- // }).catch(function (err) {
832
- // console.log('creacterr', err);
833
-
834
- // });;
835
-
836
-
837
-
838
-
839
-
840
- // } catch (error) {
841
- // console.error('PDF生成失败:', error);
842
- // alert('PDF生成失败,请检查控制台错误信息');
843
-
844
- // // 恢复按钮状态
845
- // const pdfBtn = document.getElementById('generate-pdf-btn');
846
- // pdfBtn.textContent = '生成PDF';
847
- // pdfBtn.disabled = false;
848
- // }
849
- // }
850
-
851
- // // 关闭面板
852
- // function closePanel() {
853
- // if (isSelecting) {
854
- // stopSelection();
855
- // }
856
-
857
- // // 移除高亮
858
- // const highlight = document.querySelector('.dompdf-highlight');
859
- // if (highlight) {
860
- // highlight.classList.remove('dompdf-highlight');
861
- // }
862
-
863
- // // 移除样式
864
- // const style = document.querySelector('#dompdf-highlight-style');
865
- // if (style) {
866
- // style.remove();
867
- // }
868
-
869
- // // 移除面板
870
- // if (controlPanel) {
871
- // controlPanel.remove();
872
- // controlPanel = null;
873
- // }
874
-
875
- // selectedElement = null;
876
- // }
877
-
878
- // // 初始化
879
- // function init() {
880
- // // 等待页面加载完成
881
- // if (document.readyState === 'loading') {
882
- // document.addEventListener('DOMContentLoaded', init);
883
- // return;
884
- // }
885
-
886
- // // 创建控制面板
887
- // controlPanel = createControlPanel();
888
-
889
- // // 绑定事件
890
- // document.getElementById('select-element-btn').addEventListener('click', () => {
891
- // if (isSelecting) {
892
- // stopSelection();
893
- // } else {
894
- // startSelection();
895
- // }
896
- // });
897
-
898
- // document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
899
- // document.getElementById('close-panel-btn').addEventListener('click', closePanel);
900
-
901
- // // 让面板可拖拽
902
- // let isDragging = false;
903
- // let dragOffset = {
904
- // x: 0,
905
- // y: 0
906
- // };
907
-
908
- // controlPanel.addEventListener('mousedown', (e) => {
909
- // if (e.target.tagName !== 'BUTTON') {
910
- // isDragging = true;
911
- // dragOffset.x = e.clientX - controlPanel.offsetLeft;
912
- // dragOffset.y = e.clientY - controlPanel.offsetTop;
913
- // controlPanel.style.cursor = 'move';
914
- // }
915
- // });
916
-
917
- // document.addEventListener('mousemove', (e) => {
918
- // if (isDragging) {
919
- // controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
920
- // controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
921
- // controlPanel.style.right = 'auto';
922
- // }
923
- // });
924
-
925
- // document.addEventListener('mouseup', () => {
926
- // isDragging = false;
927
- // controlPanel.style.cursor = '';
928
- // });
929
-
930
- // console.log('dompdf 用户脚本已加载');
931
- // }
932
-
933
- // // 启动脚本
934
- // init();
935
-
1
+ // ==UserScript==
2
+ // @name HTML2PDF 网页元素转PDF
3
+ // @namespace http://tampermonkey.net/
4
+ // @version 1.0
5
+ // @description 在任意网站添加按钮,选择页面元素并生成PDF
6
+ // @author You
7
+ // @match *://*/*
8
+ // @grant none
9
+ // @require file:///D:/project-code/html2pdf/dist/html2pdf.js
10
+ // @require file:///D:/project-code/html2pdf/examples/SourceHanSansSC-Normal-Min-normal.js
11
+ // ==/UserScript==
12
+
13
+ (function () {
14
+ 'use strict';
15
+
16
+ // 全局变量
17
+ let isSelecting = false;
18
+ let selectedElement = null;
19
+ let overlay = null;
20
+ let controlPanel = null;
21
+
22
+ // 创建控制面板
23
+ function createControlPanel() {
24
+ const panel = document.createElement('div');
25
+ panel.id = 'html2pdf-control-panel';
26
+ panel.style.cssText = `
27
+ position: fixed;
28
+ top: 20px;
29
+ right: 20px;
30
+ z-index: 10000;
31
+ font-family: 'Arial', sans-serif;
32
+ transition: all 0.3s ease;
33
+ display: flex;
34
+ flex-direction: column;
35
+ align-items: flex-end;
36
+ `;
37
+
38
+ // 创建主面板内容(默认隐藏)
39
+ const panelContent = document.createElement('div');
40
+ panelContent.id = 'html2pdf-panel-content';
41
+ panelContent.style.cssText = `
42
+ background: linear-gradient(145deg, #0F1C2E, #1E2A45);
43
+ border: 1px solid #3A86FF;
44
+ border-radius: 10px;
45
+ padding: 15px;
46
+ box-shadow: 0 4px 20px rgba(0,0,0,0.4), 0 0 15px rgba(58, 134, 255, 0.4);
47
+ color: #e1e1e1;
48
+ min-width: 220px;
49
+ display: none;
50
+ backdrop-filter: blur(5px);
51
+ margin-top: 10px;
52
+ `;
53
+
54
+ panelContent.innerHTML = `
55
+ <div style="
56
+ margin-bottom: 15px;
57
+ font-weight: bold;
58
+ color: #5EEAD4;
59
+ font-size: 16px;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ ">
64
+ <span>HTML2PDF 工具</span>
65
+ <div style="
66
+ width: 40px;
67
+ height: 4px;
68
+ background: linear-gradient(90deg, #5EEAD4, #3A86FF);
69
+ border-radius: 2px;
70
+ box-shadow: 0 0 8px rgba(94, 234, 212, 0.6);
71
+ "></div>
72
+ </div>
73
+ <button id="select-element-btn" style="
74
+ width: 100%;
75
+ padding: 8px 12px;
76
+ margin-bottom: 10px;
77
+ background: linear-gradient(90deg, #3A86FF, #5E60CE);
78
+ color: white;
79
+ border: none;
80
+ border-radius: 6px;
81
+ cursor: pointer;
82
+ font-size: 14px;
83
+ box-shadow: 0 2px 10px rgba(58, 134, 255, 0.4);
84
+ transition: all 0.2s ease;
85
+ ">选择元素</button>
86
+ <button id="generate-pdf-btn" style="
87
+ width: 100%;
88
+ padding: 8px 12px;
89
+ margin-bottom: 10px;
90
+ background: linear-gradient(90deg, #5EEAD4, #38BDF8);
91
+ color: white;
92
+ border: none;
93
+ border-radius: 6px;
94
+ cursor: pointer;
95
+ font-size: 14px;
96
+ box-shadow: 0 2px 10px rgba(94, 234, 212, 0.4);
97
+ opacity: 0.5;
98
+ transition: all 0.2s ease;
99
+ margin-left:0;
100
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
101
+ " disabled>生成PDF</button>
102
+ <button id="close-panel-btn" style="
103
+ width: 100%;
104
+ padding: 6px 12px;
105
+ background: linear-gradient(90deg, #F72585, #7209B7);
106
+ color: white;
107
+ border: none;
108
+ border-radius: 6px;
109
+ cursor: pointer;
110
+ font-size: 12px;
111
+ box-shadow: 0 2px 10px rgba(247, 37, 133, 0.4);
112
+ transition: all 0.2s ease;
113
+ margin-left: 0;
114
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
115
+ ">关闭</button>
116
+ <div id="selected-info" style="
117
+ margin-top: 10px;
118
+ padding: 10px;
119
+ background: rgba(14, 23, 38, 0.6);
120
+ border-radius: 6px;
121
+ font-size: 12px;
122
+ color: #e1e1e1;
123
+ display: none;
124
+ border-left: 3px solid #5EEAD4;
125
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2) inset;
126
+ "></div>
127
+ `;
128
+
129
+ // 创建触发按钮(默认显示)
130
+ const triggerButton = document.createElement('div');
131
+ triggerButton.id = 'html2pdf-trigger-button';
132
+ triggerButton.style.cssText = `
133
+ width: 50px;
134
+ height: 50px;
135
+ border-radius: 50%;
136
+ background: linear-gradient(145deg, #3A86FF, #5E60CE);
137
+ box-shadow: 0 4px 15px rgba(58, 134, 255, 0.5), 0 0 20px rgba(58, 134, 255, 0.3);
138
+ cursor: pointer;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ transition: all 0.3s ease;
143
+ position: relative;
144
+ overflow: hidden;
145
+ `;
146
+
147
+ // 添加PDF图标
148
+ triggerButton.innerHTML = `
149
+ <div style="
150
+ color: white;
151
+ font-size: 20px;
152
+ font-weight: bold;
153
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
154
+ ">PDF</div>
155
+ <div style="
156
+ position: absolute;
157
+ width: 100%;
158
+ height: 100%;
159
+ border-radius: 50%;
160
+ border: 2px solid rgba(94, 234, 212, 0.4);
161
+ animation: pulse 2s infinite;
162
+ "></div>
163
+ `;
164
+
165
+ // 添加脉冲动画样式
166
+ const style = document.createElement('style');
167
+ style.textContent = `
168
+ @keyframes pulse {
169
+ 0% {
170
+ transform: scale(1);
171
+ opacity: 0.8;
172
+ }
173
+ 70% {
174
+ transform: scale(1.1);
175
+ opacity: 0;
176
+ }
177
+ 100% {
178
+ transform: scale(1);
179
+ opacity: 0;
180
+ }
181
+ }
182
+ #select-element-btn:hover, #generate-pdf-btn:not([disabled]):hover, #close-panel-btn:hover {
183
+ transform: translateY(-2px);
184
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3);
185
+ filter: brightness(1.1);
186
+ }
187
+ #html2pdf-trigger-button:hover {
188
+ transform: scale(1.05);
189
+ box-shadow: 0 4px 20px rgba(58, 134, 255, 0.6), 0 0 30px rgba(58, 134, 255, 0.4);
190
+ }
191
+ .html2pdf-highlight {
192
+ outline: 3px solid #5EEAD4 !important;
193
+ outline-offset: 2px !important;
194
+ box-shadow: 0 0 15px rgba(94, 234, 212, 0.4) !important;
195
+ }
196
+ `;
197
+ document.head.appendChild(style);
198
+
199
+ // 将触发按钮和面板内容添加到主面板
200
+ panel.appendChild(triggerButton);
201
+ panel.appendChild(panelContent);
202
+ document.body.appendChild(panel);
203
+
204
+ // 添加触发按钮点击事件
205
+ triggerButton.addEventListener('click', () => {
206
+ const content = document.getElementById('html2pdf-panel-content');
207
+ if (content.style.display === 'none') {
208
+ content.style.display = 'block';
209
+ triggerButton.style.transform = 'scale(0.9)';
210
+ } else {
211
+ content.style.display = 'none';
212
+ triggerButton.style.transform = 'scale(1)';
213
+ }
214
+ });
215
+
216
+ return panel;
217
+ }
218
+
219
+ // 创建选择覆盖层
220
+ function createOverlay() {
221
+ const overlay = document.createElement('div');
222
+ overlay.id = 'html2pdf-overlay';
223
+ overlay.style.cssText = `
224
+ position: fixed;
225
+ top: 0;
226
+ left: 0;
227
+ width: 100%;
228
+ height: 100%;
229
+ background: rgba(0, 123, 186, 0.1);
230
+ z-index: 9999;
231
+ cursor: crosshair;
232
+ pointer-events: none;
233
+ `;
234
+ document.body.appendChild(overlay);
235
+ return overlay;
236
+ }
237
+
238
+ // 高亮元素
239
+ function highlightElement(element) {
240
+ // 移除之前的高亮
241
+ const prevHighlight = document.querySelector('.html2pdf-highlight');
242
+ if (prevHighlight) {
243
+ prevHighlight.classList.remove('html2pdf-highlight');
244
+ }
245
+
246
+ // 添加高亮样式
247
+ if (element && element !== document.body) {
248
+ element.classList.add('html2pdf-highlight');
249
+
250
+ // 添加高亮CSS
251
+ if (!document.querySelector('#html2pdf-highlight-style')) {
252
+ const style = document.createElement('style');
253
+ style.id = 'html2pdf-highlight-style';
254
+ // style.textContent = `
255
+ // .html2pdf-highlight {
256
+ // outline: 3px solid #007cba !important;
257
+ // outline-offset: 2px !important;
258
+ // }
259
+ // `;
260
+ document.head.appendChild(style);
261
+ }
262
+ }
263
+ }
264
+
265
+ // 高亮元素
266
+ function highlightElement(element) {
267
+ // 移除之前的高亮
268
+ const prevHighlight = document.querySelector('.html2pdf-highlight');
269
+ if (prevHighlight) {
270
+ prevHighlight.classList.remove('html2pdf-highlight');
271
+ }
272
+
273
+ // 添加高亮样式
274
+ if (element && element !== document.body) {
275
+ element.classList.add('html2pdf-highlight');
276
+
277
+ // 添加高亮CSS
278
+ if (!document.querySelector('#html2pdf-highlight-style')) {
279
+ const style = document.createElement('style');
280
+ style.id = 'html2pdf-highlight-style';
281
+ style.textContent = `
282
+ .html2pdf-highlight {
283
+ outline: 3px solid #007cba !important;
284
+ outline-offset: 2px !important;
285
+
286
+ }
287
+ `;
288
+ document.head.appendChild(style);
289
+ }
290
+ }
291
+ }
292
+
293
+ // 开始选择模式
294
+ function startSelection() {
295
+ isSelecting = true;
296
+ overlay = createOverlay();
297
+ document.body.style.cursor = 'crosshair';
298
+
299
+ // 更新按钮状态
300
+ const selectBtn = document.getElementById('select-element-btn');
301
+ selectBtn.textContent = '取消选择';
302
+ selectBtn.style.background = '#dc3545';
303
+
304
+ // 添加事件监听
305
+ document.addEventListener('mouseover', onMouseOver);
306
+ document.addEventListener('click', onElementClick);
307
+ document.addEventListener('keydown', onKeyDown);
308
+ }
309
+
310
+ // 停止选择模式
311
+ function stopSelection() {
312
+ isSelecting = false;
313
+ document.body.style.cursor = '';
314
+
315
+ if (overlay) {
316
+ overlay.remove();
317
+ overlay = null;
318
+ }
319
+
320
+ // 更新按钮状态
321
+ const selectBtn = document.getElementById('select-element-btn');
322
+ selectBtn.textContent = '选择元素';
323
+ selectBtn.style.background = 'linear-gradient(90deg, #4cc9f0, #4361ee)';
324
+
325
+ // 移除事件监听
326
+ document.removeEventListener('mouseover', onMouseOver);
327
+ document.removeEventListener('click', onElementClick);
328
+ document.removeEventListener('keydown', onKeyDown);
329
+ }
330
+
331
+ // 鼠标悬停事件
332
+ function onMouseOver(e) {
333
+ if (!isSelecting) return;
334
+ e.preventDefault();
335
+
336
+ const element = e.target;
337
+ if (element !== controlPanel && !controlPanel.contains(element)) {
338
+ highlightElement(element);
339
+ }
340
+ }
341
+
342
+ // 元素点击事件
343
+ function onElementClick(e) {
344
+ if (!isSelecting) return;
345
+ e.preventDefault();
346
+ e.stopPropagation();
347
+
348
+ const element = e.target;
349
+ if (element !== controlPanel && !controlPanel.contains(element)) {
350
+ selectedElement = element;
351
+ stopSelection();
352
+ updateSelectedInfo(element);
353
+ enablePdfGeneration();
354
+ }
355
+ }
356
+
357
+ // 键盘事件(ESC取消选择)
358
+ function onKeyDown(e) {
359
+ if (e.key === 'Escape' && isSelecting) {
360
+ stopSelection();
361
+ }
362
+ }
363
+
364
+ // 更新选中元素信息
365
+ function updateSelectedInfo(element) {
366
+ const info = document.getElementById('selected-info');
367
+ const tagName = element.tagName.toLowerCase();
368
+ const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
369
+ const id = element.id ? `#${element.id}` : '';
370
+
371
+ // info.innerHTML = `
372
+ // <strong>已选择元素:</strong><br>
373
+ // 标签: ${tagName}${id}${className}<br>
374
+ // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
375
+ // ${element.parentElement && element.parentElement !== document.body ?
376
+ // `<button id="select-parent-btn" style="
377
+ // margin-top: 8px;
378
+ // padding: 4px 8px;
379
+ // background: linear-gradient(90deg, #5E60CE, #7209B7);
380
+ // color: white;
381
+ // border: none;
382
+ // border-radius: 4px;
383
+ // cursor: pointer;
384
+ // font-size: 12px;
385
+ // box-shadow: 0 2px 6px rgba(94, 96, 206, 0.4);
386
+ // transition: all 0.2s ease;
387
+ // display: block;
388
+ // width: 100%;
389
+ // ">选择父元素</button>` :
390
+ // ''
391
+ // }
392
+ // `;
393
+ info.style.display = 'block';
394
+
395
+ // 如果有父元素且不是body,添加选择父元素按钮事件
396
+ // if (element.parentElement && element.parentElement !== document.body) {
397
+ // document.getElementById('select-parent-btn').addEventListener('click', () => {
398
+ // selectParentElement(element);
399
+ // });
400
+ // }
401
+ }
402
+
403
+ // 选择父元素
404
+ // function selectParentElement(element) {
405
+ // if (element && element.parentElement && element.parentElement !== document.body) {
406
+ // // 更新选中元素为父元素
407
+ // selectedElement = element.parentElement;
408
+
409
+ // // 高亮显示父元素
410
+ // highlightElement(selectedElement);
411
+
412
+ // // 更新选中信息
413
+ // updateSelectedInfo(selectedElement);
414
+ // }
415
+ // }
416
+
417
+ // 启用PDF生成按钮
418
+ function enablePdfGeneration() {
419
+ const pdfBtn = document.getElementById('generate-pdf-btn');
420
+ pdfBtn.disabled = false;
421
+ pdfBtn.style.opacity = '1';
422
+ }
423
+
424
+ // 生成PDF
425
+ async function generatePDF() {
426
+ if (!selectedElement) {
427
+ alert('请先选择要转换的元素');
428
+ return;
429
+ }
430
+
431
+ try {
432
+ // 显示加载状态
433
+ const pdfBtn = document.getElementById('generate-pdf-btn');
434
+ const originalText = pdfBtn.textContent;
435
+ pdfBtn.textContent = '生成中...';
436
+ pdfBtn.disabled = true;
437
+
438
+ // 使用html2canvas截图
439
+ html2pdf(selectedElement, {
440
+ useCORS: true,
441
+ scale: 1,
442
+ fontConfig: {
443
+ fontFamily: 'SourceHanSansCN-Medium',
444
+ fontBase64: window.fontBase64, //
445
+ fontUrl: '',
446
+ fontWeight: 400,
447
+ fontStyle: 'normal'
448
+ },
449
+ }).then(function (canvas) {
450
+ const link = document.createElement('a');
451
+ link.download = 'output.png';
452
+ link.href = canvas.toDataURL('image/png');
453
+ link.click();
454
+ // 恢复按钮状态
455
+ pdfBtn.textContent = originalText;
456
+ pdfBtn.disabled = false;
457
+
458
+ alert('PDF生成成功!');
459
+ }).catch(function (err) {
460
+ console.log('creacterr', err);
461
+
462
+ });;
463
+
464
+
465
+
466
+
467
+
468
+ } catch (error) {
469
+ console.error('PDF生成失败:', error);
470
+ alert('PDF生成失败,请检查控制台错误信息');
471
+
472
+ // 恢复按钮状态
473
+ const pdfBtn = document.getElementById('generate-pdf-btn');
474
+ pdfBtn.textContent = '生成PDF';
475
+ pdfBtn.disabled = false;
476
+ }
477
+ }
478
+
479
+
480
+ // 关闭面板
481
+ function closePanel() {
482
+ if (isSelecting) {
483
+ stopSelection();
484
+ }
485
+
486
+ // 移除高亮
487
+ const highlight = document.querySelector('.html2pdf-highlight');
488
+ if (highlight) {
489
+ highlight.classList.remove('html2pdf-highlight');
490
+ }
491
+
492
+ // 移除样式
493
+ const style = document.querySelector('#html2pdf-highlight-style');
494
+ if (style) {
495
+ style.remove();
496
+ }
497
+
498
+ // 移除面板
499
+ if (controlPanel) {
500
+ controlPanel.remove();
501
+ controlPanel = null;
502
+ }
503
+
504
+ selectedElement = null;
505
+ }
506
+
507
+ // 初始化
508
+ function init() {
509
+ // 等待页面加载完成
510
+ if (document.readyState === 'loading') {
511
+ document.addEventListener('DOMContentLoaded', init);
512
+ return;
513
+ }
514
+
515
+ // 创建控制面板
516
+ controlPanel = createControlPanel();
517
+
518
+ // 绑定事件
519
+ document.getElementById('select-element-btn').addEventListener('click', () => {
520
+ if (isSelecting) {
521
+ stopSelection();
522
+ } else {
523
+ startSelection();
524
+ }
525
+ });
526
+
527
+ document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
528
+ document.getElementById('close-panel-btn').addEventListener('click', closePanel);
529
+
530
+ // 让面板可拖拽
531
+ let isDragging = false;
532
+ let dragOffset = {
533
+ x: 0,
534
+ y: 0
535
+ };
536
+
537
+ controlPanel.addEventListener('mousedown', (e) => {
538
+ if (e.target.tagName !== 'BUTTON') {
539
+ isDragging = true;
540
+ dragOffset.x = e.clientX - controlPanel.offsetLeft;
541
+ dragOffset.y = e.clientY - controlPanel.offsetTop;
542
+ controlPanel.style.cursor = 'move';
543
+ }
544
+ });
545
+
546
+ document.addEventListener('mousemove', (e) => {
547
+ if (isDragging) {
548
+ controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
549
+ controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
550
+ controlPanel.style.right = 'auto';
551
+ }
552
+ });
553
+
554
+ document.addEventListener('mouseup', () => {
555
+ isDragging = false;
556
+ controlPanel.style.cursor = '';
557
+ });
558
+
559
+ console.log('HTML2PDF 用户脚本已加载');
560
+ }
561
+
562
+ // 启动脚本
563
+ init();
564
+
565
+ })();
566
+
567
+
568
+
569
+ // (function () {
570
+ // 'use strict';
571
+
572
+ // // 全局变量
573
+ // let isSelecting = false;
574
+ // let selectedElement = null;
575
+ // let overlay = null;
576
+ // let controlPanel = null;
577
+
578
+ // // 创建控制面板
579
+ // function createControlPanel() {
580
+ // const panel = document.createElement('div');
581
+ // panel.id = 'dompdf-control-panel';
582
+ // panel.style.cssText = `
583
+ // position: fixed;
584
+ // top: 20px;
585
+ // right: 20px;
586
+ // z-index: 10000;
587
+ // background: #fff;
588
+ // border: 2px solid #007cba;
589
+ // border-radius: 8px;
590
+ // padding: 15px;
591
+ // box-shadow: 0 4px 12px rgba(0,0,0,0.15);
592
+ // font-family: Arial, sans-serif;
593
+ // min-width: 200px;
594
+ // `;
595
+
596
+ // panel.innerHTML = `
597
+ // <div style="margin-bottom: 10px; font-weight: bold; color: #333;">dompdf 工具</div>
598
+ // <button id="select-element-btn" style="
599
+ // width: 100%;
600
+ // padding: 8px 12px;
601
+ // margin-bottom: 8px;
602
+ // background: #007cba;
603
+ // color: white;
604
+ // border: none;
605
+ // border-radius: 4px;
606
+ // cursor: pointer;
607
+ // font-size: 14px;
608
+ // ">选择元素</button>
609
+ // <button id="generate-pdf-btn" style="
610
+ // width: 100%;
611
+ // padding: 8px 12px;
612
+ // margin-bottom: 8px;
613
+ // background: #28a745;
614
+ // color: white;
615
+ // border: none;
616
+ // border-radius: 4px;
617
+ // cursor: pointer;
618
+ // font-size: 14px;
619
+ // opacity: 0.5;
620
+ // margin-left:0
621
+ // " disabled>生成PDF</button>
622
+ // <button id="close-panel-btn" style="
623
+ // width: 100%;
624
+ // padding: 6px 12px;
625
+ // background: #dc3545;
626
+ // color: white;
627
+ // border: none;
628
+ // border-radius: 4px;
629
+ // cursor: pointer;
630
+ // font-size: 12px;
631
+ // margin - left: 0
632
+ // ">关闭</button>
633
+ // <div id="selected-info" style="
634
+ // margin-top: 10px;
635
+ // padding: 8px;
636
+ // background: #f8f9fa;
637
+ // border-radius: 4px;
638
+ // font-size: 12px;
639
+ // color: #666;
640
+ // display: none;
641
+ // "></div>
642
+ // `;
643
+
644
+ // document.body.appendChild(panel);
645
+ // return panel;
646
+ // }
647
+
648
+ // // 创建选择覆盖层
649
+ // function createOverlay() {
650
+ // const overlay = document.createElement('div');
651
+ // overlay.id = 'dompdf-overlay';
652
+ // overlay.style.cssText = `
653
+ // position: fixed;
654
+ // top: 0;
655
+ // left: 0;
656
+ // width: 100%;
657
+ // height: 100%;
658
+ // background: rgba(0, 123, 186, 0.1);
659
+ // z-index: 9999;
660
+ // cursor: crosshair;
661
+ // pointer-events: none;
662
+ // `;
663
+ // document.body.appendChild(overlay);
664
+ // return overlay;
665
+ // }
666
+
667
+ // // 高亮元素
668
+ // function highlightElement(element) {
669
+ // // 移除之前的高亮
670
+ // const prevHighlight = document.querySelector('.dompdf-highlight');
671
+ // if (prevHighlight) {
672
+ // prevHighlight.classList.remove('dompdf-highlight');
673
+ // }
674
+
675
+ // // 添加高亮样式
676
+ // if (element && element !== document.body) {
677
+ // element.classList.add('dompdf-highlight');
678
+
679
+ // // 添加高亮CSS
680
+ // if (!document.querySelector('#dompdf-highlight-style')) {
681
+ // const style = document.createElement('style');
682
+ // style.id = 'dompdf-highlight-style';
683
+ // style.textContent = `
684
+ // .dompdf-highlight {
685
+ // outline: 3px solid #007cba !important;
686
+ // outline-offset: 2px !important;
687
+
688
+ // }
689
+ // `;
690
+ // document.head.appendChild(style);
691
+ // }
692
+ // }
693
+ // }
694
+
695
+ // // 开始选择模式
696
+ // function startSelection() {
697
+ // isSelecting = true;
698
+ // overlay = createOverlay();
699
+ // document.body.style.cursor = 'crosshair';
700
+
701
+ // // 更新按钮状态
702
+ // const selectBtn = document.getElementById('select-element-btn');
703
+ // selectBtn.textContent = '取消选择';
704
+ // selectBtn.style.background = '#dc3545';
705
+
706
+ // // 添加事件监听
707
+ // document.addEventListener('mouseover', onMouseOver);
708
+ // document.addEventListener('click', onElementClick);
709
+ // document.addEventListener('keydown', onKeyDown);
710
+ // }
711
+
712
+ // // 停止选择模式
713
+ // function stopSelection() {
714
+ // isSelecting = false;
715
+ // document.body.style.cursor = '';
716
+
717
+ // if (overlay) {
718
+ // overlay.remove();
719
+ // overlay = null;
720
+ // }
721
+
722
+ // // 更新按钮状态
723
+ // const selectBtn = document.getElementById('select-element-btn');
724
+ // selectBtn.textContent = '选择元素';
725
+ // selectBtn.style.background = '#007cba';
726
+
727
+ // // 移除事件监听
728
+ // document.removeEventListener('mouseover', onMouseOver);
729
+ // document.removeEventListener('click', onElementClick);
730
+ // document.removeEventListener('keydown', onKeyDown);
731
+ // }
732
+
733
+ // // 鼠标悬停事件
734
+ // function onMouseOver(e) {
735
+ // if (!isSelecting) return;
736
+ // e.preventDefault();
737
+
738
+ // const element = e.target;
739
+ // if (element !== controlPanel && !controlPanel.contains(element)) {
740
+ // highlightElement(element);
741
+ // }
742
+ // }
743
+
744
+ // // 元素点击事件
745
+ // function onElementClick(e) {
746
+ // if (!isSelecting) return;
747
+ // e.preventDefault();
748
+ // e.stopPropagation();
749
+
750
+ // const element = e.target;
751
+ // if (element !== controlPanel && !controlPanel.contains(element)) {
752
+ // selectedElement = element;
753
+ // stopSelection();
754
+ // updateSelectedInfo(element);
755
+ // enablePdfGeneration();
756
+ // }
757
+ // }
758
+
759
+ // // 键盘事件(ESC取消选择)
760
+ // function onKeyDown(e) {
761
+ // if (e.key === 'Escape' && isSelecting) {
762
+ // stopSelection();
763
+ // }
764
+ // }
765
+
766
+ // // 更新选中元素信息
767
+ // function updateSelectedInfo(element) {
768
+ // const info = document.getElementById('selected-info');
769
+ // const tagName = element.tagName.toLowerCase();
770
+ // const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
771
+ // const id = element.id ? `#${element.id}` : '';
772
+
773
+ // info.innerHTML = `
774
+ // <strong>已选择元素:</strong><br>
775
+ // 标签: ${tagName}${id}${className}<br>
776
+ // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
777
+ // `;
778
+ // info.style.display = 'block';
779
+ // }
780
+
781
+ // // 启用PDF生成按钮
782
+ // function enablePdfGeneration() {
783
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
784
+ // pdfBtn.disabled = false;
785
+ // pdfBtn.style.opacity = '1';
786
+ // }
787
+
788
+ // // 生成PDF
789
+ // async function generatePDF() {
790
+ // if (!selectedElement) {
791
+ // alert('请先选择要转换的元素');
792
+ // return;
793
+ // }
794
+
795
+ // try {
796
+ // // 显示加载状态
797
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
798
+ // const originalText = pdfBtn.textContent;
799
+ // pdfBtn.textContent = '生成中...';
800
+ // pdfBtn.disabled = true;
801
+
802
+ // // 使用html2canvas截图
803
+ // dompdf(selectedElement, {
804
+ // useCORS: true,
805
+ // scale: 1,
806
+ // fontConfig: {
807
+ // fontFamily: 'SourceHanSansCN-Medium',
808
+ // fontBase64: window.fontBase64, //
809
+ // fontUrl: '',
810
+ // fontWeight: 400,
811
+ // fontStyle: 'normal'
812
+ // },
813
+ // }).then(function (blob) {
814
+ // const url = URL.createObjectURL(blob);
815
+ // const a = document.createElement('a');
816
+ // a.href = url;
817
+ // a.download = "example.pdf";
818
+ // document.body.appendChild(a);
819
+ // a.click();
820
+
821
+ // // 清理
822
+ // setTimeout(() => {
823
+ // document.body.removeChild(a);
824
+ // URL.revokeObjectURL(url);
825
+ // }, 100);
826
+ // // 恢复按钮状态
827
+ // pdfBtn.textContent = originalText;
828
+ // pdfBtn.disabled = false;
829
+
830
+ // alert('PDF生成成功!');
831
+ // }).catch(function (err) {
832
+ // console.log('creacterr', err);
833
+
834
+ // });;
835
+
836
+
837
+
838
+
839
+
840
+ // } catch (error) {
841
+ // console.error('PDF生成失败:', error);
842
+ // alert('PDF生成失败,请检查控制台错误信息');
843
+
844
+ // // 恢复按钮状态
845
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
846
+ // pdfBtn.textContent = '生成PDF';
847
+ // pdfBtn.disabled = false;
848
+ // }
849
+ // }
850
+
851
+ // // 关闭面板
852
+ // function closePanel() {
853
+ // if (isSelecting) {
854
+ // stopSelection();
855
+ // }
856
+
857
+ // // 移除高亮
858
+ // const highlight = document.querySelector('.dompdf-highlight');
859
+ // if (highlight) {
860
+ // highlight.classList.remove('dompdf-highlight');
861
+ // }
862
+
863
+ // // 移除样式
864
+ // const style = document.querySelector('#dompdf-highlight-style');
865
+ // if (style) {
866
+ // style.remove();
867
+ // }
868
+
869
+ // // 移除面板
870
+ // if (controlPanel) {
871
+ // controlPanel.remove();
872
+ // controlPanel = null;
873
+ // }
874
+
875
+ // selectedElement = null;
876
+ // }
877
+
878
+ // // 初始化
879
+ // function init() {
880
+ // // 等待页面加载完成
881
+ // if (document.readyState === 'loading') {
882
+ // document.addEventListener('DOMContentLoaded', init);
883
+ // return;
884
+ // }
885
+
886
+ // // 创建控制面板
887
+ // controlPanel = createControlPanel();
888
+
889
+ // // 绑定事件
890
+ // document.getElementById('select-element-btn').addEventListener('click', () => {
891
+ // if (isSelecting) {
892
+ // stopSelection();
893
+ // } else {
894
+ // startSelection();
895
+ // }
896
+ // });
897
+
898
+ // document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
899
+ // document.getElementById('close-panel-btn').addEventListener('click', closePanel);
900
+
901
+ // // 让面板可拖拽
902
+ // let isDragging = false;
903
+ // let dragOffset = {
904
+ // x: 0,
905
+ // y: 0
906
+ // };
907
+
908
+ // controlPanel.addEventListener('mousedown', (e) => {
909
+ // if (e.target.tagName !== 'BUTTON') {
910
+ // isDragging = true;
911
+ // dragOffset.x = e.clientX - controlPanel.offsetLeft;
912
+ // dragOffset.y = e.clientY - controlPanel.offsetTop;
913
+ // controlPanel.style.cursor = 'move';
914
+ // }
915
+ // });
916
+
917
+ // document.addEventListener('mousemove', (e) => {
918
+ // if (isDragging) {
919
+ // controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
920
+ // controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
921
+ // controlPanel.style.right = 'auto';
922
+ // }
923
+ // });
924
+
925
+ // document.addEventListener('mouseup', () => {
926
+ // isDragging = false;
927
+ // controlPanel.style.cursor = '';
928
+ // });
929
+
930
+ // console.log('dompdf 用户脚本已加载');
931
+ // }
932
+
933
+ // // 启动脚本
934
+ // init();
935
+
936
936
  // })();