307 lines
10 KiB
TypeScript
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
|