Files
labelmain-demo/components/label/components/RightDescTools.tsx
2026-02-09 18:20:33 +08:00

307 lines
10 KiB
TypeScript

"use client"
import {
Box,
Button,
Checkbox,
Flex,
Group,
Radio,
ScrollArea,
Stack,
Text,
TextInput,
} from "@mantine/core"
import { useForm } from "@mantine/form"
import { useEffect, useRef } from "react"
import { Task } from "../api/task/typing"
import { useBottomToolsStore } from "../useBottomToolsStore"
import { useDescToolsStore } from "../useDescToolsStore"
import { useTopToolsStore } from "../useTopToolsStore"
import EditorContainer from "./EditorContainer"
interface ComponentProps {
taskDetail?: Task.DataProps
// projectDetail?: Project.DetailResponse;
}
const RightDescTools = ({ taskDetail }: ComponentProps) => {
const { isView } = useTopToolsStore()
const { activeImage } = useBottomToolsStore()
const {
descOperations,
updateDescDataFlag,
setDescData,
getDataByClassName,
} = useDescToolsStore()
const form = useForm<any>({
initialValues: {},
})
const isUpdatingFromStore = useRef(false)
const handleFormUpdate = () => {
if (isUpdatingFromStore.current) return
const data = form.values as any
let dataMap = new Map()
taskDetail?.data_name.forEach((detail_name) => {
if (detail_name.name[0] !== activeImage) {
if (useDescToolsStore.getState().descData.has(detail_name.name[0])) {
dataMap.set(
detail_name.name[0],
useDescToolsStore.getState().descData.get(detail_name.name[0])
)
}
} else {
const updateMap = new Map()
Object.entries(data).forEach(([label_class, val]: any) => {
let value = { ...val }
if (value.is_correct !== undefined) {
value.is_correct = value.is_correct === "true"
}
const keys = Object.keys(value)
if (keys.includes("value")) {
updateMap.set(label_class, value)
} else {
updateMap.set(label_class, { value: value })
}
})
dataMap.set(activeImage, updateMap)
}
})
setDescData(dataMap)
}
useEffect(() => {
handleFormUpdate()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [form.values])
useEffect(() => {
isUpdatingFromStore.current = true
form.reset()
if (activeImage) {
const formData = useDescToolsStore
.getState()
.getFormDataByImageId(activeImage)
if (formData) {
const newFormData = { ...formData }
Object.keys(newFormData).forEach((key) => {
if (newFormData[key]?.is_correct !== undefined) {
newFormData[key] = {
...newFormData[key],
is_correct: String(newFormData[key].is_correct),
}
}
})
form.setValues(newFormData)
} else {
form.setValues({})
}
}
setTimeout(() => {
isUpdatingFromStore.current = false
}, 0)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeImage])
useEffect(() => {
if (updateDescDataFlag) {
isUpdatingFromStore.current = true
const formData = useDescToolsStore
.getState()
.getFormDataByImageId(useBottomToolsStore.getState().activeImage)
if (formData) {
const newFormData = { ...formData }
Object.keys(newFormData).forEach((key) => {
if (newFormData[key]?.is_correct !== undefined) {
newFormData[key] = {
...newFormData[key],
is_correct: String(newFormData[key].is_correct),
}
}
})
form.setValues(newFormData)
}
useDescToolsStore.getState().updateFlag(false)
setTimeout(() => {
isUpdatingFromStore.current = false
}, 0)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [updateDescDataFlag])
return (
<Box h="100%">
<Box
py="xs"
px="sm"
style={{
borderBottom:
"1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))",
}}>
<Text fw={600} size="lg">
</Text>
</Box>
<ScrollArea h="calc(100% - 34px)" px="sm">
<Stack gap="md" py="xs">
{descOperations.map((operation) => {
const isOptions = operation.sub_attributes_describe.length > 0
const isReview = [4, 6].includes(taskDetail?.label_status || 0)
const currentData = getDataByClassName(
activeImage,
operation.label_class
)
const hasComment = currentData?.comment
return (
<Box key={operation.label_class}>
<Flex justify="space-between" align="center" mb="xs">
{isOptions ? (
<Text fw={600} size="lg">
{operation.label_class}
</Text>
) : (
<Group>
<Text fw={600} size="lg">
{operation.label_class}
</Text>
<Radio.Group
{...form.getInputProps(
`${operation.label_class}.is_correct`
)}
size="xs">
<Group gap="xs">
<Radio
label="正确"
value="true"
disabled={!isReview || !!isView}
/>
<Radio
label="错误"
value="false"
disabled={!isReview || !!isView}
/>
</Group>
</Radio.Group>
</Group>
)}
{isReview && !hasComment && !isOptions ? (
<Button
variant="subtle"
size="xs"
onClick={() => {
form.setFieldValue(
`${operation.label_class}.comment`,
"<p></p>"
)
}}>
</Button>
) : null}
</Flex>
{isOptions ? (
operation.sub_attributes_describe.map((subDesc) => (
<Box
key={`${operation.label_class}${subDesc.chinese_name}`}
mb="xs">
{subDesc.select_mode === 0 ? (
<TextInput
label={subDesc.chinese_name}
placeholder={`请输入${subDesc.chinese_name}`}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}
disabled={!!isView}
/>
) : subDesc.select_mode === 1 ? (
<Radio.Group
label={subDesc.chinese_name}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}>
<Group gap="xs" mt={4}>
{subDesc.optional_item.map((option) => (
<Radio
key={option}
value={option}
label={option}
disabled={!!isView}
/>
))}
</Group>
</Radio.Group>
) : subDesc.select_mode === 2 ? (
<Checkbox.Group
label={subDesc.chinese_name}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}>
<Group gap="xs" mt={4}>
{subDesc.optional_item.map((option) => (
<Checkbox
key={option}
value={option}
label={option}
disabled={!!isView}
/>
))}
</Group>
</Checkbox.Group>
) : null}
</Box>
))
) : (
<>
<Box mb="xs">
<EditorContainer
value={
(form.values as any)[operation.label_class]?.value
}
onChange={(val: any) =>
form.setFieldValue(
`${operation.label_class}.value`,
val
)
}
/>
</Box>
<Box
style={{ display: !hasComment ? "none" : "block" }}
mt="xs">
<EditorContainer
color="border-danger"
value={
(form.values as any)[operation.label_class]?.comment
}
onChange={(val: any) =>
form.setFieldValue(
`${operation.label_class}.comment`,
val
)
}
/>
</Box>
</>
)}
</Box>
)
})}
</Stack>
</ScrollArea>
</Box>
)
}
export default RightDescTools