修复鸿蒙打印导检单
This commit is contained in:
263
package-lock.json
generated
263
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"pdfjs-dist": "^5.4.449",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-router-dom": "^7.9.6"
|
"react-router-dom": "^7.9.6"
|
||||||
@@ -985,6 +986,256 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@napi-rs/canvas": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-hOkywnrkdFdVpsuaNsZWfEY7kc96eROV2DuMTTvGF15AZfwobzdG2w0eDlU5UBx3Lg/XlWUnqVT5zLUWyo5h6A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"workspaces": [
|
||||||
|
"e2e/*"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@napi-rs/canvas-android-arm64": "0.1.86",
|
||||||
|
"@napi-rs/canvas-darwin-arm64": "0.1.86",
|
||||||
|
"@napi-rs/canvas-darwin-x64": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-arm-gnueabihf": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-arm64-gnu": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-arm64-musl": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-riscv64-gnu": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-x64-gnu": "0.1.86",
|
||||||
|
"@napi-rs/canvas-linux-x64-musl": "0.1.86",
|
||||||
|
"@napi-rs/canvas-win32-arm64-msvc": "0.1.86",
|
||||||
|
"@napi-rs/canvas-win32-x64-msvc": "0.1.86"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-android-arm64": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-IjkZFKUr6GzMzzrawJaN3v+yY3Fvpa71e0DcbePfxWelFKnESIir+XUcdAbim29JOd0JE0/hQJdfUCb5t/Fjrw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-darwin-arm64": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-PUCxDq0wSSJbtaOqoKj3+t5tyDbtxWumziOTykdn3T839hu6koMaBFpGk9lXpsGaPNgyFpPqjxhtsPljBGnDHg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-darwin-x64": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-rlCFLv4Rrg45qFZq7mysrKnsUbMhwdNg3YPuVfo9u4RkOqm7ooAJvdyDFxiqfSsJJTqupYqa9VQCUt8WKxKhNQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-6xWwyMc9BlDBt+9XHN/GzUo3MozHta/2fxQHMb80x0K2zpZuAdDKUYHmYzx9dFWDY3SbPYnx6iRlQl6wxnwS1w==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-arm64-gnu": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-r2OX3w50xHxrToTovOSQWwkVfSq752CUzH9dzlVXyr8UDKFV8dMjfa9hePXvAJhN3NBp4TkHcGx15QCdaCIwnA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-arm64-musl": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-jbXuh8zVFUPw6a9SGpgc6EC+fRbGGyP1NFfeQiVqGLs6bN93ROtPLPL6MH9Bp6yt0CXUFallk2vgKdWDbmW+bw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-9IwHR2qbq2HceM9fgwyL7x37Jy3ptt1uxvikQEuWR0FisIx9QEdt7F3huljCky76aoouF2vSd0R2fHo3ESRoPw==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-x64-gnu": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-Jor+rhRN6ubix+D2QkNn9XlPPVAYl+2qFrkZ4oZN9UgtqIUZ+n+HljxhlkkDFRaX1mlxXOXPQjxaZg17zDSFcQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-linux-x64-musl": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-A28VTy91DbclopSGZ2tIon3p8hcVI1JhnNpDpJ5N9rYlUnVz1WQo4waEMh+FICTZF07O3coxBNZc4Vu4doFw7A==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-win32-arm64-msvc": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-q6G1YXUt3gBCAS2bcDMCaBL4y20di8eVVBi1XhjUqZSVyZZxxwIuRQHy31NlPJUCMiyNiMuc6zeI0uqgkWwAmA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/canvas-win32-x64-msvc": {
|
||||||
|
"version": "0.1.86",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.86.tgz",
|
||||||
|
"integrity": "sha512-X0g46uRVgnvCM1cOjRXAOSFSG63ktUFIf/TIfbKCUc7QpmYUcHmSP9iR6DGOYfk+SggLsXoJCIhPTotYeZEAmg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -3565,6 +3816,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/pdfjs-dist": {
|
||||||
|
"version": "5.4.449",
|
||||||
|
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.449.tgz",
|
||||||
|
"integrity": "sha512-CegnUaT0QwAyQMS+7o2POr4wWUNNe8VaKKlcuoRHeYo98cVnqPpwOXNSx6Trl6szH02JrRcsPgletV6GmF3LtQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.16.0 || >=22.3.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@napi-rs/canvas": "^0.1.81"
|
||||||
|
}
|
||||||
|
},
|
||||||
"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",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"pdfjs-dist": "^5.4.449",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-router-dom": "^7.9.6"
|
"react-router-dom": "^7.9.6"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import * as pdfjsLib from 'pdfjs-dist';
|
||||||
|
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
|
||||||
|
|
||||||
import { getDaojiandanPdf as getDaojiandanPdfApi, submitDaojiandanSign } from '../../api';
|
import { getDaojiandanPdf as getDaojiandanPdfApi, submitDaojiandanSign } from '../../api';
|
||||||
import type { ExamClient } from '../../data/mockData';
|
import type { ExamClient } from '../../data/mockData';
|
||||||
@@ -6,6 +8,22 @@ import { setExamActionRecord, setDaojiandanPdf, getDaojiandanPdf } from '../../u
|
|||||||
import type { SignaturePadHandle } from '../ui';
|
import type { SignaturePadHandle } from '../ui';
|
||||||
import { Button, SignaturePad } from '../ui';
|
import { Button, SignaturePad } from '../ui';
|
||||||
|
|
||||||
|
// Polyfill for Promise.withResolvers
|
||||||
|
if (typeof (Promise as any).withResolvers === 'undefined') {
|
||||||
|
(Promise as any).withResolvers = function <T>() {
|
||||||
|
let resolve!: (value: T | PromiseLike<T>) => void;
|
||||||
|
let reject!: (reason?: any) => void;
|
||||||
|
const promise = new Promise<T>((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
|
return { promise, resolve, reject };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置 PDF.js worker
|
||||||
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
||||||
|
|
||||||
export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
||||||
const [pdfUrl, setPdfUrl] = useState<string | null>(null);
|
const [pdfUrl, setPdfUrl] = useState<string | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -17,9 +35,10 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
|||||||
const [submitMessage, setSubmitMessage] = useState<string | null>(null);
|
const [submitMessage, setSubmitMessage] = useState<string | null>(null);
|
||||||
const [showPreview, setShowPreview] = useState(false);
|
const [showPreview, setShowPreview] = useState(false);
|
||||||
const [fetchLoading, setFetchLoading] = useState(false);
|
const [fetchLoading, setFetchLoading] = useState(false);
|
||||||
|
const [pdfData, setPdfData] = useState<ArrayBuffer | null>(null);
|
||||||
const signaturePadRef = useRef<SignaturePadHandle | null>(null);
|
const signaturePadRef = useRef<SignaturePadHandle | null>(null);
|
||||||
const printRef = useRef<HTMLDivElement>(null);
|
const printRef = useRef<HTMLDivElement>(null);
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const canvasContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const handleSubmitSign = async () => {
|
const handleSubmitSign = async () => {
|
||||||
const examId = Number(client.id);
|
const examId = Number(client.id);
|
||||||
@@ -126,12 +145,14 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 第一步:加载 PDF 数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!pdfUrl) return;
|
if (!pdfUrl) return;
|
||||||
|
|
||||||
let objectUrl: string | null = null;
|
let objectUrl: string | null = null;
|
||||||
setPdfReady(false);
|
setPdfReady(false);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
setPdfData(null);
|
||||||
|
|
||||||
fetch(pdfUrl)
|
fetch(pdfUrl)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
@@ -141,12 +162,15 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
|||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
objectUrl = URL.createObjectURL(blob);
|
objectUrl = URL.createObjectURL(blob);
|
||||||
setPdfBlobUrl(objectUrl);
|
setPdfBlobUrl(objectUrl);
|
||||||
|
return blob.arrayBuffer();
|
||||||
|
})
|
||||||
|
.then((arrayBuffer) => {
|
||||||
|
setPdfData(arrayBuffer);
|
||||||
|
setLoading(false);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('PDF 拉取失败', err);
|
console.error('PDF 拉取失败', err);
|
||||||
setError('PDF 加载失败,请稍后重试');
|
setError('PDF 加载失败,请稍后重试');
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,15 +181,133 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
|||||||
};
|
};
|
||||||
}, [pdfUrl]);
|
}, [pdfUrl]);
|
||||||
|
|
||||||
|
// 第二步:渲染 PDF
|
||||||
|
useEffect(() => {
|
||||||
|
if (!pdfData || !canvasContainerRef.current) return;
|
||||||
|
|
||||||
|
console.log('开始渲染 PDF');
|
||||||
|
setPdfReady(false);
|
||||||
|
|
||||||
|
const renderAllPages = async () => {
|
||||||
|
try {
|
||||||
|
const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise;
|
||||||
|
console.log('PDF 加载成功,共 ' + pdf.numPages + ' 页');
|
||||||
|
|
||||||
|
if (!canvasContainerRef.current) {
|
||||||
|
console.log('canvasContainerRef 仍为 null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空容器
|
||||||
|
canvasContainerRef.current.innerHTML = '';
|
||||||
|
|
||||||
|
const scale = 1.2;
|
||||||
|
|
||||||
|
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
|
||||||
|
const page = await pdf.getPage(pageNum);
|
||||||
|
const viewport = page.getViewport({ scale });
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
console.log('无法获取 canvas context');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.height = viewport.height;
|
||||||
|
canvas.width = viewport.width;
|
||||||
|
canvas.style.display = 'block';
|
||||||
|
canvas.style.marginBottom = '10px';
|
||||||
|
canvas.className = 'mx-auto border rounded-lg shadow-sm';
|
||||||
|
|
||||||
|
canvasContainerRef.current.appendChild(canvas);
|
||||||
|
|
||||||
|
const renderContext = {
|
||||||
|
canvasContext: context,
|
||||||
|
viewport: viewport,
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
await page.render(renderContext).promise;
|
||||||
|
console.log('渲染完成第 ' + pageNum + ' 页');
|
||||||
|
}
|
||||||
|
|
||||||
|
setPdfReady(true);
|
||||||
|
console.log('所有页面渲染完成');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('PDF 渲染失败', err);
|
||||||
|
setError('PDF 渲染失败,请稍后重试: ' + err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
renderAllPages();
|
||||||
|
}, [pdfData]);
|
||||||
|
|
||||||
const handlePrint = () => {
|
const handlePrint = () => {
|
||||||
if (!pdfBlobUrl || !pdfReady) return;
|
if (!pdfBlobUrl || !pdfReady || !canvasContainerRef.current) return;
|
||||||
const printWindow = window.open(pdfBlobUrl, '_blank');
|
|
||||||
if (printWindow) {
|
// 创建打印窗口
|
||||||
printWindow.onload = () => {
|
const printWindow = window.open('', '_blank');
|
||||||
printWindow.focus();
|
if (!printWindow) return;
|
||||||
|
|
||||||
|
// 获取所有的 canvas
|
||||||
|
const canvases = canvasContainerRef.current.querySelectorAll('canvas');
|
||||||
|
|
||||||
|
// 构建打印页面
|
||||||
|
printWindow.document.write(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>导检单打印</title>
|
||||||
|
<style>
|
||||||
|
@media print {
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
page-break-after: always;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
img:last-child {
|
||||||
|
page-break-after: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
`);
|
||||||
|
|
||||||
|
// 将每个 canvas 转换为图片并添加到打印窗口
|
||||||
|
canvases.forEach((canvas) => {
|
||||||
|
const imgData = (canvas as HTMLCanvasElement).toDataURL('image/png');
|
||||||
|
printWindow.document.write(`<img src="${imgData}" />`);
|
||||||
|
});
|
||||||
|
|
||||||
|
printWindow.document.write(`
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
|
||||||
|
printWindow.document.close();
|
||||||
|
|
||||||
|
// 等待图片加载完成后执行打印
|
||||||
|
printWindow.onload = () => {
|
||||||
|
printWindow.focus();
|
||||||
|
setTimeout(() => {
|
||||||
printWindow.print();
|
printWindow.print();
|
||||||
};
|
}, 1000);
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -306,13 +448,7 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
|||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
<div ref={printRef} className='print-content'>
|
<div ref={printRef} className='print-content'>
|
||||||
<div className='flex justify-center border rounded-lg p-4 bg-gray-50 overflow-auto max-h-[600px]'>
|
<div className='flex justify-center border rounded-lg p-4 bg-gray-50 overflow-auto max-h-[600px]'>
|
||||||
<iframe
|
<div ref={canvasContainerRef} className='w-full' />
|
||||||
src={pdfBlobUrl || ''}
|
|
||||||
className='w-full h-[600px] border rounded-lg'
|
|
||||||
title='导检单PDF预览'
|
|
||||||
onLoad={() => setPdfReady(true)}
|
|
||||||
ref={iframeRef}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user