我有一个可以拖放的项目列表,它工作正常。但是,我在跨索引拖放分组元素时遇到问题。该数组与我提供的代码中显示的一样,我无法更改其结构。
我想要实现的是能够拖放任务和组,当我将一个组拖放到一个任务或另一个组中时,该组应该成为该任务或组的子项。
如果您需要更多信息,请告诉我。阵列如图所示,别无他法。
export default function App() {
const dragRef = useRef<number>(-1);
const [items, setItems] = useState([
{ schema: "task", title: "Tarea A", level: 0, position: "1" },
{ schema: "task", title: "Tarea B", level: 0, position: "2" },
{ schema: "group", title: "Grupo 0", level: 0, position: "3" },
{ schema: "group", title: "Grupo 1", level: 0, position: "4" },
{ schema: "task", title: "Tarea 1", level: 1, position: "4.1" },
{ schema: "task", title: "Tarea 2", level: 1, position: "4.2" },
{ schema: "group", title: "Sub group 1", level: 1, position: "4.3" },
{ schema: "task", title: "Tarea sub 1", level: 2, position: "4.3.1" },
{ schema: "task", title: "Tarea sub 2", level: 2, position: "4.3.2" },
{ schema: "task", title: "Tarea C", level: 0, position: "5" }
]);
这是逻辑:
const handleDragStart = (e: React.DragEvent, i: number) => {
dragRef.current = i;
};
const getTargetIndex = (sourceLevel: number, indexTarget: number) => {
let index = indexTarget;
let target = items[index];
while (target.level > sourceLevel) {
index -= 1;
target = items[index];
}
return index;
};
const getLastChildIndex = (targetIndex: number) => {
let childIndex = targetIndex + 1;
return childIndex;
};
const handleReSort = (indexTarget: number, indexSource: number) => {
const source = items[indexSource];
let targetIndex = getTargetIndex(source.level, indexTarget);
const target = items[targetIndex];
const isSameLevel = target.level === source.level;
const isAnyAGroup = target.schema === "group" || source.schema === "group";
const _items = [...items];
if (isSameLevel && !isAnyAGroup) {
_items.splice(indexSource, 1);
_items.splice(targetIndex, 0, source);
setItems(_items);
return;
}
if (isSameLevel && isAnyAGroup) {
const targetIsGroup = target.schema === "group" || source.schema === "group";
const targetIsLast = targetIndex + 1 === items.length;
const targetIsEmpty =
!targetIsGroup || targetIsLast ? true : items[targetIndex + 1].level === target.level;
const sourceIsGroup = source.schema === "group";
const sourceIsLast = indexSource + 1 === items.length;
const sourceIsEmpty =
!sourceIsGroup || sourceIsLast ? true : items[indexSource + 1].level === source.level;
// Remove the source element from _items list
_items.splice(indexSource, 1);
// Insert the source element into its new position
if (targetIsEmpty && sourceIsEmpty) {
// If both target and source elements are empty, insert the source element at the target index
_items.splice(indexTarget, 0, source);
setItems(_items);
} else {
if (!sourceIsEmpty && !targetIsEmpty) {
// If both target and source elements have children
} else if (!targetIsEmpty) {
targetIndex = getLastChildIndex(targetIndex);
_items.splice(targetIndex, 0, source);
setItems(_items);
} else {
// If only the source element has children
}
}
}
};
const handleDrop = (e: React.DragEvent, indexTarget: number) => {
e.preventDefault();
if (!dragRef || dragRef.current === -1) return;
const indexSource = dragRef.current;
handleReSort(indexTarget, indexSource);
};
return (
<div className="App">
<ul>
{items.map((item: any, i: number) => (
<li
draggable
className={`item-level-${item.level} schema-${item.schema}`}
onDragStart={(e: React.DragEvent) => handleDragStart(e, i)}
onDrop={(e: React.DragEvent) => handleDrop(e, i)}
onDragOver={(e) => e.preventDefault()}
>
{item.title}
</li>
))}
</ul>
</div>
);