新增图片生成pdf小工具

This commit is contained in:
Guarp 2025-04-14 14:43:48 +08:00
parent 2cdc8c99d1
commit 7ad837cf42
10 changed files with 858 additions and 4 deletions

359
package-lock.json generated
View File

@ -19,6 +19,7 @@
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"marked": "^15.0.7", "marked": "^15.0.7",
"mermaid": "^11.4.1", "mermaid": "^11.4.1",
"pdfmake": "^0.2.18",
"sweetalert2": "^11.16.0", "sweetalert2": "^11.16.0",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
@ -582,6 +583,47 @@
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="
}, },
"node_modules/@foliojs-fork/fontkit": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.2.tgz",
"integrity": "sha512-IfB5EiIb+GZk+77TRB86AHroVaqfq8JRFlUbz0WEwsInyCG0epX2tCPOy+UfaWPju30DeVoUAXfzWXmhn753KA==",
"dependencies": {
"@foliojs-fork/restructure": "^2.0.2",
"brotli": "^1.2.0",
"clone": "^1.0.4",
"deep-equal": "^1.0.0",
"dfa": "^1.2.0",
"tiny-inflate": "^1.0.2",
"unicode-properties": "^1.2.2",
"unicode-trie": "^2.0.0"
}
},
"node_modules/@foliojs-fork/linebreak": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.2.tgz",
"integrity": "sha512-ZPohpxxbuKNE0l/5iBJnOAfUaMACwvUIKCvqtWGKIMv1lPYoNjYXRfhi9FeeV9McBkBLxsMFWTVVhHJA8cyzvg==",
"dependencies": {
"base64-js": "1.3.1",
"unicode-trie": "^2.0.0"
}
},
"node_modules/@foliojs-fork/pdfkit": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/@foliojs-fork/pdfkit/-/pdfkit-0.15.3.tgz",
"integrity": "sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==",
"dependencies": {
"@foliojs-fork/fontkit": "^1.9.2",
"@foliojs-fork/linebreak": "^1.1.1",
"crypto-js": "^4.2.0",
"jpeg-exif": "^1.1.4",
"png-js": "^1.0.0"
}
},
"node_modules/@foliojs-fork/restructure": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@foliojs-fork/restructure/-/restructure-2.0.2.tgz",
"integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA=="
},
"node_modules/@iconify/types": { "node_modules/@iconify/types": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
@ -1835,6 +1877,11 @@
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
} }
}, },
"node_modules/base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@ -1859,6 +1906,31 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/brotli": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
"integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
"dependencies": {
"base64-js": "^1.1.2"
}
},
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/call-bind-apply-helpers": { "node_modules/call-bind-apply-helpers": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@ -1871,6 +1943,21 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chevrotain": { "node_modules/chevrotain": {
"version": "11.0.3", "version": "11.0.3",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz",
@ -1919,6 +2006,14 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -1956,6 +2051,11 @@
"layout-base": "^1.0.0" "layout-base": "^1.0.0"
} }
}, },
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@ -2451,6 +2551,57 @@
} }
} }
}, },
"node_modules/deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"dependencies": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delaunator": { "node_modules/delaunator": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
@ -2480,6 +2631,11 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/dfa": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
"integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q=="
},
"node_modules/diff": { "node_modules/diff": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
@ -2898,6 +3054,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/functions-have-names": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@ -2972,6 +3136,17 @@
"resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz",
"integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==" "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="
}, },
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": { "node_modules/has-symbols": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@ -3059,6 +3234,21 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-binary-path": { "node_modules/is-binary-path": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@ -3071,6 +3261,21 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-date-object": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -3114,11 +3319,33 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-url": { "node_modules/is-url": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
}, },
"node_modules/jpeg-exif": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz",
"integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ=="
},
"node_modules/jquery": { "node_modules/jquery": {
"version": "3.7.1", "version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
@ -3466,6 +3693,29 @@
"resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
}, },
"node_modules/object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/package-manager-detector": { "node_modules/package-manager-detector": {
"version": "0.2.11", "version": "0.2.11",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
@ -3474,6 +3724,11 @@
"quansync": "^0.2.7" "quansync": "^0.2.7"
} }
}, },
"node_modules/pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
"integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
},
"node_modules/path-data-parser": { "node_modules/path-data-parser": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz",
@ -3484,6 +3739,20 @@
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="
}, },
"node_modules/pdfmake": {
"version": "0.2.18",
"resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.18.tgz",
"integrity": "sha512-Fe+GnMS8EVZu5rci/CDaQ+xmUoHvx8P+rvIlrwSYM6A5c7Aik8G6lpJbddhjBE2jXGjv6WcUCFCB06uZbjxkMw==",
"dependencies": {
"@foliojs-fork/linebreak": "^1.1.2",
"@foliojs-fork/pdfkit": "^0.15.3",
"iconv-lite": "^0.6.3",
"xmldoc": "^1.3.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -3511,6 +3780,11 @@
"pathe": "^2.0.3" "pathe": "^2.0.3"
} }
}, },
"node_modules/png-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
"integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g=="
},
"node_modules/points-on-curve": { "node_modules/points-on-curve": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz",
@ -3618,6 +3892,25 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
}, },
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
"es-errors": "^1.3.0",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"set-function-name": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/robust-predicates": { "node_modules/robust-predicates": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
@ -3730,6 +4023,11 @@
"url": "https://paulmillr.com/funding/" "url": "https://paulmillr.com/funding/"
} }
}, },
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
},
"node_modules/scroll-into-view-if-needed": { "node_modules/scroll-into-view-if-needed": {
"version": "2.2.31", "version": "2.2.31",
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
@ -3744,6 +4042,36 @@
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"dev": true "dev": true
}, },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/set-function-name": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/slate": { "node_modules/slate": {
"version": "0.72.8", "version": "0.72.8",
"resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz",
@ -3812,6 +4140,11 @@
"url": "https://github.com/sponsors/limonte" "url": "https://github.com/sponsors/limonte"
} }
}, },
"node_modules/tiny-inflate": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
},
"node_modules/tiny-warning": { "node_modules/tiny-warning": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
@ -3868,6 +4201,24 @@
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==" "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="
}, },
"node_modules/unicode-properties": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
"integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
"dependencies": {
"base64-js": "^1.3.0",
"unicode-trie": "^2.0.0"
}
},
"node_modules/unicode-trie": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
"integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
"dependencies": {
"pako": "^0.2.5",
"tiny-inflate": "^1.0.0"
}
},
"node_modules/unimport": { "node_modules/unimport": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-4.1.2.tgz", "resolved": "https://registry.npmjs.org/unimport/-/unimport-4.1.2.tgz",
@ -4196,6 +4547,14 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
"integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==" "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
},
"node_modules/xmldoc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.3.0.tgz",
"integrity": "sha512-y7IRWW6PvEnYQZNZFMRLNJw+p3pezM4nKYPfr15g4OOW9i8VpeydycFuipE2297OvZnh3jSb2pxOt9QpkZUVng==",
"dependencies": {
"sax": "^1.2.4"
}
} }
} }
} }

View File

@ -20,6 +20,7 @@
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"marked": "^15.0.7", "marked": "^15.0.7",
"mermaid": "^11.4.1", "mermaid": "^11.4.1",
"pdfmake": "^0.2.18",
"sweetalert2": "^11.16.0", "sweetalert2": "^11.16.0",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",

2
public/libs/Sortable.min.js vendored Normal file

File diff suppressed because one or more lines are too long

16
public/libs/pdf-lib.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,212 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片转PDF</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
margin: 0;
background-color: #f4f4f4;
}
h1 {
font-size: 2.5vw;
margin-bottom: 20px;
color: #333;
}
#image-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
margin: 20px 0;
padding: 10px;
border: 2px dashed #ccc;
background-color: #fff;
min-height: 100px;
width: 100%;
max-width: 1200px;
}
.image-item {
position: relative;
border: 1px solid #ccc;
overflow: hidden;
transition: transform 0.2s;
cursor: move; /* 提示用户可以拖拽 */
}
.image-item:hover {
transform: scale(1.05);
}
.image-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.delete-btn {
position: absolute;
top: 5px;
right: 5px;
background-color: rgb(0, 0, 0);
opacity: 0.5;
color: white;
margin: 0;
border: none;
border-radius: 50%;
width: 20px;
height: 20px;
padding: 0;
font-size: 12px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
}
button:hover {
background-color: #0056b3;
}
@media (max-width: 600px) {
h1 {
font-size: 5vw;
}
button {
font-size: 14px;
padding: 8px 16px;
}
}
</style>
</head>
<body>
<h1>图片转PDF</h1>
<input type="file" id="file-input" multiple accept="image/*">
<div id="image-container"></div>
<button id="generate-pdf">生成PDF</button>
<!-- 引入外部库 -->
<script src="../../../libs/Sortable.min.js"></script>
<script src="../../../libs/pdf-lib.min.js"></script>
<script>
const fileInput = document.getElementById('file-input');
const imageContainer = document.getElementById('image-container');
const generateButton = document.getElementById('generate-pdf');
let images = [];
// 文件选择事件
fileInput.addEventListener('change', (e) => {
handleFiles(e.target.files);
});
// 生成PDF
generateButton.addEventListener('click', async () => {
if (images.length === 0) {
alert('请先添加至少一张图片!');
return;
}
const pdfDoc = await PDFLib.PDFDocument.create();
for (const image of images) {
const imgBytes = await fetch(image.src).then(res => res.arrayBuffer());
let img = image.file.type === 'image/png' ?
await pdfDoc.embedPng(imgBytes) :
await pdfDoc.embedJpg(imgBytes);
const page = pdfDoc.addPage([img.width, img.height]);
page.drawImage(img, { x: 0, y: 0, width: img.width, height: img.height });
}
const pdfBytes = await pdfDoc.save();
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '图片合集.pdf';
a.click();
URL.revokeObjectURL(url);
});
// 处理文件
function handleFiles(files) {
Array.from(files).forEach(file => {
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = function(e) {
const imgWrapper = document.createElement('div');
imgWrapper.classList.add('image-item');
const img = document.createElement('img');
img.src = e.target.result;
const deleteBtn = document.createElement('button');
deleteBtn.classList.add('delete-btn');
deleteBtn.innerHTML = '×';
deleteBtn.addEventListener('click', () => {
imgWrapper.remove();
images = images.filter(item => item.src !== img.src);
});
imgWrapper.appendChild(img);
imgWrapper.appendChild(deleteBtn);
imageContainer.appendChild(imgWrapper);
images.push({ src: e.target.result, file });
setImageSize();
};
reader.readAsDataURL(file);
}
});
}
// 获取视口宽度
function getViewportWidth() {
return window.innerWidth || document.documentElement.clientWidth;
}
// 设置图片尺寸
function setImageSize() {
const viewportWidth = getViewportWidth();
const imageItems = document.querySelectorAll('.image-item');
let size = viewportWidth >= 1200 ? 150 : viewportWidth >= 600 ? 100 : 80;
imageItems.forEach(item => {
item.style.width = `${size}px`;
item.style.height = `${size}px`;
});
}
// 监听窗口resize事件
window.addEventListener('resize', setImageSize);
setImageSize();
// 拖拽导入支持
imageContainer.addEventListener('dragover', (e) => {
e.preventDefault();
});
imageContainer.addEventListener('drop', (e) => {
e.preventDefault();
if (e.dataTransfer.files.length > 0) {
handleFiles(e.dataTransfer.files);
}
});
// 初始化 Sortable.js 进行拖拽排序
new Sortable(imageContainer, {
animation: 150,
onEnd: function(evt) {
// 更新 images 数组顺序
const movedItem = images.splice(evt.oldIndex, 1)[0];
images.splice(evt.newIndex, 0, movedItem);
}
});
</script>
</body>
</html>

View File

@ -14,6 +14,7 @@ const tools = ref([
{ id: 1, title: 'GPA在线计算器', description: '手动输入在线算', image: null, category: ['计算'] }, { id: 1, title: 'GPA在线计算器', description: '手动输入在线算', image: null, category: ['计算'] },
{ id: 2, title: 'PDF页面提取器', description: '提取指定页和封面', image: null, category: ['提取', 'pdf'] }, { id: 2, title: 'PDF页面提取器', description: '提取指定页和封面', image: null, category: ['提取', 'pdf'] },
{ id: 3, title: '请求测试器', description: '自定义请求测试', image: null, category: ['开发', '网络'] }, { id: 3, title: '请求测试器', description: '自定义请求测试', image: null, category: ['开发', '网络'] },
{ id: 4, title: '图片转PDF', description: '导入图片生成pdf', image: null, category: ['pdf', '生成'] },
]); ]);
onMounted(() => { onMounted(() => {

View File

@ -0,0 +1,235 @@
<template>
<div class="quiz-review-container">
<!-- 加载中提示 -->
<div v-if="isLoading" class="loading">加载中...</div>
<!-- 当前题目 -->
<div v-else class="question-container">
<h2>题目 {{ currentIndex + 1 }}</h2>
<QuestionText :text="currentQuestion.text" :medias="data.medias" />
<div class="options">
<div v-for="(answer, idx) in currentQuestion.answers.slice(1)" :key="idx" class="option">
<label :class="{ 'correct': idx === correctIndex }">
<input type="radio" :value="idx" disabled />
<general-renderer :content-input="processMedia(answer, data.medias)"></general-renderer>
</label>
</div>
</div>
<!-- 解析 -->
<div v-if="currentQuestion.explanation" class="explanation">
<h3>解题思路</h3>
<general-renderer :content-input="processMedia(currentQuestion.explanation, data.medias)"></general-renderer>
</div>
<!-- 导航按钮 -->
<div class="navigation">
<button v-if="currentIndex > 0" @click="prevQuestion" class="nav-btn">上一题</button>
<button v-if="currentIndex < totalQuestions - 1" @click="nextQuestion" class="nav-btn">下一题</button>
</div>
<!-- 进度条使用 el-slider -->
<div class="progress-bar">
<el-slider
v-model="currentIndex"
:min="0"
:max="totalQuestions - 1"
:show-tooltip="true"
:format-tooltip="formatTooltip"
@change="handleSliderChange"
/>
</div>
</div>
</div>
</template>
<script setup>
import { reactive, ref, onMounted, computed } from 'vue';
import axios from 'axios';
import QuestionText from './QuestionText.vue';
import GeneralRenderer from "../../../components/GeneralRenderer.vue";
import { useRoute } from 'vue-router';
import swal from "../../../utils/sweetalert.js";
import { demoResourceURL } from "../../../utils/demoResource.js";
import { ElSlider } from 'element-plus';
import store from "../../../store/index.js"; // el-slider
const route = useRoute();
//
const isLoading = ref(true); //
const currentIndex = ref(0); // el-slider
const totalQuestions = ref(0); //
const data = reactive({
itemtypes: [],
texts: [],
explanations: [],
answerkeys: [],
answers: [],
medias: {}
});
//
const currentQuestion = computed(() => {
if (data.texts.length <= 1 || currentIndex.value >= totalQuestions.value) return null;
const index = currentIndex.value + 1;
return {
text: data.texts[index],
answers: data.answers[index],
answerkeys: data.answerkeys[index],
explanation: data.explanations[index],
type: data.itemtypes[index]
};
});
const correctIndex = computed(() => {
if (!currentQuestion.value) return null;
return currentQuestion.value.answerkeys.findIndex((key, idx) => idx > 0 && key === 1) - 1;
});
//
const loadData = async () => {
const categorise = route.query.cat || 'apphy1';
const file = route.query.id || 'phy250227';
try {
const response = await axios.get(demoResourceURL('pod', `${categorise}/${file}.json`));
const jsonData = response.data;
Object.assign(data, jsonData);
totalQuestions.value = data.texts.length - 1; // texts[0]
if (totalQuestions.value > 0) {
currentIndex.value = 0;
}
} catch (error) {
console.error('加载数据失败:', error);
swal.tip('error', '数据加载失败,请稍后重试。');
} finally {
isLoading.value = false;
}
};
//
const prevQuestion = () => {
if (currentIndex.value > 0) {
currentIndex.value--;
}
};
const nextQuestion = () => {
if (currentIndex.value < totalQuestions.value - 1) {
currentIndex.value++;
}
};
//
const processMedia = (text, medias) => {
if (!text) return '';
const mediaRegex = /<media i(\d+)>/g;
return text.replace(mediaRegex, (match, id) => {
const mediaKey = `m${id}`;
if (medias[mediaKey]) {
const [type, url] = medias[mediaKey];
if (type === 'image') {
return `<img class="pod-image" src="${url}" width="100%" height="auto" alt="Question Image" />`;
}
}
return '';
});
};
//
const formatTooltip = (val) => {
return `题目 ${val + 1}`;
};
//
const handleSliderChange = (val) => {
currentIndex.value = val; //
};
//
onMounted(()=> {
loadData();
});
</script>
<style scoped>
.quiz-review-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
width: calc(100% - 49px);
margin: auto;
height: calc(100vh - 109px);
overflow-y: scroll;
padding: 20px;
font-family: Arial, sans-serif;
}
.loading {
text-align: center;
font-size: 18px;
color: #666;
}
.question-container {
margin-bottom: 20px;
max-width: 800px;
}
.options {
margin-top: 20px;
}
.option {
margin: 10px 0;
}
.option label {
display: flex;
flex-direction: row;
align-items: center;
padding: 10px 0;
}
.option input {
margin-right: 10px;
}
.option label.correct {
background-color: rgba(0, 187, 45, 0.2);
color: #155724;
padding: 10px;
border-radius: 5px;
}
.explanation {
margin-top: 20px;
padding: 15px;
border-top: 1px solid #ddd;
}
.navigation {
margin-top: 20px;
}
.nav-btn {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-right: 10px;
}
.nav-btn:hover {
background-color: #0056b3;
}
.progress-bar {
position: absolute;
bottom: 10px;
margin-top: 20px;
width: calc(100% - 50px);
max-width: 800px;
}
</style>

View File

@ -27,7 +27,7 @@ onMounted(async () => {
<div class="folder"> <div class="folder">
<div class="folder-title">{{ cat }}</div> <div class="folder-title">{{ cat }}</div>
<div class="pods-display"> <div class="pods-display">
<router-link class="pods" v-for="pod in podList" :to="`/demos/pod/quiz?cat=${pod.categories.toLowerCase().replaceAll(' ', '')}&id=${pod.file}`"> <router-link class="pods" v-for="pod in podList.filter(v => v.categories === cat)" :to="`/demos/pod/quiz?cat=${pod.categories.toLowerCase().replaceAll(' ', '')}&id=${pod.file}`">
<div class="title">{{ pod.title }}</div> <div class="title">{{ pod.title }}</div>
<div class="date">{{ pod.date }}</div> <div class="date">{{ pod.date }}</div>
</router-link> </router-link>
@ -41,12 +41,14 @@ onMounted(async () => {
<style scoped> <style scoped>
.container { .container {
width: 100%; width: 100%;
height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: row;
justify-content: flex-start; justify-content: center;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
gap: 20px; gap: 20px;
overflow-y: auto;
} }
.pod-container { .pod-container {
width: 100%; width: 100%;

View File

@ -0,0 +1,23 @@
<script setup>
</script>
<template>
<div class="container">
<iframe ref="iframeRef" src="/static/isolatedPages/image2pdf/index.html" width="100%" height="100%"></iframe>
</div>
</template>
<style scoped>
.container {
width: 100%;
height: calc(100vh - 40px);
padding: 0;
}
iframe {
border: none;
width: 100%;
height: 100%;
margin-bottom: 20px;
}
</style>

View File

@ -83,7 +83,8 @@ const routes = [
component: () => import('../pages/demoPages/podExercise/Pod_page.vue'), component: () => import('../pages/demoPages/podExercise/Pod_page.vue'),
meta: { title: '做题' }, meta: { title: '做题' },
children: [ children: [
{ path: "quiz", component: () => import('../pages/demoPages/podExercise/Quiz.vue') } { path: "quiz", component: () => import('../pages/demoPages/podExercise/Quiz.vue') },
{ path: "answer", component: () => import('../pages/demoPages/podExercise/Answer.vue') }
] ]
}, },
{ {
@ -109,6 +110,8 @@ const routes = [
{ path: "pdf-extractor", component: () => import('../pages/toolPages/pdfExtractor/pdfEx_page.vue') }, { path: "pdf-extractor", component: () => import('../pages/toolPages/pdfExtractor/pdfEx_page.vue') },
{ path: "3", component: () => import('../pages/toolPages/RequestTester/requestTester_page.vue') }, { path: "3", component: () => import('../pages/toolPages/RequestTester/requestTester_page.vue') },
{ path: "request-tester", component: () => import('../pages/toolPages/RequestTester/requestTester_page.vue') }, { path: "request-tester", component: () => import('../pages/toolPages/RequestTester/requestTester_page.vue') },
{ path: "4", component: () => import('../pages/toolPages/image2pdf/image2pdf_page.vue') },
{ path: "image-to-pdf", component: () => import('../pages/toolPages/image2pdf/image2pdf_page.vue') },
] ]
}, { }, {
path: '/about', path: '/about',