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: