2026-05-20-02-32-47 支持NII导出包与分割类别范围
This commit is contained in:
@@ -13,7 +13,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import * as THREE from 'three';
|
||||
import { DicomFusionVolume, DicomPreview, ModelPose, ModuleStyle, Project, SavedModelPose } from '../types';
|
||||
import { api, downloadMask, downloadSelectedProjectExports, ProjectExportTarget } from '../lib/api';
|
||||
import { api, downloadMask, downloadProjectExportBundle, ProjectExportTarget, SegmentationExportScope } from '../lib/api';
|
||||
|
||||
interface ModelPreviewPayload {
|
||||
fileName: string;
|
||||
@@ -83,6 +83,10 @@ const exportOptions: Array<{ id: ProjectExportTarget; label: string; description
|
||||
{ id: 'segmentation', label: '分割影像', description: '同维度 Label Map' },
|
||||
{ id: 'pose', label: '位姿数据', description: 'JSON 侧车' },
|
||||
];
|
||||
const segmentationScopeOptions: Array<{ id: SegmentationExportScope; label: string; description: string }> = [
|
||||
{ id: 'visible', label: '可见类别', description: '仅导出当前显示构件' },
|
||||
{ id: 'all', label: '所有类别', description: '包含隐藏构件' },
|
||||
];
|
||||
const moduleColors = ['#3b82f6', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6', '#14b8a6', '#f97316', '#64748b', '#ec4899'];
|
||||
const fusionBaseExtent = 4.6;
|
||||
const axisInsetLength = 17;
|
||||
@@ -1925,6 +1929,7 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
|
||||
segmentation: true,
|
||||
pose: true,
|
||||
});
|
||||
const [segmentationExportScope, setSegmentationExportScope] = useState<SegmentationExportScope>('visible');
|
||||
const [project, setProject] = useState<Project | null>(null);
|
||||
const [fusionVolume, setFusionVolume] = useState<DicomFusionVolume | null>(null);
|
||||
const [fusionError, setFusionError] = useState('');
|
||||
@@ -1936,7 +1941,7 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
|
||||
const handleExport = async (format: 'nii' | 'nii.gz') => {
|
||||
setExporting(true);
|
||||
try {
|
||||
await downloadMask(projectId, format, modelPose);
|
||||
await downloadMask(projectId, format, modelPose, segmentationExportScope);
|
||||
} catch (error) {
|
||||
setFusionError(error instanceof Error ? error.message : '导出失败');
|
||||
} finally {
|
||||
@@ -1956,8 +1961,11 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
|
||||
setExporting(true);
|
||||
setFusionError('');
|
||||
try {
|
||||
await downloadSelectedProjectExports(projectId, selectedItems, 'nii.gz', { pose: modelPose });
|
||||
window.setTimeout(() => setExporting(false), selectedItems.length * 220 + 200);
|
||||
await downloadProjectExportBundle(projectId, selectedItems, 'nii.gz', {
|
||||
pose: modelPose,
|
||||
segmentationScope: segmentationExportScope,
|
||||
});
|
||||
window.setTimeout(() => setExporting(false), 900);
|
||||
setShowExportMenu(false);
|
||||
} catch (error) {
|
||||
setFusionError(error instanceof Error ? error.message : '导出失败');
|
||||
@@ -2329,12 +2337,38 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
{exportSelection.segmentation && (
|
||||
<div className="mt-3 rounded-xl border border-emerald-100 bg-emerald-50/70 p-2">
|
||||
<div className="mb-2 flex items-center justify-between gap-2">
|
||||
<p className="text-[10px] font-bold text-emerald-800">分割类别范围</p>
|
||||
<span className="text-[9px] font-bold text-emerald-600">附带 labels.json</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
{segmentationScopeOptions.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
onClick={() => setSegmentationExportScope(option.id)}
|
||||
className={`rounded-lg px-2 py-1.5 text-left transition ${
|
||||
segmentationExportScope === option.id
|
||||
? 'bg-emerald-600 text-white shadow-sm'
|
||||
: 'bg-white text-emerald-700 hover:bg-emerald-100'
|
||||
}`}
|
||||
>
|
||||
<span className="block text-[10px] font-bold">{option.label}</span>
|
||||
<span className={`block text-[9px] ${segmentationExportScope === option.id ? 'text-emerald-50' : 'text-emerald-500'}`}>
|
||||
{option.description}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
onClick={handleExportSelected}
|
||||
disabled={exporting}
|
||||
className="mt-3 flex h-9 w-full items-center justify-center rounded-xl bg-slate-900 text-[11px] font-bold text-white hover:bg-black disabled:opacity-50"
|
||||
>
|
||||
导出所选
|
||||
导出所选压缩包
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user