diff --git a/electron/main.js b/electron/main.js index 5334fee..7bcde9f 100644 --- a/electron/main.js +++ b/electron/main.js @@ -300,16 +300,18 @@ ipcMain.handle("print-pdf", async (event, pdfDataOrUrl, printOptions = {}) => { throw new Error(`PDF文件大小异常(${stats.size} bytes),可能文件损坏`); } + const duplexMode = printOptions?.duplex; log.info( `准备打印PDF: ${pdfFilePath}, 打印机: ${ targetPrinterName || "默认打印机" - }` + }, 双面打印: ${duplexMode ? "是" : "否"}` ); // 使用 pdf-to-printer 打印 const printOptions_ptp = { printer: targetPrinterName || undefined, silent: true, // 静默打印 + duplex: duplexMode || false, // 双面打印选项 }; await ptp.print(pdfFilePath, printOptions_ptp); diff --git a/src/components/DuplexToggle.css b/src/components/DuplexToggle.css new file mode 100644 index 0000000..cb56ce5 --- /dev/null +++ b/src/components/DuplexToggle.css @@ -0,0 +1,32 @@ +.duplex-toggle { + display: flex; + align-items: center; + cursor: pointer; + user-select: none; + gap: 10px; + transition: opacity 0.2s ease; +} + +.duplex-toggle:hover { + opacity: 0.8; +} + +.duplex-toggle-icon { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + font-size: 16px; + transition: all 0.2s ease; + flex-shrink: 0; + font-family: NotoSansCJKsc-Medium; +} + + +.duplex-toggle-label { + font-size: 20px; + font-family: NotoSansCJKsc-Regular; + color: rgba(0, 45, 93, 1); +} \ No newline at end of file diff --git a/src/components/DuplexToggle.tsx b/src/components/DuplexToggle.tsx new file mode 100644 index 0000000..f9454ca --- /dev/null +++ b/src/components/DuplexToggle.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import "./DuplexToggle.css"; + +interface DuplexToggleProps { + checked: boolean; + onChange: (checked: boolean) => void; + label?: string; +} + +const DuplexToggle: React.FC = ({ + checked, + onChange, + label = "", +}) => { + const handleClick = () => { + onChange(!checked); + }; + + return ( +
+
+ {checked ? "双" : "单"} +
+ {label} +
+ ); +}; + +export default DuplexToggle; + diff --git a/src/electron.d.ts b/src/electron.d.ts index c035364..c64da7f 100644 --- a/src/electron.d.ts +++ b/src/electron.d.ts @@ -14,7 +14,7 @@ interface ElectronAPI { ) => Promise<{ success: boolean; data?: string; error?: string }>; printPdf: ( pdfUrl: string, - options?: { printerName?: string } + options?: { printerName?: string; duplex?: boolean } ) => Promise<{ success: boolean; error?: string }>; getPrinters: () => Promise<{ success: boolean; diff --git a/src/pages/UI8/UI8.css b/src/pages/UI8/UI8.css index a751257..e33e24a 100644 --- a/src/pages/UI8/UI8.css +++ b/src/pages/UI8/UI8.css @@ -348,4 +348,11 @@ .ui8-printer-error { font-size: 22px; color: #b12651; +} + +.ui8-duplex-option { + margin-top: 15px; + display: flex; + justify-content: flex-end; + align-items: center; } \ No newline at end of file diff --git a/src/pages/UI8/UI8.tsx b/src/pages/UI8/UI8.tsx index 1a9bfb7..db346b4 100644 --- a/src/pages/UI8/UI8.tsx +++ b/src/pages/UI8/UI8.tsx @@ -5,11 +5,13 @@ import "./UI8.css"; import "../../assets/css/basic.css"; import { useNavigate } from "react-router-dom"; import ConfirmButton from "../../components/ConfirmButton"; +import DuplexToggle from "../../components/DuplexToggle"; import ui8A from "../../assets/ui8A.png"; import ui8B from "../../assets/ui8B.png"; import { getDaojiandanPdf } from "../../api/hisApi"; const PREFERRED_PRINTER_KEY = "preferredPrinterName"; +const PREFERRED_DUPLEX_KEY = "preferredDuplex"; type PrinterInfo = ElectronPrinterInfo; @@ -74,6 +76,7 @@ const UI8: React.FC = () => { const printerDropdownRef = useRef(null); const pdfContainerRef = useRef(null); const [isRightSectionHidden, setIsRightSectionHidden] = useState(false); + const [duplexEnabled, setDuplexEnabled] = useState(false); const getExamId = () => { const storedId = localStorage.getItem("selectedExamId"); @@ -221,6 +224,12 @@ const UI8: React.FC = () => { fetchPrinters(); + // 恢复双面打印设置 + const storedDuplex = localStorage.getItem(PREFERRED_DUPLEX_KEY); + if (storedDuplex === "true") { + setDuplexEnabled(true); + } + return () => { isMounted = false; }; @@ -343,7 +352,10 @@ const UI8: React.FC = () => { const printResult = await window.electronAPI.printPdf( printData, - selectedPrinter ? { printerName: selectedPrinter } : undefined + { + ...(selectedPrinter ? { printerName: selectedPrinter } : {}), + duplex: duplexEnabled, + } ); if (!printResult.success) { @@ -363,7 +375,7 @@ const UI8: React.FC = () => { } finally { setIsPrinting(false); } - }, [originPdfUrls, pdfFiles, printers.length, selectedPrinter, navigate, isPrinting]); + }, [originPdfUrls, pdfFiles, printers.length, selectedPrinter, navigate, isPrinting, duplexEnabled]); const handlePageCountUpdate = useCallback((index: number, numPages: number) => { window.electronAPI?.log("info", `[UI8] PDF渲染成功 (index=${index}),共 ${numPages} 页`); @@ -399,6 +411,17 @@ const UI8: React.FC = () => { } }} > + { + setDuplexEnabled(enabled); + localStorage.setItem(PREFERRED_DUPLEX_KEY, enabled.toString()); + window.electronAPI?.log( + "info", + `[UI8] 双面打印设置为: ${enabled ? "启用" : "禁用"}` + ); + }} + /> {printersLoading ? "打印机加载中..." @@ -436,6 +459,7 @@ const UI8: React.FC = () => { {printerError && (
{printerError}
)} +
diff --git a/src/pages/UI9/UI9.tsx b/src/pages/UI9/UI9.tsx index 76b0601..a838e8c 100644 --- a/src/pages/UI9/UI9.tsx +++ b/src/pages/UI9/UI9.tsx @@ -27,8 +27,8 @@ const UI9: React.FC = () => { navigate("/"); }, [navigate]); - const [countdown, setCountdown] = useState(30); - const [backTime, setBackTime] = useState("确认(30S)"); + const [countdown, setCountdown] = useState(45); + const [backTime, setBackTime] = useState("确认(45S)"); useEffect(() => { if (countdown > 0) {