2026-05-07-18-42-53 优化可视化工具栏和构件ID联动
This commit is contained in:
@@ -21,20 +21,13 @@ import {
|
||||
Upload
|
||||
} from 'lucide-react';
|
||||
import * as THREE from 'three';
|
||||
import { DicomInfo, DicomPreview, Project } from '../types';
|
||||
import { DicomInfo, DicomPreview, ModuleStyle, Project } from '../types';
|
||||
import { api, downloadDicomArchive, downloadMask } from '../lib/api';
|
||||
|
||||
type Plane = 'axial' | 'sagittal' | 'coronal';
|
||||
type DisplayMode = DicomPreview['mode'];
|
||||
type SolidityLevel = 'standard' | 'fine' | 'ultra' | 'solid';
|
||||
|
||||
interface ModuleStyle {
|
||||
visible: boolean;
|
||||
color: string;
|
||||
opacity: number;
|
||||
partId: number;
|
||||
}
|
||||
|
||||
interface ModelPose {
|
||||
rotateX: number;
|
||||
rotateY: number;
|
||||
@@ -708,6 +701,28 @@ export default function ProjectLibrary({
|
||||
const sliceTotal = dicomPreview?.total ?? selectedProject?.dicomCount ?? 0;
|
||||
const selectedSolidity = solidityOptions.find((option) => option.id === solidityLevel) ?? solidityOptions[0];
|
||||
|
||||
const makeDefaultModuleStyle = (index: number, fallback?: Partial<ModuleStyle>): ModuleStyle => ({
|
||||
visible: fallback?.visible ?? true,
|
||||
color: fallback?.color ?? defaultModuleColors[index % defaultModuleColors.length],
|
||||
opacity: fallback?.opacity ?? 0.72,
|
||||
partId: Math.max(1, Math.min(255, Math.round(fallback?.partId ?? index + 1))),
|
||||
});
|
||||
|
||||
const commitModuleStyles = (next: Record<string, ModuleStyle>) => {
|
||||
setModuleStyles(next);
|
||||
if (!selectedProject) {
|
||||
return;
|
||||
}
|
||||
api.updateProjectModuleStyles(selectedProject.id, next)
|
||||
.then((updated) => {
|
||||
setSelectedProject(updated);
|
||||
setProjects((items) => items.map((item) => (item.id === updated.id ? updated : item)));
|
||||
})
|
||||
.catch((error) => {
|
||||
setActionMessage(error instanceof Error ? error.message : '构件样式保存失败');
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setViewMode(initialViewMode);
|
||||
}, [initialViewMode]);
|
||||
@@ -715,12 +730,7 @@ export default function ProjectLibrary({
|
||||
useEffect(() => {
|
||||
const next: Record<string, ModuleStyle> = {};
|
||||
stlFiles.forEach((fileName, index) => {
|
||||
next[fileName] = moduleStyles[fileName] ?? {
|
||||
visible: true,
|
||||
color: defaultModuleColors[index % defaultModuleColors.length],
|
||||
opacity: 0.72,
|
||||
partId: index + 1,
|
||||
};
|
||||
next[fileName] = makeDefaultModuleStyle(index, selectedProject?.moduleStyles?.[fileName] ?? moduleStyles[fileName]);
|
||||
});
|
||||
setModuleStyles(next);
|
||||
setSliceIndex(0);
|
||||
@@ -773,17 +783,15 @@ export default function ProjectLibrary({
|
||||
}, [sliceIndex, sliceTotal]);
|
||||
|
||||
const updateModuleStyle = (fileName: string, partial: Partial<ModuleStyle>) => {
|
||||
setModuleStyles(prev => ({
|
||||
...prev,
|
||||
[fileName]: {
|
||||
visible: true,
|
||||
color: '#3b82f6',
|
||||
opacity: 0.72,
|
||||
partId: 1,
|
||||
...(prev[fileName] ?? {}),
|
||||
const index = Math.max(0, stlFiles.indexOf(fileName));
|
||||
const next = {
|
||||
...moduleStyles,
|
||||
[fileName]: makeDefaultModuleStyle(index, {
|
||||
...(moduleStyles[fileName] ?? selectedProject?.moduleStyles?.[fileName]),
|
||||
...partial,
|
||||
},
|
||||
}));
|
||||
}),
|
||||
};
|
||||
commitModuleStyles(next);
|
||||
};
|
||||
|
||||
const updateModulePartId = (fileName: string, value: number) => {
|
||||
@@ -793,18 +801,14 @@ export default function ProjectLibrary({
|
||||
|
||||
const toggleAllModules = () => {
|
||||
const nextVisible = !allModulesVisible;
|
||||
setModuleStyles(prev => {
|
||||
const next = { ...prev };
|
||||
stlFiles.forEach((fileName, index) => {
|
||||
next[fileName] = {
|
||||
visible: nextVisible,
|
||||
color: next[fileName]?.color ?? defaultModuleColors[index % defaultModuleColors.length],
|
||||
opacity: next[fileName]?.opacity ?? 0.72,
|
||||
partId: next[fileName]?.partId ?? index + 1,
|
||||
};
|
||||
const next = { ...moduleStyles };
|
||||
stlFiles.forEach((fileName, index) => {
|
||||
next[fileName] = makeDefaultModuleStyle(index, {
|
||||
...(next[fileName] ?? selectedProject?.moduleStyles?.[fileName]),
|
||||
visible: nextVisible,
|
||||
});
|
||||
return next;
|
||||
});
|
||||
commitModuleStyles(next);
|
||||
};
|
||||
|
||||
const stepSlice = (delta: number) => {
|
||||
@@ -1290,7 +1294,7 @@ export default function ProjectLibrary({
|
||||
|
||||
<div className="rounded-2xl bg-slate-50 border border-slate-100 p-4 space-y-3">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p className="text-xs font-bold text-slate-700">整体位姿</p>
|
||||
<p className="text-xs font-bold text-slate-700">模型位姿</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={resetModelRotationPose}
|
||||
|
||||
Reference in New Issue
Block a user