From 1e62e96953c56399cddaa00cc1727cb93e4325e0 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Wed, 15 Apr 2026 19:03:27 +0800 Subject: [PATCH 1/6] fix(label): contextMenu --- .../label/components/PaperContainer.tsx | 76 +++++++------------ components/label/components/TopTools.tsx | 40 +++------- components/label/util.ts | 39 ++++++++++ 3 files changed, 76 insertions(+), 79 deletions(-) diff --git a/components/label/components/PaperContainer.tsx b/components/label/components/PaperContainer.tsx index 43af6c9..5042816 100644 --- a/components/label/components/PaperContainer.tsx +++ b/components/label/components/PaperContainer.tsx @@ -52,7 +52,7 @@ import { renderGroupPath } from "../useRenderGroupPath" import useRenderTag from "../useRenderTag" import { useRightToolsStore } from "../useRightToolsStore" import { useTopToolsStore } from "../useTopToolsStore" -import { checkCommentsIsSame } from "../util" +import { buildSubAttributeFormValues, checkCommentsIsSame } from "../util" import { safeClone } from "../utils/clone" import { labelTypeMap } from "../utils/constants" import { adjustPoints } from "../utils/paperjs" @@ -3315,50 +3315,26 @@ const PaperContainer = ( .get(activeImage) ?.get(operationId) ?.find((item) => item[0] === id) + const operationSchema = getOperationSchema(operationId) + const nowComment = + currentPath?.[2].comment?.[currentPath?.[2].comment.length - 1] - form.setFieldValue("id", id.toString()) - form.setFieldValue("operation", operationId) - if (currentPath?.[2].sub_attributes) { - let operationSchema = getOperationSchema(operationId) - let obj: { - [key: string]: string | string[] - } = {} - Object.entries(currentPath?.[2].sub_attributes).map(([key, value]) => { - let select_mode = operationSchema?.sub_attributes_describe?.find( - (item) => item.chinese_name === key - )?.select_mode - switch (select_mode) { - case 2: - obj[key] = Array.isArray(value) - ? value - : (value as string) - .split(",") - .map((item) => item.trim()) - .filter(Boolean) - return - default: - obj[key] = value as string - return - } - }) - form.setFieldValue("sub_attributes", obj) - } - if (currentPath?.[2].comment) { - const nowComment = - currentPath?.[2].comment[currentPath?.[2].comment.length - 1] - form.setFieldValue( - "check_box_comments", + form.setValues({ + id: id.toString(), + operation: operationId, + sub_attributes: buildSubAttributeFormValues( + operationSchema, + currentPath?.[2].sub_attributes || {} + ), + check_box_comments: nowComment && nowComment.check_box_comments.length ? nowComment.check_box_comments - : [] - ) - form.setFieldValue( - "text_comments", + : [], + text_comments: nowComment && nowComment.text_comments.length ? nowComment.text_comments[0] - : "" - ) - } + : "", + }) // 可选的ids let images = Array.from(labelState.keys()).filter( (key) => key !== activeImage @@ -3580,11 +3556,10 @@ const PaperContainer = ( }) } // newOperation的subAttributes - let subAttr = Object.assign( - {}, + let subAttr = safeClone( useTopToolsStore.getState().subAttributes[ operationSchema?.label_class ?? "" - ] + ] || {} ) // 修改labeldata setOperation(activeImage, newOperation, [ @@ -3612,16 +3587,21 @@ const PaperContainer = ( ) const handleChangeContextMenuSubAttr = useCallback( - (key: string, value: string) => { + (key: string, value: string | string[]) => { + const currentSubAttributes = safeClone( + (pathItem?.[2]?.sub_attributes || + newDetail.sub_attributes || + {}) as Record + ) + currentSubAttributes[key] = Array.isArray(value) ? value.join(",") : value + setOperation(activeImage, operationId, [ id, pathItem?.[1] || [], { ...newDetail, ...(pathItem?.[2] || {}), - sub_attributes: Object.assign(newDetail.sub_attributes || {}, { - [key]: value, - }), + sub_attributes: currentSubAttributes, }, pathItem?.[3] || [], ]) @@ -3892,7 +3872,7 @@ const PaperContainer = ( ) handleChangeContextMenuSubAttr( item.chinese_name, - value.toString() + value ) }}> diff --git a/components/label/components/TopTools.tsx b/components/label/components/TopTools.tsx index e818b8e..a3ef089 100644 --- a/components/label/components/TopTools.tsx +++ b/components/label/components/TopTools.tsx @@ -98,7 +98,7 @@ import { NODE_SIZE_MIN, useTopToolsStore, } from "../useTopToolsStore" -import { getSubAttrStatus } from "../util" +import { buildSubAttributeFormValues, getSubAttrStatus } from "../util" import { safeClone } from "../utils/clone" import { labelTypeMap, TaskStatusEnum } from "../utils/constants" import { adjustAllPoints } from "../utils/paperjs" @@ -1488,36 +1488,10 @@ const TopTools = ( operationId: string, values: Record = {} ) => { - const schema = getOperationSchema(operationId) - if (!schema?.sub_attributes_describe?.length) return {} - - const nextValues: Record = {} - - schema.sub_attributes_describe.forEach((item) => { - const currentValue = values[item.chinese_name] - if ( - currentValue === undefined || - currentValue === null || - currentValue === "" - ) - return - - if (item.select_mode === 2) { - nextValues[item.chinese_name] = Array.isArray(currentValue) - ? currentValue - : currentValue - .split(",") - .map((value) => value.trim()) - .filter(Boolean) - return - } - - nextValues[item.chinese_name] = Array.isArray(currentValue) - ? currentValue[0] || "" - : currentValue - }) - - return nextValues + return buildSubAttributeFormValues( + getOperationSchema(operationId), + values + ) }, [getOperationSchema] ) @@ -1627,6 +1601,10 @@ const TopTools = ( size="xs" onClick={() => { form.reset() + form.setFieldValue( + "sub_attributes", + getPresetFormValues(activeOperation, {}) + ) if (operationSchema?.label_class) setsubAttributes(operationSchema.label_class, {}) }}> diff --git a/components/label/util.ts b/components/label/util.ts index 3e0bce3..9849c77 100644 --- a/components/label/util.ts +++ b/components/label/util.ts @@ -86,6 +86,45 @@ export const getSubAttrStatus = ( return bool } +export const buildSubAttributeFormValues = ( + operationSchema: Project.LabelSchemaList | null, + detail: Record = {} +) => { + const nextValues: Record = {} + if (!operationSchema?.sub_attributes_describe?.length) return nextValues + + operationSchema.sub_attributes_describe.forEach((item) => { + nextValues[item.chinese_name] = item.select_mode === 2 ? [] : "" + + const currentValue = detail?.[item.chinese_name] + if ( + currentValue === undefined || + currentValue === null || + currentValue === "" || + (Array.isArray(currentValue) && currentValue.length === 0) + ) { + return + } + + if (item.select_mode === 2) { + nextValues[item.chinese_name] = Array.isArray(currentValue) + ? currentValue + : currentValue + .toString() + .split(",") + .map((value: string) => value.trim()) + .filter(Boolean) + return + } + + nextValues[item.chinese_name] = Array.isArray(currentValue) + ? currentValue[0] || "" + : currentValue.toString() + }) + + return nextValues +} + // export const checkCommentsIsSame: ( a: any[] | null, From 7358306488b5810e8d6b89acaa22b6b0e182a68f Mon Sep 17 00:00:00 2001 From: zhangheng Date: Thu, 16 Apr 2026 13:55:51 +0800 Subject: [PATCH 2/6] fix(editor): fix --- components/label/components/EditorContainer.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/label/components/EditorContainer.tsx b/components/label/components/EditorContainer.tsx index d0fe8f8..3e60f21 100644 --- a/components/label/components/EditorContainer.tsx +++ b/components/label/components/EditorContainer.tsx @@ -3,7 +3,6 @@ import { Box } from "@mantine/core" import { RichTextEditor } from "@mantine/tiptap" import "@mantine/tiptap/styles.css" -import { IconPhoto } from "@tabler/icons-react" import Image from "@tiptap/extension-image" import Link from "@tiptap/extension-link" import Placeholder from "@tiptap/extension-placeholder" @@ -148,7 +147,7 @@ const EditorContainer = ({ - + {/* @@ -160,7 +159,7 @@ const EditorContainer = ({ title="上传图片"> - + */} From 1f9436864b95b962046f42cf41b5cd066b9462db Mon Sep 17 00:00:00 2001 From: zhangheng Date: Thu, 16 Apr 2026 15:13:26 +0800 Subject: [PATCH 3/6] feat(table): sum --- app/project/detail/OwnTaskTableContainer.tsx | 38 ++++++++++++++++++- app/project/detail/TaskTableContainer.tsx | 40 +++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/app/project/detail/OwnTaskTableContainer.tsx b/app/project/detail/OwnTaskTableContainer.tsx index 9844f91..5b03352 100644 --- a/app/project/detail/OwnTaskTableContainer.tsx +++ b/app/project/detail/OwnTaskTableContainer.tsx @@ -38,6 +38,31 @@ import { useRouter, useSearchParams } from "next/navigation" import { useCallback, useEffect, useMemo, useState } from "react" import TaskStatusTag from "./components/TaskStatusTag" +const EMPTY_TASK_SIZE: Task.SizeProps = Object.freeze({ + object_size: 0, + valid_size: 0, + first_comment_size: 0, + second_comment_size: 0, + new_size: 0, + prelabel_size: 0, + prelabel_modify_size: 0, + dynamic_size: 0, + static_size: 0, + review_size: 0, + review_dynamic_size: 0, + review_static_size: 0, + key_frame_size: 0, + question_size: 0, + total_qa_group_size: 0, + single_qa_group_size: 0, + multiple_qa_group_size: 0, + new_qa_group_size: 0, + new_single_qa_group_size: 0, + new_multiple_qa_group_size: 0, + review_question_size: 0, + comment_question_size: 0, +}) + function createInitialFilters() { return { search_id: "", @@ -67,6 +92,7 @@ export default function OwnTaskTableContainer(props: { const user_id = usePermissionStore((s) => s.user_id) const [total, setTotal] = useState(0) + const [totalSize, setTotalSize] = useState(EMPTY_TASK_SIZE) const [pageNumber, setPageNumber] = useState(1) const [pageSize, setPageSize] = useState(15) @@ -130,9 +156,11 @@ export default function OwnTaskTableContainer(props: { const res = await getTaskList(appliedParams) setRecords(res?.task_list ?? []) setTotal(res?.total_items ?? 0) + setTotalSize(res?.total_size ?? EMPTY_TASK_SIZE) } catch (e) { setRecords([]) setTotal(0) + setTotalSize(EMPTY_TASK_SIZE) notifications.show({ color: "red", title: "加载失败", @@ -201,6 +229,7 @@ export default function OwnTaskTableContainer(props: { accessor: "id", title: "任务ID", width: 100, + footer: "总计", render: (record) => (