worklist-historylist-bin-多选功能设计.md 11 KB

Worklist/HistoryList/Bin 多选功能设计文档

1. 需求概述

1.1 功能需求

  • 多选功能:在 worklist、historylist 和 bin 表格中支持多选操作
  • 鼠标操作:在桌面环境下,使用 Ctrl + 鼠标点击 进行多选/取消多选
  • 触摸屏操作:在触摸屏环境下,单击选中,再次单击取消选中
  • 视觉反馈:选中的行需要有明显的视觉标识

1.2 技术要求

  • 基于 Ant Design Table 组件实现
  • 兼容现有的 Redux 状态管理
  • 支持不同设备环境(桌面/触摸屏)
  • 保持现有功能不变

2. 参与者分析

2.1 组件参与者

组件 职责 文件位置
WorklistTable 表格展示组件,处理行点击事件 src/pages/patient/components/WorklistTable.tsx
WorklistPage Worklist 页面容器,管理状态和事件处理 src/pages/patient/worklist.tsx
HistoryListPage HistoryList 页面容器,管理状态和事件处理 src/pages/patient/HistoryList.tsx
BinPage Bin 页面容器,管理状态和事件处理 src/pages/patient/Bin.tsx
useMultiSelection 自定义 Hook,处理多选逻辑 src/hooks/useMultiSelection.ts
useTouchDoubleClick 现有 Hook,处理触摸屏双击事件 src/hooks/useTouchDoubleClick.ts

2.2 状态管理参与者

Redux Slice 职责 文件位置
workSelectionSlice 管理 worklist 的选中状态 src/states/patient/worklist/slices/workSlice.ts
historySelectionSlice 管理 historylist 的选中状态 src/states/patient/worklist/slices/history.ts
binSelectionSlice 管理 bin 的选中状态 src/states/patient/bin/slices/binSlice.ts
selectedPatientSlice 管理选中患者信息 src/states/patient/worklist/slices/selectedPatientSlice.ts
thumbnailListSlice 管理缩略图列表 src/states/patient/worklist/slices/thumbnailListSlice.ts

2.3 数据结构参与者

数据结构 职责 文件位置
Task 任务数据模型 src/domain/work.ts
SelectionState 选中状态接口 src/states/list_template/type.model.ts
WorkFilter Worklist 过滤条件 src/states/patient/worklist/types/workfilter.ts
BinFilter Bin 过滤条件 src/states/patient/bin/types/binFilter.ts

3. 架构设计

3.1 整体架构图

graph TB
    subgraph "用户界面层"
        A[WorklistPage] --> B[WorklistTable]
        C[HistoryListPage] --> D[WorklistTable]
        E[BinPage] --> F[WorklistTable]
    end
    
    subgraph "逻辑层"
        B --> G[useMultiSelection Hook]
        D --> G
        F --> G
        G --> H[useTouchDoubleClick Hook]
    end
    
    subgraph "状态管理层"
        I[workSelectionSlice] --> J[Redux Store]
        K[historySelectionSlice] --> J
        L[binSelectionSlice] --> J
        M[thumbnailListSlice] --> J
    end
    
    subgraph "数据层"
        N[API Service] --> O[后端服务]
    end
    
    B --> I
    D --> K
    F --> L
    I --> J
    K --> J
    L --> J
    J --> N
    N --> O

3.2 数据流图

flowchart TD
    A[用户操作] --> B{设备类型}
    B -->|桌面| C[Ctrl+点击]
    B -->|触摸屏| D[单击]
    
    C --> E[useMultiSelection]
    D --> E
    
    E --> F[判断当前选中状态]
    F --> G{是否已选中}
    G -->|是| H[从选中列表移除]
    G -->|否| I[添加到选中列表]
    
    H --> J[更新Redux状态]
    I --> J
    
    J --> K[更新表格行样式]
    J --> L[更新缩略图]
    J --> M[更新操作面板]

3.3 泳道图

swimlane
    title 多选功能交互流程
    participant "用户" as User
    participant "WorklistTable" as Table
    participant "useMultiSelection" as Hook
    participant "Redux Store" as Store
    participant "缩略图组件" as Thumbnails
    participant "操作面板" as Operations

    User --> Table: 点击表格行
    Table --> Hook: 处理点击事件
    Hook --> Hook: 判断设备类型
    Hook --> Hook: 判断Ctrl键状态
    Hook --> Store: 更新选中状态
    Store --> Table: 更新行样式
    Store --> Thumbnails: 更新选中项
    Store --> Operations: 更新操作按钮状态

4. 详细设计

4.1 多选 Hook 设计

// src/hooks/useMultiSelection.ts
interface UseMultiSelectionOptions {
  selectedIds: string[];
  onSelectionChange: (ids: string[]) => void;
  enableMultiSelect?: boolean;
}

export const useMultiSelection = ({
  selectedIds,
  onSelectionChange,
  enableMultiSelect = true,
}: UseMultiSelectionOptions) => {
  const handleRowClick = (record: Task, event: React.MouseEvent) => {
    if (!enableMultiSelect) {
      onSelectionChange([record.StudyID]);
      return;
    }

    const isCtrlPressed = event.ctrlKey || event.metaKey;
    const studyId = record.StudyID;

    if (isCtrlPressed) {
      // 桌面环境:Ctrl+点击进行多选/取消多选
      const newSelectedIds = selectedIds.includes(studyId)
        ? selectedIds.filter(id => id !== studyId)
        : [...selectedIds, studyId];
      onSelectionChange(newSelectedIds);
    } else {
      // 普通点击:清空其他选择,只选中当前项
      onSelectionChange([studyId]);
    }
  };

  const handleTouchClick = (record: Task) => {
    // 触摸屏环境:单击选中,再次单击取消选中
    const studyId = record.StudyID;
    const newSelectedIds = selectedIds.includes(studyId)
      ? selectedIds.filter(id => id !== studyId)
      : [studyId];
    onSelectionChange(newSelectedIds);
  };

  return {
    handleRowClick,
    handleTouchClick,
  };
};

4.2 表格组件修改

// 修改 WorklistTable 组件
const WorklistTable: React.FC<WorklistTableProps> = ({
  // ... 其他 props
  selectedIds,
  handleRowClick,
  handleRowDoubleClick,
}) => {
  const { handleTouchClick } = useMultiSelection({
    selectedIds,
    onSelectionChange: handleRowClick,
  });

  const { handleTouchStart } = useTouchDoubleClick({
    onDoubleClick: handleRowDoubleClick,
    delay: 300,
  });

  return (
    <Table<DataType>
      // ... 其他配置
      onRow={(record, index) => ({
        onClick: (event) => handleRowClick(record, event),
        onDoubleClick: () => handleRowDoubleClick(record),
        onTouchStart: (e) => {
          handleTouchStart(e);
          handleTouchClick(record);
        },
        style: {
          cursor: 'pointer',
          userSelect: 'none',
          backgroundColor: selectedIds.includes(record.StudyID) 
            ? 'rgba(255, 255, 0, 0.3)' 
            : 'transparent',
        },
      })}
      rowClassName={(record) =>
        selectedIds.includes(record.StudyID)
          ? 'bg-yellow-500 hover:bg-yellow-800'
          : ''
      }
    />
  );
};

4.3 Redux 状态管理

现有的 Redux slices 已经包含了 selectionSlice,它提供了 setSelectedIdsclearSelection 方法。我们需要确保这些方法在多选场景下正常工作。

// 在各个页面组件中使用
const handleRowClick = (record: Task, event: React.MouseEvent) => {
  const { handleRowClick } = useMultiSelection({
    selectedIds,
    onSelectionChange: (newIds) => {
      dispatch(workSelectionSlice.actions.setSelectedIds(newIds));
      dispatch(updateThumbnailsFromWorkSelection(newIds));
    },
  });

  handleRowClick(record, event);
};

5. 实现计划

5.1 文件修改清单

文件 修改类型 描述
src/hooks/useMultiSelection.ts 新增 多选逻辑 Hook
src/pages/patient/components/WorklistTable.tsx 修改 添加多选支持
src/pages/patient/worklist.tsx 修改 更新行点击处理逻辑
src/pages/patient/HistoryList.tsx 修改 更新行点击处理逻辑
src/pages/patient/Bin.tsx 修改 更新行点击处理逻辑
src/states/patient/worklist/slices/thumbnailListSlice.ts 修改 确保支持多选缩略图更新

5.2 实现步骤

  1. 创建多选 Hook

    • 实现 useMultiSelection Hook
    • 处理桌面和触摸屏的不同交互逻辑
    • 提供清晰的 API 接口
  2. 修改表格组件

    • 更新 WorklistTable 组件以支持多选
    • 添加视觉反馈(行样式变化)
    • 保持现有双击功能不变
  3. 更新页面组件

    • 修改 worklist.tsxHistoryList.tsxBin.tsx
    • 集成多选 Hook
    • 更新 Redux 状态管理
  4. 测试和优化

    • 测试不同设备环境下的交互
    • 优化性能和用户体验
    • 确保现有功能不受影响

6. 测试方案

6.1 功能测试

测试场景 预期结果 测试方法
桌面环境单击表格行 只选中当前行,清空其他选择 使用鼠标单击表格行
桌面环境Ctrl+单击表格行 多选/取消多选当前行 按住Ctrl键单击表格行
触摸屏单击表格行 选中/取消选中当前行 使用触摸屏单击表格行
双击表格行 触发双击事件(如进入检查) 双击表格行
选中行后切换页面 保持选中状态 在不同页面间切换
清空选择 所有选择被清空 点击清空按钮

6.2 兼容性测试

测试项目 测试内容 预期结果
浏览器兼容性 Chrome, Firefox, Safari, Edge 功能正常
设备兼容性 桌面、平板、手机 交互方式适配
屏幕分辨率 不同分辨率下显示 界面布局正常
性能测试 大量数据下的多选 响应速度可接受

6.3 边界情况测试

测试场景 预期结果
空数据表格 无操作响应
选中所有行后删除 删除后选择状态正确
网络中断时操作 操作被正确缓存
快速连续点击 正确处理点击事件

7. 潜在问题与解决方案

7.1 潜在问题

  1. 性能问题

    • 大量数据时多选操作可能导致性能下降
    • 频繁的 Redux 状态更新可能影响响应速度
  2. 交互冲突

    • 现有的双击功能可能与新的多选功能冲突
    • 触摸屏的双击检测可能与单击选择冲突
  3. 状态同步

    • 多个页面之间的选中状态可能不同步
    • 缩略图更新可能不及时

7.2 解决方案

  1. 性能优化

    • 使用虚拟滚动处理大量数据
    • 批量更新 Redux 状态
    • 优化重渲染逻辑
  2. 交互优化

    • 明确区分单击和双击事件
    • 在触摸屏上使用不同的交互方式
    • 添加视觉提示帮助用户理解交互方式
  3. 状态管理

    • 确保每个页面独立管理自己的选中状态
    • 使用 Redux 中间件处理状态同步
    • 添加加载状态处理异步操作

8. 总结

本设计文档详细描述了 worklist、historylist 和 bin 表格多选功能的实现方案。通过使用自定义 Hook 和修改现有组件,我们可以在保持现有功能不变的前提下,添加多选功能。该方案支持桌面和触摸屏两种交互方式,并提供了清晰的视觉反馈。

主要特点:

  • 统一的多选逻辑,支持不同设备环境
  • 基于 Redux 的状态管理,确保数据一致性
  • 良好的用户体验和视觉反馈
  • 完善的测试方案和问题处理机制

该方案可以有效地满足用户的多选需求,同时保持代码的可维护性和扩展性。