|
@@ -18,10 +18,19 @@ import StackViewer, {
|
|
|
RotateCounterclockwise90,
|
|
|
setOriginalSize,
|
|
|
VerticalFlip,
|
|
|
+ activateLengthMeasurement,
|
|
|
+ deactivateLengthMeasurement,
|
|
|
+ clearLengthMeasurements,
|
|
|
} from './viewers/stack.image.viewer';
|
|
|
import { useSelector, useDispatch } from 'react-redux';
|
|
|
import store, { RootState } from '@/states/store';
|
|
|
import { clearAction } from '@/states/view/functionAreaSlice';
|
|
|
+import {
|
|
|
+ clearMeasurementAction,
|
|
|
+ selectCurrentMeasurementAction,
|
|
|
+ setToolActive,
|
|
|
+ setToolInactive,
|
|
|
+} from '@/states/view/measurementPanelSlice';
|
|
|
import * as cornerstone from '@cornerstonejs/core';
|
|
|
import * as cornerstoneTools from '@cornerstonejs/tools';
|
|
|
import { SystemMode } from '@/states/systemModeSlice';
|
|
@@ -73,6 +82,7 @@ const ViewerContainer: React.FC<ViewerContainerProps> = ({ imageUrls }) => {
|
|
|
const [selectedViewers, setSelectedViewers] = useState<number[]>([]);
|
|
|
const [gridLayout, setGridLayout] = useState<string>('1x1');
|
|
|
const action = useSelector((state: RootState) => state.functionArea.action);
|
|
|
+ const measurementAction = useSelector(selectCurrentMeasurementAction);
|
|
|
const dispatch = useDispatch();
|
|
|
const selectedBodyPosition = useSelector(
|
|
|
(state: RootState) => state.bodyPositionList.selectedBodyPosition
|
|
@@ -309,6 +319,49 @@ const ViewerContainer: React.FC<ViewerContainerProps> = ({ imageUrls }) => {
|
|
|
ApplyColormap(`viewport-${index}`);
|
|
|
});
|
|
|
break;
|
|
|
+ // ==================== 线段测量相关操作 ====================
|
|
|
+ case '线段测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ activateLengthMeasurement(`viewport-${index}`);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,为所有可见的 viewport 激活
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ activateLengthMeasurement(`viewport-${i}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Activating Length Measurement');
|
|
|
+ break;
|
|
|
+ case '清除测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ clearLengthMeasurements(`viewport-${index}`);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,清除所有可见 viewport 的测量
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ clearLengthMeasurements(`viewport-${i}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Clearing Length Measurements');
|
|
|
+ break;
|
|
|
+ case '停用线段测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ deactivateLengthMeasurement(`viewport-${index}`);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,停用所有可见 viewport 的测量工具
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ deactivateLengthMeasurement(`viewport-${i}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Deactivating Length Measurement');
|
|
|
+ break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -316,6 +369,125 @@ const ViewerContainer: React.FC<ViewerContainerProps> = ({ imageUrls }) => {
|
|
|
}
|
|
|
}, [action]);
|
|
|
|
|
|
+ // ==================== 测量面板 Action 处理 ====================
|
|
|
+ useEffect(() => {
|
|
|
+ if (measurementAction) {
|
|
|
+ console.log(`[ViewerContainer] 处理测量操作: ${measurementAction}`);
|
|
|
+
|
|
|
+ // 处理测量相关操作
|
|
|
+ switch (measurementAction) {
|
|
|
+ case '线段测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ const success = activateLengthMeasurement(`viewport-${index}`);
|
|
|
+ if (success) {
|
|
|
+ dispatch(
|
|
|
+ setToolActive({
|
|
|
+ toolName: 'LengthTool',
|
|
|
+ viewportId: `viewport-${index}`,
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,为所有可见的 viewport 激活
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ const success = activateLengthMeasurement(`viewport-${i}`);
|
|
|
+ if (success) {
|
|
|
+ dispatch(
|
|
|
+ setToolActive({
|
|
|
+ toolName: 'LengthTool',
|
|
|
+ viewportId: `viewport-${i}`,
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Activating Length Measurement from MeasurementPanel');
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '清除测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ clearLengthMeasurements(`viewport-${index}`);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,清除所有可见 viewport 的测量
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ clearLengthMeasurements(`viewport-${i}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Clearing Length Measurements from MeasurementPanel');
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '停用线段测量':
|
|
|
+ if (selectedViewers.length > 0) {
|
|
|
+ selectedViewers.forEach((index) => {
|
|
|
+ const success = deactivateLengthMeasurement(`viewport-${index}`);
|
|
|
+ if (success) {
|
|
|
+ dispatch(
|
|
|
+ setToolInactive({
|
|
|
+ toolName: 'LengthTool',
|
|
|
+ viewportId: `viewport-${index}`,
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有选中的 viewport,停用所有可见 viewport 的测量工具
|
|
|
+ const visibleViewportCount = getVisibleViewportCount();
|
|
|
+ for (let i = 0; i < visibleViewportCount; i++) {
|
|
|
+ const success = deactivateLengthMeasurement(`viewport-${i}`);
|
|
|
+ if (success) {
|
|
|
+ dispatch(
|
|
|
+ setToolInactive({
|
|
|
+ toolName: 'LengthTool',
|
|
|
+ viewportId: `viewport-${i}`,
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log('Deactivating Length Measurement from MeasurementPanel');
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '角度测量':
|
|
|
+ console.log('Angle Measurement - 功能待实现');
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '测量校正':
|
|
|
+ console.log('Measurement Calibration - 功能待实现');
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ console.log(`未处理的测量操作: ${measurementAction}`);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理测量 action
|
|
|
+ dispatch(clearMeasurementAction());
|
|
|
+ }
|
|
|
+ }, [measurementAction, selectedViewers, gridLayout, dispatch]);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前可见的 viewport 数量
|
|
|
+ */
|
|
|
+ const getVisibleViewportCount = (): number => {
|
|
|
+ switch (gridLayout) {
|
|
|
+ case '1x1':
|
|
|
+ return 1;
|
|
|
+ case '1x2':
|
|
|
+ case '2x1':
|
|
|
+ return Math.min(2, imageUrls.length);
|
|
|
+ case '2x2':
|
|
|
+ return Math.min(4, imageUrls.length);
|
|
|
+ default:
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
const handleSelectViewer = (index: number, event) => {
|
|
|
setSelectedViewers((prev) =>
|
|
|
prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index]
|