generated from template/vite-react-template
Compare commits
2 Commits
263218b481
...
f858d1aa5b
| Author | SHA1 | Date | |
|---|---|---|---|
| f858d1aa5b | |||
| 87d48e6fc3 |
2
.cnb.yml
2
.cnb.yml
@@ -4,7 +4,7 @@ include:
|
||||
|
||||
.common_env: &common_env
|
||||
env:
|
||||
TO_REPO: template/vite-react-template
|
||||
TO_REPO: kevisual/pdf
|
||||
TO_URL: git.xiongxiao.me
|
||||
imports:
|
||||
- https://cnb.cool/kevisual/env/-/blob/main/.env.development
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/png" href="https://kevisual.xiongxiao.me/root/center/panda.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<link rel="stylesheet" href="/src/index.css" />
|
||||
<title>PDF 模块</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
|
||||
13
package.json
13
package.json
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "vite-react",
|
||||
"name": "@kevisual/pdf",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"type": "module",
|
||||
"basename": "/",
|
||||
"basename": "/root/pdf",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"ui": "pnpm dlx shadcn@latest add ",
|
||||
"pub": "envision deploy ./dist -k vite-react -v 0.0.1"
|
||||
"pub": "envision deploy ./dist -k pdf -v 0.0.4 -y y -u"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
@@ -20,14 +20,18 @@
|
||||
"@kevisual/router": "0.0.70",
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@tanstack/react-router": "^1.158.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.19",
|
||||
"es-toolkit": "^1.44.0",
|
||||
"lucide-react": "^0.563.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"pdfjs-dist": "^5.4.624",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-dropzone": "^14.4.0",
|
||||
"react-hook-form": "^7.71.1",
|
||||
"react-pdf": "^10.3.0",
|
||||
"zustand": "^5.0.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
@@ -40,6 +44,7 @@
|
||||
"@tanstack/react-router-devtools": "^1.158.0",
|
||||
"@tanstack/router-plugin": "^1.158.0",
|
||||
"@types/node": "^25.2.0",
|
||||
"@types/pdfjs-dist": "^2.10.378",
|
||||
"@types/react": "^19.2.10",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.3",
|
||||
|
||||
263
pnpm-lock.yaml
generated
263
pnpm-lock.yaml
generated
@@ -17,6 +17,9 @@ importers:
|
||||
'@tanstack/react-router':
|
||||
specifier: ^1.158.0
|
||||
version: 1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
@@ -32,15 +35,24 @@ importers:
|
||||
nanoid:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
pdfjs-dist:
|
||||
specifier: ^5.4.624
|
||||
version: 5.4.624
|
||||
react:
|
||||
specifier: ^19.2.4
|
||||
version: 19.2.4
|
||||
react-dom:
|
||||
specifier: ^19.2.4
|
||||
version: 19.2.4(react@19.2.4)
|
||||
react-dropzone:
|
||||
specifier: ^14.4.0
|
||||
version: 14.4.0(react@19.2.4)
|
||||
react-hook-form:
|
||||
specifier: ^7.71.1
|
||||
version: 7.71.1(react@19.2.4)
|
||||
react-pdf:
|
||||
specifier: ^10.3.0
|
||||
version: 10.3.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
zustand:
|
||||
specifier: ^5.0.11
|
||||
version: 5.0.11(@types/react@19.2.10)(immer@10.1.1)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4))
|
||||
@@ -63,6 +75,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^25.2.0
|
||||
version: 25.2.0
|
||||
'@types/pdfjs-dist':
|
||||
specifier: ^2.10.378
|
||||
version: 2.10.378
|
||||
'@types/react':
|
||||
specifier: ^19.2.10
|
||||
version: 19.2.10
|
||||
@@ -622,6 +637,81 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.89':
|
||||
resolution: {integrity: sha512-CXxQTXsjtQqKGENS8Ejv9pZOFJhOPIl2goenS+aU8dY4DygvkyagDhy/I07D1YLqrDtPvLEX5zZHt8qUdnuIpQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.89':
|
||||
resolution: {integrity: sha512-k29cR/Zl20WLYM7M8YePevRu2VQRaKcRedYr1V/8FFHkyIQ8kShEV+MPoPGi+znvmd17Eqjy2Pk2F2kpM2umVg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.89':
|
||||
resolution: {integrity: sha512-iUragqhBrA5FqU13pkhYBDbUD1WEAIlT8R2+fj6xHICY2nemzwMUI8OENDhRh7zuL06YDcRwENbjAVxOmaX9jg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.89':
|
||||
resolution: {integrity: sha512-y3SM9sfDWasY58ftoaI09YBFm35Ig8tosZqgahLJ2WGqawCusGNPV9P0/4PsrLOCZqGg629WxexQMY25n7zcvA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.89':
|
||||
resolution: {integrity: sha512-NEoF9y8xq5fX8HG8aZunBom1ILdTwt7ayBzSBIwrmitk7snj4W6Fz/yN/ZOmlM1iyzHDNX5Xn0n+VgWCF8BEdA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.89':
|
||||
resolution: {integrity: sha512-UQQkIEzV12/l60j1ziMjZ+mtodICNUbrd205uAhbyTw0t60CrC/EsKb5/aJWGq1wM0agvcgZV72JJCKfLS6+4w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.89':
|
||||
resolution: {integrity: sha512-1/VmEoFaIO6ONeeEMGoWF17wOYZOl5hxDC1ios2Bkz/oQjbJJ8DY/X22vWTmvuUKWWhBVlo63pxLGZbjJU/heA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.89':
|
||||
resolution: {integrity: sha512-ebLuqkCuaPIkKgKH9q4+pqWi1tkPOfiTk5PM1LKR1tB9iO9sFNVSIgwEp+SJreTSbA2DK5rW8lQXiN78SjtcvA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.89':
|
||||
resolution: {integrity: sha512-w+5qxHzplvA4BkHhCaizNMLLXiI+CfP84YhpHm/PqMub4u8J0uOAv+aaGv40rYEYra5hHRWr9LUd6cfW32o9/A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@napi-rs/canvas-win32-arm64-msvc@0.1.89':
|
||||
resolution: {integrity: sha512-DmyXa5lJHcjOsDC78BM3bnEECqbK3xASVMrKfvtT/7S7Z8NGQOugvu+L7b41V6cexCd34mBWgMOsjoEBceeB1Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.89':
|
||||
resolution: {integrity: sha512-WMej0LZrIqIncQcx0JHaMXlnAG7sncwJh7obs/GBgp0xF9qABjwoRwIooMWCZkSansapKGNUHhamY6qEnFN7gA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas@0.1.89':
|
||||
resolution: {integrity: sha512-7GjmkMirJHejeALCqUnZY3QwID7bbumOiLrqq2LKgxrdjdmxWQBTc6rcASa2u8wuWrH7qo4/4n/VNrOwCoKlKg==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@popperjs/core@2.11.8':
|
||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||
|
||||
@@ -1121,6 +1211,10 @@ packages:
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
|
||||
'@types/pdfjs-dist@2.10.378':
|
||||
resolution: {integrity: sha512-TRdIPqdsvKmPla44kVy4jv5Nt5vjMfVjbIEke1CRULIrwKNRC4lIiZvNYDJvbUMNCFPNIUcOKhXTyMJrX18IMA==}
|
||||
deprecated: This is a stub types definition. pdfjs-dist provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/prop-types@15.7.14':
|
||||
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
|
||||
|
||||
@@ -1166,6 +1260,10 @@ packages:
|
||||
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
attr-accept@2.2.5:
|
||||
resolution: {integrity: sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
babel-dead-code-elimination@1.0.12:
|
||||
resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
|
||||
|
||||
@@ -1197,6 +1295,9 @@ packages:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
class-variance-authority@0.7.1:
|
||||
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
|
||||
|
||||
clsx@1.2.1:
|
||||
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -1243,6 +1344,10 @@ packages:
|
||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
detect-libc@2.0.4:
|
||||
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1313,6 +1418,10 @@ packages:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
file-selector@2.1.2:
|
||||
resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
fill-range@7.1.1:
|
||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1527,6 +1636,20 @@ packages:
|
||||
magic-string@0.30.21:
|
||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||
|
||||
make-cancellable-promise@2.0.0:
|
||||
resolution: {integrity: sha512-3SEQqTpV9oqVsIWqAcmDuaNeo7yBO3tqPtqGRcKkEo0lrzD3wqbKG9mkxO65KoOgXqj+zH2phJ2LiAsdzlogSw==}
|
||||
|
||||
make-event-props@2.0.0:
|
||||
resolution: {integrity: sha512-G/hncXrl4Qt7mauJEXSg3AcdYzmpkIITTNl5I+rH9sog5Yw0kK6vseJjCaPfOXqOqQuPUP89Rkhfz5kPS8ijtw==}
|
||||
|
||||
merge-refs@2.0.0:
|
||||
resolution: {integrity: sha512-3+B21mYK2IqUWnd2EivABLT7ueDhb0b8/dGK8LoFQPrU61YITeCMn14F7y7qZafWNZhUEKb24cJdiT5Wxs3prg==}
|
||||
peerDependencies:
|
||||
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@@ -1540,6 +1663,9 @@ packages:
|
||||
engines: {node: ^18 || >=20}
|
||||
hasBin: true
|
||||
|
||||
node-readable-to-web-readable-stream@0.4.2:
|
||||
resolution: {integrity: sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==}
|
||||
|
||||
node-releases@2.0.18:
|
||||
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
||||
|
||||
@@ -1581,6 +1707,14 @@ packages:
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
pdfjs-dist@5.4.296:
|
||||
resolution: {integrity: sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==}
|
||||
engines: {node: '>=20.16.0 || >=22.3.0'}
|
||||
|
||||
pdfjs-dist@5.4.624:
|
||||
resolution: {integrity: sha512-sm6TxKTtWv1Oh6n3C6J6a8odejb5uO4A4zo/2dgkHuC0iu8ZMAXOezEODkVaoVp8nX1Xzr+0WxFJJmUr45hQzg==}
|
||||
engines: {node: '>=20.16.0 || >=22.3.0'}
|
||||
|
||||
picocolors@1.1.0:
|
||||
resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
|
||||
|
||||
@@ -1633,6 +1767,12 @@ packages:
|
||||
react: '>= 16.3.0'
|
||||
react-dom: '>= 16.3.0'
|
||||
|
||||
react-dropzone@14.4.0:
|
||||
resolution: {integrity: sha512-8VvsHqg9WGAr+wAnP0oVErK5HOwAoTOzRsxLPzbBXrtXtFfukkxMyuvdI/lJ+5OxtsrzmvWE5Eoo3Y4hMsaxpA==}
|
||||
engines: {node: '>= 10.13'}
|
||||
peerDependencies:
|
||||
react: '>= 16.8 || 18.0.0'
|
||||
|
||||
react-hook-form@7.56.4:
|
||||
resolution: {integrity: sha512-Rob7Ftz2vyZ/ZGsQZPaRdIefkgOSrQSPXfqBdvOPwJfoGnjwRJUs7EM7Kc1mcoDv3NOtqBzPGbcMB8CGn9CKgw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@@ -1667,6 +1807,16 @@ packages:
|
||||
react-is@19.1.0:
|
||||
resolution: {integrity: sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==}
|
||||
|
||||
react-pdf@10.3.0:
|
||||
resolution: {integrity: sha512-2LQzC9IgNVAX8gM+6F+1t/70a9/5RWThYxc+CWAmT2LW/BRmnj+35x1os5j/nR2oldyf8L+hCAMBmVKU8wrYFA==}
|
||||
peerDependencies:
|
||||
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-refresh@0.18.0:
|
||||
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1878,6 +2028,9 @@ packages:
|
||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
warning@4.0.3:
|
||||
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
|
||||
|
||||
webpack-virtual-modules@0.6.2:
|
||||
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||
|
||||
@@ -2430,6 +2583,54 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-arm64-msvc@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.89':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas@0.1.89':
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas-android-arm64': 0.1.89
|
||||
'@napi-rs/canvas-darwin-arm64': 0.1.89
|
||||
'@napi-rs/canvas-darwin-x64': 0.1.89
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.89
|
||||
'@napi-rs/canvas-linux-arm64-gnu': 0.1.89
|
||||
'@napi-rs/canvas-linux-arm64-musl': 0.1.89
|
||||
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.89
|
||||
'@napi-rs/canvas-linux-x64-gnu': 0.1.89
|
||||
'@napi-rs/canvas-linux-x64-musl': 0.1.89
|
||||
'@napi-rs/canvas-win32-arm64-msvc': 0.1.89
|
||||
'@napi-rs/canvas-win32-x64-msvc': 0.1.89
|
||||
optional: true
|
||||
|
||||
'@popperjs/core@2.11.8': {}
|
||||
|
||||
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.10)(react@19.2.4)':
|
||||
@@ -2821,6 +3022,10 @@ snapshots:
|
||||
|
||||
'@types/parse-json@4.0.2': {}
|
||||
|
||||
'@types/pdfjs-dist@2.10.378':
|
||||
dependencies:
|
||||
pdfjs-dist: 5.4.624
|
||||
|
||||
'@types/prop-types@15.7.14': {}
|
||||
|
||||
'@types/react-dom@19.2.3(@types/react@19.2.10)':
|
||||
@@ -2866,6 +3071,8 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
attr-accept@2.2.5: {}
|
||||
|
||||
babel-dead-code-elimination@1.0.12:
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
@@ -2910,6 +3117,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
class-variance-authority@0.7.1:
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
|
||||
clsx@1.2.1: {}
|
||||
|
||||
clsx@2.1.1: {}
|
||||
@@ -2942,6 +3153,8 @@ snapshots:
|
||||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@2.0.4: {}
|
||||
|
||||
diff@8.0.3: {}
|
||||
@@ -3013,6 +3226,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.3
|
||||
|
||||
file-selector@2.1.2:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
fill-range@7.1.1:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
@@ -3177,12 +3394,23 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
make-cancellable-promise@2.0.0: {}
|
||||
|
||||
make-event-props@2.0.0: {}
|
||||
|
||||
merge-refs@2.0.0(@types/react@19.2.10):
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.10
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
nanoid@5.1.6: {}
|
||||
|
||||
node-readable-to-web-readable-stream@0.4.2:
|
||||
optional: true
|
||||
|
||||
node-releases@2.0.18: {}
|
||||
|
||||
normalize-path@3.0.0: {}
|
||||
@@ -3210,6 +3438,15 @@ snapshots:
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pdfjs-dist@5.4.296:
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas': 0.1.89
|
||||
|
||||
pdfjs-dist@5.4.624:
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas': 0.1.89
|
||||
node-readable-to-web-readable-stream: 0.4.2
|
||||
|
||||
picocolors@1.1.0: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
@@ -3256,6 +3493,13 @@ snapshots:
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
||||
react-dropzone@14.4.0(react@19.2.4):
|
||||
dependencies:
|
||||
attr-accept: 2.2.5
|
||||
file-selector: 2.1.2
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.4
|
||||
|
||||
react-hook-form@7.56.4(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
@@ -3278,6 +3522,21 @@ snapshots:
|
||||
|
||||
react-is@19.1.0: {}
|
||||
|
||||
react-pdf@10.3.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
dequal: 2.0.3
|
||||
make-cancellable-promise: 2.0.0
|
||||
make-event-props: 2.0.0
|
||||
merge-refs: 2.0.0(@types/react@19.2.10)
|
||||
pdfjs-dist: 5.4.296
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
tiny-invariant: 1.3.3
|
||||
warning: 4.0.3
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.10
|
||||
|
||||
react-refresh@0.18.0: {}
|
||||
|
||||
react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
@@ -3479,6 +3738,10 @@ snapshots:
|
||||
|
||||
void-elements@3.1.0: {}
|
||||
|
||||
warning@4.0.3:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
webpack-virtual-modules@0.6.2: {}
|
||||
|
||||
ws@8.18.1:
|
||||
|
||||
@@ -2,10 +2,12 @@ import ReactDOM from 'react-dom/client'
|
||||
import { RouterProvider, createRouter } from '@tanstack/react-router'
|
||||
import { routeTree } from './routeTree.gen'
|
||||
import './index.css'
|
||||
import { basename } from './modules/basename'
|
||||
|
||||
// Set up a Router instance
|
||||
const router = createRouter({
|
||||
routeTree,
|
||||
basepath: basename,
|
||||
defaultPreload: 'intent',
|
||||
scrollRestoration: true,
|
||||
})
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// @ts-ignore
|
||||
export const basename = DEV_SERVER ? '/' : BASE_NAME;
|
||||
export const basename = BASE_NAME;
|
||||
|
||||
@@ -1,3 +1,208 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { useDropzone } from 'react-dropzone'
|
||||
import * as pdfjsLib from 'pdfjs-dist'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Upload, Download, FileText, Loader2 } from 'lucide-react'
|
||||
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url'
|
||||
|
||||
// 设置 PDF.js worker
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker
|
||||
// pdfjsLib.GlobalWorkerOptions.workerSrc = "//cdn.jsdelivr.net/npm/pdfjs-dist@5.4.624/build/pdf.min.mjs"
|
||||
// pdfjsLib.GlobalWorkerOptions.workerSrc = "//unpkg.com/pdfjs-dist@5.4.624/build/pdf.min.mjs"
|
||||
|
||||
export const Home = () => {
|
||||
return <div>Home Page</div>
|
||||
const [pdfFile, setPdfFile] = useState<File | null>(null)
|
||||
const [pdfName, setPdfName] = useState<string>('')
|
||||
const [pageCount, setPageCount] = useState<number>(0)
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [converting, setConverting] = useState<boolean>(false)
|
||||
|
||||
const onDrop = useCallback(async (acceptedFiles: File[]) => {
|
||||
const file = acceptedFiles[0]
|
||||
if (file && file.type === 'application/pdf') {
|
||||
setPdfFile(file)
|
||||
setPdfName(file.name.replace('.pdf', ''))
|
||||
|
||||
// 读取 PDF 获取页数
|
||||
setLoading(true)
|
||||
try {
|
||||
const arrayBuffer = await file.arrayBuffer()
|
||||
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise
|
||||
setPageCount(pdf.numPages)
|
||||
} catch (error) {
|
||||
console.error('Error loading PDF:', error)
|
||||
alert('加载 PDF 失败,请重试')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
onDrop,
|
||||
accept: {
|
||||
'application/pdf': ['.pdf']
|
||||
},
|
||||
multiple: false
|
||||
})
|
||||
|
||||
const handleDownload = async () => {
|
||||
if (!pdfFile) return
|
||||
|
||||
setConverting(true)
|
||||
try {
|
||||
const arrayBuffer = await pdfFile.arrayBuffer()
|
||||
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise
|
||||
|
||||
// 遍历每一页
|
||||
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
|
||||
const page = await pdf.getPage(pageNum)
|
||||
|
||||
// 设置缩放比例以获得高质量图片
|
||||
const scale = 2.0
|
||||
const viewport = page.getViewport({ scale })
|
||||
|
||||
// 创建 canvas
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
canvas.height = viewport.height
|
||||
canvas.width = viewport.width
|
||||
|
||||
if (!context) continue
|
||||
|
||||
// 渲染 PDF 页面到 canvas
|
||||
await page.render({
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
canvas: canvas
|
||||
}).promise
|
||||
|
||||
// 将 canvas 转换为 blob 并下载
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob) {
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `${pdfName}_${pageNum}.png`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
}, 'image/png')
|
||||
|
||||
// 添加延迟避免浏览器下载限制
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
}
|
||||
|
||||
alert(`成功转换并下载 ${pdf.numPages} 张图片!`)
|
||||
} catch (error) {
|
||||
console.error('Error converting PDF:', error)
|
||||
alert('转换 PDF 失败,请重试')
|
||||
} finally {
|
||||
setConverting(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full bg-linear-to-br from-blue-50 to-indigo-100 p-8 overflow-auto">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl font-bold text-gray-800 mb-2">
|
||||
PDF 转图片工具
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
上传 PDF 文件,将每一页转换为单独的图片
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 上传区域 */}
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={`
|
||||
border-2 border-dashed rounded-lg p-12 mb-8 text-center cursor-pointer
|
||||
transition-all duration-200 ease-in-out
|
||||
${isDragActive
|
||||
? 'border-blue-500 bg-blue-50'
|
||||
: 'border-gray-300 bg-white hover:border-blue-400 hover:bg-blue-50/50'
|
||||
}
|
||||
`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<Upload className={`w-16 h-16 ${isDragActive ? 'text-blue-500' : 'text-gray-400'}`} />
|
||||
{isDragActive ? (
|
||||
<p className="text-lg text-blue-600 font-medium">
|
||||
释放文件以上传...
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-lg text-gray-700 font-medium">
|
||||
拖拽 PDF 文件到这里,或点击选择文件
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
仅支持 PDF 格式
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* PDF 信息卡片 */}
|
||||
{pdfFile && (
|
||||
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-4 flex-1">
|
||||
<FileText className="w-12 h-12 text-blue-500 shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-lg font-semibold text-gray-800 truncate">
|
||||
{pdfFile.name}
|
||||
</h3>
|
||||
<div className="mt-2 space-y-1 text-sm text-gray-600">
|
||||
<p>
|
||||
文件大小: {(pdfFile.size / 1024 / 1024).toFixed(2)} MB
|
||||
</p>
|
||||
{loading ? (
|
||||
<p className="flex items-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
正在加载 PDF...
|
||||
</p>
|
||||
) : (
|
||||
<p>页数: {pageCount} 页</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleDownload}
|
||||
disabled={loading || converting || pageCount === 0}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
{converting ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
转换中...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Download className="w-4 h-4" />
|
||||
下载图片
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 说明 */}
|
||||
<div className="bg-white rounded-lg shadow-md p-6">
|
||||
<h3 className="font-semibold text-gray-800 mb-3">使用说明:</h3>
|
||||
<ol className="list-decimal list-inside space-y-2 text-gray-600 text-sm">
|
||||
<li>点击或拖拽上传 PDF 文件</li>
|
||||
<li>等待文件加载完成,查看页数信息</li>
|
||||
<li>点击"下载图片"按钮,自动将每一页转换为 PNG 图片</li>
|
||||
<li>图片将按顺序命名,如:文件名_1.png, 文件名_2.png...</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export const Route = createRootRoute({
|
||||
function RootComponent() {
|
||||
return (
|
||||
<>
|
||||
<div className="p-2 flex gap-2 text-lg">
|
||||
<div className="p-2 flex gap-2 text-lg h-16">
|
||||
<Link
|
||||
to="/"
|
||||
activeProps={{
|
||||
@@ -20,7 +20,9 @@ function RootComponent() {
|
||||
</Link>
|
||||
</div>
|
||||
<hr />
|
||||
<main className='h-[calc(100vh-64px)] overflow-hidden'>
|
||||
<Outlet />
|
||||
</main>
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
</>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user