feat: 拉通python.exe
This commit is contained in:
parent
b2c5b581fc
commit
96b53bb22d
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -24,3 +24,6 @@ release
|
|||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
|
||||
_internal
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
// 开始轮询服务状态
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 图标
|
||||
|
|
10
apps/desktop/kernel.errors.txt
Normal file
10
apps/desktop/kernel.errors.txt
Normal 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)
|
||||
\----------------------------------------------------------------------------------------------------------------------/
|
||||
|
||||
|
||||
|
||||
|
|
@ -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",
|
||||
|
|
BIN
apps/desktop/public/main.exe
Normal file
BIN
apps/desktop/public/main.exe
Normal file
Binary file not shown.
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user