/** * 编辑点交互组件 * 实现脉冲动画效果和点击交互 */ import React, { useCallback, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Edit3, Check, X, Loader2 } from 'lucide-react'; import { EditPoint as EditPointType, EditPointStatus } from './types'; interface EditPointProps { /** 编辑点数据 */ editPoint: EditPointType; /** 是否被选中 */ isSelected: boolean; /** 容器尺寸 */ containerSize: { width: number; height: number }; /** 点击事件处理 */ onClick: (editPoint: EditPointType) => void; /** 删除事件处理 */ onDelete: (id: string) => void; /** 编辑事件处理 */ onEdit: (id: string) => void; /** 样式配置 */ style?: { size?: number; color?: string; pulseColor?: string; }; } /** * 编辑点组件 */ export const EditPoint: React.FC = ({ editPoint, isSelected, containerSize, onClick, onDelete, onEdit, style = {} }) => { const { size = 12, color = '#3b82f6', pulseColor = 'rgba(59, 130, 246, 0.3)' } = style; // 计算绝对位置 const absolutePosition = useMemo(() => ({ x: (editPoint.position.x / 100) * containerSize.width, y: (editPoint.position.y / 100) * containerSize.height }), [editPoint.position, containerSize]); // 处理点击事件 const handleClick = useCallback((e: React.MouseEvent) => { e.stopPropagation(); onClick(editPoint); }, [onClick, editPoint]); // 处理删除事件 const handleDelete = useCallback((e: React.MouseEvent) => { e.stopPropagation(); onDelete(editPoint.id); }, [onDelete, editPoint.id]); // 处理编辑事件 const handleEdit = useCallback((e: React.MouseEvent) => { e.stopPropagation(); onEdit(editPoint.id); }, [onEdit, editPoint.id]); // 根据状态获取颜色 const getStatusColor = useCallback(() => { switch (editPoint.status) { case EditPointStatus.PENDING: return '#f59e0b'; // 黄色 case EditPointStatus.EDITED: return '#10b981'; // 绿色 case EditPointStatus.PROCESSING: return '#3b82f6'; // 蓝色 case EditPointStatus.COMPLETED: return '#059669'; // 深绿色 case EditPointStatus.FAILED: return '#ef4444'; // 红色 default: return color; } }, [editPoint.status, color]); // 根据状态获取图标 const getStatusIcon = useCallback(() => { switch (editPoint.status) { case EditPointStatus.PENDING: return Edit3; case EditPointStatus.EDITED: return Check; case EditPointStatus.PROCESSING: return Loader2; case EditPointStatus.COMPLETED: return Check; case EditPointStatus.FAILED: return X; default: return Edit3; } }, [editPoint.status]); const StatusIcon = getStatusIcon(); const statusColor = getStatusColor(); return ( {/* 脉冲动画背景 */} {(editPoint.status === EditPointStatus.PENDING || isSelected) && ( )} {/* 主编辑点 */} {/* 选中状态的操作按钮 */} {isSelected && editPoint.status !== EditPointStatus.PROCESSING && ( {/* 编辑按钮 */} {/* 删除按钮 */} )} {/* 状态提示文本 */} {isSelected && editPoint.description && ( {editPoint.description.length > 50 ? `${editPoint.description.substring(0, 50)}...` : editPoint.description } )} {/* 时间戳显示 */} {isSelected && ( {Math.floor(editPoint.timestamp)}s )} ); };