فهرست منبع

解决worillist 中因添加RIS项而引起的多选问题

dengdx 1 ماه پیش
والد
کامیت
3e2f16979b
3فایلهای تغییر یافته به همراه93 افزوده شده و 28 حذف شده
  1. 40 13
      src/hooks/useMultiSelection.ts
  2. 43 12
      src/pages/patient/components/WorklistTable.tsx
  3. 10 3
      src/pages/patient/worklist.tsx

+ 40 - 13
src/hooks/useMultiSelection.ts

@@ -3,7 +3,8 @@ import { Task } from '@/domain/work';
 
 interface UseMultiSelectionOptions {
   selectedIds: string[];
-  onSelectionChange: (ids: string[]) => void;
+  selectedSecondaryIds?: string[];  // 可选
+  onSelectionChange: ((ids: string[], secondaryIds?: string[]) => void);
   enableMultiSelect?: boolean;
 }
 
@@ -13,9 +14,11 @@ interface UseMultiSelectionOptions {
  */
 export const useMultiSelection = ({
   selectedIds,
+  selectedSecondaryIds,
   onSelectionChange,
   enableMultiSelect = true,
 }: UseMultiSelectionOptions) => {
+  const useDualIdMode = selectedSecondaryIds !== undefined;
   /**
    * 处理桌面环境的行点击事件
    * @param record - 点击的行数据
@@ -24,22 +27,46 @@ export const useMultiSelection = ({
   const handleRowClick = useCallback((record: Task, event: React.MouseEvent) => {
     if (!enableMultiSelect) {
       // 如果禁用多选,只选中当前项
-      onSelectionChange([record.StudyID]);
+      onSelectionChange([record.StudyID], useDualIdMode ? [record.entry_id ?? ''] : undefined);
       return;
     }
 
     const studyId = record.StudyID;
-    
+    const entryId = record.entry_id;
+
     if (event.ctrlKey || event.metaKey) {
       // 桌面环境:Ctrl+点击进行多选/取消多选
-      const newSelectedIds = selectedIds.includes(studyId)
-        ? selectedIds.filter(id => id !== studyId) // 取消选择
-        : [...selectedIds, studyId]; // 添加选择
-      
-      onSelectionChange(newSelectedIds);
+      let newSelectedIds;
+      let newSelectedSecondaryIds;
+      if (useDualIdMode) {
+        if (studyId) {//本地task
+          const index = selectedIds.indexOf(studyId);
+          if (index > -1) {//说明已经在选中数组中了,需要取消选择
+            newSelectedIds = selectedIds.splice(index, 1);
+            newSelectedSecondaryIds = selectedSecondaryIds?.splice(index, 1);
+          } else {
+            newSelectedIds = [...selectedIds, studyId];
+            newSelectedSecondaryIds = [...(selectedSecondaryIds ?? []), entryId ?? ''];
+          }
+        } else if (entryId) {//ris task
+          const index = selectedSecondaryIds.indexOf(entryId);
+          if (index > -1) {//说明已经在选中数组中了,需要取消选择
+            newSelectedIds = selectedIds.splice(index, 1);
+            newSelectedSecondaryIds = selectedSecondaryIds?.splice(index, 1);
+          } else {
+            newSelectedIds = [...selectedIds, studyId];
+            newSelectedSecondaryIds = [...(selectedSecondaryIds ?? []), entryId ?? ''];
+          }
+        }
+      } else {
+        newSelectedIds = selectedIds.includes(studyId)
+          ? selectedIds.filter(id => id !== studyId) // 取消选择
+          : [...selectedIds, studyId]; // 添加选择
+      }
+      onSelectionChange(newSelectedIds, newSelectedSecondaryIds);
     } else {
       // 普通点击:清空其他选择,只选中当前项
-      onSelectionChange([studyId]);
+      onSelectionChange([studyId], useDualIdMode ? [record.entry_id ?? ''] : undefined);
     }
   }, [selectedIds, onSelectionChange, enableMultiSelect]);
 
@@ -49,13 +76,13 @@ export const useMultiSelection = ({
    */
   const handleTouchClick = useCallback((record: Task) => {
     const studyId = record.StudyID;
-    
+
     // 触摸屏环境:单击选中,再次单击取消选中
     const newSelectedIds = selectedIds.includes(studyId)
       ? selectedIds.filter(id => id !== studyId) // 取消选择
       : [studyId]; // 添加选择
-    
-    onSelectionChange(newSelectedIds);
+
+    onSelectionChange(newSelectedIds, useDualIdMode ? [record.entry_id ?? ''] : undefined);
   }, [selectedIds, onSelectionChange]);
 
   /**
@@ -73,7 +100,7 @@ export const useMultiSelection = ({
       handleRowClick(record, event);
     } else {
       // 默认行为:只选中当前项
-      onSelectionChange([record.StudyID]);
+      onSelectionChange([record.StudyID], useDualIdMode ? [record.entry_id ?? ''] : undefined);
     }
   }, [handleRowClick, handleTouchClick, onSelectionChange]);
 

+ 43 - 12
src/pages/patient/components/WorklistTable.tsx

@@ -380,7 +380,8 @@ interface WorklistTableProps {
   filters?: WorkFilter;
   page?: number;
   pageSize?: number;
-  selectedIds: string[];
+  selectedIds: string[];                      // 必填(保持向后兼容)
+  selectedSecondaryIds?: string[];            // 可选(新增)
   handleRowClick: (record: Task, event?: React.MouseEvent) => void;
   handleRowDoubleClick: (record: Task) => void;
 }
@@ -392,9 +393,38 @@ const WorklistTable: React.FC<WorklistTableProps> = ({
   // page,
   // pageSize,
   selectedIds,
+  selectedSecondaryIds,  // 可能为 undefined
   handleRowClick,
   handleRowDoubleClick,
 }) => {
+  // 判断是否使用双ID模式
+  const useDualIdMode = selectedSecondaryIds !== undefined;
+  // 生成 rowKey
+  const getRowKey = (record: Task): string => {
+    if (useDualIdMode) {
+      // 新模式:使用 StudyID + entry_id 组合
+      return `${record.StudyID || 'no-study'}_${record.entry_id || 'no-entry'}`;
+    }
+    // 兼容模式:仅使用 StudyID
+    return record.StudyID;
+  };
+  // 判断记录是否被选中
+  const isRecordSelected = (record: Task): boolean => {
+    if (useDualIdMode) {
+      // 新模式:检查双ID
+      if (record.StudyID) {
+        const indexByStudyId = selectedIds.indexOf(record.StudyID);
+        return selectedSecondaryIds[indexByStudyId] === record.entry_id;
+      } else if (record.entry_id) {
+        const indexByEntryId = selectedSecondaryIds.indexOf(record.entry_id);
+        return selectedIds[indexByEntryId] === record.StudyID;
+      }
+      throw new Error('Record must have at least StudyID or entry_id defined in dual ID mode.');
+    } else {
+      // 兼容模式:仅检查 StudyID
+      return selectedIds.includes(record.StudyID);
+    }
+  };
   // 根据传入的配置过滤和排序列
   const visibleColumns = useMemo(() => {
     // 如果没有配置,显示所有列(保持当前行为)
@@ -437,15 +467,15 @@ const WorklistTable: React.FC<WorklistTableProps> = ({
 
   const handleResize =
     (index: number) =>
-    (_: React.SyntheticEvent<Element>, { size }: ResizeCallbackData) => {
-      console.log('Resizing column:', index, size);
-      const newColumns = [...columns];
-      newColumns[index] = {
-        ...newColumns[index],
-        width: size.width,
+      (_: React.SyntheticEvent<Element>, { size }: ResizeCallbackData) => {
+        console.log('Resizing column:', index, size);
+        const newColumns = [...columns];
+        newColumns[index] = {
+          ...newColumns[index],
+          width: size.width,
+        };
+        setColumns(newColumns);
       };
-      setColumns(newColumns);
-    };
 
   const mergedColumns = columns.map<TableColumnsType<DataType>[number]>(
     (col, index) => ({
@@ -467,9 +497,10 @@ const WorklistTable: React.FC<WorklistTableProps> = ({
       scroll={{ x: 'max-content' }}
       components={{ header: { cell: ResizableTitle } }}
       dataSource={worklistData}
-      rowKey="StudyID"
+      rowKey={getRowKey}
       pagination={false}
       onRow={(record, index) => {
+        const isSelected = isRecordSelected(record);
         const { handleTouchStart } = useTouchDoubleClick({
           onDoubleClick: () => handleRowDoubleClick(record),
           delay: 300,
@@ -485,7 +516,7 @@ const WorklistTable: React.FC<WorklistTableProps> = ({
           style: {
             cursor: 'pointer',
             userSelect: 'none', // 防止文本选择
-            backgroundColor: selectedIds.includes(record.StudyID)
+            backgroundColor: isSelected
               ? 'rgba(255, 255, 0, 0.3)'
               : 'transparent',
           },
@@ -493,7 +524,7 @@ const WorklistTable: React.FC<WorklistTableProps> = ({
       }}
       rowHoverable={false}
       rowClassName={(record) =>
-        selectedIds.includes(record.StudyID)
+        isRecordSelected(record)
           ? 'bg-yellow-500 hover:bg-yellow-800'
           : ''
       }

+ 10 - 3
src/pages/patient/worklist.tsx

@@ -43,6 +43,9 @@ const WorklistPage: React.FC = () => {
   const selectedIds = useSelector(
     (state: RootState) => state.workSelection.selectedIds
   );
+  const selectedSecondaryIds = useSelector(  // 获取次要选中ID列表
+    (state: RootState) => state.workSelection.selectedSecondaryIds
+  );
   const worklistData = useSelector(
     (state: RootState) => state.workEntities.data
   );
@@ -90,12 +93,13 @@ const WorklistPage: React.FC = () => {
   // 使用多选 Hook
   const { handleRowClick } = useMultiSelection({
     selectedIds,
-    onSelectionChange: (newIds) => {
-      console.log('Selected IDs changed:', newIds);
+    selectedSecondaryIds,
+    onSelectionChange: (newIds,secondNewIds) => {
+      console.log('Selected IDs changed:', newIds,secondNewIds);
       
       // 如果只有一个选中项,设置选中患者用于显示照片
       if (newIds.length === 1) {
-        const selectedRecord = worklistData.find(item => item.StudyID === newIds[0]);
+        const selectedRecord = worklistData.find(item => item.StudyID === newIds[0]&&item.entry_id===secondNewIds?.[0]);
         if (selectedRecord) {
           setSelectedPatientForPortrait(selectedRecord);
         }
@@ -106,6 +110,7 @@ const WorklistPage: React.FC = () => {
       
       // 更新 Redux 状态(用于其他功能)
       dispatch(workSelectionSlice.actions.setSelectedIds(newIds));
+      dispatch(workSelectionSlice.actions.setSelectedSecondaryIds(secondNewIds??[]));
       dispatch(updateThumbnailsFromWorkSelection(newIds));
     },
     enableMultiSelect: true,
@@ -142,6 +147,7 @@ const WorklistPage: React.FC = () => {
               page={page}
               pageSize={pageSize}
               selectedIds={selectedIds}
+              selectedSecondaryIds={selectedSecondaryIds}  // 新增
               handleRowClick={handleRowClickInternal}
               handleRowDoubleClick={handleRowDoubleClick}
             />
@@ -189,6 +195,7 @@ const WorklistPage: React.FC = () => {
                   page={page}
                   pageSize={pageSize}
                   selectedIds={selectedIds}
+                  selectedSecondaryIds={selectedSecondaryIds}  // 新增
                   handleRowClick={handleRowClickInternal}
                   handleRowDoubleClick={handleRowDoubleClick}
                 />