2026-05-20-23-28-51 项目库映射交互与导入提示优化
This commit is contained in:
@@ -1257,7 +1257,7 @@ interface PlaneSegment {
|
||||
b: Point2D;
|
||||
}
|
||||
|
||||
interface OverlayStats {
|
||||
export interface OverlayStats {
|
||||
activeModules: number;
|
||||
filledPixels: number;
|
||||
segmentCount: number;
|
||||
@@ -1881,6 +1881,7 @@ export function VoxelizationMappingView({
|
||||
variant = 'workspace',
|
||||
toolbar,
|
||||
overlayPlacement,
|
||||
onOverlayStatsChange,
|
||||
}: {
|
||||
project: Project | null;
|
||||
moduleStyles: Record<string, ModuleStyle>;
|
||||
@@ -1893,7 +1894,8 @@ export function VoxelizationMappingView({
|
||||
rotation: number;
|
||||
variant?: 'workspace' | 'library';
|
||||
toolbar?: React.ReactNode;
|
||||
overlayPlacement?: 'bottom' | 'side';
|
||||
overlayPlacement?: 'bottom' | 'side' | 'none';
|
||||
onOverlayStatsChange?: (stats: OverlayStats, visibleModuleCount: number) => void;
|
||||
}) {
|
||||
const baseCanvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||
const overlayCanvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||
@@ -1918,6 +1920,10 @@ export function VoxelizationMappingView({
|
||||
const isLibraryVariant = variant === 'library';
|
||||
const activeOverlayPlacement = overlayPlacement ?? (isLibraryVariant ? 'side' : 'bottom');
|
||||
|
||||
useEffect(() => {
|
||||
onOverlayStatsChange?.(overlayStats, visibleModuleCount);
|
||||
}, [onOverlayStatsChange, overlayStats, visibleModuleCount]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!project?.dicomCount) {
|
||||
setDicomPreview(null);
|
||||
@@ -2360,6 +2366,7 @@ export default function ReverseWorkspace({
|
||||
const workspaceLoadProjectRef = useRef('');
|
||||
const poseRepeatRef = useRef<{ timeout: number | null; interval: number | null }>({ timeout: null, interval: null });
|
||||
const poseImportInputRef = useRef<HTMLInputElement | null>(null);
|
||||
const visualToolbarScrollRef = useRef<HTMLDivElement | null>(null);
|
||||
const saveToastTimerRef = useRef<number | null>(null);
|
||||
const savedWorkspaceSnapshotRef = useRef('');
|
||||
const initialZStretchRef = useRef<{ projectId: string; pending: boolean }>({ projectId: '', pending: false });
|
||||
@@ -2767,13 +2774,26 @@ export default function ReverseWorkspace({
|
||||
}
|
||||
};
|
||||
|
||||
const restoreVisualToolbarScroll = (scrollTop: number | null) => {
|
||||
if (scrollTop === null) {
|
||||
return;
|
||||
}
|
||||
window.requestAnimationFrame(() => {
|
||||
if (visualToolbarScrollRef.current) {
|
||||
visualToolbarScrollRef.current.scrollTop = scrollTop;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const nudgeModelPose = (key: ModelPoseKey, delta: number) => {
|
||||
const scrollTop = visualToolbarScrollRef.current?.scrollTop ?? null;
|
||||
setModelPose((current) => ({
|
||||
...current,
|
||||
[key]: clampPoseValue(key, current[key] + delta),
|
||||
}));
|
||||
setSelectedPoseId('custom');
|
||||
setPoseImportStatus('');
|
||||
restoreVisualToolbarScroll(scrollTop);
|
||||
};
|
||||
|
||||
const handlePoseInputChange = (key: ModelPoseKey, value: string) => {
|
||||
@@ -3378,7 +3398,7 @@ export default function ReverseWorkspace({
|
||||
</div>
|
||||
|
||||
<div className="flex-1 bg-white rounded-3xl border border-slate-100 shadow-sm overflow-hidden flex flex-col p-4 gap-4">
|
||||
<div className="flex-1 overflow-auto space-y-4 pr-1">
|
||||
<div ref={visualToolbarScrollRef} className="flex-1 overflow-auto space-y-4 pr-1">
|
||||
<div>
|
||||
<p className="mb-2 text-[10px] font-bold uppercase tracking-widest text-slate-400">模型显示</p>
|
||||
<div className="grid grid-cols-2 gap-1 rounded-xl bg-slate-100 p-1">
|
||||
@@ -3511,7 +3531,10 @@ export default function ReverseWorkspace({
|
||||
<div key={item.key} className="grid grid-cols-[44px_28px_1fr_28px_72px] items-center gap-2 text-[10px] font-bold text-slate-500">
|
||||
<span>{item.label}</span>
|
||||
<button
|
||||
onMouseDown={() => startPoseRepeat(item.key, -poseStepConfig[item.key].step)}
|
||||
onMouseDown={(event) => {
|
||||
event.preventDefault();
|
||||
startPoseRepeat(item.key, -poseStepConfig[item.key].step);
|
||||
}}
|
||||
onMouseUp={stopPoseRepeat}
|
||||
onMouseLeave={stopPoseRepeat}
|
||||
onTouchStart={(event) => {
|
||||
@@ -3535,7 +3558,10 @@ export default function ReverseWorkspace({
|
||||
className="accent-blue-600"
|
||||
/>
|
||||
<button
|
||||
onMouseDown={() => startPoseRepeat(item.key, poseStepConfig[item.key].step)}
|
||||
onMouseDown={(event) => {
|
||||
event.preventDefault();
|
||||
startPoseRepeat(item.key, poseStepConfig[item.key].step);
|
||||
}}
|
||||
onMouseUp={stopPoseRepeat}
|
||||
onMouseLeave={stopPoseRepeat}
|
||||
onTouchStart={(event) => {
|
||||
|
||||
Reference in New Issue
Block a user