130 lines
2.9 KiB
TypeScript
130 lines
2.9 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 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
|
|
}
|