worklistToExam.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { addWork, clearWorks } from '../../states/exam/examWorksCacheSlice';
  2. import { setBusinessFlow } from '../../states/BusinessFlowSlice';
  3. import { fetchTaskDetails } from '../../API/patient/workActions';
  4. import { Series } from '@/domain/series';
  5. import { XImage } from '@/domain/xImage';
  6. import store from '@/states/store';
  7. import { Task } from '@/domain/work';
  8. import { dview } from '../dview';
  9. import {
  10. transformWorksToBodyPositions,
  11. setBodyPositions,
  12. } from '../../states/exam/bodyPositionListSlice';
  13. /**
  14. * 准备一个或多个 work 的详细数据用于检查
  15. * @param works - 单个 Task 对象或 Task 数组
  16. * @returns 包含完整 Views 数据的 Task 数组
  17. */
  18. export const prepareWorksForExam = async (
  19. works: Task | Task[]
  20. ): Promise<Task[]> => {
  21. // 统一转为数组处理
  22. const workArray = Array.isArray(works) ? works : [works];
  23. // 并行获取所有 work 的详细数据
  24. const preparedWorks = await Promise.all(
  25. workArray.map(async (work) => {
  26. const taskDetails = await fetchTaskDetails(work.StudyID);
  27. return {
  28. ...work,
  29. Views: taskDetails.series.flatMap<dview>((series: Series) =>
  30. series.images.map<dview>(
  31. (image: XImage) =>
  32. ({
  33. view_id: image.view_id,
  34. series_instance_uid: series.series_instance_uid,
  35. study_instance_uid: taskDetails.study_instance_uid,
  36. study_id: taskDetails.study_id,
  37. procedure_id: series.procedure_id,
  38. view_description: image.view_description,
  39. view_type: '',
  40. PrimarySopUID: image.sop_instance_uid,
  41. expose_status: image.expose_status,
  42. judged_status: image.judged_status,
  43. image_file_path: image.image_file_path,
  44. image_file: image.image_file_path,
  45. thumbnail_file: image.thumbnail_file || '',
  46. }) satisfies dview
  47. )
  48. ),
  49. } as Task;
  50. })
  51. );
  52. return preparedWorks;
  53. };
  54. const worklistToExam = async (task: Task) => {
  55. const dispatch = store.dispatch;
  56. try {
  57. // 使用公共函数准备数据
  58. const [updatedTask] = await prepareWorksForExam(task);
  59. console.log('[worklist进入检查] after prepareWorksForExam');
  60. // 判断所有体位是否已曝光(需要检查 Views 不为空)
  61. const allExposed =
  62. updatedTask.Views.length > 0 &&
  63. updatedTask.Views.every((view) => view.expose_status === 'Exposed');
  64. console.log('[worklist进入检查] 判断曝光情况,是否全部体位已曝光:', allExposed);
  65. // Clear existing works in the cache
  66. await dispatch(clearWorks());
  67. // Save the updated task to the cache
  68. await dispatch(addWork(updatedTask));
  69. // 需要先转换为体位列表
  70. const bodyPositions = await transformWorksToBodyPositions([updatedTask]);
  71. dispatch(setBodyPositions(bodyPositions));
  72. // 根据曝光状态决定跳转目标
  73. if (allExposed) {
  74. // 所有体位已曝光 - 直接进入处理界面
  75. dispatch(setBusinessFlow('process'));
  76. } else {
  77. // 有未曝光体位 - 进入检查界面
  78. dispatch(setBusinessFlow('exam'));
  79. }
  80. } catch (error) {
  81. console.error('Error in worklistToExam:', error);
  82. throw error;
  83. }
  84. };
  85. // 批量处理多个选中工单进入图像处理
  86. const worklistToProcess = async (selectedIds: string[]) => {
  87. const dispatch = store.dispatch;
  88. try {
  89. // Clear existing works in the cache
  90. dispatch(clearWorks());
  91. // 批量处理选中的工单
  92. for (const studyId of selectedIds) {
  93. // 获取基础Task信息
  94. const state = store.getState();
  95. const baseTask = state.workEntities.data.find(
  96. (task) => task.StudyID === studyId
  97. );
  98. if (!baseTask) {
  99. console.warn(`Task with StudyID ${studyId} not found in workEntities`);
  100. continue;
  101. }
  102. // Fetch task details from the backend
  103. const taskDetails = await fetchTaskDetails(studyId);
  104. // Map the fetched task details to the Task type (复用现有映射逻辑)
  105. const updatedTask: Task = {
  106. ...baseTask,
  107. Views: taskDetails.series.flatMap<dview>((series: Series) =>
  108. series.images.map<dview>(
  109. (image: XImage) =>
  110. ({
  111. view_id: image.view_id,
  112. series_instance_uid: series.series_instance_uid,
  113. study_instance_uid: taskDetails.study_instance_uid,
  114. study_id: taskDetails.study_id,
  115. procedure_id: series.procedure_id,
  116. view_description: image.view_description,
  117. view_type: '',
  118. PrimarySopUID: image.sop_instance_uid,
  119. expose_status: image.expose_status,
  120. judged_status: image.judged_status,
  121. image_file_path: image.image_file_path,
  122. image_file: image.image_file_path,
  123. thumbnail_file: image.thumbnail_file || '',
  124. }) satisfies dview
  125. )
  126. ),
  127. };
  128. // Save the updated task to the cache
  129. dispatch(addWork(updatedTask));
  130. }
  131. // 转换为体位列表
  132. const works = store.getState().examWorksCache.works;
  133. transformWorksToBodyPositions(works).then((bodyPositions) => {
  134. store.dispatch(setBodyPositions(bodyPositions));
  135. });
  136. } catch (error) {
  137. console.error('Error in worklistToProcess:', error);
  138. throw error;
  139. }
  140. };
  141. export default worklistToExam;
  142. export { worklistToProcess };