廖井涛
2025-08-14 3a23449ea810c6d0c9a3ece8d986246cba8e7706
Merge branch 'master' of http://10.153.19.25:10101/r/ERP_override
22个文件已修改
1个文件已添加
743 ■■■■ 已修改文件
north-glass-erp/northglass-erp/src/components/sd/order/OrderProcess.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/hook/copyTableCellValue.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/ar.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/en.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/kr.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/ru.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/lang/zh.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/companySet/天津北玻.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/companySet/常州吉利.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/companySet/新疆恒鑫.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/companySet/洛阳北玻.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/stores/sd/companySet/金华天成.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/report/ProcessCardProgress.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/MaterialBOM.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/OrderBOM.vue 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/order/CreateOrder.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportController.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/java/com/example/erp/service/pp/ReportService.java 162 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/pp/DamageDetails.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/pp/Report.xml 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/sd/OrderProcessDetailMapper.xml 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/components/sd/order/OrderProcess.vue
@@ -1,9 +1,12 @@
<script setup>
import {computed, onMounted, reactive, ref, watch} from "vue";
import {addListener,destroyAreaBox} from "@/hook/mouseMoveHomePage";
import {changeFilterEvent, filterChanged} from "@/hook"
import {useI18n} from "vue-i18n"
import request from "@/utils/request"
import {ElMessage} from "element-plus"
import VxeUI from "vxe-pc-ui";
import {copyTableCellValue,copyTableCellValueShow} from "@/hook/copyTableCellValue";
const { t } = useI18n()
const xGrid = ref()
const gridOptions = reactive({
@@ -25,6 +28,7 @@
  filterConfig: {   //筛选配置项
    // remote: true
  },
  mouseConfig:{selected: true},
  columnConfig: {
    resizable: true,
    useKey: true
@@ -64,6 +68,17 @@
    ]
  }
})
const gridEvents = {
  cellDblclick ({row,column}) {
    if(orderType.value===1){
      copyTableCellValue(row,column)
    }else{
      copyTableCellValueShow(row,column)
    }
  }
}
const list = ref([])
let props = defineProps({
@@ -84,8 +99,9 @@
  {field: 'glassQuantity', width: 90,title: t('order.glassQuantity')},
  {field: 'grossArea',slots: { default: 'show'}, width: 90,title: t('order.area')},
  {field: 'shippedQuantity',slots: { default: 'show'},width: 120, title: t('delivery.deliveryQuantity')},
  {field: 'inventory',slots: { default: 'show'},width: 120, title: t('productStock.inventoryQuantity')},
  {field: 'inventoryArea',slots: { default: 'show'},width: 120, title: t('report.inventoryArea')},
  {field: 'shippedArea',slots: { default: 'show'},width: 120, title: t('report.shippedArea')},
  {field: 'Storage',slots: { default: 'show'},width: 120, title: t('report.inventoryNum')},
  // {field: 'inventoryArea',slots: { default: 'show'},width: 120, title: t('report.inventoryArea')},
  {field: 'StorageArea',slots: { default: 'show'},width: 120, title: t('report.StorageArea')},
  {field: 'broken_num',width: 90, title: t('reportingWorks.quantityBroken')},
]
@@ -94,6 +110,7 @@
onMounted(()=>{
  getWorkOrder()
  //addListener(xGrid.value,gridOptions)
})
watch(()=>props.orderId,(newValue)=>{
@@ -146,7 +163,7 @@
      gridOptions.columns.forEach(item =>{
        item.filterMethod = filterChanged
      })
      list.value = ['quantity','inventory','inventoryArea','gross_area','shippedQuantity','glassQuantity','StorageArea']
      list.value = ['quantity','Storage','gross_area','shippedQuantity','shippedArea','glassQuantity','StorageArea']
      title.value = res.data.title
      res.data.title.forEach((item,index) =>{
        list.value.push('reportWorkQuantity.'+item.process)
@@ -240,6 +257,7 @@
        class="mytable-scrollbar"
        ref="xGrid"
        v-bind="gridOptions"
        v-on="gridEvents"
    >
      <template #num1_filter="{ column, $panel }">
        <div>
@@ -286,5 +304,13 @@
::v-deep(.vxe-grid .vxe-body--column.row-green) {
  background-color: #D5EAFF;
}
.vxe-grid {
  /* ç¦ç”¨æµè§ˆå™¨é»˜è®¤é€‰ä¸­ */
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  transform: translateZ(0);
}
</style>
north-glass-erp/northglass-erp/src/hook/copyTableCellValue.js
New file
@@ -0,0 +1,32 @@
import VxeUI from "vxe-pc-ui";
function copyTableCellValueShow(row, column) {
    if(column.field.indexOf('.')>-1){
        let  array = column.field.split('.')
        if (row[array[0]][array[1]+'Show']!==null){
            VxeUI.clipboard.copy(row[array[0]+'Show'][array[1]])
        }
    }else {
        if (row[column.field+'Show']!==null){
            VxeUI.clipboard.copy(row[column.field+'Show'])
        }
    }
}
function copyTableCellValue(row, column) {
    if(column.field.indexOf('.')>-1){
        let  array = column.field.split('.')
        if (row[array[0]][array[1]]!==null){
            VxeUI.clipboard.copy(row[array[0]][array[1]])
        }
    }else {
        if (row[column.field]!==null){
            VxeUI.clipboard.copy(row[column.field])
        }
    }
}
export {copyTableCellValue,copyTableCellValueShow}
north-glass-erp/northglass-erp/src/lang/ar.js
@@ -71,6 +71,7 @@
        copy:'复制',
        msg:{
            max255:'أدخل 255 Ø­Ø±ÙÙ‹Ø§ ÙƒØ­Ø¯ Ø£Ù‚صى',
            max10:"最多输入10个字符",
            range99999Dec2:
                'يرجى Ø¥Ø¯Ø®Ø§Ù„ Ø±Ù‚Ù… Ø¨ÙŠÙ† 0 Ùˆ99999 Ø¨Ø­Ø¯ Ø£Ù‚صى Ø±Ù‚مين Ø¹Ø´Ø±ÙŠÙŠÙ†',
            range99999Dec3:
@@ -1073,7 +1074,8 @@
        finished :'معدل Ø§Ù„منتجات Ø§Ù„نهائية',
        finishedProductReport :'تقرير Ø§Ù„منتجات Ø§Ù„نهائية',
        workProcessName:'在制品名称',
        StorageArea:'入库面积'
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/en.js
@@ -71,6 +71,7 @@
        copy:'Copy',
        msg:{
            max255:"The value contains a maximum of 255 characters",
            max10:"最多输入10个字符",
            range99999Dec2:
                "Please enter a number between 0 and 99999 with a maximum of two decimals",
            range99999Dec3:
@@ -1076,7 +1077,8 @@
        finished :'Rate of finished product',
        finishedProductReport :'Finished product report',
        workProcessName:'在制品名称',
        StorageArea:'入库面积'
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/kr.js
@@ -71,6 +71,7 @@
        copy:'주문 ë³µì œ',
        msg:{
            max255:"최대 255자 ìž…ë ¥ ê°€ëŠ¥",
            max10:"最多输入10个字符",
            range99999Dec2:
                "0부터 99,999까지의 ìˆ«ìž ìž…ë ¥. ì†Œìˆ˜ì  ë‘˜ì§¸ ìžë¦¬ê¹Œì§€ í—ˆìš©",
            range99999Dec3:
@@ -1084,7 +1085,8 @@
        finished :'양품률',
        finishedProductReport :'완제품 ë³´ê³ ì„œ',
        workProcessName:'在制品名称',
        StorageArea:'入库面积'
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/ru.js
@@ -71,6 +71,7 @@
        copy:'复制',
        msg:{
            max255:"Введите 255 ÑÐ¸Ð¼Ð²Ð¾Ð»Ð¾Ð².",
            max10:"最多输入10个字符",
            range99999Dec2:
                "Введите Ñ‡Ð¸ÑÐ»Ð¾ Ð¼ÐµÐ¶Ð´Ñƒ 0 - 99999 Ð¸ ÑÐ¾Ñ…раните Ð´Ð¾ Ð´Ð²ÑƒÑ… Ð´ÐµÑÑÑ‚ичных Ð·Ð½Ð°ÐºÐ¾Ð².",
            range99999Dec3:
@@ -1072,7 +1073,8 @@
        finished :'Коэффициент Ð³Ð¾Ñ‚овой Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ†Ð¸Ð¸',
        finishedProductReport :'Отчет Ð¾ Ð³Ð¾Ñ‚овой Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ†Ð¸Ð¸',
        workProcessName:'在制品名称',
        StorageArea:'入库面积'
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
        page:{
north-glass-erp/northglass-erp/src/lang/zh.js
@@ -71,6 +71,7 @@
        copy:'复制',
        msg:{
            max255:"最多输入255个字符",
            max10:"最多输入10个字符",
            range99999Dec2:
                "请输入0-99999之间的数字,最多保留两位小数",
            range99999Dec3:
@@ -1088,7 +1089,8 @@
        finished :'成品率',
        finishedProductReport :'成品报表',
        workProcessName:'在制品名称',
        StorageArea:'入库面积'
        StorageArea:'入库面积',
        shippedArea:'发货面积'
    },
    productionBasicData:{
north-glass-erp/northglass-erp/src/stores/sd/companySet/Ìì½ò±±²£.js
@@ -3,6 +3,7 @@
export default defineStore('companyInfo', {
    state: () => ({
        edgingType:false,//产品创建磨边类型是否必选
        hollow:'*',
        notChangeProduct:true,//天津true,其他false,是否开启非本人创建的产品不能修改
        timeOut:false,//金华true,其他false,是否开启超时改变复选框状态
north-glass-erp/northglass-erp/src/stores/sd/companySet/³£ÖݼªÀû.js
@@ -3,6 +3,7 @@
export default defineStore('companyInfo', {
    state: () => ({
        edgingType:false,//产品创建磨边类型是否必选
        hollow:'*',
        notChangeProduct:false,//天津true,其他false,是否开启非本人创建的产品不能修改
        timeOut:false,//金华true,其他false,是否开启超时改变复选框状态
north-glass-erp/northglass-erp/src/stores/sd/companySet/н®ºãöÎ.js
@@ -3,6 +3,7 @@
export default defineStore('companyInfo', {
    state: () => ({
        edgingType:false,//产品创建磨边类型是否必选
        hollow:'*',
        notChangeProduct:false,//天津true,其他false,是否开启非本人创建的产品不能修改
        timeOut:false,//金华true,其他false,是否开启超时改变复选框状态
north-glass-erp/northglass-erp/src/stores/sd/companySet/ÂåÑô±±²£.js
@@ -3,7 +3,8 @@
export default defineStore('companyInfo', {
    state: () => ({
        hollow:'+',
        edgingType:true,//产品创建磨边类型是否必选
        hollow:'+',//产品创建中空用+号或星号
        notChangeProduct:false,//天津true,其他false,是否开启非本人创建的产品不能修改
        timeOut:false,//金华true,其他false,是否开启发货超时改变复选框状态颜色
        connectMes:false,//常州,义乌true,其他false,显示订单报工转移是否启用
north-glass-erp/northglass-erp/src/stores/sd/companySet/½ð»ªÌì³É.js
@@ -3,6 +3,7 @@
export default defineStore('companyInfo', {
    state: () => ({
        edgingType:false,//产品创建磨边类型是否必选
        hollow:'*',
        notChangeProduct:false,//天津true,其他false,是否开启非本人创建的产品不能修改
        timeOut:true,//金华true,其他false,是否开启发货超时改变复选框状态颜色
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -648,11 +648,11 @@
  adjustGrayRectangles(layoutIndex);
};
const mergeAdjacentGrayRects = (glassDetails,totalWidth,totalHeight) => {
const mergeAdjacentGrayRects = (glassDetails, totalWidth, totalHeight) => {
  const grayRects = glassDetails.filter(r => r.isRemain);
  const grayRects2 = glassDetails.filter(r => r.isRemain);
  let merged = [];
  const nonGrayRects = glassDetails.filter(r => !r.isRemain);
  // æŒ‰åæ ‡æŽ’序,优先按x坐标,其次按y坐标
  grayRects.sort((a, b) => {
    if (a.x !== b.x) return a.x - b.x;
    return a.y - b.y;
@@ -660,30 +660,31 @@
  if (grayRects.length === 0) return;
  merged.push({ ...grayRects[0] });
  const merged = [];
  // ä»Žç¬¬ä¸€ä¸ªçŸ©å½¢å¼€å§‹
  let current = { ...grayRects[0] };
  // éåŽ†æ‰€æœ‰ä½™æ–™çŸ©å½¢è¿›è¡Œåˆå¹¶
  for (let i = 1; i < grayRects.length; i++) {
      const last = merged[merged.length-1];
      const current = grayRects[i];
    const next = grayRects[i];
    if (current.x === last.x + last.width &&
        current.y === last.y &&
        current.height === last.height) {
      last.width += current.width;
      last.x = Math.round(last.x);
      last.y = Math.round(last.y);
      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.width === last.width) {
      last.height += current.height;
      last.x = Math.round(last.x);
      last.y = Math.round(last.y);
      last.width = Math.round(last.width);
      last.height = Math.round(last.height);
    } else {
    // æ£€æŸ¥æ˜¯å¦å¯ä»¥æ°´å¹³åˆå¹¶ï¼ˆåŒä¸€è¡Œï¼Œé«˜åº¦ç›¸åŒï¼Œç›¸é‚»ï¼‰
    if (current.y === next.y &&
        current.height === next.height &&
        current.x + current.width === next.x) {
      // æ°´å¹³åˆå¹¶
      current.width += next.width;
    }
    // æ£€æŸ¥æ˜¯å¦å¯ä»¥åž‚直合并(同一列,宽度相同,相邻)
    else if (current.x === next.x &&
        current.width === next.width &&
        current.y + current.height === next.y) {
      // åž‚直合并
      current.height += next.height;
    }
    else {
      // æ— æ³•合并,保存当前矩形,开始新的合并
      merged.push({
        x: Math.round(current.x),
        y: Math.round(current.y),
@@ -691,54 +692,100 @@
        height: Math.round(current.height),
        isRemain: true
      });
      current = { ...next };
    }
  }
  const nonGray = glassDetails.filter(r => !r.isRemain);
  //删除原数组拼接新的小片跟余料
  glassDetails.splice(0, glassDetails.length, ...nonGray, ...merged);
  // é‡æ–°æž„建数组:非余料 + åˆå¹¶åŽçš„余料
  glassDetails.splice(0, glassDetails.length, ...nonGrayRects, ...merged);
};
// ç¡®ä¿è¿”回的区域不重叠
const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
  // ä»Žæ•´ä¸ªåŽŸç‰‡å¼€å§‹
  let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
  // é€ä¸ªå¤„理障碍物(已放置的玻璃片)
  obstacles.forEach(obstacle => {
    remaining = cutRemainingAreas(remaining, obstacle, totalWidth, totalHeight);
  });
  // å¯¹ç»“果进行排序,确保一致性
  remaining.sort((a, b) => {
    if (a.x !== b.x) return a.x - b.x;
    return a.y - b.y;
  });
  return remaining;
};
// è°ƒæ•´åŽé‡æ–°è®¡ç®—灰色余料
const adjustGrayRectangles = (layoutIndex) => {
  const layout = layouts.value[layoutIndex];
  const glassDetails = layout.glassDetails;
  //小片的数据
  // 1. ç­›é€‰å‡ºéžä½™æ–™çš„玻璃片(即实际要切割的玻璃片)
  const nonGrayRects = glassDetails.filter(glassDetail => !glassDetail.isRemain);
  //所有的小片余料坐标跟尺寸
  // 2. è®¡ç®—剩余可用区域
  let remainingAreas = calculateRemainingAreas(layout.width, layout.height, nonGrayRects);
  const uniqueArr = Array.from(
      new Set(remainingAreas.map(item => JSON.stringify(item)))
  ).map(item => JSON.parse(item));
  //余料的数据
  // 3. åŽ»é‡å¤„ç† - æ›´ä¸¥æ ¼çš„去重逻辑
  const uniqueArr = removeDuplicateAreas(remainingAreas);
  // 4. èŽ·å–å½“å‰å·²å­˜åœ¨çš„ä½™æ–™çŸ©å½¢ï¼ˆéœ€è¦ä¿ç•™å¼•ç”¨ä»¥ä¾¿æ›´æ–°ï¼‰
  const currentGrayRects = glassDetails.filter(r => r.isRemain);
  //循环余料数据跟全部的对比
  currentGrayRects.forEach((_, index) => {
    if (index >= remainingAreas.length) {
      glassDetails.splice(index, 1);
    }
  // 5. æ¸…除所有现有的余料矩形
  // å…ˆæ”¶é›†éžä½™æ–™çŸ©å½¢
  const nonRemainRects = glassDetails.filter(r => !r.isRemain);
  // 6. é‡æ–°æž„建玻璃详情数组
  // ä¿ç•™éžä½™æ–™çŸ©å½¢
  const newGlassDetails = [...nonRemainRects];
  // æ·»åŠ æ–°çš„ä½™æ–™çŸ©å½¢
  uniqueArr.forEach((area) => {
    newGlassDetails.push({
      x: Math.round(area.x),
      y: Math.round(area.y),
      width: Math.round(area.width),
      height: Math.round(area.height),
      isRemain: true
    });
  });
  uniqueArr.forEach((area, index) => {
    if (index < currentGrayRects.length) {
      currentGrayRects[index].x = Math.round(area.x);
      currentGrayRects[index].y = Math.round(area.y);
      currentGrayRects[index].width = Math.round(area.width);
      currentGrayRects[index].height = Math.round(area.height);
    } else {
      glassDetails.push({
        x: Math.round(area.x),
        y: Math.round(area.y),
        width: Math.round(area.width),
        height: Math.round(area.height),
        isRemain: true
      });
    }
  });
  // 7. æ›´æ–°å¸ƒå±€çš„玻璃详情
  layout.glassDetails = newGlassDetails;
  mergeAdjacentGrayRects(glassDetails,layout.width, layout.height);
  // 8. åˆå¹¶ç›¸é‚»çš„余料矩形
  mergeAdjacentGrayRects(layout.glassDetails, layout.width, layout.height);
};
const removeDuplicateAreas = (areas) => {
  const result = [];
  areas.forEach(area => {
    // æ£€æŸ¥æ˜¯å¦ä¸Žå·²å­˜åœ¨çš„区域重叠或相等
    const isDuplicate = result.some(existingArea => {
      return (
          existingArea.x === area.x &&
          existingArea.y === area.y &&
          existingArea.width === area.width &&
          existingArea.height === area.height
      );
    });
    if (!isDuplicate) {
      result.push(area);
    }
  });
  return result;
};
//旋转方法
const rotateRect = (layoutIndex, rectIndex) => {
@@ -882,19 +929,24 @@
};
//重新计算余料坐标以及尺寸1
const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
  let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
  obstacles.forEach(glassDetail => {
    remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
  });
  return remaining;
};
// const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
//   let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
//   obstacles.forEach(glassDetail => {
//     remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
//   });
//   return remaining;
// };
//重新计算余料坐标以及尺寸2
const cutRemainingAreas = (remainingAreas, obstacle,totalWidth,totalHeight) => {
const cutRemainingAreas = (remainingAreas, obstacle, totalWidth, totalHeight) => {
  const newRemaining = [];
  remainingAreas.forEach(area => {
    // å¦‚果障碍物与当前区域有重叠
    if (checkOverlap(area, obstacle)) {
      // åˆ‡åˆ†å½“前区域为最多4个新区域
      // å·¦ä¾§åŒºåŸŸ
      if (obstacle.x > area.x) {
        newRemaining.push({
          x: area.x,
@@ -903,35 +955,50 @@
          height: area.height
        });
      }
      // å³ä¾§åŒºåŸŸ
      if (obstacle.x + obstacle.width < area.x + area.width) {
        newRemaining.push({
          x: obstacle.x + obstacle.width,
          y: area.y,
          width: area.width - (obstacle.x + obstacle.width - area.x),
          width: area.x + area.width - (obstacle.x + obstacle.width),
          height: area.height
        });
      }
      if (obstacle.y > area.y) {
        newRemaining.push({
          x: area.x,
          y: area.y,
          width: area.width,
          height: obstacle.y - area.y
        });
      }
      if (obstacle.y + obstacle.height < area.y + area.height ) {
          newRemaining.push({
            x: area.x,
            y: obstacle.y + obstacle.height,
            width: area.width,
            height: area.height - (obstacle.y + obstacle.height - area.y)
          });
      // ä¸Šæ–¹åŒºåŸŸï¼ˆä»…在障碍物左右边界之间的区域)
      if (obstacle.y > area.y) {
        const startX = Math.max(area.x, obstacle.x);
        const endX = Math.min(area.x + area.width, obstacle.x + obstacle.width);
        if (endX > startX) {
          newRemaining.push({
            x: startX,
            y: area.y,
            width: endX - startX,
            height: obstacle.y - area.y
          });
        }
      }
      // ä¸‹æ–¹åŒºåŸŸï¼ˆä»…在障碍物左右边界之间的区域)
      if (obstacle.y + obstacle.height < area.y + area.height) {
        const startX = Math.max(area.x, obstacle.x);
        const endX = Math.min(area.x + area.width, obstacle.x + obstacle.width);
        if (endX > startX) {
          newRemaining.push({
            x: startX,
            y: obstacle.y + obstacle.height,
            width: endX - startX,
            height: area.y + area.height - (obstacle.y + obstacle.height)
          });
        }
      }
    } else {
      // æ²¡æœ‰é‡å ï¼Œä¿ç•™åŽŸåŒºåŸŸ
      newRemaining.push(area);
    }
  });
  return newRemaining;
};
north-glass-erp/northglass-erp/src/views/pp/report/ProcessCardProgress.vue
@@ -63,7 +63,7 @@
//点击查询
const getWorkOrder = () => {
  gridOptions.columns = gridOptions.columns.slice(0, 11); //清除动态生成的列重新查询
  request.post(`/report/processCardProgress/${form.orderId}`, column).then((res) => {
  request.post(`/report/processCardProgressReport/${form.orderId}`, column).then((res) => {
    if (res.code == 200) {
      if (res.data.data.length === 0) {
        ElMessage.warning(t('report.noDataFoundForThisOrder'))
north-glass-erp/northglass-erp/src/views/sd/bom/MaterialBOM.vue
@@ -399,13 +399,13 @@
      id="print"
      v-model="dialogTableVisible"
      destroy-on-close
      style="width: 40%;height:40%;"
      style="width: 400px;height:280px;margin-top: 200px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
  >
    <el-form
        ref="ruleFormRef"
        style="max-width: 600px"
        style="max-width: 600px;"
        :model="ruleForm"
        status-icon
        :rules="rules"
@@ -429,10 +429,11 @@
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)">
        <el-button style="margin-left: 235px" @click="resetForm(ruleFormRef)">重置</el-button>
        <el-button style="float: right"  type="primary" @click="submitForm(ruleFormRef)">
          æäº¤
        </el-button>
        <el-button @click="resetForm(ruleFormRef)">重置</el-button>
      </el-form-item>
    </el-form>
north-glass-erp/northglass-erp/src/views/sd/bom/OrderBOM.vue
@@ -657,19 +657,104 @@
        id="print"
        v-model="dialogTableVisible"
        destroy-on-close
        style="width: 90%;height:90%;margin-top: 3vh "
        style="width: 600px;height: 600px"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
    >
        <el-card style="max-width: 480px">
          <template #header>
            <div class="card-header">
              <span>产品1</span>
            </div>
          </template>
          <p v-for="o in 4" :key="o" class="text item">{{ '用料 ' + o +":xx元" }}</p>
          <template #footer>合计xx元</template>
        </el-card>
      <el-card style="max-width: 480px;margin-left: 45px">
        <template #header>
          <div class="card-header">
            <span style="font-weight: bold">成品合计</span>
            &nbsp &nbsp &nbsp
            <span>面积:1312.48㎡</span>
            &nbsp &nbsp &nbsp
            <span>数量:200</span>
            &nbsp &nbsp &nbsp
            <span>周长:5325.7m</span>
          </div>
        </template>
        <el-row >
          <el-col :span="8">6mm超白:</el-col>
          <el-col :span="8">3149.72㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">8mm超白:</el-col>
          <el-col :span="8">787.72㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">铝框:</el-col>
          <el-col :span="8">2662.85m</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">0.76PVB:</el-col>
          <el-col :span="8">1706.22㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">其他:</el-col>
          <el-col :span="8">5</el-col>
        </el-row>
      </el-card>
      <el-card style="max-width: 480px;margin-left: 45px;margin-top: 20px">
        <template #header>
          <div class="card-header">
            <span style="font-weight: bold">6mm超白钢化+12A+6mm超白钢化+0.76PVB+6mm超白钢化</span>
            <br/>
            <span>面积:656.24㎡</span>
            &nbsp &nbsp &nbsp
            <span>数量:100</span>
            &nbsp &nbsp &nbsp
            <span>周长:2662.85m</span>
          </div>
        </template>
        <el-row >
          <el-col :span="8">6mm超白:</el-col>
          <el-col :span="8">2362.464㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">铝框:</el-col>
          <el-col :span="8">2662.85m</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">0.76PVB:</el-col>
          <el-col :span="8">853.11㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">其他:</el-col>
          <el-col :span="8">5</el-col>
        </el-row>
<!--          <template #footer>合计xx元</template>-->
      </el-card>
      <el-card style="max-width: 480px;margin-left: 45px;margin-top: 20px">
        <template #header>
          <div class="card-header">
            <span style="font-weight: bold">8mm超白钢化+0.76PVB+6mm超白钢化</span>
            <br/>
            <span>面积:656.24㎡</span>
            &nbsp &nbsp &nbsp
            <span>数量:100</span>
            &nbsp &nbsp &nbsp
            <span>周长:2662.85m</span>
          </div>
        </template>
        <el-row >
          <el-col :span="8">6mm超白:</el-col>
          <el-col :span="8">787.72㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">8mm超白:</el-col>
          <el-col :span="8">787.72㎡</el-col>
        </el-row>
        <el-row>
          <el-col :span="8">0.76PVB:</el-col>
          <el-col :span="8">853.11㎡</el-col>
        </el-row>
        <!--          <template #footer>合计xx元</template>-->
      </el-card>
    </el-dialog>
@@ -702,6 +787,8 @@
  background-color: orangered;
  border-color: orangered;
}
.el-row{
  text-align: center
}
</style>
north-glass-erp/northglass-erp/src/views/sd/order/CreateOrder.vue
@@ -191,6 +191,10 @@
  ],
  //表单验证
  editRules: {
    edgingType: [
      { required: company.edgingType},
      { min: 0, max: 10, message: t('basicData.msg.max10') }
    ],
    buildingNumber: [
      { required: false},
      { min: 0, max: 255, message: t('basicData.msg.max255') }
north-glass-erp/src/main/java/com/example/erp/controller/pp/ReportController.java
@@ -29,11 +29,16 @@
    }
    //流程卡进度
    @ApiOperation("流程卡进度")
    @ApiOperation("订单流程卡进度")
    @PostMapping("/processCardProgress/{orderId}")
    public Result processCardProgress(@PathVariable String orderId, @RequestBody List<Integer> columns) {
        return Result.seccess(reportService.processCardProgressSv(orderId, columns));
    }
    @ApiOperation("报表流程卡进度")
    @PostMapping("/processCardProgressReport/{orderId}")
    public Result processCardProgressReport(@PathVariable String orderId, @RequestBody List<Integer> columns) {
        return Result.seccess(reportService.processCardProgressReportSv(orderId, columns));
    }
    @ApiOperation("流程卡进度汇总")
    @SaCheckPermission("selectOrder.search")
    @PostMapping("/processCardProgressCollect/{orderId}")
north-glass-erp/src/main/java/com/example/erp/mapper/pp/ReportMapper.java
@@ -124,6 +124,8 @@
    List<Map<String, String>> processCardProgressCollectMp(String orderId);
    List<Map<String, String>> processCardProgressReportMp(String orderId);
//    Map<String, Integer> getWorkInProgressTotal(
//                                                @Param("selectTime1") Date selectTime1, @Param("selectTime2") Date selectTime2,
north-glass-erp/src/main/java/com/example/erp/service/pp/ReportService.java
@@ -156,7 +156,7 @@
                            .eq("basic_name",uniqueList.get(i).get("process"))
                            .last("limit 1")
            );
            //判断磨边和磨边后工序
            //判断夹胶和夹胶后工序
            //Objects.equals(basicData.getNickname(), "stepA") || Objects.equals(basicData.getNickname(), "stepC")
            if(Objects.equals(basicData.getNickname(), "stepA") || Objects.equals(basicData.getNickname(), "stepC")){
                clos.put(uniqueList.get(i).get("process"), 16+i);
@@ -164,7 +164,7 @@
            //判断中空和中空后工序
            //Objects.equals(basicData.getNickname(), "stepB") || Objects.equals(basicData.getNickname(), "stepD")
            if(Objects.equals(basicData.getNickname(), "stepB") || Objects.equals(basicData.getNickname(), "stepD")){
                columns.add(15+i);
                columns.add(16+i);
            }
        }
@@ -182,53 +182,53 @@
                rowCount.add(getRow);
            });
        });
        if(!clos.isEmpty()){
            //循环结果
            for (int i=0;i<dataList.size();i++ ) {
                Map<String, String> data = JSON.parseObject(dataList.get(i).get("reportWorkQuantity"),
                        new TypeReference<Map<String, String>>() {
                        });
                Map<String, String> dataShow = JSON.parseObject(dataList.get(i).get("reportWorkQuantityShow"),
                        new TypeReference<Map<String, String>>() {
                        });
               //判断后工序此流程卡号是否有次破
                List<DamageDetails> hasBreak = damageDetailsMapper
                        .selectList(new LambdaQueryWrapper<DamageDetails>()
                                .eq(DamageDetails::getProcessId, dataList.get(i).get("processId"))
                                .eq(DamageDetails::getOrderNumber, dataList.get(i).get("order_number"))
                                .eq(DamageDetails::getTechnologyNumber, dataList.get(i).get("technology_number"))
                                .eq(DamageDetails::getPatchStatus, 0)
                                .gt(DamageDetails::getBreakageQuantity,0)
                        );
                if(!hasBreak.isEmpty()){
                    int finalI = i;
                    data.forEach((thisProcess, index)->{
                        String behindProcess = orderProcessDetailMapper.getBehindProcess(
            //循环结果
        for (int i=0;i<dataList.size();i++ ) {
            Map<String, String> data = JSON.parseObject(dataList.get(i).get("reportWorkQuantity"),
                    new TypeReference<Map<String, String>>() {
                    });
            Map<String, String> dataShow = JSON.parseObject(dataList.get(i).get("reportWorkQuantityShow"),
                    new TypeReference<Map<String, String>>() {
                    });
           //判断后工序此流程卡号是否有次破
            List<DamageDetails> hasBreak = damageDetailsMapper
                    .selectList(new LambdaQueryWrapper<DamageDetails>()
                            .eq(DamageDetails::getProcessId, dataList.get(i).get("processId"))
                            .eq(DamageDetails::getOrderNumber, dataList.get(i).get("order_number"))
                            .eq(DamageDetails::getTechnologyNumber, dataList.get(i).get("technology_number"))
                            .eq(DamageDetails::getPatchStatus, 0)
                            .gt(DamageDetails::getBreakageQuantity,0)
                    );
            if(!hasBreak.isEmpty()){
                int finalI = i;
                data.forEach((thisProcess, index)->{
                    String behindProcess = orderProcessDetailMapper.getBehindProcess(
                            dataList.get(finalI).get("processId"),
                            String.valueOf(dataList.get(finalI).get("order_number")),
                            String.valueOf(dataList.get(finalI).get("technology_number")),
                            thisProcess,
                            orderId
                    );
                    if(behindProcess!=null &&!behindProcess.isEmpty()){
                        Integer behindDamageSum = damageDetailsMapper.getBehindDamageSum(
                                dataList.get(finalI).get("processId"),
                                String.valueOf(dataList.get(finalI).get("order_number")),
                                String.valueOf(dataList.get(finalI).get("technology_number")),
                                thisProcess,
                                orderId
                                behindProcess
                        );
                        if(behindProcess!=null &&!behindProcess.isEmpty()){
                            Integer behindDamageSum = damageDetailsMapper.getBehindDamageSum(
                                    dataList.get(finalI).get("processId"),
                                    String.valueOf(dataList.get(finalI).get("order_number")),
                                    String.valueOf(dataList.get(finalI).get("technology_number")),
                                    behindProcess
                            );
                            if(behindDamageSum>0){
                                data.put(thisProcess, String.valueOf(Integer.parseInt(data.get(thisProcess) )- behindDamageSum));
                                dataShow.put(thisProcess, String.valueOf(Integer.parseInt(dataShow.get(thisProcess) )- behindDamageSum));
                            }
                        if(behindDamageSum>0){
                            data.put(thisProcess, String.valueOf(Integer.parseInt(data.get(thisProcess) )- behindDamageSum));
                            dataShow.put(thisProcess, String.valueOf(Integer.parseInt(dataShow.get(thisProcess) )- behindDamageSum));
                        }
                    });
                }
                    }
                });
            }
            if(!clos.isEmpty()){
                Integer max = orderGlassDetailMapper
                        .getMaxTechnologyNumberByGroup(dataList.get(i).get("order_id"),
@@ -240,6 +240,7 @@
                                String.valueOf(dataList.get(i).get("order_number")),
                                String.valueOf(dataList.get(i).get("group"))
                        );
                for (String key : clos.keySet()) {
                    if(data.get(key) != null){
@@ -257,11 +258,12 @@
                    }
                }
                dataList.get(i).put("reportWorkQuantity",JSON.toJSONString(data));
                dataList.get(i).put("reportWorkQuantityShow",JSON.toJSONString(dataShow));
            }
            dataList.get(i).put("reportWorkQuantity",JSON.toJSONString(data));
            dataList.get(i).put("reportWorkQuantityShow",JSON.toJSONString(dataShow));
        }
@@ -828,4 +830,78 @@
        map.put("title", uniqueList);
        return  null;
    }
    public Map<String, Object> processCardProgressReportSv(String orderId, List<Integer> columns) {
        Map<String, Object> map = new HashMap<>();
        //获取表格内容数据
        map.put("data", reportMapper.processCardProgressReportMp(orderId));
        //获取表头工序筛选数据
        List<Map<String, String>> processFilterList = orderProcessDetailMapper.filterOrderProcess(orderId);
        List<Map<String, String>> processList = processFilterList;
        List<String> filterList = new ArrayList<>();
        //循环遍历数组,判断此序号当前的工序
        for (int i = 1; i < processFilterList.size(); i++) {
            filterList.add(processFilterList.get(i).get("process"));
            List<Map<String, String>> lastProcessList =
                    orderProcessDetailMapper.filterLastProcess(
                            orderId,
                            String.valueOf(processFilterList.get(i).get("order_number")),
                            String.valueOf(processFilterList.get(i).get("technology_number")),
                            String.valueOf(processFilterList.get(i).get("id"))
                    );
            if (!lastProcessList.isEmpty()) {
                int finalI = i;
                lastProcessList.forEach(lastProcess -> {
                    if (filterList.contains(lastProcess.get("process"))) {
                        processList.add(lastProcess);
                    }
                });
            }
        }
        // ä½¿ç”¨HashSet来记录已经遇到的value值
        Set<String> seenValues = new HashSet<>();
        // åˆ›å»ºä¸€ä¸ªæ–°çš„List来存储结果
        List<Map<String, String>> uniqueList = new ArrayList<>();
        // åå‘遍历原始List
        for (int i = processList.size() - 1; i >= 0; i--) {
            Map<String, String> maps = processList.get(i);
            String value = maps.values().iterator().next(); // å‡è®¾æ¯ä¸ªMap只有一个value
            // å¦‚æžœvalue还没有被看到过,就添加到结果List和HashSet中
            if (!seenValues.contains(value)) {
                uniqueList.add(0, maps); // æ·»åŠ åˆ°ç»“æžœList的开头,以保持原顺序
                seenValues.add(value);
            }
        }
        map.put("title", uniqueList);
        List<Map<String, Object>> getRowCount = orderProcessDetailMapper.getGlassLRow(orderId);
        List<Map<String, Integer>> rowCount = new ArrayList<>();
        columns.forEach(col -> {
            getRowCount.forEach(row -> {
                Map<String, Integer> getRow = new HashMap<>();
                // { row: 0, col: 1, rowspan: 3, colspan: 0},
                Object rowNumObj = row.get("RowNum");
                if (rowNumObj instanceof Double) {
                    getRow.put("row", ((Double) rowNumObj).intValue());
                } else if (rowNumObj instanceof Integer) {
                    getRow.put("row", (Integer) rowNumObj);
                }
                getRow.put("col", col);
                getRow.put("rowspan", (Integer) row.get("rowCount"));
                getRow.put("colspan", 0);
                rowCount.add(getRow);
            });
        });
        map.put("mergeCells", rowCount);
        return map;
    }
}
north-glass-erp/src/main/resources/mapper/pp/DamageDetails.xml
@@ -14,7 +14,15 @@
    and a.breakage_quantity>0
    and a.patch_status=0
    and b.reviewed_state>=0
    and b.this_process in (SUBSTRING_INDEX(#{behindProcess},',',1))
    and b.this_process in (WITH RECURSIVE cte AS (
                            SELECT 1 AS n
                            UNION ALL
                            SELECT n + 1 FROM cte WHERE n &lt; 20 -- è¿™é‡Œçš„ 20 æ˜¯æœ€å¤§æ‹†åˆ†ä¸ªæ•°
                        )
                           SELECT REGEXP_SUBSTR(#{behindProcess}, '[^,]+', 1, n) AS process
                           FROM cte
                           WHERE REGEXP_SUBSTR(#{behindProcess}, '[^,]+', 1, n) IS NOT NULL)
</select>
</mapper>
north-glass-erp/src/main/resources/mapper/pp/Report.xml
@@ -186,17 +186,17 @@
               c.quantity-ifnull(c.termination_quantity,0) as glassQuantity,
               c.quantity-ifnull(c.termination_quantity,0) as quantityShow,
               (c.quantity-ifnull(c.termination_quantity,0))*a.compute_area as grossAreaShow,
               ifnull(f.inventory, 0) as inventoryShow,
               round(ifnull(f.inventory, 0) * a.compute_area, 2) as inventoryAreaShow, -- åº“存面积
               round( (c.quantity-ifnull(c.termination_quantity,0))*a.compute_area,2) as grossAreaShow,
               ifnull(c.received_quantity, 0) as StorageShow,
               ifnull(dd.quantity, 0) as shippedQuantityShow, -- å‘货数量
               (ifnull(c.received_quantity, 0))*a.compute_area  as StorageAreaShow,-- å…¥åº“面积
               round(ifnull(dd.quantity, 0)*a.compute_area,2) as shippedAreaShow, -- å‘货面积
               round((ifnull(c.received_quantity, 0))*a.compute_area,2)  as StorageAreaShow,-- å…¥åº“面积
               if(c.technology_number=1,(c.quantity-ifnull(c.termination_quantity,0))*a.compute_area,0) as grossArea,
               if(c.technology_number=1,ifnull(f.inventory, 0) ,0)                        as inventory,
               if(c.technology_number=1,round(ifnull(f.inventory, 0) * a.compute_area, 2),0)      as inventoryArea,
               if(c.technology_number=1, round((c.quantity-ifnull(c.termination_quantity,0))*a.compute_area,2),0) as grossArea,
               if(c.technology_number=1,ifnull(c.received_quantity, 0) ,0)                        as Storage,
               if(c.technology_number=1,ifnull(dd.quantity, 0) ,0)                          as shippedQuantity,
               if(c.technology_number=1,(ifnull(c.received_quantity, 0))*a.compute_area,0)  as StorageArea,
               if(c.technology_number=1,round(ifnull(dd.quantity, 0)*a.compute_area,2),0)         as shippedArea,
               if(c.technology_number=1, round((ifnull(c.received_quantity, 0))*a.compute_area,2),0)  as StorageArea,
               ifnull(JSON_UNQUOTE(JSON_EXTRACT(a.other_columns, '$.S01')),'') AS glassNumber,
@@ -213,8 +213,8 @@
                               and c.technology_number = b.technology_number
                 left join sd.`order` as d
                           on c.order_id = d.order_id
                 left join mm.finished_goods_inventory as f
                           on c.order_id = f.order_id and f.order_number = c.order_number
#                  left join mm.finished_goods_inventory as f
#                            on c.order_id = f.order_id and f.order_number = c.order_number
                 left join sd.delivery_detail as dd on dd.order_id = a.order_id and dd.order_number = a.order_number
                 left join (SELECT process_id,
                                   order_number,
@@ -3006,4 +3006,93 @@
       order by a.process_id
    </select>
    <select id="processCardProgressReportMp">
        select a.product_name,
               b.glass_child,
               d.order_type,
               concat(c.process_id, '/', c.technology_number) as process_id,
               c.process_id as 'processId',
                c.order_id,
               c.order_number,
               c.technology_number,
               b.child_width,
               b.child_height,
               c.quantity,
               c.quantity-ifnull(c.termination_quantity,0) as thisQuantity,/*用于判断是否改变颜色*/
               e.reportWorkQuantity,
               e.reportWorkQuantityShow,
               e.reportWorkQuantityCount,
               e.reportWorkTime,
               e.broken_num,
               c.quantity-ifnull(c.termination_quantity,0) as glassQuantity,
               c.quantity*a.area as gross_area,
               c.quantity-ifnull(c.termination_quantity,0) as quantityShow,
               (c.quantity-ifnull(c.termination_quantity,0))*a.compute_area as grossAreaShow,
               ifnull(f.inventory, 0) as inventoryShow,
               round(ifnull(f.inventory, 0) * a.compute_area, 2) as inventoryAreaShow, -- åº“存面积
               ifnull(dd.quantity, 0) as shippedQuantityShow, -- å‘货数量
               (ifnull(c.received_quantity, 0))*a.compute_area  as StorageAreaShow,-- å…¥åº“面积
               if(c.technology_number=1,(c.quantity-ifnull(c.termination_quantity,0))*a.compute_area,0) as grossArea,
               if(c.technology_number=1,ifnull(f.inventory, 0) ,0)                        as inventory,
               if(c.technology_number=1,round(ifnull(f.inventory, 0) * a.compute_area, 2),0)      as inventoryArea,
               if(c.technology_number=1,ifnull(dd.quantity, 0) ,0)                          as shippedQuantity,
               if(c.technology_number=1,(ifnull(c.received_quantity, 0))*a.compute_area,0)  as StorageArea,
               ifnull(JSON_UNQUOTE(JSON_EXTRACT(a.other_columns, '$.S01')),'') AS glassNumber,
               b.`group`
        from pp.flow_card as c
                 left join
             sd.order_detail as a
             on c.order_id = a.order_id
                 and c.order_number = a.order_number
                 left join sd.order_glass_detail as b
                           on c.order_id = b.order_id
                               and b.order_number = c.order_number
                               and c.technology_number = b.technology_number
                 left join sd.`order` as d
                           on c.order_id = d.order_id
                 left join mm.finished_goods_inventory as f
                           on c.order_id = f.order_id and f.order_number = c.order_number
                 left join sd.delivery_detail as dd on dd.order_id = a.order_id and dd.order_number = a.order_number
                 left join (SELECT process_id,
                                   order_number,
                                   technology_number,
                                   sum(a.broken_num) as broken_num,
                                   concat('{',
                                          GROUP_CONCAT(concat("\"", process, "\":\"", if(technology_number!=1 and (bd.nickname='stepD' || bd.nickname='stepB' ) ,0,reporting_work_num), "\"")),
                                          '}'
                                       )             as reportWorkQuantity,
                                   concat('{',
                                          GROUP_CONCAT(concat("\"", process, "\":\"", reporting_work_num, "\"")),
                                          '}'
                                       )             as reportWorkQuantityShow,
                                   concat('{',
                                          GROUP_CONCAT(concat("\"", process, "\":\"", reporting_work_num_count, "\"")),
                                          '}'
                                       )             as reportWorkQuantityCount,
                                   concat('{',
                                          GROUP_CONCAT(concat("\"", process, "\":\"", IFNULL(date(update_time),''), "\"")),
                                          '}'
                                       )             as reportWorkTime
                            FROM sd.order_process_detail as a
                                     left join (SELECT DISTINCT basic_name,nickname from sd.basic_data as bd where  bd.basic_category = 'process') as bd
                                               on a.process = bd.basic_name
                            where a.order_id = #{orderId}
                            GROUP BY process_id, a.order_number, a.technology_number
        ) as e
                           on e.process_id = c.process_id
                               and e.technology_number = c.technology_number
                               and e.order_number = c.order_number
        where a.order_id = #{orderId} and d.create_order>0 and c.quantity-ifnull(c.termination_quantity,0)>0
        group by c.order_number,
                 c.technology_number,
                 c.process_id
        order by c.process_id, c.order_number, c.technology_number
    </select>
</mapper>
north-glass-erp/src/main/resources/mapper/sd/OrderProcessDetailMapper.xml
@@ -119,17 +119,18 @@
        select
             max(a.technology_number) as rowCount,
             RowNum
        from sd.order_process_detail as a
        from pp.flow_card as a
        left join
            (select min((@i:=@i+1)) AS RowNum,c.*
             from sd.order_glass_detail as c,
             from pp.flow_card  as c,
                  (SELECT @i:=-1) as d
             where order_id = #{orderId}
             GROUP BY order_number
             GROUP BY order_number,process_id
             ) as b
        on b.order_number = a.order_number
        on b.id = a.id
        where a.order_id = #{orderId}
        group by a.order_number
        group by a.order_number,a.process_id
        order by RowNum
    </select>
    <update id="insertByReportingWorkDetail">