PrintControl.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import React, { useState, useMemo, useEffect } from 'react';
  2. import { Select, Button, Space, message } from 'antd';
  3. import { showNotImplemented } from '@/utils/notificationHelper';
  4. import { useAppSelector } from '@/states/store';
  5. import { getPrintManager } from '@/services/print';
  6. import { selectFilmHasImage } from '@/states/print/selectors';
  7. import { useSelector } from 'react-redux';
  8. const PrintControl: React.FC = () => {
  9. const [selectedNode, setSelectedNode] = useState<string>('');
  10. const [selectedSize, setSelectedSize] = useState<string>('14IN×17IN');
  11. const [isPrinting, setIsPrinting] = useState(false);
  12. const [canPrint, setCanPrint] = useState<boolean>(false);
  13. // 获取当前胶片信息
  14. const activeFilm = useAppSelector((state) => {
  15. const films = state.print.films;
  16. const activeId = state.print.activeFilmId;
  17. return films.find(f => f.id === activeId);
  18. });
  19. const hasImage = useSelector(() => selectFilmHasImage(activeFilm));
  20. // 创建打印管理器实例
  21. const printManager = useMemo(() => getPrintManager(), []);
  22. // TODO: 打印节点需要从后端API获取
  23. const printNodes = [
  24. { value: 'node1', label: 'TestPrinter' },
  25. // { value: 'node2', label: '打印节点2' },
  26. ];
  27. // 检查当前胶片是否有图像
  28. const checkIfCanPrint = () => {
  29. if (activeFilm && hasImage) {
  30. setCanPrint(true);
  31. } else {
  32. setCanPrint(false);
  33. }
  34. };
  35. useEffect(() => {
  36. checkIfCanPrint();
  37. }, [activeFilm, activeFilm?.images]);
  38. const handleLocalPrint = async () => {
  39. if (isPrinting) {
  40. message.warning('打印正在进行中,请稍候');
  41. return;
  42. }
  43. if (!canPrint) {
  44. message.warning('当前胶片上没有图像,无法打印');
  45. return;
  46. }
  47. try {
  48. setIsPrinting(true);
  49. console.log('[本地打印] 开始打印,胶片尺寸:', selectedSize);
  50. // 调试:检查 Electron 环境
  51. console.log('[本地打印] 检查 window.electronPrint:', !!window.electronPrint);
  52. console.log('[本地打印] 检查 window.electronAPI:', !!window.electronAPI);
  53. // 检查胶片元素是否存在
  54. const filmElement = document.getElementById('film-print-area');
  55. if (!filmElement) {
  56. throw new Error('未找到胶片元素 film-print-area');
  57. }
  58. // 检查Canvas数量
  59. const canvases = filmElement.querySelectorAll('canvas');
  60. console.log(`[本地打印] 发现 ${canvases.length} 个Canvas元素`);
  61. await printManager.print({
  62. elementId: 'film-print-area',
  63. filmSize: selectedSize,
  64. orientation: activeFilm?.orientation === 'horizontal' ? 'landscape' : 'portrait',
  65. silent: false, // 显示打印对话框,让用户选择打印机
  66. });
  67. message.info('打印结束');
  68. } catch (error) {
  69. console.error('[本地打印] 打印失败:', error);
  70. message.error(`打印失败: ${error.message || '未知错误'}`);
  71. } finally {
  72. setIsPrinting(false);
  73. }
  74. };
  75. const handleDicomPrint = () => {
  76. showNotImplemented('DICOM打印');
  77. };
  78. const filmSizes = [
  79. { value: '14IN×17IN', label: '14IN×17IN' },
  80. { value: '14IN×14IN', label: '14IN×14IN' },
  81. { value: '17IN×17IN', label: '17IN×17IN' },
  82. ];
  83. useEffect(() => {
  84. checkIfCanPrint();
  85. }, [activeFilm]);
  86. return (
  87. <div>
  88. <div className="font-semibold">打印设置</div>
  89. <Space direction="vertical" style={{ width: '100%' }} size="middle">
  90. {/* 打印节点下拉框 */}
  91. <div>
  92. <div className="mb-1">打印节点</div>
  93. <Select
  94. style={{ width: '100%' }}
  95. placeholder="选择打印节点"
  96. value={selectedNode}
  97. onChange={setSelectedNode}
  98. options={printNodes}
  99. // TODO: 暂时disabled,等待后端API
  100. disabled={printNodes.length === 0}
  101. />
  102. {printNodes.length === 0 && (
  103. <div className="text-gray-400 mt-1">
  104. TODO: 等待后端API提供打印节点
  105. </div>
  106. )}
  107. </div>
  108. {/* 尺寸下拉框 */}
  109. <div>
  110. <div className="mb-1">胶片尺寸</div>
  111. <Select
  112. style={{ width: '100%' }}
  113. value={selectedSize}
  114. onChange={setSelectedSize}
  115. options={filmSizes}
  116. />
  117. </div>
  118. {/* 打印按钮 */}
  119. <div>
  120. <Space direction="vertical" style={{ width: '100%' }}>
  121. <Button
  122. type="primary"
  123. block
  124. onClick={handleLocalPrint}
  125. disabled={!canPrint}
  126. >
  127. 本地打印
  128. </Button>
  129. <Button
  130. block
  131. onClick={handleDicomPrint}
  132. disabled={!selectedNode}
  133. >
  134. DICOM打印
  135. </Button>
  136. </Space>
  137. </div>
  138. </Space>
  139. </div>
  140. );
  141. };
  142. export default PrintControl;