2026-05-08-03-03-52 修正DICOM切片范围为单范围条

This commit is contained in:
2026-05-08 03:07:21 +08:00
parent 22b0a93654
commit 765e4cc41a
6 changed files with 255 additions and 24 deletions

View File

@@ -818,6 +818,8 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
const safeSliceEnd = clamp(sliceEnd, 0, maxSlice);
const displayStart = Math.min(safeSliceStart, safeSliceEnd);
const displayEnd = Math.max(safeSliceStart, safeSliceEnd);
const rangeStartPercent = maxSlice > 0 ? (displayStart / maxSlice) * 100 : 0;
const rangeEndPercent = maxSlice > 0 ? (displayEnd / maxSlice) * 100 : 0;
const selectedDisplay = displayOptions.find((item) => item.id === displayLevel) ?? displayOptions[0];
const selectedDicomOpacity = dicomOpacityOptions.find((item) => item.id === dicomOpacityLevel) ?? dicomOpacityOptions[0];
const preloadPoints = [0.2, 0.4, 0.6, 0.8, 1].map((ratio) => clamp(Math.max(0, Math.round((project?.dicomCount ?? 1) * ratio) - 1), 0, maxSlice));
@@ -924,30 +926,43 @@ export default function ReverseWorkspace({ projectId }: { projectId: string }) {
{displayStart + 1} - {displayEnd + 1} / {project?.dicomCount ?? 0}
</span>
</div>
<label className="grid grid-cols-[76px_1fr_64px] items-center gap-3 text-[10px] font-bold text-slate-500">
<input
type="range"
min="0"
max={maxSlice}
value={safeSliceStart}
onChange={(event) => setSliceStart(Number(event.target.value))}
className="accent-blue-600"
/>
<span className="text-right font-mono">{safeSliceStart + 1}</span>
</label>
<label className="mt-2 grid grid-cols-[76px_1fr_64px] items-center gap-3 text-[10px] font-bold text-slate-500">
<input
type="range"
min="0"
max={maxSlice}
value={safeSliceEnd}
onChange={(event) => setSliceEnd(Number(event.target.value))}
className="accent-blue-600"
/>
<span className="text-right font-mono">{safeSliceEnd + 1}</span>
</label>
<div className="py-1">
<div className="relative h-10">
<div className="absolute inset-x-0 top-1/2 h-2 -translate-y-1/2 rounded-full bg-slate-200" />
<div
className="absolute top-1/2 h-2 -translate-y-1/2 rounded-full bg-blue-600"
style={{
left: `${rangeStartPercent}%`,
right: `${100 - rangeEndPercent}%`,
}}
/>
<input
type="range"
aria-label="DICOM 切片范围起点"
min="0"
max={maxSlice}
value={safeSliceStart}
onChange={(event) => setSliceStart(Number(event.target.value))}
className="dicom-range-input"
style={{ zIndex: safeSliceStart >= safeSliceEnd ? 5 : 4 }}
/>
<input
type="range"
aria-label="DICOM 切片范围终点"
min="0"
max={maxSlice}
value={safeSliceEnd}
onChange={(event) => setSliceEnd(Number(event.target.value))}
className="dicom-range-input"
style={{ zIndex: safeSliceStart >= safeSliceEnd ? 4 : 5 }}
/>
</div>
<div className="mt-1 grid grid-cols-3 text-[10px] font-bold text-slate-500">
<span> {safeSliceStart + 1}</span>
<span className="text-center text-blue-600"></span>
<span className="text-right"> {safeSliceEnd + 1}</span>
</div>
</div>
<p className="mt-3 text-[10px] leading-5 text-slate-400">
M-N姿
</p>

View File

@@ -1 +1,61 @@
@import "tailwindcss";
.dicom-range-input {
appearance: none;
-webkit-appearance: none;
background: transparent;
height: 100%;
inset: 0;
pointer-events: none;
position: absolute;
width: 100%;
}
.dicom-range-input:focus {
outline: none;
}
.dicom-range-input::-webkit-slider-runnable-track {
background: transparent;
border: 0;
height: 8px;
}
.dicom-range-input::-webkit-slider-thumb {
appearance: none;
-webkit-appearance: none;
background: #2563eb;
border: 3px solid #ffffff;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.28);
cursor: grab;
height: 20px;
margin-top: -6px;
pointer-events: auto;
width: 20px;
}
.dicom-range-input::-moz-range-track {
background: transparent;
border: 0;
height: 8px;
}
.dicom-range-input::-moz-range-thumb {
background: #2563eb;
border: 3px solid #ffffff;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.28);
cursor: grab;
height: 14px;
pointer-events: auto;
width: 14px;
}
.dicom-range-input:active::-webkit-slider-thumb {
cursor: grabbing;
}
.dicom-range-input:active::-moz-range-thumb {
cursor: grabbing;
}