Parcourir la source

feat(exam): check quota when entering examination, show prompt and block access if quota is insufficient or acquisition fails

sw il y a 1 mois
Parent
commit
5ea8094227

+ 21 - 0
src/API/security/quotaActions.ts

@@ -0,0 +1,21 @@
+import axiosInstance from '../interceptor';
+
+interface QuotaResponse {
+  code: string;
+  data: {
+    total: number;
+    available: number;
+    online: boolean;
+  };
+  description: string;
+  solution: string;
+}
+
+export function getQuota(): Promise<QuotaResponse> {
+  return axiosInstance.get('/auth/resource/quota').then((response) => {
+    if (response.data.code !== '0x000000') {
+      throw new Error(`API error: ${response.data.description}`);
+    }
+    return response.data;
+  });
+}

+ 2 - 0
src/app.tsx

@@ -8,6 +8,7 @@ import { initializeProductState } from './states/productSlice';
 import './app.css';
 import { lightTheme, darkTheme } from './themes';
 import ProductSelector from './components/ProductSelector';
+import QuotaAlertModal from './pages/security/QuotaAlertModal';
 
 const locale = (window.navigator.language || 'en').toLowerCase().split('-')[0]; // Get locale from browser or default to 'en'
 import messages_en from './assets/i18n/messages/en';
@@ -66,6 +67,7 @@ function App({ children }: PropsWithChildren<React.ReactNode>) {
             }}
           >
             <AcquisitionTracer />
+            <QuotaAlertModal />
             {children}
             {process.env.NODE_ENV === 'development' && <ProductSelector />}
             <div

+ 32 - 0
src/pages/security/QuotaAlertModal.tsx

@@ -0,0 +1,32 @@
+import React from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { Modal } from 'antd';
+import { RootState } from '../../states/store';
+import { hideQuotaAlert } from '../../states/security/quotaModalSlice';
+
+const QuotaAlertModal: React.FC = () => {
+  const dispatch = useDispatch();
+  const isQuotaAlertVisible = useSelector(
+    (state: RootState) => state.quotaModal.isQuotaAlertVisible
+  );
+
+  const handleOk = () => {
+    dispatch(hideQuotaAlert());
+  };
+
+  return (
+    <Modal
+      title="Quota Alert"
+      open={isQuotaAlertVisible}
+      onOk={handleOk}
+      onCancel={handleOk}
+      footer={null}
+      centered
+      style={{ top: 20 }}
+    >
+      <p>Quota check failed. Please contact support.</p>
+    </Modal>
+  );
+};
+
+export default QuotaAlertModal;

+ 19 - 0
src/states/businessFlowMiddlewareLogic.ts

@@ -4,6 +4,8 @@ import { BusinessFlowState, setBusinessFlow } from './BusinessFlowSlice';
 import { setFeedbackOpen } from './exam/largeScreenSlice';
 import { suspendOrCompleteStudy } from '@/API/patient/workActions';
 import { RootState } from './store';
+import { getQuota } from '@/API/security/quotaActions';
+import { showQuotaAlert } from './security/quotaModalSlice';
 
 let continueBusinessFlow = '';
 
@@ -24,6 +26,23 @@ const businessFlowMiddlewareLogic: Middleware =
     );
     //进入检查
     if (action.payload === 'exam') {
+      //进入检查前判断配额
+      try {
+        const quotaResponse = await getQuota();
+        if (quotaResponse.data.available >= quotaResponse.data.total) {
+          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;
+      }
+
       prepare();
       return next(action);
     }

+ 2 - 0
src/states/store.ts

@@ -37,6 +37,7 @@ import largeScreenReducer from './exam/largeScreenSlice';
 import deviceAreaReducer from './exam/deviceAreaSlice';
 import historyPanelSwitchReducer from './patient/worklist/slices/historyPanelSwitchSlice';
 import panelSwitchForViewReducer from './panelSwitchSliceForView';
+import quotaModalReducer from './security/quotaModalSlice';
 
 const store = configureStore({
   reducer: {
@@ -69,6 +70,7 @@ const store = configureStore({
     deviceArea: deviceAreaReducer,
     historyPanelSwitch: historyPanelSwitchReducer,
     panelSwitchForView: panelSwitchForViewReducer,
+    quotaModal: quotaModalReducer,
   },
   middleware: (getDefaultMiddleware) =>
     getDefaultMiddleware().concat(