2024-09-06 14:27:41 +08:00
|
|
|
import { app, dialog, ipcMain, shell } from "electron";
|
2024-08-29 16:59:25 +08:00
|
|
|
import os from "os";
|
|
|
|
import {
|
|
|
|
findDcmFiles,
|
2024-09-02 14:18:06 +08:00
|
|
|
keyProp,
|
2024-08-29 16:59:25 +08:00
|
|
|
processFilesInBatches,
|
|
|
|
structureMetadata,
|
|
|
|
} from "./core/dicom";
|
2024-09-02 14:18:06 +08:00
|
|
|
import { db } from "./core/db";
|
2024-09-05 15:28:22 +08:00
|
|
|
import axios from "axios";
|
|
|
|
import path from "node:path";
|
2024-09-06 14:27:41 +08:00
|
|
|
import { mkdir, stat } from "fs/promises";
|
2024-08-29 16:59:25 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 渲染进程和主进程的事件调度
|
|
|
|
*/
|
2024-09-05 15:28:22 +08:00
|
|
|
const registerIpcMainHandlers = (mainWindow: Electron.BrowserWindow | null) => {
|
2024-08-29 16:59:25 +08:00
|
|
|
if (!mainWindow) return;
|
|
|
|
|
|
|
|
ipcMain.removeAllListeners();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 等待渲染完成再显示窗口
|
|
|
|
*/
|
|
|
|
ipcMain.on("ipc-loaded", () => mainWindow.show());
|
|
|
|
|
2024-09-05 15:28:22 +08:00
|
|
|
ipcMain.on("ai:task", (_, data) => {
|
|
|
|
const { selectDicoms } = data;
|
2024-09-06 15:09:32 +08:00
|
|
|
const promises = selectDicoms.reduce(
|
|
|
|
(
|
|
|
|
promiseChain: Promise<any>,
|
|
|
|
dicom: { filePaths: any; PatientName: any; SeriesInstanceUID: any }
|
|
|
|
) => {
|
|
|
|
return promiseChain.then(() => {
|
|
|
|
const { filePaths, PatientName, SeriesInstanceUID } = dicom;
|
|
|
|
const img_path = path.dirname(filePaths[0]);
|
|
|
|
const save_path = path.join(
|
|
|
|
app.getPath("userData"),
|
|
|
|
"output",
|
|
|
|
PatientName,
|
|
|
|
SeriesInstanceUID
|
|
|
|
);
|
|
|
|
const params = {
|
|
|
|
img_path,
|
|
|
|
save_path,
|
|
|
|
pu: "GPU",
|
|
|
|
module: "root",
|
|
|
|
turbo: true,
|
|
|
|
};
|
2024-09-06 08:59:59 +08:00
|
|
|
|
2024-09-06 15:09:32 +08:00
|
|
|
const startTime = Date.now(); // 记录请求开始时间
|
|
|
|
console.log(
|
|
|
|
`Request for ${PatientName} started at ${new Date(
|
|
|
|
startTime
|
|
|
|
).toISOString()}`
|
|
|
|
);
|
|
|
|
console.log(params);
|
2024-09-05 15:28:22 +08:00
|
|
|
|
2024-09-06 15:09:32 +08:00
|
|
|
return axios
|
|
|
|
.post("http://127.0.0.1:5000/root", { ...params })
|
|
|
|
.then((response) => {
|
|
|
|
const endTime = Date.now(); // 记录请求结束时间
|
|
|
|
const duration = (endTime - startTime) / 1000; // 计算耗时,单位为秒
|
|
|
|
console.log(
|
|
|
|
`Response for ${PatientName} received at ${new Date(
|
|
|
|
endTime
|
|
|
|
).toISOString()} (Duration: ${duration} seconds)`
|
|
|
|
);
|
|
|
|
console.log(response.data);
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
const endTime = Date.now(); // 即使失败也记录结束时间
|
|
|
|
const duration = (endTime - startTime) / 1000;
|
|
|
|
console.error(
|
|
|
|
`Error for ${PatientName} at ${new Date(
|
|
|
|
endTime
|
|
|
|
).toISOString()} (Duration: ${duration} seconds)`
|
|
|
|
);
|
|
|
|
console.error(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
Promise.resolve()
|
|
|
|
); // 从 resolve() 开始,依次链接每个 Promise
|
2024-09-05 15:28:22 +08:00
|
|
|
|
2024-09-06 08:59:59 +08:00
|
|
|
const overallStartTime = Date.now(); // 记录总的开始时间
|
2024-09-05 15:28:22 +08:00
|
|
|
promises.then(() => {
|
2024-09-06 08:59:59 +08:00
|
|
|
const overallEndTime = Date.now(); // 记录总的结束时间
|
|
|
|
const overallDuration = (overallEndTime - overallStartTime) / 1000; // 总耗时
|
|
|
|
console.log(`All dicoms processed in ${overallDuration} seconds.`);
|
2024-09-05 15:28:22 +08:00
|
|
|
});
|
|
|
|
});
|
2024-08-30 16:58:44 +08:00
|
|
|
|
2024-09-03 14:10:36 +08:00
|
|
|
/**
|
|
|
|
* 显示选择文件夹的dialog
|
|
|
|
*/
|
2024-09-02 11:18:49 +08:00
|
|
|
ipcMain.on("import-dicom-dialog-visible", async (event) => {
|
2024-08-30 16:58:44 +08:00
|
|
|
const result = await dialog.showOpenDialog({
|
|
|
|
properties: ["openDirectory"],
|
|
|
|
});
|
|
|
|
if (result.canceled) return null;
|
|
|
|
const filePaths = result.filePaths[0];
|
2024-09-02 11:18:49 +08:00
|
|
|
event.reply("scan-start");
|
2024-09-03 14:10:36 +08:00
|
|
|
const scanTimeStart = Date.now();
|
2024-09-02 11:18:49 +08:00
|
|
|
const dcmPaths = await findDcmFiles(filePaths);
|
2024-08-31 02:18:35 +08:00
|
|
|
const batchSize = os.cpus().length * 1 || 10;
|
|
|
|
const items = await processFilesInBatches(dcmPaths, batchSize);
|
|
|
|
const structDicom = await structureMetadata(items, (progress) => {
|
2024-09-02 11:18:49 +08:00
|
|
|
event.reply("scan-progress", progress);
|
2024-08-31 02:18:35 +08:00
|
|
|
});
|
2024-09-02 14:18:06 +08:00
|
|
|
// 存数据库
|
|
|
|
const changeTime = Date.now();
|
|
|
|
for (const item of structDicom) {
|
|
|
|
const existSeries = db.data.series.find(
|
|
|
|
(i) => i[keyProp] === item[keyProp]
|
|
|
|
);
|
|
|
|
existSeries
|
|
|
|
? Object.assign(existSeries, item, { updateTime: changeTime })
|
2024-09-03 14:10:36 +08:00
|
|
|
: db.data.series.push({
|
|
|
|
...item,
|
|
|
|
createTime: changeTime,
|
|
|
|
updateTime: changeTime,
|
|
|
|
});
|
2024-09-02 14:18:06 +08:00
|
|
|
await db.write();
|
|
|
|
}
|
2024-09-03 14:10:36 +08:00
|
|
|
event.reply("scan-progress-done", {
|
|
|
|
structDicom,
|
|
|
|
scanDuration: Date.now() - scanTimeStart,
|
|
|
|
});
|
2024-09-06 15:09:32 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
ipcMain.on("one-step", async (event, dir) => {
|
|
|
|
const directory = path.resolve(dir);
|
|
|
|
const dcmPaths = await findDcmFiles(directory);
|
|
|
|
const batchSize = os.cpus().length * 1 || 10;
|
|
|
|
const items = await processFilesInBatches(dcmPaths, batchSize);
|
|
|
|
const structDicom = await structureMetadata(items);
|
|
|
|
// 存数据库
|
|
|
|
const changeTime = Date.now();
|
|
|
|
for (const item of structDicom) {
|
|
|
|
const existSeries = db.data.series.find(
|
|
|
|
(i) => i[keyProp] === item[keyProp]
|
|
|
|
);
|
|
|
|
existSeries
|
|
|
|
? Object.assign(existSeries, item, { updateTime: changeTime })
|
|
|
|
: db.data.series.push({
|
|
|
|
...item,
|
|
|
|
createTime: changeTime,
|
|
|
|
updateTime: changeTime,
|
|
|
|
});
|
|
|
|
await db.write();
|
|
|
|
}
|
|
|
|
// 启动分析
|
|
|
|
const promises = structDicom.reduce((promiseChain, dicom) => {
|
|
|
|
return promiseChain.then(() => {
|
|
|
|
const { filePaths, PatientName = "", SeriesInstanceUID = "" } = dicom;
|
|
|
|
const img_path = path.dirname(filePaths[0]);
|
|
|
|
const save_path = path.join(
|
|
|
|
app.getPath("userData"),
|
|
|
|
"output",
|
|
|
|
PatientName,
|
|
|
|
SeriesInstanceUID
|
|
|
|
);
|
|
|
|
const params = {
|
|
|
|
img_path,
|
|
|
|
save_path,
|
|
|
|
pu: "GPU",
|
|
|
|
module: "root",
|
|
|
|
turbo: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
const startTime = Date.now(); // 记录请求开始时间
|
|
|
|
return axios
|
|
|
|
.post("http://127.0.0.1:5000/root", { ...params })
|
|
|
|
.then((response) => {
|
|
|
|
const endTime = Date.now(); // 记录请求结束时间
|
|
|
|
const duration = (endTime - startTime) / 1000; // 计算耗时,单位为秒
|
|
|
|
event.reply(
|
|
|
|
"taskFinished",
|
|
|
|
`Response for ${PatientName} received at ${new Date(
|
|
|
|
endTime
|
|
|
|
).toISOString()} (Duration: ${duration} seconds)`
|
|
|
|
);
|
|
|
|
console.log(response);
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
const endTime = Date.now(); // 即使失败也记录结束时间
|
|
|
|
const duration = (endTime - startTime) / 1000;
|
|
|
|
console.error(
|
|
|
|
`Error for ${PatientName} at ${new Date(
|
|
|
|
endTime
|
|
|
|
).toISOString()} (Duration: ${duration} seconds)`
|
|
|
|
);
|
|
|
|
console.error(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}, Promise.resolve()); // 从 resolve() 开始,依次链接每个 Promise
|
|
|
|
|
|
|
|
const overallStartTime = Date.now(); // 记录总的开始时间
|
|
|
|
promises.then(() => {
|
|
|
|
const overallEndTime = Date.now(); // 记录总的结束时间
|
|
|
|
const overallDuration = (overallEndTime - overallStartTime) / 1000; // 总耗时
|
|
|
|
event.reply("tasksFinished", overallDuration);
|
|
|
|
});
|
2024-08-30 16:58:44 +08:00
|
|
|
});
|
2024-09-02 14:18:06 +08:00
|
|
|
|
2024-09-03 14:10:36 +08:00
|
|
|
/**
|
|
|
|
* api 获取 列表的中数据
|
|
|
|
*/
|
2024-09-03 15:28:30 +08:00
|
|
|
ipcMain.on("db:series:select", async (event) => {
|
2024-09-02 14:18:06 +08:00
|
|
|
await db.read();
|
|
|
|
const seriesList = db.data.series;
|
|
|
|
event.reply("db:series:select:response", seriesList);
|
|
|
|
});
|
2024-09-06 14:27:41 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 用户配置保存
|
|
|
|
*/
|
|
|
|
ipcMain.on("setInferDevice", async (event, device) => {
|
|
|
|
await db.update(({ setting }) => ({ ...setting, inferDevice: device }));
|
|
|
|
event.reply("setInferDevice:response", `推理硬件修改为${device}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 打开输出文件夹目录
|
|
|
|
*/
|
|
|
|
ipcMain.on("openOutputPath", async () => {
|
|
|
|
await db.read();
|
|
|
|
const optPath = db.data.setting.outputPath;
|
|
|
|
const resolvedPath = path.resolve(optPath);
|
|
|
|
try {
|
|
|
|
// 检查路径是否存在
|
|
|
|
const stats = await stat(resolvedPath);
|
|
|
|
if (stats.isDirectory()) shell.openPath(resolvedPath);
|
|
|
|
} catch (error: any) {
|
|
|
|
await mkdir(resolvedPath, { recursive: true });
|
|
|
|
shell.openPath(resolvedPath);
|
|
|
|
}
|
|
|
|
});
|
2024-08-29 16:59:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
export default registerIpcMainHandlers;
|