feat: 拉通python.exe

This commit is contained in:
mozzie 2024-09-05 15:28:22 +08:00
parent b2c5b581fc
commit 96b53bb22d
9 changed files with 127 additions and 88 deletions

3
.gitignore vendored
View File

@ -24,3 +24,6 @@ release
*.njsproj
*.sln
*.sw?
_internal

View File

@ -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,
});
});
// 开始轮询服务状态

View File

@ -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

View File

@ -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 图标

View File

@ -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)
\----------------------------------------------------------------------------------------------------------------------/

View File

@ -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",

Binary file not shown.

View File

@ -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<CarouselApi>();
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 = () => {
</div>
</ScrollArea>
<div className="flex-shrink-0 px-4 py-4 text-right">
<Button
disabled={flaskWaiting}
onClick={handleBootPythonServer}
>
<Button onClick={handleTasks}>
<SparkleIcon className="mr-2 h-4 w-4" />
{flaskRunning ? "运行中" : "启动"}
</Button>
</div>
</div>

View File

@ -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