import { CompressOutlined, DeleteOutlined, ExpandOutlined, EyeOutlined, PrinterOutlined, ZoomInOutlined, ZoomOutOutlined, } from '@ant-design/icons'; import { Button, Card, Empty, message, Popconfirm, Slider } from 'antd'; import React, { useEffect, useRef, useState } from 'react'; import { DragDropContext, Draggable, Droppable, DropResult, } from 'react-beautiful-dnd'; // 直接导入组件而不是使用 React.lazy import DealerInfoModule from './DealerInfoModule'; import OtherFeesModule from './OtherFeesModule'; import OtherInfoModule from './OtherInfoModule'; import PackingSpecModule from './PackingSpecModule'; import ShippingInfoModule from './ShippingInfoModule'; import TitleModule from './TitleModule'; import TotalAmountModule from './TotalAmountModule'; import VehicleInfoModule from './VehicleInfoModule'; import WeightInfoModule from './WeightInfoModule'; interface PreviewCanvasProps { modules: any[]; selectedModule: any; onModuleSelect: (module: any) => void; onModuleDelete: (moduleId: string) => void; onModuleReorder: (newModules: any[]) => void; onClearAll?: () => void; // 添加清空所有模块的回调函数 } const PreviewCanvas: React.FC = ({ modules, selectedModule, onModuleSelect, onModuleDelete, onModuleReorder, onClearAll, // 接收清空所有模块的回调函数 }) => { const [isPreviewMode, setIsPreviewMode] = useState(false); const [scale, setScale] = useState(1); const [position, setPosition] = useState({ x: 0, y: 0 }); const [isDragging, setIsDragging] = useState(false); const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); const [isFullscreen, setIsFullscreen] = useState(false); const canvasRef = useRef(null); const containerRef = useRef(null); const fullscreenElementRef = useRef(null); const handleDragEnd = (result: DropResult) => { // 如果没有拖拽到有效位置,则直接返回 if (!result.destination) { return; } const items = Array.from(modules); const [reorderedItem] = items.splice(result.source.index, 1); items.splice(result.destination.index, 0, reorderedItem); onModuleReorder(items); }; // 全屏功能 const toggleFullscreen = () => { if (!fullscreenElementRef.current) return; if (!isFullscreen) { // 进入全屏 const element = fullscreenElementRef.current; if (element.requestFullscreen) { element.requestFullscreen(); } else if ((element as any).mozRequestFullScreen) { // Firefox (element as any).mozRequestFullScreen(); } else if ((element as any).webkitRequestFullscreen) { // Chrome, Safari and Opera (element as any).webkitRequestFullscreen(); } else if ((element as any).msRequestFullscreen) { // IE/Edge (element as any).msRequestFullscreen(); } setIsFullscreen(true); } else { // 退出全屏 if (document.exitFullscreen) { document.exitFullscreen(); } else if ((document as any).mozCancelFullScreen) { // Firefox (document as any).mozCancelFullScreen(); } else if ((document as any).webkitExitFullscreen) { // Chrome, Safari and Opera (document as any).webkitExitFullscreen(); } else if ((document as any).msExitFullscreen) { // IE/Edge (document as any).msExitFullscreen(); } setIsFullscreen(false); } }; // 监听全屏状态变化 useEffect(() => { const handleFullscreenChange = () => { const isCurrentlyFullscreen = document.fullscreenElement || (document as any).webkitFullscreenElement || (document as any).mozFullScreenElement || (document as any).msFullscreenElement; setIsFullscreen(!!isCurrentlyFullscreen); }; document.addEventListener('fullscreenchange', handleFullscreenChange); document.addEventListener('webkitfullscreenchange', handleFullscreenChange); document.addEventListener('mozfullscreenchange', handleFullscreenChange); document.addEventListener('MSFullscreenChange', handleFullscreenChange); return () => { document.removeEventListener('fullscreenchange', handleFullscreenChange); document.removeEventListener( 'webkitfullscreenchange', handleFullscreenChange, ); document.removeEventListener( 'mozfullscreenchange', handleFullscreenChange, ); document.removeEventListener( 'MSFullscreenChange', handleFullscreenChange, ); }; }, []); // 打印预览功能 const handlePrint = () => { // 获取要打印的内容 const printContentElement = document.getElementById('preview-canvas'); if (!printContentElement) { message.error('未能找到打印内容'); return; } // 创建一个用于打印的隐藏iframe const printWindow = window.open('', '_blank'); if (printWindow) { // 获取预览区域的HTML内容 const contentHTML = printContentElement.innerHTML; // 构建打印内容 let printContent = ` 发货单打印预览
${contentHTML}
`; // 写入内容到打印窗口 printWindow.document.write(printContent); printWindow.document.close(); } else { message.error('无法打开打印预览窗口,请检查浏览器设置'); } }; // 缩放功能 const handleZoomIn = () => { setScale((prev) => Math.min(prev + 0.1, 3)); }; const handleZoomOut = () => { setScale((prev) => Math.max(prev - 0.1, 0.5)); }; const handleResetZoom = () => { setScale(1); setPosition({ x: 0, y: 0 }); }; const handleSliderChange = (value: number) => { setScale(value / 100); }; // 鼠标滚轮缩放 const handleWheel = (e: React.WheelEvent) => { if (!isPreviewMode) return; e.preventDefault(); const delta = e.deltaY > 0 ? -0.1 : 0.1; setScale((prev) => Math.min(Math.max(prev + delta, 0.5), 3)); }; // 拖动功能 const handleMouseDown = (e: React.MouseEvent) => { if (!isPreviewMode) return; setIsDragging(true); setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y, }); }; const handleMouseMove = (e: React.MouseEvent) => { if (!isPreviewMode || !isDragging) return; setPosition({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y, }); }; const handleMouseUp = () => { setIsDragging(false); }; // 点击预览区域外取消选中 const handleContainerClick = (e: React.MouseEvent) => { if (e.target === containerRef.current) { onModuleSelect(null); } }; // 清理拖动状态 useEffect(() => { if (!isPreviewMode) { setIsDragging(false); } }, [isPreviewMode]); const renderModule = (module: any, index: number) => { const props = { config: module.config, isSelected: selectedModule?.id === module.id, onSelect: () => onModuleSelect(module), onDelete: () => onModuleDelete(module.id), onMoveUp: () => { if (index > 0) { const newModules = [...modules]; const temp = newModules[index]; newModules[index] = newModules[index - 1]; newModules[index - 1] = temp; onModuleReorder(newModules); } }, onMoveDown: () => { if (index < modules.length - 1) { const newModules = [...modules]; const temp = newModules[index]; newModules[index] = newModules[index + 1]; newModules[index + 1] = temp; onModuleReorder(newModules); } }, canMoveUp: index > 0, canMoveDown: index < modules.length - 1, }; // 创建组件映射对象 const componentMap = { title: TitleModule, dealerInfo: DealerInfoModule, shippingInfo: ShippingInfoModule, weightInfo: WeightInfoModule, packingSpec: PackingSpecModule, vehicleInfo: VehicleInfoModule, otherFees: OtherFeesModule, totalAmount: TotalAmountModule, otherInfo: OtherInfoModule, }; const Component = componentMap[module.type as keyof typeof componentMap]; if (isPreviewMode) { return Component ? ( ) : null; } return ( {(provided, snapshot) => (
{Component ? ( ) : null}
)}
); }; // 为 Droppable 组件创建一个不使用 memo 的包装组件 const DroppableWrapper = ({ children }: { children: React.ReactNode }) => ( {(provided, snapshot) => (
{children} {provided.placeholder}
)}
); return ( 0 ? (
{onClearAll && ( )} {isPreviewMode && ( <> )} {isPreviewMode && ( )}
) : null } bodyStyle={{ maxHeight: 'calc(100vh - 200px)', overflowY: 'auto', margin: '0 auto', position: 'relative', cursor: isPreviewMode ? (isDragging ? 'grabbing' : 'grab') : 'default', }} >
{isPreviewMode ? ( <>
缩放: {Math.round(scale * 100)}%
{modules.map((module, index) => renderModule(module, index))}
) : (
{modules.length === 0 ? (
) : ( {modules.map((module, index) => renderModule(module, index))} )}
)}
); }; export default PreviewCanvas;