perf(timer): perf
This commit is contained in:
@@ -48,7 +48,11 @@ import { useDescToolsStore } from "./useDescToolsStore"
|
||||
import { useKeyboardStore } from "./useKeyBoardStore"
|
||||
import { usePaperStore } from "./usePaperStore"
|
||||
import { useRightToolsStore } from "./useRightToolsStore"
|
||||
import { useIntervalStore, useTimerStore } from "./useTimerStore"
|
||||
import {
|
||||
useIntervalStore,
|
||||
useLabelTimeStore,
|
||||
useTimerStore,
|
||||
} from "./useTimerStore"
|
||||
import { useTopToolsStore } from "./useTopToolsStore"
|
||||
import { findGroupKey } from "./util"
|
||||
import { safeClone } from "./utils/clone"
|
||||
@@ -157,19 +161,20 @@ const LabelPage = ({
|
||||
// Project.LabelSchemaList[]
|
||||
// >([]);
|
||||
const topRef = useRef<any>(null)
|
||||
const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const autoSaveInProgressRef = useRef(false)
|
||||
const paperContainerRef = useRef<any>(null)
|
||||
const qaToolContainerRef = useRef<any>(null)
|
||||
const [isConfirmSave, setIsConfirmSave] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [sizes, setSizes] = useState<number[]>([])
|
||||
|
||||
const {
|
||||
label: labelData,
|
||||
setLabel,
|
||||
setStateStack,
|
||||
setLabelTime,
|
||||
} = useLabelStore()
|
||||
const { isAutoSave, autoSaveGap } = useIntervalStore()
|
||||
const labelData = useLabelStore((state) => state.label)
|
||||
const setLabel = useLabelStore((state) => state.setLabel)
|
||||
const setStateStack = useLabelStore((state) => state.setStateStack)
|
||||
const setLabelTime = useLabelTimeStore((state) => state.setLabelTime)
|
||||
const isAutoSave = useIntervalStore((state) => state.isAutoSave)
|
||||
const autoSaveGap = useIntervalStore((state) => state.autoSaveGap)
|
||||
|
||||
const {
|
||||
editMode,
|
||||
@@ -1310,17 +1315,40 @@ const LabelPage = ({
|
||||
|
||||
// auto save
|
||||
useEffect(() => {
|
||||
if (isAutoSave && !isView) {
|
||||
const minute = 60 * 1000
|
||||
useIntervalStore.getState().startTimer(() => {
|
||||
topRef.current.handleSave()
|
||||
}, autoSaveGap * minute)
|
||||
} else {
|
||||
useIntervalStore.getState().clearTimer()
|
||||
let cancelled = false
|
||||
if (autoSaveTimerRef.current !== null) {
|
||||
clearTimeout(autoSaveTimerRef.current)
|
||||
autoSaveTimerRef.current = null
|
||||
}
|
||||
if (!isAutoSave || isView) return
|
||||
|
||||
const minute = 60 * 1000
|
||||
const delay = autoSaveGap * minute
|
||||
const scheduleNext = () => {
|
||||
autoSaveTimerRef.current = setTimeout(async () => {
|
||||
if (cancelled) return
|
||||
if (autoSaveInProgressRef.current) {
|
||||
scheduleNext()
|
||||
return
|
||||
}
|
||||
autoSaveInProgressRef.current = true
|
||||
try {
|
||||
await topRef.current?.handleSave?.()
|
||||
} catch (error) {
|
||||
console.error("[LabelNossr] auto save failed", error)
|
||||
} finally {
|
||||
autoSaveInProgressRef.current = false
|
||||
if (!cancelled) scheduleNext()
|
||||
}
|
||||
}, delay)
|
||||
}
|
||||
scheduleNext()
|
||||
return () => {
|
||||
useIntervalStore.getState().clearTimer()
|
||||
cancelled = true
|
||||
if (autoSaveTimerRef.current !== null) {
|
||||
clearTimeout(autoSaveTimerRef.current)
|
||||
autoSaveTimerRef.current = null
|
||||
}
|
||||
}
|
||||
}, [autoSaveGap, isAutoSave, isView])
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import { useDescToolsStore } from "../useDescToolsStore"
|
||||
import { useKeyboardStore } from "../useKeyBoardStore"
|
||||
import { useOtherToolsStore } from "../useOtherToolsStore"
|
||||
import { usePaperStore } from "../usePaperStore"
|
||||
import { useLabelTimeStore } from "../useTimerStore"
|
||||
import { useTopToolsStore } from "../useTopToolsStore"
|
||||
import { getSubAttrStatus } from "../util"
|
||||
import { safeClone } from "../utils/clone"
|
||||
@@ -50,7 +51,9 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
|
||||
const itemRefs = useRef<Record<string, HTMLDivElement | null>>({})
|
||||
|
||||
const { label: storeLabel, setLabel, pushStateStack } = useLabelStore()
|
||||
const storeLabel = useLabelStore((state) => state.label)
|
||||
const setLabel = useLabelStore((state) => state.setLabel)
|
||||
const pushStateStack = useLabelStore((state) => state.pushStateStack)
|
||||
const {
|
||||
inputNumber,
|
||||
setInputNumber,
|
||||
@@ -521,17 +524,16 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
review2_uid: 0,
|
||||
}
|
||||
data.key_frame = true
|
||||
const currentLabelTime =
|
||||
useLabelTimeStore.getState().labelTime
|
||||
if (taskDetail.label_status === 2) {
|
||||
data.label1_ts =
|
||||
useLabelStore.getState().labelTime.label
|
||||
data.label1_ts = currentLabelTime.label
|
||||
data.label1_uid = usePermissionStore.getState().user_id
|
||||
} else if (taskDetail.label_status === 4) {
|
||||
data.review1_ts =
|
||||
useLabelStore.getState().labelTime.review1
|
||||
data.review1_ts = currentLabelTime.review1
|
||||
data.review1_uid = usePermissionStore.getState().user_id
|
||||
} else if (taskDetail.label_status === 6) {
|
||||
data.review2_ts =
|
||||
useLabelStore.getState().labelTime.review2
|
||||
data.review2_ts = currentLabelTime.review2
|
||||
data.review2_uid = usePermissionStore.getState().user_id
|
||||
}
|
||||
setKeyFrameData(activeImage, data)
|
||||
|
||||
@@ -159,12 +159,12 @@ const PaperContainer = (
|
||||
|
||||
const { activeImage } = useBottomToolsStore()
|
||||
|
||||
const {
|
||||
label: storeLabel,
|
||||
deleteOperation,
|
||||
setOperation,
|
||||
getLabelDetailDataByKeys,
|
||||
} = useLabelStore()
|
||||
const storeLabel = useLabelStore((state) => state.label)
|
||||
const deleteOperation = useLabelStore((state) => state.deleteOperation)
|
||||
const setOperation = useLabelStore((state) => state.setOperation)
|
||||
const getLabelDetailDataByKeys = useLabelStore(
|
||||
(state) => state.getLabelDetailDataByKeys
|
||||
)
|
||||
|
||||
const {
|
||||
objectOperations,
|
||||
|
||||
@@ -49,7 +49,8 @@ const RightGroupTools: React.FC<RightGroupToolsComponentProps> = (props) => {
|
||||
},
|
||||
[projectDetail?.label_schema_list]
|
||||
)
|
||||
const { setLabel, pushStateStack } = useLabelStore()
|
||||
const setLabel = useLabelStore((state) => state.setLabel)
|
||||
const pushStateStack = useLabelStore((state) => state.pushStateStack)
|
||||
const { pathGroupMap, groupPathVisible, setGroupPathVisible } =
|
||||
useRightToolsStore()
|
||||
const { activeImage } = useBottomToolsStore()
|
||||
|
||||
@@ -78,7 +78,7 @@ export const renderOperationIcon = (
|
||||
const RightObjectTools: React.FC<RightObjectToolsComponentProps> = (props) => {
|
||||
const { labelState, projectDetail, taskDetail } = props
|
||||
|
||||
const { label: storeLabel } = useLabelStore()
|
||||
const storeLabel = useLabelStore((state) => state.label)
|
||||
|
||||
const { activeImage } = useBottomToolsStore()
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ import { useBottomToolsStore } from "../useBottomToolsStore"
|
||||
import { useDescToolsStore } from "../useDescToolsStore"
|
||||
import { usePaperStore } from "../usePaperStore"
|
||||
import { useRightToolsStore } from "../useRightToolsStore"
|
||||
import { useIntervalStore } from "../useTimerStore"
|
||||
import { useIntervalStore, useLabelTimeStore } from "../useTimerStore"
|
||||
import { useTopToolsStore } from "../useTopToolsStore"
|
||||
import { getSubAttrStatus } from "../util"
|
||||
import { labelTypeMap, TaskStatusEnum } from "../utils/constants"
|
||||
@@ -133,6 +133,17 @@ const initialWorkLoad: WorkLoad = {
|
||||
question_size: {},
|
||||
}
|
||||
|
||||
const TaskTimerDisplay = ({
|
||||
currentTimeKey,
|
||||
}: {
|
||||
currentTimeKey: "label" | "review1" | "review2"
|
||||
}) => {
|
||||
const currentTime = useLabelTimeStore(
|
||||
(state) => state.labelTime[currentTimeKey]
|
||||
)
|
||||
return <>{dayjs.duration(currentTime, "seconds").format("HH:mm:ss")}</>
|
||||
}
|
||||
|
||||
const TopTools = (
|
||||
props: TopToolsComponentProps,
|
||||
ref: React.Ref<unknown> | undefined
|
||||
@@ -157,13 +168,10 @@ const TopTools = (
|
||||
const [duplicateName, setDuplicateName] = useState("")
|
||||
const [recoverOpen, setRecoverOpen] = useState(false)
|
||||
const [taskOpen, setTaskOpen] = useState(false)
|
||||
const {
|
||||
label: labelData,
|
||||
setLabel,
|
||||
labelTime,
|
||||
setLabelTime,
|
||||
pushStateStack,
|
||||
} = useLabelStore()
|
||||
const labelData = useLabelStore((state) => state.label)
|
||||
const setLabel = useLabelStore((state) => state.setLabel)
|
||||
const pushStateStack = useLabelStore((state) => state.pushStateStack)
|
||||
const setLabelTime = useLabelTimeStore((state) => state.setLabelTime)
|
||||
const { activeImage } = useBottomToolsStore()
|
||||
const {
|
||||
isView,
|
||||
@@ -212,8 +220,10 @@ const TopTools = (
|
||||
} = useTopToolsStore()
|
||||
|
||||
const { pathGroupMap } = useRightToolsStore()
|
||||
const { isAutoSave, setIsAutoSave, autoSaveGap, setAutoSaveGap } =
|
||||
useIntervalStore()
|
||||
const isAutoSave = useIntervalStore((state) => state.isAutoSave)
|
||||
const setIsAutoSave = useIntervalStore((state) => state.setIsAutoSave)
|
||||
const autoSaveGap = useIntervalStore((state) => state.autoSaveGap)
|
||||
const setAutoSaveGap = useIntervalStore((state) => state.setAutoSaveGap)
|
||||
|
||||
// 当前是否可以操作功能按键
|
||||
const currentEditAuth = useMemo(() => {
|
||||
@@ -723,10 +733,11 @@ const TopTools = (
|
||||
}
|
||||
}
|
||||
|
||||
const currentLabelTime = useLabelTimeStore.getState().labelTime
|
||||
const workTime = {
|
||||
label_work_time: labelTime.label,
|
||||
first_review_work_time: labelTime.review1,
|
||||
second_review_work_time: labelTime.review2,
|
||||
label_work_time: currentLabelTime.label,
|
||||
first_review_work_time: currentLabelTime.review1,
|
||||
second_review_work_time: currentLabelTime.review2,
|
||||
}
|
||||
// 生成新workload
|
||||
let time = 0
|
||||
@@ -851,9 +862,6 @@ const TopTools = (
|
||||
}
|
||||
}, [
|
||||
labelCategories,
|
||||
labelTime.label,
|
||||
labelTime.review1,
|
||||
labelTime.review2,
|
||||
oldWorkLoad,
|
||||
pathGroupMap,
|
||||
projectDetail,
|
||||
@@ -1257,22 +1265,23 @@ const TopTools = (
|
||||
console.log(error)
|
||||
return
|
||||
}
|
||||
const currentLabelTime = useLabelTimeStore.getState().labelTime
|
||||
const handleAction = (current_status: number) => {
|
||||
switch (current_status) {
|
||||
case 2:
|
||||
return {
|
||||
commit_action: key || 1,
|
||||
work_time: labelTime.label,
|
||||
work_time: currentLabelTime.label,
|
||||
}
|
||||
case 4:
|
||||
return {
|
||||
commit_action: key || 2,
|
||||
work_time: labelTime.review1,
|
||||
work_time: currentLabelTime.review1,
|
||||
}
|
||||
case 6:
|
||||
return {
|
||||
commit_action: key || 3,
|
||||
work_time: labelTime.review2,
|
||||
work_time: currentLabelTime.review2,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
@@ -1345,15 +1354,15 @@ const TopTools = (
|
||||
useEffect(() => {
|
||||
let timer = setInterval(() => {
|
||||
if (isView) return
|
||||
setLabelTime({
|
||||
...labelTime,
|
||||
[currentTimeKey]: labelTime[currentTimeKey] + 1,
|
||||
})
|
||||
setLabelTime((prev) => ({
|
||||
...prev,
|
||||
[currentTimeKey]: prev[currentTimeKey] + 1,
|
||||
}))
|
||||
}, 1000)
|
||||
return () => {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, [currentTimeKey, isView, labelTime, setLabelTime])
|
||||
}, [currentTimeKey, isView, setLabelTime])
|
||||
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
@@ -1748,9 +1757,7 @@ const TopTools = (
|
||||
{isLabelTask && (
|
||||
<Flex justify="space-between" align="center" gap="md" px="md">
|
||||
<Timer style={{ width: 20, height: 20 }} />
|
||||
{dayjs
|
||||
.duration(labelTime[currentTimeKey], "seconds")
|
||||
.format("HH:mm:ss")}
|
||||
<TaskTimerDisplay currentTimeKey={currentTimeKey} />
|
||||
</Flex>
|
||||
)}
|
||||
<Flex justify="flex-end" align="center" gap="md" px="0" flex={1}>
|
||||
|
||||
@@ -7,6 +7,11 @@ import { safeClone } from "./utils/clone"
|
||||
|
||||
type LabelData = Map<string, Map<string, [number, any[], any, any[]][]>>
|
||||
type LabelPathTuple = [number, any[], any, any[]]
|
||||
type LabelTime = {
|
||||
label: number
|
||||
review1: number
|
||||
review2: number
|
||||
}
|
||||
|
||||
const isPaperPointLike = (value: any) => {
|
||||
return (
|
||||
@@ -53,11 +58,7 @@ const normalizeLabelPathTuple = (path: LabelPathTuple): LabelPathTuple => {
|
||||
interface LabelState {
|
||||
// pathId pathPoints detail hollowPathPoints
|
||||
label: LabelData
|
||||
labelTime: {
|
||||
label: number
|
||||
review1: number
|
||||
review2: number
|
||||
}
|
||||
labelTime: LabelTime
|
||||
labelDefaultComments: Comment[]
|
||||
setLabel: (label: LabelData) => void
|
||||
stateStack: LabelData[]
|
||||
@@ -83,11 +84,9 @@ interface LabelState {
|
||||
[keys: string]: any
|
||||
}
|
||||
) => void
|
||||
setLabelTime: (labelTime: {
|
||||
label: number
|
||||
review1: number
|
||||
review2: number
|
||||
}) => void
|
||||
setLabelTime: (
|
||||
labelTime: LabelTime | ((prev: LabelTime) => LabelTime)
|
||||
) => void
|
||||
setLabelDefaultComments: (arr: Comment[]) => void
|
||||
setImage: (
|
||||
imageId: string,
|
||||
@@ -312,7 +311,10 @@ export const useLabelStore = create(
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
labelTime,
|
||||
labelTime:
|
||||
typeof labelTime === "function"
|
||||
? labelTime(state.labelTime)
|
||||
: labelTime,
|
||||
}
|
||||
}),
|
||||
setLabelDefaultComments: (labelDefaultComments) =>
|
||||
|
||||
@@ -65,3 +65,40 @@ export const useIntervalStore = create<IntervalStore>((set, get) => ({
|
||||
set((state) => ({ ...state, autoSaveGap: value }))
|
||||
},
|
||||
}))
|
||||
|
||||
export interface LabelTimeState {
|
||||
label: number
|
||||
review1: number
|
||||
review2: number
|
||||
}
|
||||
|
||||
interface LabelTimeStore {
|
||||
labelTime: LabelTimeState
|
||||
setLabelTime: (
|
||||
labelTime: LabelTimeState | ((prev: LabelTimeState) => LabelTimeState)
|
||||
) => void
|
||||
resetLabelTime: () => void
|
||||
}
|
||||
|
||||
const initialLabelTimeState: LabelTimeState = {
|
||||
label: 0,
|
||||
review1: 0,
|
||||
review2: 0,
|
||||
}
|
||||
|
||||
export const useLabelTimeStore = create<LabelTimeStore>((set) => ({
|
||||
labelTime: initialLabelTimeState,
|
||||
setLabelTime: (labelTime) =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
labelTime:
|
||||
typeof labelTime === "function"
|
||||
? labelTime(state.labelTime)
|
||||
: labelTime,
|
||||
})),
|
||||
resetLabelTime: () =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
labelTime: initialLabelTimeState,
|
||||
})),
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user