feat: 导入dicom基本交互
This commit is contained in:
parent
7fb2511ba4
commit
d4a43e211a
|
@ -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);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
Loading…
Reference in New Issue
Block a user