add per-state DICOM zip downloads

This commit is contained in:
2026-05-03 00:17:30 +08:00
parent 18541db9d4
commit 479a39d880
2 changed files with 38 additions and 7 deletions

View File

@@ -815,6 +815,7 @@ export default function App() {
].map(t => { ].map(t => {
const screenshotDir = deformationJob?.result?.previews?.screenshots; const screenshotDir = deformationJob?.result?.previews?.screenshots;
const imagePath = screenshotDir ? `${screenshotDir}/${t.key}.png` : ''; const imagePath = screenshotDir ? `${screenshotDir}/${t.key}.png` : '';
const stateZip = deformationJob?.result?.stateZips?.[t.key];
return ( return (
<div key={t.key} className="bg-white p-4 rounded-2xl border flex flex-col hover:border-blue-200 transition-colors shadow-sm group min-h-[285px]"> <div key={t.key} className="bg-white p-4 rounded-2xl border flex flex-col hover:border-blue-200 transition-colors shadow-sm group min-h-[285px]">
<div className="flex justify-between items-center mb-3"> <div className="flex justify-between items-center mb-3">
@@ -831,6 +832,15 @@ export default function App() {
</div> </div>
)} )}
</div> </div>
{stateZip?.path && (
<a
href={fileUrl(stateZip.path)}
download={stateZip.name}
className="mt-3 py-2.5 bg-slate-100 text-slate-600 rounded-xl text-[11px] font-black hover:bg-green-600 hover:text-white transition-all flex items-center justify-center gap-2"
>
<Download size={13} /> DICOM ZIP
</a>
)}
</div> </div>
); );
})} })}

View File

@@ -467,18 +467,27 @@ def make_preview(input_dir, angle_degrees):
} }
def serialize_outputs(output_paths, preview_paths, zip_path=None): def zip_metadata(zip_path):
zip_path = Path(zip_path).resolve()
return {
"path": str(zip_path),
"name": zip_path.name,
"size": zip_path.stat().st_size,
}
def serialize_outputs(output_paths, preview_paths, zip_path=None, state_zips=None):
return { return {
"outputs": {key: str(Path(value).resolve()) for key, value in output_paths.items()}, "outputs": {key: str(Path(value).resolve()) for key, value in output_paths.items()},
"previews": { "previews": {
"comparison": str(Path(preview_paths["comparison"]).resolve()), "comparison": str(Path(preview_paths["comparison"]).resolve()),
"screenshots": str(Path(preview_paths["screenshots"]).resolve()), "screenshots": str(Path(preview_paths["screenshots"]).resolve()),
}, },
"zip": { "zip": zip_metadata(zip_path) if zip_path else None,
"path": str(Path(zip_path).resolve()), "stateZips": {
"name": Path(zip_path).name, key: zip_metadata(value)
"size": Path(zip_path).stat().st_size, for key, value in (state_zips or {}).items()
} if zip_path else None, },
} }
@@ -591,12 +600,24 @@ class Handler(BaseHTTPRequestHandler):
transition_width, transition_width,
progress, progress,
) )
set_job(job_id, message="正在打包各状态 DICOM ZIP...")
state_zips = {}
for state_key in [
"original",
"hard_boundary",
"gaussian_smooth",
"soft_transition",
]:
state_zips[state_key] = zip_folder(
output_paths[state_key],
job_root / f"{state_key}_{job_id}.zip",
)
set_job(job_id, message="正在打包四状态输出 ZIP...") set_job(job_id, message="正在打包四状态输出 ZIP...")
zip_path = zip_folder( zip_path = zip_folder(
output_dir, output_dir,
job_root / f"head_ct_morph_{job_id}.zip", job_root / f"head_ct_morph_{job_id}.zip",
) )
return serialize_outputs(output_paths, preview_paths, zip_path) return serialize_outputs(output_paths, preview_paths, zip_path, state_zips)
self.send_json(start_job("deformation", worker), status=202) self.send_json(start_job("deformation", worker), status=202)
return return