Files
labelimage/components/label/util.ts
2026-04-15 19:03:27 +08:00

169 lines
4.0 KiB
TypeScript

import { Project } from "./api/project/typing"
const nonEditableInputTypes = new Set([
"button",
"checkbox",
"color",
"file",
"hidden",
"image",
"radio",
"range",
"reset",
"submit",
])
const editableRoles = new Set([
"textbox",
"searchbox",
"combobox",
"spinbutton",
])
const resolveTargetElement = (target: EventTarget | null) => {
if (target instanceof Element) return target
if (target instanceof Node) return target.parentElement
return null
}
export const isEditableKeyboardTarget = (target: EventTarget | null) => {
const element = resolveTargetElement(target)
if (!element) return false
const editableElement = element.closest(
[
"input",
"textarea",
"select",
"[contenteditable='']",
"[contenteditable='true']",
"[role='textbox']",
"[role='searchbox']",
"[role='combobox']",
"[role='spinbutton']",
].join(",")
)
if (!editableElement) return false
if (editableElement instanceof HTMLInputElement) {
return !nonEditableInputTypes.has(editableElement.type.toLowerCase())
}
if (
editableElement instanceof HTMLTextAreaElement ||
editableElement instanceof HTMLSelectElement
) {
return true
}
if (editableElement instanceof HTMLElement) {
if (editableElement.isContentEditable) return true
const role = editableElement.getAttribute("role")
return role ? editableRoles.has(role) : false
}
return false
}
// 是否存在不符合要求的子属性
export const getSubAttrStatus = (
operationSchema: Project.LabelSchemaList | null,
detail: {
[key: string]: string
}
) => {
if (!operationSchema?.sub_attributes_describe?.length) return false
let bool = operationSchema?.sub_attributes_describe?.some((item) => {
if (item.isrequired === 1) {
if (!detail || !detail?.[item.chinese_name]) {
return true
} else {
return false
}
}
})
return bool
}
export const buildSubAttributeFormValues = (
operationSchema: Project.LabelSchemaList | null,
detail: Record<string, any> = {}
) => {
const nextValues: Record<string, string | string[]> = {}
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,
b: any[] | null,
c: any[] | null,
d: any[] | null
) => boolean = (
detailCheckboxComments,
detailTextComments,
checkboxComments,
textComments
) => {
if (detailCheckboxComments?.length !== checkboxComments?.length) {
return false
}
if (detailTextComments?.length !== textComments?.length) {
return false
}
const areCheckboxCommentsSame =
detailCheckboxComments?.every((comment, index) => {
return comment === checkboxComments?.[index]
}) ?? true
const areTextCommentsSame =
detailTextComments?.every((comment, index) => {
return comment === textComments?.[index]
}) ?? true
return areCheckboxCommentsSame && areTextCommentsSame
}
// find group key
export const findGroupKey: (
group: { [x: number]: number[] },
id: number
) => number = (group, id) => {
for (const key in group) {
if (group[key].includes(id)) {
return Number(key)
}
}
return -1
}