Просмотр исходного кода

feat(report): implement preview function for diagnostic reports

sw 3 недель назад
Родитель
Сommit
262a76f16a

+ 5 - 4
src/API/patient/DiagnosisReportActions.ts

@@ -40,10 +40,11 @@ export const saveDiagnosisReport = async (
 export const previewDiagnosisReport = async (
   report: DiagnosisReport
 ): Promise<DiagnosisReportResponse> => {
-  const response = await axiosInstance.post(
-    `/auth/report/preview`,
-    report
-  );
+const response = await axiosInstance.post(
+  `/auth/report/preview`,
+  report,
+  { responseType: 'blob' }
+);
   return response.data;
 };
 

+ 2 - 0
src/pages/patient/DiagnosticReport/index.tsx

@@ -3,6 +3,7 @@ import { useAppDispatch } from '@/states/store';
 import { ReportHeader } from './components/ReportHeader';
 import { ReportMain } from './components/ReportMain';
 import { ReportFooter } from './components/ReportFooter';
+import PdfPreviewModal from '@/states/patient/DiagnosticReport/PdfPreviewModal';
 
 const DiagnosticReport: React.FC = () => {
   const dispatch = useAppDispatch();
@@ -17,6 +18,7 @@ const DiagnosticReport: React.FC = () => {
       <ReportHeader />
       <ReportMain className="flex-1 overflow-scroll" />
       <ReportFooter reportData={reportData} />
+      <PdfPreviewModal></PdfPreviewModal>
     </div>
   );
 };

+ 52 - 0
src/states/patient/DiagnosticReport/PdfPreviewModal.tsx

@@ -0,0 +1,52 @@
+import { Modal, Result } from 'antd';
+import { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { RootState, useAppDispatch } from '@/states/store';
+import { setNeedsPreview } from './slice';
+
+export default function PdfPreviewModal() {
+  const [url, setUrl] = useState<string | null>(null);
+  const dispatch = useAppDispatch();
+  const previewResponse = useSelector(
+    (state: RootState) => state.diagnosticReport.previewResponse
+  );
+  const needsPreview = useSelector(
+    (state: RootState) => state.diagnosticReport.needsPreview
+  );
+
+  useEffect(() => {
+    if (!needsPreview) return; // 如果不需要预览,则不处理
+    console.log('previewResponse', previewResponse);
+    if (!previewResponse) return setUrl(null);
+
+    const blob = new Blob([previewResponse], { type: 'application/pdf' });
+    const u = URL.createObjectURL(blob);
+    setUrl(u);
+    return () => {
+      URL.revokeObjectURL(u);
+      // clearPdfBlob();
+    };
+  }, [needsPreview, previewResponse]);
+
+  return (
+    <Modal
+      title="PDF 预览"
+      open={needsPreview}
+      onCancel={() => {
+        dispatch(setNeedsPreview(false));
+      }}
+      footer={null}
+      width="90vw"
+      bodyStyle={{ height: '85vh', padding: 0 }}
+    >
+      {!url ? (
+        <Result status="warning" title="PDF 已失效" />
+      ) : (
+        <iframe
+          src={url}
+          style={{ width: '100%', height: '100%', border: 'none' }}
+        />
+      )}
+    </Modal>
+  );
+}

+ 2 - 1
src/states/patient/DiagnosticReport/previewReportThunk.ts

@@ -11,7 +11,7 @@ import _ from 'cypress/types/lodash';
 
 export const previewReportThunk = createAsyncThunk(
   'diagnosticReport/previewReport',
-   
+
   async (_, { getState }) => {
     const state = getState() as RootState;
     const report0 = {
@@ -32,6 +32,7 @@ export const previewReportThunk = createAsyncThunk(
       review_physician: state.baseInfo.reviewPhysician,
     };
     const response = await previewDiagnosisReport(report0);
+    console.log('【诊断报告】预览返回', response);
     return response;
   }
 );

+ 12 - 2
src/states/patient/DiagnosticReport/slice.ts

@@ -5,18 +5,23 @@ import { previewReportThunk } from './previewReportThunk';
 interface DiagnosticReportState {
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
   report: any;
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  previewResponse: any;
   isPreviewing: boolean;
   isSaving: boolean;
   isFinished: boolean;
   visible: boolean;
+  needsPreview: boolean;
 }
 
 const initialState: DiagnosticReportState = {
   report: null,
+  previewResponse: null,
   isPreviewing: false,
   isSaving: false,
   isFinished: false,
   visible: false,
+  needsPreview: false,
 };
 
 const diagnosticReportSlice = createSlice({
@@ -32,6 +37,9 @@ const diagnosticReportSlice = createSlice({
     toggleVisible(state) {
       state.visible = !state.visible;
     },
+    setNeedsPreview(state, action: PayloadAction<boolean>) {
+      state.needsPreview = action.payload;
+    },
   },
   extraReducers: (builder) => {
     builder
@@ -48,8 +56,10 @@ const diagnosticReportSlice = createSlice({
       .addCase(previewReportThunk.pending, (state) => {
         state.isPreviewing = true;
       })
-      .addCase(previewReportThunk.fulfilled, (state) => {
+      .addCase(previewReportThunk.fulfilled, (state, action) => {
         state.isPreviewing = false;
+        state.needsPreview = true;
+        state.previewResponse = action.payload; // Store the response in the new field
       })
       .addCase(previewReportThunk.rejected, (state) => {
         state.isPreviewing = false;
@@ -57,6 +67,6 @@ const diagnosticReportSlice = createSlice({
   },
 });
 
-export const { finishReport, setVisible, toggleVisible } =
+export const { finishReport, setVisible, toggleVisible, setNeedsPreview } =
   diagnosticReportSlice.actions;
 export default diagnosticReportSlice.reducer;