|
|
@@ -1,6 +1,6 @@
|
|
|
import React from 'react';
|
|
|
import { useSelector, useDispatch } from 'react-redux';
|
|
|
-import { Checkbox } from 'antd';
|
|
|
+import { Radio } from 'antd';
|
|
|
import { RootState, AppDispatch } from '../../../states/store';
|
|
|
import { updateSelectedPositions } from '../../../states/view/invertContrastSlice';
|
|
|
import { getExposedImageUrl, getViewIconUrl, getDcmImageUrl } from '../../../API/bodyPosition';
|
|
|
@@ -10,8 +10,8 @@ import { selectSelectedPositions } from '../../../states/view/invertContrastSlic
|
|
|
/**
|
|
|
* InvertContrastThumbnailList - 反色对比缩略图列表组件
|
|
|
*
|
|
|
- * 功能:显示当前检查的所有体位缩略图,支持多选用于对比
|
|
|
- * 最多选择2个体位:第一个作为原图,第二个作为反色图
|
|
|
+ * 功能:显示当前检查的所有体位缩略图,支持单选用于反色对比
|
|
|
+ * 选择一个体位:左侧显示原图,右侧显示反色图
|
|
|
*/
|
|
|
const InvertContrastThumbnailList: React.FC = () => {
|
|
|
const dispatch = useDispatch<AppDispatch>();
|
|
|
@@ -25,23 +25,12 @@ const InvertContrastThumbnailList: React.FC = () => {
|
|
|
const selectedPositions = useSelector(selectSelectedPositions);
|
|
|
|
|
|
/**
|
|
|
- * 处理体位选择变更 - 传递DCM URL而非JPG URL
|
|
|
+ * 处理体位选择变更 - 单选模式,每次选择替换当前选择
|
|
|
*/
|
|
|
- const handlePositionToggle = (bodyPosition: ExtendedBodyPosition, checked: boolean) => {
|
|
|
+ const handlePositionSelect = (bodyPosition: ExtendedBodyPosition) => {
|
|
|
const dcmUrl = getDcmImageUrl(bodyPosition.sop_instance_uid);
|
|
|
- let newSelected = [...selectedPositions];
|
|
|
-
|
|
|
- if (checked) {
|
|
|
- // 添加选择(最多2个)
|
|
|
- if (!newSelected.includes(dcmUrl) && newSelected.length < 2) {
|
|
|
- newSelected.push(dcmUrl);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 移除选择
|
|
|
- newSelected = newSelected.filter(url => url !== dcmUrl);
|
|
|
- }
|
|
|
-
|
|
|
- dispatch(updateSelectedPositions({ positions: newSelected }));
|
|
|
+ // 单选模式:直接替换为当前选择的体位
|
|
|
+ dispatch(updateSelectedPositions({ positions: [dcmUrl] }));
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
@@ -72,32 +61,30 @@ const InvertContrastThumbnailList: React.FC = () => {
|
|
|
}}
|
|
|
>
|
|
|
<div className="text-sm font-medium text-gray-700 mb-2 px-2">
|
|
|
- 选择对比体位 (最多2个)
|
|
|
+ 选择对比体位
|
|
|
</div>
|
|
|
|
|
|
{bodyPositions.map((bodyPosition, index) => {
|
|
|
const imageUrl = getPositionImageUrl(bodyPosition);
|
|
|
const isSelected = isPositionSelected(bodyPosition);
|
|
|
- const isDisabled = selectedPositions.length >= 2 && !isSelected; // 超过2个时禁用未选中项
|
|
|
|
|
|
return (
|
|
|
<div
|
|
|
key={bodyPosition.sop_instance_uid || index}
|
|
|
className={`relative border rounded-md overflow-hidden transition-all ${
|
|
|
isSelected ? 'border-blue-500 shadow-md' : 'border-gray-300'
|
|
|
- } ${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:shadow-sm'}`}
|
|
|
+ } cursor-pointer hover:shadow-sm`}
|
|
|
style={{
|
|
|
width: '100%',
|
|
|
aspectRatio: '1',
|
|
|
backgroundColor: '#fff'
|
|
|
}}
|
|
|
+ onClick={() => handlePositionSelect(bodyPosition)}
|
|
|
>
|
|
|
- {/* 复选框 */}
|
|
|
+ {/* 单选按钮 */}
|
|
|
<div className="absolute top-1 left-1 z-20">
|
|
|
- <Checkbox
|
|
|
+ <Radio
|
|
|
checked={isSelected}
|
|
|
- disabled={isDisabled}
|
|
|
- onChange={(e) => handlePositionToggle(bodyPosition, e.target.checked)}
|
|
|
style={{
|
|
|
backgroundColor: 'rgba(255,255,255,0.9)',
|
|
|
borderRadius: '2px',
|
|
|
@@ -111,18 +98,15 @@ const InvertContrastThumbnailList: React.FC = () => {
|
|
|
{bodyPosition.view_name}
|
|
|
</div>
|
|
|
|
|
|
- {/* 缩略图 - 改为可点击的按钮 */}
|
|
|
- <button
|
|
|
- className={`${isSelected ? 'ring-2 ring-blue-500' : ''} w-full h-full overflow-hidden focus:outline-none`}
|
|
|
- onClick={() => handlePositionToggle(bodyPosition, !isSelected)}
|
|
|
- >
|
|
|
+ {/* 缩略图 */}
|
|
|
+ <div className={`${isSelected ? 'ring-2 ring-blue-500' : ''} w-full h-full overflow-hidden`}>
|
|
|
<img
|
|
|
src={imageUrl}
|
|
|
alt={bodyPosition.view_name}
|
|
|
className="w-full h-full object-cover cursor-pointer"
|
|
|
draggable={false}
|
|
|
/>
|
|
|
- </button>
|
|
|
+ </div>
|
|
|
|
|
|
{/* 状态标签 */}
|
|
|
{bodyPosition.dview.expose_status === 'Exposed' && (
|