diff --git a/components/label/LabelNossr.tsx b/components/label/LabelNossr.tsx index 8e3a961..d94fd83 100644 --- a/components/label/LabelNossr.tsx +++ b/components/label/LabelNossr.tsx @@ -228,6 +228,7 @@ const LabelPage = ({ const labelData = useLabelStore((state) => state.label) const setLabel = useLabelStore((state) => state.setLabel) const setStateStack = useLabelStore((state) => state.setStateStack) + const selectedPathMap = useObjectStore((state) => state.selectedPath) const setLabelTime = useLabelTimeStore((state) => state.setLabelTime) const isAutoSave = useIntervalStore((state) => state.isAutoSave) const autoSaveGap = useIntervalStore((state) => state.autoSaveGap) @@ -244,6 +245,8 @@ const LabelPage = ({ showGroupList, showTaskList, showDescList, + showTags, + showTagsConfigs, showMultiFrame, setShowMultiFrame, isView, @@ -2086,6 +2089,7 @@ const LabelPage = ({ console.log(e.key) const mode = usePaperStore.getState().mode const lowerKey = e.key.toLowerCase() + const commandKey = e.ctrlKey || e.metaKey if (e.repeat && ["a", "b", "d", "h", "m", ",", "."].includes(lowerKey)) return @@ -2170,7 +2174,7 @@ const LabelPage = ({ return } - if (e.ctrlKey && e.key.toLowerCase() === "f") { + if (commandKey && lowerKey === "f") { e.preventDefault() handleMergeSelectedObjects() return @@ -2189,24 +2193,26 @@ const LabelPage = ({ useKeyboardStore.getState().setShift(true) } - if (mode !== "support") - if (Number(e.key)) { - handleShortcut(e.key, e.ctrlKey) - } else if (Number(e.key) === 0) { - handleShortcut("10", e.ctrlKey) + if (mode !== "support" && /^[0-9]$/.test(e.key)) { + if (commandKey) e.preventDefault() + if (e.key === "0") { + handleShortcut("10", commandKey) + } else { + handleShortcut(e.key, commandKey) } + } - if (e.key === "s" && (e.metaKey || e.ctrlKey)) { + if (lowerKey === "s" && commandKey) { e.preventDefault() setIsConfirmSave(true) } - if (e.key === "g" && (e.metaKey || e.ctrlKey)) { + if (lowerKey === "g" && commandKey) { e.preventDefault() paperContainerRef.current.handleCreatePathGroup() } - if (e.key === "Control") { + if (e.key === "Control" || e.key === "Meta") { e.preventDefault() useKeyboardStore.getState().setCtrl(true) } @@ -2241,7 +2247,7 @@ const LabelPage = ({ } // 复制 - if (e.key === "c" && e.ctrlKey) { + if (lowerKey === "c" && commandKey) { e.preventDefault() useKeyboardStore .getState() @@ -2253,13 +2259,13 @@ const LabelPage = ({ } // 粘贴 - if (e.key === "v" && e.ctrlKey) { + if (lowerKey === "v" && commandKey) { e.preventDefault() paperContainerRef.current.copyAnnotationDataToMultiFrame() } // 撤回 - if (e.key === "z" && e.ctrlKey) { + if (lowerKey === "z" && commandKey) { e.preventDefault() // 清除当前页数据 const clear = () => { @@ -2349,11 +2355,13 @@ const LabelPage = ({ setShift(false) useKeyboardStore.getState().setShift(false) } - if (e.key === "Control") { + if (e.key === "Control" || e.key === "Meta") { useKeyboardStore.getState().setCtrl(false) } } const wheel = (e: WheelEvent) => { + const target = e.target as HTMLElement | null + if (target?.closest('[data-label-context-menu="true"]')) return e.preventDefault() const currentScale = useTopToolsStore.getState().scale let newScale = e.deltaY < 0 ? currentScale * 1.1 : currentScale * 0.9 @@ -2555,6 +2563,62 @@ const LabelPage = ({ return h }, [projectDetail?.label_type, metaOperation, showMultiFrame, headerHeight]) + const selectedTagPreviewList = useMemo(() => { + if (!showTags) return [] + const selectedIds = selectedPathMap[activeImage] || [] + if (!selectedIds.length) return [] + const imageLabel = labelData.get(activeImage) + if (!imageLabel) return [] + + const selectedIdSet = new Set(selectedIds) + const rawItems: Array<{ id: number; content: string }> = [] + + imageLabel.forEach((labelList, categoryId) => { + const category = objectOperations.find( + (item) => item.category_id.toString() === categoryId + ) + const labelClass = category?.label_class || "" + labelList.forEach(([id, _points, detail]) => { + if (!selectedIdSet.has(id)) return + const parentGroupId = + usePaperStore.getState().getItemById(id)?.data?.parentGroupId ?? + detail?.parentGroupId + let content = "" + if (showTagsConfigs.includes("ID")) { + content += `${id}${parentGroupId ? `@${parentGroupId}` : ""}` + } + if (showTagsConfigs.includes("类别")) { + content += `${content ? " " : ""}${labelClass}` + } + if ( + detail?.sub_attributes && + Object.keys(detail.sub_attributes).length + ) { + Object.keys(detail.sub_attributes).forEach((key) => { + if (showTagsConfigs.includes("子属性")) content += ` ${key}:` + if (showTagsConfigs.includes("属性值")) + content += `${detail.sub_attributes[key]};` + }) + } + + const normalized = content.trim() + if (!normalized) return + rawItems.push({ id, content: normalized }) + }) + }) + + return selectedIds + .map((id) => rawItems.find((item) => item.id === id)) + .filter((item): item is { id: number; content: string } => !!item) + }, [ + activeImage, + labelData, + objectOperations, + selectedPathMap, + showTags, + showTagsConfigs, + ]) + const fullscreenRef = useRef(null) return ( @@ -2627,14 +2691,50 @@ const LabelPage = ({ }} mode="vertical" /> - + + + {selectedTagPreviewList.length > 0 && ( + + + 选中对象标签 + + + {selectedTagPreviewList.map((item) => ( + + {item.content} + + ))} + + + )} + diff --git a/components/label/components/PaperContainer.tsx b/components/label/components/PaperContainer.tsx index 003b8f8..9c9cc9d 100644 --- a/components/label/components/PaperContainer.tsx +++ b/components/label/components/PaperContainer.tsx @@ -2363,10 +2363,14 @@ const PaperContainer = ( return ( { + event.stopPropagation() + }} style={{ position: "absolute", zIndex: 1000, diff --git a/components/label/usePaperStore.ts b/components/label/usePaperStore.ts index b2ee6b5..468b75c 100644 --- a/components/label/usePaperStore.ts +++ b/components/label/usePaperStore.ts @@ -1425,27 +1425,17 @@ export const usePaperStore = create((set) => ({ }) // 标识位为true时:选中路径隐藏tags; 没选中显示tags const configs = useTopToolsStore.getState().showTagsConfigs - if (useTopToolsStore.getState().showTags) - if (panMode) { - lastTags.forEach((tag) => { - if (tag.data.tag_category === "mask") - tag.visible = configs.includes("外框") - else if (tag.data.tag_category === "point_text") - tag.visible = configs.includes("点ID") - else tag.visible = true - }) - tags.forEach((tag) => { - tag.visible = false - }) - } else { - tags.forEach((tag) => { - if (tag.data.tag_category === "mask") - tag.visible = configs.includes("外框") - else if (tag.data.tag_category === "point_text") - tag.visible = configs.includes("点ID") - else tag.visible = true - }) + if (useTopToolsStore.getState().showTags) { + const setTagVisibleByConfig = (tag: any) => { + if (tag.data.tag_category === "mask") + tag.visible = configs.includes("外框") + else if (tag.data.tag_category === "point_text") + tag.visible = configs.includes("点ID") + else tag.visible = true } + lastTags.forEach(setTagVisibleByConfig) + tags.forEach(setTagVisibleByConfig) + } console.log("鼠标按下 选中路径", activePath, "当前模式", panMode) @@ -5332,6 +5322,14 @@ export const usePaperStore = create((set) => ({ circles.forEach((circle) => { circle.scale(1 / newScale) }) + + const tagItems = usePaperStore.getState().group!.getItems({ + data: { type: "tag" }, + }) as paper.Item[] + tagItems.forEach((item) => { + if (item.data?.tag_category === "mask") return + item.scale(1 / newScale) + }) } }, getAll: () => { diff --git a/components/label/useRenderTag.ts b/components/label/useRenderTag.ts index bda9efa..ad10f98 100644 --- a/components/label/useRenderTag.ts +++ b/components/label/useRenderTag.ts @@ -72,6 +72,7 @@ const useRenderTag = () => { parent: group, visible, }) + // 文本框 const textMask = new paper.Path.Rectangle(text.bounds) textMask.set({