chenlu
2025-05-19 eb6c8328231985b96ad11b38b38ae1ec926beb9a
Merge branch 'master' of http://bore.pub:10439/r/ERP_override
23个文件已修改
1个文件已添加
1943 ■■■■ 已修改文件
north-glass-erp/northglass-erp/src/components/pp/Optimization.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/router/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/order/orderInfo.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeProject.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/GlassInventory.vue 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue 424 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizeCompute.vue 300 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/basicData/SearchBasicData.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeProjectMange.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/service/sd/BasicDateService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/sd/BasicDataMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/components/pp/Optimization.vue
New file
@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
  <canvas id="canvas"></canvas>
</template>
<style scoped>
</style>
north-glass-erp/northglass-erp/src/router/index.js
@@ -357,7 +357,7 @@
              component: () => import('../views/pp/glassOptimize/OptimizeParms.vue'),
            },
            {
              path: '/optimizeProject/:projectNo/:thickNess/:model',
              path: '/optimizeProject/:projectNo/:thickNess/:model/:quantity/:area/:optimizeState',
              name: 'optimizeInfo',
              component: () => import('../views/pp/glassOptimize/OptimizeProject.vue')
            },
north-glass-erp/northglass-erp/src/stores/sd/order/orderInfo.js
@@ -32,7 +32,12 @@
                }
            }
        }
        },
        projectNo:ref(),
        optimizeData:{
            optimalResults:'',
            originalFilm:''
        },
@@ -75,6 +80,11 @@
                    }
                }
            }
            this.projectNo=null
            this.optimizeData={
                optimalResults:null,
                originalFilm:null
            }
        }
    },
    persist: true
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/GlassComputed.vue
@@ -10,6 +10,7 @@
  project : null
});
const state = ref()
const computed = ref(null);
const computedCard = ref(null);
const computedData = ref({
@@ -86,65 +87,87 @@
}
const handleSimulation = async () => {
  const data=computeCardRef.value.selectFullData();
  let arry = computeCardRef.value.selectFullData();
  let data = arry;
  data = data.reduce((acc, item) => {
    if (item.tempering) {
      acc.push(item);
    }
    return acc;
  }, []);
  if(data.length===arry.length){
    state.value=1
  }else{
    state.value=2
  }
  if(props.project!=null){
    computed.value.glass_thickness=props.project.glass_thickness
    computed.value.glass_type=props.project.glass_type
  }
  data.forEach(item=>{
    const processCard = {
      process_no: item.processId,
      layers: item.technologyNumber,
      total_layers: item.total_layers,
      total_num: item.total_num,
      total_area: item.total_area,
      is_must: true,
      allow_rotate: item.allow_rotate,
      priority_level: 0,
      tempering: item.tempering,
      curtain_wall: item.curtain_wall,
      patch_state: item.patch_state,
      merge: item.merge,
      glass_details: []
    };
  if(data.length>0){
    data.forEach(item=>{
      const processCard = {
        process_no: item.processId,
        layers: item.technologyNumber,
        total_layers: item.total_layers,
        total_num: item.total_num,
        total_area: item.total_area,
        is_must: true,
        allow_rotate: item.allow_rotate,
        priority_level: 0,
        tempering: item.tempering,
        curtain_wall: item.curtain_wall,
        patch_state: item.patch_state,
        merge: item.merge,
        glass_details: []
      };
    request.post(`/glassOptimize/selectComputeDetail/${item.processId}/${item.technologyNumber}/${item.patch_state}`).then((res) => {
      if(Number(res.code) === 200){
        res.data.data.forEach(items=>{
          const detail={
            process_id:null,
            technology_number:null,
            order_number:null,
            layers_number:null,
            max_width:null,
            max_height:null,
            child_width:null,
            child_height:null,
            quantity:null,
            patch_state:null
          }
          detail.process_id=items.process_id
          detail.technology_number=items.technology_number
          detail.order_number=items.order_number
          detail.layers_number=item.total_layers
          detail.max_width=items.maxwidth
          detail.max_height=items.maxheight
          detail.child_width=items.width
          detail.child_height=items.height
          detail.quantity=items.quantity
          detail.patch_state=item.patch_state
      request.post(`/glassOptimize/selectComputeDetail/${item.processId}/${item.technologyNumber}/${item.patch_state}`).then((res) => {
        if(Number(res.code) === 200){
          res.data.data.forEach(items=>{
            const detail={
              process_id:null,
              technology_number:null,
              order_number:null,
              layers_number:null,
              max_width:null,
              max_height:null,
              child_width:null,
              child_height:null,
              quantity:null,
              patch_state:null
            }
            detail.process_id=items.process_id
            detail.technology_number=items.technology_number
            detail.order_number=items.order_number
            detail.layers_number=item.total_layers
            detail.max_width=items.maxwidth
            detail.max_height=items.maxheight
            detail.child_width=items.width
            detail.child_height=items.height
            detail.quantity=items.quantity
            detail.patch_state=item.patch_state
          processCard.glass_details.push(detail)
        })
            processCard.glass_details.push(detail)
          })
      }else{
        ElMessage.warning(res.msg)
      }
        }else{
          ElMessage.warning(res.msg)
        }
      })
      computed.value.process_cards.push(processCard)
    })
    computed.value.process_cards.push(processCard)
  })
  console.log(computed.value)
    console.log(computed.value)
  }else{
    ElMessage.warning("没有需要钢化工艺的数据请直接保存")
    state.value=3
    return
  }
  /*request.post(`/glassOptimize/simulationCalculate`,computed.value).then((res) => {
    if(Number(res.code) === 200){
@@ -252,9 +275,9 @@
              "angle": 0.0,
              "glass_type": 3,
              "height": 862,
              "layers_number": 2,
              "order_number": 33,
              "process_id": "NG24120028A005",
              "layers_number": 1,
              "order_number": 1,
              "process_id": "NG22091408A06",
              "technology_number": 2,
              "tempering_feed_sequence": 1,
              "tempering_layout_id": 1,
@@ -266,9 +289,9 @@
              "angle": 0.1,
              "glass_type": 4,
              "height": 862,
              "layers_number": 2,
              "order_number": 33,
              "process_id": "NG24120028A005",
              "layers_number": 1,
              "order_number": 1,
              "process_id": "NG22091408A06",
              "technology_number": 2,
              "tempering_feed_sequence": 2,
              "tempering_layout_id": 1,
@@ -279,9 +302,8 @@
          ],
          "guidance": 15,
          "rackinfos": [
            "NG24120026A003-2",
            "NG24120027A003-2",
            "NG24120028A005-2"
            "NG24111432A004-1",
            "NG25000086A001-1"
          ],
          "ratioResult": [
            {
@@ -378,7 +400,7 @@
  <div style="width: 100%; height: 100%;">
   
    <div id="compute">
      <compute  :data="computedData"  @fetch-data="handleFetchData" :project="props.project"  @sendData="handleData"  @simulate-click="handleSimulation" />
      <compute  :data="computedData" :state="state"  @fetch-data="handleFetchData" :project="props.project"  @sendData="handleData"  @simulate-click="handleSimulation" />
    </div>
    <div id="computeCard">
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue
@@ -17,7 +17,11 @@
import request from "@/utils/request";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
import {useRoute} from "vue-router";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
const route = useRoute();
const orderInfo = useOrderInfoStore()
const { t } = useI18n();
const savedProjectNo = localStorage.getItem('projectNo');
const processId = savedProjectNo;
@@ -47,6 +51,11 @@
}
onMounted(() => {
  selectLayout();
  if(orderInfo.optimizeData.optimalResults!=null){
    layoutData.value=orderInfo.optimizeData.optimalResults
    dataLoaded.value = true;
  }else{
    selectLayout();
  }
});
</script>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizationRectPrint.vue
@@ -44,7 +44,7 @@
  '4rows-2cols': { width: 1000, height: 1000 },
  '3rows-2cols': { width: 1000, height: 1000 },
  '3rows-1col': { width: 1000, height: 1000 },
  '2rows-2cols': { width: 1200, height: 1200 }
  '2rows-2cols': { width: 1400, height: 800 }
};
// 当前布局的尺寸
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
@@ -2,8 +2,8 @@
    <div >
      <RectRenderer 
    :layoutData="layoutData" 
    :gw="1400"
    :gh="1100"
    :gw="1400"
    :gh="800"
    style="width: 1500px; height: 800px; position: relative;"
    v-if="dataLoaded"
  />
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue
@@ -25,7 +25,7 @@
const saveToDatabase = () => {
  console.log(settings)
  request.post(`/glassOptimize/optimizeParms`, settings).then((res) => {
  request.post(`/glassOptimize/optimizeParms/${username}`, settings).then((res) => {
    if (res.code == 200 && res.data === true) {
      ElMessage.success(t('basicData.msg.saveSuccess'))
    } else {
@@ -61,19 +61,20 @@
const paramMapping = {
  yShapeJoinOptimization: { name: '异形拼接优化', type: 'checkbox' },
  autoMiddleEmptyPairing: { name: '自动中空配对', type: 'checkbox' },
  smallPieceRotationProhibited: { name: '小片禁止旋转', type: 'checkbox' },
  smallPieceRotationProhibited: { name: '小片旋转', type: 'checkbox' },
  maxFramesOnSite: { name: '现场最大可放架子数量', type: 'text' },
  bendEdgeDistance: { name: '掰边距(mm)', type: 'text' },
  positiveTolerance: { name: '正公差(mm)', type: 'text' },
  negativeTolerance: { name: '负公差(mm)', type: 'text' },
  cutterOriginPosition: { name: '切割机原点位置', type: 'select' },
  uniformShapeEdgeTrimAmount: { name: '统一设置异形修边量', type: 'text' },
  edgeTrimMode: { name: '修边模式', type: 'select' },
  parallelOptimizationChannels: { name: '并行优化的通道数量', type: 'text' },
  optimizationMethod: { name: '优化方式', type: 'select' },
  travType: { name: '横切', type: 'select' },
  optimizationIterations: { name: '重复优化次数', type: 'text' },
  finishedProductGrindingAmount: { name: '成品默认磨量', type: 'text' },
  rawPieceEdgeTrimAmount: { name: '原片默认修边量', type: 'text' },
  finishedSinglePieceBelowGrindingAmount: { name: '成品单片小于多少时磨量为', type: 'text' }
  finishedSinglePieceBelowGrindingAmount: { name: '成品单片小于多少时磨量为', type: 'text' },
  rackCycleQty: { name: '循环落架数', type: 'text' }
};
// 动态生成参数列表
@@ -337,13 +338,14 @@
                <input 
                  v-if="param.type === 'checkbox'" 
                  type="checkbox" 
                  :checked="settings.optimization[param.key] === '1'"
                  @click="() => { settings.optimization[param.key] = settings.optimization[param.key] === '1' ? '0' : '1' }"
                  :checked="settings.optimization[param.key] === true"
                  @click="() => { settings.optimization[param.key] = settings.optimization[param.key]!==true }"
                >
                <select 
                  v-else-if="param.type === 'select'" 
                  :name="param.key" 
                  class="cs"
                  v-model="settings.optimization[param.key]"
                >
                  <option 
                    v-for="option in getOptions(param.key)" 
@@ -508,14 +510,19 @@
function getOptions(key) {
  const optionsMapping = {
    cutterOriginPosition: [
      { value: 'topLeft', label: '左上角' },
      { value: 'bottomLeft', label: '左下角' },
      { value: 'topRight', label: '右上角' },
      { value: 'bottomRight', label: '右下角' }
      { value: 2, label: '左上角' },
      { value: 1, label: '左下角' },
      { value: 4, label: '右上角' },
      { value: 3, label: '右下角' }
    ],
    edgeTrimMode: [
      { value: 'intelligent', label: '智能修边' },
      { value: 'complete', label: '完全修边' }
    optimizationMethod: [
      { value: 1, label: 'optima' },
      { value: 2, label: '北玻' }
    ],
    travType: [
      { value: 'X', label: 'X' },
      { value: 'Y', label: 'Y' },
      { value: 'XY', label: 'XY' }
    ]
  };
  return optionsMapping[key] || [];
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeProject.vue
@@ -6,6 +6,7 @@
import ProjectMange from "@/views/pp/glassOptimize/ProjectMange.vue";
import {ref} from "vue";
import {ElMessage} from "element-plus";
let dialogVisible = ref(false)
let detailPage = ref(0)
const changeDialog = (value) => {
@@ -15,6 +16,8 @@
//从工程管理获取工程号,并跳转
const projectNumber = ref();
const  glassInventoryRef=ref(null)
const switchDialog = (number) => {
  projectNumber.value = number;
  detailPage.value = 3;
@@ -45,6 +48,14 @@
    isTrimmingDialogVisible.value = value;
  };
let checkboxChangeData = ref('');
const getSmallPieceData = () => {
    checkboxChangeData.value=glassInventoryRef.value.checkboxChanges();
};
</script>
<template >
@@ -53,10 +64,12 @@
     <project-detail @changeDialog="changeDialog"
                     @forward-data-to-grandparent="handleProjectDetailData"
                     @send-inventory-to-op="handleInventoyData"
                     :TrimmingDialogVisible="isTrimmingDialogVisible" />
                     @getSmallPieceData="getSmallPieceData"
                     :TrimmingDialogVisible="isTrimmingDialogVisible" :CheckboxChangeData="checkboxChangeData" />
   </div>
   <div id="main-footer">
     <glass-inventory :receivedData="dataForGlassInventory"
     <glass-inventory ref="glassInventoryRef"
         :receivedData="dataForGlassInventory"
                      :InventoryData="sendDataGlassInventory"
                      @select-trimming="sendTrimming"/>
   </div>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue
@@ -57,6 +57,8 @@
    {field: 'thickness', width: 50, title: '厚度',},
    {field: 'type', width: 50, title: '类型',},
    {field: 'state', width: 50, title: '状态',},
    {field: 'temperingState', width: 50, title: '钢化状态',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged},
    {field: 'optimizeState', width: 50, title: '优化状态',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged},
    {field: 'quantity', width: 50, title: '数量',},
    {field: 'area', width: 50, title: '面积',},
    {field: 'processCardQuantity', width: 100, title: '流程卡数量',},
@@ -91,7 +93,7 @@
        [
          {code: 'openProject', name: '打开工程', prefixIcon: 'vxe-icon-folder-open'},
          {code: 'compute', name: '模拟计算', prefixIcon: 'vxe-icon-subtable'},
          {code: 'optimizeTypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'},
          //{code: 'optimizeTypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'},
          {code: 'production', name: '允许生产', prefixIcon: 'vxe-icon-square-checked'},
          {code: 'novisible', name: '生产不可见', prefixIcon: 'vxe-icon-eye-fill-close'},
          {code: 'copyproject', name: '复刻工程', prefixIcon: 'vxe-icon-copy'},
@@ -113,17 +115,20 @@
const operationConfigs = [
  {
    code: 'openProject', // 打开工程
    initialState: ['1','10', '20', '100', '200'], //
    initialState: ['1', '100', '200'], //
    targetState: null,
    successMsg: '已打开!',
    checkMessage: '当前工程状态不符合条件,请确认工程状态后再操作!',
    requiresRow: true,
    openFile: async ({row}) => {
      orderInfo.optimizeData.optimalResults=null
      orderInfo.optimizeData.originalFilm=null
      const projectNumber = row.projectNumber;
      const thickness = row.thickness;
      const glassType = row.glassType;
      const quantity = row.quantity;
      const area = row.area;
      const optimizeState = row.optimizeState;
      await router.push({
        name: 'optimizeInfo',
        params: {
@@ -131,14 +136,16 @@
          thickNess: thickness,
          model: glassType,
          quantity: quantity,
          area: area
          area: area,
          optimizeState:optimizeState
        }
      });
    }
  },
  {
    code: 'compute', // 打开模拟计算操作
    initialState: ['1', '2'], //
    initialState: '1',
    temperingState: '0',
    targetState: null,
    successMsg: '模拟计算已启动!',
    checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!',
@@ -150,7 +157,7 @@
  },
  {
    code: 'optimizeTypography',
    initialState: ['10', '20','100'], //
    initialState: ['1','100'], //
    targetState: null,
    successMsg: '优化排版已启动!',
    checkMessage: '当前工程状态不符合优化排版条件,请确认工程状态后再操作!',
@@ -159,44 +166,60 @@
      const projectNumber = row.projectNumber;
      const thickness = row.thickness;
      const glassType = row.glassType;
      const quantity = row.quantity;
      const area = row.area;
      const optimizeState = row.optimizeState;
      await router.push({
        name: 'optimizeInfo',
        params: {
          projectNo: projectNumber,
          thickNess: thickness,
          model: glassType
          model: glassType,
          quantity: quantity,
          area: area,
          optimizeState:optimizeState
        }
      });
    }
  },
  {
    code: 'undoCompute',
    initialState: '10',
    targetState: 2,
    initialState: 1,
    temperingState: 1,
    targetState: 0,
    targetStates: 0,
    successMsg: '撤销模拟计算成功,数据已更新!',
    checkMessage: '当前工程状态不符合撤销模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'undoOptimize',
    initialState: '20',
    targetState: 10,
    initialState: 1,
    optimizeState: 1,
    targetState: 0,
    targetStates: 0,
    successMsg: '撤销优化成功,数据已更新!',
    checkMessage: '当前工程状态不符合撤销优化条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'production',
    initialState: '20',
    initialState: 1,
    temperingState: 1,
    optimizeState: 1,
    targetState: 100,
    targetStates: 0,
    successMsg: '设置成功,允许生产!',
    checkMessage: '当前工程状态不符合允许生产条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'novisible',
    initialState: '100',
    targetState: 20,
    initialState: 100,
    temperingState: 1,
    optimizeState: 1,
    targetState: 1,
    targetStates: 0,
    successMsg: '设置成功,生产不可见!',
    checkMessage: '当前工程状态不符合生产不可见条件,请确认工程状态后再操作!',
    requiresRow: true,
@@ -211,7 +234,7 @@
  },
  {
    code: 'delProject',
    initialState: ['1', '2', '10', '20', '100'],
    initialState: ['1', '100'],
    targetState: null,
    successMsg: '工程删除成功!',
    checkMessage: '当前工程状态不符合删除条件,请确认工程状态后再操作!',
@@ -243,11 +266,8 @@
function getOriginalState(targetState) {
  // 根据工程状态返回对应的原始状态
  const stateMapping = {
    2: '10',
    10: '20',
    100: '200',
    200: '100',
    1: ['2', '10', '20'],
    1: '100',
    100: '1'
  };
  return stateMapping[targetState] || targetState;
}
@@ -280,7 +300,21 @@
          return;
        }
        if (config.code === 'compute') {
          config.actionFunction({row});
          if(row.state===1 && row.temperingState===0){
            config.actionFunction({row});
          }else{
            ElMessage.warning(config.checkMessage);
          }
          return;
        }
        else if (config.code === 'openProject') {
          handleSameDataOperation(row).then(({isRoutesEqual}) => {
            if (!isRoutesEqual) {
              config.openFile({row});
              ElMessage.success(config.successMsg);
            }
          });
          return;
        }
        // 添加确认提示弹窗,询问用户是否进行当前操作
@@ -312,50 +346,60 @@
              return;
            }
            deleteProject(row.projectNumber, config);
          } else if (!checkOperationCondition(config, row)) {
            ElMessage.warning(config.checkMessage);
            return;
          } else {
            if (config.code === 'openProject') {
              handleSameDataOperation(row).then(({isRoutesEqual}) => {
                if (!isRoutesEqual) {
                  config.openFile({row});
                  ElMessage.success(config.successMsg);
                }
              });
            } else if (config.code === 'compute') {
              config.actionFunction({row});
            } else  if (config.code === 'optimizeTypography') {
          }else {
            if (config.code === 'optimizeTypography') {
              handleSameDataOperation(row).then(({isRoutesEqual}) => {
                if (!isRoutesEqual) {
                  config.Typography({row});
                  ElMessage.success(config.successMsg);
                  return;
                }
              });
            }
            else {
              row.state = config.targetState;
              let code=0
              if(config.code === 'undoCompute'){
                if(row.temperingState==1&&row.state===1){
                  row.temperingState = config.targetStates;
                  code=1
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }else if(config.code === 'undoOptimize'){
                if(row.optimizeState==1&&row.state===1){
                  row.optimizeState = config.targetStates;
                  code=2
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
              else if(config.code === 'production'){
                if(row.temperingState==1&&row.optimizeState===1&&row.state===1){
                  row.state = config.targetState;
                  code=3
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
              else if(config.code === 'novisible'){
                if(row.state===100){
                  row.state = config.targetState;
                  code=4
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
              const index = produceList.value.findIndex(item => item === row);
              if (index !== -1) {
                produceList.value.splice(index, 1, {...row});
                xGrid.value.reloadData(produceList.value);
              }
              if(config.code === 'undoCompute'){
                code=1
              }else if(config.code === 'undoOptimize'){
                code=2
              }
              else if(config.code === 'production'){
                code=3
              }
              else if(config.code === 'novisible'){
                code=4
              }
              else if(config.code === 'InitializeProject'){
                code=5
              }
              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,code, config.successMsg);
              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,config.targetStates,code, config.successMsg);
            }
          }
        }).catch(() => {
@@ -380,20 +424,28 @@
};
// 公共处理函数,处理相同数据时的操作,并返回targetRoute对象(右键菜单和双击打开)
const handleSameDataOperation = async ({projectNumber, thickness, glassType}) => {
const handleSameDataOperation = async ({projectNumber, thickness, glassType,quantity,area,optimizeState}) => {
  const targetRoute = {
    name: 'optimizeInfo',
    params: {
      projectNo: projectNumber,
      thickNess: String(thickness),
      model: glassType
      model: glassType,
      quantity: quantity,
      area: area,
      optimizeState:optimizeState
    }
  };
  const currentRoute = router.currentRoute.value;
  console.log(router.currentRoute.value)
  console.log(targetRoute)
  const isRoutesEqual = currentRoute.name === targetRoute.name &&
      currentRoute.params.projectNo === targetRoute.params.projectNo &&
      currentRoute.params.thickNess === targetRoute.params.thickNess &&
      currentRoute.params.model === targetRoute.params.model;
      parseFloat(currentRoute.params.thickNess) === parseFloat(targetRoute.params.thickNess) &&
      currentRoute.params.model === targetRoute.params.model &&
      parseInt(currentRoute.params.quantity) === parseInt(targetRoute.params.quantity) &&
      parseFloat(currentRoute.params.area) === parseFloat(targetRoute.params.area)&&
      parseFloat(currentRoute.params.optimizeState) === parseFloat(targetRoute.params.optimizeState);
  if (isRoutesEqual) {
    handleConfirm();
  }
@@ -428,12 +480,13 @@
  }
}
function updateProjectStateAndHandleResponse(row, projectNumber, targetState,code, successMsg) {
function updateProjectStateAndHandleResponse(row, projectNumber, targetState,targetStates,code, successMsg) {
  const updateParams = {
    projectNumber: projectNumber,
    stateToUpdate: targetState
    stateToUpdate: targetState,
    targetStates: targetStates
  };
  request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${code}`, updateParams, {
  request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${targetStates}/${code}`, updateParams, {
    headers: {
      'Content-Type': 'application/json'
    }
@@ -497,7 +550,7 @@
    value: '1',
    label: '初始状态,1',
  },
  {
  /*{
    value: '2',
    label: '第一次优化,2',
  },
@@ -508,7 +561,7 @@
  {
    value: '20',
    label: '优化完成,20',
  },
  },*/
  {
    value: '100',
    label: '生产可见,100',
@@ -629,6 +682,7 @@
  const params = buildRequestParams();
  request.post(`/glassOptimize/optimizeProjectMange/${params.startSelectTime}/${params.endSelectTime}`, filterData.value).then((res) => {
    if (res.code == 200) {
      console.log(res.data.data)
      produceList.value = deepClone(res.data.data);
      gridOptions.data = produceList.value;
      xGrid.value.loadData(produceList.value);
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue
@@ -17,6 +17,7 @@
const props = defineProps({
  projectNo : String,
  project: null,
  state:null,
  data: {
    type: Array,
    default: () => []
@@ -235,29 +236,47 @@
const handleSave = () => {
  if (props.data) {
    console.log(props.data)
  if(props.state==3){
    let projectData = ref({
      projectdetail: props.data.data[0].glass_details,
      ratioResult: props.data.data[0].ratioResult,
      rackinfos: props.data.data[0].rackinfos,
      resultSum: props.data.data[0].resultSum,
      guidance: props.data.data[0].guidance,
      userName : username,
      inputValues:inputValues
    })
    request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => {
      if (res.code == 200 && res.data === true) {
        ElMessage.success(t('basicData.msg.saveSuccess'))
      } else {
        ElMessage.warning(res.msg)
      }
    })
      let projectData = ref({
        inputValues:inputValues,
        userName : username,
        state:props.state
      })
      request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => {
        if (res.code == 200 && res.data === true) {
          ElMessage.success(t('basicData.msg.saveSuccess'))
        } else {
          ElMessage.warning(res.msg)
        }
      })
  }else{
    if (props.data) {
      let projectData = ref({
        projectdetail: props.data.data[0].glass_details,
        ratioResult: props.data.data[0].ratioResult,
        rackinfos: props.data.data[0].rackinfos,
        resultSum: props.data.data[0].resultSum,
        guidance: props.data.data[0].guidance,
        userName : username,
        inputValues:inputValues,
        state:props.state
      })
      request.post(`/glassOptimize/simulationSave`, projectData.value).then((res) => {
        if (res.code == 200 && res.data === true) {
          ElMessage.success(t('basicData.msg.saveSuccess'))
        } else {
          ElMessage.warning(res.msg)
        }
      })
    }
  }
}
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/GlassInventory.vue
@@ -5,7 +5,9 @@
import {ElMessage, ElMessageBox} from "element-plus";
import {useRoute} from "vue-router";
import {addListener, toolbarButtonClickEvent} from "@/hook/mouseMove";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
const { t } = useI18n()
const orderInfo = useOrderInfoStore()
const xGrid = ref()
const gridOptions = reactive({
@@ -38,7 +40,7 @@
  columns:[
    {type:'seq',fixed:"left", title:' ', width: 50},
    {type: 'checkbox', fixed: "left", title: t('basicData.check'), width: 80},
    {type: 'checkbox', fixed: "left", title: t('basicData.check'),  width: 80},
    {field: 'id', title: '物料编码',},
    {field:'width',editRender: { name: 'input',attrs: {disabled:true}}, title: t('order.width'),},
    {field: 'height',editRender: { name: 'input',attrs: {disabled:true}},title: t('order.height')},
@@ -71,7 +73,7 @@
  },
})
const emit = defineEmits(['select-trimming']);
const emit = defineEmits(['select-trimming'],['checkboxChange']);
// 右键菜单
const operationConfigs = [
  {
@@ -161,7 +163,7 @@
let type = ref(1);
const selectMaterialStore = async () =>{
  request.get(`/glassOptimize/materialStore/${thickness.value}/${model.value}/${projectNo}?type=${type.value}`).then((res) => {
  request.get(`/glassOptimize/materialStore/${thickness.value}/${model.value}/${projectNo.value}?type=${type.value}`).then((res) => {
    if (Number(res.code) === 200) {
      const rawData = res.data.data;
      const edgeTrimming = res.data.edgeTrimming;
@@ -211,6 +213,15 @@
          gridOptions.columns[10].editRender.attrs.disabled=true
          gridOptions.columns[11].editRender.attrs.disabled=true
        }
        if(orderInfo.optimizeData.originalFilm!==null){
          formattedData.forEach(item => {
            orderInfo.optimizeData.originalFilm.forEach(items => {
              if(item.id===items.stockCode){
                item.processingQuantity=items.count
              }
            });
          });
        }
        xGrid.value.loadData(formattedData);
        gridOptions.data = formattedData;
      } else {
@@ -225,7 +236,12 @@
onMounted(() => {
  addListener(xGrid.value,gridOptions)
  if(route.params.projectNo!=null){
    projectNo=route.params.projectNo
    projectNo.value=route.params.projectNo
    selectMaterialStore();
  }else if(orderInfo.projectNo!==null){
    projectNo.value=orderInfo.projectNo.projectNo
    thickness.value=orderInfo.projectNo.thickNess
    model.value=orderInfo.projectNo.model
    selectMaterialStore();
  }
@@ -301,6 +317,11 @@
};
const checkboxChanges= () => {
  return xGrid.value.getCheckboxRecords();
}
defineExpose({checkboxChanges})
</script>
<template>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -9,7 +9,7 @@
        @click="selectLayout(layoutIndex)"
        :class="{ 'selected': selectedLayoutIndex === layoutIndex }"
      >
        {{ layout.width }} × {{ layout.height }} × {{ layout.SameCount }}
        {{ layout.width }} × {{ layout.height }} × {{ layout.quantity  }}
      </div>
    </div>
@@ -30,27 +30,27 @@
        <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
          <!-- 灰色矩形 -->
          <div
            v-for="(rect, rectIndex) in layout.rects.filter(r => r.isRemain)"
            v-for="(glassDetail, rectIndex) in layout.glassDetails.filter(r => r.isRemain)"
            :key="`gray-${rectIndex}`"
            :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
            class="layout-rect"
            :style="rectStyle(rect, layoutIndex)"
            @contextmenu.prevent="handleGrayRectRightClick(layoutIndex, rectIndex,rect)"
            class="layout-glassDetail"
            :style="rectStyle(glassDetail, layoutIndex)"
            @contextmenu.prevent="handleGrayRectRightClick(layoutIndex, rectIndex,glassDetail)"
          >
<!--            <div class="rect-content">
              <div class="size">{{ rect.w }}×{{ rect.h }}</div>
              <div v-if="showJiaHao" class="jia-hao">{{ rect.JiaHao }}</div>
              <div v-if="showProcessId" class="liuchengka">{{ rect.liuchengka }}</div>
<!--            <div class="glassDetail-content">
              <div class="size">{{ glassDetail.width }}×{{ glassDetail.height }}</div>
              <div v-if="showJiaHao" class="jia-hao">{{ glassDetail.JiaHao }}</div>
              <div v-if="showProcessId" class="liuchengka">{{ glassDetail.liuchengka }}</div>
            </div>-->
          </div>
          <!-- 蓝色矩形 -->
          <div
            v-for="(rect, rectIndex) in layout.rects.filter(r => !r.isRemain)"
            v-for="(glassDetail, rectIndex) in layout.glassDetails.filter(r => !r.isRemain)"
            :key="`blue-${rectIndex}`"
            :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
            class="layout-rect"
            :style="rectStyle(rect, layoutIndex)"
            class="layout-glassDetail"
            :style="rectStyle(glassDetail, layoutIndex)"
            @contextmenu.prevent="handleRectRightClick(layoutIndex, rectIndex)"
            @mousedown="handleRectDragStart(layoutIndex, rectIndex)"
            @mousemove="handleRectDragging"
@@ -58,11 +58,11 @@
            @mouseleave="handleRectDragEnd"
            @click="handleRectClick(layoutIndex, rectIndex)"
          >
            <div class="rect-content">
              <div class="size">{{ rect.w }}×{{ rect.h }}</div>
            <div class="glassDetail-content">
              <div class="size">{{ glassDetail.realWidth }}×{{ glassDetail.realHeight }}</div>
              <div>{{rectIndex }}</div>
              <div v-if="showJiaHao" class="jia-hao">{{ rect.JiaHao }}</div>
              <div v-if="showProcessId" class="liuchengka">{{ rect.liuchengka }}</div>
              <div v-if="showJiaHao" class="jia-hao">{{ glassDetail.rackNo }}</div>
              <div v-if="showProcessId" class="liuchengka">{{ glassDetail.processId }}</div>
            </div>
          </div>
        </div>
@@ -99,9 +99,10 @@
const rectsElements = ref({});
const focusIndex = ref(null);
const layouts = ref([]);
const layoutsHead = ref();
const panelClass = ref('');
const panelStyle = ref(props.style);
const rectClass = ref('layout-rect');
const rectClass = ref('layout-glassDetail');
const selectedLayoutIndex = ref(0);
const currentRect = ref(null);
const dragging = ref(false);
@@ -114,17 +115,17 @@
//保存调整
const submitLayouts = async () => {
  layouts.value.forEach(layout => {
    layout.rects.forEach(rect => {
      rect.x = Math.round(rect.x);
      rect.y = Math.round(rect.y);
      rect.w = Math.round(rect.w);
      rect.h = Math.round(rect.h);
    layout.glassDetails.forEach(glassDetail => {
      glassDetail.x = Math.round(glassDetail.x);
      glassDetail.y = Math.round(glassDetail.y);
      glassDetail.width = Math.round(glassDetail.width);
      glassDetail.height = Math.round(glassDetail.height);
    });
  });
  const savedProjectNo = localStorage.getItem('projectNo');
  const processId = savedProjectNo;
  const Layouts = layouts.value;
  request.post(`/glassOptimize/updateOptimizeResult/${processId}`, JSON.stringify({ Layouts }), {
  layoutsHead.value.Layouts=layouts.value
  request.post(`/glassOptimize/updateOptimizeResult/${processId}`, layoutsHead.value, {
    headers: {
      'Content-Type': 'application/json'
    }
@@ -189,8 +190,8 @@
      const newRect = {
        x: 0,
        y: 0,
        w: values[0],
        h: values[1],
        width: values[0],
        height: values[1],
        isRemain: false
      };
      addNewRect(layoutIndex, newRect);
@@ -207,7 +208,7 @@
  if (bestFitPosition) {
    newRect.x = bestFitPosition.x;
    newRect.y = bestFitPosition.y;
    layout.rects.push(newRect);
    layout.glassDetails.push(newRect);
    adjustGrayRectangles(layoutIndex);
  } else {
    ElMessage.warning('无法放置,没有足够的空间');
@@ -217,21 +218,21 @@
//添加成品判断是否可以放下
const findBestFitPosition = (layoutIndex, newRect) => {
  const layout = layouts.value[layoutIndex];
  const obstacles = layout.rects.filter(r => !r.isRemain);
  const obstacles = layout.glassDetails.filter(r => !r.isRemain);
  let bestFit = null;
  let minAreaDifference = Infinity;
  const remainingAreas = calculateRemainingAreas(layout.width, layout.height, obstacles);
  remainingAreas.forEach(area => {
    if (newRect.w <= area.w && newRect.h <= area.h) {
      const areaDifference = Math.abs(area.w * area.h - newRect.w * newRect.h);
    if (newRect.width <= area.width && newRect.height <= area.height) {
      const areaDifference = Math.abs(area.width * area.height - newRect.width * newRect.height);
      if (areaDifference < minAreaDifference) {
        minAreaDifference = areaDifference;
        bestFit = {
          x: area.x,
          y: area.y,
          w: newRect.w,
          h: newRect.h
          width: newRect.width,
          height: newRect.height
        };
      }
    }
@@ -243,14 +244,12 @@
//版图内容样式加载
const layoutContainerStyle = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const scale = Math.min(
    (props.gw - 100) / layout.width,
    (props.gh - 100) / layout.height
  const scale = Math.min(0.25
  );
  return {
    position: 'absolute',
    left: `${(props.gw - layout.width * scale) / 2}px`,
    top: `${(props.gh - layout.height * scale) / 2}px`,
    left: `20px`,
    top: `140px`,
    width: `${layout.width * scale}px`,
    height: `${layout.height * scale}px`,
    overflow: 'visible',
@@ -262,14 +261,12 @@
//版图内容头部样式加载
const layoutInfoStyle = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const scale = Math.min(
    (props.gw - 100) / layout.width,
    (props.gh - 100) / layout.height
  const scale = Math.min(0.25
  );
  return {
    position: 'absolute',
    left: `${(props.gw - layout.width * scale) / 2}px`,
    top: `${(props.gh - layout.height * scale) / 2 - 45}px`,
    left: `20px`,
    top: `100px`,
    background: 'none',
    textAlign: 'center',
    zIndex: 1000
@@ -277,23 +274,21 @@
};
//版图内容小片样式加载
const rectStyle = (rect, layoutIndex) => {
const rectStyle = (glassDetail, layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const scale = Math.min(
    (props.gw - 100) / layout.width,
    (props.gh - 100) / layout.height
  const scale = Math.min(0.25
  );
  return {
    position: 'absolute',
    left: `${rect.x * scale}px`,
    bottom: `${rect.y * scale}px`,
    width: `${rect.w * scale}px`,
    height: `${rect.h * scale}px`,
    backgroundColor: rect.isRemain ? '#f0f0f0' : themeColor.value,
    left: `${glassDetail.x * scale}px`,
    bottom: `${glassDetail.y * scale}px`,
    width: `${glassDetail.width * scale}px`,
    height: `${glassDetail.height * scale}px`,
    backgroundColor: glassDetail.isRemain ? '#f0f0f0' : themeColor.value,
    border: '1px solid #000',
    cursor: 'pointer',
    draggable: !rect.isRemain,
    zIndex: rect.isRemain ? 1 : 2
    draggable: !glassDetail.isRemain,
    zIndex: glassDetail.isRemain ? 1 : 2
  };
};
@@ -305,8 +300,8 @@
//小片右键菜单功能
const handleRectRightClick = (layoutIndex, rectIndex) => {
  const rect = layouts.value[layoutIndex].rects[rectIndex];
  if (rect.isRemain) return;
  const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
  if (glassDetail.isRemain) return;
  const contextMenu = document.createElement('div');
  contextMenu.className = 'context-menu';
@@ -440,9 +435,9 @@
};
//余料右键菜单功能
const handleGrayRectRightClick = (layoutIndex, rectIndex,rects) => {
  //const rect = rects[rectIndex];
  if (!rects.isRemain) return;
const handleGrayRectRightClick = (layoutIndex, rectIndex,glassDetails) => {
  //const glassDetail = glassDetails[rectIndex];
  if (!glassDetails.isRemain) return;
  const contextMenu = document.createElement('div');
  contextMenu.className = 'context-menu';
@@ -488,8 +483,8 @@
//小片鼠标按下事件
const handleRectDragStart = (layoutIndex, rectIndex) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  if (rect.isRemain) return;
  const glassDetail = layout.glassDetails[rectIndex];
  if (glassDetail.isRemain) return;
  dragging.value = true;
  dragRect.value = { layoutIndex, rectIndex };
@@ -506,7 +501,7 @@
  const layoutIndex = dragRect.value.layoutIndex;
  const rectIndex = dragRect.value.rectIndex;
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const glassDetail = layout.glassDetails[rectIndex];
  const scale = Math.min(
    (props.gw - 100) / layout.width,
    (props.gh - 100) / layout.height
@@ -515,11 +510,11 @@
  const deltaX = event.clientX - dragStartPos.value.x;
  const deltaY = event.clientY - dragStartPos.value.y;
  const newRect = { ...rect };
  const newRect = { ...glassDetail };
  newRect.x += deltaX / scale;
  newRect.y += deltaY / scale;
  const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
  const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
  let isValidMove = true;
  otherRects.forEach(otherRect => {
@@ -529,14 +524,14 @@
  });
  if (newRect.x < 0 || newRect.y < 0 ||
      newRect.x + newRect.w > layout.width ||
      newRect.y + newRect.h > layout.height) {
      newRect.x + newRect.width > layout.width ||
      newRect.y + newRect.height > layout.height) {
    isValidMove = false;
  }
  if (isValidMove) {
    rect.x = newRect.x;
    rect.y = newRect.y;
    glassDetail.x = newRect.x;
    glassDetail.y = newRect.y;
    dragStartPos.value = {
      x: event.clientX,
      y: event.clientY
@@ -550,15 +545,15 @@
  if (dragRect.value) {
    const layoutIndex = dragRect.value.layoutIndex;
    const rectIndex = dragRect.value.rectIndex;
    const rect = layouts.value[layoutIndex].rects[rectIndex];
    const glassDetail = layouts.value[layoutIndex].glassDetails[rectIndex];
    const layout = layouts.value[layoutIndex];
    const scale = Math.min(
      (props.gw - 100) / layout.width,
      (props.gh - 100) / layout.height
    );
    rect.x = Math.round(rect.x);
    rect.y = Math.round(rect.y);
    glassDetail.x = Math.round(glassDetail.x);
    glassDetail.y = Math.round(glassDetail.y);
    adjustAlignmentPosition(layoutIndex, rectIndex);
  }
@@ -568,43 +563,43 @@
const adjustAlignmentPosition = (layoutIndex, rectIndex) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const otherRects = layout.rects.filter((r, i) => i !== rectIndex);
  const glassDetail = layout.glassDetails[rectIndex];
  const otherRects = layout.glassDetails.filter((r, i) => i !== rectIndex);
  const threshold = Math.max(rect.w, rect.h) * 0.1;
  const threshold = Math.max(glassDetail.width, glassDetail.height) * 0.1;
  otherRects.forEach(otherRect => {
    // 水平对齐
    if (Math.abs(rect.x - otherRect.x) < threshold) {
      rect.x = Math.round((rect.x + otherRect.x) / 2);
    if (Math.abs(glassDetail.x - otherRect.x) < threshold) {
      glassDetail.x = Math.round((glassDetail.x + otherRect.x) / 2);
    }
    // 水平对齐右侧边缘
    if (Math.abs((rect.x + rect.w) - (otherRect.x + otherRect.w)) < threshold) {
      rect.x = Math.round((otherRect.x + otherRect.w - rect.w));
    if (Math.abs((glassDetail.x + glassDetail.width) - (otherRect.x + otherRect.width)) < threshold) {
      glassDetail.x = Math.round((otherRect.x + otherRect.width - glassDetail.width));
    }
    // 垂直对齐
    if (Math.abs(rect.y - otherRect.y) < threshold) {
      rect.y = Math.round((rect.y + otherRect.y) / 2);
    if (Math.abs(glassDetail.y - otherRect.y) < threshold) {
      glassDetail.y = Math.round((glassDetail.y + otherRect.y) / 2);
    }
    // 垂直对齐下边缘
    if (Math.abs((rect.y + rect.h) - (otherRect.y + otherRect.h)) < threshold) {
      rect.y = Math.round((otherRect.y + otherRect.h - rect.h));
    if (Math.abs((glassDetail.y + glassDetail.height) - (otherRect.y + otherRect.height)) < threshold) {
      glassDetail.y = Math.round((otherRect.y + otherRect.height - glassDetail.height));
    }
  });
  // 确保矩形不会超出布局边界
  rect.x = Math.max(0, rect.x);
  rect.y = Math.max(0, rect.y);
  rect.x = Math.min(rect.x, layout.width - rect.w);
  rect.y = Math.min(rect.y, layout.height - rect.h);
  glassDetail.x = Math.max(0, glassDetail.x);
  glassDetail.y = Math.max(0, glassDetail.y);
  glassDetail.x = Math.min(glassDetail.x, layout.width - glassDetail.width);
  glassDetail.y = Math.min(glassDetail.y, layout.height - glassDetail.height);
  // 调整后重新计算灰色余料
  adjustGrayRectangles(layoutIndex);
};
const mergeAdjacentGrayRects = (rects,totalWidth,totalHeight) => {
  const grayRects = rects.filter(r => r.isRemain);
  const grayRects2 = rects.filter(r => r.isRemain);
const mergeAdjacentGrayRects = (glassDetails,totalWidth,totalHeight) => {
  const grayRects = glassDetails.filter(r => r.isRemain);
  const grayRects2 = glassDetails.filter(r => r.isRemain);
  let merged = [];
  grayRects.sort((a, b) => {
@@ -621,44 +616,44 @@
      const current = grayRects[i];
    if (current.x === last.x + last.w &&
    if (current.x === last.x + last.width &&
        current.y === last.y &&
        current.h === last.h) {
      last.w += current.w;
        current.height === last.height) {
      last.width += current.width;
      last.x = Math.round(last.x);
      last.y = Math.round(last.y);
      last.w = Math.round(last.w);
      last.h = Math.round(last.h);
    } else if (current.y === last.y + last.h &&
      last.width = Math.round(last.width);
      last.height = Math.round(last.height);
    } else if (current.y === last.y + last.height &&
               current.x === last.x &&
               current.w === last.w) {
      last.h += current.h;
               current.width === last.width) {
      last.height += current.height;
      last.x = Math.round(last.x);
      last.y = Math.round(last.y);
      last.w = Math.round(last.w);
      last.h = Math.round(last.h);
      last.width = Math.round(last.width);
      last.height = Math.round(last.height);
    } else {
      merged.push({
        x: Math.round(current.x),
        y: Math.round(current.y),
        w: Math.round(current.w),
        h: Math.round(current.h),
        width: Math.round(current.width),
        height: Math.round(current.height),
        isRemain: true
      });
    }
  }
  const nonGray = rects.filter(r => !r.isRemain);
  const nonGray = glassDetails.filter(r => !r.isRemain);
  //删除原数组拼接新的小片跟余料
  rects.splice(0, rects.length, ...nonGray, ...merged);
  glassDetails.splice(0, glassDetails.length, ...nonGray, ...merged);
};
// 调整后重新计算灰色余料
const adjustGrayRectangles = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const rects = layout.rects;
  const glassDetails = layout.glassDetails;
  //小片的数据
  const nonGrayRects = rects.filter(rect => !rect.isRemain);
  const nonGrayRects = glassDetails.filter(glassDetail => !glassDetail.isRemain);
  //所有的小片余料坐标跟尺寸
  let remainingAreas = calculateRemainingAreas(layout.width, layout.height, nonGrayRects);
@@ -666,11 +661,11 @@
      new Set(remainingAreas.map(item => JSON.stringify(item)))
  ).map(item => JSON.parse(item));
  //余料的数据
  const currentGrayRects = rects.filter(r => r.isRemain);
  const currentGrayRects = glassDetails.filter(r => r.isRemain);
  //循环余料数据跟全部的对比
  currentGrayRects.forEach((_, index) => {
    if (index >= remainingAreas.length) {
      rects.splice(index, 1);
      glassDetails.splice(index, 1);
    }
  });
@@ -678,50 +673,50 @@
    if (index < currentGrayRects.length) {
      currentGrayRects[index].x = Math.round(area.x);
      currentGrayRects[index].y = Math.round(area.y);
      currentGrayRects[index].w = Math.round(area.w);
      currentGrayRects[index].h = Math.round(area.h);
      currentGrayRects[index].width = Math.round(area.width);
      currentGrayRects[index].height = Math.round(area.height);
    } else {
      rects.push({
      glassDetails.push({
        x: Math.round(area.x),
        y: Math.round(area.y),
        w: Math.round(area.w),
        h: Math.round(area.h),
        width: Math.round(area.width),
        height: Math.round(area.height),
        isRemain: true
      });
    }
  });
  mergeAdjacentGrayRects(rects,layout.width, layout.height);
  mergeAdjacentGrayRects(glassDetails,layout.width, layout.height);
};
//旋转方法
const rotateRect = (layoutIndex, rectIndex) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const originalState = { ...rect };
  const glassDetail = layout.glassDetails[rectIndex];
  const originalState = { ...glassDetail };
  const temp = rect.w;
  rect.w = rect.h;
  rect.h = temp;
  const temp = glassDetail.width;
  glassDetail.width = glassDetail.height;
  glassDetail.height = temp;
  const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
  const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
  let isValidRotation = true;
  otherRects.forEach(otherRect => {
    if (checkOverlap(rect, otherRect)) {
    if (checkOverlap(glassDetail, otherRect)) {
      isValidRotation = false;
    }
  });
  if (rect.x + rect.w > layout.width || rect.y + rect.h > layout.height) {
  if (glassDetail.x + glassDetail.width > layout.width || glassDetail.y + glassDetail.height > layout.height) {
    isValidRotation = false;
  }
  if (isValidRotation) {
    adjustGrayRectangles(layoutIndex);
  } else {
    rect.w = originalState.w;
    rect.h = originalState.h;
    glassDetail.width = originalState.width;
    glassDetail.height = originalState.height;
    ElMessage.warning('无法旋转,存在重叠或超出边界');
  }
};
@@ -729,21 +724,21 @@
//移动旋转方法
const moveRectAndRotate = (layoutIndex, rectIndex, direction) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const grayRects = layout.rects.filter(r => r.isRemain);
  const glassDetail = layout.glassDetails[rectIndex];
  const grayRects = layout.glassDetails.filter(r => r.isRemain);
  const temp = rect.w;
  rect.w = rect.h;
  rect.h = temp;
  const temp = glassDetail.width;
  glassDetail.width = glassDetail.height;
  glassDetail.height = temp;
  const canPlace = grayRects.some(grayRect => {
    return grayRect.w >= rect.w && grayRect.h >= rect.h;
    return grayRect.width >= glassDetail.width && grayRect.height >= glassDetail.height;
  });
  if (!canPlace) {
    const temp = rect.w;
    rect.w = rect.h;
    rect.h = temp;
    const temp = glassDetail.width;
    glassDetail.width = glassDetail.height;
    glassDetail.height = temp;
    ElMessage.warning('无法旋转,没有足够的空间');
    return;
  }
@@ -755,24 +750,24 @@
//移动方法
const moveRect = (layoutIndex, rectIndex, direction) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const originalState = { ...rect };
  const glassDetail = layout.glassDetails[rectIndex];
  const originalState = { ...glassDetail };
  let maxStep = 0;
  const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
  const obstacles = layout.glassDetails.filter(r => r.isRemain || r !== glassDetail);
  switch (direction) {
    case 'up':
      maxStep = getAvailableSpaceUp(rect, layout, obstacles);
      maxStep = getAvailableSpaceUp(glassDetail, layout, obstacles);
      break;
    case 'down':
      maxStep = getAvailableSpaceDown(rect, layout, obstacles);
      maxStep = getAvailableSpaceDown(glassDetail, layout, obstacles);
      break;
    case 'left':
      maxStep = getAvailableSpaceLeft(rect, layout, obstacles);
      maxStep = getAvailableSpaceLeft(glassDetail, layout, obstacles);
      break;
    case 'right':
      maxStep = getAvailableSpaceRight(rect, layout, obstacles);
      maxStep = getAvailableSpaceRight(glassDetail, layout, obstacles);
      break;
  }
@@ -783,39 +778,39 @@
  switch (direction) {
    case 'up':
      rect.y += maxStep;
      glassDetail.y += maxStep;
      break;
    case 'down':
      rect.y -= maxStep;
      glassDetail.y -= maxStep;
      break;
    case 'left':
      rect.x -= maxStep;
      glassDetail.x -= maxStep;
      break;
    case 'right':
      rect.x += maxStep;
      glassDetail.x += maxStep;
      break;
  }
  const otherRects = layout.rects.filter(r => !r.isRemain && r !== rect);
  const otherRects = layout.glassDetails.filter(r => !r.isRemain && r !== glassDetail);
  let isValidMove = true;
  otherRects.forEach(otherRect => {
    if (checkOverlap(rect, otherRect)) {
    if (checkOverlap(glassDetail, otherRect)) {
      isValidMove = false;
    }
  });
  if (rect.x < 0 || rect.y < 0 ||
      rect.x + rect.w > layout.width ||
      rect.y + rect.h > layout.height) {
  if (glassDetail.x < 0 || glassDetail.y < 0 ||
      glassDetail.x + glassDetail.width > layout.width ||
      glassDetail.y + glassDetail.height > layout.height) {
    isValidMove = false;
  }
  if (isValidMove) {
    adjustGrayRectangles(layoutIndex);
  } else {
    rect.x = originalState.x;
    rect.y = originalState.y;
    glassDetail.x = originalState.x;
    glassDetail.y = originalState.y;
    ElMessage.warning('无法移动,存在重叠或超出边界');
  }
};
@@ -823,23 +818,23 @@
//删除小片
const deleteRect = (layoutIndex, rectIndex) => {
  const layout = layouts.value[layoutIndex];
  layout.rects.splice(rectIndex, 1);
  layout.glassDetails.splice(rectIndex, 1);
  adjustGrayRectangles(layoutIndex);
};
//判断原片跟小片移动是否超出
const checkOverlap = (rect1, rect2) => {
  return !(rect1.x + rect1.w <= rect2.x ||
           rect1.x >= rect2.x + rect2.w ||
           rect1.y + rect1.h <= rect2.y ||
           rect1.y >= rect2.y + rect2.h);
  return !(rect1.x + rect1.width <= rect2.x ||
           rect1.x >= rect2.x + rect2.width ||
           rect1.y + rect1.height <= rect2.y ||
           rect1.y >= rect2.y + rect2.height);
};
//重新计算余料坐标以及尺寸1
const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
  let remaining = [{ x: 0, y: 0, w: totalWidth, h: totalHeight }];
  obstacles.forEach(rect => {
    remaining = cutRemainingAreas(remaining, rect,totalWidth,totalHeight);
  let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
  obstacles.forEach(glassDetail => {
    remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
  });
  return remaining;
};
@@ -853,32 +848,32 @@
        newRemaining.push({
          x: area.x,
          y: area.y,
          w: obstacle.x - area.x,
          h: area.h
          width: obstacle.x - area.x,
          height: area.height
        });
      }
      if (obstacle.x + obstacle.w < area.x + area.w) {
      if (obstacle.x + obstacle.width < area.x + area.width) {
        newRemaining.push({
          x: obstacle.x + obstacle.w,
          x: obstacle.x + obstacle.width,
          y: area.y,
          w: area.w - (obstacle.x + obstacle.w - area.x),
          h: area.h
          width: area.width - (obstacle.x + obstacle.width - area.x),
          height: area.height
        });
      }
      if (obstacle.y > area.y) {
        newRemaining.push({
          x: area.x,
          y: area.y,
          w: area.w,
          h: obstacle.y - area.y
          width: area.width,
          height: obstacle.y - area.y
        });
      }
      if (obstacle.y + obstacle.h < area.y + area.h ) {
      if (obstacle.y + obstacle.height < area.y + area.height ) {
          newRemaining.push({
            x: area.x,
            y: obstacle.y + obstacle.h,
            w: area.w,
            h: area.h - (obstacle.y + obstacle.h - area.y)
            y: obstacle.y + obstacle.height,
            width: area.width,
            height: area.height - (obstacle.y + obstacle.height - area.y)
          });
      }
@@ -892,13 +887,13 @@
//定义每个版图的综合内容
const getCurrentRectInfo = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[focusIndex.value?.rectIndex || 0];
  if (!rect) return '';
/*  const glassDetail = layout.glassDetails[focusIndex.value?.rectIndex || 0];
  if (!glassDetail) return '';*/
  const totalRects = layouts.value.length;
  const currentRectIndex = layoutIndex + 1;
  const width = layout.width;
  const height = layout.height;
  const percentage = ((rect.w / layout.width) * 100).toFixed(1) + '%';
  const percentage = (layout.usageRate * 100).toFixed(2) + '%';
  return `${currentRectIndex}/${totalRects} ${width}×${height} ×1 ${percentage}`;
};
@@ -910,56 +905,57 @@
//把传输的数据赋值
const updateLayout = () => {
  if (!layoutPanel.value) return;
  layouts.value = props.layoutData.Layouts;
  layoutsHead.value = props.layoutData;
  layouts.value = props.layoutData.layouts;
};
//向上移动计算坐标
const getAvailableSpaceUp = (rect, layout, obstacles) => {
  let maxSpace = layout.height - (rect.y + rect.h);
const getAvailableSpaceUp = (glassDetail, layout, obstacles) => {
  let maxSpace = layout.height - (glassDetail.y + glassDetail.height);
  obstacles.forEach(obstacle => {
    if (obstacle.y > rect.y + rect.h &&
        obstacle.x <= rect.x + rect.w &&
        obstacle.x + obstacle.w >= rect.x) {
      maxSpace = Math.min(maxSpace, obstacle.y - (rect.y + rect.h));
    if (obstacle.y > glassDetail.y + glassDetail.height &&
        obstacle.x <= glassDetail.x + glassDetail.width &&
        obstacle.x + obstacle.width >= glassDetail.x) {
      maxSpace = Math.min(maxSpace, obstacle.y - (glassDetail.y + glassDetail.height));
    }
  });
  return maxSpace;
};
//向下移动计算坐标
const getAvailableSpaceDown = (rect, layout, obstacles) => {
  let maxSpace = rect.y;
const getAvailableSpaceDown = (glassDetail, layout, obstacles) => {
  let maxSpace = glassDetail.y;
  obstacles.forEach(obstacle => {
    if (obstacle.y + obstacle.h < rect.y &&
        obstacle.x <= rect.x + rect.w &&
        obstacle.x + obstacle.w >= rect.x) {
      maxSpace = Math.min(maxSpace, rect.y - (obstacle.y + obstacle.h));
    if (obstacle.y + obstacle.height < glassDetail.y &&
        obstacle.x <= glassDetail.x + glassDetail.width &&
        obstacle.x + obstacle.width >= glassDetail.x) {
      maxSpace = Math.min(maxSpace, glassDetail.y - (obstacle.y + obstacle.height));
    }
  });
  return maxSpace;
};
//向左移动计算坐标
const getAvailableSpaceLeft = (rect, layout, obstacles) => {
  let maxSpace = rect.x;
const getAvailableSpaceLeft = (glassDetail, layout, obstacles) => {
  let maxSpace = glassDetail.x;
  obstacles.forEach(obstacle => {
    if (obstacle.x + obstacle.w < rect.x &&
        obstacle.y <= rect.y + rect.h &&
        obstacle.y + obstacle.h >= rect.y) {
      maxSpace = Math.min(maxSpace, rect.x - (obstacle.x + obstacle.w));
    if (obstacle.x + obstacle.width < glassDetail.x &&
        obstacle.y <= glassDetail.y + glassDetail.height &&
        obstacle.y + obstacle.height >= glassDetail.y) {
      maxSpace = Math.min(maxSpace, glassDetail.x - (obstacle.x + obstacle.width));
    }
  });
  return maxSpace;
};
//向右移动计算坐标
const getAvailableSpaceRight = (rect, layout, obstacles) => {
  let maxSpace = layout.width - (rect.x + rect.w);
const getAvailableSpaceRight = (glassDetail, layout, obstacles) => {
  let maxSpace = layout.width - (glassDetail.x + glassDetail.width);
  obstacles.forEach(obstacle => {
    if (obstacle.x > rect.x + rect.w &&
        obstacle.y <= rect.y + rect.h &&
        obstacle.y + obstacle.h >= rect.y) {
      maxSpace = Math.min(maxSpace, obstacle.x - (rect.x + rect.w));
    if (obstacle.x > glassDetail.x + glassDetail.width &&
        obstacle.y <= glassDetail.y + glassDetail.height &&
        obstacle.y + obstacle.height >= glassDetail.y) {
      maxSpace = Math.min(maxSpace, obstacle.x - (glassDetail.x + glassDetail.width));
    }
  });
  return maxSpace;
@@ -973,8 +969,8 @@
  const { layoutIndex, rectIndex } = focusIndex.value;
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[rectIndex];
  const obstacles = layout.rects.filter(r => r.isRemain || r !== rect);
  const glassDetail = layout.glassDetails[rectIndex];
  const obstacles = layout.glassDetails.filter(r => r.isRemain || r !== glassDetail);
  switch (event.key) {
    case 'ArrowUp':
@@ -1027,20 +1023,20 @@
const mirrorLayoutX = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const width = layout.width;
  const rects = [...layout.rects]; // 创建副本避免直接修改
  const glassDetails = [...layout.glassDetails]; // 创建副本避免直接修改
  rects.forEach(rect => {
  glassDetails.forEach(glassDetail => {
    // 计算X镜像后的坐标
    const newX = width - rect.x - rect.w;
    const newY = rect.y;
    const newX = width - glassDetail.x - glassDetail.width;
    const newY = glassDetail.y;
    // 更新矩形位置
    rect.x = newX;
    rect.y = newY;
    glassDetail.x = newX;
    glassDetail.y = newY;
  });
  // 更新布局
  layout.rects = rects;
  layout.glassDetails = glassDetails;
  adjustGrayRectangles(layoutIndex);
};
@@ -1048,19 +1044,19 @@
const mirrorLayoutY = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const height = layout.height;
  const rects = [...layout.rects]; // 创建副本避免直接修改
  const glassDetails = [...layout.glassDetails]; // 创建副本避免直接修改
  rects.forEach(rect => {
  glassDetails.forEach(glassDetail => {
    // 计算Y镜像后的坐标
    const newX = rect.x;
    const newY = height - rect.y - rect.h;
    const newX = glassDetail.x;
    const newY = height - glassDetail.y - glassDetail.height;
    // 更新矩形位置
    rect.y = newY;
    glassDetail.y = newY;
  });
  // 更新布局
  layout.rects = rects;
  layout.glassDetails = glassDetails;
  adjustGrayRectangles(layoutIndex);
};
@@ -1099,7 +1095,7 @@
  margin-top: 50px;
}
.layout-rect {
.layout-glassDetail {
  user-select: none;
}
@@ -1118,7 +1114,7 @@
  font-weight: bold;
}
.rect-content {
.glassDetail-content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizeCompute.vue
@@ -1,12 +1,15 @@
<script setup>
import {ref, computed} from "vue";
import {ref, computed, watch} from "vue";
import {Connection} from "@element-plus/icons-vue";
import {useRoute} from "vue-router";
import {useRoute, useRouter} from "vue-router";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
const router = useRouter()
const orderInfo = useOrderInfoStore()
const props = defineProps({
  quantity : null,
  area:null
  area:null,
  optimizeData:null
});
//计时器
let seconds = ref(0);
@@ -16,10 +19,21 @@
//优化进度条
let progress = ref(0);
let quantity = ref(0);
let area = ref(0);
let optimizeData = ref();
let originalFilm = ref([]);
let totalUtilizationRate = ref('');
let tailPieceRate = ref('');
const mockData=ref();
//优化次数;时长;效率
let progressValue1 = ref(10);
let progressValue2 = ref(1000);
let progressValue3 = ref(50);
const formattedTime = computed(() => {
  const minutes = Math.floor(seconds.value / 60);
@@ -27,18 +41,200 @@
  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
});
const startTimer = () => {
  console.log(props)
  if (!isRunning.value) {
    intervalId = setInterval(() => {
      seconds.value++;
      progress.value += 10;
      if (progress.value >= 100) {
        progress.value = 100;
        clearInterval(intervalId);
      }
    }, 1000);
    isRunning.value = true;
  if(progress.value>0){
    seconds.value = 0;
    progress.value = 0;
    originalFilm.value=[]
    totalUtilizationRate.value=''
    tailPieceRate.value=''
    isRunning.value = false;
  }
  if(props.optimizeData!=null){
    document.getElementById("start").disabled=true
    document.getElementById("complete").style.display="none"
    console.log(props.optimizeData)
    if (!isRunning.value) {
      isRunning.value = true;
      intervalId = setInterval(() => {
        seconds.value++;
        progress.value += 1;
        if (progress.value >= 100) {
          progress.value = 100;
          clearInterval(intervalId);
        }
      }, 1000);
    }
    mockData.value = {
      code: 200,
      data: [{
        "projectNo":"P25041001",
        "totalQuantity":1,
        "glassTotalQuantity":1,
        "glassTotalArea":1,
        "avgCutRate":1,
        "lastCutRate":1,
        "validCutRate":1,
        "layouts":[
          {
            "stockId":3,
            "usageRate":0.9,
            "width":4500,
            "height":2440,
            "stockCode":11,
            "upTrim":12,
            "downTrim":12,
            "leftTrim":12,
            "rightTrim":12,
            "quantity":1,
            "glassQuantity":6,
            "glassArea":45,
            "materialType":1,
            "mergeID":1,
            "glassDetails":[
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":1,
                "markIcon":"",
                "x":0,
                "y":0,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":2,
                "markIcon":"",
                "x":2070,
                "y":0,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":3,
                "markIcon":"",
                "x":0,
                "y":725,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":4,
                "markIcon":"",
                "x":2070,
                "y":725,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":5,
                "markIcon":"",
                "x":0,
                "y":1450,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":false,
                "width":2070,
                "height":725,
                "realWidth":2070,
                "realHeight":725,
                "layer":1,
                "totalLayer":2,
                "orderSort":1,
                "processId":"NG22091408A06",
                "stockSort":1,
                "polySort":6,
                "markIcon":"",
                "x":2070,
                "y":1450,
                "patchState":0,
                "isRotate":0,
                "rackNo":1,
                "glassPoint":{}
              },
              {"isRemain":true,
                "width":2070,
                "height":265,
                "x":0,
                "y":2175
              },
              {"isRemain":true,
                "width":2070,
                "height":265,
                "x":2070,
                "y":2175
              },
              {"isRemain":true,
                "width":360,
                "height":2440,
                "x":4140,
                "y":0
              }]
          }
        ]}]
    }
    }
};
const pauseTimer = () => {
  if (isRunning.value) {
@@ -47,11 +243,49 @@
  }
};
const resetTimer = () => {
  clearInterval(intervalId);
  router.push({path: '/main/glassOptimize/Optimization'})
  /*clearInterval(intervalId);
  isRunning.value = false;
  seconds.value = 0;
  progress.value = 0;
  progress.value = 0;*/
};
watch(
    ()=> [progress.value],
    ([newValue])=> {
      if(progress.value===10){
        orderInfo.optimizeData.optimalResults=mockData.value.data[0]
        mockData.value.data[0].layouts.forEach(items=>{
          // 根据唯一标识(如 id)查找是否已存在
          const existingItem = originalFilm.value.find(item => item["width"] === items["width"]&&item["height"] === items["height"]);
          if (existingItem) {
            // 存在:数量加1(假设字段为 count)
            existingItem.count += 1;
          } else {
            // 不存在:新增到数组(初始化 count=1)
            const array={
              width:items["width"],
              height:items["height"],
              upTrim:items["upTrim"],
              downTrim:items["downTrim"],
              leftTrim:items["leftTrim"],
              rightTrim:items["rightTrim"],
              stockCode:items["stockCode"],
              count:1
            }
            originalFilm.value.push(array);
          }
        })
        orderInfo.optimizeData.originalFilm=originalFilm.value
        totalUtilizationRate.value=mockData.value.data[0].avgCutRate*100
        tailPieceRate.value=mockData.value.data[0].layouts*100
        pauseTimer()
        document.getElementById("complete").style.display="block"
        document.getElementById("start").disabled=false
      }
    });
</script>
@@ -62,17 +296,17 @@
        <span style="margin-left: -20px;">需切成品</span><br>
        <div>
          <span>总面积(m2):</span>
          <vxe-input class="input" disabled placeholder=""></vxe-input>
          <span>总数量(片):{{props.quantity}}</span>
          <vxe-input class="input" disabled placeholder=""></vxe-input>
          <vxe-input class="input"  v-model="props.area" disabled ></vxe-input>
          <span>总数量(片):</span>
          <vxe-input class="input" v-model="props.quantity" disabled ></vxe-input>
          <span>优化时长(秒):</span>
          <span class="time-display">{{ formattedTime }}</span>
          <el-button type="primary" style="margin-left: 20px" @click="startTimer">开始优化</el-button>
          <el-button class="buttons" type="primary" @click="pauseTimer">暂停</el-button>
          <el-button class="buttons" type="primary" @click="resetTimer">完成</el-button>
          <el-button id="start" type="primary" style="margin-left: 20px" @click="startTimer">开始优化</el-button>
<!--          <el-button class="buttons" type="primary" @click="pauseTimer">暂停</el-button>-->
          <el-button id="complete" class="buttons" type="primary" style="display: none" @click="resetTimer">完成</el-button>
        </div>
        <br>
        <div style="display: flex;margin-top: -10px">
<!--        <div style="display: flex;margin-top: -10px">
          <span>方案池 优化次数:</span>
          <el-slider v-model="progressValue1" :min="2" :max="20" size="small" style="max-width: 200px;"></el-slider>
          <span>单次优化时长:</span>
@@ -80,7 +314,7 @@
          <span>钢化效率优先:</span>
          <el-slider v-model="progressValue3" :show-tooltip="false" size="small" style="max-width: 200px;"></el-slider>
          <span>切裁率优先</span>
        </div>
        </div>-->
      </div>
    </el-header>
  </div>
@@ -96,15 +330,15 @@
                   striped-flow
                   duration="45"/>
    </div>
    <div style="height: 100px; margin-top: 20px; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
      <span style="font-weight: bold">耗用原片</span>
    </div>
    <div style="height: 130px; margin-top: 20px;  display: flex; border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
      <span style="font-weight: bold">当前结果</span>
      <div style="margin-top: 5%">
    <div style="height: 250px; margin-top: 20px;   border: 2px solid #e6e6e6; padding: 10px; border-radius: 5px;">
      <span style="font-weight: bold">当前结果</span><br/>
      <div v-for="(item, index) in originalFilm">
          <div>{{index+1}}:{{item.width}}x{{item.height}}={{item.count}}</div>
      </div>
      <div style="margin-top: 2%">
        <span>产生时间:{{ formattedTime }}</span>
        <span style="margin-left: 20px">总利用率:0.0%</span>
        <span style="margin-left: 20px">尾片:</span>
        <span style="margin-left: 20px">总利用率:{{totalUtilizationRate}}%</span>
        <span style="margin-left: 20px">尾片:{{tailPieceRate}}%</span>
      </div>
    </div>
  </div>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue
@@ -9,9 +9,13 @@
import request from "@/utils/request";
import {ElMessage, ElMessageBox} from "element-plus";
import {useRoute} from 'vue-router';
import useUserInfoStore from "@/stores/userInfo";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
const {t} = useI18n()
const { t } = useI18n();
const userStore = useUserInfoStore()
const orderInfo = useOrderInfoStore()
const username = userStore.user.userName
const xGrid = ref()
const gridOptions = reactive({
@@ -170,7 +174,7 @@
      sortable: true
    },
    {
      field: 'technology_number',
      field: 'layer',
      width: 150,
      title: '层',
      filters: [{data: ''}],
@@ -359,8 +363,64 @@
//优化计算
const dialogVisible = ref({});
const optimizeData = ref({
  projectNo:null,
  allowRotate:null,
  cutOrigin:null,
  minCutDistance :null,
  optimizeMode:null,
  travType:null,
  rackCycleQty:null,
  glassDetails :[],
  materialDetails:[]
});
const openDialog = (index) => {
  dialogVisible.value[index] = true;
  if(index===4){
    if(parseInt(optimizeState.value)===1){
      ElMessage.warning("该工程已优化")
      return;
    }
    emit('getSmallPieceData', 1);
    xGrid.value.getTableData().fullData.forEach(items=>{
      const detail={
        width :null,
        height :null,
        processId :null,
        layer :null,
        totalLayer :null,
        orderSort :null,
        markIcon :null,
        quantity:null,
        patchState :null,
        upGrind :null,
        downGrind :null,
        leftGrind:null,
        rightGrind :null,
        rackNo:0
      }
      detail.width=items.width
      detail.height=items.height
      detail.processId=items.process_id
      detail.layer=items.layer
      detail.totalLayer=items.total_layer
      detail.orderSort=items.order_number
      detail.markIcon=items.icon
      detail.patchState=items.patch_state
      detail.quantity=items.quantity
      detail.upGrind=items.longGrind1
      detail.downGrind=items.longGrind2
      detail.leftGrind=items.shortGrind1
      detail.rightGrind=items.shortGrind2
      optimizeData.value.glassDetails .push(detail)
    })
  }else{
    dialogVisible.value[index] = true;
  }
};
//关闭弹窗
const closeDialog = (index) => {
@@ -369,13 +429,52 @@
//右键菜单统一修边
const props = defineProps({
  TrimmingDialogVisible: Boolean
  TrimmingDialogVisible: Boolean,
  CheckboxChangeData: null
});
watch(() => props.TrimmingDialogVisible, (newValue) => {
/*watch(() => props.TrimmingDialogVisible, (newValue) => {
  if (newValue === true) {
    dialogVisible.value[3] = newValue;
  }
});
});*/
watch(
    ()=> [props.TrimmingDialogVisible,props.CheckboxChangeData],
    ([newValue, oldValue])=> {
      if (props.TrimmingDialogVisible!=null){
        dialogVisible.value[3] = newValue;
      }
      if (props.CheckboxChangeData!=null && props.CheckboxChangeData.length>0){
        props.CheckboxChangeData.forEach(items=>{
          const detail={
            width :null,
            height :null,
            stockCode  :null,
            quantity  :null,
            upTrim :null,
            downTrim :null,
            leftTrim :null,
            rightTrim:null,
            priority:0
          }
          detail.width=items.width
          detail.height=items.height
          detail.stockCode=items.id
          detail.quantity=items.available_quantity
          detail.upTrim=items.upTrim
          detail.downTrim=items.downTrim
          detail.leftTrim=items.leftTrim
          detail.rightTrim=items.rightTrim
          optimizeData.value.materialDetails.push(detail)
        })
        dialogVisible.value[4] = true;
      }else{
        ElMessage.warning('请选择原片');
      }
      console.log(optimizeData.value)
    });
const route = useRoute();
//工程号
@@ -385,15 +484,35 @@
const model = ref(route.params.model);
const quantitys = ref(route.params.quantity);
const areas = ref(route.params.area);
const optimizeState = ref(route.params.optimizeState);
onBeforeUnmount(() => {
  localStorage.setItem('projectNo', projectNo.value);
});
const saveOptimizeData = () => {
  if(orderInfo.optimizeData!==null){
    request.post(`/glassOptimize/saveOptimizeData/${projectNo.value}`,orderInfo.optimizeData).then((res) => {
      if ((Number(res.code) === 200)) {
        ElMessage.success("保存成功");
      } else {
        ElMessage.warning(res.msg);
      }
    }).catch((error) => {
      console.error("获取数据出错:", error);
    });
  }else {
    ElMessage.warning("数据未优化");
  }
}
const fetchData = () => {
  request.post(`/glassOptimize/projectInfo/${projectNo.value}`).then((res) => {
    if ((Number(res.code) === 200)) {
      const data = res.data.data;
      const grindingTrimming = res.data.grindingTrimming;
      optimizeState.value=res.data.optimizeState;
      if(grindingTrimming!==null){
        const formattedData = grindingTrimming.map(item => {
          const formattedItem = {};
@@ -441,9 +560,34 @@
    console.error("获取数据出错:", error);
  });
};
const firstLoading = async() => {
  request.post(`/glassOptimize/selectOptimizeParms/${username}`).then((res) => {
    if (res.code == "200") {
      const parsedData = JSON.parse(res.data);
      optimizeData.value.projectNo=projectNo.value
      optimizeData.value.allowRotate=parsedData.optimization.smallPieceRotationProhibited
      optimizeData.value.optimizeMode=parsedData.optimization.optimizationMethod
      optimizeData.value.minCutDistance=parsedData.optimization.bendEdgeDistance
      optimizeData.value.cutOrigin=parsedData.optimization.cutterOriginPosition
      optimizeData.value.travType=parsedData.optimization.travType
      optimizeData.value.rackCycleQty=parsedData.optimization.rackCycleQty
    } else {
      ElMessage.warning(res.msg)
    }
  })
}
onMounted(() => {
  if (projectNo.value) {
    orderInfo.projectNo=route.params
    fetchData();
    firstLoading();
  }else if(orderInfo.projectNo!==null){
    projectNo.value=orderInfo.projectNo.projectNo
    fetchData();
    firstLoading();
  }
});
@@ -564,11 +708,12 @@
                   style="width: 35%;height:80%;margin-top: 3vh;">
          <set-trimming :closeDialog="closeDialog" @send-data-event="handleTrimmingData"/>
        </el-dialog>
        <el-button id="button" type="primary">保存</el-button>
        <el-button id="button" type="primary" @click="saveOptimizeData()">保存</el-button>
        <el-button id="button" type="primary" @click="openDialog(4)">优化</el-button>
        <el-dialog v-model="dialogVisible[4]" title="优化计算" destroy-on-close
                   style="width: 75%;height:90%;margin-top: 3vh;">
          <optimize-compute :quantity="quantitys" :area="areas" @send-data-event="handleTrimmingData"/>
          <optimize-compute :quantity="quantitys" :area="areas" :optimizeData="optimizeData"
                            @send-data-event="handleTrimmingData"/>
        </el-dialog>
      </div>
    </div>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
@@ -9,16 +9,16 @@
        <div class="layout-container" :style="layoutContainerStyle(layoutIndex)">
          <div class="grid-container" :class="`cols-${printColumns}`">
            <div
              v-for="(rect, rectIndex) in layout.rects"
              v-for="(glassDetail, rectIndex) in layout.glassDetails"
              :key="rectIndex"
              :ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
              :class="rectClass"
              :style="rectStyle(rect, layoutIndex)"
              :style="rectStyle(glassDetail, layoutIndex)"
              @click="handleRectClick(layoutIndex, rectIndex)"
            >
              <div v-if="!rect.isRemain" class="rect-content">
                <div class="size">{{ rect.w }}×{{ rect.h }}</div>
                <div class="jia-hao">{{ rect.JiaHao }}</div>
              <div v-if="!glassDetail.isRemain" class="glassDetail-content">
                <div class="size">{{ glassDetail.realWidth }}×{{ glassDetail.realHeight }}</div>
                <div class="jia-hao">{{ glassDetail.rackNo}}</div>
              </div>
            </div>
          </div>
@@ -35,7 +35,7 @@
const props = defineProps({
  layoutData: { type: Object, required: true },
  gw: { type: Number, default: 1400 },
  gh: { type: Number, default: 1100 },
  gh: { type: Number, default: 800 },
  style: { type: String, default: 'width:100%;height:800px;display:block;background:gray' },
  printLayout: { type: String, default: '2rows-2cols' }, // 可选值:4rows-2cols, 3rows-2cols, 3rows-1col, 2rows-2cols
  fixedPageHeight: { type: Number, default: 1100 } // 固定页面高度
@@ -48,8 +48,8 @@
const layouts = ref([]);
const panelClass = ref('');
const panelStyle = ref(props.style);
const rectClass = ref('layout-rect');
const processId = localStorage.getItem('projectNo');
const rectClass = ref('layout-glassDetail');
const processId = ref();
const printColumns = ref(2); // 初始化为2列
const layoutsPerPage = ref(4); // 默认每页显示4个布局(2行×2列)
@@ -75,7 +75,7 @@
  return {
    position: 'absolute',
    left: `${x}px`,
    top: `${y}px`,
    top: `${y-25}px`,
    width: `${containerWidth}px`,
    height: `${containerHeight}px`,
    overflow: 'visible',
@@ -95,7 +95,7 @@
  return {
    position: 'absolute',
    left: `${x}px`,
    top: `${y - 45}px`,
    top: `${y-25}px`,
    width: `${scale}px`,
    textAlign: 'center',
    zIndex: 1000,
@@ -105,30 +105,31 @@
  };
};
const rectStyle = (rect, layoutIndex) => {
const rectStyle = (glassDetail, layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const containerWidth = (props.gw - 100) / printColumns.value;
  const containerHeight = (props.gh - 100) / Math.ceil(layoutsPerPage.value / printColumns.value);
  // 根据当前打印布局获取放大比例
  const currentScale = layoutScales[props.printLayout] || 1.0;
  const scale = Math.min(
    containerWidth / layout.width,
    containerHeight / layout.height
  ) * currentScale; // 应用当前布局的放大比例
  ) ; // 应用当前布局的放大比例
  return {
    position: 'absolute',
    left: `${rect.x * scale}px`,
    top: `${rect.y * scale}px`,
    width: `${rect.w * scale}px`,
    height: `${rect.h * scale}px`,
    backgroundColor: rect.isRemain ? '#f0f0f0' : '#a0d8ef',
    left: `${glassDetail.x * scale}px`,
    bottom: `${glassDetail.y * scale}px`,
    width: `${glassDetail.width * scale}px`,
    height: `${glassDetail.height * scale}px`,
    backgroundColor: glassDetail.isRemain ? '#f0f0f0' : '#a0d8ef',
    border: '1px solid #000',
    cursor: 'pointer'
  };
};
const handleRectClick = (layoutIndex, rectIndex) => {
  focusIndex.value = { layoutIndex, rectIndex };
@@ -137,15 +138,13 @@
const getCurrentRectInfo = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const rect = layout.rects[focusIndex.value?.rectIndex || 0];
  if (!rect) return '';
  const totalRects = layouts.value.length;
  const currentRectIndex = layoutIndex + 1;
  const width = layout.width;
  const height = layout.height;
  const sum = layout.rects.reduce((sum, r) => sum + (r.w * r.h), 0);
  const areaUtilization = ((sum / (width * height)) * 100).toFixed(2);
  return `${currentRectIndex}/${totalRects} ${height}X${width}X1 ${areaUtilization}%`;
  const sum = layout.glassDetails.reduce((sum, r) => sum + (width * height), 0);
  const percentage = (layout.usageRate * 100).toFixed(2) + '%';
  return `${currentRectIndex}/${totalRects} ${width}X${height}X${layout.quantity} ${percentage}`;
};
const adjustPrintLayout = () => {
@@ -174,7 +173,20 @@
const updateLayout = () => {
  if (!layoutPanel.value) return;
  layouts.value = props.layoutData.Layouts;
  //layouts.value = props.layoutData.layouts;
  processId.value=props.layoutData.projectNo;
  let originalFilm = ref([])
  //layouts.value =
      props.layoutData.layouts.forEach(items=>{
        const existingItem = originalFilm.value.find(item => item.mergeId === items.mergeId);
        if (existingItem) {
          // 存在:数量加1(假设字段为 count)
          existingItem.quantity += 1;
        } else {
          originalFilm.value.push(items);
        }
      })
  layouts.value=originalFilm.value
  adjustPrintLayout();
  // 强制重新渲染
  layoutPanel.value.offsetHeight; // 触发布局更新
@@ -317,7 +329,7 @@
  overflow: visible;
}
.rect-content {
.glassDetail-content {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
north-glass-erp/northglass-erp/src/views/sd/basicData/SearchBasicData.vue
@@ -154,7 +154,7 @@
    {title: t('basicData.operate'), width: 110, slots: { default: 'button_slot' },fixed:"left",},
    {type: 'seq', title: t('basicData.number'), width: 80 ,fixed:"left",},
    {field:'basicName',title: t('orderBasicData.name'),filters: [{data: ''}],slots: {filter: 'num1_filter'},filterMethod: filterChanged},
    {field:'nickname',title: t('orderBasicData.alias')},
    {field:'nickname',title: t('orderBasicData.alias'),slots: { default: 'showNickname' }},
    {field:'createTime',title: t('basicData.creationTime')},
@@ -278,6 +278,12 @@
          </el-popconfirm>
        </template>
        <template #showNickname="{ row }">
          <span v-if="row.basicCategory==='icon' && row.nickname!=null">picture</span>
          <span v-else>{{row.nickname}}</span>
        </template>
        <template #num1_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
north-glass-erp/src/main/java/com/example/erp/controller/pp/GlassOptimizeController.java
@@ -95,13 +95,14 @@
    //修改工程状态
    @ApiOperation("修改工程状态接口")
    @PostMapping("/updateProjectState/{projectNumber}/{state}/{code}")
    @PostMapping("/updateProjectState/{projectNumber}/{state}/{states}/{code}")
    public Result updateProjectState(
            @PathVariable String projectNumber,
            @PathVariable Integer state,
            @PathVariable Integer states,
            @PathVariable Integer code
    ) {
        if (glassOptimizeService.updateProjectState(projectNumber, state,code)) {
        if (glassOptimizeService.updateProjectState(projectNumber, state,states,code)) {
            return Result.seccess();
        } else {
            throw new ServiceException(Constants.Code_500, "修改失败");
@@ -164,10 +165,10 @@
    }
    @ApiOperation("优化设置保存")
    @PostMapping("/optimizeParms")
    public Result optimizeParmsSave(@RequestBody Map<String, Object> object) {
    @PostMapping("/optimizeParms/{username}")
    public Result optimizeParmsSave(@RequestBody Map<String, Object> object,@PathVariable String username) {
        try {
            return Result.seccess(glassOptimizeService.optimizeParmsSave(object));
            return Result.seccess(glassOptimizeService.optimizeParmsSave(object,username));
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error();
@@ -229,10 +230,10 @@
    @ApiOperation("保存优化结果接口")
    @PostMapping("/saveOptimizeResult")
    public Result saveOptimizeResult(
    @PostMapping("/saveOptimizeData/{projectId}")
    public Result saveOptimizeResult( @PathVariable String projectId,
            @RequestBody Map<String,Object> object){
        return  Result.seccess(glassOptimizeService.saveOptimizeResult(object));
        return  Result.seccess(glassOptimizeService.saveOptimizeResult(object,projectId));
    }
north-glass-erp/src/main/java/com/example/erp/entity/pp/OptimizeProjectMange.java
@@ -19,6 +19,8 @@
    private Double thickness;
    private Integer type;
    private Integer state;
    private Integer temperingState;
    private Integer optimizeState;
    private Double quantity;
    private Double area;
    private Integer processCardQuantity;
north-glass-erp/src/main/java/com/example/erp/mapper/pp/GlassOptimizeMapper.java
@@ -53,6 +53,11 @@
    //修改工程状态
    Boolean updateProjectStateMp(String projectNumber,Integer state);
    Boolean updateProjectTemperingStateMp(String projectNumber,Integer states);
    Boolean updateProjectOptimizeStateMp(String projectNumber,Integer states);
    List<Map<String, Object>> getProjectListMp();
    //删除工程
@@ -63,6 +68,12 @@
    int deleteOptimizeHeatLayout(String projectNumber);
    int deleteOptimizeDetail(String projectNumber);
    int deleteOptimizeLayout(String projectNumber);
    int deleteOptimizeProjectFile(String projectNumber);
    int updateOptimizeUse(String projectNumber);
    List<OptimizeHeatDetail> selectOptimizeHeatDetail(String projectNumber);
@@ -76,6 +87,7 @@
    //模拟计算流程卡详情
    List<Map<String, Object>> selectComputeDetailMp(String processId,Integer technologyNumber);
    List<Map<String, Object>> selectComputeDetailMpPatchState(String processId,Integer technologyNumber);
@@ -85,8 +97,19 @@
    void addratioResult(Map<String, Object> object);
    //模拟计算保存 工程信息
    void addratioProjectResult(Map<String, Object> object);
    void insertOptimizeHeatDetail(String projectId,String processId,Integer technologyNumber,Integer patchState,
                                  Integer orderNumber,Double width,Double height,Integer index,String username);
    //优化设置保存
    void optimizeParmsSave(String jsonString);
    void optimizeParmsSave(String jsonString,String username);
    void addOptimizeDetail(List<Map<String, Object>> object,String projectId);
    void addOptimizeLayout(List<Map<String, Object>> object,String projectId);
    void addOptimizeProjectFile(String object,String projectId,String name);
    void addOptimizeUse(List<Map<String, Object>> object,String projectId,String name);
    //优化结果保存
    void optimizeResultSave(String jsonString);
@@ -115,6 +138,8 @@
    Double getSelectAreaPatchLog(String processId, String technologyNumber);
    Integer selectPatchLogState(String processId, Integer technologyNumber,Integer orderNumber,String projectNo);
    Boolean addProjectMp(String projectId, String projectNmae, String glassThickness, String glassType,
                         Integer sumQuantity, Double sumArea, String userName,Integer processIdCount, String processId, Integer type);
north-glass-erp/src/main/java/com/example/erp/service/pp/GlassOptimizeService.java
@@ -4,6 +4,8 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.example.erp.common.RabbitMQUtil;
import com.example.erp.entity.pp.*;
import com.example.erp.entity.sd.Delivery;
@@ -28,6 +30,7 @@
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
@@ -123,10 +126,108 @@
        try {
            Map<String, Object> objectMap = (Map<String, Object>) object.get("inputValues");
            String projectNo = objectMap.get("project_no").toString();
            String userName = object.get("userName").toString();
            Map<String, Object> optimizeProjectMap = glassOptimizeMapper.selectProjectCount(projectNo);
            glassOptimizeMapper.addSimulation(object);
            glassOptimizeMapper.addratioResult(object);
            glassOptimizeMapper.addratioProjectResult(object);
            if(Integer.valueOf(object.get("state").toString())==3){
                List<Map<String, Object>> flowCardList = glassOptimizeMapper.selectProjectComputeMp(projectNo);
                int index=0;
                for (Map<String, Object> flowCard:flowCardList){
                    List<Map<String, Object>> glassDetailList=new ArrayList<>();
                    if(Integer.valueOf(flowCard.get("patch_state").toString())==0){
                         glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(),
                                Integer.valueOf(flowCard.get("technologyNumber").toString()));
                    }else{
                         glassDetailList = glassOptimizeMapper.selectComputeDetailMpPatchState(flowCard.get("processId").toString(),
                                Integer.valueOf(flowCard.get("technologyNumber").toString()));
                    }
                    for (Map<String, Object> glassDetail:glassDetailList){
                        for(int i=0;i<Integer.valueOf(glassDetail.get("quantity").toString());i++){
                            index+=1;
                            glassOptimizeMapper.insertOptimizeHeatDetail(
                                    projectNo,flowCard.get("processId").toString(),
                                    Integer.valueOf(flowCard.get("technologyNumber").toString()),
                                    Integer.valueOf(flowCard.get("patch_state").toString()),
                                    Integer.valueOf(glassDetail.get("order_number").toString()),
                                    Double.valueOf(glassDetail.get("width").toString()),
                                    Double.valueOf(glassDetail.get("height").toString()),index,userName
                            );
                        }
                    }
                    glassOptimizeMapper.updateProjectTemperingStateMp(projectNo,1);
                }
            }else{
                List<Map<String, Object>> objectList = (List<Map<String, Object>>) object.get("projectdetail");
                for (Map<String, Object> objectMap1:objectList){
                    Integer count = glassOptimizeMapper.selectPatchLogState(objectMap1.get("process_id").toString(),
                            Integer.valueOf(objectMap1.get("layers_number").toString()),Integer.valueOf(objectMap1.get("order_number").toString()),projectNo);
                    if(count>0){
                        objectMap1.put("patchState",1);
                    }else {
                        objectMap1.put("patchState",0);
                    }
                }
                glassOptimizeMapper.addSimulation(object);
                glassOptimizeMapper.addratioResult(object);
                glassOptimizeMapper.addratioProjectResult(object);
                if(Integer.valueOf(object.get("state").toString())==2){
                    List<Map<String, Object>> flowCardList = glassOptimizeMapper.selectProjectComputeMp(projectNo);
                    List<String> rackinfosList = (List<String>) object.get("rackinfos");
                    Iterator<Map<String, Object>> iterator = flowCardList.iterator();
                    while (iterator.hasNext()) {
                        Map<String, Object> map = iterator.next();
                        for(String rackinfos:rackinfosList){
                            String processId=rackinfos.substring(0,14);
                            String processId1=map.get("processId").toString();
                            Integer technologyNumber= Integer.valueOf(rackinfos.substring(15));
                            Integer technologyNumber1= Integer.valueOf(map.get("technologyNumber").toString());
                            if(map.get("processId").toString().equals(processId) && Integer.valueOf(map.get("technologyNumber").toString())==technologyNumber){
                                iterator.remove();
                            }
                        }
                    }
                    int index=0;
                    for (Map<String, Object> flowCard:flowCardList){
                        List<Map<String, Object>> glassDetailList=new ArrayList<>();
                        if(flowCard.get("patch_state").toString()=="0"){
                            glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(),
                                    Integer.valueOf(flowCard.get("technologyNumber").toString()));
                        }else{
                            glassDetailList = glassOptimizeMapper.selectComputeDetailMp(flowCard.get("processId").toString(),
                                    Integer.valueOf(flowCard.get("technologyNumber").toString()));
                        }
                        for (Map<String, Object> glassDetail:glassDetailList){
                            for(int i=0;i<Integer.valueOf(glassDetail.get("quantity").toString());i++){
                                index+=1;
                                glassOptimizeMapper.insertOptimizeHeatDetail(
                                        projectNo,flowCard.get("processId").toString(),
                                        Integer.valueOf(flowCard.get("technologyNumber").toString()),
                                        Integer.valueOf(flowCard.get("patch_state").toString()),
                                        Integer.valueOf(glassDetail.get("order_number").toString()),
                                        Double.valueOf(glassDetail.get("width").toString()),
                                        Double.valueOf(glassDetail.get("height").toString()),index,userName
                                );
                            }
                        }
                    }
                }
            }
            if(Integer.valueOf(optimizeProjectMap.get("optimize_state").toString())==1){
                List<OptimizeHeatDetail> optimizeHeatDetail = glassOptimizeMapper.selectOptimizeHeatDetail(projectNo);
                for (OptimizeHeatDetail projectdetail:optimizeHeatDetail){
                    OptimizeDetail optimizeDetail=glassOptimizeMapper.selectOptimizeDetailById(projectNo,projectdetail.getProcessId(),
                            projectdetail.getOrderSort(),projectdetail.getLayer());
                    glassOptimizeMapper.updateOptimizeDetail(optimizeDetail.getId(),projectdetail.getLayoutId(),projectdetail.getSort());
                }
            }
            return true;
        } catch (Exception e) {
@@ -137,12 +238,12 @@
    //优化设置保存
    public Boolean optimizeParmsSave(Map<String, Object> object) {
    public Boolean optimizeParmsSave(Map<String, Object> object,String username) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(object);
            glassOptimizeMapper.optimizeParmsSave(jsonString);
            glassOptimizeMapper.optimizeParmsSave(jsonString,username);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -153,11 +254,32 @@
    //优化调整结果保存
    public Boolean saveOptimizeResult(Map<String, Object> object) {
    public Boolean saveOptimizeResult(Map<String, Object> object,String projectId) {
        try {
            Map<String, Object> optimalResults = (Map<String, Object>) object.get("optimalResults");
            List<Map<String, Object>> originalFilm = (List<Map<String, Object>>) object.get("originalFilm");
            glassOptimizeMapper.addOptimizeUse(originalFilm,projectId,"admin");
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(object);
            glassOptimizeMapper.optimizeResultSave(jsonString);
            String json = mapper.writeValueAsString(optimalResults);
            glassOptimizeMapper.addOptimizeProjectFile(json,projectId,"admin");
            List<Map<String, Object>> objectMapList = (List<Map<String, Object>>) optimalResults.get("layouts");
            glassOptimizeMapper.addOptimizeLayout(objectMapList,projectId);
            for(Map<String, Object> objectMap:objectMapList){
                List<Map<String, Object>> objectMap2 = (List<Map<String, Object>>) objectMap.get("glassDetails");
                //迭代玻璃明细集合删除余料
                Iterator<Map<String, Object>> iterator = objectMap2.iterator();
                while (iterator.hasNext()) {
                    Map<String, Object> map = iterator.next();
                    if (map.get("isRemain").toString()=="true") {
                        iterator.remove();
                    }
                }
                glassOptimizeMapper.addOptimizeDetail(objectMap2,projectId);
            }
            glassOptimizeMapper.updateProjectOptimizeStateMp(projectId,1);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
@@ -189,14 +311,13 @@
    public Map<String, Object> projectInfoSv(String projectNo) {
        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNo);
        Map<String, Object> map = new HashMap<>();
        if(Integer.parseInt(stringObjectMap.get("state").toString())<10){
            map.put("data", glassOptimizeMapper.firstOptimization(projectNo));
            map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming());
        }else if(stringObjectMap.get("state").equals(10)){
        if(Integer.parseInt(stringObjectMap.get("optimize_state").toString())==1||Integer.parseInt(stringObjectMap.get("tempering_state").toString())==1){
            map.put("optimizeState", Integer.parseInt(stringObjectMap.get("optimize_state").toString()));
            map.put("data", glassOptimizeMapper.analogComputationOptimization(projectNo));
            map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming());
        }else{
            map.put("data", glassOptimizeMapper.analogComputationOptimization(projectNo));
            map.put("optimizeState", Integer.parseInt(stringObjectMap.get("optimize_state").toString()));
            map.put("data", glassOptimizeMapper.firstOptimization(projectNo));
            map.put("grindingTrimming", glassOptimizeMapper.getGrindingTrimming());
        }
        return map;
@@ -214,16 +335,7 @@
    public Map<String, Object> materialStoreSv(String thickness, String model, String projectNumber,Integer type) {
        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber);
        Map<String, Object> map = new HashMap<>();
        if(Integer.parseInt(stringObjectMap.get("state").toString())<10){
            if(type==1){
                map.put("data", glassOptimizeMapper.materialStoreMp(thickness,model));
            }else if(type==2){
                map.put("data", glassOptimizeMapper.surplusMaterialsMp(thickness,model));
            }else{
                map.put("data", glassOptimizeMapper.materialStoreSurplusMp(thickness,model));
            }
            map.put("edgeTrimming", glassOptimizeMapper.getEdgeTrimming());
        }else if(Integer.parseInt(stringObjectMap.get("state").toString())==10){
        if(Integer.parseInt(stringObjectMap.get("optimize_state").toString())==0){
            if(type==1){
                map.put("data", glassOptimizeMapper.materialStoreMp(thickness,model));
            }else if(type==2){
@@ -278,20 +390,21 @@
    }
    //修改排版状态
    public Boolean updateProjectState(String projectNumber, Integer state, Integer code) {
    public Boolean updateProjectState(String projectNumber, Integer state,Integer states, Integer code) {
        if (!projectNumber.isEmpty()) {
            //撤销模拟计算
            if(code==1){
                glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
                glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber);
                glassOptimizeMapper.updateProjectStateMp(projectNumber, state);
                glassOptimizeMapper.updateProjectTemperingStateMp(projectNumber, states);
            }
            //撤销优化排版
            else if(code==2){
                glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
                glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
                glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber);
                glassOptimizeMapper.updateProjectStateMp(projectNumber, state);
                glassOptimizeMapper.deleteOptimizeDetail(projectNumber);
                glassOptimizeMapper.deleteOptimizeLayout(projectNumber);
                glassOptimizeMapper.deleteOptimizeProjectFile(projectNumber);
                glassOptimizeMapper.updateOptimizeUse(projectNumber);
                glassOptimizeMapper.updateProjectOptimizeStateMp(projectNumber, states);
            }
            //允许生产
            else if(code==3){
@@ -314,11 +427,15 @@
    //删除工程
    public boolean deleteProject(String projectNumber,Integer type) {
        Map<String, Object> stringObjectMap = glassOptimizeMapper.selectProjectCount(projectNumber);
        if(stringObjectMap.get("state").equals(10)){
        if(stringObjectMap.get("tempering_state").equals(1)){
            glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
            glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber);
        }else if(stringObjectMap.get("state").equals(20)){
        }
        if(stringObjectMap.get("optimize_state").equals(1)){
            glassOptimizeMapper.deleteOptimizeDetail(projectNumber);
            glassOptimizeMapper.deleteOptimizeLayout(projectNumber);
            glassOptimizeMapper.deleteOptimizeLayout(projectNumber);
            glassOptimizeMapper.updateOptimizeUse(projectNumber);
            glassOptimizeMapper.deleteOptimizeHeatDetail(projectNumber);
            glassOptimizeMapper.deleteOptimizeHeatLayout(projectNumber);
        }
north-glass-erp/src/main/java/com/example/erp/service/sd/BasicDateService.java
@@ -31,7 +31,7 @@
    public Map<String, List<Object>> getOrderBasicData() {
        //获取订单基本数据类型
        //创建Map对象
        Map<String, List<Object>> orderBasicDataMap = new HashMap<>(); ;
        Map<String, List<Object>> orderBasicDataMap = new HashMap<>();
        //创建List对象
        orderBasicDataMap = getBasicDataByType("order");
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
@@ -41,6 +41,8 @@
        <result property="thickness" column="thickness"/>
        <result property="type" column="type"/>
        <result property="state" column="state"/>
        <result property="temperingState" column="Tempering state"/>
        <result property="optimizeState" column="Optimize state"/>
        <result property="quantity" column="quantity"/>
        <result property="area" column="area"/>
        <result property="processCardQuantity" column="process Card Quantity"/>
@@ -100,7 +102,8 @@
              c.quantity,
              o.shape,
              concat( c.process_id, '-', c.technology_number ) AS 'process_id',
              c.technology_number,
              c.technology_number as layer,
              c.layers_number as total_layer,
              d.glass_child,
              o.product_name,
              o.price,
@@ -109,7 +112,8 @@
              round( d.area * c.quantity, 4 ) as 'area',
              c.order_number,
              d.icon,
              op.project_name
              op.project_name,
              0 as patch_state
          FROM
              pp.flow_card c
                  LEFT JOIN sd.order_detail o ON c.order_id = o.order_id
@@ -133,7 +137,8 @@
                c.patch_num as quantity,
                o.shape,
                concat( c.process_id, '-', c.technology_number ) AS 'process_id',
                c.technology_number,
                c.technology_number as layer,
                fc.layers_number as total_layer,
                d.glass_child,
                o.product_name,
                o.price,
@@ -142,7 +147,8 @@
                round( d.area * c.patch_num, 4 ) as 'area',
                c.order_sort as order_number,
                d.icon,
                op.project_name
                op.project_name,
                1 as patch_state
            FROM
                pp.patch_log c
                    LEFT JOIN sd.order_detail o ON c.order_id = o.order_id
@@ -151,6 +157,7 @@
                    AND c.order_sort = d.order_number
                    AND c.technology_number = d.technology_number
                    INNER JOIN pp.optimize_project AS op ON op.project_no = c.project_no
                    LEFT JOIN pp.flow_card fc ON c.process_id = fc.process_id and fc.technology_number=c.technology_number
            WHERE
                c.project_no IS NOT NULL
              and c.project_no = #{projectNo}
@@ -160,7 +167,7 @@
    </select>
    <!--第一次优化查询-->
    <!--优化查询-->
    <select id="analogComputationOptimization">
        SELECT
            h.project_no,
@@ -170,7 +177,9 @@
            count( 1 ) AS quantity,
            o.shape,
            concat( h.process_id, '-', h.layer ) AS 'process_id',
            h.process_id as process_ids,
            h.layer,
            c.layers_number as total_layer,
            d.glass_child,
            o.product_name,
            o.price,
@@ -179,7 +188,8 @@
            round( d.area * count( 1 ), 4 ) AS 'area',
            c.order_number,
            d.icon,
            o.price
            o.price,
            h.patch_state
        from
            pp.`optimize_heat_detail` h
                LEFT JOIN pp.flow_card c ON h.process_id = c.process_id
@@ -263,6 +273,8 @@
            i.id AS id,
            i.producer AS producer,
            i.available_quantity-i.plan_quantity AS available_quantity,
            null as processingQuantity,
            1 as materialType,
            JSON_EXTRACT(s.json, '$.width') AS width,
            JSON_EXTRACT(s.json, '$.height') AS height,
            JSON_EXTRACT(s.json, '$.thickness') AS thickness,
@@ -292,6 +304,8 @@
            i.id AS id,
            '' AS producer,
            i.quantity AS available_quantity,
            null as processingQuantity,
            0 as materialType,
            i.width,
            i.height,
            i.thickness,
@@ -310,6 +324,8 @@
            i.id AS id,
            i.producer AS producer,
            i.available_quantity-i.plan_quantity AS available_quantity,
            null as processingQuantity,
            1 as materialType,
            JSON_EXTRACT(s.json, '$.width') AS width,
            JSON_EXTRACT(s.json, '$.height') AS height,
            JSON_EXTRACT(s.json, '$.thickness') AS thickness,
@@ -335,6 +351,8 @@
            i.id AS id,
            '' AS producer,
            i.quantity AS available_quantity,
            null as processingQuantity,
            0 as materialType,
            i.width,
            i.height,
            i.thickness,
@@ -531,6 +549,8 @@
               p.`glass_thickness`                   AS `Thickness`,
               p.`type`                              AS `Type`,
               p.`state`                             AS `State`,
               p.`tempering_state`                    AS `Tempering state`,
               p.`optimize_state`                     AS `Optimize state`,
               p.`glass_total`                       AS `Quantity`,
               p.`glass_total_area`                  AS `Area`,
               p.`process_qty`                       AS `Process Card Quantity`,
@@ -549,7 +569,8 @@
               `p`.`update_time`                     AS `Modify time`
        from pp.optimize_project as p
                 left join pp.optimize_admin as a on p.creater = a.Id
        where (`p`.`state` > 1)
        where (`p`.`state` > 0)
            and (tempering_state>0 or optimize_state>0)
            and DATE (`p`.`create_time`) BETWEEN #{startSelectTime} AND #{endSelectTime}
        <if test="optimizeProjectMange.projectNumber != null and optimizeProjectMange.projectNumber != ''">
            and p.project_no regexp #{optimizeProjectMange.projectNumber}
@@ -563,6 +584,20 @@
    <update id="updateProjectStateMp">
        update pp.optimize_project as p
        set p.state = #{state}
        where p.project_no = #{projectNumber}
    </update>
    <!--修改模拟计算工程状态-->
    <update id="updateProjectTemperingStateMp">
        update pp.optimize_project as p
        set p.tempering_state = #{states}
        where p.project_no = #{projectNumber}
    </update>
    <!--修改优化工程状态-->
    <update id="updateProjectOptimizeStateMp">
        update pp.optimize_project as p
        set p.optimize_state = #{states}
        where p.project_no = #{projectNumber}
    </update>
@@ -586,6 +621,21 @@
        delete from pp.optimize_detail
        where project_no = #{projectNumber}
    </delete>
    <delete id="deleteOptimizeLayout">
        delete from pp.optimize_layout
        where project_no = #{projectNumber}
    </delete>
    <delete id="deleteOptimizeProjectFile">
        delete from pp.optimize_project_file
        where project_no = #{projectNumber}
    </delete>
    <update id="updateOptimizeUse">
        update pp.optimize_use set state=0
        where project_no = #{projectNumber}
    </update>
    <select id="selectOptimizeDetailById">
        select * from pp.optimize_detail
@@ -622,7 +672,7 @@
                    p.creater = a.Id
                    )))
        WHERE
            ( p.state = 1 )
            ( p.state = 1 ) and p.tempering_state=0 and optimize_state=0
        ORDER BY
            p.create_time DESC,
            p.project_no
@@ -716,6 +766,7 @@
                 `g`.`area`,
                 `g`.`icon`
    </select>
    <select id="selectComputeDetailMpPatchState">
        select `l`.`order_id`                           AS order_id,
@@ -844,6 +895,13 @@
        group by process_id,technology_number
    </select>
    <select id="selectPatchLogState">
        select
            count(*)
        from pp.patch_log
        where process_id=#{processId} and technology_number=#{technologyNumber} and order_sort=#{orderNumber} and project_no=#{projectNo}
    </select>
    <update id="updateProjectMp">
        update pp.optimize_project set project_name=#{projectNmae},glass_total=#{sumQuantity},glass_total_area= #{sumArea},
                                       type=#{type},process_qty=#{processIdCount},process_cards=#{processId} where project_no=#{projectId}
@@ -904,6 +962,53 @@
            );
        </foreach>
    </insert>
    <insert id="insertOptimizeHeatDetail">
            INSERT INTO pp.optimize_heat_detail (
            project_no,
            process_id,
            width,
            height,
            x_axis,
            y_axis,
            rotate_angle,
            creater,
            create_time,
            update_time,
            patch_state,
            layer,
            order_sort,
            layout_id,
            sort,
            glass_id,
            pair_width,
            pair_height,
            intRemark,
            strRemark
            ) VALUES (
            #{projectId},
            #{processId},
            #{width},
            #{height},
            0,
            0,
            0,
            #{username},
            NOW(),
            NOW(),
            #{patchState},
            #{technologyNumber},
            #{orderNumber},
            0,
            #{index},
            null,
            #{width},
            #{height},
            null,
            null
            );
    </insert>
    <!--模拟计算结果保存-->
    <insert id="addratioResult" parameterType="map">
        <foreach collection="ratioResult" item="glass">
@@ -931,11 +1036,140 @@
        </foreach>
    </insert>
    <!--优化小片保存-->
    <insert id="addOptimizeDetail" parameterType="map">
        <foreach collection="object" item="glass">
            INSERT INTO pp.optimize_detail (
            project_no,
            process_id,
            layer,
            total_layer,
            order_sort,
            stock_id,
            polys_id,
            o_width,
            o_height,
            width,
            height,
            x_axis,
            y_axis,
            patch_state,
            mark_icon
            ) VALUES (
            #{projectId},
            #{glass.processId},
            #{glass.layer},
            #{glass.totalLayer},
            #{glass.orderSort},
            #{glass.stockSort},
            #{glass.polySort},
            #{glass.realwidth},
            #{glass.realheight},
            #{glass.width},
            #{glass.height},
            #{glass.x},
            #{glass.y},
            #{glass.patchState},
            #{glass.markIcon}
            );
        </foreach>
    </insert>
    <!--优化结果json格式保存-->
    <insert id="addOptimizeProjectFile" >
            INSERT INTO pp.optimize_project_file (
            project_no,
            type,
            content,
            create_time,
            creater
            ) VALUES (
            #{projectId},
            "优化结果",
            #{object},
            now(),
            #{name}
            );
    </insert>
    <!--优化原片保存-->
    <insert id="addOptimizeLayout" parameterType="map">
        <foreach collection="object " item="glass">
            INSERT INTO pp.optimize_layout (
            project_no,
            stock_id,
            width,
            height,
            usage_rate,
            stock_code,
            up_trim,
            down_trim,
            left_trim,
            right_trim,
            glass_count,
            glass_area,
            create_time
            ) VALUES (
            #{projectId},
            #{glass.stockId},
            #{glass.width},
            #{glass.height},
            #{glass.usageRate},
            #{glass.stockCode},
            #{glass.upTrim},
            #{glass.downTrim},
            #{glass.leftTrim},
            #{glass.rightTrim},
            #{glass.glassCount},
            #{glass.glassArea},
            now()
            );
        </foreach>
    </insert>
    <!--优化原片保存-->
    <insert id="addOptimizeUse" parameterType="map">
        <foreach collection="object " item="glass">
            INSERT INTO pp.optimize_use (
            project_no,
            raw_stock_code,
            type,
            width,
            height,
            use_count,
            not_use_count,
            state,
            left_trim,
            down_trim,
            right_trim,
            up_trim,
            creater,
            create_time
            ) VALUES (
            #{projectId},
            #{glass.stockCode},
                      1,
            #{glass.width},
            #{glass.height},
            #{glass.count},
            #{glass.count},
                      1,
            #{glass.leftTrim},
            #{glass.downTrim},
            #{glass.rightTrim},
            #{glass.upTrim},
            #{name},
            now()
            );
        </foreach>
    </insert>
    <!--模拟计算工程更新-->
    <update id="addratioProjectResult" parameterType="map">
        UPDATE pp.optimize_project
        SET
            state = 10,
            tempering_state = 1,
            furnaces_qty=#{resultSum[0]},
            load_rate=#{resultSum[1]},
            chaos_pct = #{inputValues.chaos_pct},
@@ -950,10 +1184,11 @@
            project_no = #{inputValues.project_no}
    </update>
<!--优化设置保存-->
    <update id="optimizeParmsSave">
        update erp_user_info.user as u
        set u.optimize_parms = #{jsonString}
        set u.optimize_parms = #{jsonString} where user_name=#{username}
    </update>
    <update id="updateOptimizeResult">
north-glass-erp/src/main/resources/mapper/sd/BasicDataMapper.xml
@@ -5,7 +5,7 @@
<mapper namespace="com.example.erp.mapper.sd.BasicDateMapper">
    <select id="getOrderBasicData">
        select
            *
            id,basic_type,if(basic_category='icon',null,nickname) as 'nickname',basic_name,basic_category,create_time,update_time
        from
            basic_data as a
        where a.basic_type=#{type}