chenlu
2025-10-12 73af02320e1d3c43fbc12d06f1935569ae49e155
Merge branch 'master' of http://10.153.19.25:10105/r/ERP_override
17个文件已修改
590 ■■■■■ 已修改文件
north-glass-erp/northglass-erp/src/hook/mouseMove.ts 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/hook/mouseMoveHomePage.ts 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/ar.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/en.js 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/kr.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/ru.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectCreate.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProcessCard.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProcessCardDetail.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/delivery/DeliveryReport.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/dto/sd/DeliveryDetailDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/sd/DeliveryDetailMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/hook/mouseMove.ts
@@ -165,7 +165,8 @@
    result.forEach((item,index) => {
        if(index>0){
            sum = Number(add(sum, (item[0] || 0)))
            const val = isNaN(item[0])?0:item[0]
            sum = Number(add(sum, (val || 0)))
        }
    })
north-glass-erp/northglass-erp/src/hook/mouseMoveHomePage.ts
@@ -165,7 +165,8 @@
    result.forEach((item,index) => {
        if(index>0){
            sum = Number(add(sum, (item[0] || 0)))
            const val = isNaN(item[0])?0:item[0]
            sum = Number(add(sum, (val || 0)))
        }
    })
north-glass-erp/northglass-erp/src/lang/ar.js
@@ -177,6 +177,8 @@
           productAbbreviation:'اختصار المنتج',
           productDuplication:'تكرار المنتج',
           msg1:'创建人是:',
           msg2:'无法操作!',
       }
    },
    order:{
@@ -283,6 +285,16 @@
        valueAddedTax:'增值税',
        cuttingTransport:'运输消减',
        colourCeramicGlaze:'彩釉图号',
        transferPage:{
            oldOrderId:'原订单号',
            newOrderId:'新订单号',
            oldOrderNumber:'原订单序号',
            newOrderNumber:'新订单序号',
            confirmTitle:'确实转移此序号的流程卡报工数据?',
            errorToMes:'与mes通讯异常'
        },
        msg:{
            productCheck:'الرجاء اختيار منتج',
            tableLengthNot:'لا توجد بيانات للجدول',
@@ -397,7 +409,6 @@
        qr2Local:'二维码2位置',
        default:'默认'
    },
    workOrder:{
@@ -429,6 +440,8 @@
            selectDetailProcessCard:"流程卡明细查询"
        },
        yesTitle:'有标题打印',
        noTitle:'无标题打印',
        buildingNumber:'楼号',
        longSide:'长边',
        shortSide:'短边',
@@ -586,6 +599,9 @@
            addReportingWork:"إضافة تقرير جديد",
            qualityInspectionReview:"مراجعة  فحص الجودة",
        },
        msgMannerPacking:'请选择包装方式',
        saveWorkStorage:'报工入库',
        mannerPacking:'包装方式',
        glassNumber:'رقم الزجاج',
        glassAddress:'علامة الزجاج',
        WorkReportingManagement:'إدارة التقارير',
@@ -915,6 +931,7 @@
        printPatchesMsg1:'请选择标签模板',
        labelTemplate:'标签模板:',
        listLabelTemplates:'标签模板列表'
    },
    rework:{
        page:{
@@ -964,6 +981,7 @@
        userId:'اسم المستخدم',
        user:'مستخدم',
        setUpRoles:'تعيين الدور الوظيفي',
        setProcess:'设置工序',
        changePassword:'تغيير كلمة المرور',
        OldPassword:'كلمة المرور القديمة',
        TheNewPassword:'كلمة المرور الجديدة',
@@ -1105,6 +1123,7 @@
        qualityReport:'تقرير الجودة',
        productionScheduling:'排产计划报表',
        yieldReport:'تقرير معدل المنتجات النهائية',
        yieldProcessReport:'成品率工序汇总报表',
        workingProcedure:'العملية',
        inventoryArea:'منطقة التخزين',
        pleaseSelectADateFirst:'الرجاء تحديد تاريخ أولا',
@@ -1135,6 +1154,7 @@
        workProcessName:'在制品名称',
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/en.js
@@ -177,6 +177,8 @@
            productAbbreviation:'Product abbreviation',
            productDuplication:'Product repetition',
            msg1:'创建人是:',
            msg2:'无法操作!',
        }
    },
    order:{
@@ -283,6 +285,16 @@
        valueAddedTax:'增值税',
        cuttingTransport:'运输消减',
        colourCeramicGlaze:'彩釉图号',
        transferPage:{
            oldOrderId:'原订单号',
            newOrderId:'新订单号',
            oldOrderNumber:'原订单序号',
            newOrderNumber:'新订单序号',
            confirmTitle:'确实转移此序号的流程卡报工数据?',
            errorToMes:'与mes通讯异常'
        },
        msg:{
            productCheck:'Please select a product',
            tableLengthNot:'No table data',
@@ -316,7 +328,6 @@
            updateOrderIdErrorInputNumber:'请输入数字',
            updateOrderIdErrorNotNo1:'不能修改第一个单子',
            updateOrderError:'此订单已工艺审核或修改无法再次修改,页面将自动刷新!'
        },
        preciseMode:'精确模式',
        ambiguityModels:'模糊模式',
@@ -428,6 +439,8 @@
            printFlowCard:"Process card printing",
            selectDetailProcessCard:"Process card details query"
        },
        yesTitle:'有标题打印',
        noTitle:'无标题打印',
        buildingNumber:'楼号',
        longSide:'长边',
        shortSide:'短边',
@@ -460,6 +473,7 @@
        reviewedState:'Review Status',
        reviewed:'Reviewer',
        schedulingId:'Production Scheduling Number',
        notes:'Примечания',
        scheduling:'Production Scheduling',
        schedulingOk:'Please select the data on the right first',
        schedulingNo:'Please enter a positive integer',
@@ -530,8 +544,6 @@
        selectFill:'Selected fill',
        engineeringPrinting:'Engineering Printing',
        pleaseSelectProject:'Please Select Project',
        mergeState:'Merge State',
        merge:'Merge',
        printQuantity:'Print Quantity',
@@ -587,6 +599,9 @@
            addReportingWork:"New Work Reporting",
            qualityInspectionReview:"Quality Inspection Review",
        },
        msgMannerPacking:'请选择包装方式',
        saveWorkStorage:'报工入库',
        mannerPacking:'包装方式',
        glassNumber:'Code',
        glassAddress:'Glass Address',
        WorkReportingManagement:'Work Reporting Management ',
@@ -857,7 +872,6 @@
            shipmentProductClassificationReport:"Category report of shipped products ",
            createDelivery:'Create delivery',
            deliveryReport:'Delivery report',
        },
        delivery:'Delivery',
        place :'Place',
@@ -907,6 +921,7 @@
            addReplenish:"Add Patches",
            printReplenishFlowCard:"Print Patches"
        },
        patchManagement:'Patch Management',
        addPatches:"Add Patches ",
        printPatches:'Print Patches',
@@ -916,6 +931,7 @@
        printPatchesMsg1:'请选择标签模板',
        labelTemplate:'标签模板:',
        listLabelTemplates:'标签模板列表'
    },
    rework:{
        page:{
@@ -965,6 +981,7 @@
        userId:'User ID',
        user:'User',
        setUpRoles:'Set a role',
        setProcess:'设置工序',
        changePassword:'Change password',
        OldPassword:'Old password',
        TheNewPassword:'New password',
@@ -1106,6 +1123,7 @@
        qualityReport:'Quality statement',
        productionScheduling:'Production scheduling report',
        yieldReport:'Yield report',
        yieldProcessReport:'成品率工序汇总报表',
        workingProcedure:'Process',
        inventoryArea:'Stock area(m²)',
        pleaseSelectADateFirst:'Please select the date first',
@@ -1136,6 +1154,7 @@
        workProcessName:'在制品名称',
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/kr.js
@@ -177,6 +177,8 @@
            productAbbreviation:'제품명 축약',
            productDuplication:'제품 중복',
            msg1:'创建人是:',
            msg2:'无法操作!',
        }
    },
    order:{
@@ -406,6 +408,7 @@
        qr1Local:'二维码1位置',
        qr2Local:'二维码2位置',
        default:'默认'
    },
    workOrder:{
@@ -437,6 +440,8 @@
            selectDetailProcessCard:'프로세스 카드 상세 조회'
        },
        yesTitle:'有标题打印',
        noTitle:'无标题打印',
        buildingNumber:'楼号',
        longSide:'长边',
        shortSide:'短边',
@@ -594,6 +599,9 @@
            addReportingWork:"공수 보고 추가",
            qualityInspectionReview:"검품 승인",
        },
        msgMannerPacking:'请选择包装方式',
        saveWorkStorage:'报工入库',
        mannerPacking:'包装方式',
        glassNumber:'일련번호',
        glassAddress:'마킹',
        WorkReportingManagement:'업무 보고 관리',
@@ -1115,6 +1123,7 @@
        qualityReport:'품질 보고서',
        productionScheduling:'생산 일정 편성',
        yieldReport:'양품률 보고서',
        yieldProcessReport:'成品率工序汇总报表',
        workingProcedure:'공정',
        inventoryArea:'재고 지역',
        pleaseSelectADateFirst:'날짜를 선택하세요',
@@ -1145,6 +1154,7 @@
        workProcessName:'在制品名称',
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/ru.js
@@ -177,7 +177,8 @@
            productAbbreviation:'Продукция',
            productDuplication:'产品重复',
            default:'默认'
            msg1:'创建人是:',
            msg2:'无法操作!',
        }
    },
    order:{
@@ -284,6 +285,16 @@
        valueAddedTax:'增值税',
        cuttingTransport:'运输消减',
        colourCeramicGlaze:'彩釉图号',
        transferPage:{
            oldOrderId:'原订单号',
            newOrderId:'新订单号',
            oldOrderNumber:'原订单序号',
            newOrderNumber:'新订单序号',
            confirmTitle:'确实转移此序号的流程卡报工数据?',
            errorToMes:'与mes通讯异常'
        },
        msg:{
            productCheck:'Пожалуйста, выберите продукт',
            tableLengthNot:'Нет данных таблицы',
@@ -326,6 +337,7 @@
        layer:'单片模式',
        notFinish:'待完成',
        processCardCollect:'流程卡汇总',
    },
    searchOrder:{
        createOrder:'Выписать заказ',
@@ -426,7 +438,10 @@
            addProcessCard:"分架新增",
            printFlowCard:"流程卡打印",
            selectDetailProcessCard:"流程卡明细查询"
        },
        yesTitle:'有标题打印',
        noTitle:'无标题打印',
        buildingNumber:'楼号',
        longSide:'长边',
        shortSide:'短边',
@@ -584,6 +599,9 @@
            addReportingWork:"Новые отзывы",
            qualityInspectionReview:"Проверка качества",
        },
        msgMannerPacking:'请选择包装方式',
        saveWorkStorage:'报工入库',
        mannerPacking:'包装方式',
        glassNumber:'number',
        glassAddress:'Стеклянная маркировка',
        WorkReportingManagement:'Управление обратной связью',
@@ -963,6 +981,7 @@
        userId:'Идентификатор пользователя',
        user:'Пользователи',
        setUpRoles:'Настройка ролей',
        setProcess:'设置工序',
        changePassword:'Изменить пароль',
        OldPassword:'Старый пароль',
        TheNewPassword:'Новый пароль',
@@ -1104,6 +1123,7 @@
        qualityReport:'Отчет о качестве',
        productionScheduling:'排产计划报表',
        yieldReport:'Отчет о готовой продукции',
        yieldProcessReport:'成品率工序汇总报表',
        workingProcedure:'Операции',
        inventoryArea:'Складская площадь',
        pleaseSelectADateFirst:'Пожалуйста, выберите дату.',
@@ -1134,6 +1154,7 @@
        workProcessName:'在制品名称',
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
@@ -1,5 +1,8 @@
<template>
  <div>
    <el-button id="button" type="primary" @click="printReports" style="background: #409eff; position: fixed; top: 90px; right: 100px; padding: 20px; color: white; border: none; cursor: pointer; margin-right: 10px;">
      预览
    </el-button>
    <el-button id="button" type="primary" @click="handlePrint" style="position: fixed; top: 90px; right: 20px; padding: 20px; background: #409eff; color: white; border: none; border-radius: 5px; cursor: pointer;">
      打印
    </el-button>
@@ -7,17 +10,30 @@
    <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 20px;">
      <span>工程编号:</span>
      <el-input readonly placeholder="" style="width: 150px" v-model="processId"></el-input>&nbsp;
      <el-checkbox v-model="config.plain">
        切材率
      <el-checkbox v-model="config.printLayouts">
        打印版图
      </el-checkbox>
      <el-checkbox v-model="config.printReport">
        打印报告
      </el-checkbox>
      <div style="margin-right: 30px;"></div>
      <span>布局选择:</span>
      <el-select v-model="config.type"  style="width: 120px;">
        <el-option v-for="type in linkTypes" :key="type" :value="type" />
      <el-select v-model="config.columnTypes"  style="width: 120px;">
        <el-option v-for="type in columnTypes" :key="type" :value="type" />
      </el-select>
      <el-button id="button" type="primary" @click="handlePrint" style="background: #409eff; color: white; border: none; cursor: pointer;">
        预览
      </el-button>
      <el-select v-model="config.rowTypes"  style="width: 120px;">
        <el-option v-for="type in rowTypes" :key="type" :value="type" />
      </el-select>
    </div>
    <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 20px;">
      <span>显示小片信息:</span>
      <el-select v-model="config.glassInfo"  style="width: 120px;">
        <el-option v-for="type in glassInfo" :key="type" :value="type" />
      </el-select>
      <span>显示切割信息:</span>
      <el-select v-model="config.cutInfo"  style="width: 120px;">
        <el-option v-for="type in cutInfo" :key="type" :value="type" />
      </el-select>
    </div>
    <div ref="printContainer" style="position: relative;">
@@ -44,6 +60,8 @@
import { ref, onMounted, watch, reactive, inject } from 'vue';
import RectRenderer from './page/RectRenderer.vue';
import request from "@/utils/request";
import {ElMessage, ElMessageBox} from "element-plus";
import requestOptimize from "@/utils/requestOptimize";
const props = defineProps({
  project : null,
@@ -54,11 +72,19 @@
const savedProjectNo = localStorage.getItem('projectNo');
const processId = ref('');
const layoutData = ref();
const optimizeUse = ref();
const reportData = ref();
const layoutSet = ref();
const materialList = ref();
const productList = ref();
const dataLoaded = ref(false);
const materialDetails = ref();
const injectedProjectNo = inject('projectNo', null);
const state = ref();
const linkTypes = ['一列', '两列', '三列']
const columnTypes = ['一列', '两列', '三列', '四列']
const rowTypes = ['一行', '两行']
const glassInfo = ['不显示', '显示在右侧', '显示在下侧']
const cutInfo = ['不显示', '显示']
// 定义不同布局对应的尺寸
const layoutDimensions = {
@@ -75,13 +101,15 @@
const currentPrintHeight = ref(layoutDimensions[printLayout.value].height);
const selectLayout = () => {
  request.post(`/glassOptimize/selectOptimizeResult/${processId.value}`)
  request.post(`/glassOptimize/getOptimizeInfo/${processId.value}`)
    .then((res) => {
      if (res.code == 200) {
        try {
          layoutData.value = JSON.parse(res.data.data[0].Layouts);
          materialDetails.value=res.data.optimizeUse;
          dataLoaded.value=true;
          layoutData.value = res.data.layouts;
          optimizeUse.value=res.data.optimizeUse[0];
          // 添加控制台输出
          console.log('layoutData:', layoutData.value);
          console.log('optimizeUse:', optimizeUse.value);
        } catch (error) {
          console.error("解析布局数据失败:", error);
        }
@@ -94,9 +122,142 @@
    });
};
const selectReportData= () => {
  request.post(`/glassOptimize/getReportData/${processId.value}`)
      .then((res) => {
        if (res.code == 200) {
          try {
            reportData.value = res.data.reportData[0];
            console.log('reportData:', reportData.value);
          } catch (error) {
            console.error("解析布局数据失败:", error);
          }
        } else {
          console.error("请求失败,状态码:", res.code);
        }
      })
      .catch((error) => {
        console.error("请求失败:", error);
      });
};
const selectMaterialData= () => {
  request.post(`/glassOptimize/materialInfo/${processId.value}`)
      .then((res) => {
        if (res.code == 200) {
          try {
            materialList.value = res.data.materialList[0];
            console.log('reportData:', materialList.value);
          } catch (error) {
            console.error("解析布局数据失败:", error);
          }
        } else {
          console.error("请求失败,状态码:", res.code);
        }
      })
      .catch((error) => {
        console.error("请求失败:", error);
      });
};
const selectProductData= () => {
  request.post(`/glassOptimize/getProductList/${processId.value}`)
      .then((res) => {
        if (res.code == 200) {
          try {
            productList.value = res.data.productList;
            console.log('productList:', productList.value);
          } catch (error) {
            console.error("解析布局数据失败:", error);
          }
        } else {
          console.error("请求失败,状态码:", res.code);
        }
      })
      .catch((error) => {
        console.error("请求失败:", error);
      });
};
const printReports = async() => {
  try {
    // 确保有数据可以提交
    if (!processId) {
      ElMessage.warning('没有可打印的数据');
      return;
    }
    // 映射 rowTypes 到 layoutRows
    const layoutRowsMap = {
      '一行': 1,
      '两行': 2
    };
    // 映射 columnTypes 到 layoutColumns
    const layoutColumnsMap = {
      '一列': 1,
      '两列': 2,
      '三列': 3,
      '四列': 4
    };
    // 映射 glassInfo 到 glassInfoShow
    const glassInfoMap = {
      '不显示': 0,
      '显示在右侧': 1,
      '显示在下侧': 2
    };
    // 映射 cutInfo 到 cutInfoShow
    const cutInfoMap = {
      '不显示': 0,
      '显示': 1
    };
    const response = await requestOptimize.post('/api/reports', {
      fileName: processId.value,
      projectNo: processId.value,
      companyName : '1',
      glassThickness : optimizeUse.value.thickness,
      glassType : optimizeUse.value.model,
      quantity : String(optimizeUse.value.processingQuantity),
      printLayouts : config.printLayouts ? '1' : '0',
      printReport : config.printReport ? '1' : '0',
      layouts : layoutData.value,
      reportData: reportData.value,
      materialList: materialList.value,
      productList: productList.value,
      layoutSet: {
        layoutRows: layoutRowsMap[config.rowTypes] || 1,
        layoutColumns: layoutColumnsMap[config.columnTypes] || 1,
        glassInfoShow: glassInfoMap[config.glassInfo] || 0,
        cutInfoShow: cutInfoMap[config.cutInfo] || 0
      }
    }, {
      headers: {
        'Content-Type': 'application/json'
      }
    });
  } catch (error) {
    console.error('保存失败:', error);
    ElMessage.error('保存失败,请稍后再试');
  }
};
const config = reactive({
  type: '两列',
  columnTypes: '两列',
  rowTypes: '两行',
  plain: true,
  printLayouts: true,
  printReport: true,
  glassInfo: '不显示',
  cutInfo: '显示'
})
onMounted(() => {
@@ -112,6 +273,9 @@
  if (processId.value) {
    selectLayout();
    selectReportData();
    selectMaterialData();
    selectProductData();
  }
});
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectCreate.vue
@@ -343,7 +343,7 @@
    <div id="project-list">
      <div style="width: 100%;height: 100%">
        <h1>工程列表</h1>
        <h2>工程列表</h2>
        <vxe-grid
            size="small"
            height="100%"
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProcessCard.vue
@@ -394,7 +394,7 @@
      </template>
      <template #toolbar_buttons>
        <h1>膜系筛选:</h1>
        <h2>膜系筛选:</h2>
        <el-select v-model="optionVal" clearable default-value="default_city" placeholder="选择膜系"
                   style="width: 120px">
          <el-option
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProcessCardDetail.vue
@@ -121,7 +121,7 @@
<template>
  <div style="width: 100%;height: 100%">
    <h1>流程卡详情</h1>
    <h2>流程卡详情</h2>
    <vxe-grid
        size="small"
        height="100%"
north-glass-erp/northglass-erp/src/views/sd/delivery/DeliveryReport.vue
@@ -39,6 +39,8 @@
    {field: 'delivery.deliveryAddress',width:150, title: t('delivery.shippingAddress'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'orderId',width:120, title: t('order.orderId'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'orderNumber',width:120, title: t('order.OrderNum'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'orderDetail.buildingNumber',width:120, title: t('order.buildingNumber'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'boxNo',width:120, title: t('productStock.boxNumber'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'deliveryDetailRemakes',width:120, title: t('basicData.remarks'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'createTime',width:120, title: t('basicData.reportData'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java
@@ -255,6 +255,26 @@
        return  Result.seccess(glassOptimizeService.saveOptimizeResult(object,projectId));
    }
    @ApiOperation("查询报告数据接口")
    @PostMapping("/getReportData/{processId}")
    public Result getReportData(@PathVariable String processId){
        return  Result.seccess(glassOptimizeService.getReportDataSv(processId));
    }
    @ApiOperation("查询物料信息接口")
    @PostMapping("/materialInfo/{processId}")
    public Result materialInfo(
            @PathVariable String processId){
        return  Result.seccess(glassOptimizeService.getMaterialInfoSv(processId));
    }
    @ApiOperation("查询产品列表接口")
    @PostMapping("/getProductList/{processId}")
    public Result getProductList(
            @PathVariable String processId){
        return  Result.seccess(glassOptimizeService.getProductListSv(processId));
    }
    @ApiOperation("查询优化结果接口")
    @PostMapping("/selectOptimizeResult/{processId}")
north-glass-erp/src/main/java/com/example/erp/dto/sd/DeliveryDetailDTO.java
@@ -68,6 +68,10 @@
    private String orderId;
    @ExcelProperty("订单序号")
    private Integer orderNumber;
    @ExcelProperty("楼层编号")
    private String buildingNumber;
    @ExcelProperty("箱号")
    private String boxNo;
    @ExcelProperty("批次")
    private String batch;
    @ExcelProperty("宽")
north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java
@@ -215,4 +215,16 @@
    void addUpdateOffcut(Map<String, Object> detail, String processId, String glassType, String glassThickness, int stockId);
    void updateProjectOptimize(String projectId, Integer states, Map<String, Object> optimalResults);
    List<Map<String, Object>> getReportDataProcessIdSv(String processId);
    List<Map<String, Object>> getPeriMeterDataSv(String processId);
    List<Map<String, Object>> getMaterialInfoSv(String processId);
    List<Map<String, Object>> getProductListSv(String processId);
    List<Map<String, Object>> selectProjectList(String processId);
    List<Map<String, Object>> materialOptimizeUse(String processId);
}
north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java
@@ -558,7 +558,7 @@
//        Map<String, Object> result = new HashMap<>();
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("layouts", layouts);
        result.put("optimizeUse", glassOptimizeMapper.materialStoreOptimizeUse(processId));
        result.put("optimizeUse", glassOptimizeMapper.materialOptimizeUse(processId));
        return result;
    }
@@ -1208,4 +1208,137 @@
    }
    public Map<String, Object> getReportDataSv(String processId) {
        Map<String, Object> perimap = new HashMap<>();
        perimap.put("peridata", glassOptimizeMapper.getPeriMeterDataSv(processId));
        Map<String, Object> map = new HashMap<>();
        Object layoutSetObj = glassOptimizeMapper.getReportDataProcessIdSv(processId);
        map.put("reportData", layoutSetObj);
        List<Map<String, Object>> peridata = (List<Map<String, Object>>) perimap.get("peridata");
        double totalPerimeter = 0.0;
        if (peridata != null && !peridata.isEmpty()) {
            for (Map<String, Object> perimeterData : peridata) {
                if (perimeterData.containsKey("perimeter") && perimeterData.get("perimeter") != null) {
                    try {
                        Object perimeterObj = perimeterData.get("perimeter");
                        if (perimeterObj instanceof Number) {
                            totalPerimeter += ((Number) perimeterObj).doubleValue();
                        } else {
                            totalPerimeter += Double.parseDouble(perimeterObj.toString());
                        }
                    } catch (NumberFormatException e) {
                        System.err.println("无法解析周长数据: " + perimeterData.get("perimeter"));
                    }
                }
            }
        }
        if (layoutSetObj instanceof List) {
            List<Map<String, Object>> layoutSet = (List<Map<String, Object>>) layoutSetObj;
            if (!layoutSet.isEmpty()) {
                layoutSet.get(0).put("rectanglePerimeter", totalPerimeter);
            }
        }
        return map;
    }
    public Map<String, Object> getMaterialInfoSv(String processId) {
        Map<String, Object> map = new HashMap<>();
        map.put("materialList", glassOptimizeMapper.getMaterialInfoSv(processId));
        return map;
    }
    public Map<String, Object> getProductListSv(String processId) {
        Map<String, Object> productMap = new HashMap<>();
        List<Map<String, Object>> productInfo = glassOptimizeMapper.selectProjectList(processId);
        productMap.put("productInfo", productInfo);
        Map<String, Object> map = new HashMap<>();
        if (productInfo != null && !productInfo.isEmpty()) {
            // 按照 processCard 分组
            Map<String, List<Map<String, Object>>> groupedByProcessCard = new HashMap<>();
            for (Map<String, Object> item : productInfo) {
                String processCard = (String) item.get("processCard");
                if (processCard != null) {
                    groupedByProcessCard.computeIfAbsent(processCard, k -> new ArrayList<>()).add(item);
                }
            }
            // 为每个 processCard 计算统计信息
            List<Map<String, Object>> result = new ArrayList<>();
            for (Map.Entry<String, List<Map<String, Object>>> entry : groupedByProcessCard.entrySet()) {
                String processCard = entry.getKey();
                List<Map<String, Object>> items = entry.getValue();
                // 计算统计信息
                double longestSide = 0;
                double shortestSide = Double.MAX_VALUE;
                int specQuantity = items.size();
                int totalQuantity = 0;
                // 使用 BigDecimal 精确计算面积
                BigDecimal totalArea = BigDecimal.ZERO;
                for (Map<String, Object> item : items) {
                    // 安全获取长和宽
                    Number widthObj = (Number) item.get("width");
                    Number heightObj = (Number) item.get("height");
                    if (widthObj == null || heightObj == null) {
                        continue;
                    }
                    double width = widthObj.doubleValue();
                    double height = heightObj.doubleValue();
                    // 更新最长边和最短边
                    double maxSide = Math.max(width, height);
                    double minSide = Math.min(width, height);
                    if (maxSide > longestSide) {
                        longestSide = maxSide;
                    }
                    if (minSide < shortestSide) {
                        shortestSide = minSide;
                    }
                    // 安全获取数量
                    Number quantityObj = (Number) item.get("quantity");
                    if (quantityObj != null) {
                        totalQuantity += quantityObj.intValue();
                    }
                    // 安全获取面积 —— 使用 BigDecimal 精确累加
                    Object areaObj = item.get("Area");
                    if (areaObj != null) {
                        // 关键:通过 toString() 转为字符串再构造 BigDecimal,避免 double 精度损失
                        BigDecimal area = new BigDecimal(areaObj.toString());
                        totalArea = totalArea.add(area);
                    }
                }
                // 处理 shortestSide 的边界情况
                if (shortestSide == Double.MAX_VALUE) {
                    shortestSide = 0;
                }
                // 构造返回数据
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("processCard", processCard);
                resultMap.put("longestSide", longestSide);
                resultMap.put("shortestSide", shortestSide);
                resultMap.put("specQuantity", specQuantity);
                resultMap.put("totalQuantity", totalQuantity);
                resultMap.put("totalArea", totalArea);
                result.add(resultMap);
            }
            map.put("productList", result);
        }
        return map;
    }
}
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
@@ -1949,6 +1949,107 @@
        WHERE
            project_no = #{projectId}
    </select>
    <select id="getReportDataProcessIdSv" resultType="java.util.Map" parameterType="java.lang.String">
        SELECT
            op.project_no as projectId,
            op.glass_total as rectangleQuantity,
            '0' as otherShapeQuantity,
            op.glass_total_area as rectangleArea,
            '0' as otherShapeArea,
            '0' as otherShapePerimeter
        FROM
            pp.optimize_project as op
        WHERE
            op.project_no = #{processId}
    </select>
    <select id="getPeriMeterDataSv" resultType="java.util.Map" parameterType="java.lang.String">
        SELECT
            od.id,
            od.project_no,
            od.p_width,
            od.p_height,
            (od.p_width + od.p_height)*2 AS perimeter
        FROM
            pp.optimize_detail as od
        WHERE
            od.project_no =  #{processId}
    </select>
    <select id="getMaterialInfoSv" resultType="java.util.Map" parameterType="java.lang.String">
        SELECT
            ou.raw_stock_code AS code,
            ou.use_count AS quantity,
            ou.width,
            ou.height,
            ou.width*ou.height*ou.use_count/1000000.0 as useArea,
            op.glass_total_area as totalArea
        FROM
            pp.optimize_use ou
                INNER JOIN pp.optimize_project op on ou.project_no = op.project_no
        WHERE
            ou.project_no = #{processId} and ou.state=1
    </select>
    <select id="getProductListSv" resultType="java.util.Map" parameterType="java.lang.String">
    </select>
    <select id="selectProjectList" resultType="java.util.Map" parameterType="java.lang.String">
        ( SELECT
              c.project_no,
              c.quantity AS quantity,
              d.child_width AS width,
              d.child_height AS height,
              concat( c.process_id, '-', c.technology_number ) AS processCard,
              round( d.area * c.quantity, 4 ) AS Area,
              c.order_number
          FROM
              pp.flow_card c
                  LEFT JOIN sd.order_glass_detail d ON c.order_id = d.order_id
                  AND c.order_number = d.order_number
                  AND c.technology_number = d.technology_number
          WHERE
              c.project_no IS NOT NULL
            AND c.project_no = #{processId}
          ORDER BY
              c.process_id,
              c.order_number
        ) UNION
        (
            SELECT
                c.project_no,
                c.patch_num AS quantity,
                d.child_width AS width,
                d.child_height AS height,
                concat( c.process_id, '-', c.technology_number ) AS processCard,
                round( d.area * c.patch_num, 4 ) AS Area,
                c.order_sort
            FROM
                pp.patch_log c
                    LEFT JOIN sd.order_glass_detail d ON c.order_id = d.order_id
                    AND c.order_sort = d.order_number
                    AND c.technology_number = d.technology_number
            WHERE
                c.project_no IS NOT NULL
              AND c.project_no = #{processId}
            ORDER BY
                c.process_id,
                c.order_sort)
    </select>
    <select id="materialOptimizeUse" resultType="java.util.Map">
        select ou.raw_stock_code AS id,
               ou.use_count AS processingQuantity,
               ou.width,
               ou.height,
               ou.left_trim as leftTrim,
               ou.down_trim as downTrim,
               ou.up_trim as upTrim,
               ou.right_trim as rightTrim,
               JSON_UNQUOTE(JSON_EXTRACT(ms.json, '$.thickness')) AS thickness,
               JSON_UNQUOTE(JSON_EXTRACT(ms.json, '$.name')) AS name,
               JSON_UNQUOTE(JSON_EXTRACT(ms.json, '$.model')) AS model
        from pp.optimize_use ou
                 left join mm.material_store ms on ou.raw_stock_code=ms.id where project_no=#{projectNumber} and state=1
    </select>
</mapper>
north-glass-erp/src/main/resources/mapper/sd/DeliveryDetailMapper.xml
@@ -73,6 +73,7 @@
        <result column="delivery_detail_remakes" property="deliveryDetailRemakes"/>
        <result column="delivery_detail_state" property="deliveryDetailState"/>
        <result column="create_time" property="createTime"/>
        <result column="box_no" property="boxNo"/>
        <result column="customer_id" property="delivery.customerId"/>
        <result column="customer_name" property="delivery.customerName"/>
@@ -94,6 +95,7 @@
        <result column="product_name" property="orderDetail.productName"/>
        <result column="width" property="orderDetail.width"/>
        <result column="height" property="orderDetail.height"/>
        <result column="building_number" property="orderDetail.buildingNumber"/>
        <result column="other_money" property="order.otherMoney"/>
        <result column="batch" property="order.batch"/>
@@ -592,7 +594,9 @@
        d.freight,
        o.batch,
        od.width,
        od.height
        od.height,
        od.building_number,
        dd.box_no
        from sd.delivery_detail dd
        left join sd.delivery d on dd.delivery_id=d.delivery_id
        left join order_detail od on dd.order_id=od.order_id and dd.order_number=od.order_number
@@ -607,6 +611,12 @@
            </if>
            <if test="deliveryDetail.orderDetail!=null and (deliveryDetail.orderDetail.height != null and deliveryDetail.orderDetail.height != '')">
                and od.height regexp REGEXP_REPLACE(#{deliveryDetail.orderDetail.height},'\\.0+$','')
            </if>
            <if test="deliveryDetail.orderDetail!=null and (deliveryDetail.orderDetail.buildingNumber != null and deliveryDetail.orderDetail.buildingNumber != '')">
                and od.building_number like concat('%',#{deliveryDetail.orderDetail.buildingNumber},'%')
            </if>
            <if test="deliveryDetail.boxNo != null and deliveryDetail.boxNo != ''">
                and dd.box_no like concat('%',#{deliveryDetail.boxNo},'%')
            </if>
            <if test="deliveryDetail.deliveryId != null and deliveryDetail.deliveryId != ''">
                and dd.delivery_id like concat('%',#{deliveryDetail.deliveryId},'%')
@@ -707,6 +717,21 @@
        left join sd.`order` o on dd.order_id=o.order_id
        <where>
            and date(dd.create_time)>=#{startDate} and date(dd.create_time) &lt;= #{endDate}
            <if test="deliveryDetail.order!=null and (deliveryDetail.order.batch != null and deliveryDetail.order.batch != '')">
                and o.batch like concat('%',#{deliveryDetail.order.batch},'%')
            </if>
            <if test="deliveryDetail.orderDetail!=null and (deliveryDetail.orderDetail.width != null and deliveryDetail.orderDetail.width != '')">
                and od.width regexp REGEXP_REPLACE(#{deliveryDetail.orderDetail.width},'\\.0+$','')
            </if>
            <if test="deliveryDetail.orderDetail!=null and (deliveryDetail.orderDetail.height != null and deliveryDetail.orderDetail.height != '')">
                and od.height regexp REGEXP_REPLACE(#{deliveryDetail.orderDetail.height},'\\.0+$','')
            </if>
            <if test="deliveryDetail.orderDetail!=null and (deliveryDetail.orderDetail.buildingNumber != null and deliveryDetail.orderDetail.buildingNumber != '')">
                and od.building_number like concat('%',#{deliveryDetail.orderDetail.buildingNumber},'%')
            </if>
            <if test="deliveryDetail.boxNo != null and deliveryDetail.boxNo != ''">
                and dd.box_no like concat('%',#{deliveryDetail.boxNo},'%')
            </if>
            <if test="deliveryDetail.deliveryId != null and deliveryDetail.deliveryId != ''">
                and dd.delivery_id like concat('%',#{deliveryDetail.deliveryId},'%')
            </if>
@@ -791,6 +816,7 @@
            <if test="deliveryDetail.delivery!=null and (deliveryDetail.delivery.freightPrice != null )">
                and d.freight_price regexp REGEXP_REPLACE(#{deliveryDetail.delivery.freightPrice},'\\.0+$','')
            </if>
        </where>
        order by dd.delivery_id,dd.delivery_number
    </select>
@@ -1322,7 +1348,9 @@
        d.freight_quantity,
        od.width,
        od.height,
        o.batch
        o.batch,
        od.building_number,
        dd.box_no
        from sd.delivery_detail dd
        left join sd.delivery d on dd.delivery_id=d.delivery_id
        left join order_detail od on dd.order_id=od.order_id and dd.order_number=od.order_number