| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- import { Middleware, PayloadAction } from '@reduxjs/toolkit';
- import prepare, { unprepare } from '../domain/exam/prepare';
- import { BusinessFlowState, setBusinessFlow } from './BusinessFlowSlice';
- import { setFeedbackOpen } from './exam/largeScreenSlice';
- import { setFeatureNotAvailableOpen } from './featureNotAvailableSlice';
- import { suspendOrCompleteStudy } from '@/API/patient/workActions';
- import { setExpDisable } from '@/API/exam/deviceActions';
- import { RootState } from './store';
- import { getQuota } from '@/API/security/quotaActions';
- import { showQuotaAlert } from './security/quotaModalSlice';
- import emitter from '@/utils/eventEmitter';
- import {
- setBodyPositions,
- transformWorksToBodyPositions,
- } from './exam/bodyPositionListSlice';
- import {
- worklistToProcess,
- prepareWorksForExam,
- } from '@/domain/patient/worklistToExam';
- import { executeRegisterLogic } from '@/domain/patient/registerLogic';
- import registerToExam from '@/domain/patient/registerToExam';
- import { addWork, clearWorks } from './exam/examWorksCacheSlice';
- import { resetViewerContainer } from './view/viewerContainerSlice';
- let continueBusinessFlow = '';
- const businessFlowMiddlewareLogic: Middleware =
- (store) => (next) => async (action: PayloadAction<string>) => {
- //const result = next(action);
- // console.log(
- // `[businessFlowMiddleware] Action dispatched: ${action.type} ${action.payload}`
- // );
- if (action.type !== setBusinessFlow.type) {
- return next(action); // Only handle setBusinessFlow actions
- }
- // 响应功能不可用后的继续操作
- if (action.payload === 'continueAfterFeatureNotAvailable') {
- console.log(
- `[businessFlowMiddleware] Continuing to: ${continueBusinessFlow}`
- );
- return next({ ...action, payload: continueBusinessFlow });
- }
- const state = store.getState().BusinessFlow as BusinessFlowState;
- const currentKey = state.currentKey;
- const targetKey = action.payload;
- console.log(`[businessFlowMiddleware] currentKey: ${currentKey}`);
- console.log(
- `[businessFlowMiddleware] Current business flow is now: ${state.currentKey} ; Last key was: ${state.lastKey}`
- );
- //进入检查
- if (action.payload === 'exam') {
- //进入检查前判断配额
- try {
- const quotaResponse = await getQuota();
- if (quotaResponse.data.available <= 0) {
- store.dispatch(showQuotaAlert());
- return;
- }
- if (quotaResponse.code !== '0x000000') {
- store.dispatch(showQuotaAlert());
- return;
- }
- } catch (error) {
- console.error('[businessFlowMiddleware] Quota check failed:', error);
- store.dispatch(showQuotaAlert());
- return;
- }
- if (currentKey === 'worklist' || currentKey === 'history') {
- const state = store.getState();
- // 获取选中的 study
- const selectedIds =
- currentKey === 'worklist'
- ? state.workSelection.selectedIds
- : state.historySelection.selectedIds;
- const entitiesData =
- currentKey === 'worklist'
- ? state.workEntities.data
- : state.historyEntities.data;
- if (selectedIds.length === 0) {
- console.warn('[businessFlowMiddleware] No study selected for exam');
- return; // 阻止进入 exam
- }
- const selectedWork = entitiesData.find(
- (work) => work.StudyID === selectedIds[0]
- );
- if (!selectedWork) {
- console.error('[businessFlowMiddleware] Selected study not found');
- return; // 阻止进入 exam
- }
- try {
- // 使用公共函数准备数据
- const [updatedTask] = await prepareWorksForExam(selectedWork);
- // 清空并更新缓存
- store.dispatch(clearWorks());
- store.dispatch(addWork(updatedTask));
- // 转换为 body positions
- const bodyPositions = await transformWorksToBodyPositions([
- updatedTask,
- ]);
- store.dispatch(setBodyPositions(bodyPositions));
- console.log(
- `[businessFlowMiddleware] Successfully prepared ${bodyPositions.length} body positions for exam`
- );
- } catch (error) {
- console.error(
- '[businessFlowMiddleware] Failed to prepare data for exam:',
- error
- );
- return; // 阻止进入 exam
- }
- }
- // 进入检查前,如果是从register来的,则判断数据合法性,执行注册等逻辑
- if (currentKey === 'register') {
- const systemMode = (store.getState() as RootState).systemMode.mode;
- // 如果是急诊模式,跳过验证(急诊流程已经完成注册)
- if (systemMode === 'Emergency') {
- console.log(
- '[businessFlowMiddleware] Emergency mode, skipping register validation'
- );
- // 急诊模式下仍需要准备 body positions
- try {
- const state = store.getState();
- const works = state.examWorksCache.works;
- const bodyPositions = await transformWorksToBodyPositions(works);
- store.dispatch(setBodyPositions(bodyPositions));
- } catch (error) {
- console.error(
- '[businessFlowMiddleware] Failed to prepare body positions:',
- error
- );
- return; // 阻止进入exam
- }
- } else {
- // 正常注册流程,需要验证
- const result = await executeRegisterLogic(store);
- if (!result.success) {
- console.log(
- '[businessFlowMiddleware] Register validation failed, blocking entry to exam'
- );
- return; // 阻止进入exam
- }
- try {
- await registerToExam(result.data!);
- const state = store.getState();
- const works = state.examWorksCache.works;
- await transformWorksToBodyPositions(works)
- .then((bodyPositions) => {
- store.dispatch(setBodyPositions(bodyPositions));
- })
- .catch((error) => {
- console.error(
- '[businessFlowMiddleware] Transform works to body positions failed:',
- error
- );
- return; // 阻止进入exam
- });
- } catch (_error) {
- console.log(
- '[businessFlowMiddleware] Register validation failed',
- _error
- );
- return; // 阻止进入exam
- }
- console.log(
- '[businessFlowMiddleware] Register validation succeeded, proceeding to exam'
- );
- }
- }
- prepare();
- return next(action);
- }
- if (action.payload === 'process') {
- if (isFromExamToView(action.payload, currentKey)) {
- //从检查进入图像处理,有可能是曝光导致的,怎么知道呢?看发生器状态
- if (store.getState().generatorMonitor.acquisitionState === 1) {
- //发生器正在采集
- console.log(
- `[businessFlowMiddleware] Exiting exam flow, but generator is still acquiring.`
- );
- return next(action); // 发生器正在采集,不能退出
- } else {
- //非曝光导致的从检查进入处理 // 说明从检查退出 , 执行清理
- console.log(
- `[businessFlowMiddleware] Exiting exam flow, last key was: ${state.lastKey}`
- );
- // 离开检查前,禁止发生器曝光
- try {
- await setExpDisable();
- } catch (error) {
- console.error('[businessFlowMiddleware] setExpDisable Failed to disable exposure:', error);
- }
- unprepare();
- }
- } else {
- //不是从检查进入图像处理,
- if (currentKey === 'worklist') {
- //从工单进入图像处理,准备数据
- const state = store.getState() as RootState;
- const selectedIds = state.workSelection.selectedIds;
- if (selectedIds.length > 0) {
- try {
- await worklistToProcess(selectedIds);
- console.log(
- `[businessFlowMiddleware] Successfully processed ${selectedIds.length} selected works from worklist to process`
- );
- } catch (error) {
- console.error(
- '[businessFlowMiddleware] Error processing works from worklist:',
- error
- );
- // 可以选择是否阻止进入process,这里我们选择继续
- return;
- }
- } else {
- console.warn(
- '[businessFlowMiddleware] No works selected in worklist to process'
- );
- }
- }
- if (currentKey === 'history') {
- //从历史进入图像处理,
- //从工单进入图像处理,准备数据
- const state = store.getState() as RootState;
- const selectedIds = state.historySelection.selectedIds;
- if (selectedIds.length > 0) {
- try {
- await worklistToProcess(selectedIds);
- console.log(
- `[businessFlowMiddleware] Successfully processed ${selectedIds.length} selected works from worklist to process`
- );
- } catch (error) {
- console.error(
- '[businessFlowMiddleware] Error processing works from worklist:',
- error
- );
- // 可以选择是否阻止进入process,这里我们选择继续
- return;
- }
- } else {
- console.warn(
- '[businessFlowMiddleware] No works selected in worklist to process'
- );
- }
- }
- return next(action);
- }
- }
- if (
- action.payload === 'archivelist' ||
- action.payload === 'bin' ||
- action.payload === 'outputlist' ||
- action.payload === 'print'
- ) {
- console.log(
- `[businessFlowMiddleware] Feature not available: ${action.payload}`
- );
- continueBusinessFlow = action.payload; // 保存要继续的业务流程
- store.dispatch(setFeatureNotAvailableOpen(true));
- return;
- }
- if (isLeavingProcess(action.payload, currentKey)) {
- // 说明从图像处理退出 , 执行清理
- console.log(
- `[businessFlowMiddleware] Leaving process flow, last key was: ${state.lastKey}`
- );
- // 重置 viewerContainerSlice 到初始状态
- store.dispatch(resetViewerContainer());
- }
- //退出检查的判断和退出处理的判断
- if ((
- isExitingExam(action.payload, currentKey) &&
- action.payload !== 'exitExamCompleted' &&
- action.payload !== 'exitExamSuspended' &&
- action.payload !== 'process' // 从检查进入处理,不需要检查曝光情况
- ) ||
- isLeavingProcess(action.payload, currentKey) &&
- action.payload !== 'exitExamCompleted' &&
- action.payload !== 'exitExamSuspended' &&
- action.payload !== 'exam'
- ){
- console.log(
- `[businessFlowMiddleware] Exiting exam flow to go to : ${action.payload}`
- );
- const exposureStatus = store.getState().bodyPositionList.exposureStatus;
- console.log(
- `[businessFlowMiddleware] Exposure status: ${exposureStatus}`
- );
- if (exposureStatus === 'Half Exposed') {
- store.dispatch(setFeedbackOpen(true)); //显示反馈框
- // store.dispatch({ type: 'SET_CONTINUE_BUSINESS_FLOW', payload: currentKey });
- continueBusinessFlow = action.payload; // 保存退出检查时,要去哪个业务流程
- return; //阻止退出exam 或者 process
- } else if (exposureStatus === 'Fully Exposed') {
- // Notify backend
- console.log(
- '[businessFlowMiddleware] Fully Exposed, notifying backend'
- );
- const studyId =
- (store.getState() as RootState)?.bodyPositionList?.selectedBodyPosition
- ?.work?.StudyID ?? '';
- suspendOrCompleteStudy(studyId, 'Completed').then(() => {
- console.log(`[businessFlowMiddleware] 全曝光,通知后端完成`)
- }).catch((error) => {
- console.log(`[businessFlowMiddleware] 全曝光,通知后端失败 ${error}`);
- });
- // Proceed with the action
- return next(action);
- } else if (exposureStatus === 'Not Exposed') {
- // Proceed with the action
- return next(action);
- }
- }
- //退出检查的中间过程
- if (action.payload === 'exitExamCompleted') {
- // Notify backend with different interfaces for completed and suspended
- console.log(
- `[businessFlowMiddleware] Notifying backend for ${action.payload}`
- );
- // 通知服务端。
- const studyId =
- (store.getState() as RootState)?.bodyPositionList?.selectedBodyPosition
- ?.work?.StudyID ?? '';
- if (!studyId) {
- console.error(
- '[businessFlowMiddleware] No study ID found for the selected body position.'
- );
- }
- await suspendOrCompleteStudy(studyId, 'Completed');
- return next({ ...action, payload: continueBusinessFlow });
- }
- if (action.payload === 'exitExamSuspended') {
- // Notify backend with different interfaces for completed and suspended
- const studyId =
- (store.getState() as RootState)?.bodyPositionList?.selectedBodyPosition
- ?.work?.StudyID ?? '';
- if (!studyId) {
- console.error(
- '[businessFlowMiddleware] No study ID found for the selected body position.'
- );
- }
- await suspendOrCompleteStudy(studyId, 'InProgress');
- console.log(
- `[businessFlowMiddleware] Notifying backend for ${action.payload}`
- );
- return next({ ...action, payload: continueBusinessFlow });
- }
- const result = next(action);
- // 发射业务流程切换完成事件
- emitter.emit('BUSINESS_FLOW_CHANGED', {
- from: currentKey,
- to: targetKey,
- timestamp: Date.now(),
- });
- console.log(
- `[businessFlowMiddleware] Emitted BUSINESS_FLOW_CHANGED event: ${currentKey} -> ${targetKey}`
- );
- return result;
- };
- /**
- * 从检查到图像处理
- */
- function isFromExamToView(currentAction: string, currentKey: string): boolean {
- return currentAction === 'process' && currentKey === 'exam';
- }
- function isExitingExam(currentAction: string, currentKey: string): boolean {
- console.log(
- `[businessFlowMiddleware] Checking if exiting exam: ${currentAction} vs ${currentKey}`
- );
- return currentAction !== 'exam' && currentKey === 'exam';
- }
- function isLeavingProcess(currentAction: string, currentKey: string): boolean {
- return currentAction !== 'process' && currentKey === 'process';
- }
- export default businessFlowMiddlewareLogic;
|