huang
2025-10-20 8b7ae914554652266b31f3bb4237106f1b220cc7
阿尔及利亚代码逻辑修改,页面布局修改
1个文件已添加
32个文件已修改
1470 ■■■■ 已修改文件
UI-Project/src/lang/en.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/py.js 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/zh.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/utils/constants.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/GlassStorage/rawfilmstorage2.vue 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/GlassStorage/rawhistory.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Returns/upreturnhistory.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Returns/upreturns3.vue 144 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/common/config/Const.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineering/entity/Engineering.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineering/service/impl/EngineeringServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/entity/LoadGlassDeviceTaskHistory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/entity/request/LoadGlassDeviceTaskHistoryRequest.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/service/impl/LoadGlassDeviceTaskHistoryServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/rawglassdetails/service/impl/RawGlassStorageDetailsServiceImpl.java 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/resources/mapper/UpPattenUsageMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/config/S7Config.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassPushMessage.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassTask.java 467 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/controller/RawGlassStorageDetailsController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglasstask/controller/RawGlassStorageTaskController.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/resources/logback-spring.xml 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/config/S7Config.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/engineering/controller/EngineeringController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/job/OpcLoadGlassTask.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/job/PlcLoadGlassTask.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/s7/entity/S7DataSP.java 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/controller/UpPattenUsageController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/service/UpPattenUsageService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/service/impl/UpPattenUsageServiceImpl.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application-alg.yml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/en.js
@@ -90,6 +90,7 @@
        glassnull: 'An error occurred while updating the glass status',
        deletemessage: 'Do you want to delete this message?',
        layoutSequence: 'Serial Number',
        isEnable: 'Is it enabled',
    },
    sorter: {
        onesort: 'Line breaking pieces',
@@ -103,6 +104,7 @@
        advancerequests: 'Film entry request',
        releaserequest: 'Production request',
        straighttasks: 'Direct Task',
        warehouseReturntasks: 'Warehouse return task',
        endingtask: 'end',
        another: 'other',
        taskRunning: 'task request',
@@ -660,6 +662,8 @@
        pwarehousing: 'Inventory request',
        wareout: 'Original film outbound',
        information: 'Whether to release this information from the warehouse?',
        warehouseReturn: 'Return to warehouse',
        emptyShelfPosition:'Empty shelf to hoisting position',
        pwareout: 'Outbound request',
        position: 'Lifting position:',
        cposition: 'Please select the lifting position',
UI-Project/src/lang/py.js
@@ -89,6 +89,7 @@
        glassnull: 'Ошибка при обновлении стекла',
        deletemessage:'Удалить эту информацию или нет?',
        layoutSequence:'Серийн номер',
        isEnable:'Включить ли',
    },
    sorter: {
        onesort:'一线掰片',
@@ -102,6 +103,7 @@
        advancerequests:'进片请求',
        releaserequest:'出片请求',
        straighttasks:'直通任务',
        warehouseReturntasks:'回库任务',
        endingtask:'结束',
        another:'其他',
        taskRunning:'任务请求',
@@ -440,7 +442,6 @@
        insort: 'Введите сортировку',
        operate: 'Операция',
        exit: 'Редактор',
        delete:'Удал',
        semenu:'Таблица меню второй степени',
        semenuname:'二级菜单名称:',
        inmenu: 'Введите меню',
@@ -668,6 +669,8 @@
        dedelete:'是否删除该条内容?',
        dedisable:'是否禁用该条内容?',
        deoutbound:'是否出库该条内容?',
        emptyShelfPosition:'Перекладывание пустой полки в положение подъема',
        warehouseReturn:'Возврат на склад',
        selectwarehousing:'请选择吊装位',
        inwarehousing:'吊装位:',
        warehousing1:'吊装位1',
UI-Project/src/lang/zh.js
@@ -89,6 +89,7 @@
          glassnull:'更新玻璃状态时发生错误',
          deletemessage:'是否删除该条信息?',
          layoutSequence:'序号',
          isEnable:'是否启用',
      },
      sorter:{
          onesort:'一线掰片',
@@ -102,6 +103,7 @@
          advancerequests:'进片请求',
          releaserequest:'出片请求',
          straighttasks:'直通任务',
          warehouseReturntasks:'回库任务',
          endingtask:'结束',
          another:'其他',
          id:'磨边前理片笼表ID',
@@ -664,6 +666,8 @@
          pwarehousing:'入库请求',
          wareout:'原片出库',
          information:'是否出库该条信息?',
          warehouseReturn:'回库',
          emptyShelfPosition:'空架子到吊装位',
          pwareout:'出库请求',
          position:'吊装位:',
          cposition:'请选择吊装位',
UI-Project/src/utils/constants.js
@@ -1,6 +1,6 @@
//  export const WebSocketHost = "192.168.2.100";
// export const WebSocketHost = "192.168.10.86";
// export const WebSocketHost = "192.168.0.39";
export const WebSocketHost = "10.153.19.150";
export const WebSocketHost = "10.153.19.45";
// export const WebSocketHost = "10.153.19.47";
// export const WebSocketHost = "10.153.19.162";
// export const WebSocketHost = "127.0.0.1";
UI-Project/src/views/GlassStorage/rawfilmstorage2.vue
@@ -88,7 +88,7 @@
const value = ref('')
const options = [
  {
    value: 101,
    value: 99,
    label: t('film.warehousing1'),
  },
]
@@ -117,8 +117,10 @@
  window.localStorage.setItem('startTime', formatTimestamp(oneWeekAgo))
}
onMounted(() => {
  console.log("onMounted 钩子已触发");
  socket = initializeWebSocket(socketUrl, handleMessage);
  parseAndSetTime();
  getListRawGlassTask();
});
let socket = null;
const socketUrl = `ws://${WebSocketHost}:${host}/api/glassStorage/api/talk/rawGlass`;
@@ -295,6 +297,38 @@
const handleBinde = (row) => {
  dialogFormVisiblee.value = true;
};
// 查询原片仓储任务详情
const getListRawGlassTask = async (row) => {
  try {
    console.log("[getListRawGlassTask] 函数已被调用,开始执行");
    var url = "/glassStorage/rawGlassStorageTask/listRawGlassTask";
    const response = await request.post(url)
    if (response.code === 200) {
      ElMessage.success(response.message);
      // 更新tableDataa数据
      if (response.data && response.data.tasks && response.data.tasks[0]) {
        const formattedTasks = response.data.tasks[0].map(task => {
          if (task && task.createTime) {
            return { ...task, createTime: formatTimestamp(task.createTime) };
          }
          return task;
        });
        tableDataa.value = formattedTasks;
      }
      // 更新tableDatab数据,确保页面能及时显示任务
      if (response.data && response.data.rawStationDetailsList && response.data.rawStationDetailsList[0]) {
        tableDatab.value = response.data.rawStationDetailsList[0];
      }
    } else {
      ElMessage.error(response.msg);
    }
  } catch (error) {
    console.error('查询原片仓储任务详情失败:', error);
  }
};
// 删除 
const deleteWarehousing = async (row) => {
  try {
@@ -353,14 +387,18 @@
    const response = await request.post(url)
    if (response.code == 200) {
      ElMessage.success(response.message);
      dialogFormVisiblec.value = false;
      leftingStation.value = '';
      // 调用获取任务详情的接口,确保数据及时更新
      await getListRawGlassTask();
      dialogFormVisiblec.value = false;
    } else {
      // 请求失败,显示错误消息
      ElMessage.error(response.msg);
    }
  }
  catch (error) {
    dialogFormVisiblec.value = false;
    console.error('入库请求失败:', error);
  }
}
// 出库请求
@@ -587,7 +625,7 @@
function getStatusText1(taskType) {
  switch (taskType) {
    case 1:
      return t('sorter.advancetask');//进片任务
      return t('sorter.warehouseReturntasks');//回库任务
    case 2:
      return t('sorter.outputtasks');//出片任务
    case 3:
@@ -595,27 +633,31 @@
    case 4:
      return t('sorter.advancerequests');//进片请求
    case 5:
      return t('sorter.releaserequest');//出片请求
      return t('sorter.warehouseReturntasks');//回库请求
  }
}
function getStatusType2(taskState) {
  switch (taskState) {
    case 0:
      return 'info';
    case 2:
      return 'warning';
    case 1:
      return 'warning';
    case 2:
      return 'success';
    case 3:
      return 'danger';
  }
}
function getStatusText2(taskState) {
  switch (taskState) {
    case 0:
      return t('film.built');//新建
    case 2:
      return t('film.fail');//失败
    case 1:
      return t('film.execution');//执行中
    case 2:
      return t('film.finish');//完成
    case 3:
      return t('film.fail');//失败
  }
}
onBeforeUnmount(() => {
@@ -632,10 +674,10 @@
        {{ $t('film.warehousing') }}
      </el-button>
      <el-button style="margin-left: 20px;" id="searchButton" type="success" @click="handleBindc">
        {{ $t('film.pwarehousing') }}
        {{ $t('film.emptyShelfPosition') }}
      </el-button>
      <el-button style="margin-left: 20px;" id="searchButton" type="success" @click="handleBinde">{{
        $t('film.pwareout')
        $t('film.warehouseReturn')
      }}
      </el-button>
      <el-button style="margin-left: 20px;" id="searchButton" type="success" @click="handlehistorical">{{
@@ -645,17 +687,17 @@
      <el-date-picker style="margin-left: 10px;" v-model="timeRange" type="datetimerange" format="YYYY/MM/DD HH:mm:ss"
        value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="$t('film.starttime')"
        :end-placeholder="$t('film.endtime')" :default-time="defaultTime" />
      <el-select v-model="selectValuesa[0]" clearable :placeholder="$t('film.taskstatus')" style="margin-left: 10px;">
      <el-select v-model="selectValuesa[0]" clearable :placeholder="$t('film.taskstatus')" style="margin-left: 10px; width: 200px;">
        <el-option :label="$t('film.built')" value="0"></el-option>
        <el-option :label="$t('film.finish')" value="1"></el-option>
        <el-option :label="$t('film.fail')" value="2"></el-option>
      </el-select>
      <el-select v-model="selectValuesa[1]" clearable :placeholder="$t('film.tasktype')" style="margin-left: 10px;">
      <el-select v-model="selectValuesa[1]" clearable :placeholder="$t('film.tasktype')" style="margin-left: 10px; width: 200px;">
        <el-option :label="$t('sorter.advancetask')" value="1"></el-option>
        <el-option :label="$t('sorter.outputtasks')" value="2"></el-option>
        <el-option :label="$t('sorter.schedulingtasks')" value="3"></el-option>
        <el-option :label="$t('sorter.advancerequests')" value="4"></el-option>
        <el-option :label="$t('sorter.releaserequest')" value="5"></el-option>
        <el-option :label="$t('sorter.warehouseReturntasks')" value="5"></el-option>
      </el-select>
      <el-button type="primary" style="margin-left: 10px;" @click="selectReportData()">{{ $t('film.inquire')
      }}</el-button>
@@ -685,9 +727,9 @@
          <el-table-column prop="createTime" align="center" :label="$t('film.createtime')" />
          <el-table-column fixed="right" :label="$t('film.operate')" align="center">
            <template #default="scope">
              <el-button :disabled="(scope.row.taskState !== 0)" type="text" plain @click="successfull(scope.row)">{{
              <el-button :disabled="(scope.row.taskState == 0 && scope.row.taskType == 1)" type="text" plain @click="successfull(scope.row)">{{
                $t('searchOrder.successfullyprocessed') }}</el-button>
              <el-button :disabled="(scope.row.taskState !== 0)" type="text" plain @click="handleptask(scope.row)">{{
              <el-button :disabled="(scope.row.taskState == 0 && scope.row.taskType == 1)" type="text" plain @click="handleptask(scope.row)">{{
                $t('searchOrder.taskfailure') }}</el-button>
            </template>
          </el-table-column>
@@ -757,7 +799,7 @@
    <el-dialog v-model="dialogFormVisiblea" top="5vh" width="85%">
      <el-table ref="table" style="margin-top: 20px;height: 700px;" :data="tableDatab"
        :header-cell-style="{ background: '#F2F3F5 ', color: '#1D2129' }">
        <el-table-column prop="deviceId" fixed align="center" :label="$t('film.station')" min-width="80" />
        <!-- <el-table-column prop="deviceId" fixed align="center" :label="$t('film.station')" min-width="80" /> -->
        <el-table-column prop="slot" fixed align="center" :label="$t('film.slot')" min-width="80" />
        <el-table-column prop="patternWidth" align="center" :label="$t('film.width')" min-width="80" />
        <el-table-column prop="patternHeight" align="center" :label="$t('film.height')" min-width="80" />
@@ -865,11 +907,11 @@
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dialogFormVisiblec" top="24vh" width="30%" :title="$t('film.pwarehousing')">
    <el-dialog v-model="dialogFormVisiblec" top="24vh" width="30%" :title="$t('film.emptyShelfPosition')">
      <div style="margin-left: 50px;margin-bottom: 10px;">
        <el-form-item :label="$t('film.position')" :required="true">
          <el-select v-model="leftingStation" clearable :placeholder="$t('film.cposition')" style="margin-left: 20px;">
            <el-option :label="$t('film.position1')" value="101"></el-option>
            <el-option :label="$t('film.position1')" value="99"></el-option>
          </el-select>
        </el-form-item>
      </div>
@@ -882,11 +924,11 @@
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dialogFormVisiblee" top="24vh" width="30%" :title="$t('film.pwareout')">
    <el-dialog v-model="dialogFormVisiblee" top="24vh" width="30%" :title="$t('film.warehouseReturn')">
      <div style="margin-left: 50px;margin-bottom: 10px;">
        <el-form-item :label="$t('film.position')" :required="true">
          <el-select v-model="leftingStation" clearable :placeholder="$t('film.cposition')" style="margin-left: 20px;">
            <el-option :label="$t('film.position1')" value="101"></el-option>
            <el-option :label="$t('film.position1')" value="99"></el-option>
          </el-select>
        </el-form-item>
      </div>
UI-Project/src/views/GlassStorage/rawhistory.vue
@@ -368,27 +368,31 @@
  case 4:  
  return t('sorter.advancerequests');//进片请求
  case 5:  
  return t('sorter.releaserequest');//出片请求
  return t('sorter.warehouseReturntasks');//回库请求
}  
}
function getStatusType2(taskState) {  
switch (taskState) {  
  case 0:
    return 'info';
  case 2:
    return 'warning';
  case 1:
    return 'success';
  case 0:
      return 'info';
    case 1:
      return 'warning';
    case 2:
      return 'success';
    case 3:
      return 'danger';
}  
}
function getStatusText2(taskState) {  
switch (taskState) {
  case 0:
    return t('film.built');//新建
  case 2:
    return t('film.fail');//失败
  case 1:
    return t('film.finish');//完成
   case 0:
      return t('film.built');//新建
    case 1:
      return t('film.execution');//执行中
    case 2:
      return t('film.finish');//完成
    case 3:
      return t('film.fail');//失败
}  
}
onMounted(() => {
UI-Project/src/views/Returns/upreturnhistory.vue
@@ -1,11 +1,12 @@
<template>  
    <div>  
  <div style="display: flex;width: 1770px;">
    <el-input v-model="rawGlassWidth" clearable style="margin-left: 10px;margin-bottom: 10px;width: 200px;" :placeholder="$t('Mounting.width')" />
    <el-input v-model="rawGlassHeight" clearable style="margin-left: 10px;margin-bottom: 10px;width: 200px;" :placeholder="$t('Mounting.height')" />
    <el-input v-model="rawGlassThickness" clearable style="margin-left: 10px;margin-bottom: 10px;width: 200px;" :placeholder="$t('Mounting.thickness')" />
    <el-input v-model="rawGlassfilmsId" clearable style="margin-left: 10px;margin-bottom: 10px;width: 200px;" :placeholder="$t('workOrder.coatingtypesbe')" />
    <el-input v-model="slot" clearable style="margin-left: 10px;margin-bottom: 10px;width: 200px;" :placeholder="$t('workOrder.upnumber')" />
  <div style="display: flex;width: 1770px; margin-top: 10px;">
    <el-input v-model="engineeringId" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('Mounting.project')" />
    <el-input v-model="rawGlassWidth" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('Mounting.width')" />
    <el-input v-model="rawGlassHeight" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('Mounting.height')" />
    <el-input v-model="rawGlassThickness" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('Mounting.thickness')" />
    <el-input v-model="rawGlassfilmsId" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('workOrder.coatingtypesbe')" />
    <!-- <el-input v-model="slot" clearable style="margin-left: 10px;margin-bottom: 10px;width: 190px;" :placeholder="$t('workOrder.upnumber')" /> -->
    <el-select v-model="selectValuesa[0]" filterable :placeholder="$t('searchOrder.taskstatus')" clearable
        style="width: 200px;margin-left: 10px;">
        <el-option :label="$t('searchOrder.empty')" value="0"></el-option>
@@ -24,6 +25,8 @@
          <el-button type="primary" style="margin-left: 10px;margin-bottom: 10px;" @click="sethistorical()">{{$t('reportmanage.inquire')}}</el-button>
     </div>
        <el-table ref="table" style="margin-top: 20px;height: 580px;width: 1770px;" :data="tableDatax" :header-cell-style="{background:'#F2F3F5 ',color:'#1D2129'}">
      <el-table-column prop="id" align="center" label="ID" min-width="80" />
      <el-table-column prop="engineeringId" :label="$t('Mounting.project')" align="center"></el-table-column>
      <el-table-column prop="rawGlassWidth" align="center" :label="$t('Mounting.width')" min-width="70" />
      <el-table-column prop="rawGlassHeight" align="center" :label="$t('Mounting.height')" min-width="70" />
      <el-table-column prop="rawGlassThickness" align="center" :label="$t('Mounting.thickness')" min-width="80" />
@@ -84,6 +87,7 @@
const rawGlassWidth = ref('');
const rawGlassfilmsId = ref('');
const slot = ref('');
const engineeringId = ref('')
let getglobalDate = window.localStorage.getItem('getglobalDate')
const historical = async () => {
  try {
@@ -96,7 +100,7 @@
        rawGlassWidth: '',
        rawGlassfilmsId: '',
        slot: 0,
        station: 1,
        station: 5,
        taskStateList: [],
        beginDate: startTime,
        endDate: getglobalDate
@@ -148,7 +152,7 @@
        rawGlassWidth: rawGlassWidth.value,
        rawGlassfilmsId: rawGlassfilmsId.value,
        slot: pslot,
        station: 1,
        station: 5,
        taskStateList: celllist,
        beginDate: (formatTimestamp(timeRange.value) && formatTimestamp(timeRange.value[0])) || '',
        endDate: (formatTimestamp(timeRange.value) && formatTimestamp(timeRange.value[1])) || '',
@@ -189,6 +193,7 @@
  let startTime = window.localStorage.getItem('startTime')
  let page = window.localStorage.getItem('pagenumber')
  const response = await request.post("/loadGlass/loadglassdevicetaskhistory/queryLoadGlassHistoryTask", {
        engineeringId: engineeringId.value,
        pageNo: 1,
        pageSize: 20,
        rawGlassHeight: rawGlassHeight.value,
@@ -196,7 +201,7 @@
        rawGlassWidth: rawGlassWidth.value,
        rawGlassfilmsId: rawGlassfilmsId.value,
        slot: pslot,
        station: 1,
        station: 5,
        taskStateList: celllist,
        beginDate: (formatTimestamp(timeRange.value) && formatTimestamp(timeRange.value[0])) || '',
        endDate: (formatTimestamp(timeRange.value) && formatTimestamp(timeRange.value[1])) || '',
@@ -280,17 +285,21 @@
    case 1: 
      return 'success';  
    case 2: 
      return 'info';
      return 'info';
    case 3:
      return 'danger';
  }  
}
function getStatusTextb(taskState: number) {
  switch (taskState) {
    case 0:  
      return t('searchOrder.empty');
      return t('searchOrder.waiting');
    case 1:  
      return t('film.execution');
    case 2:  
      return t('searchOrder.endtask');
    case 3:
      return t('film.fail');
  }  
}
function getStatusTypea(taskRunning: number) {  
UI-Project/src/views/Returns/upreturns3.vue
@@ -7,7 +7,7 @@
import request from "@/utils/request"
import { closeWebSocket, initializeWebSocket } from '@/utils/WebSocketService';
const router = useRouter()
const { t } = useI18n()
const { t } = useI18n();
const selectValuesa = reactive([]);
const selectedProjectNo = ref('');
const stationCell = ref('1');
@@ -20,7 +20,7 @@
const blindbd = ref(false)
const canSelectProjecta = ref(true);
const canSelectProjectb = ref(true);
const canSelectProjectc = ref(false);
const canSelectProjectc = ref(true);
const tableDatad = ref([])
const upstatus = ref(t('basicData.machineaa'));
const cuttingMachineStatusColor = ref('#911005');
@@ -28,8 +28,33 @@
const tableDatab = ref<any[]>([]);
const tableData = ref([])
// 暂停按钮
const isPaused = ref(false); // 暂停状态标识:false=未暂停(显示“暂停”),true=已暂停(显示“启动”)
// 取消(恢复)时的弹窗显隐
const resumeDialogVisible = ref(false);
// 存储后端返回的state=5的工程列表
const pauseEngineeringList = ref([]);
// 检查是否有正在执行中的任务
const hasRunningTask = ref(false);
const dialogFormVisiblea = ref(false)
function getTagType(state) {
  switch(state) {
    case 100: return 'success'; // 100=通过(绿色)
    case 101: return 'danger';  // 101=执行中(红色)
    default: return 'warning';  // 其他=待处理(橙色)
  }
}
  // 动态获取标签文本(支持国际化)
function getTagText(state) {
  switch(state) {
    case 100: return t('Mounting.pass');      // 通过
    case 101: return t('film.execution');     // 执行中
    default: return t('Mounting.waiting');    // 待处理
  }
}
const titleSelectJson = ref({
  engineerId: [],
@@ -93,6 +118,11 @@
let socket = null;
const socketUrl = `ws://${WebSocketHost}:${host}/api/loadGlass/api/talk/loadGlassOne`;
const handleMessage = (data: any) => {
  if (data.engineering == null) {
     isPaused.value = true;
  }else{
    isPaused.value = false;
  }
  if (data.inkageState != null) {
    cuttingMachineStatusColor.value = data.inkageState[0] === 1 ? 'green' : '#911005';
  }
@@ -108,17 +138,25 @@
  } else {
    tableDataa.value = []
  }
  canSelectProjectc.value = true;
  canSelectProjecta.value = false;
  canSelectProjectb.value = false;
  tableData.value = [];
  window.localStorage.setItem('engineeringIda', '');
  if (data.upPattenUsages.length != 0) {
    tableData.value = data.upPattenUsages[0]
    window.localStorage.setItem('engineeringIda', tableData.value[0].engineeringId)
    canSelectProjecta.value = false;
    canSelectProjectb.value = false;
    canSelectProjectc.value = true;
     if (tableData.value.length > 0) {
      window.localStorage.setItem('engineeringIda', tableData.value[0].engineeringId);
    }
    hasRunningTask.value = tableData.value.some(task => task.state === 101);
    console.log(hasRunningTask);
    // canSelectProjectc.value = !hasRunningTask;
  }
  else {
    hasRunningTask.value = false;
    canSelectProjecta.value = true;
    canSelectProjectb.value = true;
    canSelectProjectc.value = false;
    tableData.value = [];
    window.localStorage.setItem('engineeringIda', '')
  }
@@ -283,18 +321,29 @@
// 暂停
const handleup = async () => {
  try {
    let filmRemove = window.localStorage.getItem('filmRemove')
    let engineeringId = window.localStorage.getItem('engineeringIda')
    const filmRemove = window.localStorage.getItem('filmRemove')
    let engineeringId;
    const currentEngineering = pauseEngineeringList.value[0];
    if (currentEngineering) {
      // 从选中的工程中获取ID(取消弹窗中选择的工程)
      engineeringId = currentEngineering.engineerId;
    } else {
      // 使用本地缓存的工程ID(暂停弹窗的场景)
      engineeringId = window.localStorage.getItem('engineeringIda');
    }
    if (engineeringId !== '') {
      const response = await request.post('/loadGlass/engineering/engineering/pause', {
        stationCell: 5,
        filmRemove: filmRemove,
        engineerId: engineeringId,
        state: 0,
        state: isPaused.value ? 1 : 5
      })
      if (response.code == 200) {
      if (response.code == 200) {
        // 切换暂停/启动状态
        isPaused.value = !isPaused.value;
        ElMessage.success(response.message);
        blinda.value = false;
        resumeDialogVisible.value = false;
      } else {
        ElMessage.error(response.message);
      }
@@ -331,23 +380,45 @@
// 暂停
const handleBinda = (row) => {
  blinda.value = true;
const handleBinda = async () => {
  if (!isPaused.value) {
    // 情况1:当前是“暂停”状态→打开暂停确认弹窗
    blinda.value = true;
  } else {
    // 情况2:当前是“取消”状态→打开新增弹窗,并查询state=5的工程
    try {
      // 调用后端查询state=5的工程接口
      const response = await request.get('/loadGlass/engineering/engineering/selectTask');
      if (response.code === 200) {
        pauseEngineeringList.value = response.data; // 存储工程列表
        resumeDialogVisible.value = true; // 打开新增弹窗
      } else {
        ElMessage.error(t('film.fail') + response.message);
      }
    } catch (error) {
      console.error('查询暂停工程异常:', error);
      ElMessage.error(t('film.fail') + '查询失败,请重试');
    }
  }
};
// 是否禁用
const toggleEnableState = async (row: any) => {
  if (!row.id) {
  if (!row.deviceId) {
    ElMessage.error(t('basicData.updatanull'));
    return;
  }
  const newState = row.state === 100 ? 0 : 100;
  const newState = row.state === 1 ? 0 : 1;
  try {
    const response = await request.post('/loadGlass/up-patten-usage/updateGlassState', { id: row.id, state: newState });
    var url = "/glassStorage/rawGlassStorageStation/updateSlotState?slot=" + row.slot + "&state=" + newState;
    const response = await request.post(url)
    if (response.code === 200) {
      ElMessage.success(response.message);
      row.state = newState;
    } else {
      ElMessage.error(response.message);
    }
    row.state = newState;
  } catch (error) {
    ElMessage.error(t('basicData.glassnull'));
  }
@@ -592,7 +663,7 @@
      <el-dialog v-model="dialogFormVisiblea" top="5vh" width="85%">
        <el-table ref="table" style="margin-top: 20px;height: 700px;" :data="tableDatab"
          :header-cell-style="{ background: '#F2F3F5 ', color: '#1D2129' }">
          <el-table-column prop="deviceId" fixed align="center" :label="$t('film.station')" min-width="80" />
          <!-- <el-table-column prop="deviceId" fixed align="center" :label="$t('film.station')" min-width="80" /> -->
          <el-table-column prop="slot" fixed align="center" :label="$t('film.slot')" min-width="80" />
          <el-table-column prop="patternWidth" align="center" :label="$t('film.width')" min-width="80" />
          <el-table-column prop="patternHeight" align="center" :label="$t('film.height')" min-width="80" />
@@ -609,9 +680,10 @@
          <el-table-column fixed="right" :label="$t('film.operate')" align="center" width="270">
            <template #default="scope">
              <el-input v-model="inputQuantities[scope.row.slot]" type="number" min="0" @input="handleInput(scope.row)"
                :placeholder="$t('basicData.selectquantity')" :disabled="scope.row.slot > 100" style="width: 120px; margin-right: 10px;">
                :placeholder="$t('basicData.selectquantity')" v-if ="scope.row.slot < 99"
                style="width: 120px; margin-right: 10px;">
              </el-input>
              <el-button type="text" :disabled="scope.row.slot > 100" @click="handleBind(scope.row)">
              <el-button type="text" v-if = "scope.row.slot < 99"  :disabled="isPaused || hasRunningTask" @click="handleBind(scope.row)">
                {{ $t('basicData.startloading') }} </el-button>
            </template>
          </el-table-column>
@@ -620,10 +692,34 @@
      <!--暂停-->
      <el-button :disabled="!canSelectProjectc" style="margin-top: 5px;margin-left: 20px;" id="searchButton"
        type="warning" @click="handleBinda">{{ $t('basicData.stop') }}</el-button>
        :type="isPaused ? 'danger' : 'warning'" @click="handleBinda">{{ isPaused ? $t('sorter.cancel') :
        $t('basicData.stop') }}</el-button>
      <el-button style="margin-top: 5px;margin-left: 20px;" id="searchButton" type="info" @click="handlehistorical">{{
        $t('searchOrder.historicaltasks') }}</el-button>
      <el-dialog v-model="resumeDialogVisible" top="24vh" width="40%">
        <!-- 工程列表展示 -->
        <div v-if="pauseEngineeringList.length > 0">
          <div style="text-align: center; margin-bottom: 10px;">
          {{ $t('basicData.isEnable')}}{{ pauseEngineeringList[0].engineerId }}{{ $t('basicData.project') }}
          </div>
        </div>
        <!-- 无暂停工程时的提示 -->
        <div v-else class="no-data" style="text-align: center; padding: 20px;">
          <el-empty description="No pause engineering" />
        </div>
        <!-- 弹窗底部按钮 -->
        <template #footer>
          <div id="dialog-footer">
            <el-button type="primary" @click="handleup">
              {{ $t('basicData.confirm') }}
            </el-button>
            <el-button @click="resumeDialogVisible = false">{{ $t('basicData.cancel') }}</el-button>
          </div>
        </template>
      </el-dialog>
      <!-- <el-select disabled v-model="selectValuesa[1]" clearable :placeholder="$t('Mounting.twoloadingline')"
        style="margin-top: 5px;margin-left: 20px;">
        <el-option :label="$t('Mounting.all')" value="0"></el-option>
@@ -650,8 +746,8 @@
            <el-table-column prop="layoutSequence" :label="$t('Mounting.projectnumber')" align="center" />
            <el-table-column align="center" :label="$t('Mounting.state')" min-width="80" prop="state">
              <template #default="scope">
                <el-tag :type="scope.row.state === 100 ? 'success' : 'warning'" @click="toggleEnableState(scope.row)">
                  {{ scope.row.state === 100 ? $t('Mounting.pass') : $t('Mounting.waiting') }}
                <el-tag :type="getTagType(scope.row.state)">
                  {{ getTagText(scope.row.state) }}
                </el-tag>
              </template>
            </el-table-column>
@@ -680,12 +776,12 @@
              <el-table-column prop="remainQuantity" align="center" :label="$t('basicData.quantity')" min-width="80" />
              <el-table-column prop="patternThickness" align="center" :label="$t('basicData.thickness')"
                min-width="60" />
              <el-table-column fixed="right" :label="$t('film.operate')" align="center" width="100">
              <!-- <el-table-column fixed="right" :label="$t('film.operate')" align="center" width="100">
                <template #default="scope">
                  <el-button :disabled="(!scope.row.patternThickness)" type="text" plain
                    @click="handleptask(scope.row.workstationId)">{{ $t('basicData.rackreset') }}</el-button>
                </template>
              </el-table-column>
              </el-table-column> -->
            </el-table>
          </div>
        </div>
hangzhoumesParent/common/servicebase/src/main/java/com/mes/common/config/Const.java
@@ -276,8 +276,9 @@
    public static final List<Integer> RAW_GLASS_STATE_IN_ALL = Arrays.asList(100, 102, 103);
    public static final Integer RAW_GLASS_TASK_NEW = 0;
    public static final Integer RAW_GLASS_TASK_SUCCESS = 1;
    public static final Integer RAW_GLASS_TASK_FAILURE = 2;
    public static final Integer RAW_GLASS_TASK_RUNNING = 1;
    public static final Integer RAW_GLASS_TASK_SUCCESS = 2;
    public static final Integer RAW_GLASS_TASK_FAILURE = 3;
    /**
     * 设备号
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineering/entity/Engineering.java
@@ -7,6 +7,7 @@
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
@@ -108,4 +109,9 @@
     */
    @TableField(exist = false)
    private Integer filmRemove;
    /**
     * 当天日期
     */
    private Date createTime;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineering/service/impl/EngineeringServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.engineering.entity.Engineering;
@@ -146,9 +147,22 @@
    @Override
    public boolean pauseTask(String engineerId, Integer state) {
        Engineering engineering = this.getBaseMapper().selectOne(
                Wrappers.lambdaQuery(Engineering.class)
                        .eq(Engineering::getEngineerId, engineerId)
        );
        if (engineering == null) {
            // 工程不存在,返回失败
            return false;
        }
        // 2. 根据当前状态决定目标状态(1→5,5→1)
        Integer targetState = engineering.getState() == 1 ? 5 : 1;
        //暂停正在进行工程
        LambdaUpdateChainWrapper<Engineering> pauseWrapper = new LambdaUpdateChainWrapper<>(this.getBaseMapper());
        pauseWrapper.set(Engineering::getState, 5);
        pauseWrapper.set(Engineering::getState, targetState);
        pauseWrapper.eq(Engineering::getEngineerId, engineerId);
        return pauseWrapper.update();
    }
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/entity/LoadGlassDeviceTaskHistory.java
@@ -73,5 +73,10 @@
     */
    private Integer damageCount;
    /**
     * 工程号
     */
    private String engineeringId;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/entity/request/LoadGlassDeviceTaskHistoryRequest.java
@@ -19,6 +19,11 @@
@Data
public class LoadGlassDeviceTaskHistoryRequest extends PageRequest {
    /**
     * 工程编号
     */
    private String engineeringId;
    /**
     * 原片宽
     */
    private String rawGlassWidth;
hangzhoumesParent/common/servicebase/src/main/java/com/mes/opctask/service/impl/LoadGlassDeviceTaskHistoryServiceImpl.java
@@ -29,10 +29,11 @@
        }
        Page<LoadGlassDeviceTaskHistory> page = new Page<>(request.getPageNo(), request.getPageSize());
        LambdaQueryWrapper<LoadGlassDeviceTaskHistory> wrapper = new LambdaQueryWrapper<LoadGlassDeviceTaskHistory>()
                .like(StringUtils.isNotBlank(request.getRawGlassWidth()), LoadGlassDeviceTaskHistory::getRawGlassWidth, request.getRawGlassWidth())
                .like(StringUtils.isNotBlank(request.getRawGlassHeight()), LoadGlassDeviceTaskHistory::getRawGlassHeight, request.getRawGlassHeight())
                .like(StringUtils.isNotBlank(request.getRawGlassThickness()), LoadGlassDeviceTaskHistory::getRawGlassThickness, request.getRawGlassThickness())
                .like(StringUtils.isNotBlank(request.getRawGlassfilmsId()), LoadGlassDeviceTaskHistory::getRawGlassFilmsId, request.getRawGlassfilmsId())
                .like(StringUtils.isNotBlank(request.getRawGlassWidth()), LoadGlassDeviceTaskHistory::getRawGlassWidth, "%" + request.getRawGlassWidth() + "%")
                .like(StringUtils.isNotBlank(request.getRawGlassHeight()), LoadGlassDeviceTaskHistory::getRawGlassHeight, "%" + request.getRawGlassHeight() + "%")
                .like(StringUtils.isNotBlank(request.getRawGlassThickness()), LoadGlassDeviceTaskHistory::getRawGlassThickness, "%" + request.getRawGlassThickness() + "%")
                .like(StringUtils.isNotBlank(request.getRawGlassfilmsId()), LoadGlassDeviceTaskHistory::getRawGlassFilmsId, "%" + request.getRawGlassfilmsId() + "%")
                .eq(request.getEngineeringId() != null, LoadGlassDeviceTaskHistory::getEngineeringId, request.getEngineeringId())
                .eq(request.getStation() != 0, LoadGlassDeviceTaskHistory::getStation, request.getStation())
                .eq(request.getSlot() != 0, LoadGlassDeviceTaskHistory::getSlot, request.getSlot())
                .in(CollectionUtil.isNotEmpty(request.getTaskStateList()), LoadGlassDeviceTaskHistory::getTaskState, request.getTaskStateList())
hangzhoumesParent/common/servicebase/src/main/java/com/mes/rawglassdetails/service/impl/RawGlassStorageDetailsServiceImpl.java
@@ -20,6 +20,7 @@
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
@@ -43,6 +44,9 @@
    @Autowired(required = false)
    MiloService miloService;
    // 吊装位
    private static final Integer LEFTING_01 = 99;
    @Override
    public boolean deleteRawGlassStorageDetails(String device_id) {
        QueryWrapper<RawGlassStorageDetails> queryWrapper = new QueryWrapper<>();
@@ -59,12 +63,16 @@
        return list();
    }
    // 空架子到吊装位
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String warehousingRequest(int leftingStation) {
        RawGlassStorageDetails storageDetails = getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN_ALL)
                .eq(RawGlassStorageDetails::getSlot, leftingStation));
                .eq(RawGlassStorageDetails::getSlot, leftingStation)
                // 添加行锁,其他请求需等待锁释放
                .last("FOR UPDATE"));
        if (null != storageDetails) {
            log.info("当前吊装位有架子,结束本地入库请求");
            return "fail";
@@ -138,13 +146,43 @@
        return "success";
    }
    // 出库
    @Override
    public String outWarehousing(Long slotId) {
        update(new LambdaUpdateWrapper<RawGlassStorageDetails>().eq(RawGlassStorageDetails::getSlot, slotId)
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
        // 1. 检查当前架子状态
        RawGlassStorageDetails details = getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, slotId)
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN));
        if (details == null) {
            log.info("架子状态异常,无法执行出库操作");
            return "fail";
        }
        // 2. 将架子状态改为“待出库”(标记为可执行)
        update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, slotId)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_WAIT_OUT));
        //生成一条详情数据  仅记录架子状态
        return "success";
        // 3. 直接生成出库任务(关键:在页面点击时就创建任务记录)
        try {
            // 起始位:仓库存储位(slotId),目标位:吊装位99
            generateTask(
                    slotId.intValue(),          // 起始位:仓库存储位(slotId)
                    LEFTING_01,                 // 目标位:吊装位99
                    slotId.intValue(),          // 架子号
                    details.getRemainQuantity(), // 数量
                    Const.RAW_GLASS_TASK_TYPE_OUT // 任务类型:出库
            );
            log.info("出库任务生成成功,架子:{},目标位:{}", slotId, LEFTING_01);
            return "success";
        } catch (Exception e) {
            log.error("生成出库任务失败", e);
            // 失败时回滚状态
            update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                    .eq(RawGlassStorageDetails::getSlot, slotId)
                    .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN));
            return "fail";
        }
    }
    @Override
@@ -152,14 +190,14 @@
        return baseMapper.listBySlotState(liftingStation, state);
    }
    // 回库
    @Override
    public String outWarehousingRequest(int leftingStation) {
        //对应工位是否有空架子
        RawGlassStorageDetails details = getOne(new LambdaQueryWrapper<RawGlassStorageDetails>().eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .eq(RawGlassStorageDetails::getSlot, leftingStation));
        if (null == details) {
            log.info("无空架子,结束本地出片请求");
            log.info("无空架子,结束回库任务");
            return "fail";
        }
        //生成一条详情数据  仅记录架子状态
@@ -168,7 +206,7 @@
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
        try {
            generateTask(leftingStation, details.getShelf(), details.getShelf(), details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_OUT_REQUEST);
            generateTask(leftingStation, details.getShelf(), details.getShelf(), details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_IN);
        } catch (Exception e) {
            return "fail";
        }
@@ -195,11 +233,11 @@
                .shelf(shelf)
                .createTime(new Date()).build();
        rawGlassStorageTaskService.save(task);
        List<ReadWriteEntity> list = new ArrayList<>();
        list.add(generateReadWriteEntity("CC.CC.taskWord", 1));
        list.add(generateReadWriteEntity("CC.CC.startSlot", startSlot));
        list.add(generateReadWriteEntity("CC.CC.endSlot", endSlot));
        miloService.writeToOpcWord(list);
//        List<ReadWriteEntity> list = new ArrayList<>();
//        list.add(generateReadWriteEntity("CC.CC.taskWord", 1));
//        list.add(generateReadWriteEntity("CC.CC.startSlot", startSlot));
//        list.add(generateReadWriteEntity("CC.CC.endSlot", endSlot));
//        miloService.writeToOpcWord(list);
        return Boolean.TRUE;
    }
hangzhoumesParent/common/servicebase/src/main/resources/mapper/UpPattenUsageMapper.xml
@@ -14,17 +14,29 @@
        <result column="group_number" property="groupNumber"/>
    </resultMap>
    <select id="queryRawGlassByEngineeringId" resultMap="baseMap">
        SET @prev_width := NULL;
        SET @prev_height := NULL;
        SET @counter := 0;
        SELECT t.*,
               @counter := IF(@prev_width = width and @prev_height = height, @counter, @counter + 1) AS group_number,
               @prev_width := width,
               @prev_height := height
        FROM up_patten_usage t
        where t.engineering_id = #{engineeringId}
          and t.state = 0
        ORDER BY t.layout_sequence
        SELECT
            t.*,
            t.group_number
        FROM (
                 SELECT
                     upu.*,
                     -- 计算组号
                     @counter := IF(@prev_width = upu.width AND @prev_height = upu.height,
                                    @counter,
                                    @counter + 1) AS group_number,
                     -- 变量赋值
                     @prev_width := upu.width,
                     @prev_height := upu.height
                 FROM
                     up_patten_usage upu,
                     -- 关键:用虚拟表初始化变量,替代单独的SET语句
                     (SELECT @prev_width := NULL, @prev_height := NULL, @counter := 0) AS init_var
                 WHERE
                     upu.engineering_id = #{engineeringId}
                   AND upu.state = 0
                 ORDER BY
                     upu.layout_sequence
             ) AS t
    </select>
    <select id="queryFinishByEngineering" resultType="java.lang.Integer">
        SELECT id
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/config/S7Config.java
@@ -15,15 +15,15 @@
public class S7Config {
    @Bean(name = "s7SerializerSPOne")
    public S7Serializer s7SerializerSPOne() {
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.86");
//        S7PLC s7PLC = new S7PLC(EPlcType.S1500, "10.153.19.191");
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.80");
//        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.0.15");
        return S7Serializer.newInstance(s7PLC);
    }
    @Bean(name = "s7SerializerSPTwo")
    public S7Serializer s7SerializerSPTwo() {
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.86");
//        S7PLC s7PLC = new S7PLC(EPlcType.S1500, "10.153.19.191");
        return S7Serializer.newInstance(s7PLC);
    }
//    @Bean(name = "s7SerializerSPTwo")
//    public S7Serializer s7SerializerSPTwo() {
//        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.86");
////        S7PLC s7PLC = new S7PLC(EPlcType.S1500, "10.153.19.191");
//        return S7Serializer.newInstance(s7PLC);
//    }
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassPushMessage.java
@@ -42,7 +42,7 @@
    @Resource
    private OrdersService ordersService;
    @Scheduled(fixedDelay = 2000)
    @Scheduled(fixedDelay = 500)
    public void sendRawGlassMessage() {
        log.info("发送任务信息和架子信息");
        JSONObject jsonObject = new JSONObject();
@@ -59,7 +59,7 @@
        }
    }
    @Scheduled(fixedDelay = 1000)
    @Scheduled(fixedDelay = 500)
    public void largenScreen() {
        log.info("发送任务信息和架子信息");
        JSONObject jsonObject = new JSONObject();
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassTask.java
@@ -67,17 +67,27 @@
    private static final String LOAD_GLASS_DEVICE_TWO_TASK = "load_glass_device_two_task";
    private static final List<Integer> LOAD_STATION_01 = Arrays.asList(101, 102);
    private static final List<Integer> LOAD_STATION_02 = Arrays.asList(103, 104);
    private static final List<Integer> LOAD_STATION_ALL = Arrays.asList(101, 102, 103, 104);
    private static final Integer LEFTING_01 = 98;
    private static final Integer LEFTING_02 = 99;
    private static final List<Integer> LOAD_STATION_01 = Collections.singletonList(101);
//    private static final List<Integer> LOAD_STATION_02 = Arrays.asList(103, 104);
//    private static final List<Integer> LOAD_STATION_ALL = Arrays.asList(101, 102, 103, 104);
    private static final Integer LEFTING_01 = 99;
//    private static final Integer LEFTING_02 = 99;
    private static final Integer LOAD_GLASS_ONE_DEVICE = 5;
    private static final Integer LOAD_GLASS_TWO_DEVICE = 6;
    @Scheduled(fixedDelay = 1000)
    public void rawStorageTask() throws Exception {
        S7Data S7DataWL1 = s7Serializer.read(S7Data.class);
//        S7Data S7DataWL1 = new S7Data();
//        S7DataWL1.setRequest((short) 1);
//        S7DataWL1.setConfirmation((short) 0);
//        S7DataWL1.setReportWord((short) 0);
//        S7DataWL1.setTaskWord((short) 0);
//        String requestWord = S7DataWL1.getRequest().toString();
//        String confireWord = S7DataWL1.getConfirmation().toString();
//        String reportWord = S7DataWL1.getReportWord().toString();
//        String taskWord = S7DataWL1.getTaskWord().toString();
        String requestWord = S7DataWL1.getRequest().toString();
        String confireWord = S7DataWL1.getConfirmation().toString();
        String reportWord = S7DataWL1.getReportWord().toString();
@@ -129,19 +139,19 @@
            log.info("执行调度任务,结束");
            return;
        }
        flag = outboundTask();
        flag = inboundRequestTask();
        if (flag) {
            log.info("执行出库任务,结束");
            log.info("执行吊装位请求任务");
            return;
        }
        flag = warehouseTask();
        if (flag) {
            log.info("执行入库任务");
            log.info("执行回库任务");
            return;
        }
        flag = shelfResetTask();
        flag = outboundTask();
        if (flag) {
            log.info("执行复位任务");
            log.info("执行出库任务,结束");
            return;
        }
        log.info("无任务执行,结束");
@@ -150,6 +160,8 @@
    @Scheduled(fixedDelay = 1000)
    public void rawStorageInCar() throws Exception {
        S7Data S7DataWL1 = s7Serializer.read(S7Data.class);
//        S7Data S7DataWL1 = new S7Data();
//        S7DataWL1.setInCar((short) 1);
        String value = S7DataWL1.getInCar().toString();
//        ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.inCar");
//        String value = entity.getValue() + "";
@@ -171,6 +183,8 @@
    @Scheduled(fixedDelay = 1000)
    public void rawStorageFinish() throws Exception {
        S7Data S7DataWL1 = s7Serializer.read(S7Data.class);
//        S7Data S7DataWL1 = new S7Data();
//        S7DataWL1.setReportWord((short) 1);
        String value = S7DataWL1.getReportWord().toString();
//        ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.reportWord");
//        String value = entity.getValue() + "";
@@ -185,7 +199,7 @@
            return;
        }
        RawGlassStorageTask task = rawGlassStorageTaskService.getOne(new LambdaQueryWrapper<RawGlassStorageTask>()
                .in(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW));
                .in(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING, Const.RAW_GLASS_TASK_NEW));
        RawGlassStorageDetails targetDetails = rawGlassStorageDetailsService.generateDetails(details, task.getEndSlot());
        int deviceId = details.getDeviceId();
        Integer taskType = task.getTaskType();
@@ -196,7 +210,7 @@
                    .eq(RawGlassStorageDetails::getSlot, task.getStartSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_CAR));
            log.info("任务状态已更改为:已完成");
            rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING)
                    .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_SUCCESS));
            switch (taskType) {
                case 1:
@@ -208,7 +222,7 @@
                    break;
                case 2:
                case 4:
                    log.info("2、出片,4、入库请求。{}", taskType);
                    log.info("2、出片,4、吊装位请求。{}", taskType);
                    targetDetails = new RawGlassStorageDetails();
                    targetDetails.setSlot(task.getEndSlot());
                    targetDetails.setDeviceId(deviceId);
@@ -232,21 +246,18 @@
                        .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING, Const.RAW_GLASS_STATE_CAR));
            }
            rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING)
                    .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_FAILURE));
        }
        S7Data s7Data = new S7Data();
        s7Data.setConfirmation((short) 1);
        s7Serializer.write(s7Data);
//        List<ReadWriteEntity> list = new ArrayList<>();
//        list.add(generateReadWriteEntity("CC.CC.confirmation", 1));
//        miloService.writeToOpcWord(list);
    }
    private boolean isHasRunningTask() {
        RawGlassStorageTask task = rawGlassStorageTaskService.getOne(new LambdaQueryWrapper<RawGlassStorageTask>()
                .in(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW));
                .in(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
        return task == null ? Boolean.FALSE : Boolean.TRUE;
    }
@@ -269,55 +280,127 @@
        }
        return Boolean.FALSE;
    }
    /**
     * 处理空架子吊装位请求任务:将仓库的空架子送到吊装位99,等待入库
     *
     * @return
     */
    public boolean inboundRequestTask() throws Exception {
        // 步骤1:查询“未执行的空架子到吊装位请求任务”(类型IN_REQUEST,状态NEW)
        RawGlassStorageTask inRequestTask = rawGlassStorageTaskService.getOne(new LambdaQueryWrapper<RawGlassStorageTask>()
                .eq(RawGlassStorageTask::getTaskType, Const.RAW_GLASS_TASK_TYPE_IN_REQUEST) // 空架子入库请求类型
                .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                .last("limit 1")); // 每次处理一个任务,避免冲突
        if (inRequestTask == null) {
            log.info("无待执行的空架子吊装位请求任务");
            return Boolean.FALSE;
        }
        // 步骤2:检查任务关联的空架子状态(需为“待入库”,且确实是空架子)
        RawGlassStorageDetails emptyShelf = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, inRequestTask.getStartSlot()) // 起始位:仓库空架子位
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING)); // 待入库状态);
        if (emptyShelf == null) {
            log.info("空架子到吊装位请求任务关联的架子异常(非空架子或状态错误),跳过执行");
            return Boolean.FALSE;
        }
        // 步骤3:检查目标吊装位99是否空闲
        List<RawGlassStorageDetails> liftingShelfList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, inRequestTask.getEndSlot()) // 目标位:吊装位99
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN_ALL));
        if (CollectionUtil.isNotEmpty(liftingShelfList)) {
            log.info("吊装位{}已有关联架子,无法执行空架子到吊装位请求", inRequestTask.getEndSlot());
            return Boolean.FALSE;
        }
        // 步骤4:更新空架子状态为“执行中”
        rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, emptyShelf.getSlot())
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
        // 步骤5:更新任务状态为“执行中”,避免重复执行
        rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                .eq(RawGlassStorageTask::getId, inRequestTask.getId())
                .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
        // 步骤6:发送PLC指令,驱动空架子从仓库→吊装位
        S7Data s7Data = new S7Data();
        s7Data.setTaskWord((short) 1); // 任务触发信号
        s7Data.setStartSlot((short) inRequestTask.getStartSlot().intValue()); // 起始位:仓库空架子位
        s7Data.setEndSlot((short) inRequestTask.getEndSlot().intValue());     // 目标位:吊装位99
        s7Serializer.write(s7Data);
        log.info("执行空架子到吊装位请求任务:从仓库{}到吊装位{}", inRequestTask.getStartSlot(), inRequestTask.getEndSlot());
        return Boolean.TRUE;
    }
    /**
     * 出库任务:1、点出库,立马生成出片任务 2、点出库修改工位详情内的状态为待出库,定时任务扫描生成出库任务
     */
    public boolean outboundTask() throws Exception {
        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_WAIT_OUT)
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1"));
        if (CollectionUtil.isEmpty(rawGlassList)) {
            log.info("系统没有需要出库的原片信息");
        // 步骤1:查询已生成的“未执行出库任务”(状态为NEW,类型为OUT)
        RawGlassStorageTask outboundTask = rawGlassStorageTaskService.getOne(new LambdaQueryWrapper<RawGlassStorageTask>()
                .eq(RawGlassStorageTask::getTaskType, Const.RAW_GLASS_TASK_TYPE_OUT)
                .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                .last("limit 1")); // 每次处理一个任务
        if (outboundTask == null) {
            log.info("无待执行的出库任务");
            return Boolean.FALSE;
        }
        //获取工位上是否有架子,
        // 步骤2:获取任务关联的架子详情,检查状态是否合法(待出库)
        RawGlassStorageDetails details = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, outboundTask.getStartSlot()) // 任务起始位(仓库位)
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_WAIT_OUT)); // 待出库状态
        if (details == null) {
            log.info("出库任务关联的架子状态异常,跳过执行");
            return Boolean.FALSE;
        }
        // 步骤3:检查吊装位99是否空闲(无架子)
        List<RawGlassStorageDetails> emptyLeftingList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN_ALL)
                .in(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1 and device_id = 4"));
        if (CollectionUtil.isNotEmpty(emptyLeftingList) && emptyLeftingList.size() > 1) {
            log.info("吊装位当前都有架子,结束出片任务");
        if (CollectionUtil.isNotEmpty(emptyLeftingList)) {
            log.info("吊装位99当前有架子,无法执行出库任务");
            return Boolean.FALSE;
        }
        //获取需要落架的
        List<Integer> leftingList = emptyLeftingList.stream().map(RawGlassStorageDetails::getSlot).collect(Collectors.toList());
        int lefting = CollectionUtil.isEmpty(leftingList) ? LEFTING_01 : leftingList.get(0).equals(LEFTING_01) ? LEFTING_02 : LEFTING_01;
        Integer startSlot = rawGlassList.get(0).getSlot();
        //生成出库任务
        rawGlassStorageDetailsService.generateTask(startSlot, lefting, startSlot, rawGlassList.get(0).getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_OUT);
//        List<ReadWriteEntity> list = new ArrayList<>();
//        list.add(generateReadWriteEntity("CC.CC.taskWord", 1));
//        list.add(generateReadWriteEntity("CC.CC.taskSending", 1));
//        list.add(generateReadWriteEntity("CC.CC.startSlot", startSlot));
//        list.add(generateReadWriteEntity("CC.CC.endSlot", lefting));
//        miloService.writeToOpcWord(list);
        //修改出片任务状态
        // 步骤4:更新架子状态为“执行中”
        rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, rawGlassList.get(0).getSlot())
                .eq(RawGlassStorageDetails::getSlot, details.getSlot())
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_WAIT_OUT)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
        // 步骤5:更新任务状态为“执行中”(避免重复执行)
        rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                .eq(RawGlassStorageTask::getId, outboundTask.getId())
                .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
        S7Data s7Data = new S7Data();
        s7Data.setTaskWord((short) 1);
        s7Data.setStartSlot((short) outboundTask.getStartSlot().intValue()); // 仓库存储位(起始位)
        s7Data.setEndSlot((short) outboundTask.getEndSlot().intValue());     // 吊装位99(目标位)
        s7Serializer.write(s7Data);
        return Boolean.TRUE;
    }
    /**
     * 复位任务:1、点复位,立马生成复位任务 2、点出库修改工位详情内的状态为架子复位,定时任务扫描生成复位任务
     */
    public boolean shelfResetTask() throws Exception {
        // 1. 查询“待复位”的架子(状态为RESET,且工位启用)
        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RESET)
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1"));
@@ -325,22 +408,35 @@
            log.info("系统没有需要复位的原片信息");
            return Boolean.FALSE;
        }
        //生成复位任务
//        rawGlassStorageDetailsService.generatask(rawGlassList.get(0).getSlot(), rawGlassList.get(0).getShelf(), rawGlassList.get(0).getShelf(), rawGlassList.get(0).getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
        // 2. 取第一条待复位的架子(每次处理一个)
        RawGlassStorageDetails details = rawGlassList.get(0);
        Integer startSlot = details.getSlot();       // 复位起始位(当前架子所在位)
        Integer targetSlot = details.getShelf();     // 复位目标位(初始仓库存储位)
//        List<ReadWriteEntity> list = new ArrayList<>();
//        list.add(generateReadWriteEntity("CC.CC.taskWord", 1));
//        list.add(generateReadWriteEntity("CC.CC.taskSending", 1));
//        list.add(generateReadWriteEntity("CC.CC.startSlot", startSlot));
//        list.add(generateReadWriteEntity("CC.CC.endSlot", lefting));
//        miloService.writeToOpcWord(list);
        // 3. 生成复位任务(类型建议单独定义:如Const.RAW_GLASS_TASK_TYPE_RESET,避免与调度任务混淆)
        rawGlassStorageDetailsService.generateTask(
                startSlot,
                targetSlot,
                targetSlot,
                details.getRemainQuantity(),
                Const.RAW_GLASS_TASK_TYPE_DISPATCH
        );
        //修改复位任务状态
        // 4. 更新架子状态为“执行中”
        rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, rawGlassList.get(0).getSlot())
                .eq(RawGlassStorageDetails::getSlot, startSlot)
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RESET)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
        // 5. 补充PLC交互:发送复位指令
        S7Data s7Data = new S7Data();
        s7Data.setTaskWord((short) 1); // 任务触发信号
        s7Data.setStartSlot((short) startSlot.intValue()); // 起始位:当前架子位
        s7Data.setEndSlot((short) targetSlot.intValue());   // 目标位:初始仓库位
        s7Serializer.write(s7Data);
        log.info("执行架子复位任务:从{}到{}", startSlot, targetSlot);
        return Boolean.TRUE;
    }
@@ -350,32 +446,49 @@
     * @throws Exception
     */
    public boolean warehouseTask() throws Exception {
        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .gt(RawGlassStorageDetails::getRemainQuantity, 0)
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1 and device_id = 4")
                .inSql(RawGlassStorageDetails::getShelf, "select slot from raw_glass_storage_station where enable_state = 1 "));
        if (CollectionUtil.isEmpty(rawGlassList)) {
            log.info("吊装位被禁用/架子所在工位被禁用/无原片信息");
            return Boolean.FALSE;
//        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
//                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
//                .gt(RawGlassStorageDetails::getRemainQuantity, 0)
//                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1 and device_id = 4")
//                .inSql(RawGlassStorageDetails::getShelf, "select slot from raw_glass_storage_station where enable_state = 1 "));
//        if (CollectionUtil.isEmpty(rawGlassList)) {
//            log.info("吊装位被禁用/架子所在工位被禁用/无原片信息");
//            return Boolean.FALSE;
//        }
        // 查询回库任务
        RawGlassStorageTask task = rawGlassStorageTaskService.getOne(new LambdaQueryWrapper<RawGlassStorageTask>()
                .in(RawGlassStorageTask::getTaskType,  Const.RAW_GLASS_TASK_TYPE_IN)
                .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                .last("limit 1"));
        if (task == null) {
            log.info("无待执行的回库任务");
            return false;
        }
        //生成进笼任务
        RawGlassStorageDetails details = rawGlassList.get(0);
        rawGlassStorageDetailsService.generateTask(details.getSlot(), details.getShelf(), details.getShelf(),
                details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_IN);
        RawGlassStorageDetails details = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, task.getStartSlot()) // 任务起始位(吊装位)
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING)); // 已标记为执行中
        if (details == null) {
            log.info("任务关联的架子状态异常,跳过执行");
            return false;
        }
        rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                .eq(RawGlassStorageTask::getId, task.getId())
                .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
        log.info("执行回库任务:从{}到{}", task.getStartSlot(), task.getEndSlot());
//        List<ReadWriteEntity> list = new ArrayList<>();
//        list.add(generateReadWriteEntity("CC.CC.taskWord", 1));
//        list.add(generateReadWriteEntity("CC.CC.taskSending", 1));
//        list.add(generateReadWriteEntity("CC.CC.startSlot", details.getSlot()));
//        list.add(generateReadWriteEntity("CC.CC.endSlot", details.getShelf()));
//        miloService.writeToOpcWord(list);
        //生成工位任务,将吊装位的玻璃状态改位进笼中
        //修改吊装位的原片状态为103 出片中
        //修改出片任务状态
        rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getSlot, rawGlassList.get(0).getSlot())
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
        S7Data s7Data = new S7Data();
        s7Data.setTaskWord((short) 1);
        s7Data.setStartSlot((short) details.getSlot().intValue());
        s7Data.setEndSlot((short) details.getShelf().intValue());
        s7Serializer.write(s7Data);
        return Boolean.TRUE;
    }
@@ -397,12 +510,13 @@
                .collect(Collectors.groupingBy(UpPattenUsageVO::getGroupNumber));
        List<UpPattenUsageVO> usageVOS = upListMap.get("1");
        //获取当前上片位1号架子信息
        List<Integer> loadStation = LOAD_GLASS_ONE_DEVICE.equals(stationCell) ? LOAD_STATION_01 : LOAD_STATION_02;
        List<Integer> loadStation = LOAD_STATION_01;
        List<RawGlassStorageStation> stations = rawGlassStorageStationService.list(new LambdaQueryWrapper<RawGlassStorageStation>()
                .in(RawGlassStorageStation::getSlot, loadStation)
                .eq(RawGlassStorageStation::getEnableState, Const.SLOT_ON).orderByAsc(RawGlassStorageStation::getSlot));
                .eq(RawGlassStorageStation::getEnableState, Const.SLOT_ON)
                .orderByAsc(RawGlassStorageStation::getSlot));
        if (CollectionUtils.isEmpty(stations)) {
            log.info("没有可用的上片位");
            log.info("101的上片位不可用");
            return Boolean.FALSE;
        }
@@ -410,160 +524,77 @@
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1")
                .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                .eq(RawGlassStorageDetails::getDeviceId, stationCell));
        if (stations.size() == 1) {
            if (CollectionUtils.isEmpty(loadStationList)) {
                RawGlassStorageDetails rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
                rawGlassStorageDetailsService.generateTask(rawDetails.getSlot(), stations.get(0).getSlot(), rawDetails.getShelf(), rawDetails.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
                rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                        .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                return Boolean.TRUE;
            }
            RawGlassStorageDetails oneLoadStation = loadStationList.get(0);
            if (oneLoadStation.getRemainQuantity() <= 0 || !compareRawSize(usageVOS.get(0), oneLoadStation)) {
                rawGlassStorageDetailsService.generateTask(stations.get(0).getSlot(), oneLoadStation.getShelf(), oneLoadStation.getShelf(), oneLoadStation.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getSlot, oneLoadStation.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                        .set(RawGlassStorageDetails::getDeviceId, Const.RAW_GLASS_STATE_RUNNING));
                return Boolean.FALSE;
            }
        }
        log.info("获取{}上片线的工位信息{}", stationCell, loadStationList);
        if (CollectionUtils.isEmpty(loadStationList)) {
            log.info("1号上片位生成调度任务");
            RawGlassStorageDetails rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
            if (CollectionUtils.isEmpty(loadStationList)) {
                log.info("仓库内无匹配的玻璃");
            if (rawDetails == null) {
                log.info("仓库无匹配规格的原片,无法调度到101工位");
                return Boolean.FALSE;
            }
            rawGlassStorageDetailsService.generateTask(rawDetails.getSlot(), loadStation.get(0), rawDetails.getShelf(), rawDetails.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
            //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
            // 生成调度任务:仓库原片位 → 101上片位
            rawGlassStorageDetailsService.generateTask(
                    rawDetails.getSlot(),
                    stations.get(0).getSlot(),
                    rawDetails.getShelf(),
                    rawDetails.getRemainQuantity(),
                    Const.RAW_GLASS_TASK_TYPE_DISPATCH);
            rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                    .eq(RawGlassStorageTask::getTaskType, Const.RAW_GLASS_TASK_TYPE_DISPATCH)
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                    .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
            rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                    .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                    .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot())
                    .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                    .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
            S7Data s7Data = new S7Data();
            s7Data.setTaskWord((short) 1);
            s7Data.setStartSlot((short) rawDetails.getSlot().intValue()); // 起始位:仓库
            s7Data.setEndSlot((short) LOAD_STATION_01.get(0).intValue()); // 目标位:上片位101
            s7Serializer.write(s7Data); // 发送到PLC
            log.info("调度任务已发送PLC:从仓库{}到上片位{}", rawDetails.getSlot(), LOAD_STATION_01);
            return Boolean.TRUE;
        }
        RawGlassStorageDetails oneLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(0))).findFirst().orElse(null);
        if (null == oneLoadStation) {
            RawGlassStorageDetails twoLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(1))).findFirst().orElse(null);
            if (twoLoadStation.getRemainQuantity() > 0) {
                if (compareRawSize(usageVOS.get(0), twoLoadStation)) {
//                    2号上片位的原片信息源工程信息一致,可上片操作,结束本次任务
                    return Boolean.FALSE;
                } else {
//                    生成1号位入库任务
                    log.info("2号上片位玻璃尺寸不一致,1号上片位生成调度任务");
                    //按照尺寸及数量获取数量最接近的格子信息
                    RawGlassStorageDetails rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
                    if (null == rawDetails) {
                        log.info("仓库内无需要上架的玻璃");
                        return Boolean.FALSE;
                    }
                    rawGlassStorageDetailsService.generateTask(rawDetails.getSlot(), loadStation.get(0), rawDetails.getShelf(), rawDetails.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                    //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
                    rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                            .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                            .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                    return Boolean.TRUE;
                }
            } else {
//                生成1号位入库任务
                log.info("2号上片位仅剩空架子,1号上片位生成调度任务");
                RawGlassStorageDetails rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
                rawGlassStorageDetailsService.generateTask(rawDetails.getSlot(), loadStation.get(0), rawDetails.getShelf(), rawDetails.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                        .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                return Boolean.TRUE;
            }
        } else {
            String tableName = stationCell == 5 ? LOAD_GLASS_DEVICE_ONE_TASK : LOAD_GLASS_DEVICE_TWO_TASK;
            if (oneLoadStation.getRemainQuantity() > 0) {
                if (compareRawSize(usageVOS.get(0), oneLoadStation)) {
                    //结束仓储调度,等待上片任务
                    //在上片任务执行空闲过程中,可执行二号位出入库任务  二号架子的信息是否需要调度,不需要调度直接放回false
                    log.info("获取二号位原片信息");
                    RawGlassStorageDetails twoLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(1))).findFirst().orElse(null);
                    if (null == twoLoadStation) {
                        //按照尺寸生成二号位上片任务信息
                        LoadGlassDeviceTask loadTask = loadGlassDeviceTaskService.queryTaskMessage(tableName);
                        RawGlassStorageDetails rawDetails = null;
                        if (oneLoadStation.getRemainQuantity() > (loadTask.getTotalCount() + loadTask.getDamageCount())) {
                            usageVOS = upListMap.get("2");
                            if (CollectionUtils.isEmpty(usageVOS)) {
                                log.info("当前工程的原片即将用完,结束本次调度");
                                return Boolean.FALSE;
                            }
                            rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
                        } else {
                            rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size());
        // 上片位101有玻璃 → 判断尺寸是否匹配
        RawGlassStorageDetails oneLoadStation = loadStationList.get(0);
        if (oneLoadStation.getRemainQuantity() <= 0 || !compareRawSize(usageVOS.get(0), oneLoadStation)) {
                        }
                        if (null == rawDetails) {
                            log.info("原片仓储没有相同尺寸的玻璃");
                            return Boolean.FALSE;
                        }
                        rawGlassStorageDetailsService.generateTask(rawDetails.getSlot(), loadStation.get(1), rawDetails.getShelf(), rawDetails.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                        //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
                        rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                                .eq(RawGlassStorageDetails::getSlot, rawDetails.getSlot()).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                                .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                        return Boolean.TRUE;
                    } else {
                        //todo:当二号为的尺寸大于0时,是否执行调度任务,更换当前原片的尺寸,等待下一次任务的直接执行;还是继续等待,当尺寸不一样,等待一号工位的进出库调度任务。
                        if (twoLoadStation.getRemainQuantity() > 0) {
                            LoadGlassDeviceTask loadTask = loadGlassDeviceTaskService.queryTaskMessage(tableName);
                            if (oneLoadStation.getRemainQuantity() > (loadTask.getTotalCount() + loadTask.getDamageCount())) {
                                usageVOS = upListMap.get("2");
                                if (CollectionUtils.isEmpty(usageVOS)) {
                                    log.info("当前工程的原片即将用完,结束本次调度");
                                    return Boolean.FALSE;
                                }
                            }
                            if (compareRawSize(usageVOS.get(0), twoLoadStation)) {
//                              //2号上片位的原片信息源工程信息一致,可上片操作,结束本次任务
                                return Boolean.FALSE;
                            } else {
//                    生成1号位入库任务
                                log.info("2号上片位玻璃尺寸不一致,2号上片位生成出片调度任务");
                                //按照尺寸及数量获取数量最接近的格子信息
                                rawGlassStorageDetailsService.generateTask(loadStation.get(1), twoLoadStation.getShelf(), twoLoadStation.getShelf(), twoLoadStation.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                                //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
                                rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                                        .eq(RawGlassStorageDetails::getSlot, loadStation.get(1)).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                                        .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                                return Boolean.TRUE;
                            }
                        } else {
                            //todo:生成出库任务
                            rawGlassStorageDetailsService.generateTask(loadStation.get(1), twoLoadStation.getShelf(), twoLoadStation.getShelf(), twoLoadStation.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                            //结束调度任务 修改工位状态(起始位)状态为103 RAW_GLASS_STATE_RUNNING 任务完成后将状态改为101  目标位新增一条数据,架子号为(起始位)
                            rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                                    .eq(RawGlassStorageDetails::getSlot, loadStation.get(1)).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                                    .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                            return Boolean.TRUE;
                        }
                    }
//                    return Boolean.FALSE;
                } else {
                    log.info("2号上片位仅剩空架子,1号上片位生成出库调度任务");
                    rawGlassStorageDetailsService.generateTask(loadStation.get(0), oneLoadStation.getShelf(), oneLoadStation.getShelf(), oneLoadStation.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                    rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                            .eq(RawGlassStorageDetails::getSlot, loadStation.get(0)).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                            .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                    return Boolean.TRUE;
                }
            } else {
                log.info("1号上片位玻璃尺寸不一致,1号上片位生成出库调度任务");
                rawGlassStorageDetailsService.generateTask(loadStation.get(0), oneLoadStation.getSlot(), oneLoadStation.getShelf(), oneLoadStation.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getSlot, loadStation.get(0)).eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                        .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
                return Boolean.TRUE;
            // 检查上片机是否正在工作,若正在工作则不生成退回任务
            if (pattenUsageList.stream().allMatch(vo -> vo.getState() == 101)) {
                log.warn("上片机{}正在工作,无法执行退回任务", stationCell);
                return Boolean.FALSE;
            }
            // 生成退回任务:101上片位 → 原仓库存储位
            rawGlassStorageDetailsService.generateTask(
                    stations.get(0).getSlot(),
                    oneLoadStation.getShelf(),
                    oneLoadStation.getShelf(),
                    oneLoadStation.getRemainQuantity(),
                    Const.RAW_GLASS_TASK_TYPE_DISPATCH);
            rawGlassStorageTaskService.update(new LambdaUpdateWrapper<RawGlassStorageTask>()
                    .eq(RawGlassStorageTask::getTaskType, Const.RAW_GLASS_TASK_TYPE_DISPATCH)
                    .eq(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_NEW)
                    .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_RUNNING));
            rawGlassStorageDetailsService.update(new LambdaUpdateWrapper<RawGlassStorageDetails>()
                    .eq(RawGlassStorageDetails::getSlot, oneLoadStation.getSlot())
                    .eq(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                    .set(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_RUNNING));
            S7Data s7Data = new S7Data();
            s7Data.setTaskWord((short) 1); // 任务触发信号
            s7Data.setStartSlot((short) LOAD_STATION_01.get(0).intValue()); // 起始位:上片位101
            s7Data.setEndSlot((short) oneLoadStation.getShelf().intValue()); // 目标位:仓库
            s7Serializer.write(s7Data); // 发送到PLC
            log.info("退回任务已发送PLC:从上片位{}到仓库{}", LOAD_STATION_01, oneLoadStation.getShelf());
            return Boolean.FALSE;
        }
        // 上片位101玻璃尺寸匹配且数量充足 → 无需调度
        log.info("101工位玻璃尺寸匹配且数量充足,无需调度");
        return Boolean.FALSE;
    }
    private ReadWriteEntity generateReadWriteEntity(String identifier, int value) {
@@ -579,7 +610,7 @@
                .eq(RawGlassStorageDetails::getPatternWidth, usageVO.getWidth())
                .eq(RawGlassStorageDetails::getPatternHeight, usageVO.getHeight())
                .eq(RawGlassStorageDetails::getPatternThickness, usageVO.getThickness())
                .notIn(RawGlassStorageDetails::getSlot, LOAD_STATION_ALL)
                .notIn(RawGlassStorageDetails::getSlot, LOAD_STATION_01)
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .orderByAsc(RawGlassStorageDetails::getRemainQuantity)
                .last("order by abs(t.remain_quantity - " + remainQuantity + ")  asc")
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/controller/RawGlassStorageDetailsController.java
@@ -60,11 +60,11 @@
    }
    @ApiOperation("出库请求")
    @ApiOperation("回库")
    @PostMapping("/outWarehousingRequest")
    public Result<String> outWarehousingRequest(int leftingStation) {
        return Result.build(
                200, "入库已完成,等待任务执行", rawGlassStorageDetailsService.outWarehousingRequest(leftingStation));
                200, "回库已完成,等待任务执行", rawGlassStorageDetailsService.outWarehousingRequest(leftingStation));
    }
    @ApiOperation("架子复位")
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglasstask/controller/RawGlassStorageTaskController.java
@@ -46,15 +46,20 @@
    @ApiOperation("任务成功处理")
    @PostMapping("/taskSuccess")
    public Result<Boolean> taskSuccess(Long taskId) {
        return Result.build(200, "查询成功", rawGlassStorageTaskService.taskSuccess(taskId));
        return Result.build(200, "修改成功", rawGlassStorageTaskService.taskSuccess(taskId));
    }
    @ApiOperation("任务失败处理")
    @PostMapping("/taskError")
    public Result<Boolean> taskError(Long taskId) {
        return Result.build(200, "查询成功", rawGlassStorageTaskService.taskError(taskId));
        return Result.build(200, "修改成功", rawGlassStorageTaskService.taskError(taskId));
    }
    @ApiOperation("查询原片仓储任务详情")
    @PostMapping("/listRawGlassTask")
    public Result<List<RawGlassStorageTask>> listRawGlassTask() {
        return Result.build(200, "查询成功", rawGlassStorageTaskService.listRawGlassTask());
    }
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/resources/application-dev.yml
@@ -28,7 +28,7 @@
    password: 123456
kangaroohy:
  milo:
    enabled: true
    enabled: false
    primary: default
    config:
      default:
hangzhoumesParent/moduleService/GlassStorageModule/src/main/resources/logback-spring.xml
New file
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
    <!-- logger上下文名称(根据业务修改) -->
    <contextName>glassStorage</contextName>
    <!-- 定义了一个名为serverName的属性,它的值来自于logging.file.name,如果没有找到该属性默认为MyServerName(根据业务修改) -->
    <springProperty name="serverName" source="logging.file.name" defaultValue="glassStorage"/>
    <springProperty name="logging.path" source="logging.file.path" defaultValue="././logs/"/>
    <!-- 彩色日志依赖的渲染类 -->
    <!-- 定义了一个名为clr的转换规则,它使用org.springframework.boot.logging.logback.ColorConverter类进行转换,这个元素通常用于将日志输出中的文本着色,以便更容易地区分不同的日志级别或其他信息 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <!-- WhitespaceThrowableProxyConverter和ExtendedWhitespaceThrowableProxyConverter都是用于将异常信息转换为字符串,并将其中的换行符替换为空格,以便更容易地在日志输出中显示的类。它们之间的区别在于,ExtendedWhitespaceThrowableProxyConverter在输出异常信息时会包含更多的详细信息,例如异常的类名、方法名和行号等 -->
    <!-- 定义了一个名为wex的转换规则,它使用org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter类进行转换,这个元素通常用于将异常信息转换为字符串,并将其中的换行符替换为空格,以便更容易地在日志输出中显示 -->
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <!-- 定义了一个名为wEx的转换规则,它使用org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter类进行转换,这个元素通常用于将异常信息转换为字符串,并将其中的换行符替换为空格,以便更容易地在日志输出中显示 -->
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <!-- 彩色日志格式 -->
    <!-- value值是日志输出模板, :-是属性名和其默认值之间的分隔符,作用与:相同 -->
    <!-- 定义日志输出格式的转换规则,%d{yyyy-MM-dd HH:mm:ss.SSS}表示日期和时间,%clr表示将输出文本着色,{faint}表示使用淡色 -->
    <!-- %5p表示日志级别输出右对齐,左边以空格填充 -->
    <!-- ${PID:- }表示进程ID,%clr表示将输出文本着色,{magenta}表示使用洋红色 -->
    <!-- -表示一个分隔符 -->
    <!-- %t:显示产生该日志的线程名;%15:若字符长度小于15,则左边用空格填充;%.15:若字符长度超过15,截去多余字符 -->
    <!-- %-40:若字符长度小于40,则右边用空格填充;%.40:若字符长度超过40,截去多余字符;logger{39}对应的是“logging.WARNING”级别。具体来说,Python的logging模块定义了以下几个级别(从低到高):NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL。因此,logger{39}表示的是WARNING级别,即日志记录器会记录所有WARNING级别及以上的日志信息 -->
    <!-- %m表示日志消息;%n表示换行符;${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}表示异常信息。如果日志输出中包含异常信息,这个规则将会将其转换为字符串,并将其中的换行符替换为空格,以便更容易地在日志输出中显示 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--1. 输出到控制台-->
    <!-- 定义控制台日志输出的appender,class="ch.qos.logback.core.ConsoleAppender"表示使用Logback框架提供的ConsoleAppender类来输出日志到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <!-- 定义日志输出级别的过滤器,class="ch.qos.logback.classic.filter.ThresholdFilter"表示使用Logback框架提供的ThresholdFilter类来过滤日志输出,<level>debug</level>表示只输出debug级别及以上的日志 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <!-- ${CONSOLE_LOG_PATTERN}表示控制台日志输出格式,UTF-8表示编码格式 -->
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <!-- 定义文件日志输出的appender,class="ch.qos.logback.core.rolling.RollingFileAppender"表示使用Logback框架提供的RollingFileAppender类来输出日志到文件 -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${logging.path}/${serverName}/web_debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <!-- 定义日志文件滚动策略的标签,class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"表示使用Logback框架提供的TimeBasedRollingPolicy类来定义日志文件的滚动策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <!-- 定义日志文件名的模式。在这个模式中,${logging.path}表示日志文件的路径,%d{yyyy-MM-dd}表示日期格式,%i表示文件索引 -->
            <fileNamePattern>${logging.path}/${serverName}/web-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 定义日志文件滚动策略的标签,class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"表示使用Logback框架提供的SizeAndTimeBasedFNATP类来定义日志文件的滚动策略,<maxFileSize>100MB</maxFileSize>表示日志文件的最大大小为100MB。这个滚动策略通常用于按照时间和文件大小滚动日志文件,以便更好地管理日志文件的大小和数量 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <!-- 定义日志输出级别的过滤器。在这个过滤器中,class="ch.qos.logback.classic.filter.LevelFilter"表示使用Logback框架提供的LevelFilter类来过滤日志输出,<level>debug</level>表示只输出debug级别及以上的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <!-- <onMatch>ACCEPT</onMatch>表示如果日志事件与过滤器匹配,则接受该事件,<onMismatch>DENY</onMismatch>表示如果日志事件与过滤器不匹配,则拒绝该事件 -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${logging.path}/${serverName}/web_info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 天天日志归档路径以及格式 -->
            <fileNamePattern>${logging.path}/${serverName}/web-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${logging.path}/${serverName}/web_warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logging.path}/${serverName}/web-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${logging.path}/${serverName}/web_error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logging.path}/${serverName}/web-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--     4.1 开发环境:打印控制台-->
    <!-- 用于在Spring Boot应用程序中配置日志记录的标签。在这个标签中,name="dev"表示这个配置文件只在dev环境中生效,<logger name="com.myClass.controller" level="debug"/>表示为com.myClass.controller(根据业务修改)这个包下的类配置日志输出级别为debug -->
    <!--    <springProfile name="dev">-->
    <!--        <logger name="com.myClass.controller" level="debug"/>-->
    <!--    </springProfile>-->
    <!-- 用于配置日志输出的标签。在这个标签中,level="info"表示日志输出级别为info,<appender-ref ref="CONSOLE"/>、<appender-ref ref="DEBUG_FILE"/>、<appender-ref ref="INFO_FILE"/>、<appender-ref ref="WARN_FILE"/>、<appender-ref ref="ERROR_FILE"/>表示将日志输出到不同的appender中,分别为控制台、debug文件、info文件、warn文件和error文件 -->
    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="INFO_FILE"/>
        <appender-ref ref="WARN_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
</configuration>
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/config/S7Config.java
@@ -15,7 +15,13 @@
public class S7Config {
    @Bean
    public S7Serializer s7SerializerSP1() {
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.86");
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "192.168.10.10");
        return S7Serializer.newInstance(s7PLC);
    }
    @Bean
    public S7Serializer s7SerializerSP2() {
        S7PLC s7PLC = new S7PLC(EPlcType.S1200, "10.168.10.0");
        return S7Serializer.newInstance(s7PLC);
    }
}
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/engineering/controller/EngineeringController.java
@@ -62,7 +62,7 @@
    @PostMapping("/pause") //暂停上片任务
    @ResponseBody
    public  Result <List<UpPattenUsage>> pause(@RequestBody Engineering engineering) {
        boolean work=engineeringService.pauseTask(engineering.getEngineerId(),engineering.getState());
        boolean work = engineeringService.pauseTask(engineering.getEngineerId(),engineering.getState());
//        List<UpPattenUsage> glass = upPattenUsageService.prioritylist();String message;
        if(work){
            return Result.build(200, "成功", null);
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/job/OpcLoadGlassTask.java
@@ -62,7 +62,7 @@
    private S7Serializer s7SerializerSPOne;
    @Autowired
    @Qualifier("s7SerializerSP1")
    @Qualifier("s7SerializerSP2")
    private S7Serializer s7SerializerSPTwo;
    private static final List<Integer> LOAD_STATION_01 = Arrays.asList(101, 102);
@@ -81,7 +81,7 @@
    //2、1号上片位是否有原片,原片尺寸是否和上片待上片的尺寸一致
    //3、1号无原片,且没有架子,2号上片位尺寸是否和带上片尺寸一致
    //4、不一致可能出现玻璃破损导致的上一架原片数量不够
    @Scheduled(fixedDelay = 5000)
    @Scheduled(fixedDelay = 2000)
    public void opcLoadGlassOne() {
        opcLoadGlassChild(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE);
    }
@@ -91,7 +91,7 @@
        opcLoadGlassChild(LOAD_GLASS_DEVICE_TWO_TASK, LOAD_GLASS_TWO_DEVICE);
    }
    @Scheduled(fixedDelay = 5000)
    @Scheduled(fixedDelay = 2000)
    public void opcLoadGlassOneFinish() {
        opcLoadGlassFinishChid(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE);
    }
@@ -125,33 +125,43 @@
    private void opcLoadGlassChild(String tableName, Integer deviceId) {
        S7DataSP s7DataSP = new S7DataSP();
//        s7DataSP.setPlcRequest(1);
//        s7DataSP.setMesConfirm(0);
        if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) {
            s7DataSP = s7SerializerSPOne.read(S7DataSP.class);
        } else {
            s7DataSP = s7SerializerSPTwo.read(S7DataSP.class);
        }
        log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP);
        if (s7DataSP.getPlcRequest() == 0) {
            if (s7DataSP.getMesSend() != 0) {
                S7DataSP resetSend = new S7DataSP();
                resetSend.setMesSend(0);
                s7SerializerSPOne.write(resetSend);
                log.info("{}上片线,PLC请求清零,MES同步清零mesSend", deviceId);
            }
            return;
        }
        // 当PLC请求新任务(plcRequest=1)且无未确认汇报(mesConfirm=0)时处理
        if (s7DataSP.getPlcRequest() != 1 || s7DataSP.getMesConfirm() != 0) {
            log.info("{}上片线,PLC未请求新任务或存在未确认汇报,跳过本次处理", deviceId);
            return;
        }
        Engineering engineering = engineeringMapper.selectOne(new LambdaQueryWrapper<Engineering>()
                .eq(Engineering::getState, Const.ENGINEERING_RUNNING).eq(Engineering::getStationCell, deviceId));
                .eq(Engineering::getState, Const.ENGINEERING_RUNNING)
                .eq(Engineering::getStationCell, deviceId));
        if (null == engineering) {
            log.info("{}上片线,没有工程任务", deviceId);
            return;
        }
        //任务暂停
        S7DataSP task = new S7DataSP();
        if ("0".equals(s7DataSP.getInkageState().toString())) {
            log.info("{}上片线,处于离线状态:{},结束本地上片请求", deviceId, s7DataSP.getInkageState().toString());
            return;
        }
        if (s7DataSP.getTaskRunning()) {
            log.info("{}上片线,有正在执行的任务,结束本地上片请求", deviceId);
            return;
        }
        List<UpPattenUsageVO> pattenUsageList = upPattenUsageMapper.queryRawGlassByEngineeringId(engineering.getEngineerId());
        log.info("按照当前获取到正在需要上片的原片信息有:{}", pattenUsageList);
        if (CollectionUtils.isEmpty(pattenUsageList)) {
            log.info("当前工程需要上片的原片信息为空,任务已结束");
            //todo:是否将工程状态改为已完成
            return;
        }
        Map<String, List<UpPattenUsageVO>> upListMap = pattenUsageList.stream()
@@ -162,7 +172,7 @@
        List<Integer> loadStation = LOAD_GLASS_DEVICE_ONE_TASK.equals(tableName) ? LOAD_STATION_01 : LOAD_STATION_02;
        List<RawGlassStorageDetails> loadStationList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1")
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN_ALL)
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                .eq(RawGlassStorageDetails::getDeviceId, deviceId));
        if (CollectionUtils.isEmpty(loadStationList)) {
            log.info("当前上片线路两个上片位都没有原片信息,结束本次上片任务,等待仓储调度任务");
@@ -177,14 +187,18 @@
            }
            int number = Math.min(twoLoadStation.getRemainQuantity(), usageVOS.size());
            //生成上片任务
            LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory();
            task.setTotalCount(number);
            task.setTaskRunning(Boolean.TRUE);
            task.setTaskRunning(1);
            task.setRawGlassWidth((int) usageVOS.get(0).getWidth());
            task.setRawGlassHeight((int) usageVOS.get(0).getHeight());
            task.setSlot(loadStation.get(1));
            task.setSlot(loadStation.get(0));
            task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId());
            task.setEngineeringId(usageVOS.get(0).getEngineeringId());
            saveHistoryTask(task, deviceId);
            S7DataSP s7DataSPWrite = new S7DataSP();
            s7DataSPWrite.setTotalCount(number);
            s7DataSPWrite.setTaskRunning(Boolean.TRUE);
            s7DataSPWrite.setMesSend(1);
            s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth());
            s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight());
            s7DataSPWrite.setSlot(loadStation.get(1));
@@ -193,7 +207,6 @@
            } else {
                s7SerializerSPTwo.write(s7DataSPWrite);
            }
            saveHistoryTask(task, deviceId);
            return;
        }
        //尺寸不一样或者原片数量大于0
@@ -203,14 +216,23 @@
        }
        //生成上片任务
        int number = Math.min(oneLoadStation.getRemainQuantity(), usageVOS.size());
        LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory();
        task.setTotalCount(number);
        task.setTaskRunning(Boolean.TRUE);
        task.setTaskRunning(1);
        task.setRawGlassWidth((int) usageVOS.get(0).getWidth());
        task.setRawGlassHeight((int) usageVOS.get(0).getHeight());
        task.setRawGlassThickness((int) usageVOS.get(0).getThickness());
        task.setSlot(loadStation.get(0));
        task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId());
        task.setEngineeringId(usageVOS.get(0).getEngineeringId());
        saveHistoryTask(task, deviceId);
        UpPattenUsage upPattenUsage = upPattenUsageMapper.selectById(usageVOS.get(0).getId());
        upPattenUsage.setState(101);
        upPattenUsageMapper.updateById(upPattenUsage);
        S7DataSP s7DataSPWrite = new S7DataSP();
        s7DataSPWrite.setTotalCount(number);
        s7DataSPWrite.setTaskRunning(Boolean.TRUE);
        s7DataSPWrite.setMesSend(1);
        s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth());
        s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight());
        s7DataSPWrite.setSlot(loadStation.get(0));
@@ -219,71 +241,78 @@
        } else {
            s7SerializerSPTwo.write(s7DataSPWrite);
        }
        saveHistoryTask(task, deviceId);
    }
    private void opcLoadGlassFinishChid(String tableName, Integer deviceId) {
        S7DataSP s7DataSP = new S7DataSP();
//        s7DataSP.setPlcReport(1);
//        s7DataSP.setMesConfirm(0);
        if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) {
            s7DataSP = s7SerializerSPOne.read(S7DataSP.class);
        } else {
            s7DataSP = s7SerializerSPTwo.read(S7DataSP.class);
        }
        log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP);
        if (s7DataSP.getTaskRunning().toString().equals(Const.ENGINEERING_NEW)) {
            log.info("无任务,结束");
        if (s7DataSP.getPlcReport() == 0) {
            if (s7DataSP.getMesConfirm() != 0) {
                S7DataSP resetConfirm = new S7DataSP();
                resetConfirm.setMesConfirm(0);
                s7SerializerSPOne.write(resetConfirm);
                log.info("{}上片线,PLC汇报清零,MES同步清零mesConfirm", deviceId);
            }
            return;
        }
        if (Integer.parseInt(s7DataSP.getTaskState().toString()) <= 1) {
            log.info("任务正在执行,结束");
        if (s7DataSP.getPlcReport() == 0 || s7DataSP.getMesConfirm() != 0) {
            log.info("{}上片线,无PLC汇报或已确认,跳过本次处理", deviceId);
            return;
        }
        //获取任务完成情况
//         已完成数量  破损数量
        Integer finishCount = Integer.parseInt(s7DataSP.getFinishCount().toString());
        Integer damageCount = Integer.parseInt(s7DataSP.getDamageCount().toString());
        Integer slot = Integer.parseInt(s7DataSP.getSlot().toString());
        LoadGlassDeviceTaskHistory unconfirmedTask = loadGlassDeviceTaskHistoryService.getOne(
                new LambdaQueryWrapper<LoadGlassDeviceTaskHistory>()
                        .eq(LoadGlassDeviceTaskHistory::getStation, deviceId)
                        .eq(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_RUNNING)
        );
        String upUsageId = unconfirmedTask.getEngineeringId();
        if (s7DataSP.getPlcReport() == 1) {
            // 汇报成功:更新上片记录为“成功”
            upPattenUsageMapper.update(null,
                    new LambdaUpdateWrapper<UpPattenUsage>()
                            .set(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS)
                            .eq(UpPattenUsage::getEngineeringId, upUsageId)
                            .eq(UpPattenUsage::getState, 101)
            );
            unconfirmedTask.setTaskState(Const.RAW_GLASS_TASK_SUCCESS);
            unconfirmedTask.setFinishCount(unconfirmedTask.getFinishCount() + 1);
            log.info("{}上片线,任务汇报成功,更新上片记录[{}]为成功", deviceId, upUsageId);
        } else if (s7DataSP.getPlcReport() == 2) {
            // 汇报破损
            unconfirmedTask.setTaskState(200);
            unconfirmedTask.setDamageCount(unconfirmedTask.getDamageCount() + 1);
            log.warn("{}上片线,任务汇报破损,上片记录[{}]标记为破损", deviceId,  upUsageId);
        }
        unconfirmedTask.setUpdateTime(new Date());
        loadGlassDeviceTaskHistoryService.updateById(unconfirmedTask);
        //更新当前架子上的原片剩余情况
        rawGlassStorageDetailsService.update(new UpdateWrapper<RawGlassStorageDetails>()
                .inSql("slot", "select slot from raw_glass_storage_station where enable_state = 1")
//                .eq("slot", task.getSlot())
                .eq("slot", slot)
                .eq("slot", unconfirmedTask.getSlot())
                .eq("state", Const.RAW_GLASS_STATE_IN)
                .setSql("remain_quantity = remain_quantity - " + (finishCount + damageCount)));
        //更新工程下的原片数量 todo:sql待优化
        if (finishCount > 0) {
            List<Integer> ids = upPattenUsageMapper.queryFinishByEngineering(deviceId, finishCount);
            upPattenUsageMapper.update(null, new LambdaUpdateWrapper<UpPattenUsage>()
                    .in(UpPattenUsage::getId, ids)
                    .set(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS));
        }
        //任务表数据情况
                .setSql("remain_quantity = GREATEST(remain_quantity - 1, 0)"));
        //汇报字给1
        S7DataSP s7DataSPWrite = new S7DataSP();
        s7DataSPWrite.setTaskRunning(Boolean.FALSE);
        s7DataSPWrite.setTotalCount(0);
        s7DataSPWrite.setRawGlassWidth(0);
        s7DataSPWrite.setRawGlassHeight(0);
        s7DataSPWrite.setSlot(0);
        if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) {
            s7SerializerSPOne.write(s7DataSPWrite);
        } else {
            s7SerializerSPTwo.write(s7DataSPWrite);
        }
        loadGlassDeviceTaskHistoryService.update(new LambdaUpdateWrapper<LoadGlassDeviceTaskHistory>()
                .set(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_SUCCESS)
                .eq(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_NEW)
                .eq(LoadGlassDeviceTaskHistory::getStation, deviceId)
        );
        s7DataSPWrite.setMesConfirm(1);
        s7SerializerSPOne.write(s7DataSPWrite);
    }
    private boolean saveHistoryTask(S7DataSP task, Integer deviceId) {
    private boolean saveHistoryTask(LoadGlassDeviceTaskHistory task, Integer deviceId) {
        LoadGlassDeviceTaskHistory taskHistory = new LoadGlassDeviceTaskHistory();
        BeanUtils.copyProperties(task, taskHistory);
        taskHistory.setStation(deviceId);
        taskHistory.setCreateTime(new Date());
        taskHistory.setTaskState(Const.RAW_GLASS_TASK_NEW);
        taskHistory.setTaskState(Const.RAW_GLASS_TASK_RUNNING);
        loadGlassDeviceTaskHistoryService.save(taskHistory);
        return Boolean.TRUE;
    }
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/job/PlcLoadGlassTask.java
@@ -132,7 +132,7 @@
        }
    }
    @Scheduled(fixedDelay = 10000)
    @Scheduled(fixedDelay = 1000)
    public void loadOneGlass() {
        loadGlassChild("loadGlassRequestOne", 5, LOAD_GLASS_DEVICE_ONE_TASK, "loadGlassOne");
    }
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/s7/entity/S7DataSP.java
@@ -1,6 +1,6 @@
package com.mes.s7.entity;
import com.github.xingshuangs.iot.common.enums.EDataType;
import com.github.xingshuangs.iot.protocol.common.enums.EDataType;
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable;
import lombok.Data;
@@ -13,32 +13,33 @@
public class S7DataSP {
    @S7Variable(address = "DB19.14", type = EDataType.UINT16)
    private Integer taskState;
    @S7Variable(address = "DB151.0", type = EDataType.UINT16)
    private Integer plcRequest;
    @S7Variable(address = "DB19.18", type = EDataType.UINT16)
    private Integer damageCount;
    @S7Variable(address = "DB151.2", type = EDataType.UINT16)
    private Integer plcRequestId;
    @S7Variable(address = "DB19.20", type = EDataType.UINT16)
    private Integer rawGlassWidth;
    @S7Variable(address = "DB151.10", type = EDataType.UINT16)
    private Integer plcReport;
    @S7Variable(address = "DB19.22", type = EDataType.UINT16)
    private Integer rawGlassHeight;
    @S7Variable(address = "DB151.12", type = EDataType.UINT16)
    private Integer plcReportId;
    @S7Variable(address = "DB19.24", type = EDataType.UINT16)
    @S7Variable(address = "DB151.20", type = EDataType.UINT16)
    private Integer mesSend;
    @S7Variable(address = "DB151.22", type = EDataType.UINT16)
    private Integer mesSendId;
    @S7Variable(address = "DB151.24", type = EDataType.UINT16)
    private Integer slot;
    @S7Variable(address = "DB19.26", type = EDataType.UINT16)
    private Integer totalCount;
    @S7Variable(address = "DB151.26", type = EDataType.UINT16)
    private Integer rawGlassHeight;
    @S7Variable(address = "DB19.28", type = EDataType.UINT16)
    private Integer finishCount;
    @S7Variable(address = "DB151.28", type = EDataType.UINT16)
    private Integer rawGlassWidth;
    @S7Variable(address = "DB19.16.0", type = EDataType.BOOL)
    private Boolean taskRunning;
    @S7Variable(address = "DB19.30", type = EDataType.UINT16)
    private Integer inkageState;
    @S7Variable(address = "DB151.40", type = EDataType.UINT16)
    private Integer mesConfirm;
}
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/controller/UpPattenUsageController.java
@@ -94,5 +94,17 @@
        }
    }
    @ApiOperation("添加任务")
    @PostMapping("/insertTask")
    public Result insertTask(Integer quantity, Integer slot) {
        return Result.build(200, "添加成功", upPattenUsageService.insertTask(quantity, slot));
    }
    @ApiOperation("删除任务")
    @PostMapping("/deleteTask")
    public Result deleteUpPattenTask(String id) {
        return Result.build(200, "删除成功", upPattenUsageService.deleteUpPattenTask(id));
    }
}
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/service/UpPattenUsageService.java
@@ -89,5 +89,20 @@
      */
     String identControls(DamageRequest request);
     /**
      * 开始上片
      *
      * @param quantity
      * @param slot
      * @return
      */
     Boolean insertTask(Integer quantity, Integer slot);
    /**
     * 删除任务
     *
     * @return
     */
     Boolean deleteUpPattenTask(String id);
}
hangzhoumesParent/moduleService/LoadGlassModule/src/main/java/com/mes/uppattenusage/service/impl/UpPattenUsageServiceImpl.java
@@ -4,15 +4,19 @@
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.query.MPJQueryWrapper;
import com.mes.common.config.Const;
import com.mes.damage.entity.request.DamageRequest;
import com.mes.damage.service.DamageService;
import com.mes.engineering.entity.Engineering;
import com.mes.engineering.service.EngineeringService;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.mapper.OptimizeProjectMapper;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.mes.rawglassdetails.service.RawGlassStorageDetailsService;
import com.mes.uppattenusage.entity.OptimizeUpPattenUsage;
import com.mes.uppattenusage.entity.UpPattenUsage;
import com.mes.uppattenusage.mapper.UpPattenUsageMapper;
@@ -22,7 +26,12 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
@@ -45,6 +54,10 @@
    DamageService damageService;
    @Autowired
    RedisUtil redisUtil;
    @Resource
    RawGlassStorageDetailsService rawGlassStorageDetailsService;
    @Override
    public List<UpPattenUsage> prioritylist() {
        //获取正在上片的任务id
@@ -101,7 +114,7 @@
        // 创建一个 List 用于保存映射后的实体对象
        List<UpPattenUsage> resultList = new ArrayList<>();
// 遍历查询结果中的每个 Map 对象
        // 遍历查询结果中的每个 Map 对象
        if (upPattenUsageList != null) {
            for (OptimizeUpPattenUsage map : upPattenUsageList) {
                // 创建一个新的 OptimizeProject 对象
@@ -229,4 +242,91 @@
        damageService.autoSubmitReport(request.getGlassId(), request.getLine(), request.getWorkingProcedure(), "上片机", request.getState());
        return "success";
    }
    @Override
    public Boolean insertTask(Integer quantity, Integer slot) {
        engineeringService.update(
                new LambdaUpdateWrapper<Engineering>()
                        .eq(Engineering::getState, Const.ENGINEERING_RUNNING)
                        .set(Engineering::getState, Const.ENGINEERING_SUCCESS)
        );
        Calendar calendar = Calendar.getInstance();
        // 当天 00:00:00
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date todayStart = calendar.getTime();
        // 当天 23:59:59
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        Date todayEnd = calendar.getTime();
        // 2. 构建查询条件:状态为“运行中” + 时间在当天范围内
        Integer count = engineeringService.count(
                new LambdaQueryWrapper<Engineering>()
                        .eq(Engineering::getState, Const.ENGINEERING_RUNNING) // 原状态条件
                        // 核心:createTime 大于等于当天开始,小于等于当天结束
                        .ge(Engineering::getCreateTime, todayStart)
                        .le(Engineering::getCreateTime, todayEnd)
        );
        RawGlassStorageDetails rawGlassStorageDetails = rawGlassStorageDetailsService.getOne(
                new LambdaQueryWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getSlot, slot)
                        .eq(RawGlassStorageDetails::getState, 100)
        );
        String engineerId = generateSingleProjectNo(count);
        Engineering engineering = new Engineering();
        engineering.setEngineerId(engineerId);
        engineering.setEngineerName(rawGlassStorageDetails.getFilmsId());
        engineering.setState(1);
        engineering.setStationCell(5);
        engineering.setPlanPatternTotal(slot);
        engineering.setFilmsId(rawGlassStorageDetails.getFilmsId());
        engineeringService.save(engineering);
        for (int i = 1; i <= quantity; i++) {
            UpPattenUsage saveDetails = new UpPattenUsage();
            saveDetails.setEngineeringId(engineerId);
            saveDetails.setFilmsId(rawGlassStorageDetails.getFilmsId());
            saveDetails.setWidth(rawGlassStorageDetails.getPatternWidth());
            saveDetails.setHeight(rawGlassStorageDetails.getPatternHeight());
            saveDetails.setThickness(rawGlassStorageDetails.getPatternThickness());
            saveDetails.setLayoutSequence(i);
            saveDetails.setState(0);
            this.save(saveDetails);
        }
        return Boolean.TRUE;
    }
    private static String generateSingleProjectNo(int currentCount) {
        // 1. 固定前缀 "P"
        final String PREFIX = "P";
        // 2. 格式化当前日期为「年2位+月2位+日2位」(如2025-05-08 → "250508")
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyMMdd");
        String dateStr = LocalDate.now().format(dateFormatter);
        // 3. 计算新序号(已有数量+1),并处理“小于10补0”
        int newSequence = currentCount + 1;
        // 关键:%02d 表示固定2位数字,不足则补0(1→"01",9→"09",10→"10")
        String formattedSequence = String.format("%02d", newSequence);
        // 4. 拼接工程号(前缀+日期+补0后的序号)
        return PREFIX + dateStr + formattedSequence;
    }
    @Override
    public Boolean deleteUpPattenTask(String id) {
        //删除上片顺序表
        QueryWrapper<UpPattenUsage> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        return this.remove(wrapper);
    }
}
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application-alg.yml
@@ -9,16 +9,6 @@
          username: root
          password: beibo.123/
          driver-class-name: com.mysql.cj.jdbc.Driver
        pp:
          url: jdbc:mysql://192.168.10.86:3306/pp?serverTimezone=GMT%2b8
          username: root
          password: beibo.123/
          driver-class-name: com.mysql.cj.jdbc.Driver
        sd:
          url: jdbc:mysql://192.168.10.86:3306/sd?serverTimezone=GMT%2b8
          username: root
          password: beibo.123/
          driver-class-name: com.mysql.cj.jdbc.Driver
      druid:
        wall:
          multi-statement-allow: true
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application-dev.yml
@@ -33,7 +33,7 @@
    password: 123456
kangaroohy:
  milo:
    enabled: true
    enabled: false
    primary: default
    config:
      default: