廖井涛
2025-08-01 4a5eb357ecb19b994c5381c52796cb41c05e79cf
Merge branch 'master' of http://10.153.19.25:10101/r/ERP_override
11个文件已修改
543 ■■■■■ 已修改文件
north-glass-erp/northglass-erp/src/lang/zh.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue 83 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizeCompute.vue 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/processCard/AddProcessCard.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/zh.js
@@ -650,6 +650,7 @@
        pleaseNumber8:'请输入序号',
        pleaseNumber9:'正确的完工或次破数量',
        pleaseNumber10:'完工数不能大于流程卡数量',
        pleaseNumber11:'可修改数量不足',
    },
    productStock:{
        page:{
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/Optimization.vue
@@ -1,10 +1,10 @@
<template>
  <div>
    <RectRenderer
    <RectRenderer
      v-if="dataLoaded"
      :layoutData="layoutData"
      :gw="1150"
      :gh="850"
      :layoutData="layoutData"
      :gw="1150"
      :gh="850"
      style="width: 1000px; height: 800px; position: relative;"
    />
  </div>
@@ -13,7 +13,6 @@
<script setup>
import { ref, onMounted } from 'vue';
import RectRenderer from './page/OptimizationRect.vue';
import mockLayoutData from '../../../components/pp/MockData';
import request from "@/utils/request";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
@@ -29,18 +28,21 @@
const dataLoaded = ref(false);
const selectLayout = () => {
  if(processId!=="undefined"){
  if(processId && processId !== "undefined"){
    request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
        .then((res) => {
          if (res.code == 200) {
          if (res.code == 200 && res.data && res.data.data && res.data.data.length > 0) {
            try {
              const parsedData = JSON.parse(res.data.data[0].Layouts);
              layoutData.value = parsedData;
              dataLoaded.value = true;
              ElMessage.success("打开版图成功");
            } catch (error) {
              ElMessage.error("解析数据时出错:", error);
              console.error("解析数据时出错:", error);
              ElMessage.error("解析数据时出错");
            }
          } else {
            ElMessage.warning("未找到版图数据");
          }
        })
        .catch((error) => {
@@ -48,14 +50,22 @@
          ElMessage.error(t('basicData.msg.ServerConnectionError'));
        });
  }
}
onMounted(() => {
  if(orderInfo.optimizeData.optimalResults!=null){
    layoutData.value=orderInfo.optimizeData.optimalResults
    dataLoaded.value = true;
  }else{
  // 检查 store 中是否有数据,并确保数据结构正确
  if(orderInfo.optimizeData && orderInfo.optimizeData.optimalResults) {
    // 确保数据结构符合 OptimizationRect.vue 的期望格式
    const optimalResults = orderInfo.optimizeData.optimalResults;
    if (optimalResults.layouts) {
      layoutData.value = optimalResults;
      dataLoaded.value = true;
    } else {
      // 如果数据结构不匹配,尝试从后端获取
      selectLayout();
    }
  } else {
    // 如果 store 中没有数据,则从后端获取
    selectLayout();
  }
});
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
@@ -15,60 +15,71 @@
      保存OPT
    </button>
  </template>
  <script setup>
  import { ref,onMounted } from 'vue';
  import RectRenderer from './page/RectRenderer.vue';
  import mockLayoutData from '../../../components/pp/MockData';
  import request from "@/utils/request";
<script setup>import { ref, onMounted } from 'vue';
import RectRenderer from './page/RectRenderer.vue';
import request from "@/utils/request";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
const { t } = useI18n();
 // const layoutData = ref(mockLayoutData);
  const savedProjectNo = localStorage.getItem('projectNo');
const savedProjectNo = localStorage.getItem('projectNo');
const processId = savedProjectNo;
const layoutData = ref(null);
const dataLoaded = ref(false);
const selectLayout = () => {
request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
.then((res) => {
  if (res.code == 200) {
    try {
      const parsedData = JSON.parse(res.data.data[0].Layouts);
      layoutData.value = parsedData;
      dataLoaded.value = true;
    } catch (error) {
    }
  } else {
  request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
      .then((res) => {
        if ((res.code === 200 || res.code === '200') && res.data && res.data.data && res.data.data.length > 0) {
          try {
            console.log("原始数据:", res.data.data[0]); // 调试信息
  }
})
.catch((error) => {
  console.error("请求失败:", error);
  ElMessage.error(t('basicData.msg.requestFailed'));
});
}
            // 解析保存的布局数据
            const parsedData = JSON.parse(res.data.data[0].Layouts);
            console.log("解析后的数据:", parsedData); // 调试信息
            // 确保数据结构正确
            if (parsedData && parsedData.layouts) {
              layoutData.value = parsedData;
              dataLoaded.value = true;
            } else {
              ElMessage.warning("数据格式不正确");
            }
          } catch (error) {
            console.error("数据解析失败:", error);
            ElMessage.error("数据解析失败: " + error.message);
          }
        } else {
          ElMessage.warning("未找到优化数据");
        }
      })
      .catch((error) => {
        console.error("请求失败:", error);
        ElMessage.error(t('basicData.msg.requestFailed'));
      });
};
onMounted(() => {
  selectLayout();
});
  const submitLayouts = async () => {
const submitLayouts = async () => {
  try {
    // 确保有数据可以提交
    if (!layoutData.value) {
      ElMessage.warning('没有可保存的数据');
      return;
    }
    const response = await request.post('/glassOptimize/generateOpt', {
      Layouts: layoutData.value.Layouts
      Layouts: JSON.stringify(layoutData.value) // 序列化整个layoutData对象
    }, {
      headers: {
        'Content-Type': 'application/json'
      },
      responseType: 'blob' // 以 blob 形式接收响应
      responseType: 'blob'
    });
    // 处理下载
@@ -83,12 +94,8 @@
    ElMessage.success('OPT文件下载成功,请选择文件路径');
  } catch (error) {
    console.error('下载失败:', error);
    // 显示错误消息给用户
    ElMessage.error('下载失败,请稍后再试');
  }
};
  </script>
</script>
  
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue
@@ -413,8 +413,19 @@
                }
              }else if(config.code === 'undoOptimize'){
                if(row.optimizeState==1&&row.state===1){
                  // 先更新前端显示的状态
                  row.optimizeState = config.targetStates;
                  code=2
                  code=2;
                  // 更新列表中的数据以刷新显示
                  const index = produceList.value.findIndex(item => item === row);
                  if (index !== -1) {
                    produceList.value.splice(index, 1, {...row});
                    xGrid.value.reloadData(produceList.value);
                  }
                  // 显示成功消息
                  ElMessage.success(config.successMsg);
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -80,7 +80,9 @@
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router'; // 添加这行
import request from "@/utils/request";
const router = useRouter(); // 添加这行
import { useI18n } from "vue-i18n";
import { ElMessage, ElMessageBox } from "element-plus";
import useUserInfoStore from "@/stores/userInfo";
@@ -126,7 +128,18 @@
  });
  const savedProjectNo = localStorage.getItem('projectNo');
  const processId = savedProjectNo;
  layoutsHead.value.Layouts=layouts.value
  // 构造与原始数据结构一致的对象
  const saveData = {
    projectNo: processId,
    layouts: layouts.value,
    // 复制原始数据中的其他必要字段
    ...layoutsHead.value
  };
  // 确保 Layouts 字段是序列化的字符串
  const requestData = {
    Layouts: JSON.stringify(saveData)
  };
  request.post(`/glassOptimize/updateOptimizeResult/${processId}`, layoutsHead.value, {
    headers: {
      'Content-Type': 'application/json'
@@ -134,6 +147,8 @@
  }).then((res) => {
    if (res.code == 200 && res.data === true) {
      ElMessage.success(t('basicData.msg.saveSuccess'));
      // // 保存成功后跳转到数控界面
      // router.push({ path: '/main/glassOptimize/OptimizeControl' });
    } else {
      ElMessage.warning(res.msg);
    }
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizeCompute.vue
@@ -1,9 +1,11 @@
<script setup>
import {ref, computed, watch} from "vue";
import {Connection} from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from 'element-plus'; // 添加这行
import {useRoute, useRouter} from "vue-router";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
import requestOptimize from "@/utils/requestOptimize";
import request from "@/utils/request";
const router = useRouter()
const orderInfo = useOrderInfoStore()
@@ -75,9 +77,36 @@
            const result = response.data;
            // 更新 store 数据
            orderInfo.optimizeData.optimalResults = result.layouts[0];
            orderInfo.optimizeData.originalFilm = originalFilm.value;
            if (result.layouts && result.layouts.length > 0) {
              orderInfo.optimizeData.optimalResults = {
                layouts: result.layouts
              };
            }
            // 在这里就设置 originalFilm 数据
            const newOriginalFilm = [];
            result.layouts.forEach(items => {
              const existingItem = newOriginalFilm.find(
                  item => item.width === items.width && item.height === items.height
              );
              if (existingItem) {
                existingItem.count += 1;
              } else {
                newOriginalFilm.push({
                  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 = newOriginalFilm;
            orderInfo.optimizeData.originalFilm = newOriginalFilm; // 这一行很重要
            console.log('优化完成后设置 originalFilm:', newOriginalFilm);
            // 更新利用率
            totalUtilizationRate.value = result.avgCutRate;
            tailPieceRate.value = result.lastCutRate;
@@ -115,43 +144,106 @@
    isRunning.value = false;
  }
};
const resetTimer = () => {
  router.push({path: '/main/glassOptimize/Optimization'})
  /*clearInterval(intervalId);
  isRunning.value = false;
  seconds.value = 0;
  progress.value = 0;*/
const saveOptimizeData = async () => {
  // 检查是否有优化数据
  if(orderInfo.optimizeData !== null){
    try {
      // 确保 originalFilm 数据已设置
      if (!orderInfo.optimizeData.originalFilm) {
        orderInfo.optimizeData.originalFilm = originalFilm.value;
        console.log('保存前设置 originalFilm:', originalFilm.value);
      }
      // 发送请求保存优化数据
      const res = await request.post(`/glassOptimize/saveOptimizeData/${props.optimizeData.projectNo}`, orderInfo.optimizeData);
      if (Number(res.code) === 200) {
        ElMessage.success("保存成功");
        return true; // 保存成功
      } else {
        ElMessage.warning(res.msg || "保存失败");
        return false; // 保存失败
      }
    } catch (error) {
      ElMessage.error("保存过程中发生错误");
      console.error("保存数据出错:", error);
      return false; // 保存出错
    }
  } else {
    ElMessage.warning("无优化数据可保存");
    return false;
  }
}
const resetTimer = async () => {
  // 先保存数据,保存成功后再跳转
  const isSaved = await saveOptimizeData();
  if (isSaved) {
    // 保存成功后跳转到优化界面
    router.push({path: '/main/glassOptimize/Optimization'});
  } else {
    // 保存失败,给用户选择是否仍要离开
    ElMessageBox.confirm(
        '数据保存失败,是否仍要离开当前页面?',
        '提示',
        {
          confirmButtonText: '确定离开',
          cancelButtonText: '取消',
          type: 'warning'
        }
    ).then(() => {
      // 用户确认离开
      router.push({path: '/main/glassOptimize/Optimization'});
    }).catch(() => {
      // 用户取消,留在当前页面
      ElMessage.info('操作已取消');
    });
  }
};
// watch(
//     () => progress.value,
//     (newValue) => {
//       if (newValue === 100 && orderInfo.optimizeData && orderInfo.optimizeData.optimalResults) {
//         // 根据接口返回的 layouts 数据构建版图统计
//         const layouts = orderInfo.optimizeData.optimalResults.layouts;
//         const newOriginalFilm = [];
//
//         layouts.forEach(items => {
//           const existingItem = newOriginalFilm.find(
//               item => item.width === items.width && item.height === items.height
//           );
//
//           if (existingItem) {
//             existingItem.count += 1;
//           } else {
//             newOriginalFilm.push({
//               width: items.width,
//               height: items.height,
//               upTrim: items.upTrim,
//               downTrim: items.downTrim,
//               leftTrim: items.leftTrim,
//               rightTrim: items.rightTrim,
//               stockCode: items.stockCode,
//               count: 1
//             });
//           }
//         });
//         // 更新 originalFilm
//         originalFilm.value = newOriginalFilm;
//         console.log('设置 originalFilm 数据:', newOriginalFilm);
//       }
//     }
// );
// 简化 watch 函数
watch(
    () => progress.value,
    (newValue) => {
      if (newValue === 10) {
        // 根据接口返回的 layouts 数据构建版图统计
        const layouts = orderInfo.optimizeData.optimalResults.layouts;
        originalFilm.value = [];
        layouts.forEach(items => {
          const existingItem = originalFilm.value.find(
              item => item.width === items.width && item.height === items.height
          );
          if (existingItem) {
            existingItem.count += 1;
          } else {
            originalFilm.value.push({
              width: items.width,
              height: items.height,
              upTrim: items.upTrim,
              downTrim: items.downTrim,
              leftTrim: items.leftTrim,
              rightTrim: items.rightTrim,
              stockCode: items.stockCode,
              count: 1
            });
          }
        });
      }
      // 进度更新时不需要额外处理,因为已经在 startTimer 中处理了 originalFilm
      console.log('优化进度更新:', newValue);
    }
);
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/ProjectDetail.vue
@@ -459,6 +459,10 @@
    }
    emit('getSmallPieceData', 1);
    xGrid.value.getTableData().fullData.forEach(items=>{
      let rackNoValue = 0;
      if (items.rackNo !== undefined && items.rackNo !== null && items.rackNo !== '') {
        rackNoValue = items.rackNo;
      }
      const detail={
        width :null,
        height :null,
@@ -473,7 +477,7 @@
        downGrind :null,
        leftGrind:null,
        rightGrind :null,
        rackNo:0
        rackNo: rackNoValue
      }
      detail.width=items.width
      detail.height=items.height
@@ -488,7 +492,7 @@
      detail.downGrind=items.longGrind2
      detail.leftGrind=items.shortGrind1
      detail.rightGrind=items.shortGrind2
      detail.rackNo=items.id
      detail.rackNo=items.rackNo
      optimizeData.value.glassDetails .push(detail)
    })
@@ -567,6 +571,7 @@
const saveOptimizeData = () => {
  if(orderInfo.optimizeData!==null){
    if(quantitys.value===orderInfo.optimizeData.optimalResults.glassTotalQuantity){
      console.log("保存数据1",orderInfo.optimizeData)
      request.post(`/glassOptimize/saveOptimizeData/${projectNo.value}`,orderInfo.optimizeData).then((res) => {
        if ((Number(res.code) === 200)) {
          ElMessage.success("保存成功");
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/RectRenderer.vue
@@ -268,22 +268,33 @@
const updateLayout = () => {
  if (!layoutPanel.value) return;
  //layouts.value = props.layoutData.layouts;
  if (!props.layoutData) {
    console.warn('layoutData 为空');
    return;
  }
  console.log('RectRenderer 接收到的 layoutData:', props.layoutData);
  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
  layoutDetails.value.push(props.layoutData)
  materialDetails.value=props.materialDetails
  console.log(layouts.value)
  // 处理 layouts 数据
  if (props.layoutData.layouts && Array.isArray(props.layoutData.layouts)) {
    let originalFilm = [];
    props.layoutData.layouts.forEach(items => {
      const existingItem = originalFilm.find(item => item.mergeId === items.mergeId);
      if (existingItem) {
        existingItem.quantity += 1;
      } else {
        originalFilm.push(items);
      }
    });
    layouts.value = originalFilm;
    layoutDetails.value.push(props.layoutData);
    materialDetails.value = props.materialDetails;
    console.log('处理后的 layouts:', layouts.value);
  } else {
    console.warn('layouts 数据格式不正确或为空');
  }
  adjustPrintLayout();
  // 强制重新渲染
  layoutPanel.value.offsetHeight; // 触发布局更新
north-glass-erp/northglass-erp/src/views/pp/glassOptimizeThirdParty/OptimizeControl.vue
@@ -1,68 +1,64 @@
<template>
    <div >
      <RectRenderer
    :layoutData="layoutData"
    :gw="1400"
    :gh="1100"
    style="width: 1500px; height: 800px; position: relative;"
    v-if="dataLoaded"
  />
    </div>
    <button @click="submitLayouts" style="position: fixed; bottom: 20px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
      保存OPT
    </button>
  </template>
  <script setup>
  import { ref,onMounted } from 'vue';
  import RectRenderer from './page/RectRenderer.vue';
  import mockLayoutData from '../../../components/pp/MockData';
  import request from "@/utils/request";
  <div>
    <RectRenderer :layoutData="layoutData" :gw="1400" :gh="1100"
      style="width: 1500px; height: 800px; position: relative;" v-if="dataLoaded" />
  </div>
  <button @click="submitLayouts"
    style="position: fixed; bottom: 20px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
    保存OPT
  </button>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import RectRenderer from './page/RectRenderer.vue';
import mockLayoutData from '../../../components/pp/MockData';
import request from "@/utils/request";
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
const { t } = useI18n();
 // const layoutData = ref(mockLayoutData);
// const layoutData = ref(mockLayoutData);
  const savedProjectNo = localStorage.getItem('projectNo');
const savedProjectNo = localStorage.getItem('projectNo');
const processId = savedProjectNo;
const layoutData = ref(null);
const dataLoaded = ref(false);
const selectLayout = () => {
request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
.then((res) => {
  if (res.code == 200) {
    try {
      const parsedData = JSON.parse(res.data.data[0].Layouts);
      layoutData.value = parsedData;
      dataLoaded.value = true;
    } catch (error) {
    }
  } else {
  request.post(`/glassOptimize/selectOptimizeResult/${processId}`)
    .then((res) => {
      if (res.code == 200) {
        try {
          const parsedData = JSON.parse(res.data.data[0].Layouts);
          layoutData.value = parsedData;
          dataLoaded.value = true;
        } catch (error) {
  }
})
.catch((error) => {
  console.error("请求失败:", error);
  ElMessage.error(t('basicData.msg.requestFailed'));
});
        }
      } else {
      }
    })
    .catch((error) => {
      console.error("请求失败:", error);
      ElMessage.error(t('basicData.msg.requestFailed'));
    });
}
onMounted(() => {
  selectLayout();
});
  const submitLayouts = async () => {
const submitLayouts = async () => {
  try {
    const response = await request.post('/glassOptimize/generateOpt', {
      Layouts: layoutData.value.Layouts
      Layouts: layoutData.value.Layouts
    }, {
      headers: {
        'Content-Type': 'application/json'
@@ -89,5 +85,4 @@
  </script>
</script>
north-glass-erp/northglass-erp/src/views/pp/processCard/AddProcessCard.vue
@@ -510,23 +510,29 @@
  const $gridLeft = xGridLeft.value
  const leftData = $gridLeft.getTableData().fullData
  //落架顺序
  // 获取最大落架顺序
  let index = 1
  if (leftData.length !== 0) {
    index = Math.max(...leftData.map(d => d.landingSequence || 0)) + 1
  }
  // 流程卡号
  let processId = null
  if (maxProcseeId) {
    const base = leftData.length !== 0 ? leftData[0].processId : maxProcseeId
    const lastThree = base.slice(-3)
    const result = parseInt(lastThree) + 1
    processId = productionId + result.toString().padStart(3, '0')
  } else {
    processId = productionId + index.toString().padStart(3, '0')
  // 生成 processId(最大尾号 + 1)
  let maxProcIdNum = 0
  if (leftData.length > 0) {
    maxProcIdNum = Math.max(...leftData.map(item => {
      const pid = item.processId
      return parseInt(pid?.slice(-3)) || 0
    }))
  }
  const baseIdNum = Math.max(
      maxProcIdNum,
      parseInt(maxProcseeId?.slice(-3) || '0')
  ) + 1
  const processId = productionId + baseIdNum.toString().padStart(3, '0')
  // 校验数量
  const regex = /^(\d+|)$/
  if (!regex.test(checkedNum.value)) {
    ElMessage.warning(t('processCard.schedulingNo'))
@@ -535,62 +541,65 @@
  try {
    if (/^[1-9]\d*$/.test(checkedNum.value)) {
      //有输入数量
      // 有输入数量的
      checkedList.forEach((item) => {
        if (item.baiscQuantity < checkedNum.value * 1) {
          throw new Error(t('processCard.schedulingQuantity'))
        }
        item.quantity = checkedNum.value * 1
        item.processId = processId
        item.landingSequence = index  // ✅ 同一批次,落架顺序一致
        item.baiscQuantity -= checkedNum.value * 1
        item.computeGrossArea = (
            item.computeGrossArea - item.width * item.height * checkedNum.value / 1000000
        const newItem = JSON.parse(JSON.stringify(item))
        newItem.quantity = checkedNum.value * 1
        newItem.processId = processId
        newItem.landingSequence = index
        newItem.baiscQuantity -= checkedNum.value * 1
        newItem.computeGrossArea = (
            newItem.computeGrossArea - newItem.width * newItem.height * checkedNum.value / 1000000
        ).toFixed(2)
        const key = item._X_ROW_KEY
        delete item._X_ROW_KEY
        if (item.baiscQuantity === 0) {
        if (item.baiscQuantity === newItem.quantity) {
          $grid.remove(item)
        } else {
          item.baiscQuantity -= newItem.quantity  // 保持右表剩余数量正确
          item.computeGrossArea = (
              item.computeGrossArea - item.width * item.height * newItem.quantity / 1000000
          ).toFixed(2)
        }
        const currentLeft = $gridLeft.getTableData().fullData
        $gridLeft.clearSort()
        $gridLeft.loadData([...currentLeft, item])
        item._X_ROW_KEY = key
        $gridLeft.loadData([...currentLeft, newItem])
      })
    } else if (checkedNum.value === '') {
      //没有输入数量
      checkedList.forEach((item) => {
        item.processId = processId
        item.landingSequence = index
        item.quantity = item.baiscQuantity
        delete item._X_ROW_KEY
      // 未输入数量
      const currentLeft = $gridLeft.getTableData().fullData
      const newList = checkedList.map(item => {
        const newItem = JSON.parse(JSON.stringify(item))
        newItem.quantity = newItem.baiscQuantity
        newItem.processId = processId
        newItem.landingSequence = index
        return newItem
      })
      $grid.remove(checkedList)
      const currentLeft = $gridLeft.getTableData().fullData
      $gridLeft.clearSort()
      $gridLeft.loadData([...currentLeft, ...checkedList])
      $gridLeft.loadData([...currentLeft, ...newList])
    }
    // 清空选择和输入
    $gridLeft.clearCheckboxRow()
    $grid.clearCheckboxRow()
    checkedNum.value = ''
    // 插入后视觉排序
    // $nextTick(() => {
    //   $gridLeft.sort('landingSequence', 'asc')
    // })
  } catch (e) {
    ElMessage.warning(e.message )
    ElMessage.warning(e.message || '流程卡创建失败')
  }
}
//按编号创建流程卡
const createProcessCardNo = () => {
  const $grid = xGrid.value
north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportController.java
@@ -30,14 +30,12 @@
    //流程卡进度
    @ApiOperation("流程卡进度")
    @SaCheckPermission("selectOrder.search")
    @PostMapping("/processCardProgress/{orderId}")
    public Result processCardProgress(@PathVariable String orderId, @RequestBody List<Integer> columns) {
        return Result.seccess(reportService.processCardProgressSv(orderId, columns));
    }
    @ApiOperation("跨工序次破")
    @SaCheckPermission("crossProcessBreaking.search")
    @PostMapping("/crossProcessBreaking/{pageNum}/{pageSize}/{selectDate}")
    public Result getOrderReport(@PathVariable Integer pageNum,
                                 @PathVariable Integer pageSize,
@@ -48,7 +46,6 @@
    }
    @ApiOperation("在制品报表")
    @SaCheckPermission("workInProgress.search")
    @PostMapping("/workInProgress/{pageNum}/{pageSize}/{orderId}/{inputProject}/{selectProcesses}/{optionVal}")
    public Result workInProgress(
            @PathVariable Integer pageNum,
@@ -63,7 +60,6 @@
    }
    @ApiOperation("工序待完成报表")
    @SaCheckPermission("processToBeCompleted.search")
    @PostMapping("/selectProcessToBeCompleted/{selectTime1}/{selectTime2}/{orderId}/{inputProject}/{selectProcesses}")
    public Result selectProcessToBeCompleted(
            @PathVariable Date selectTime1,
@@ -77,7 +73,6 @@
    }
    @ApiOperation("次破明细报表")
    @SaCheckPermission("damageReport.search")
    @PostMapping("/damageReport/{pageNum}/{pageSize}/{selectTime1}/{selectTime2}")
    public Result damageReport(
            @PathVariable Integer pageNum,
@@ -90,7 +85,6 @@
    }
    @ApiOperation("分架明细报表")
    @SaCheckPermission("splittingDetailsOutside.search")
    @PostMapping("/splittingDetailsOutside/{orderId}")
    public Result splittingDetailsOutside(
            @PathVariable String orderId,
@@ -100,7 +94,6 @@
    }
    @ApiOperation("品质报表")
    @SaCheckPermission("qualityReport.search")
    @PostMapping("/qualityReport/{selectTime1}/{selectTime2}")
    public Result qualityReport(
            @PathVariable Date selectTime1,
@@ -111,7 +104,6 @@
    }
    @ApiOperation("成品率报表")
    @SaCheckPermission("yield.search")
    @PostMapping("/yield/{selectTime1}/{selectTime2}/{selectProcesses}")
    public Result yield(
            @PathVariable Date selectTime1,
@@ -123,14 +115,12 @@
    }
    @ApiOperation("生产发货进度")
    @SaCheckPermission("productionSchedule.search")
    @PostMapping("/productionSchedule/{orderId}")
    public Result productionSchedule(@PathVariable String orderId, @RequestBody List<Integer> columns) {
        return Result.seccess(reportService.productionScheduleSv(orderId, columns));
    }
    @ApiOperation("任务完成情况汇总进度")
    @SaCheckPermission("taskCompletionStatus.search")
    @PostMapping("/taskCompletionStatus/{selectTime1}/{selectTime2}/{orderId}")
    public Result taskCompletionStatus(@PathVariable Date selectTime1,
                                       @PathVariable Date selectTime2,
@@ -140,7 +130,6 @@
    }
    @ApiOperation("订单计划分解")
    @SaCheckPermission("orderPlanDecomposition.search")
    @PostMapping("/orderPlanDecomposition/{selectTime1}/{selectTime2}")
    public Result orderPlanDecomposition(@PathVariable Date selectTime1,
                                         @PathVariable Date selectTime2,
@@ -149,7 +138,6 @@
    }
    @ApiOperation("订单报工")
    @SaCheckPermission("orderPlanDecomposition.search")
    @PostMapping("/orderReportingWorks/{selectTime1}/{selectTime2}")
    public Result orderReportingWorks(@PathVariable Date selectTime1,
                                         @PathVariable Date selectTime2,
@@ -158,7 +146,6 @@
    }
    @ApiOperation("原片领料")
    @SaCheckPermission("rawMaterialRequisition.search")
    @PostMapping("/rawMaterialRequisition/{selectTime1}/{selectTime2}")
    public Result rawMaterialRequisition(@PathVariable Date selectTime1,
                                         @PathVariable Date selectTime2,
@@ -167,7 +154,6 @@
    }
    @ApiOperation("班组产量明细报表")
    @SaCheckPermission("damageReport.search")
    @PostMapping("/teamOutput/{pageNum}/{pageSize}/{selectTime1}/{selectTime2}/{selectProcesses}")
    public Result teamOutput(
            @PathVariable Integer pageNum,
@@ -291,7 +277,6 @@
    }
    @ApiOperation("在制品汇总报表")
    @SaCheckPermission("workInProgress.search")
    @PostMapping("/workInProgressCombination/{pageNum}/{pageSize}/{orderId}/{inputProject}/{selectProcesses}/{optionVal}")
    public Result workInProgressCombination(
            @PathVariable Integer pageNum,