From dfd5f0fca10416b5573a2aa675a737edc8371d3a Mon Sep 17 00:00:00 2001 From: zhangheng Date: Wed, 15 Apr 2026 17:13:28 +0800 Subject: [PATCH] fix(tool): fix size bug --- components/label/LabelNossr.tsx | 143 ++++++++++++------ .../label/components/PaperContainer.tsx | 9 ++ .../label/components/RightObjectTools.tsx | 37 +++-- components/label/components/TopTools.tsx | 10 +- 4 files changed, 136 insertions(+), 63 deletions(-) diff --git a/components/label/LabelNossr.tsx b/components/label/LabelNossr.tsx index e4241e9..f902128 100644 --- a/components/label/LabelNossr.tsx +++ b/components/label/LabelNossr.tsx @@ -83,6 +83,11 @@ let latestTaskDetailRequestSeq = 0 const RIGHT_PANEL_TRANSITION = "width 160ms ease, min-width 160ms ease, opacity 160ms ease" const RIGHT_PANEL_WILL_CHANGE = "width, min-width, opacity" +const RIGHT_PANEL_SEPARATOR = + "1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))" +const RIGHT_PANEL_SOFT_MAIN_MIN_WIDTH = 420 +const RIGHT_PANEL_HARD_MAIN_MIN_WIDTH = 260 +const RIGHT_PANEL_TARGET_WIDTH = 350 // utils const getRectPoints = ([sx, sy, w, h]: number[]) => { @@ -111,6 +116,51 @@ const getRightPanelViewportStyle = (width: number) => { } } +const allocateRightPanelSizes = ( + availableWidth: number, + visibleFlags: boolean[] +) => { + const resolvedWidth = Math.max(0, Math.round(availableWidth)) + const nextSizes = [resolvedWidth, 0, 0, 0, 0, 0] + const activeIndexes = visibleFlags.reduce((result, flag, index) => { + if (flag) result.push(index + 1) + return result + }, []) + + if (!activeIndexes.length) return nextSizes + + const activeCount = activeIndexes.length + const softPanelBudget = Math.max( + 0, + resolvedWidth - RIGHT_PANEL_SOFT_MAIN_MIN_WIDTH + ) + const hardPanelBudget = Math.max( + 0, + resolvedWidth - RIGHT_PANEL_HARD_MAIN_MIN_WIDTH + ) + let panelWidth = Math.min( + RIGHT_PANEL_TARGET_WIDTH, + Math.floor(softPanelBudget / activeCount) + ) + + if (panelWidth < RIGHT_PANEL_TARGET_WIDTH) { + panelWidth = Math.min( + RIGHT_PANEL_TARGET_WIDTH, + Math.floor(hardPanelBudget / activeCount) + ) + } + + panelWidth = Math.max(0, panelWidth) + activeIndexes.forEach((index) => { + nextSizes[index] = panelWidth + }) + + const rightPanelTotalWidth = panelWidth * activeCount + nextSizes[0] = Math.max(0, resolvedWidth - rightPanelTotalWidth) + + return nextSizes +} + const videoExtPattern = /\.(mp4|mov|avi|mkv|webm|h264|264|ts|m4v)$/i const GLOBAL_LOADING_Z_INDEX = 900 const videoMimeByExt: Record = { @@ -233,7 +283,7 @@ const LabelPage = ({ const qaToolContainerRef = useRef(null) const [isConfirmSave, setIsConfirmSave] = useState(false) const [loading, setLoading] = useState(false) - const [sizes, setSizes] = useState([]) + const [sizes, setSizes] = useState([0, 0, 0, 0, 0, 0]) const [videoFetchPendingCount, setVideoFetchPendingCount] = useState(0) const [hasReadyVideoFrame, setHasReadyVideoFrame] = useState(false) const [sourceVideoNames, setSourceVideoNames] = useState([]) @@ -2479,51 +2529,35 @@ const LabelPage = ({ // 更新Splitter状态 const updateSplitterSizes = useCallback(() => { - console.log( - "document.documentElement.clientWidth", - document.documentElement.clientWidth + const availableWidth = Math.max( + document.documentElement.clientWidth - leftWidth - 4, + 0 ) - - const len = document.documentElement.clientWidth - 4 - let arr = [len, 0, 0, 0, 0, 0] - const flags = [ + const flags: boolean[] = [ showTaskList, showGroupList, - showDescList && projectDetail && projectDetail.label_type === 5, - showDescList && projectDetail && projectDetail.label_type === 6, + (showDescList && projectDetail && projectDetail.label_type === 5) || + false, + (showDescList && projectDetail && projectDetail.label_type === 6) || + false, showObjectList, ] - let count = 0 - flags.forEach((flag) => { - if (flag) count++ - }) - if (count === 1 || count === 2) { - arr[0] = count === 1 ? len * 0.8 : len * 0.6 - flags.forEach((flag, index) => { - if (flag) { - arr[index + 1] = len * 0.2 - } - }) - } else if (count === 3) { - arr[0] = len * 0.55 - flags.forEach((flag, index) => { - if (flag) { - arr[index + 1] = len * 0.15 - } - }) - } else if (count === 4) { - arr[0] = len * 0.6 - flags.forEach((flag, index) => { - if (flag) { - arr[index + 1] = len * 0.1 - } - }) - } - setSizes(arr) - }, [projectDetail, showDescList, showGroupList, showObjectList, showTaskList]) + setSizes(allocateRightPanelSizes(availableWidth, flags)) + }, [ + leftWidth, + projectDetail, + showDescList, + showGroupList, + showObjectList, + showTaskList, + ]) useEffect(() => { updateSplitterSizes() + window.addEventListener("resize", updateSplitterSizes) + return () => { + window.removeEventListener("resize", updateSplitterSizes) + } }, [updateSplitterSizes]) useEffect(() => { @@ -2702,7 +2736,7 @@ const LabelPage = ({ {/* */} - + - + - + - + @@ -2853,7 +2893,7 @@ const LabelPage = ({ w={sizes[4]} miw={ showDescList && projectDetail && projectDetail.label_type === 6 - ? 350 + ? sizes[4] : 0 } style={{ @@ -2872,16 +2912,20 @@ const LabelPage = ({ showDescList && projectDetail && projectDetail.label_type === 6 ? "auto" : "none", + borderLeft: + showDescList && projectDetail && projectDetail.label_type === 6 + ? RIGHT_PANEL_SEPARATOR + : "none", transition: RIGHT_PANEL_TRANSITION, willChange: RIGHT_PANEL_WILL_CHANGE, }}> - + - + 0 && firstRender && lastSize?.clientWidth && @@ -3132,6 +3133,8 @@ const PaperContainer = ( const activeImageChanged = prevActiveImageRef.current !== activeImage prevActiveImageRef.current = activeImage const hasPicRaster = getPicRasters(currentGroup).length > 0 + const preserveViewportOnLayoutResize = + useTopToolsStore.getState().saveCurrentScale if (!useTopToolsStore.getState().saveCurrentScale) { currentGroup.scaling = new paper.Point(1, 1) @@ -3143,6 +3146,12 @@ const PaperContainer = ( } if (!activeImageChanged) { + if ( + preserveViewportOnLayoutResize && + (hasPicRaster || rasterLoadingImageRef.current === activeImage) + ) { + return + } if (resizeCurrentImage()) { return } diff --git a/components/label/components/RightObjectTools.tsx b/components/label/components/RightObjectTools.tsx index 1a4e4ea..74d1e9f 100644 --- a/components/label/components/RightObjectTools.tsx +++ b/components/label/components/RightObjectTools.tsx @@ -30,7 +30,7 @@ import { Spline, } from "lucide-react" import paper from "paper" -import { useCallback, useState } from "react" +import { useCallback, useMemo, useState } from "react" import { Project } from "../api/project/typing" import { Task } from "../api/task/typing" import { LabelState } from "../LabelNossr" @@ -151,6 +151,7 @@ const RightObjectTools: React.FC = (props) => { continuePolygonTarget?.imageId === activeImage ? continuePolygonTarget.objectId : null + const objectOperations = useTopToolsStore((state) => state.objectOperations) const getOperationChildren = useCallback( (imageId: string, operationId: string) => { @@ -415,9 +416,13 @@ const RightObjectTools: React.FC = (props) => { [activeImage] ) - const activeImageOperations = (labelState.get(activeImage) || []).filter( - (operationId) => getOperationChildren(activeImage, operationId).length - ) + const activeImageOperations = useMemo(() => { + const schemaOperationIds = objectOperations.map((item) => + item.category_id.toString() + ) + const imageOperationIds = labelState.get(activeImage) || [] + return Array.from(new Set([...schemaOperationIds, ...imageOperationIds])) + }, [activeImage, labelState, objectOperations]) const isObjectHidden = (imageId: string, objectId: number) => { return pathStatus[imageId + objectId]?.["HIDE"] ?? false @@ -558,9 +563,17 @@ const RightObjectTools: React.FC = (props) => { return ( - - + + { @@ -571,20 +584,23 @@ const RightObjectTools: React.FC = (props) => { }}> {areAllObjectsHidden ? : } - + <Title + order={5} + size="h5" + style={{ whiteSpace: "nowrap", lineHeight: 1.1 }}> 对象列表 - + setSearchId(e.target.value)} onKeyDown={handleSelectedBySearchId} /> - + {[3, 2, 1, 0].map((type, index) => ( = (props) => { ))} { updateImageStatus( diff --git a/components/label/components/TopTools.tsx b/components/label/components/TopTools.tsx index c41e7ca..e818b8e 100644 --- a/components/label/components/TopTools.tsx +++ b/components/label/components/TopTools.tsx @@ -54,8 +54,8 @@ import { MousePointer, Paintbrush, Pen, - SquarePen, SquareDashedMousePointer, + SquarePen, Tag, Timer, } from "lucide-react" @@ -263,14 +263,15 @@ const TopTools = ( const nextVisible = !visible const nextCount = visibleRightPanelCount + (nextVisible ? 1 : -1) if ( - (visibleRightPanelCount === 0 && nextCount === 1) || - (visibleRightPanelCount === 1 && nextCount === 0) + !saveCurrentScale && + ((visibleRightPanelCount === 0 && nextCount === 1) || + (visibleRightPanelCount === 1 && nextCount === 0)) ) { requestResizeGhost() } setter(nextVisible) }, - [requestResizeGhost, visibleRightPanelCount] + [requestResizeGhost, saveCurrentScale, visibleRightPanelCount] ) // 当前是否可以操作功能按键 @@ -1118,6 +1119,7 @@ const TopTools = ( }) try { await handleSave() + notifications.hide("save") } catch (error) { console.log(error) return