diff --git a/src/components/Common/Typesetting/typesetting.js b/src/components/Common/Typesetting/typesetting.js index 7ae889d..3d10538 100644 --- a/src/components/Common/Typesetting/typesetting.js +++ b/src/components/Common/Typesetting/typesetting.js @@ -205,7 +205,6 @@ const Typesetting = props => { const boxWidthOffset = evaluateFormula(sSecondLongitudinalOffset, variabless); // 第二列纵向偏移 const isVertical = sSettingMethod === "从上到下"; // true 表示竖向排列,false 表示横向排列 sSettingMethod === '从上到下' const reference = sSGroupOffset === "首盒"; // 第三列参考 - console.log(reference,'reference') // 计算内层盒子尺寸 加上间距 let jInnerHeight = innerHeight; let jInnerWidth = innerWidth; diff --git a/src/components/QuickQuote/index.jsx b/src/components/QuickQuote/index.jsx index 043932f..2585ae2 100644 --- a/src/components/QuickQuote/index.jsx +++ b/src/components/QuickQuote/index.jsx @@ -1460,7 +1460,12 @@ const ContentComponent = props => { if (!boxModelList.length) return; setActiveKey(0); }, [sAllPartsName]); - + useEffect(() => { + props.setState(pre => ({ + ...pre, + boxModelKey: activeKey, + })); + }, [activeKey]); const dividerProps = { className: styles.divider, orientation: "left", @@ -2763,18 +2768,48 @@ const ManyComponent = props => { // 核价事件 const onCalcPrice = () => { + const { state } = props; + const { masterData = {}, slaveConfig, slaveData = [], selectedNode = {}, backendConfig = {}, boxModelKey = 0, bestAlgorithm,activeKey } = state; + if (activeKey === 0) { + const radios = GetBestAlgorithm(props); + slaveData[boxModelKey] = { + ...slaveData[boxModelKey], + radioValue: radios.sCode, + }; + props.setState(pre => ({ ...pre, slaveData, bestAlgorithm: commonUtils.createSid(),onCalcPrices:true })); + } else { const addState = { ...props.onGetAllDelData(), manyDataCache: [], }; - props.onSaveState({ masterData: { ...props.masterData, handleType: props.masterData.handleType || "update" }, calcPriceTime: commonUtils.createSid(), ...addState, }); + props.setState(pre => ({ ...pre,onCalcPrices:false })); + } + + // setTimeout(() => { + + // }, 500); + }; + const { bestAlgorithm,onCalcPrices } = state; + useEffect(() => { + if (!bestAlgorithm) return + if (!onCalcPrices) return + const addState = { + ...props.onGetAllDelData(), + manyDataCache: [], + }; + props.onSaveState({ + masterData: { ...props.masterData, handleType: props.masterData.handleType || "update" }, + calcPriceTime: commonUtils.createSid(), + ...addState, + }); + }, [bestAlgorithm,onCalcPrices]); useEffect(() => { if (props.calcPriceTime) { props.onSaveState({ calcPriceTime: undefined }); @@ -3326,5 +3361,514 @@ const BackendParamsExtraComponent = props => { ); }; +const GetBestAlgorithm = props => { + const { state } = props; + const { masterData = {}, slaveConfig, slaveData = [], selectedNode = {}, backendConfig = {}, boxModelKey = 0 } = state; + if (!slaveConfig) return ""; + const { sParentFieldsName, sBoxModel, printParamsId } = backendConfig; + const slaveRowData = slaveData.filter(item => item.sTreeNodeName === selectedNode.showName)[boxModelKey] || {}; + if (!slaveRowData) return null; + const { sColumnNameConfigExclusion } = slaveRowData; + console.log("🚀 ~ slaveRowData:", slaveRowData); + const calcMethodData = commonUtils.convertStrToObj(sColumnNameConfigExclusion, []); + let { + dSBLB = 0, // 上边留白 + dXBLB = 0, // 下边留白 + dZBLB = 0, // 左边留白 + dYBLB = 0, // 右边留白 + // dXBJJ, // 上边距 + dXBJJ = 0, // 下边距 + // dYBJJ, // 左边距 + dYBJJ = 0, // 右边距 + sLengthFormula, // 盒长公式 + sWidthFormula, // 盒宽公式 + sPackDetailPath, + sColumnNameConfig, + bAdvancedSetting, // 高级设置 + sSvgPath, + dL = 0, + dW = 0, + } = slaveRowData; + if (selectedNode && selectedNode.sTypeKey === "juantong") { + dXBLB = dSBLB; + dZBLB = 0; + dYBLB = 0; + } + let { dHorizontal, dPortrait, dHorizontalType, dPortraitType } = slaveRowData; + const slaveDataDetail = slaveRowData; + const maxWidth = Number(slaveDataDetail?.dMaxLength); + const maxHeight = Number(slaveDataDetail?.dMaxWidth); + + let outerWidth = Number(slaveDataDetail?.dMaxLength); // 默认取最大上机尺寸 + let outerHeight = Number(slaveDataDetail?.dMaxWidth); // 默认取最大上机尺寸 + const L = slaveRowData.dL ? Number(dL) : Number(masterData?.dLength) || 0; + const W = slaveRowData.dW ? Number(dW) : masterData?.dWidth || 0; + const H = masterData?.dWidth || 0; + const D = masterData?.dHeight || 0; + // 动态计算公式值 + 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(",") + ",Math"; + // 替换公式中的变量为实际值 + const func = new Function(params, `return ${formula}`); + // 提取变量值 + const args = variableNames.map(name => Number(variables[name]) || 0); + // 执行函数并返回结果 + return func(...args, Math); + } catch (error) { + return 0; + } + }; + + // 计算公式值 + const variables = { + L, + W, + H, + D, + ...slaveRowData, + }; + let boxList = []; + if (slaveRowData.sColumnNameConfig) { + const slaveNewData = slaveRowData.upAbleConfigsExtra || JSON.parse(slaveRowData.sColumnNameConfig); + const tables = [ + { name: "盒型类别", value: slaveRowData.sBoxType, type: null }, + { name: "盒身", value: slaveRowData.sBoxBody, type: slaveRowData.sTypes }, + { name: "盒长", value: L, type: null }, + { name: "盒宽", value: W, type: null }, + { name: "盒高", value: D, type: null }, + ]; + const titleList1 = [ + { name: "上方盒舌", value: "dSFHS" }, + { name: "盒底组件", value: "dHDC" }, + { name: "下方盒舌", value: "dXFHS" }, + { name: "左(上)插位组件", value: "dZSCW" }, + { name: "左贴边位", value: "dZTBW" }, + { name: "左(下)插位组件", value: "dZXCW" }, + { name: "右(上)插位组件", value: "dYSCW" }, + { name: "右贴边位", value: "dYTBW" }, + { name: "右(下)插位组件", value: "dYXCW" }, + ]; + slaveNewData.forEach(x => { + let key = 0; + if (x.sAssignFormula) { + key = parseFloat(evaluateFormula(x.sAssignFormula, variables)).toFixed(2) || 0; + } else { + key = slaveRowData[x.sName]; + } + boxList.push({ + value: key, + sName: titleList1.find(item => item.value === x.sName)?.name || "", + isEditable: true, + isSelect: false, + selectValue: null, + selectLabel: "", + selectImage: null, + type: x.sTypes || null, + show: true, + sCode: titleList1.find(item => item.value === x.sName)?.value || "", + showName: x.showName, // 参数名称 + }); + }); + tables.forEach(x => { + boxList.push({ + value: x.value, + sName: x.name, + isEditable: true, + isSelect: false, + selectValue: null, + selectLabel: "", + selectImage: null, + type: x.type || null, + show: true, + showName: x.name, // 参数名称 + }); + }); + } + + const result = boxList?.reduce((acc, { sCode, value }) => ({ ...acc, [sCode]: Number(value) }), {}); + + // 计算表达式结果 + const variabless = { + ...variables, + ...result, + }; + Object.keys(variabless).forEach(key => { + if (variabless[key] === null || variabless[key] === undefined || variabless[key] === "") { + variabless[key] = 0; + } + }); + const calculateLayout = (radioValue, i) => { + const innerWidth = slaveRowData.sTypes === "6" ? evaluateFormula(sWidthFormula, variabless) : evaluateFormula(sLengthFormula, variabless); + const innerHeight = slaveRowData.sTypes === "6" ? evaluateFormula(sLengthFormula, variabless) : evaluateFormula(sWidthFormula, variabless); + const { sSettingMethod, sSGroupOffset, iFAngle, iSAngle, sSecondorizontalOffset, sSecondLongitudinalOffset } = radioValue ? radioValue : {}; + const dFWidthOffset = evaluateFormula(radioValue?.sFWidthOffset, variabless); // 首盒纵向偏移 + const dFLengthOffset = evaluateFormula(radioValue?.sFLengthOffset, variabless); // 首盒横向偏移 + const dSWidthOffset = evaluateFormula(radioValue?.sSWidthOffset, variabless); // 次盒纵向偏移 + const dSLengthOffset = evaluateFormula(radioValue?.sSLengthOffset, variabless); // 次盒横向偏移 + const boxLengthOffset = evaluateFormula(sSecondorizontalOffset, variabless); // 第二列横向偏移 + const boxWidthOffset = evaluateFormula(sSecondLongitudinalOffset, variabless); // 第二列纵向偏移 + const isVertical = sSettingMethod === "从上到下"; // true 表示竖向排列,false 表示横向排列 sSettingMethod === '从上到下' + const reference = sSGroupOffset === "首盒"; // 第三列参考 + // 计算内层盒子尺寸 加上间距 + let jInnerHeight = innerHeight; + let jInnerWidth = innerWidth; + let dSvgBoxWidth = innerWidth; + let dSvgBoxHeight = innerHeight; + const isRrotate = iFAngle === 90 || iFAngle === 270 || iSAngle === 90 || iSAngle === 270; + if (iFAngle === 90 || iFAngle === 270 || iSAngle === 90 || iSAngle === 270) { + jInnerHeight = innerWidth; + jInnerWidth = innerHeight; + } + if (state.selectedNode.sTypeKey === "kapai" || state.selectedNode.sTypeKey === "juantong") { + jInnerHeight = innerHeight; + jInnerWidth = innerWidth; + } + + const innerHeightCombined = + (isVertical ? jInnerHeight * 2 + dSWidthOffset + dFWidthOffset : Math.max(jInnerHeight + dFWidthOffset, jInnerHeight + dSWidthOffset)) + dXBJJ; // 计算内层盒子高度 从上向下排列 取首盒加偏移量和次盒加偏移量最大的值 从左往右排列 盒子尺寸 * 2 加上首盒偏移量和次盒偏移量 + // 计算内层盒子宽度 从上向下排列 取首盒加偏移量和次盒加偏移量最大的值 从左往右排列 盒子尺寸 * 2 加上首盒偏移量和次盒偏移量 + const innerWidthCombined = + (isVertical ? Math.max(jInnerWidth + dFLengthOffset, jInnerWidth + dSLengthOffset) : jInnerWidth * 2 + dSLengthOffset + dFLengthOffset) + dYBJJ; + // 加上间距后的最大盒子长宽 计算每列可以放多少个组合 需要计算间距 + // 每个盒子加上边距 和第二组偏移量 如果根据次盒再加上次盒偏移量 + const dSWidthOffsetCombined = innerWidthCombined + boxLengthOffset + (reference ? 0 : dSLengthOffset); + let cols = dSWidthOffsetCombined === 0 ? 0 : Math.floor(outerWidth / dSWidthOffsetCombined); + const rowsCombined = innerHeightCombined + boxWidthOffset + (reference ? 0 : dSWidthOffset); + let rows = rowsCombined === 0 ? 0 : Math.floor(outerHeight / rowsCombined); + let colsMaxLength = + cols * (innerWidthCombined + boxLengthOffset + (reference ? 0 : dSLengthOffset) + dYBJJ) + dZBLB + dYBLB - (reference ? 0 : dSLengthOffset); + let rowsMaxLength = + rows * (innerHeightCombined + boxWidthOffset + (reference ? 0 : dSWidthOffset) + dXBJJ) + dSBLB + dXBLB - (reference ? 0 : dSWidthOffset); + while (colsMaxLength > outerWidth && cols > 0) { + cols = cols - 1; + colsMaxLength = cols * (innerWidthCombined + boxLengthOffset + (reference ? 0 : dSLengthOffset) + dYBJJ); + } + + while (rowsMaxLength > outerHeight && rows > 0) { + rows = rows - 1; + rowsMaxLength = rows * (innerHeightCombined + boxWidthOffset + (reference ? 0 : dSWidthOffset) + dXBJJ); + } + // 最大上机长 上机宽 开料尺寸 + // 计算剩余空间 每组都算上偏移量 那么剩余需要加上后面偏移的总量 + const remainingWidth = outerWidth - colsMaxLength + (boxLengthOffset + (reference ? 0 : dSLengthOffset)); + const remainingHeight = outerHeight - rowsMaxLength + (boxWidthOffset + (reference ? 0 : dSWidthOffset)); + //剩余量能不能放一下单独一个 + const commonHeightCheck = remainingHeight > jInnerHeight + dXBJJ; + const commonWidthCheck = remainingWidth > jInnerWidth + dYBJJ; + const isCustomized = bAdvancedSetting; + let remaining = isVertical ? commonHeightCheck : commonWidthCheck; + + // 判断 + // const remaining = false; + const isOdd = num => { + return num % 2 !== 0; + }; + + // 是否定制 + if (isCustomized) { + if (isVertical) { + cols = dHorizontal || 0; + rows = dPortrait ? Math.trunc(dPortrait / 2) : 0; + if (isOdd(dPortrait)) { + remaining = true; + } else { + remaining = false; + } + } else { + cols = dHorizontal ? Math.trunc(dHorizontal / 2) : 0; + rows = dPortrait || 0; + if (isOdd(dHorizontal)) { + remaining = true; + } else { + remaining = false; + } + } + } + const createDiv = (col, row, index, leftPosition, topPosition, offsetZ, icon) => ( +
{ + onClick(); + }} + > +
+
+ ); + + const createBox = (col, row, index, leftPosition, topPosition, offsetZ, icon) => ( +
{ + onClick(); + }} + > +
+
+
+ {/* 次盒 */} +
+
+ ); + const createBoxOne = (col, row, index, leftPosition, topPosition, offsetZ, icon) => ( +
{ + onClick(); + }} + > +
+
+ ); + // 计算左偏移 + const calculateLeftPosition = (col, reference, isVertical, leftPosition, dYBJJ, dSLengthOffset) => { + console.log(isVertical, reference, "reference"); + if (isVertical) { + if (reference) { + return col === 0 ? leftPosition : leftPosition + dYBJJ * col; + } + return col === 0 ? leftPosition : leftPosition + (boxLengthOffset + dYBJJ) * col; + } else { + if (reference) { + return col === 0 ? leftPosition : leftPosition + dYBJJ * col; + } + return col === 0 ? leftPosition : leftPosition + (boxLengthOffset + dYBJJ) * col + dSLengthOffset * col; + } + }; + // 计算上偏移 + const calculateTopPosition = (row, reference, isVertical, topPosition, dSWidthOffset, dXBJJ) => { + if (isVertical) { + if (reference) { + return row === 0 ? topPosition : topPosition + boxWidthOffset * row; + } else { + return row === 0 ? topPosition : topPosition + (dSWidthOffset + boxWidthOffset) * row; + } + } else { + if (reference) { + return row === 0 ? 0 : topPosition + boxWidthOffset * row; + } else { + return row === 0 ? topPosition : topPosition + (dSWidthOffset + boxWidthOffset) * row; + } + } + }; + const innerDivs = []; + // 生成盒子 + if (cols === 0 || rows === 0) { + if (cols > 0) { + for (let col = 0; col < cols; col++) { + const leftPosition = col * innerWidthCombined; + const topPosition = 0 * innerHeightCombined; + innerDivs.push(createBoxOne(col, 0, 3, leftPosition, topPosition, iFAngle)); + } + } + if (rows > 0) { + for (let row = 0; row < rows; row++) { + const leftPosition = 0 * innerWidthCombined; + const topPosition = row * innerHeightCombined; + innerDivs.push(createBoxOne(0, row, 3, leftPosition, topPosition, iFAngle)); + } + } + } else { + let hasPushed = false; // 标志变量 + for (let col = 0; col < cols; col++) { + for (let row = 0; row < rows; row++) { + const leftPosition = col * innerWidthCombined; + const topPosition = row * innerHeightCombined; + innerDivs.push(createBox(col, row, 1, leftPosition, topPosition, iFAngle)); + } + // 如果可以放下首盒\ + if (remaining && isVertical) { + let leftPosition = 0; + let topPosition = 0; + if (reference) { + // 是否首盒 + // 首盒的上边距下边距 末尾盒子的上下边距 添加那一行的上边距 + leftPosition = col * innerWidthCombined + dFLengthOffset; + topPosition = rows * innerHeightCombined + dFWidthOffset; + } else { + leftPosition = col * innerWidthCombined; + topPosition = rows * innerHeightCombined; + } + innerDivs.push(createBoxOne(col, rows, 3, leftPosition, topPosition + dXBJJ, iFAngle)); + } + } + if (remaining && !isVertical) { + for (let index = 0; index < rows; index++) { + // 先默认为首盒参考 + let topPosition = 0; + let leftPosition = 0; + if (reference) { + topPosition = index * (innerHeightCombined + boxWidthOffset); + leftPosition = cols * (innerWidthCombined + boxLengthOffset); + } else { + topPosition = index * (innerHeightCombined + boxWidthOffset + dSWidthOffset); + + leftPosition = cols * (innerWidthCombined + boxLengthOffset + dSLengthOffset + dYBJJ); + } + innerDivs.push(createDiv(cols - 1, index, 3, leftPosition, topPosition, iFAngle)); + } + } + } + const propsData = innerDivs[innerDivs.length - 1]; + let openEdition = 0; + const { dWlcd, sBillNo } = slaveRowData; + + const propsDataLeft = Number(propsData.props.style.left.slice(0, -2)); + // 长需要找出最大的 + const propsDataWidth = Number(propsData.props.style.width.slice(0, -2)); + const propsDataHeight = Number(propsData.props.style.height.slice(0, -2)); + const propsDataTop = Number(propsData.props.style.top.slice(0, -2)); + // 判断列是否是单独的 + + const newMaterialLength = parseFloat(propsDataLeft + (remaining ? jInnerWidth : innerWidthCombined) + dZBLB + dYBLB).toFixed(2); // 原纸长 + const newMaterialWidth = parseFloat( + propsDataTop + propsDataHeight + dSBLB + dXBLB - (isVertical ? 0 : rows >= 1 ? (remaining ? 0 : dXBJJ) : 0) + ).toFixed(2); + + // 计算开数 + let dSinglePQty = isVertical + ? remaining + ? cols + cols * (rows * 2) + : cols * (rows * 2) + : remaining + ? rows + rows * (cols * 2) + : rows * (cols * 2); + + let dHorizontalType = isVertical ? cols : remaining ? cols * 2 + 1 : cols * 2; + let dPortraitType = isVertical ? (remaining ? rows * 2 + 1 : rows * 2) : remaining ? rows : rows; + if (cols === 0 || rows === 0) { + if (innerDivs.length > 0) { + if (cols === 0 && rows > 0) { + dSinglePQty = rows; + dPortraitType = rows; + dHorizontalType = 1; + } else if (rows === 0 && cols > 0) { + dSinglePQty = cols; + dHorizontalType = cols; + dPortraitType = 1; + } + } + } + const newDProductQty = masterData.dProductQty; + const dMaterialsKQty = slaveDataDetail.dMaterialsKQty || 1; + openEdition = (((newMaterialLength * newMaterialWidth) / (maxWidth * maxHeight)) * 100).toFixed(2); + return { + newMaterialLength, + newMaterialWidth, + dSinglePQty, + index: i, + }; + }; + let list = []; + if (calcMethodData && calcMethodData.length) { + list = calcMethodData.map((item, i) => { + return calculateLayout(item, i); + }); + } + const findMinValueItem = data => { + let minItem = null; + let minValue = Infinity; + + for (const item of data) { + const { newMaterialLength, newMaterialWidth, dSinglePQty } = item; + const length = parseFloat(newMaterialLength); + const width = parseFloat(newMaterialWidth); + const value = (length * width) / dSinglePQty; + + if (value < minValue) { + minValue = value; + minItem = item; + } + } + + return minItem; + }; + return list.length ? calcMethodData[findMinValueItem(list).index] : calcMethodData[0]; +}; export default QuickQuote;