feat(tool): hide all object
This commit is contained in:
@@ -355,13 +355,10 @@ const RightObjectTools: React.FC<RightObjectToolsComponentProps> = (props) => {
|
||||
if (operationMap) {
|
||||
const objList = operationMap.get(operationId)
|
||||
if (objList && objList.length) {
|
||||
let hideFlag = true
|
||||
objList.forEach(([id]) => {
|
||||
const objStatus =
|
||||
useObjectStore.getState().pathStatus[`${imgId}${id}`]
|
||||
if (objStatus && !objStatus["HIDE"]) {
|
||||
hideFlag = false
|
||||
}
|
||||
const hideFlag = objList.every(([id]) => {
|
||||
return useObjectStore.getState().pathStatus[`${imgId}${id}`]?.["HIDE"]
|
||||
? true
|
||||
: false
|
||||
})
|
||||
updateOperationStatus(imgId + operationId, "HIDE", hideFlag)
|
||||
}
|
||||
@@ -401,6 +398,39 @@ const RightObjectTools: React.FC<RightObjectToolsComponentProps> = (props) => {
|
||||
[activeImage]
|
||||
)
|
||||
|
||||
const activeImageOperations = labelState.get(activeImage) || []
|
||||
|
||||
const isObjectHidden = (imageId: string, objectId: number) => {
|
||||
return pathStatus[imageId + objectId]?.["HIDE"] ?? false
|
||||
}
|
||||
|
||||
const isOperationHidden = (imageId: string, operationId: string) => {
|
||||
const operationChildren = storeLabel.get(imageId)?.get(operationId) || []
|
||||
return (
|
||||
operationChildren.length > 0 &&
|
||||
operationChildren.every(([objectId]) => isObjectHidden(imageId, objectId))
|
||||
)
|
||||
}
|
||||
|
||||
const totalObjectCount = activeImageOperations.reduce(
|
||||
(count, operationId) => {
|
||||
return (
|
||||
count + (storeLabel.get(activeImage)?.get(operationId)?.length || 0)
|
||||
)
|
||||
},
|
||||
0
|
||||
)
|
||||
|
||||
const areAllObjectsHidden =
|
||||
totalObjectCount > 0 &&
|
||||
activeImageOperations.every((operationId) => {
|
||||
const operationChildren =
|
||||
storeLabel.get(activeImage)?.get(operationId) || []
|
||||
return operationChildren.every(([objectId]) =>
|
||||
isObjectHidden(activeImage, objectId)
|
||||
)
|
||||
})
|
||||
|
||||
// const renderObjectName = useCallback((name: string, input: string) => {
|
||||
// const index = name?.indexOf(input);
|
||||
// const beforeStr = name?.substring(0, index);
|
||||
@@ -509,9 +539,22 @@ const RightObjectTools: React.FC<RightObjectToolsComponentProps> = (props) => {
|
||||
<Box h="100%" w="100%">
|
||||
<Flex direction="column" h="100%" gap="xs">
|
||||
<Flex justify="space-between" align="center" px="md" py="xs">
|
||||
<Title order={4} size="h4">
|
||||
对象列表
|
||||
</Title>
|
||||
<Group gap="xs">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
aria-label={areAllObjectsHidden ? "显示全部对象" : "隐藏全部对象"}
|
||||
onClick={() => {
|
||||
if (!totalObjectCount) return
|
||||
activeImageOperations.forEach((operationId) => {
|
||||
operationHide(operationId, !areAllObjectsHidden)
|
||||
})
|
||||
}}>
|
||||
{areAllObjectsHidden ? <EyeOff size={16} /> : <Eye size={16} />}
|
||||
</ActionIcon>
|
||||
<Title order={4} size="h4">
|
||||
对象列表
|
||||
</Title>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<TextInput
|
||||
w={96}
|
||||
@@ -566,441 +609,424 @@ const RightObjectTools: React.FC<RightObjectToolsComponentProps> = (props) => {
|
||||
}}>
|
||||
<ScrollArea style={{ flex: 1 }} px="md">
|
||||
<Stack gap="xs" pb="md">
|
||||
{labelState.get(activeImage) &&
|
||||
labelState.get(activeImage)?.map((operationId) => {
|
||||
const operationSchema = getOperationSchema(operationId)
|
||||
const isCollapsed =
|
||||
operationStatus[activeImage + operationId]?.["COLLAPSE"]
|
||||
const isHide =
|
||||
operationStatus[activeImage + operationId]?.HIDE
|
||||
const hasSubAttrError = getOperationSubAttrStatus(operationId)
|
||||
const operationLabel = operationSchema?.label_class
|
||||
const operationChildren =
|
||||
storeLabel.get(activeImage)?.get(operationId) || []
|
||||
const objectCount = operationChildren.length
|
||||
const visibleChildren = operationChildren.filter((child) => {
|
||||
const { comment } = child[2]
|
||||
let visibleFlag = true
|
||||
if (comment && comment.length) {
|
||||
const latest_comment =
|
||||
(taskDetail && taskDetail.label_status === 2) ||
|
||||
comment.length === 1
|
||||
? comment[comment.length - 1]
|
||||
: comment[comment.length - 2]
|
||||
let type = latest_comment.comment_type
|
||||
if (type === 2) {
|
||||
const { last_modified_timestamp } = child[2]
|
||||
if (
|
||||
last_modified_timestamp &&
|
||||
last_modified_timestamp > latest_comment.date
|
||||
)
|
||||
type = 3
|
||||
}
|
||||
visibleFlag = checkBoxsChecked[3 - type]
|
||||
{activeImageOperations.map((operationId) => {
|
||||
const operationSchema = getOperationSchema(operationId)
|
||||
const isCollapsed =
|
||||
operationStatus[activeImage + operationId]?.["COLLAPSE"]
|
||||
const isHide = isOperationHidden(activeImage, operationId)
|
||||
const hasSubAttrError = getOperationSubAttrStatus(operationId)
|
||||
const operationLabel = operationSchema?.label_class
|
||||
const operationChildren =
|
||||
storeLabel.get(activeImage)?.get(operationId) || []
|
||||
const objectCount = operationChildren.length
|
||||
const visibleChildren = operationChildren.filter((child) => {
|
||||
const { comment } = child[2]
|
||||
let visibleFlag = true
|
||||
if (comment && comment.length) {
|
||||
const latest_comment =
|
||||
(taskDetail && taskDetail.label_status === 2) ||
|
||||
comment.length === 1
|
||||
? comment[comment.length - 1]
|
||||
: comment[comment.length - 2]
|
||||
let type = latest_comment.comment_type
|
||||
if (type === 2) {
|
||||
const { last_modified_timestamp } = child[2]
|
||||
if (
|
||||
last_modified_timestamp &&
|
||||
last_modified_timestamp > latest_comment.date
|
||||
)
|
||||
type = 3
|
||||
}
|
||||
if (checkBoxsChecked.every((value) => !value))
|
||||
visibleFlag = true
|
||||
return visibleFlag
|
||||
})
|
||||
return (
|
||||
<Box key={operationId} w="100%">
|
||||
<Paper withBorder p="xs" radius="md" shadow="sm">
|
||||
<Flex align="center" gap="xs" style={{ minWidth: 0 }}>
|
||||
<Flex
|
||||
align="center"
|
||||
gap="xs"
|
||||
style={{ flex: 1, minWidth: 0 }}>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
operationHide(operationId, !isHide)
|
||||
}>
|
||||
{!isHide ? (
|
||||
<Eye size={16} />
|
||||
) : (
|
||||
<EyeOff size={16} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<Group
|
||||
gap={8}
|
||||
wrap="nowrap"
|
||||
style={{ flex: 1, minWidth: 0 }}>
|
||||
<Group
|
||||
gap={6}
|
||||
wrap="nowrap"
|
||||
px="xs"
|
||||
py={4}
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
borderRadius: 999,
|
||||
border: `1px solid ${
|
||||
hasSubAttrError
|
||||
? "var(--mantine-color-red-2)"
|
||||
: "var(--mantine-color-gray-2)"
|
||||
}`,
|
||||
background: hasSubAttrError
|
||||
? "var(--mantine-color-red-0)"
|
||||
: "var(--mantine-color-gray-0)",
|
||||
}}>
|
||||
{renderOperationIcon(operationSchema)}
|
||||
<Text
|
||||
size="xs"
|
||||
fw={700}
|
||||
c={hasSubAttrError ? "red" : "dimmed"}
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
lineHeight: 1,
|
||||
}}>
|
||||
{renderShortcutKey(operationId)}
|
||||
</Text>
|
||||
</Group>
|
||||
<Box style={{ flex: 1, minWidth: 0 }}>
|
||||
<Text
|
||||
size="sm"
|
||||
fw={500}
|
||||
c={hasSubAttrError ? "red" : undefined}
|
||||
title={operationLabel || undefined}
|
||||
style={{
|
||||
minWidth: 0,
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
}}>
|
||||
{operationLabel}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</Flex>
|
||||
visibleFlag = checkBoxsChecked[3 - type]
|
||||
}
|
||||
if (checkBoxsChecked.every((value) => !value))
|
||||
visibleFlag = true
|
||||
return visibleFlag
|
||||
})
|
||||
return (
|
||||
<Box key={operationId} w="100%">
|
||||
<Paper withBorder p="xs" radius="md" shadow="sm">
|
||||
<Flex align="center" gap="xs" style={{ minWidth: 0 }}>
|
||||
<Flex
|
||||
align="center"
|
||||
gap="xs"
|
||||
style={{ flex: 1, minWidth: 0 }}>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={() => operationHide(operationId, !isHide)}>
|
||||
{!isHide ? <Eye size={16} /> : <EyeOff size={16} />}
|
||||
</ActionIcon>
|
||||
<Group
|
||||
gap={6}
|
||||
gap={8}
|
||||
wrap="nowrap"
|
||||
style={{ flexShrink: 0, marginLeft: "auto" }}>
|
||||
<TextInput
|
||||
w={88}
|
||||
size="xs"
|
||||
placeholder="搜索子属性"
|
||||
value={searchSubAttrs[operationId] || ""}
|
||||
onChange={(e) => {
|
||||
setSearchSubAttrs((searchValues) => ({
|
||||
...searchValues,
|
||||
[operationId]: e.target.value,
|
||||
}))
|
||||
}}
|
||||
onKeyDown={(e) =>
|
||||
handleSelectedBySearchSubAttr(e, operationId)
|
||||
}
|
||||
/>
|
||||
<Badge
|
||||
size="sm"
|
||||
variant="light"
|
||||
radius="xl"
|
||||
color={hasSubAttrError ? "red" : "gray"}>
|
||||
{objectCount}
|
||||
</Badge>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
updateOperationStatus(
|
||||
activeImage + operationId,
|
||||
"COLLAPSE",
|
||||
!isCollapsed
|
||||
)
|
||||
style={{ flex: 1, minWidth: 0 }}>
|
||||
<Group
|
||||
gap={6}
|
||||
wrap="nowrap"
|
||||
px="xs"
|
||||
py={4}
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
borderRadius: 999,
|
||||
border: `1px solid ${
|
||||
hasSubAttrError
|
||||
? "var(--mantine-color-red-2)"
|
||||
: "var(--mantine-color-gray-2)"
|
||||
}`,
|
||||
background: hasSubAttrError
|
||||
? "var(--mantine-color-red-0)"
|
||||
: "var(--mantine-color-gray-0)",
|
||||
}}>
|
||||
{!isCollapsed ? (
|
||||
<ChevronUp size={16} />
|
||||
) : (
|
||||
<ChevronDown size={16} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
{renderOperationIcon(operationSchema)}
|
||||
<Text
|
||||
size="xs"
|
||||
fw={700}
|
||||
c={hasSubAttrError ? "red" : "dimmed"}
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
lineHeight: 1,
|
||||
}}>
|
||||
{renderShortcutKey(operationId)}
|
||||
</Text>
|
||||
</Group>
|
||||
<Box style={{ flex: 1, minWidth: 0 }}>
|
||||
<Text
|
||||
size="sm"
|
||||
fw={500}
|
||||
c={hasSubAttrError ? "red" : undefined}
|
||||
title={operationLabel || undefined}
|
||||
style={{
|
||||
minWidth: 0,
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
}}>
|
||||
{operationLabel}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</Flex>
|
||||
</Paper>
|
||||
<Collapse in={!isCollapsed}>
|
||||
<Stack gap="xs" mt="xs" ml="xs">
|
||||
{visibleChildren.map((child, childIndex) => {
|
||||
const { comment } = child[2]
|
||||
const isSelected = selectedPath[
|
||||
activeImage
|
||||
]?.includes(child[0])
|
||||
const isChildHide =
|
||||
pathStatus[activeImage + child[0]]?.["HIDE"]
|
||||
const hasChildError = getSubAttrStatus(
|
||||
getOperationSchema(operationId),
|
||||
child[2]?.sub_attributes
|
||||
)
|
||||
const isLastVisibleChild =
|
||||
childIndex === visibleChildren.length - 1
|
||||
|
||||
let textColor = undefined
|
||||
let connectorColor = "var(--mantine-color-gray-4)"
|
||||
|
||||
if (hasChildError) {
|
||||
textColor = "red"
|
||||
connectorColor = "var(--mantine-color-red-3)"
|
||||
} else if (isSelected) {
|
||||
textColor = "white"
|
||||
connectorColor =
|
||||
"var(--mantine-primary-color-filled)"
|
||||
<Group
|
||||
gap={6}
|
||||
wrap="nowrap"
|
||||
style={{ flexShrink: 0, marginLeft: "auto" }}>
|
||||
<TextInput
|
||||
w={88}
|
||||
size="xs"
|
||||
placeholder="搜索子属性"
|
||||
value={searchSubAttrs[operationId] || ""}
|
||||
onChange={(e) => {
|
||||
setSearchSubAttrs((searchValues) => ({
|
||||
...searchValues,
|
||||
[operationId]: e.target.value,
|
||||
}))
|
||||
}}
|
||||
onKeyDown={(e) =>
|
||||
handleSelectedBySearchSubAttr(e, operationId)
|
||||
}
|
||||
/>
|
||||
<Badge
|
||||
size="sm"
|
||||
variant="light"
|
||||
radius="xl"
|
||||
color={hasSubAttrError ? "red" : "gray"}>
|
||||
{objectCount}
|
||||
</Badge>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
updateOperationStatus(
|
||||
activeImage + operationId,
|
||||
"COLLAPSE",
|
||||
!isCollapsed
|
||||
)
|
||||
}}>
|
||||
{!isCollapsed ? (
|
||||
<ChevronUp size={16} />
|
||||
) : (
|
||||
<ChevronDown size={16} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
</Flex>
|
||||
</Paper>
|
||||
<Collapse in={!isCollapsed}>
|
||||
<Stack gap="xs" mt="xs" ml="xs">
|
||||
{visibleChildren.map((child, childIndex) => {
|
||||
const { comment } = child[2]
|
||||
const isSelected = selectedPath[
|
||||
activeImage
|
||||
]?.includes(child[0])
|
||||
const isChildHide =
|
||||
pathStatus[activeImage + child[0]]?.["HIDE"]
|
||||
const hasChildError = getSubAttrStatus(
|
||||
getOperationSchema(operationId),
|
||||
child[2]?.sub_attributes
|
||||
)
|
||||
const isLastVisibleChild =
|
||||
childIndex === visibleChildren.length - 1
|
||||
|
||||
return (
|
||||
let textColor = undefined
|
||||
let connectorColor = "var(--mantine-color-gray-4)"
|
||||
|
||||
if (hasChildError) {
|
||||
textColor = "red"
|
||||
connectorColor = "var(--mantine-color-red-3)"
|
||||
} else if (isSelected) {
|
||||
textColor = "white"
|
||||
connectorColor =
|
||||
"var(--mantine-primary-color-filled)"
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={child[0]}
|
||||
pl="lg"
|
||||
style={{ position: "relative" }}>
|
||||
<Box
|
||||
key={child[0]}
|
||||
pl="lg"
|
||||
style={{ position: "relative" }}>
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 7,
|
||||
top: 0,
|
||||
bottom: isLastVisibleChild ? "75%" : 0,
|
||||
width: 1.5,
|
||||
borderRadius: 999,
|
||||
background: connectorColor,
|
||||
opacity: isSelected ? 0.9 : 0.35,
|
||||
}}
|
||||
/>
|
||||
{isLastVisibleChild ? (
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 7,
|
||||
top: 0,
|
||||
bottom: isLastVisibleChild ? "75%" : 0,
|
||||
width: 1.5,
|
||||
borderRadius: 999,
|
||||
background: connectorColor,
|
||||
opacity: isSelected ? 0.9 : 0.35,
|
||||
top: "calc(50% - 10px)",
|
||||
width: 14,
|
||||
height: 10,
|
||||
borderLeft: `1.5px solid ${connectorColor}`,
|
||||
borderBottom: `1.5px solid ${connectorColor}`,
|
||||
borderBottomLeftRadius: 10,
|
||||
opacity: isSelected ? 0.9 : 0.55,
|
||||
}}
|
||||
/>
|
||||
{isLastVisibleChild ? (
|
||||
) : (
|
||||
<>
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 7,
|
||||
top: "calc(50% - 10px)",
|
||||
top: "50%",
|
||||
width: 14,
|
||||
height: 10,
|
||||
borderLeft: `1.5px solid ${connectorColor}`,
|
||||
borderBottom: `1.5px solid ${connectorColor}`,
|
||||
borderBottomLeftRadius: 10,
|
||||
opacity: isSelected ? 0.9 : 0.55,
|
||||
borderTop: `1.5px solid ${connectorColor}`,
|
||||
opacity: isSelected ? 0.9 : 0.45,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 7,
|
||||
top: "50%",
|
||||
width: 14,
|
||||
borderTop: `1.5px solid ${connectorColor}`,
|
||||
opacity: isSelected ? 0.9 : 0.45,
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 4,
|
||||
top: "calc(50% - 3px)",
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: 999,
|
||||
background: connectorColor,
|
||||
boxShadow:
|
||||
"0 0 0 2px var(--mantine-color-body)",
|
||||
opacity: isSelected ? 1 : 0.85,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Paper
|
||||
withBorder
|
||||
p="xs"
|
||||
radius="md"
|
||||
shadow="sm"
|
||||
bg={
|
||||
isSelected
|
||||
? "var(--mantine-primary-color-filled)"
|
||||
: "var(--mantine-color-gray-0)"
|
||||
}
|
||||
c={isSelected ? "white" : undefined}
|
||||
onClick={() =>
|
||||
handleSelect(child[0], operationId)
|
||||
}
|
||||
style={{ cursor: "pointer" }}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Group gap="xs">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
c={isSelected ? "white" : undefined}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
objectHide(
|
||||
operationId,
|
||||
child[0],
|
||||
!isChildHide
|
||||
)
|
||||
}}>
|
||||
{!isChildHide ? (
|
||||
<Eye size={16} />
|
||||
) : (
|
||||
<EyeOff size={16} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<Text size="sm" c={textColor}>
|
||||
{child[0]?.toString()}
|
||||
</Text>
|
||||
<Tooltip
|
||||
label={
|
||||
<Stack gap={0}>
|
||||
<Box
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 4,
|
||||
top: "calc(50% - 3px)",
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: 999,
|
||||
background: connectorColor,
|
||||
boxShadow:
|
||||
"0 0 0 2px var(--mantine-color-body)",
|
||||
opacity: isSelected ? 1 : 0.85,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Paper
|
||||
withBorder
|
||||
p="xs"
|
||||
radius="md"
|
||||
shadow="sm"
|
||||
bg={
|
||||
isSelected
|
||||
? "var(--mantine-primary-color-filled)"
|
||||
: "var(--mantine-color-gray-0)"
|
||||
}
|
||||
c={isSelected ? "white" : undefined}
|
||||
onClick={() =>
|
||||
handleSelect(child[0], operationId)
|
||||
}
|
||||
style={{ cursor: "pointer" }}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Group gap="xs">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
c={isSelected ? "white" : undefined}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
objectHide(
|
||||
operationId,
|
||||
child[0],
|
||||
!isChildHide
|
||||
)
|
||||
}}>
|
||||
{!isChildHide ? (
|
||||
<Eye size={16} />
|
||||
) : (
|
||||
<EyeOff size={16} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<Text size="sm" c={textColor}>
|
||||
{child[0]?.toString()}
|
||||
</Text>
|
||||
<Tooltip
|
||||
label={
|
||||
<Stack gap={0}>
|
||||
<Group gap={4}>
|
||||
<Text size="xs">创建:</Text>
|
||||
<Text size="xs">
|
||||
{
|
||||
userOpts.find(
|
||||
(item) =>
|
||||
item.value === child[2]?.uid
|
||||
)?.label
|
||||
}
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{dayjs(
|
||||
(child[2]?.create_timestamp ||
|
||||
0) * 1000
|
||||
).format("YYYY-MM-DD HH:mm:ss")}
|
||||
</Text>
|
||||
</Group>
|
||||
{child[2]?.first_modified_uid && (
|
||||
<Group gap={4}>
|
||||
<Text size="xs">创建:</Text>
|
||||
<Text size="xs">首次修改:</Text>
|
||||
<Text size="xs">
|
||||
{
|
||||
userOpts.find(
|
||||
(item) =>
|
||||
item.value ===
|
||||
child[2]?.uid
|
||||
child[2]
|
||||
?.first_modified_uid
|
||||
)?.label
|
||||
}
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{dayjs(
|
||||
(child[2]?.create_timestamp ||
|
||||
(child[2]
|
||||
?.first_modified_timestamp ||
|
||||
0) * 1000
|
||||
).format("YYYY-MM-DD HH:mm:ss")}
|
||||
</Text>
|
||||
</Group>
|
||||
{child[2]?.first_modified_uid && (
|
||||
<Group gap={4}>
|
||||
<Text size="xs">
|
||||
首次修改:
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{
|
||||
userOpts.find(
|
||||
(item) =>
|
||||
item.value ===
|
||||
child[2]
|
||||
?.first_modified_uid
|
||||
)?.label
|
||||
}
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{dayjs(
|
||||
(child[2]
|
||||
?.first_modified_timestamp ||
|
||||
0) * 1000
|
||||
).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
)}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
{child[2]?.last_modified_uid && (
|
||||
<Group gap={4}>
|
||||
<Text size="xs">
|
||||
最新修改:
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{
|
||||
userOpts.find(
|
||||
(item) =>
|
||||
item.value ===
|
||||
child[2]
|
||||
?.last_modified_uid
|
||||
)?.label
|
||||
}
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{dayjs(
|
||||
(child[2]
|
||||
?.last_modified_timestamp ||
|
||||
0) * 1000
|
||||
).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
)}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
multiline
|
||||
bg="white"
|
||||
c="black"
|
||||
withArrow>
|
||||
<Info
|
||||
size={16}
|
||||
style={{ cursor: "pointer" }}
|
||||
color={isSelected ? "white" : "black"}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
{child[2]?.last_modified_uid && (
|
||||
<Group gap={4}>
|
||||
<Text size="xs">最新修改:</Text>
|
||||
<Text size="xs">
|
||||
{
|
||||
userOpts.find(
|
||||
(item) =>
|
||||
item.value ===
|
||||
child[2]
|
||||
?.last_modified_uid
|
||||
)?.label
|
||||
}
|
||||
</Text>
|
||||
<Text size="xs">
|
||||
{dayjs(
|
||||
(child[2]
|
||||
?.last_modified_timestamp ||
|
||||
0) * 1000
|
||||
).format("YYYY-MM-DD HH:mm:ss")}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
multiline
|
||||
bg="white"
|
||||
c="black"
|
||||
withArrow>
|
||||
<Info
|
||||
size={16}
|
||||
style={{ cursor: "pointer" }}
|
||||
color={isSelected ? "white" : "black"}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
{comment ? (
|
||||
<Group gap={4}>
|
||||
{comment.map((c: any) => {
|
||||
const count =
|
||||
c.check_box_comments.length +
|
||||
c.text_comments.length
|
||||
const { last_modified_timestamp } =
|
||||
child[2]
|
||||
let flag = false
|
||||
if (
|
||||
count > 0 &&
|
||||
last_modified_timestamp &&
|
||||
last_modified_timestamp > c.date
|
||||
)
|
||||
flag = true
|
||||
|
||||
let badgeColor = "gray"
|
||||
if (c.comment_type === 1)
|
||||
badgeColor = "green"
|
||||
if (c.comment_type === 2)
|
||||
badgeColor = "red"
|
||||
if (flag) badgeColor = "yellow"
|
||||
|
||||
return (
|
||||
<Popover
|
||||
key={`${child[0]}${c.turn}${c.times}`}
|
||||
position="left"
|
||||
withArrow>
|
||||
<Popover.Target>
|
||||
<Badge
|
||||
size="xs"
|
||||
circle
|
||||
color={badgeColor}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
{count}
|
||||
</Badge>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<Text size="xs" c={badgeColor}>
|
||||
{`P${child[2].image_id}:${
|
||||
child[2].uid
|
||||
}:${c.check_box_comments.join(
|
||||
","
|
||||
)},${c.text_comments.join(
|
||||
","
|
||||
)} ${
|
||||
c.date
|
||||
? dayjs(
|
||||
c.date * 1000
|
||||
).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
)
|
||||
: ""
|
||||
}`}
|
||||
</Text>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
)
|
||||
})}
|
||||
</Group>
|
||||
{comment ? (
|
||||
<Group gap={4}>
|
||||
{comment.map((c: any) => {
|
||||
const count =
|
||||
c.check_box_comments.length +
|
||||
c.text_comments.length
|
||||
const { last_modified_timestamp } =
|
||||
child[2]
|
||||
let flag = false
|
||||
if (
|
||||
count > 0 &&
|
||||
last_modified_timestamp &&
|
||||
last_modified_timestamp > c.date
|
||||
)
|
||||
flag = true
|
||||
|
||||
let badgeColor = "gray"
|
||||
if (c.comment_type === 1)
|
||||
badgeColor = "green"
|
||||
if (c.comment_type === 2)
|
||||
badgeColor = "red"
|
||||
if (flag) badgeColor = "yellow"
|
||||
|
||||
return (
|
||||
<Popover
|
||||
key={`${child[0]}${c.turn}${c.times}`}
|
||||
position="left"
|
||||
withArrow>
|
||||
<Popover.Target>
|
||||
<Badge
|
||||
size="xs"
|
||||
circle
|
||||
color={badgeColor}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
{count}
|
||||
</Badge>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<Text size="xs" c={badgeColor}>
|
||||
{`P${child[2].image_id}:${
|
||||
child[2].uid
|
||||
}:${c.check_box_comments.join(
|
||||
","
|
||||
)},${c.text_comments.join(
|
||||
","
|
||||
)} ${
|
||||
c.date
|
||||
? dayjs(
|
||||
c.date * 1000
|
||||
).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
)
|
||||
: ""
|
||||
}`}
|
||||
</Text>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
)
|
||||
})}
|
||||
</Group>
|
||||
) : null}
|
||||
</Flex>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
</Collapse>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
) : null}
|
||||
</Flex>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
</Collapse>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
</ScrollArea>
|
||||
</Collapse>
|
||||
|
||||
Reference in New Issue
Block a user