# 胶片本地打印功能 - 跨平台实现方案 ## 概述 本文档描述医学影像胶片(Film)的本地打印功能实现方案,支持浏览器、Electron和Android WebView三个平台。 ## 1. 业务需求 ### 1.1 核心功能 - 打印多格子医学影像胶片(1x1、1x2、2x1、2x2布局) - 支持横向/纵向打印 - 支持多种胶片尺寸(14IN×17IN、14IN×14IN、17IN×17IN) - 跨平台支持(浏览器、Electron、Android WebView) ### 1.2 技术挑战 - Cornerstone3D Canvas内容无法直接通过window.print()打印 - 需要在不影响用户界面的情况下转换Canvas为图片 - 需要适配不同平台的打印API ## 2. 架构设计 ### 2.1 整体架构 ``` PrintControl.tsx (打印触发点) ↓ PrintManager (统一管理入口) ↓ PlatformDetector (平台检测) ↓ IPrintAdapter (适配器接口) ↓ ├── BrowserPrintAdapter (浏览器) ├── ElectronPrintAdapter (Electron) └── AndroidPrintAdapter (Android) ↓ prepareFilmForPrint() (Canvas转图片) ↓ window.print() / electronPrint / androidPrint ``` ### 2.2 设计模式 - **策略模式**:根据平台选择不同的打印策略 - **适配器模式**:统一不同平台的打印API接口 - **单例模式**:PrintManager确保只有一个实例 ## 3. 核心技术方案 ### 3.1 Canvas转图片方案 **问题**:浏览器的`window.print()`无法打印Canvas动态内容 **解决方案**:临时插入方式(推荐) ```typescript 打印前: ┌─────────────┐ │ Canvas │ ← 屏幕显示 │ (打印隐藏) │ └─────────────┘ + ┌─────────────┐ │ Image │ ← 打印显示 │ (屏幕隐藏) │ └─────────────┘ 打印后:移除Image,保留Canvas ``` **优点**: - 不破坏DOM结构 - 用户界面无变化 - Cornerstone3D状态不受影响 - 支持打印预览 ### 3.2 CSS媒体查询控制 ```css /* 屏幕显示:Canvas可见,图片隐藏 */ @media screen { .print-only { display: none !important; } .screen-only { display: block !important; } } /* 打印时:Canvas隐藏,图片可见 */ @media print { .screen-only { display: none !important; } .print-only { display: block !important; } } ``` ## 4. 文件结构 ``` src/services/print/ ├── index.ts # 统一导出 ├── types.ts # 类型定义 ├── IPrintAdapter.ts # 打印适配器接口 ├── PrintManager.ts # 打印管理器 ├── PlatformDetector.ts # 平台检测 ├── adapters/ │ ├── BrowserPrintAdapter.ts # 浏览器适配器 │ ├── ElectronPrintAdapter.ts # Electron适配器 │ └── AndroidPrintAdapter.ts # Android适配器 └── utils/ ├── canvasToImage.ts # Canvas转图片工具 ├── printStyles.ts # 打印样式 └── filmSizeMapper.ts # 胶片尺寸映射 src/pages/output/print/ ├── PrintControl.tsx (修改) # 集成打印功能 └── Film.tsx (修改) # 添加打印ID ``` ## 5. 核心接口定义 ### 5.1 打印选项 ```typescript interface PrintOptions { elementId: string; // 打印元素ID filmSize: string; // 胶片尺寸 (如 '14IN×17IN') orientation: 'portrait' | 'landscape'; paperSize: 'A3' | 'A4' | 'Letter'; margins?: { top: number; right: number; bottom: number; left: number; }; scale?: number; silent?: boolean; // 静默打印(Electron支持) } ``` ### 5.2 打印适配器接口 ```typescript interface IPrintAdapter { print(options: PrintOptions): Promise; preview?(): Promise; getSupportedFeatures(): PrintFeatures; } ``` ## 6. 平台实现差异 ### 6.1 浏览器 - 使用 `window.print()` - 通过CSS `@media print` 控制样式 - 支持打印预览 ### 6.2 Electron - 使用 `webContents.print()` - 需要在preload.js暴露打印API - 支持静默打印和更多选项 - 可以保存为PDF ### 6.3 Android WebView - 通过JSBridge调用原生Android PrintManager - 需要Android原生代码配合 - 支持系统打印对话框 ## 7. 实现流程 ### 7.1 打印完整流程 ``` 1. 用户点击"本地打印"按钮 ↓ 2. PrintManager.print(options) ↓ 3. PlatformDetector检测当前平台 ↓ 4. 选择对应的PrintAdapter ↓ 5. prepareFilmForPrint() - 遍历所有Canvas - 转换为PNG图片 - 插入到DOM ↓ 6. 调用平台特定的打印API - Browser: window.print() - Electron: electronPrint.print() - Android: androidPrint.print() ↓ 7. 用户确认或取消打印 ↓ 8. cleanupAfterPrint() - 移除临时图片 - 移除临时样式类 ``` ### 7.2 Canvas转图片详细步骤 ```typescript 1. 查找所有Canvas元素 const canvases = filmElement.querySelectorAll('canvas'); 2. 等待Canvas渲染完成 await waitForCanvasesReady(canvases); 3. 转换为高质量PNG const dataUrl = canvas.toDataURL('image/png', 1.0); 4. 创建图片元素 const img = document.createElement('img'); img.src = dataUrl; img.className = 'print-only'; 5. 插入到DOM canvas.parentElement?.appendChild(img); 6. 标记Canvas canvas.classList.add('screen-only'); ``` ## 8. 胶片尺寸映射 | 胶片尺寸 | 纸张尺寸 | 方向 | |---------|----------|------| | 14IN×17IN | A3 | Portrait | | 14IN×14IN | A4 | Portrait | | 17IN×17IN | A3 | Landscape | ## 9. 关键注意事项 ### 9.1 图像质量 - 使用 `toDataURL('image/png', 1.0)` 确保医学图像高质量 - PNG格式保证无损压缩 - 避免使用JPEG(会有压缩损失) ### 9.2 用户体验 - 打印过程中用户界面不应有任何变化 - 支持打印预览(浏览器原生支持) - 提供清晰的错误提示 ### 9.3 性能优化 - Canvas转图片是同步操作,大图可能耗时 - 考虑添加loading提示 - 多个Canvas并行处理 ### 9.4 兼容性 - 确保在所有目标平台测试 - 处理打印取消的情况 - 处理打印失败的错误 ## 10. 测试计划 ### 10.1 功能测试 - [ ] 浏览器打印(Chrome、Edge、Firefox) - [ ] Electron打印 - [ ] Android WebView打印 - [ ] 不同胶片布局(1x1、1x2、2x1、2x2) - [ ] 不同胶片尺寸 - [ ] 横向/纵向打印 ### 10.2 边界测试 - [ ] 空胶片打印 - [ ] 部分格子为空 - [ ] 打印取消 - [ ] 打印失败错误处理 ### 10.3 性能测试 - [ ] 大尺寸图像打印 - [ ] 多格子同时打印 - [ ] 打印响应时间 ## 11. 未来扩展 - 支持批量打印多个胶片 - 支持打印队列管理 - 支持保存为PDF - 支持云打印服务 - 添加打印历史记录 ## 12. 参考资料 - [Window.print() - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) - [CSS @media print](https://developer.mozilla.org/en-US/docs/Web/CSS/@media) - [Electron webContents.print()](https://www.electronjs.org/docs/latest/api/web-contents#contentsprintoptions-callback) - [Android PrintManager](https://developer.android.com/reference/android/print/PrintManager) - [HTMLCanvasElement.toDataURL()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) --- **创建日期**:2025-10-27 **最后更新**:2025-10-27 **作者**:开发团队 **版本**:1.0