diff --git a/.gitignore b/.gitignore index ec42731..3e833e0 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ release *.njsproj *.sln *.sw? + + +_internal \ No newline at end of file diff --git a/apps/desktop/electron/core/PythonManager.ts b/apps/desktop/electron/core/PythonManager.ts index 19323e4..568e036 100644 --- a/apps/desktop/electron/core/PythonManager.ts +++ b/apps/desktop/electron/core/PythonManager.ts @@ -2,6 +2,7 @@ import path from "node:path"; import { spawn, ChildProcess } from "node:child_process"; import { BrowserWindow } from "electron"; +// import http from "node:http"; class PythonManager { public flaskProcess: ChildProcess | null = null; @@ -9,8 +10,8 @@ class PythonManager { constructor( private mainWindow: BrowserWindow | null, - // private url: string, - // private interval = 5000 + private url: string, + private interval = 5000 ) {} // 启动 Python 服务 @@ -22,7 +23,7 @@ class PythonManager { } // 使用 spawn 启动 Flask 服务 - this.flaskProcess = spawn(path.join(process.env.VITE_PUBLIC!, "flask_app")); + this.flaskProcess = spawn(path.join(process.env.VITE_PUBLIC!, "main.exe")); // 实时获取 stdout 日志 this.flaskProcess.stdout?.on("data", (data) => { @@ -35,14 +36,19 @@ class PythonManager { this.flaskProcess.stderr?.on("data", (data) => { const message = data.toString(); console.error(`Flask stderr: ${message}`); - this.mainWindow?.webContents.send("flask-service:response", { stderr: message }); + this.mainWindow?.webContents.send("flask-service:response", { + stderr: message, + }); }); // 监听进程关闭事件 this.flaskProcess.on("close", (code) => { console.log(`Flask process exited with code ${code}`); this.flaskProcess = null; - this.mainWindow?.webContents.send("flask-service:response", { exited: true, code }); + this.mainWindow?.webContents.send("flask-service:response", { + exited: true, + code, + }); }); // 开始轮询服务状态 diff --git a/apps/desktop/electron/ipcMainHandlers.ts b/apps/desktop/electron/ipcMainHandlers.ts index 61299f2..12268f0 100644 --- a/apps/desktop/electron/ipcMainHandlers.ts +++ b/apps/desktop/electron/ipcMainHandlers.ts @@ -1,4 +1,4 @@ -import { dialog, ipcMain } from "electron"; +import { app, dialog, ipcMain } from "electron"; import os from "os"; import { findDcmFiles, @@ -6,16 +6,14 @@ import { processFilesInBatches, structureMetadata, } from "./core/dicom"; -// import PythonManager from "./core/PythonManager"; import { db } from "./core/db"; +import axios from "axios"; +import path from "node:path"; /** * 渲染进程和主进程的事件调度 */ -const registerIpcMainHandlers = ( - mainWindow: Electron.BrowserWindow | null, - // pythonManager?: PythonManager -) => { +const registerIpcMainHandlers = (mainWindow: Electron.BrowserWindow | null) => { if (!mainWindow) return; ipcMain.removeAllListeners(); @@ -25,10 +23,51 @@ const registerIpcMainHandlers = ( */ ipcMain.on("ipc-loaded", () => mainWindow.show()); - // ipcMain.on("python-service", (_, data) => { - // const { running } = data; - // running ? pythonManager.startFlask() : pythonManager.stopFlask(); - // }); + ipcMain.on("ai:task", (_, data) => { + const { selectDicoms } = data; + const promises = selectDicoms.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, + }; + console.log(params); + + return axios + .post("http://127.0.0.1:5000/root", { ...params }) + .then((response) => { + console.log(response.data); + }) + .catch((error) => { + console.error(error); + }); + }); + }, Promise.resolve()); // 从 resolve() 开始,依次链接每个 Promise + + promises.then(() => { + console.log("All dicoms processed."); + }); + + // const img_path = + // const { + // img_path, + // save_path, + // pu = "GPU", + // module = "root", + // turbo = true, + // } = data; + }); /** * 显示选择文件夹的dialog diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 80fc8f0..7894930 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -14,6 +14,7 @@ import PythonManager from "./core/PythonManager"; import { createDatabase } from "./core/db"; import { getMachineId } from "./core/auth"; import registerIpcMainHandlers from "./ipcMainHandlers"; +import { spawn } from "node:child_process"; // const require = createRequire(import.meta.url); const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -64,6 +65,7 @@ function createWindow() { if (VITE_DEV_SERVER_URL) { win.loadURL(VITE_DEV_SERVER_URL); registerIpcMainHandlers(win); + spawn(path.join(process.env.VITE_PUBLIC!, "main.exe")); } else { win.loadFile(path.join(RENDERER_DIST, "index.html")).then(() => { if (process.argv.length >= 2) { @@ -73,8 +75,6 @@ function createWindow() { } }); } - - // pythonManager = new PythonManager(win, "http://127.0.0.1:15001", 3000); } function createTray() { @@ -135,7 +135,7 @@ app.on("activate", () => { }); app.on("before-quit", () => { - if (pythonManager?.flaskProcess) pythonManager?.stopFlask(); + pythonManager?.stopFlask(); }); app.whenReady().then(() => { @@ -144,6 +144,7 @@ app.whenReady().then(() => { createTray(); registerGlobalShortcuts(); createDatabase({ name: "cvpilot.json" }); + pythonManager?.startFlask(); console.log(path.join(app.getPath("userData"))); // 设置 Dock 图标 diff --git a/apps/desktop/kernel.errors.txt b/apps/desktop/kernel.errors.txt new file mode 100644 index 0000000..9541c79 --- /dev/null +++ b/apps/desktop/kernel.errors.txt @@ -0,0 +1,10 @@ +Instruction / Operand / Region Errors: + +/-------------------------------------------!!!KERNEL HEADER ERRORS FOUND!!!-------------------------------------------\ +Error in CISA routine with name: igc_check + Error Message: Input V38 = [256, 260) intersects with V37 = [256, 260) +\----------------------------------------------------------------------------------------------------------------------/ + + + + diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 9623eff..1d126af 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -61,7 +61,8 @@ "react-router-dom": "^6.26.0", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", - "zod": "3.23.8" + "zod": "3.23.8", + "axios": "1.7.7" }, "devDependencies": { "@radix-ui/react-icons": "^1.3.0", diff --git a/apps/desktop/public/main.exe b/apps/desktop/public/main.exe new file mode 100644 index 0000000..907c60a Binary files /dev/null and b/apps/desktop/public/main.exe differ diff --git a/apps/desktop/src/pages/Boot/index.tsx b/apps/desktop/src/pages/Boot/index.tsx index b08fa23..47fc8ae 100644 --- a/apps/desktop/src/pages/Boot/index.tsx +++ b/apps/desktop/src/pages/Boot/index.tsx @@ -1,7 +1,6 @@ import { Button } from "@/components/ui/button"; import { motion } from "framer-motion"; import { useEffect, useState } from "react"; -import { IoCheckmarkCircleSharp } from "react-icons/io5"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Dialog, @@ -15,29 +14,15 @@ import { ToastAction } from "@/components/ui/toast"; import { useToast } from "@/components/ui/use-toast"; import { RocketIcon } from "@radix-ui/react-icons"; import { useLocation } from "react-router-dom"; -import { SparkleIcon, Terminal } from "lucide-react"; +import { SparkleIcon } from "lucide-react"; import { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from "@/components/ui/resizable"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { - Carousel, - CarouselApi, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; +import { Card } from "@/components/ui/card"; +import { CarouselApi } from "@/components/ui/carousel"; import { Series } from "../Datasource/SeriesTable"; import { ScrollArea } from "@/components/ui/scroll-area"; @@ -50,13 +35,10 @@ const defaultProgress = { }; const Boot = () => { - const [flaskWaiting, setFlaskWaiting] = useState(false); - const [flaskRunning, setflaskRunning] = useState(false); - const [flaskInfo, setFlaskInfo] = useState(""); const location = useLocation(); const selectDicoms = location.state?.selectDicoms ?? - JSON.parse(localStorage.getItem("selectDicoms") ?? "{}"); + JSON.parse(localStorage.getItem("selectDicoms") ?? "[]"); /** * windows系统右键启动应用菜单的入口路径 @@ -67,21 +49,8 @@ const Boot = () => { const { toast } = useToast(); const [, setResult] = useState<[]>([]); - const [api, setApi] = useState(); - const [current, setCurrent] = useState(0); - const [count, setCount] = useState(0); - const [importDialogVisible, setImportDialogVisible] = useState(false); - useEffect(() => { - if (!api) return; - setCount(api.scrollSnapList().length); - setCurrent(api.selectedScrollSnap() + 1); - api.on("select", () => { - setCurrent(api.selectedScrollSnap() + 1); - }); - }, [api]); - useEffect(() => { const handleScanProgress = ( _event: Electron.IpcRendererEvent, @@ -144,30 +113,13 @@ const Boot = () => { } }, [importDialogVisible]); - const handleBootPythonServer = () => { - if (!flaskRunning) setFlaskWaiting(true); - window.ipcRenderer.send("python-service", { running: !flaskRunning }); + /** + * 上传到electron主进程 + */ + const handleTasks = () => { + window.ipcRenderer.send("ai:task", { selectDicoms }); }; - useEffect(() => { - window.ipcRenderer.on("flask-service:response", (_, data) => { - console.log(data); - if (data.running) { - setflaskRunning(true); - setFlaskWaiting(false); - } - if (data.stdout || data.stderr) { - setflaskRunning(true); - setFlaskWaiting(false); - setFlaskInfo(data.stderr); - } - if (data.exited) { - setFlaskInfo(""); - setflaskRunning(false); - } - }); - }, []); - useEffect(() => { window.ipcRenderer.on("open-folder", (_, data) => { console.log("右键菜单拉起启动文件夹路径", data); @@ -232,12 +184,9 @@ const Boot = () => {
-
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74ac5b8..2cfe486 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,6 +70,9 @@ importers: antd: specifier: ^5.20.0 version: 5.20.3(date-fns@3.6.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + axios: + specifier: 1.7.7 + version: 1.7.7 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -1785,6 +1788,9 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} @@ -2391,6 +2397,15 @@ packages: react: ^18.0.0 react-dom: ^18.0.0 + follow-redirects@1.15.8: + resolution: {integrity: sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.0: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} @@ -3212,6 +3227,9 @@ packages: resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} engines: {node: '>=12.0.0'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@2.0.1: resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} @@ -5749,7 +5767,7 @@ snapshots: app-builder-bin@4.0.0: {} - app-builder-lib@24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): + app-builder-lib@24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): dependencies: '@develar/schema-utils': 2.6.5 '@electron/notarize': 2.2.1 @@ -5763,7 +5781,7 @@ snapshots: builder-util-runtime: 9.2.4 chromium-pickle-js: 0.2.0 debug: 4.3.6 - dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3) ejs: 3.1.10 electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3) electron-publish: 24.13.1 @@ -5870,6 +5888,14 @@ snapshots: postcss: 8.4.41 postcss-value-parser: 4.2.0 + axios@1.7.7: + dependencies: + follow-redirects: 1.15.8 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + b4a@1.6.6: {} balanced-match@1.0.2: {} @@ -6241,9 +6267,9 @@ snapshots: dlv@1.1.3: {} - dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): + dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) builder-util: 24.13.1 builder-util-runtime: 9.2.4 fs-extra: 10.1.0 @@ -6311,7 +6337,7 @@ snapshots: electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) archiver: 5.3.2 builder-util: 24.13.1 fs-extra: 10.1.0 @@ -6321,11 +6347,11 @@ snapshots: electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) builder-util: 24.13.1 builder-util-runtime: 9.2.4 chalk: 4.1.2 - dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3) fs-extra: 10.1.0 is-ci: 3.0.1 lazy-val: 1.0.5 @@ -6595,6 +6621,8 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + follow-redirects@1.15.8: {} + foreground-child@3.3.0: dependencies: cross-spawn: 7.0.3 @@ -7433,6 +7461,8 @@ snapshots: '@types/node': 22.5.2 long: 5.2.3 + proxy-from-env@1.1.0: {} + pump@2.0.1: dependencies: end-of-stream: 1.4.4