/* eslint-disable */ import React, { useRef, useState, useEffect } from "react"; import style from "./index.less"; import { createEnvelope, createAirplaneBox, createDeductionBox, createTote, createBoxs, createHeavenBox, createDiscBox, createShowBox, createLiningBox, } from "./createAirplaneBox"; const DynamicSVG = props => { const svgRef = useRef(null); const svgContainerRef = useRef(null); const [boxKey, setBoxKey] = useState(new Date().getTime()); const [currentTranslateX, setCurrentTranslateX] = useState(0); const [currentTranslateY, setCurrentTranslateY] = useState(0); const [currentScale, setCurrentScale] = useState(1); const [positionInfo, setPositionInfo] = useState({ x: 0, y: 0, width: 0, height: 0 }); // 先默认为抵扣盒 const { boxModel } = props; //盒型参数 const { masterData, slaveData, selectedNode } = props.state; // 主数据 const slaveDataDetail = slaveData?.find(item => item.sTreeNodeName === selectedNode.showName && item.sBoxModel === boxModel); const width = Number(masterData?.dLength); const height = Number(masterData?.dHeight); const deep = Number(masterData?.dWidth); // 确认是竖向排列还是横向排列 const L = masterData?.dLength; const W = masterData?.dWidth; const H = masterData?.dHeight; const D = masterData?.dHeight; const variables = { L, W, H, D, ...slaveDataDetail, }; useEffect( () => { const svg = svgRef.current; svg.innerHTML = ""; initSVG(); // 处理 if (slaveDataDetail?.sName.includes("扣抵盒")) { const c = slaveDataDetail?.dc; const g = slaveDataDetail?.dg; const a = slaveDataDetail?.da; createBox(width, height, deep, c, g, a); } else if (slaveDataDetail?.sName.includes("飞机盒")) { const list = createAirplaneBox(variables); if (list && list.length) { const leftWidth = (evaluateFormula(slaveDataDetail.sLengthFormula, variables) + slaveDataDetail.dTd * 2 - L) / 2; initBox(list, leftWidth + 9, slaveDataDetail.dD3, slaveDataDetail.dTd * 2, 0); } } else if (slaveDataDetail?.sName.includes("自动扣底盒")) { const top = slaveDataDetail.dc + W; const list = createDeductionBox(variables); if (list && list.length) { initBox(list, 0, top, 0, 0); } } else if (slaveDataDetail?.sName.includes("手提袋")) { const list = createTote(variables); if (list && list.length) { initBox(list, slaveDataDetail.dF, slaveDataDetail.dF1, 0, 0); } } else if (slaveDataDetail?.sName.includes("普通盒(纸箱)")) { const list = createBoxs(variables); if (list && list.length) { initBox(list, slaveDataDetail.dG, slaveDataDetail.dF, 0, 0); } } else if (slaveDataDetail?.sName.includes("天地盖")) { const list = createHeavenBox(variables); if (list && list.length) { initBox(list, D, slaveDataDetail.dF1 + 2, 4, 4); } } else if (slaveDataDetail?.sName.includes("盘式盒")) { const list = createDiscBox(variables); if (list && list.length) { const left = slaveDataDetail?.dTd + slaveDataDetail?.dD1 + slaveDataDetail?.dDj + D + 2; initBox(list, left, 0, 4, 0); } } else if (slaveDataDetail?.sName.includes("展示盒")) { const list = createShowBox(variables); if (list && list.length) { initBox(list, 0, slaveDataDetail?.dD2, 0, 0); } } else if (slaveDataDetail?.sName.includes("内衬")) { const list = createLiningBox(variables); if (list && list.length) { initBox(list, 0, 0, 0, 0); } } else if (slaveDataDetail?.sName.includes("信封")) { const list = createEnvelope(variables); if (list && list.length) { initBox(list, slaveDataDetail?.dS1, slaveDataDetail?.dF1, 0, 0); } } }, [slaveDataDetail] ); // 动态计算公式值 const evaluateFormula = (formula, variables) => { if (!formula) return 0; // 如果公式为空,返回0 try { // 提取公式中的变量名 const variableNames = formula.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g) || []; // 构建函数参数 const params = variableNames.join(","); // 替换公式中的变量为实际值 const func = new Function(params, `return ${formula}`); // 提取变量值 const args = variableNames.map(name => Number(variables[name]) || 0); // 执行函数并返回结果 return func(...args); } catch (error) { console.error("公式计算错误:", error); return 0; } }; // 盒身 const createPathElement = (x, y, width, height, id, wrapperId) => { const d = `M ${x} ${y} L ${x} ${y + height} L ${x + width} ${y + height} L ${x + width} ${y} L ${x} ${y} Z`; const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); svg.setAttribute("stroke-dasharray", "3.8"); // 添加虚线效果 return svg; }; // 左上部件 const createDynamicTop = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); // 动态生成路径,基于输入参数 const d = `M ${offsetX} ${offsetY} L ${offsetX} ${offsetY - deep - size + 2} A 2 2 0 0 1 ${offsetX + 2} ${offsetY - deep - size} L ${offsetX + width - 2} ${offsetY - deep - size} A 2 2 0 0 1 ${offsetX + width} ${offsetY - deep - size + 2} L ${offsetX + width} ${offsetY - deep} L ${offsetX} ${offsetY - deep} L ${offsetX + width} ${offsetY - deep} L ${offsetX + width} ${offsetY} `; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 左边贴边 const createTrapezoid = (width, height, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); const d = `M ${offsetX} ${offsetY} L ${offsetX - size} ${offsetY + 2} L ${offsetX - size} ${offsetY + height - 2} L ${offsetX} ${offsetY + height}`; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 左上盒舌 const createTopTongue = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); const d = `M ${offsetX + width} ${offsetY} L ${offsetX + width + 2} ${offsetY - 2} L ${offsetX + width + 2} ${offsetY - size - 2} L ${offsetX + width + deep - 5} ${offsetY - size - 2} A 2 2 0 0 1 ${offsetX + width + deep - 3} ${offsetY - size} L ${offsetX + width + deep} ${offsetY}`; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 右上盒舌 const createTopTongueRight = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); // "M 130 0 L 133 87 A 2 2 0 0 1 135 85 L 158 85 L 158 98 L 160 0 Z" const d = `M ${offsetX} ${offsetY} L ${offsetX + 3} ${offsetY - size + 2} A 2 2 0 0 1 ${offsetX + 5} ${offsetY - size} L ${offsetX + deep - 2} ${offsetY - size} L ${offsetX + deep - 2} ${offsetY - 2} L ${offsetX + deep} ${offsetY} `; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 右下盒舌 const createBottomTongueRight = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); // M 130 160 L 132 162 L 132 175 L 156 175 A 2 2 0 0 0 158 173 L 160 160 Z const d = `M ${offsetX} ${offsetY + height} L ${offsetX + 2} ${offsetY + height + 2} L ${offsetX + 2} ${offsetY + height + size} L ${offsetX + deep - 4} ${offsetY + height + size} A 2 2 0 0 0 ${offsetX + deep - 2} ${offsetY + height + size - 2} L ${offsetX + deep} ${offsetY + height} `; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 右下部件 const createBottom = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); // "M 90 160 L 90 198 A 2 2 0 0 0 92 200 L 128 200 A 2 2 0 0 0 130 198 L 130 197 L 90 197 L 130 197 L 130 160 Z " const d = `M ${offsetX} ${offsetY + height} L ${offsetX} ${offsetY + height + deep + size - 2} A 2 2 0 0 0 ${offsetX + 2} ${offsetY + height + deep + size} L ${offsetX + width - 2} ${offsetY + height + deep + size} A 2 2 0 0 0 ${offsetX + width} ${offsetY + height + deep + size - 2} L ${offsetX + width} ${offsetY + height + deep} L${offsetX} ${offsetY + height + deep} L${offsetX + width} ${offsetY + height + deep} L ${offsetX + width} ${offsetY + height} `; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 左下盒舌 const createBottomTongue = (width, height, deep, offsetX, offsetY, size) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); // M 90 160 L 88 162 L 88 175 L 64 175 A 2 2 0 0 1 62 173 L 60 160 Z const d = `M ${offsetX} ${offsetY + height} L ${offsetX - 2} ${offsetY + height + 2} L ${offsetX - 2} ${offsetY + height + size} L ${offsetX - deep + 4} ${offsetY + height + size} A 2 2 0 0 1 ${offsetX - deep + 2} ${offsetY + height + size - 2} L ${offsetX - deep} ${offsetY + height} `; svg.setAttribute("d", d); svg.setAttribute("fill", "transparent"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 标注 const createArrowWithText = (width, height, deep, offsetX, offsetY, size) => { // 定义箭头标记 const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); const d = `M ${offsetX + width / 2} ${offsetY - deep + 15} L ${offsetX + width / 2} ${offsetY - deep + 5} L ${offsetX + width / 2 - 5} ${offsetY - deep + 5} L${offsetX + width / 2} ${offsetY - deep} L ${offsetX + width / 2 + 5} ${offsetY - deep + 5} L${offsetX + width / 2} ${offsetY - deep + 5}`; svg.setAttribute("d", d); svg.setAttribute("fill", "#333"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 添加标注 const createText = (offsetX, offsetY, size, textContent) => { const text = document.createElementNS("http://www.w3.org/2000/svg", "text"); text.setAttribute("x", offsetX); // 文字水平居中 text.setAttribute("y", offsetY); // 文字垂直居中 text.setAttribute("text-anchor", "middle"); // 文字水平居中 text.setAttribute("dominant-baseline", "middle"); // 文字垂直居中 text.setAttribute("fill", "#333"); // 文字颜色 text.setAttribute("font-size", size); // 文字大小 text.setAttribute("font-weight", "bold"); // 文字加粗 text.textContent = textContent || "Text"; // 默认文字内容 return text; }; // 竖向双箭头 const createDoubleArrow = (height, offsetX, offsetY, Y) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); const d = `M ${offsetX} ${offsetY} L ${offsetX} ${height - 5} L ${offsetX + 5} ${height - 5} L ${offsetX} ${height} L ${offsetX - 5} ${height - 5} L ${offsetX} ${height - 5} L ${offsetX} ${Y + 5} L ${offsetX + 5} ${Y + 5} L ${offsetX} ${Y} L ${offsetX - 5} ${Y + 5} L ${offsetX} ${Y + 5}`; svg.setAttribute("d", d); svg.setAttribute("fill", "#333"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 横向双箭头 const createHorizontalDoubleArrow = (width, offsetX, offsetY) => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "path"); const d = `M ${offsetX} ${offsetY} L ${offsetX - width / 2 + 5} ${offsetY} L ${offsetX - width / 2 + 5} ${offsetY - 5} L ${offsetX - width / 2} ${offsetY} L ${offsetX - width / 2 + 5} ${offsetY + 5} L ${offsetX - width / 2 + 5} ${offsetY} L ${offsetX + width / 2 - 5} ${offsetY} L ${offsetX + width / 2 - 5} ${offsetY + 5} L ${offsetX + width / 2} ${offsetY} L ${offsetX + width / 2 - 5} ${offsetY - 5} L ${offsetX + width / 2 - 5} ${offsetY}`; svg.setAttribute("d", d); svg.setAttribute("fill", "#333"); svg.setAttribute("stroke", "#333"); svg.setAttribute("stroke-width", "1"); return svg; }; // 扣抵盒 const createBox = (width, height, deep, c, g, a) => { let pathList = []; // 四面盒身 const rectangles = [ { x: 0, y: 0, width, height, id: "ac_path_c795a39_2oj", wrapperId: "3476" }, { x: 0 + width, y: 0, width: deep, height, id: "ac_path_c795a39_2on", wrapperId: "3480" }, { x: 0 + width + deep, y: 0, width, height, id: "ac_path_c795a39_2or", wrapperId: "3484" }, { x: 0 + width * 2 + deep, y: 0, width: deep, height, id: "ac_path_c795a39_2ov", wrapperId: "3488" }, ]; const svg = svgRef.current; // 添加梯形 pathList.push(createTrapezoid(width, height, 0, 0, g)); pathList.push(createDynamicTop(width, height, deep, 0, 0, c)); pathList.push(createTopTongue(width, height, deep, 0, 0, a)); pathList.push(createTopTongueRight(width, height, deep, width * 2 + deep + 0, 0, a)); pathList.push(createBottomTongueRight(width, height, deep, width * 2 + deep + 0, 0, a)); pathList.push(createBottom(width, height, deep, 0 + deep + width, 0, c)); // 是否下舌头 pathList.push(createBottomTongue(width, height, deep, 0 + deep + width, 0, a)); // 上边部件贴位标注 pathList.push(createArrowWithText(width, height, deep, 0, 0, a)); pathList.push(createDoubleArrow(height, width + deep + width / 2 - 20, height / 2, 0)); pathList.push(createDoubleArrow(a + height, width * 2 + deep + deep / 2, height + a / 2, height)); pathList.push(createHorizontalDoubleArrow(width, width + deep + width / 2, height / 2 - 20)); pathList.push(createHorizontalDoubleArrow(deep, width + deep / 2, height / 2)); pathList.push(createText(width / 2 + 5, -deep - 5, 14, "c")); pathList.push(createText(width * 2 + deep + deep / 2 + 10, height + a / 2, 14, "a")); pathList.push(createText(-g / 2, height / 2, 14, "g")); pathList.push(createText(width + deep + width / 2 - 10, height / 2, 14, "D")); pathList.push(createText(width + deep + width / 2 + 10, height / 2 - 10, 14, "L")); pathList.push(createText(width + deep / 2, height / 2 + 10, 14, "W")); pathList.forEach(item => { svg.appendChild(item); }); const viewBoxWidth = width * 2 + deep * 2 + g + 2; const viewBoxHeight = height + (deep + c) * 2 + 2; // 更新 SVG 的 viewBox 和尺寸 const svgContainer = svgContainerRef.current; svg.setAttribute("viewBox", `${-g - 1} ${-(deep + c) - 1} ${viewBoxWidth} ${viewBoxHeight}`); svg.setAttribute("width", `${viewBoxWidth}px`); svg.setAttribute("height", `${viewBoxHeight}px`); svgContainer.style.width = `${viewBoxWidth}px`; svgContainer.style.height = `${viewBoxHeight}px`; rectangles.forEach(rect => { const pathElement = createPathElement(rect.x, rect.y, rect.width, rect.height, rect.id, rect.wrapperId); svg.appendChild(pathElement); }); }; const initBox = (list, g, c, width, height) => { const svg = svgRef.current; list.forEach(item => { svg.appendChild(item); }); const viewBoxWidth = evaluateFormula(slaveDataDetail.sLengthFormula, variables) + 1 + width; const viewBoxHeight = evaluateFormula(slaveDataDetail.sWidthFormula, variables) + height; // 更新 SVG 的 viewBox 和尺寸 const svgContainer = svgContainerRef.current; svg.setAttribute("viewBox", `${-g} ${-c} ${viewBoxWidth} ${viewBoxHeight}`); svg.setAttribute("width", `${viewBoxWidth}px`); svg.setAttribute("height", `${viewBoxHeight}px`); svgContainer.style.width = `${viewBoxWidth}px`; svgContainer.style.height = `${viewBoxHeight}px`; }; const initSVG = () => { const svg = svgRef.current; svg.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${currentScale})`; }; const moveSVG = (translateX, translateY) => { setCurrentTranslateX(currentTranslateX + translateX); setCurrentTranslateY(currentTranslateY + translateY); }; const zoomSVG = scaleChange => { const newScale = currentScale + scaleChange; setCurrentScale(Math.max(0.5, Math.min(3, newScale))); }; const updateSVGTransform = () => { const svg = svgRef.current; svg.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${currentScale})`; updatePositionInfo(); }; const updatePositionInfo = () => { if (svgRef.current) { const rect = svgRef.current.getBoundingClientRect(); setPositionInfo({ x: rect.x, y: rect.y, width: rect.width, height: rect.height, }); } }; useEffect( () => { updateSVGTransform(); }, [currentTranslateX, currentTranslateY, currentScale] ); // 当 SVG 的位置或大小变化时,更新位置信息 useEffect( () => { updatePositionInfo(); }, [currentTranslateX, currentTranslateY, currentScale, width, height, deep] ); return ( //