| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /**
- * InvertContrastModal - 反色对比Modal组件
- *
- * 完整布局:左侧缩略图列表 + 中间对比区域 + 底部工具栏
- */
- import React, { useEffect } from 'react';
- import { Modal } from 'antd';
- import * as cornerstone from '@cornerstonejs/core';
- import { useSelector, useDispatch } from 'react-redux';
- import { RootState, AppDispatch } from '@/states/store';
- import {
- selectIsModalOpen,
- selectSelectedPositions,
- closeInvertContrastModal,
- updateSelectedPositions
- } from '@/states/view/invertContrastSlice';
- import { StackViewerWithErrorBoundary, invertContrast } from './viewers/stack.image.viewer';
- import InvertContrastThumbnailList from './InvertContrastThumbnailList';
- import InvertContrastToolbar from './InvertContrastToolbar';
- const InvertContrastModal: React.FC = () => {
- const dispatch = useDispatch<AppDispatch>();
- const isOpen = useSelector(selectIsModalOpen);
- const selectedPositions = useSelector(selectSelectedPositions);
- const renderingEngineId = 'myRenderingEngine'; // 重用主渲染引擎
- // 获取左图和右图的URL
- const leftImageUrl = selectedPositions[0] || '';
- const rightImageUrl = selectedPositions[1] || selectedPositions[0] || ''; // 如果只有一个选择,右图和左图相同但应用反色
- const handleClose = () => {
- console.log('[InvertContrastModal] Closing modal');
- dispatch(closeInvertContrastModal());
- };
- // 应用反色效果到右侧图像
- useEffect(() => {
- if (isOpen && leftImageUrl && rightImageUrl) {
- console.log('[InvertContrastModal] Modal opened with:', { leftImageUrl, rightImageUrl });
- // Modal打开后,等待右侧viewport创建完成,然后应用反色
- const timer = setTimeout(() => {
- const rightViewportId = 'invert-contrast-right';
- try {
- console.log(`[InvertContrastModal] Applying invert to ${rightViewportId} using renderingEngine ${renderingEngineId}`);
- invertContrast(rightViewportId);
- console.log('[InvertContrastModal] Invert applied successfully');
- } catch (error) {
- console.error('[InvertContrastModal] Failed to apply invert:', error);
- console.error('[InvertContrastModal] Error stack:', error.stack);
- }
- }, 500); // 增加延迟到500ms确保viewport完全加载
- return () => clearTimeout(timer);
- }
- }, [isOpen, leftImageUrl, rightImageUrl]);
- // 工具栏事件处理
- const handleRotateLeft = () => {
- console.log('[InvertContrastModal] Rotate left clicked');
- // TODO: 实现旋转逻辑
- };
- const handleRotateRight = () => {
- console.log('[InvertContrastModal] Rotate right clicked');
- // TODO: 实现旋转逻辑
- };
- const handleHorizontalFlip = () => {
- console.log('[InvertContrastModal] Horizontal flip clicked');
- // TODO: 实现水平翻转逻辑
- };
- const handleVerticalFlip = () => {
- console.log('[InvertContrastModal] Vertical flip clicked');
- // TODO: 实现垂直翻转逻辑
- };
- const handleZoomIn = () => {
- console.log('[InvertContrastModal] Zoom in clicked');
- // TODO: 实现放大逻辑
- };
- const handleZoomOut = () => {
- console.log('[InvertContrastModal] Zoom out clicked');
- // TODO: 实现缩小逻辑
- };
- const handleReset = () => {
- console.log('[InvertContrastModal] Reset clicked');
- // TODO: 实现重置逻辑
- };
- if (!isOpen) {
- return null;
- }
- return (
- <Modal
- title="反色对比"
- open={isOpen}
- onCancel={handleClose}
- width="95vw"
- style={{
- top: 20,
- maxWidth: '95vw',
- }}
- bodyStyle={{
- height: '85vh',
- padding: 0,
- display: 'flex',
- flexDirection: 'column',
- }}
- footer={null}
- destroyOnClose // 关闭时销毁内容,避免状态残留
- maskClosable={false} // 防止点击遮罩关闭
- >
- {/* 主内容区域 */}
- <div style={{
- display: 'flex',
- flex: 1,
- height: 'calc(100% - 50px)', // 减去工具栏高度
- }}>
- {/* 左侧:缩略图列表 */}
- <div style={{
- width: '280px',
- borderRight: '1px solid #d9d9d9',
- backgroundColor: '#fafafa',
- }}>
- <InvertContrastThumbnailList />
- </div>
- {/* 右侧:对比区域 */}
- <div style={{
- flex: 1,
- display: 'grid',
- gridTemplateColumns: '1fr 1fr',
- gap: '8px',
- padding: '16px',
- backgroundColor: '#000',
- }}>
- {/* 左侧对比图 */}
- <div style={{
- border: '1px solid #d9d9d9',
- position: 'relative',
- display: 'flex',
- flexDirection: 'column',
- backgroundColor: '#000'
- }}>
- <div style={{
- position: 'absolute',
- top: 8,
- left: 8,
- zIndex: 10,
- background: 'rgba(0,0,0,0.7)',
- color: '#fff',
- padding: '4px 8px',
- borderRadius: '4px',
- fontSize: '14px'
- }}>
- {selectedPositions.length > 1 ? '原图' : '对比图'}
- </div>
- {leftImageUrl && (
- <div style={{ flex: 1, overflow: 'hidden' }}>
- <StackViewerWithErrorBoundary
- imageIndex={0}
- imageUrls={[leftImageUrl]}
- viewportId="invert-contrast-left"
- renderingEngineId={renderingEngineId}
- selected={false}
- />
- </div>
- )}
- </div>
- {/* 右侧反色图 */}
- <div style={{
- border: '1px solid #d9d9d9',
- position: 'relative',
- display: 'flex',
- flexDirection: 'column',
- backgroundColor: '#000'
- }}>
- <div style={{
- position: 'absolute',
- top: 8,
- left: 8,
- zIndex: 10,
- background: 'rgba(0,0,0,0.7)',
- color: '#fff',
- padding: '4px 8px',
- borderRadius: '4px',
- fontSize: '14px'
- }}>
- 反色图
- </div>
- {rightImageUrl && (
- <div style={{ flex: 1, overflow: 'hidden' }}>
- <StackViewerWithErrorBoundary
- imageIndex={0}
- imageUrls={[rightImageUrl]}
- viewportId="invert-contrast-right"
- renderingEngineId={renderingEngineId}
- selected={false}
- />
- </div>
- )}
- </div>
- </div>
- </div>
- {/* 底部工具栏 */}
- <InvertContrastToolbar
- onRotateLeft={handleRotateLeft}
- onRotateRight={handleRotateRight}
- onHorizontalFlip={handleHorizontalFlip}
- onVerticalFlip={handleVerticalFlip}
- onZoomIn={handleZoomIn}
- onZoomOut={handleZoomOut}
- onReset={handleReset}
- />
- </Modal>
- );
- };
- export default InvertContrastModal;
|