import type { DragEndEvent } from '@dnd-kit/core'; import { DndContext } from '@dnd-kit/core'; import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import type { FC } from 'react'; import React from 'react'; interface Props { columns: AntDesign.TableColumnCheck[]; setColumnChecks: (checks: AntDesign.TableColumnCheck[]) => void; } /** 单个可拖拽项组件 */ const SortableItem: FC<{ index: number; item: AntDesign.TableColumnCheck; onCheckChange: (oldValue: boolean, index: number) => void; }> = ({ index, item, onCheckChange }) => { // 使用 useSortable 获取拖拽属性 const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: item.key // 每个可拖拽对象的唯一标识 }); // inline 样式,用于在拖拽时移动/过渡 const style: React.CSSProperties = { transform: CSS.Transform.toString(transform), transition }; return (
onCheckChange(item.checked, index)} > {item.title}
); }; /** 列表容器组件 */ const DragContent: FC = ({ columns, setColumnChecks }) => { // 拖拽结束时的回调 const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event; if (!over) return; // 如果拖拽开始和结束位置的 id 不同,则表示有重新排序 if (active.id !== over.id) { const oldIndex = columns.findIndex(item => item.key === active.id); const newIndex = columns.findIndex(item => item.key === over.id); // arrayMove 是 DnD Kit 提供的辅助函数,用于在数组中移动元素 const newColumns = arrayMove(columns, oldIndex, newIndex); setColumnChecks(newColumns); } }; // 点击复选框时更改“checked” const handleChange = (value: boolean, index: number) => { columns[index].checked = !value; // 这里要注意保持新数组引用,确保触发 React 重新渲染 setColumnChecks([...columns]); }; return ( // DndContext 相当于顶层的拖拽环境容器 {/* SortableContext 用于告诉 DnD Kit,这个区域内的一组元素可以“排序”; items 传入当前这批可排序对象的 key(或整个对象,但 key 必须唯一); strategy 指定排序策略,如 verticalListSortingStrategy 适合竖直列表。 */} item.key)} strategy={verticalListSortingStrategy} > {columns.map((item, index) => ( ))} ); }; export default DragContent;