Browse Source

fix: 修复反色对比功能多选问题,改为单选模式

- 将 InvertContrastThumbnailList 中的 Checkbox 改为 Radio 单选按钮
- 修改 handlePositionToggle 为 handlePositionSelect,实现单选逻辑
- 移除多选相关的 isDisabled 禁用逻辑和最多2个的限制
- 更新组件注释和 UI 文案,去掉'(最多2个)'提示
- 简化选择逻辑,每次选择直接替换为新选择
- 优化交互体验,整个卡片区域可点击

改动文件:
- src/pages/view/components/InvertContrastThumbnailList.tsx
- CHANGELOG.md
- package.json (版本更新: 1.12.2 -> 1.12.3)
dengdx 3 tuần trước cách đây
mục cha
commit
909d626300
3 tập tin đã thay đổi với 48 bổ sung32 xóa
  1. 32 0
      CHANGELOG.md
  2. 1 1
      package.json
  3. 15 31
      src/pages/view/components/InvertContrastThumbnailList.tsx

+ 32 - 0
CHANGELOG.md

@@ -2,6 +2,38 @@
 
 本项目的所有重要变更都将记录在此文件中。
 
+## [1.12.3] - 2025-12-18 10:07
+
+### 修复 (Fixed)
+- **反色对比功能多选问题** ([src/pages/view/components/InvertContrastThumbnailList.tsx](src/pages/view/components/InvertContrastThumbnailList.tsx))
+  - 修复反色对比Modal打开后左侧列表可以多选的问题
+  - 将 Checkbox(复选框)改为 Radio(单选按钮)
+  - 修改选择逻辑:从"最多选择2个体位"改为"单选一个体位"
+  - 移除 isDisabled 禁用逻辑和超过2个时的限制判断
+  - 更新组件注释:从"支持多选用于对比"改为"支持单选用于反色对比"
+  - 更新 UI 文案:去掉"(最多2个)"提示
+  - 简化选择逻辑:handlePositionToggle 改为 handlePositionSelect,每次选择直接替换
+  - 优化交互体验:整个卡片区域可点击,移除按钮嵌套
+
+**核心改进:**
+- 交互更清晰:用户明确知道只能选择一个体位进行反色对比
+- 符合业务语义:反色对比的重点是反色效果,而不是两张不同图像的对比
+- 简化逻辑:去除多选相关的复杂判断和禁用逻辑
+- 提升体验:整个卡片可点击,交互更自然
+
+**技术实现:**
+- 导入组件变更:Checkbox → Radio
+- 函数重构:handlePositionToggle(bodyPosition, checked) → handlePositionSelect(bodyPosition)
+- 逻辑简化:直接使用 dispatch(updateSelectedPositions({ positions: [dcmUrl] }))
+- UI 优化:移除 disabled 判断,简化点击事件处理
+
+**改动文件:**
+- src/pages/view/components/InvertContrastThumbnailList.tsx
+- CHANGELOG.md
+- package.json (版本更新: 1.12.2 -> 1.12.3)
+
+---
+
 ## [1.12.2] - 2025-12-18 09:54
 
 ### 修复 (Fixed)

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "zsis",
-  "version": "1.12.2",
+  "version": "1.12.3",
   "private": true,
   "description": "医学成像系统",
   "main": "main.js",

+ 15 - 31
src/pages/view/components/InvertContrastThumbnailList.tsx

@@ -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' && (