/** * SortableTimelineGridItem - 可排序的时间线网格项组件 * * 功能描述: * 该组件包装 TimelineGridItem,为其添加拖拽排序能力。 * 使用 dnd-kit 的 useSortable Hook 实现拖拽功能。 * * 设计思路: * 1. 使用 useSortable Hook 获取拖拽属性 * 2. 通过 CSS transform 实现拖拽动画 * 3. 拖拽时显示占位符和视觉反馈 * 4. 支持禁用拖拽(移动端默认禁用) * * @author Timeline Team * @date 2024 */ import { StoryItem } from '@/pages/story/data'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { DragOutlined } from '@ant-design/icons'; import React, { memo, CSSProperties } from 'react'; import TimelineGridItem from './TimelineGridItem'; /** * 组件属性接口 * @property item - 时间线节点数据 * @property disabled - 是否禁用拖拽 * @property handleOption - 操作回调 * @property onOpenDetail - 打开详情回调 * @property refresh - 刷新数据回调 * @property disableEdit - 是否禁用编辑 */ interface SortableTimelineGridItemProps { item: StoryItem; disabled?: boolean; handleOption: (item: StoryItem, option: 'add' | 'edit' | 'addSubItem' | 'editSubItem') => void; onOpenDetail: (item: StoryItem) => void; refresh: () => void; disableEdit?: boolean; } /** * SortableTimelineGridItem 组件 * 为时间线节点添加拖拽排序能力 */ const SortableTimelineGridItem: React.FC = memo(({ item, disabled = false, handleOption, onOpenDetail, refresh, disableEdit = false, }) => { /** * useSortable Hook 核心功能: * - attributes: 可访问性属性(如 tabindex) * - listeners: 拖拽事件监听器 * - setNodeRef: 设置 DOM 节点引用 * - transform: CSS transform 值 * - transition: CSS transition 值 * - isDragging: 是否正在拖拽 */ const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: item.instanceId, disabled: disabled, data: { type: 'timeline-item', item, }, }); /** * 构建拖拽样式 * - transform: 应用拖拽位移和缩放 * - transition: 平滑过渡动画 * - opacity: 拖拽时降低透明度 * - zIndex: 拖拽时提升层级 */ const style: CSSProperties = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1, zIndex: isDragging ? 1000 : 'auto', position: 'relative' as const, }; return (
{/* 拖拽手柄 - 仅在非禁用状态显示 */} {!disabled && !disableEdit && (
e.stopPropagation()} >
)} {/* 原有组件 */} {/* 拖拽时的视觉反馈 */} {isDragging && (
)}
); }); SortableTimelineGridItem.displayName = 'SortableTimelineGridItem'; export default SortableTimelineGridItem;