import React, { useMemo } from 'react'; import { Button, Flex, message, Modal } from 'antd'; import { useSelector } from 'react-redux'; import { RootState, useAppDispatch } from '@/states/store'; import { selectGridLayout, selectSelectedViewers, } from '@/states/view/viewerContainerSlice'; import { judgeImageThunk, saveImageAsThunk } from '@/states/exam/bodyPositionListSlice'; import { getDcmImageUrl } from '@/API/bodyPosition'; import Icon from '@/components/Icon'; import { useButtonAvailability } from '@/utils/useButtonAvailability'; /** * 图像状态控制组件 * * 功能: * - 拒绝按钮:将图像标记为拒绝状态 * - 恢复按钮:将已拒绝的图像恢复为接受状态 * - 另存为按钮:预留功能(当前禁用) * * 业务规则: * - 仅在单分格模式(1x1)下显示拒绝/恢复按钮 * - 拒绝和恢复按钮互斥显示,基于 judged_status * - 另存为按钮始终可见但禁用 */ const ImageStateControl: React.FC = () => { const dispatch = useAppDispatch(); const { disabled:ofReject } = useButtonAvailability('拒绝'); const { disabled:ofRecover } = useButtonAvailability('恢复'); const { disabled:ofSaveAs } = useButtonAvailability('另存为'); // 获取必要的状态 const selectedViewers = useSelector(selectSelectedViewers); const gridLayout = useSelector(selectGridLayout); const bodyPositionList = useSelector( (state: RootState) => state.bodyPositionList.bodyPositions ); const loading = useSelector( (state: RootState) => state.bodyPositionList.loading ); // 查找当前选中的图像 const selectedImage = useMemo(() => { if (selectedViewers.length === 0) return null; const imageUrl = selectedViewers[0]; return bodyPositionList.find( (bp) => getDcmImageUrl(bp.sop_instance_uid) === imageUrl ); }, [selectedViewers, bodyPositionList]); // 判断按钮可见性 const isSingleGrid = gridLayout === '1x1'; const judgedStatus = selectedImage?.dview?.judged_status || ''; const showRejectButton = isSingleGrid && judgedStatus !== 'Reject'; const showRestoreButton = isSingleGrid && judgedStatus === 'Reject'; // 拒绝按钮处理函数 const handleReject = async () => { if (!selectedImage) return; Modal.confirm({ title: '确认拒绝', content: `确定要拒绝选中的图像吗?`, okText: '确认拒绝', cancelText: '取消', okButtonProps: { danger: true, 'data-testid': 'modal-confirm-delete' }, cancelButtonProps: { 'data-testid': 'modal-cancel-delete' }, centered: true, onOk: async () => { try { await dispatch( judgeImageThunk({ sopInstanceUid: selectedImage.sop_instance_uid, accept: false, }) ).unwrap(); message.success('图像已拒绝'); } catch (err) { console.error('拒绝图像失败:', err); message.error('拒绝图像失败'); } }, }); }; // 恢复按钮处理函数 const handleRestore = async () => { if (!selectedImage) return; try { await dispatch( judgeImageThunk({ sopInstanceUid: selectedImage.sop_instance_uid, accept: true, }) ).unwrap(); message.success('图像已恢复'); } catch (err) { console.error('恢复图像失败:', err); message.error('恢复图像失败'); } }; // 另存为按钮处理函数 const handleSaveAs = async () => { if (!selectedImage) return; Modal.confirm({ title: '确认另存为', content: `确定要复制选中的图像吗?`, okText: '确认', cancelText: '取消', centered: true, onOk: async () => { try { await dispatch( saveImageAsThunk({ sopInstanceUid: selectedImage.sop_instance_uid, studyId: selectedImage.study_id || '', }) ).unwrap(); message.success('图像另存为成功,体位列表已更新'); } catch (err) { console.error('图像另存为失败:', err); message.error('图像另存为失败'); } }, }); }; // 另存为按钮显示条件:单分格 + 有选中图像 + 图像已曝光 const showSaveAsButton = isSingleGrid && selectedImage !== null && selectedImage?.dview?.expose_status === 'Exposed'; return ( {showRejectButton && (