123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /**
- * 体位选择协调器 - 统一处理体位选中的完整逻辑
- * 确保自动选中和手动选中使用相同的业务流程
- */
- import { message } from 'antd';
- import { AppDispatch } from '@/states/store';
- import {
- setSelectedBodyPosition,
- ExtendedBodyPosition,
- } from '@/states/exam/bodyPositionListSlice';
- import { setBodyPositionDetail } from '@/states/exam/bodyPositionDetailSlice';
- import { changeBodyPosition } from '@/API/exam/changeBodyPosition';
- import { setExpEnable } from '@/API/exam/deviceActions';
- import { setBusinessFlow } from '@/states/BusinessFlowSlice';
- import emitter from '@/utils/eventEmitter';
- export const selectBodyPositionWithFullLogic = async (
- bodyPosition: ExtendedBodyPosition,
- dispatch: AppDispatch,
- currentKey: string,
- showMessage = false
- ): Promise<void> => {
- try {
- console.log(
- `[bodyPositionSelection] Selecting body position: ${bodyPosition.view_name}`
- );
- // 1. 更新选中状态
- dispatch(setSelectedBodyPosition(bodyPosition));
- // 2. 设置详情显示区域的数据
- dispatch(
- setBodyPositionDetail({
- view_name: bodyPosition.view_name,
- view_description: bodyPosition.view_description,
- view_icon_name: bodyPosition.view_icon_name,
- patient_name: bodyPosition.patient_name,
- patient_id: bodyPosition.patient_id,
- registration_number: bodyPosition.registration_number,
- study_description: bodyPosition.study_description,
- body_position_image: bodyPosition.view_big_icon_name,
- collimator_length: bodyPosition.collimator_length,
- collimator_width: bodyPosition.collimator_width,
- sid: bodyPosition.sid,
- // 🆕 添加新字段
- expose_status: bodyPosition.dview.expose_status,
- sop_instance_uid: bodyPosition.sop_instance_uid,
- })
- );
- // 3. 🆕 如果在exam模式,根据曝光状态决定是否同步设备
- if (currentKey === 'exam') {
- if (bodyPosition.dview.expose_status === 'Unexposed') {
- // 未曝光体位:同步设备,使能曝光
- await changeBodyPosition(bodyPosition.sop_instance_uid);
- // 切换体位成功后,使能发生器曝光
- await setExpEnable();
- const successMsg = `Body position changed successfully: ${bodyPosition.view_name}`;
- console.log(`[bodyPositionSelection] ${successMsg}`);
- if (showMessage) {
- message.success(successMsg);
- }
- } else {
- // 已曝光体位:跳过设备同步,仅更新显示
- console.log(
- `[bodyPositionSelection] Exposed position selected, skipping device sync: ${bodyPosition.view_name}`
- );
-
- if (showMessage) {
- message.info(`已选中已曝光体位: ${bodyPosition.view_name}`);
- }
- }
- } else {
- console.log(
- `[bodyPositionSelection] Current key is ${currentKey}, not executing changeBodyPosition.`
- );
- }
- } catch (error) {
- const errorMsg = 'Failed to change body position';
- console.error(`[bodyPositionSelection] ${errorMsg}:`, error);
- if (showMessage) {
- message.error(errorMsg);
- }
- throw error; // 向上传播错误,让调用者决定如何处理
- }
- };
- /**
- * 自动选中第一个体位(通常在进入exam时调用)
- * - exam 模式:自动选择第一个未曝光的体位
- * - process 模式:自动选择第一个已曝光的体位
- * - 其他模式:选择第一个体位
- */
- export const autoSelectFirstBodyPosition = async (
- bodyPositions: ExtendedBodyPosition[],
- dispatch: AppDispatch,
- currentKey: string
- ): Promise<void> => {
- if (bodyPositions.length === 0) {
- console.log('[bodyPositionSelection] No body positions available');
- return;
- }
- // 根据当前业务流程选择合适的体位
- let targetBodyPosition: ExtendedBodyPosition | undefined;
- if (currentKey === 'exam') {
- // exam 模式:选择第一个未曝光的体位
- targetBodyPosition = bodyPositions.find(
- (bp) => bp.dview.expose_status === 'Unexposed'
- );
- console.log(
- '[bodyPositionSelection] Auto-selecting first unexposed body position in exam mode'
- );
- } else if (currentKey === 'process') {
- // process 模式:选择第一个已曝光的体位
- targetBodyPosition = bodyPositions.find(
- (bp) => bp.dview.expose_status === 'Exposed'
- );
- console.log(
- '[bodyPositionSelection] Auto-selecting first exposed body position in process mode'
- );
- } else {
- // 其他模式:默认选择第一个
- targetBodyPosition = bodyPositions[0];
- console.log(
- `[bodyPositionSelection] Auto-selecting first body position in ${currentKey} mode`
- );
- }
- if (targetBodyPosition) {
- await selectBodyPositionWithFullLogic(
- targetBodyPosition,
- dispatch,
- currentKey,
- false // 自动选中时不显示用户消息
- );
- } else {
- console.warn(
- `[bodyPositionSelection] No suitable body position found for ${currentKey} mode`
- );
- }
- };
- /**
- * 手动选中体位(用户点击时调用)
- */
- export const manualSelectBodyPosition = async (
- bodyPosition: ExtendedBodyPosition,
- dispatch: AppDispatch,
- currentKey: string
- ): Promise<void> => {
- console.log(
- `[bodyPositionSelection] Manual selection: ${bodyPosition.view_name}`
- );
- await selectBodyPositionWithFullLogic(
- bodyPosition,
- dispatch,
- currentKey,
- true // 手动选中时显示用户消息
- );
- };
- /**
- * 带流程切换的体位选择(用户点击体位时调用,根据曝光状态自动切换流程)
- * @param bodyPosition 要选中的体位
- * @param dispatch Redux dispatch
- * @param currentKey 当前业务流程 key
- * @param allowFlowSwitch 是否允许自动切换流程(默认 true)
- */
- export const manualSelectBodyPositionWithFlowSwitch = async (
- bodyPosition: ExtendedBodyPosition,
- dispatch: AppDispatch,
- currentKey: string,
- allowFlowSwitch: boolean = true
- ): Promise<void> => {
- const isExposed = bodyPosition.dview.expose_status === 'Exposed';
- const isUnexposed = bodyPosition.dview.expose_status === 'Unexposed';
- let targetFlow = currentKey;
- let needSwitch = false;
- // 🆕 只有在允许流程切换时才判断是否需要切换
- if (allowFlowSwitch) {
- // 判断是否需要切换流程
- if (currentKey === 'exam' && isExposed) {
- targetFlow = 'process';
- needSwitch = true;
- console.log(
- `[bodyPositionSelection] Detected exposed position in exam mode, will switch to process`
- );
- } else if (currentKey === 'process' && isUnexposed) {
- targetFlow = 'exam';
- needSwitch = true;
- console.log(
- `[bodyPositionSelection] Detected unexposed position in process mode, will switch to exam`
- );
- }
- } else {
- console.log(
- `[bodyPositionSelection] Flow switch disabled, staying in ${currentKey} mode`
- );
- }
- if (needSwitch) {
- console.log(
- `[bodyPositionSelection] Switching flow from ${currentKey} to ${targetFlow}`
- );
- // 创建一个 Promise 来等待流程切换完成
- const flowSwitchPromise = new Promise<void>((resolve) => {
- // 设置一个一次性监听器
- const handler = (data: {
- from: string;
- to: string;
- timestamp: number;
- }) => {
- if (data.to === targetFlow) {
- console.log(
- `[bodyPositionSelection] Flow switch completed: ${data.from} -> ${data.to}`
- );
- // 移除监听器
- emitter.off('BUSINESS_FLOW_CHANGED', handler);
- resolve();
- }
- };
- emitter.on('BUSINESS_FLOW_CHANGED', handler);
- // 设置超时保护,防止事件永远不触发
- setTimeout(() => {
- emitter.off('BUSINESS_FLOW_CHANGED', handler);
- console.warn(
- '[bodyPositionSelection] Flow switch timeout, proceeding anyway'
- );
- resolve();
- }, 2000); // 2秒超时
- });
- // 触发流程切换
- dispatch(setBusinessFlow(targetFlow));
- // 等待流程切换完成
- await flowSwitchPromise;
- }
- // 使用正确的流程 key 选中体位
- await selectBodyPositionWithFullLogic(
- bodyPosition,
- dispatch,
- targetFlow,
- true
- );
- };
|