From 8a2bc25c8d88ed5873b901d1ae7db05311dc1974 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Wed, 8 Apr 2026 17:13:15 +0800 Subject: [PATCH 1/3] fix(timer): interval-store --- components/label/useTimerStore.ts | 62 +++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/components/label/useTimerStore.ts b/components/label/useTimerStore.ts index 0471920..ce0f21a 100644 --- a/components/label/useTimerStore.ts +++ b/components/label/useTimerStore.ts @@ -1,4 +1,5 @@ import { create } from "zustand" +import { persist } from "zustand/middleware" interface TimerStore { timer: NodeJS.Timeout | null @@ -37,34 +38,41 @@ interface IntervalStore { setAutoSaveGap: (autoSaveGap: number) => void } -export const useIntervalStore = create((set, get) => ({ - timer: null, - isAutoSave: false, - autoSaveGap: 5, - startTimer: (fn, delay) => { - const { timer } = get() - if (timer !== null) { - clearInterval(timer) +export const useIntervalStore = create()( + persist( + (set, get) => ({ + timer: null, + isAutoSave: false, + autoSaveGap: 5, + startTimer: (fn, delay) => { + const { timer } = get() + if (timer !== null) { + clearInterval(timer) + } + const t = setInterval(() => { + fn() + }, delay) + set((state) => ({ ...state, timer: t })) + }, + clearTimer: () => { + const { timer } = get() + if (timer !== null) { + clearInterval(timer) + set((state) => ({ ...state, timer: null })) + } + }, + setIsAutoSave: (flag: boolean) => { + set((state) => ({ ...state, isAutoSave: flag })) + }, + setAutoSaveGap: (value: number) => { + set((state) => ({ ...state, autoSaveGap: value })) + }, + }), + { + name: "interval-store", } - const t = setInterval(() => { - fn() - }, delay) - set((state) => ({ ...state, timer: t })) - }, - clearTimer: () => { - const { timer } = get() - if (timer !== null) { - clearInterval(timer) - set((state) => ({ ...state, timer: null })) - } - }, - setIsAutoSave: (flag: boolean) => { - set((state) => ({ ...state, isAutoSave: flag })) - }, - setAutoSaveGap: (value: number) => { - set((state) => ({ ...state, autoSaveGap: value })) - }, -})) + ) +) export interface LabelTimeState { label: number From 9fb29b4b4172f6eced73ff0d6824833ef1728de0 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Thu, 9 Apr 2026 09:47:53 +0800 Subject: [PATCH 2/3] fix(label): improve doubleclick --- components/label/usePaperStore.ts | 80 +++++++++++++++++-------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/components/label/usePaperStore.ts b/components/label/usePaperStore.ts index 5bd17c6..9c742f7 100644 --- a/components/label/usePaperStore.ts +++ b/components/label/usePaperStore.ts @@ -509,6 +509,37 @@ export const getShowContextMenuPosition = ( } } +const DOUBLE_CLICK_TOLERANCE_PX = 8 + +const getPaperDoubleClickTolerance = ( + coordinateSpace: "project" | "local" = "project" +) => { + const viewZoom = usePaperStore.getState().paperScope?.view.zoom || 1 + const projectTolerance = DOUBLE_CLICK_TOLERANCE_PX / viewZoom + + if (coordinateSpace === "local") { + const groupScale = usePaperStore.getState().group?.scaling.x || 1 + return projectTolerance / groupScale + } + + return projectTolerance +} + +const isPaperDoubleClick = ( + event: MouseEvent, + lastPoint: paper.Point | null | undefined, + currentPoint: paper.Point, + coordinateSpace: "project" | "local" = "project" +) => { + if (event.button !== 0 || event.detail < 2 || !lastPoint) return false + + // 交给浏览器按系统双击速度判定,再补一个小范围容差,避免画布点击抖动。 + return ( + lastPoint.getDistance(currentPoint) <= + getPaperDoubleClickTolerance(coordinateSpace) + ) +} + export const usePositionStore = create((set) => ({ currentMousePosition: [0, 0], setCurrentMousePosition: (point) => @@ -637,7 +668,6 @@ export const usePaperStore = create((set) => ({ let panTool = paperPanTool let lastPoint: paper.Point let isChanged: boolean = false - let lastTime: number // const handleSelected = (path: paper.Path) => { // // path.blendMode = "subtract"; @@ -778,8 +808,6 @@ export const usePaperStore = create((set) => ({ panTool.onMouseDown = (e: { event: MouseEvent; point: paper.Point }) => { if (startMiddleMousePan(e.event)) return if (pressCtrl) return - const currentTime = Date.now() - const timeDelta = currentTime - lastTime if (e.event && e.event.button === 0) { hidePaperContextMenu() @@ -790,6 +818,12 @@ export const usePaperStore = create((set) => ({ } let point = usePaperStore.getState().group!.globalToLocal(e.point) + const isDoubleClick = isPaperDoubleClick( + e.event, + lastPoint, + point, + "local" + ) let hitResult = usePaperStore.getState().group?.hitTest(e.point, { segments: true, @@ -978,12 +1012,7 @@ export const usePaperStore = create((set) => ({ // item.fillColor = new paper.Color("transparent"); // item.strokeColor = item.strokeColor || new paper.Color("red"); // item.strokeWidth = item.strokeWidth || 1; - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { console.log("点击位置 多边形子路径", childHitResult) if (childHitResult.item instanceof paper.Path) { // if (!childHitResult.item.data.selected) { @@ -1011,12 +1040,7 @@ export const usePaperStore = create((set) => ({ }) } else if (hitResult.item instanceof paper.Path) { // doubleclick; - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (hitResult.item.data.isHollowPolygon) return let selectedItems = usePaperStore.getState().group!.getItems({ data: { selected: true }, @@ -1216,12 +1240,7 @@ export const usePaperStore = create((set) => ({ activePath?.data?.type === "point" ) { // doubleclick - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (activePath instanceof paper.CompoundPath) { ;(activePath.children as paper.Path[]).forEach((item) => { const childHitResult = item.hitTest(point, { @@ -1310,12 +1329,7 @@ export const usePaperStore = create((set) => ({ activePath?.data?.type === "brush" || activePath?.data?.type === "point" ) { - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (activePath instanceof paper.CompoundPath) { ;(activePath.children as paper.Path[]).forEach((item) => { const childHitResult = item.hitTest(point, { @@ -1456,7 +1470,6 @@ export const usePaperStore = create((set) => ({ console.log("鼠标按下 选中路径", activePath, "当前模式", panMode) lastPoint = point - lastTime = Date.now() } panTool.onMouseDrag = (e: { @@ -3320,12 +3333,9 @@ export const usePaperStore = create((set) => ({ // 先判断是否存在吸附点 let checkPoint = currentMagnetPoint ? currentMagnetPoint : e.point + const isDoubleClick = isPaperDoubleClick(e.event, lastPoint, checkPoint) // doubleclick - if ( - lastPoint && - lastPoint.x === checkPoint.x && - lastPoint.y === checkPoint.y - ) { + if (isDoubleClick) { if (polygon) { if ((polygon as paper.Path).segments.length < 3) { polygon.remove() @@ -4246,7 +4256,7 @@ export const usePaperStore = create((set) => ({ } // doubleclick - if (lastPoint && lastPoint.x === e.point.x && lastPoint.y === e.point.y) { + if (isPaperDoubleClick(e.event, lastPoint, e.point)) { if (myPath) { // 初始化 compoundPolygon compoundPolygon = new paper.Path() @@ -4717,7 +4727,7 @@ export const usePaperStore = create((set) => ({ } // doubleclick - if (lastPoint && lastPoint.x === e.point.x && lastPoint.y === e.point.y) { + if (isPaperDoubleClick(e.event, lastPoint, e.point)) { if (myPath) { // 去除超出图片边界的部分 myCircle = myCircle.filter((circle) => { From 32d061f4707430ab51914aac39d61b5713b47b12 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Thu, 9 Apr 2026 11:21:34 +0800 Subject: [PATCH 3/3] fix(env): redis -> 172.16.103.224/sam2 -> 8000 --- .env.production | 2 +- components/label/api/label/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.production b/.env.production index 7dce3df..c56ce5d 100644 --- a/.env.production +++ b/.env.production @@ -3,7 +3,7 @@ NEXT_PUBLIC_BASE_PATH="/image" NEXT_PUBLIC_ENV=production # redis -NEXT_PUBLIC_REDIS_URL="172.16.104.95" +NEXT_PUBLIC_REDIS_URL="172.16.103.224" NEXT_PUBLIC_REDIS_PORT=8015 NEXT_PUBLIC_REDIS_PASSWORD=aAXJM2uMzPu76L93 NEXT_PUBLIC_REDIS_USERNAME=default diff --git a/components/label/api/label/index.ts b/components/label/api/label/index.ts index 47179ec..c32f8e8 100644 --- a/components/label/api/label/index.ts +++ b/components/label/api/label/index.ts @@ -122,7 +122,7 @@ export const getAuxiliaryAnnotation = (data: any) => { const BASE_SAM_API = process.env.NEXT_PUBLIC_ENV === "production" - ? "http://172.16.103.224:9120" + ? "http://172.16.103.224:8000" : process.env.NEXT_PUBLIC_ENV === "staging" ? "http://172.30.21.211:8000" : "http://172.30.21.211:8000"