feat: 导入dicom基本交互

This commit is contained in:
mozzie 2024-09-02 11:18:49 +08:00
parent 7fb2511ba4
commit d4a43e211a
3 changed files with 91 additions and 20 deletions

View File

@ -47,19 +47,20 @@ const registerIpcMainHandlers = (
running ? pythonManager.startFlask() : pythonManager.stopFlask(); running ? pythonManager.startFlask() : pythonManager.stopFlask();
}); });
ipcMain.on("scan-dicom", async (event) => { ipcMain.on("import-dicom-dialog-visible", async (event) => {
const result = await dialog.showOpenDialog({ const result = await dialog.showOpenDialog({
properties: ["openDirectory"], properties: ["openDirectory"],
}); });
if (result.canceled) return null; if (result.canceled) return null;
const filePaths = result.filePaths[0]; const filePaths = result.filePaths[0];
const dcmPaths = await findDcmFiles(filePaths) event.reply("scan-start");
const dcmPaths = await findDcmFiles(filePaths);
const batchSize = os.cpus().length * 1 || 10; const batchSize = os.cpus().length * 1 || 10;
const items = await processFilesInBatches(dcmPaths, batchSize); const items = await processFilesInBatches(dcmPaths, batchSize);
const structDicom = await structureMetadata(items, (progress) => { const structDicom = await structureMetadata(items, (progress) => {
event.reply('scan-progress', progress) event.reply("scan-progress", progress);
}); });
event.reply('scan-progress-done', structDicom) event.reply("scan-progress-done", structDicom);
}); });
}; };

View File

@ -1,15 +1,31 @@
import { Button } from "@/components/ui/button"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Progress } from "@/components/ui/progress"; import { Progress } from "@/components/ui/progress";
import { ToastAction } from "@/components/ui/toast";
import { useToast } from "@/components/ui/use-toast";
import { RocketIcon } from "@radix-ui/react-icons";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
interface ScanProgress { interface ScanProgress {
percentage: number; percentage: number;
} }
const defaultProgress = {
percentage: 0,
};
export const Datasource = () => { export const Datasource = () => {
const [progress, setProgress] = useState<ScanProgress>(); const [progress, setProgress] = useState<ScanProgress>(defaultProgress);
const [result, setResult] = useState(); const { toast } = useToast();
const [result, setResult] = useState<[]>([]);
const [importDialogVisible, setImportDialogVisible] = useState(false);
const [startTime, setStartTime] = useState<number>(Date.now());
useEffect(() => { useEffect(() => {
const handleScanProgress = (event, data) => { const handleScanProgress = (event, data) => {
@ -23,23 +39,73 @@ export const Datasource = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
console.log(1111); window.ipcRenderer.once("scan-start", () => {
setImportDialogVisible(true);
setStartTime(Date.now());
});
}, [progress?.percentage, toast]);
useEffect(() => {
const handleScanFinished = (event, data) => { const handleScanFinished = (event, data) => {
const timeDuration = ((Date.now() - startTime) / 1000).toFixed(2);
console.log(data); console.log(data);
setResult(data); setResult(data);
if (data.error) return; setImportDialogVisible(false);
if (data.error) {
return toast({
variant: "destructive",
title: "Uh oh! Something went wrong.",
description: "There was a problem with your request.",
action: <ToastAction altText="重试"></ToastAction>,
});
} else {
toast({
variant: "default",
title: "完成",
description: `本次操作共导入${data.length}组序列数据,耗时:${timeDuration } s`,
action: <ToastAction altText="启动AI测量">AI测量</ToastAction>,
});
}
}; };
window.ipcRenderer.once("scan-progress-done", handleScanFinished); window.ipcRenderer.on("scan-progress-done", handleScanFinished);
}, []); return () => {
window.ipcRenderer.off("scan-progress-done", handleScanFinished);
};
}, [startTime, toast]);
const handleCancelImport = () => {
setImportDialogVisible(false);
};
useEffect(() => {
if (!importDialogVisible) {
setProgress(defaultProgress);
setStartTime(Date.now());
}
}, [importDialogVisible]);
return ( return (
<div className="p-4"> <div className="p-4">
<div> <Dialog open={importDialogVisible} onOpenChange={setImportDialogVisible}>
<Button onClick={() => window.ipcRenderer.send("scan-dicom")}> <DialogContent className="sm:max-w-md">
<DialogHeader>
</Button> <DialogTitle></DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
<div className="flex items-center space-x-2">
<Alert>
<RocketIcon className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription>
<Progress value={progress?.percentage} /> <Progress value={progress?.percentage} />
</AlertDescription>
</Alert>
</div> </div>
</DialogContent>
</Dialog>
</div> </div>
); );
}; };

View File

@ -15,8 +15,11 @@ import {
} from "@/components/ui/menubar"; } from "@/components/ui/menubar";
import { EVENT_PARSE_DICOM } from "../../electron/ipcEvent"; import { EVENT_PARSE_DICOM } from "../../electron/ipcEvent";
import { useEffect } from "react"; import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
export const MenuBar = () => { export const MenuBar = () => {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
window.ipcRenderer.on(EVENT_PARSE_DICOM + ":RES", (event, data) => { window.ipcRenderer.on(EVENT_PARSE_DICOM + ":RES", (event, data) => {
console.log(data); console.log(data);
@ -24,12 +27,13 @@ export const MenuBar = () => {
}); });
return () => { return () => {
window.ipcRenderer.off(EVENT_PARSE_DICOM + ":RES", () => { }); window.ipcRenderer.off(EVENT_PARSE_DICOM + ":RES", () => {});
}; };
}, []); }, []);
const handleImportDicom = () => { const handleImportDicom = () => {
window.ipcRenderer.send(EVENT_PARSE_DICOM); navigate("/datasource");
window.ipcRenderer.send("import-dicom-dialog-visible");
}; };
return ( return (