fix: 上传时间计算挪到后端算
This commit is contained in:
parent
1775cad744
commit
2caf55facc
8
apps/desktop/electron/core/auth.ts
Normal file
8
apps/desktop/electron/core/auth.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { machineIdSync } from "node-machine-id";
|
||||||
|
|
||||||
|
// Asyncronous call with async/await or Promise
|
||||||
|
|
||||||
|
export const getMachineId = async () => {
|
||||||
|
const id = await machineIdSync();
|
||||||
|
console.log(id);
|
||||||
|
};
|
|
@ -50,6 +50,9 @@ const registerIpcMainHandlers = (
|
||||||
running ? pythonManager.startFlask() : pythonManager.stopFlask();
|
running ? pythonManager.startFlask() : pythonManager.stopFlask();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示选择文件夹的dialog
|
||||||
|
*/
|
||||||
ipcMain.on("import-dicom-dialog-visible", async (event) => {
|
ipcMain.on("import-dicom-dialog-visible", async (event) => {
|
||||||
const result = await dialog.showOpenDialog({
|
const result = await dialog.showOpenDialog({
|
||||||
properties: ["openDirectory"],
|
properties: ["openDirectory"],
|
||||||
|
@ -57,6 +60,7 @@ const registerIpcMainHandlers = (
|
||||||
if (result.canceled) return null;
|
if (result.canceled) return null;
|
||||||
const filePaths = result.filePaths[0];
|
const filePaths = result.filePaths[0];
|
||||||
event.reply("scan-start");
|
event.reply("scan-start");
|
||||||
|
const scanTimeStart = Date.now();
|
||||||
const dcmPaths = await findDcmFiles(filePaths);
|
const dcmPaths = await findDcmFiles(filePaths);
|
||||||
const batchSize = os.cpus().length * 1 || 10;
|
const batchSize = os.cpus().length * 1 || 10;
|
||||||
const items = await processFilesInBatches(dcmPaths, batchSize);
|
const items = await processFilesInBatches(dcmPaths, batchSize);
|
||||||
|
@ -71,12 +75,22 @@ const registerIpcMainHandlers = (
|
||||||
);
|
);
|
||||||
existSeries
|
existSeries
|
||||||
? Object.assign(existSeries, item, { updateTime: changeTime })
|
? Object.assign(existSeries, item, { updateTime: changeTime })
|
||||||
: db.data.series.push({ ...item, createTime: changeTime });
|
: db.data.series.push({
|
||||||
|
...item,
|
||||||
|
createTime: changeTime,
|
||||||
|
updateTime: changeTime,
|
||||||
|
});
|
||||||
await db.write();
|
await db.write();
|
||||||
}
|
}
|
||||||
event.reply("scan-progress-done", structDicom);
|
event.reply("scan-progress-done", {
|
||||||
|
structDicom,
|
||||||
|
scanDuration: Date.now() - scanTimeStart,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api 获取 列表的中数据
|
||||||
|
*/
|
||||||
ipcMain.on("db:series:select", async (event, data) => {
|
ipcMain.on("db:series:select", async (event, data) => {
|
||||||
await db.read();
|
await db.read();
|
||||||
const seriesList = db.data.series;
|
const seriesList = db.data.series;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import path from "node:path";
|
||||||
import registerIpcMainHandlers from "./ipcMainHandlers";
|
import registerIpcMainHandlers from "./ipcMainHandlers";
|
||||||
import PythonManager from "./core/PythonManager";
|
import PythonManager from "./core/PythonManager";
|
||||||
import { createDatabase } from "./core/db";
|
import { createDatabase } from "./core/db";
|
||||||
|
import { getMachineId, mid } from "./core/auth";
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
@ -131,6 +132,7 @@ app.on("before-quit", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
|
getMachineId();
|
||||||
createWindow();
|
createWindow();
|
||||||
createTray();
|
createTray();
|
||||||
registerGlobalShortcuts();
|
registerGlobalShortcuts();
|
||||||
|
|
|
@ -59,7 +59,8 @@
|
||||||
"react-router-dom": "^6.26.0",
|
"react-router-dom": "^6.26.0",
|
||||||
"tailwind-merge": "^2.4.0",
|
"tailwind-merge": "^2.4.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"zod": "3.23.8"
|
"zod": "3.23.8",
|
||||||
|
"node-machine-id": "1.1.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
|
|
|
@ -146,7 +146,17 @@ export const columns: ColumnDef<Series>[] = [
|
||||||
{
|
{
|
||||||
id: "updateTime",
|
id: "updateTime",
|
||||||
accessorKey: "updateTime",
|
accessorKey: "updateTime",
|
||||||
header: columnsAlias["updateTime"],
|
header: ({ column }) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||||
|
>
|
||||||
|
{columnsAlias["updateTime"]}
|
||||||
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="capitalize">
|
<div className="capitalize">
|
||||||
{new Date(row.getValue("updateTime")).toLocaleString()}
|
{new Date(row.getValue("updateTime")).toLocaleString()}
|
||||||
|
@ -185,29 +195,20 @@ export const columns: ColumnDef<Series>[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function SeriesTable() {
|
interface SeriesTableProps {
|
||||||
|
data: Series[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SeriesTable(props: SeriesTableProps) {
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
const [data, setData] = useState<Series[]>([]);
|
|
||||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({
|
||||||
SeriesInstanceUID: false,
|
SeriesInstanceUID: false,
|
||||||
updateTime: false,
|
|
||||||
});
|
});
|
||||||
const [rowSelection, setRowSelection] = useState({});
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
window.ipcRenderer.send("db:series:select");
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
window.ipcRenderer.on("db:series:select:response", (event, data) => {
|
|
||||||
console.log(data);
|
|
||||||
setData(data);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data,
|
data: props.data,
|
||||||
columns,
|
columns,
|
||||||
onSortingChange: setSorting,
|
onSortingChange: setSorting,
|
||||||
onColumnFiltersChange: setColumnFilters,
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
|
|
@ -10,8 +10,8 @@ import { Progress } from "@/components/ui/progress";
|
||||||
import { ToastAction } from "@/components/ui/toast";
|
import { ToastAction } from "@/components/ui/toast";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import { RocketIcon } from "@radix-ui/react-icons";
|
import { RocketIcon } from "@radix-ui/react-icons";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { SeriesTable } from "./SeriesTable";
|
import { Series, SeriesTable } from "./SeriesTable";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
interface ScanProgress {
|
interface ScanProgress {
|
||||||
|
@ -26,8 +26,9 @@ export const Datasource = () => {
|
||||||
const [progress, setProgress] = useState<ScanProgress>(defaultProgress);
|
const [progress, setProgress] = useState<ScanProgress>(defaultProgress);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [result, setResult] = useState<[]>([]);
|
const [result, setResult] = useState<[]>([]);
|
||||||
|
|
||||||
|
const [seriesData, setSeriesData] = useState<Series[]>([]);
|
||||||
const [importDialogVisible, setImportDialogVisible] = useState(false);
|
const [importDialogVisible, setImportDialogVisible] = useState(false);
|
||||||
const [startTime, setStartTime] = useState<number>(Date.now());
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScanProgress = (event, data) => {
|
const handleScanProgress = (event, data) => {
|
||||||
|
@ -43,15 +44,13 @@ export const Datasource = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.ipcRenderer.once("scan-start", () => {
|
window.ipcRenderer.once("scan-start", () => {
|
||||||
setImportDialogVisible(true);
|
setImportDialogVisible(true);
|
||||||
setStartTime(Date.now());
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScanFinished = (event, data) => {
|
const handleScanFinished = (event, data) => {
|
||||||
const timeDuration = ((Date.now() - startTime) / 1000).toFixed(2);
|
const { scanDuration, structDicom } = data;
|
||||||
console.log(data);
|
setResult(structDicom);
|
||||||
setResult(data);
|
|
||||||
setImportDialogVisible(false);
|
setImportDialogVisible(false);
|
||||||
|
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
|
@ -65,17 +64,20 @@ export const Datasource = () => {
|
||||||
toast({
|
toast({
|
||||||
variant: "default",
|
variant: "default",
|
||||||
title: "完成",
|
title: "完成",
|
||||||
description: `本次操作共导入${data.length}组序列数据,耗时:${timeDuration} s`,
|
description: `本次操作共导入${structDicom.length}组序列数据,耗时:${(
|
||||||
|
scanDuration / 1000
|
||||||
|
).toFixed(2)} s`,
|
||||||
action: <ToastAction altText="启动AI测量">启动AI测量</ToastAction>,
|
action: <ToastAction altText="启动AI测量">启动AI测量</ToastAction>,
|
||||||
duration: 30 * 1000,
|
duration: 30 * 1000,
|
||||||
});
|
});
|
||||||
|
window.ipcRenderer.send("db:series:select");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.ipcRenderer.on("scan-progress-done", handleScanFinished);
|
window.ipcRenderer.on("scan-progress-done", handleScanFinished);
|
||||||
return () => {
|
return () => {
|
||||||
window.ipcRenderer.off("scan-progress-done", handleScanFinished);
|
window.ipcRenderer.off("scan-progress-done", handleScanFinished);
|
||||||
};
|
};
|
||||||
}, [startTime, toast]);
|
}, [toast]);
|
||||||
|
|
||||||
const handleCancelImport = () => {
|
const handleCancelImport = () => {
|
||||||
setImportDialogVisible(false);
|
setImportDialogVisible(false);
|
||||||
|
@ -84,10 +86,20 @@ export const Datasource = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!importDialogVisible) {
|
if (!importDialogVisible) {
|
||||||
setProgress(defaultProgress);
|
setProgress(defaultProgress);
|
||||||
setStartTime(Date.now());
|
|
||||||
}
|
}
|
||||||
}, [importDialogVisible]);
|
}, [importDialogVisible]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.ipcRenderer.send("db:series:select");
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.ipcRenderer.on("db:series:select:response", (event, data) => {
|
||||||
|
console.log(data);
|
||||||
|
setSeriesData(data);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="h-full"
|
className="h-full"
|
||||||
|
@ -96,7 +108,7 @@ export const Datasource = () => {
|
||||||
exit={{ y: 0, opacity: 0 }}
|
exit={{ y: 0, opacity: 0 }}
|
||||||
transition={{ duration: 0.25 }}
|
transition={{ duration: 0.25 }}
|
||||||
>
|
>
|
||||||
<SeriesTable />
|
<SeriesTable data={seriesData} />
|
||||||
{/* 导入数据dialog */}
|
{/* 导入数据dialog */}
|
||||||
<Dialog open={importDialogVisible} onOpenChange={setImportDialogVisible}>
|
<Dialog open={importDialogVisible} onOpenChange={setImportDialogVisible}>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md">
|
||||||
|
|
|
@ -112,6 +112,9 @@ importers:
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.408.0
|
specifier: ^0.408.0
|
||||||
version: 0.408.0(react@18.3.1)
|
version: 0.408.0(react@18.3.1)
|
||||||
|
node-machine-id:
|
||||||
|
specifier: 1.1.12
|
||||||
|
version: 1.1.12
|
||||||
object-hash:
|
object-hash:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
|
@ -2976,6 +2979,9 @@ packages:
|
||||||
encoding:
|
encoding:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
node-machine-id@1.1.12:
|
||||||
|
resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==}
|
||||||
|
|
||||||
node-releases@2.0.18:
|
node-releases@2.0.18:
|
||||||
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
||||||
|
|
||||||
|
@ -7179,6 +7185,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
|
|
||||||
|
node-machine-id@1.1.12: {}
|
||||||
|
|
||||||
node-releases@2.0.18: {}
|
node-releases@2.0.18: {}
|
||||||
|
|
||||||
normalize-path@3.0.0: {}
|
normalize-path@3.0.0: {}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user