import { app, dialog, ipcMain, shell } from "electron"; import os from "os"; import { findDcmFiles, keyProp, processFilesInBatches, structureMetadata, } from "./core/dicom"; import { db } from "./core/db"; import axios from "axios"; import path from "node:path"; import { mkdir, stat } from "fs/promises"; import { readFileSync } from "node:fs"; /** * 渲染进程和主进程的事件调度 */ const registerIpcMainHandlers = (mainWindow: Electron.BrowserWindow | null) => { if (!mainWindow) return; ipcMain.removeAllListeners(); /** * 等待渲染完成再显示窗口 */ ipcMain.on("ipc-loaded", () => mainWindow.show()); ipcMain.on("ai:task", (_, data) => { const { selectDicoms } = data; const promises = selectDicoms.reduce( ( promiseChain: Promise, 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, }; const startTime = Date.now(); // 记录请求开始时间 console.log( `Request for ${PatientName} started at ${new Date( startTime ).toISOString()}` ); console.log(params); 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 const overallStartTime = Date.now(); // 记录总的开始时间 promises.then(() => { const overallEndTime = Date.now(); // 记录总的结束时间 const overallDuration = (overallEndTime - overallStartTime) / 1000; // 总耗时 console.log(`All dicoms processed in ${overallDuration} seconds.`); }); }); /** * 显示选择文件夹的dialog */ ipcMain.on("import-dicom-dialog-visible", async (event) => { const result = await dialog.showOpenDialog({ properties: ["openDirectory"], }); if (result.canceled) return null; const filePaths = result.filePaths[0]; event.reply("scan-start"); const scanTimeStart = Date.now(); const dcmPaths = await findDcmFiles(filePaths); const batchSize = os.cpus().length * 1 || 10; const items = await processFilesInBatches(dcmPaths, batchSize); const structDicom = await structureMetadata(items, (progress) => { event.reply("scan-progress", progress); }); // 存数据库 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(); } event.reply("scan-progress-done", { structDicom, scanDuration: Date.now() - scanTimeStart, }); }); 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); }); }); /** * api 获取 列表的中数据 */ ipcMain.on("db:series:select", async (event) => { await db.read(); const seriesList = db.data.series; event.reply("db:series:select:response", seriesList); }); /** * 用户配置保存 */ 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); } }); ipcMain.on("request-dicom", async (event, data) => { console.log(data); const SeriesInstanceUID = data; await db.read(); const series = await db.data.series.find( (s) => s.SeriesInstanceUID === SeriesInstanceUID ); console.log(series); if (series) { const { filePaths } = series; const buffers = filePaths.map((filePath) => { const dicomFileBuffer = readFileSync(filePath); return dicomFileBuffer; }); event.reply("request-dicom:response", series); } else { console.log("没找到series"); } }); }; export default registerIpcMainHandlers;