Quellcode durchsuchen

实现:打印操作面板上的本地打印按钮的可用性控制。可用的条件:只有当前胶片上有图像时才可以打印

dengdx vor 1 Monat
Ursprung
Commit
57834852e1

+ 8 - 1
src/pages/output/print/DcmCell.tsx

@@ -8,6 +8,8 @@ import {
 } from '@cornerstonejs/core';
 import { v4 as uuidv4 } from 'uuid';
 import { getDcmImageUrl } from '@/API/bodyPosition';
+import { useDispatch } from 'react-redux';
+import { addImageToCell, Film } from '@/states/print/printSlice';
 // import { dicomWebImageLoader } from '@cornerstonejs/dicom-web-image-loader';
 
 // // 初始化图像加载器(关键:必须提前注册)
@@ -23,10 +25,12 @@ import { getDcmImageUrl } from '@/API/bodyPosition';
 
 type ViewportContainerProps = {
   imageId: string;
+  currentFilm:Film; // 传入当前胶片对象
+    indexOfCell: number; // 可选,格子索引
   className?: string;   // 可选
 };
 
-const ViewportContainer = ({ imageId, className }: ViewportContainerProps) => {
+const ViewportContainer = ({ imageId, className,currentFilm,indexOfCell }: ViewportContainerProps) => {
     console.log(`ViewportContainer 得到的属性 :${imageId}`)
   const viewportRef = useRef(null);
   const [renderingEngine, setRenderingEngine] = useState<any>(null);
@@ -34,6 +38,7 @@ const ViewportContainer = ({ imageId, className }: ViewportContainerProps) => {
   const [hasImage, setHasImage] = useState<boolean>(false); // 跟踪是否已加载图像
     // ✅ 用 useMemo 保证 id 只生成一次
   const viewportId = useMemo(() => `stackViewport-${imageId}-${uuidv4()}`, []);
+  const dispatch = useDispatch();
 
   // 初始化 Cornerstone 渲染引擎
   useEffect(() => {
@@ -142,6 +147,8 @@ const ViewportContainer = ({ imageId, className }: ViewportContainerProps) => {
       stackViewport.render();
       // 5. 成功加载后隐藏提示
       setHasImage(true);
+      // 6. 通知到slice
+      dispatch(addImageToCell({index:indexOfCell,imageId:imageIds[0]}));
     } catch (error) {
       console.error('加载图像失败:', error);
     }

+ 9 - 9
src/pages/output/print/Film.tsx

@@ -45,9 +45,9 @@ const Film: React.FC = () => {
   const getViewportIdByUrl = (url: string): string | null => {
     return `viewport-${url}`;
   };
-  const generateCell = (imageId) => {
+  const generateCell = (imageId,indexOfCell) => {
     const actualUrl = getDcmImageUrl(imageId)
-    return (<ViewportContainer imageId={imageId} />);
+    return (<ViewportContainer imageId={imageId} currentFilm={currentFilm} indexOfCell={indexOfCell} />);
     return (
       <div
         key={imageId}
@@ -83,24 +83,24 @@ const Film: React.FC = () => {
     const { layout } = currentFilm;
     const cells: any[] = [];
     if (layout === '1x1') {
-      cells.push(generateCell(uuidv4()));
+      cells.push(generateCell(null,0));
       return cells;
     } else if (layout === '1x2') {
-      cells.push(generateCell(uuidv4()));
-      cells.push(generateCell(uuidv4()));
+      cells.push(generateCell(null,0));
+      cells.push(generateCell(null,1));
       return cells;
     } else if (layout === '2x1') {
-      cells.push(generateCell(uuidv4()));
-      cells.push(generateCell(uuidv4()));
+      cells.push(generateCell(null,0));
+      cells.push(generateCell(null,1));
       return cells;
     } else if (layout === '2x2') {
       for (let i = 0; i < 4; i++) {
-        cells.push(generateCell(uuidv4()));
+        cells.push(generateCell(null,i));
       }
       return cells;
     }
     console.warn(`没有得到布局信息`);
-    return generateCell(uuidv4());//不知道什么布局,认为只有一个格子
+    return generateCell(null,0);//不知道什么布局,认为只有一个格子
   }
 
   const handleCellClick = (sop_instance_uid: string) => {

+ 29 - 7
src/pages/output/print/PrintControl.tsx

@@ -1,4 +1,4 @@
-import React, { useState, useMemo } from 'react';
+import React, { useState, useMemo, useEffect } from 'react';
 import { Select, Button, Space, message } from 'antd';
 import { showNotImplemented } from '@/utils/notificationHelper';
 import { useAppSelector } from '@/states/store';
@@ -8,6 +8,7 @@ const PrintControl: React.FC = () => {
   const [selectedNode, setSelectedNode] = useState<string>('');
   const [selectedSize, setSelectedSize] = useState<string>('14IN×17IN');
   const [isPrinting, setIsPrinting] = useState(false);
+  const [canPrint, setCanPrint] = useState<boolean>(false);
 
   // 获取当前胶片信息
   const activeFilm = useAppSelector((state) => {
@@ -24,12 +25,20 @@ const PrintControl: React.FC = () => {
     { value: 'node1', label: 'TestPrinter' },
     // { value: 'node2', label: '打印节点2' },
   ];
+  // 检查当前胶片是否有图像
+  const checkIfCanPrint = () => {
+    const hasImages = activeFilm?.hasImage(activeFilm.images)
+    console.log(`开始计算有效图像数量 ${hasImages}`)
+    if (activeFilm && activeFilm.hasImage(activeFilm.images)) {
+      setCanPrint(true);
+    } else {
+      setCanPrint(false);
+    }
+  };
 
-  const filmSizes = [
-    { value: '14IN×17IN', label: '14IN×17IN' },
-    { value: '14IN×14IN', label: '14IN×14IN' },
-    { value: '17IN×17IN', label: '17IN×17IN' },
-  ];
+  useEffect(() => {
+    checkIfCanPrint();
+  }, [activeFilm,activeFilm?.images]);
 
   const handleLocalPrint = async () => {
     if (isPrinting) {
@@ -37,6 +46,11 @@ const PrintControl: React.FC = () => {
       return;
     }
 
+    if (!canPrint) {
+      message.warning('当前胶片上没有图像,无法打印');
+      return;
+    }
+
     try {
       setIsPrinting(true);
 
@@ -75,6 +89,14 @@ const PrintControl: React.FC = () => {
   const handleDicomPrint = () => {
     showNotImplemented('DICOM打印');
   };
+  const filmSizes = [
+    { value: '14IN×17IN', label: '14IN×17IN' },
+    { value: '14IN×14IN', label: '14IN×14IN' },
+    { value: '17IN×17IN', label: '17IN×17IN' },
+  ];
+  useEffect(() => {
+    checkIfCanPrint();
+  }, [activeFilm]);
 
   return (
     <div>
@@ -117,7 +139,7 @@ const PrintControl: React.FC = () => {
               type="primary"
               block
               onClick={handleLocalPrint}
-              disabled={!selectedNode}
+              disabled={!canPrint}
             >
               本地打印
             </Button>

+ 13 - 3
src/states/print/printSlice.ts

@@ -3,11 +3,12 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
 export type FilmLayout = '1x1' | '1x2' | '2x1' | '2x2';
 export type FilmOrientation = 'horizontal' | 'vertical';
 
-interface Film {
+export interface Film {
   id: string;
   layout: FilmLayout;
   orientation: FilmOrientation;
   images: (string | null)[]; // 图像ID或null(空格子)
+  hasImage: (images) => boolean;
 }
 
 interface PrintState {
@@ -27,6 +28,9 @@ const initialFilm: Film = {
    * 存储每个成员本质上是个sop instance uid
    */
   images: [null], // 1x1只有一个格子
+  hasImage:(images)=>{
+    console.log(`检查胶片 是否有图像:`, images);
+    return images.some(item => item !== null);},
 };
 
 const initialState: PrintState = {
@@ -47,6 +51,9 @@ const printSlice = createSlice({
         layout: '1x1',
         orientation: 'vertical',
         images: [null],
+        hasImage:(images)=>{
+          console.log(`检查胶片 ${newId} 是否有图像:`, images);
+          return images.some(item => item !== null);},
       };
       state.films.push(newFilm);
       state.activeFilmId = newId;
@@ -122,9 +129,12 @@ const printSlice = createSlice({
     // 添加图像到指定格子
     addImageToCell: (state, action: PayloadAction<{ index: number; imageId: string }>) => {
       const film = state.films.find((f) => f.id === state.activeFilmId);
+      console.log(`添加图像到胶片 ${state.activeFilmId} 的格子 ${action.payload.index} 图像ID ${action.payload.imageId}`);
       if (!film) return;
-      
-      film.images[action.payload.index] = action.payload.imageId;
+      console.log(`向胶片 ${film.id} 的格子 ${action.payload.index} 添加图像 ${action.payload.imageId}`);
+      const tmpImages = [...film.images];
+      tmpImages[action.payload.index] = action.payload.imageId;
+      film.images = tmpImages;
     },
   },
 });