UI-Project/package-lock.json
@@ -15,6 +15,7 @@ "dayjs": "^1.11.13", "echarts": "^5.5.1", "element-plus": "^2.4.0", "file-saver": "^2.0.5", "moment": "^2.30.1", "northglass-mes": "file:", "pinia": "^2.1.6", @@ -1012,6 +1013,11 @@ "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-saver": { "version": "2.0.5", "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, "node_modules/fill-range": { "version": "7.0.1", @@ -2971,6 +2977,11 @@ "reusify": "^1.0.4" } }, "file-saver": { "version": "2.0.5", "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3225,9 +3236,10 @@ "axios": "^1.6.8", "babel-polyfill": "^6.26.0", "chart.js": "^4.4.3", "dayjs": "*", "dayjs": "^1.11.13", "echarts": "^5.5.1", "element-plus": "^2.4.0", "file-saver": "^2.0.5", "http-proxy-middleware": "^3.0.0", "moment": "^2.30.1", "northglass-mes": "file:", @@ -3979,6 +3991,11 @@ "reusify": "^1.0.4" } }, "file-saver": { "version": "2.0.5", "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", UI-Project/package.json
@@ -15,6 +15,7 @@ "dayjs": "^1.11.13", "echarts": "^5.5.1", "element-plus": "^2.4.0", "file-saver": "^2.0.5", "moment": "^2.30.1", "northglass-mes": "file:", "pinia": "^2.1.6", UI-Project/src/lang/en.js
@@ -511,6 +511,8 @@ createTime: 'Return date', }, large: { statistics: 'Statistics', ExporttoExcel:'Export to Excel', slice:'slice', load: 'load', edg: 'edg', UI-Project/src/lang/zh.js
@@ -513,6 +513,8 @@ createTime :'返库日期', }, large:{ statistics: '生产统计', ExporttoExcel:'导出excel', slice:'片', load:'切割', edg:'磨边', UI-Project/src/router/index.js
@@ -490,6 +490,18 @@ }, ] }, { path: '/productionstatistics', name: 'productionstatistics', component: () => import('../views/largescreendisplay/productionstatistics.vue'), children: [ { path: '/largescreendisplay/productionstatistics', name: 'productionstatistics', component: () => import('../views/largescreendisplay/productionstatistics.vue') }, ] }, ] }) // 导航守卫 UI-Project/src/views/largescreendisplay/screendisplay.vue
@@ -1,5 +1,5 @@ <script setup> import { onBeforeUnmount, onMounted, onUnmounted, ref, computed, nextTick } from "vue"; import { onBeforeUnmount, onMounted, onUnmounted, ref, computed, nextTick, watch } from "vue"; import { useRouter } from "vue-router" import { host, WebSocketHost } from '@/utils/constants' import request from "@/utils/request" @@ -32,7 +32,10 @@ const edgTwoTasks = ref([]) const engineeringOne = ref([]) const engineeringTwo = ref([]) let myChartLoad = null; let myChartEdg = null; let myChartTemp = null; let myChartHollow = null; const socketUrl1 = `ws://${WebSocketHost}:${host}/api/cacheGlass/api/talk/largenScreen`; const handleMessage1 = (data) => { edgOneTasks.value = data.edgOneTasks[0]; @@ -41,100 +44,15 @@ engineeringTwo.value = data.engineeringTwo[0]; if (numBoxes.value != edgOneTasks.value.length) { numBoxes.value = edgOneTasks.value.length; boxStart(); initBoxes(boxes, numBoxes, 'firstup'); } if (numBoxes2.value != edgTwoTasks.value.length) { numBoxes2.value = edgTwoTasks.value.length; boxStart2(); initBoxes(boxes2, numBoxes2, 'firstup'); } const pieChartVOS = ref([]); pieChartVOS.value = data.pieChartVOS[0]; let oneFinish = ref(); let twoFinish = ref(); let oneunFinish = ref(); let twounFinish = ref(); if (pieChartVOS.value.length > 0) { if (load.value) { oneFinish = pieChartVOS.value[0].oneCompletedQuantity; twoFinish = pieChartVOS.value[0].twoCompletedQuantity; oneunFinish = pieChartVOS.value[0].oneUncompletedQuantity; twounFinish = pieChartVOS.value[0].twoUncompletedQuantity; } else { oneFinish = pieChartVOS.value[0].oneCompletedArea; twoFinish = pieChartVOS.value[0].twoCompletedArea; oneunFinish = pieChartVOS.value[0].oneUncompletedArea; twounFinish = pieChartVOS.value[0].twoUncompletedArea; } } else { oneFinish = 0; twoFinish = 0; oneunFinish = 0; twounFinish = 0; } const chartDomOne = chartOne.value; if (!chartDomOne) { console.error('图表容器未找到'); return; } const myChartOne = echarts.init(chartDomOne); const optionOne = { title: { text: t('large.load'), subtext: '', left: 'right' }, tooltip: { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series: [ { name: '', type: 'pie', radius: '50%', data: [ { value: oneFinish, name: t('large.oneFinish') }, { value: twoFinish, name: t('large.twoFinish') }, { value: oneunFinish, name: t('large.oneunFinish') }, { value: twounFinish, name: t('large.twounFinish') }, ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ], graphic: [ { type: 'rect', left: 'center', top: 0, shape: { width: 80, height: 30 }, style: { text: load.value == true ? t('large.quantity') : t('large.are'), fill: '#5470C6', stroke: '#000', lineWidth: 1 }, onclick: function () { load.value = !load.value; } } ] }; myChartOne.setOption(optionOne); timeAxisCreate("切割当天运行情况", chartLoad.value, myChartLoad, data.loadRunTimes[0]); timeAxisCreate("磨边当天运行情况", chartEdg.value, myChartEdg, data.loadRunTimes[0]); }; let socket2 = null; const temperingTaskType = ref([]) @@ -146,287 +64,250 @@ temperingGlassInfoList.value = data.temperingGlassInfoList[0]; if (numBoxes3.value != temperingTaskType.value) { numBoxes3.value = temperingTaskType.value; boxStart3(); // initBoxes(boxes3, numBoxes3, 'secondleft'); } if (temperingGlassInfoList.value > 1) { if (numBoxes4.value != 1) { numBoxes4.value = 1; // initBoxes(boxes4, numBoxes4, 'right'); } } else { if (numBoxes4.value != 0) { numBoxes4.value = 0; // initBoxes(boxes4, numBoxes4, 'right'); } } temperingGlassInfoInList.value = data.temperingGlassInfoInList[0]; const pieChartVOS = ref([]); pieChartVOS.value = data.pieChartVOS[0]; let oneFinish = ref(); let ondDamage = ref(); let oneunFinish = ref(); if (pieChartVOS.value.length > 0) { if (temp.value) { oneFinish = pieChartVOS.value[0].oneCompletedQuantity; ondDamage = pieChartVOS.value[0].oneDamageQuantity; oneunFinish = pieChartVOS.value[0].oneUncompletedQuantity; } else { oneFinish = pieChartVOS.value[0].oneCompletedArea; ondDamage = pieChartVOS.value[0].oneDamageArea; oneunFinish = pieChartVOS.value[0].oneUncompletedArea; } } else { oneFinish = 0; ondDamage = 0; oneunFinish = 0; } const chartDomOne = chartThree.value; if (!chartDomOne) { console.error('图表容器未找到'); return; } const myChartOne = echarts.init(chartDomOne); const optionOne = { title: { text: t('large.temp'), subtext: '', left: 'right' }, tooltip: { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series: [ { name: '', type: 'pie', radius: '50%', data: [ { value: oneFinish, name: t('large.oneFinish') }, { value: ondDamage, name: t('large.ondDamage') }, { value: oneunFinish, name: t('large.oneunFinish') }, ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ], graphic: [ { type: 'rect', left: 'center', top: 0, shape: { width: 80, height: 30 }, style: { text: temp.value == true ? t('large.quantity') : t('large.are'), fill: '#5470C6', stroke: '#000', lineWidth: 1 }, onclick: function () { temp.value = !temp.value; } } ] }; myChartOne.setOption(optionOne); }; let socket3 = null; const bigStorageCageUsage = ref([]) const socketUrl3 = `ws://${WebSocketHost}:${host}/api/cacheVerticalGlass/api/talk/largenScreen`; const handleMessage3 = (data) => { bigStorageCageUsage.value = data.bigStorageCageUsage[0]; const pieChartVOS = ref([]); pieChartVOS.value = data.pieChartVOS[0]; let oneFinish = ref(); let twoFinish = ref(); let oneunFinish = ref(); let twounFinish = ref(); if (pieChartVOS.value.length > 0) { if (edg.value) { oneFinish = pieChartVOS.value[0].oneCompletedQuantity; twoFinish = pieChartVOS.value[0].twoCompletedQuantity; oneunFinish = pieChartVOS.value[0].oneUncompletedQuantity; twounFinish = pieChartVOS.value[0].twoUncompletedQuantity; } else { oneFinish = pieChartVOS.value[0].oneCompletedArea; twoFinish = pieChartVOS.value[0].twoCompletedArea; oneunFinish = pieChartVOS.value[0].oneUncompletedArea; twounFinish = pieChartVOS.value[0].twoUncompletedArea; } } else { oneFinish = 0; twoFinish = 0; oneunFinish = 0; twounFinish = 0; timeAxisCreate("钢化当天运行情况", chartTemp.value, myChartTemp, data.tempRunTimes[0]); }; // let mychart = null; // 建议设为外部变量避免重复初始化 // const formatToTimeString(datetime) => { const formatToTimeString = (datetime) => { const date = new Date(datetime); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; } const chartDomOne = chartTwo.value; if (!chartDomOne) { const timeAxisCreate = (title, chartDom, mychart, RunTimes) => { if (!chartDom) { console.error('图表容器未找到'); return; } const myChartOne = echarts.init(chartDomOne); if (!mychart) { mychart = echarts.init(chartDom); } let firstTime = null; let secondTime = null; if (RunTimes.length == 0) { firstTime = "00-00-00 00:00:00"; secondTime = "00-00-00 00:00:00"; } else { firstTime = RunTimes[0].startTimestamp; secondTime = RunTimes[0].endTimestamp; } let datas = ref([]) RunTimes.forEach((item, index) => { // if (index % 2 === 0) { datas.value.push([item.firstTimestamp, -1, formatToTimeString(item.firstTimestamp)]) datas.value.push([item.secondTimestamp, 1, formatToTimeString(item.secondTimestamp)]) // } else { // datas.value.push([item.firstTimestamp, -1, item.diffMinutes]) // datas.value.push([item.firstTimestamp, -1, item.diffMinutes]) // } }) // console.log(D) // 构建线段数组 const segments = RunTimes.map(item => ({ type: 'line', symbol: 'none', data: [ [item.firstTimestamp, 0], [item.secondTimestamp, 0] ], lineStyle: { color: 'red', // 支持不同颜色 width: 4 }, z: 1 })); const optionOne = { title: { text: t('large.edg'), subtext: '', left: 'right' text: title, left: 'center', top: '5%', textStyle: { fontSize: 16, fontWeight: 'bold', color: '#333' } }, tooltip: { trigger: 'item' trigger: 'axis', axisPointer: { type: 'line' }, backgroundColor: 'rgba(50,50,50,0.7)', textStyle: { color: '#fff' } }, legend: { orient: 'vertical', left: 'left' grid: { top: '20%', left: '5%', right: '5%', bottom: '15%' }, xAxis: { type: 'time', axisLabel: { formatter: function (value) { const date = new Date(value); return ( date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0') + ':' + date.getSeconds().toString().padStart(2, '0') ); }, fontSize: 10, color: '#666' }, splitLine: { show: false }, axisLine: { lineStyle: { color: '#aaa' } } }, yAxis: { type: 'value', min: -1, max: 1, show: false }, series: [ // 主时间线(蓝色渐变,稍微加粗) { name: '', type: 'pie', radius: '50%', type: 'line', symbol: 'none', data: [ { value: oneFinish, name: t('large.oneFinish') }, { value: twoFinish, name: t('large.twoFinish') }, { value: oneunFinish, name: t('large.oneunFinish') }, { value: twounFinish, name: t('large.twounFinish') }, [firstTime, 0], [secondTime, 0] ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' lineStyle: { color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ { offset: 0, color: '#4facfe' }, { offset: 1, color: '#00f2fe' } ]), width: 5, shadowColor: 'rgba(0,0,0,0.2)', shadowBlur: 8 }, z: 0 }, // 小段时间线(统一柔和的黄色) ...segments.map(seg => ({ ...seg, lineStyle: { color: '#ffcc00', width: 3, shadowColor: 'rgba(255,204,0,0.5)', shadowBlur: 5 } } } ], graphic: [ })), // 卡片事件(优化样式) { type: 'rect', left: 'center', top: 0, type: 'custom', renderItem: function (params, api) { const x = api.coord([api.value(0), api.value(1)])[0]; const yBase = api.coord([api.value(0), 0])[1]; const yOffset = api.value(1) > 0 ? -70 : 30; const cardWidth = 40; const cardHeight = 22; const cardX = x; const cardY = yBase + yOffset; const text = api.value(2); return { type: 'group', children: [ { type: 'line', shape: { width: 80, height: 30 x1: x, y1: yBase, x2: x, y2: cardY + (api.value(1) > 0 ? cardHeight : 0) }, style: { text: edg.value == true ? t('large.quantity') : t('large.are'), fill: '#5470C6', stroke: '#000', lineWidth: 1 stroke: '#888', lineWidth: 1.5, lineDash: [4, 2] } }, onclick: function () { edg.value = !edg.value; { type: 'rect', shape: { x: cardX - cardWidth / 2, y: cardY, width: cardWidth, height: cardHeight, r: 6 // 圆角 }, style: { fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#ffffff' }, { offset: 1, color: '#e0f7fa' } ]), stroke: '#00acc1', lineWidth: 1, shadowColor: '#ccc', shadowBlur: 6 } }, { type: 'text', style: { text: text, x: cardX, y: cardY + cardHeight / 2, textAlign: 'center', textVerticalAlign: 'middle', font: '12px sans-serif', fill: '#006064' } } ] }; myChartOne.setOption(optionOne); }, encode: { x: 0 }, data: datas.value, z: 10 } ] }; mychart.setOption(optionOne); }; let socket4 = null; const hollowBigStorageCageUsage = ref([]) const socketUrl4 = `ws://${WebSocketHost}:${host}/api/hollowGlass/api/talk/largenScreen`; const handleMessage4 = (data) => { hollowBigStorageCageUsage.value = data.hollowBigStorageCageUsage[0]; const pieChartVOS = ref([]); pieChartVOS.value = data.pieChartVOS[0]; let oneFinish = ref(); let twoFinish = ref(); let oneunFinish = ref(); let twounFinish = ref(); if (pieChartVOS.value.length > 0) { if (hollow.value) { oneFinish = pieChartVOS.value[0].oneCompletedQuantity; twoFinish = pieChartVOS.value[0].twoCompletedQuantity; oneunFinish = pieChartVOS.value[0].oneUncompletedQuantity; twounFinish = pieChartVOS.value[0].twoUncompletedQuantity; } else { oneFinish = pieChartVOS.value[0].oneCompletedArea; twoFinish = pieChartVOS.value[0].twoCompletedArea; oneunFinish = pieChartVOS.value[0].oneUncompletedArea; twounFinish = pieChartVOS.value[0].twoUncompletedArea; } } else { oneFinish = 0; twoFinish = 0; oneunFinish = 0; twounFinish = 0; } const chartDomOne = chartFour.value; if (!chartDomOne) { console.error('图表容器未找到'); return; } const myChartOne = echarts.init(chartDomOne); const optionOne = { title: { text: t('large.hollow'), subtext: '', left: 'right' }, tooltip: { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series: [ { name: '', type: 'pie', radius: '50%', data: [ { value: oneFinish, name: t('large.oneFinish') }, { value: twoFinish, name: t('large.twoFinish') }, { value: oneunFinish, name: t('large.oneunFinish') }, { value: twounFinish, name: t('large.twounFinish') }, ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ], graphic: [ { type: 'rect', left: 'center', top: 0, shape: { width: 80, height: 30 }, style: { text: hollow.value == true ? t('large.quantity') : t('large.are'), fill: '#5470C6', stroke: '#000', lineWidth: 1 }, onclick: function () { hollow.value = !hollow.value; } } ] }; myChartOne.setOption(optionOne); timeAxisCreate("中空当天运行情况", chartHollow.value, myChartHollow, data.hollowRunTimes[0]); }; let socket5 = null; let myChart = null; let myChart2 = null; const productionVO = ref([]) const socketUrl5 = `ws://${WebSocketHost}:${host}/api/cacheGlass/api/talk/largenScreenProduction`; const handleMessage5 = (data) => { @@ -452,8 +333,13 @@ console.error('图表容器未找到'); return; } const myChart = echarts.init(chartDom); // myChart = echarts.init(chartDom); if (!myChart) { myChart = echarts.init(chartDom); } // else { // myChart.clear(); // } const option = { @@ -494,7 +380,13 @@ console.error('图表容器未找到'); return; } const myChart2 = echarts.init(chartDom2); // myChart2 = echarts.init(chartDom2); if (!myChart2) { myChart2 = echarts.init(chartDom2); } // else { // myChart2.clear(); // } const option2 = { title: { text: '' }, tooltip: { trigger: 'axis' }, @@ -609,20 +501,19 @@ }; const chartRef = ref(null) const chartRef2 = ref(null) const chartOne = ref(null) const chartTwo = ref(null) const chartThree = ref(null) const chartFour = ref(null) const chartLoad = ref(null) const chartEdg = ref(null) const chartTemp = ref(null) const chartHollow = ref(null) // 在组件挂载时设置默认时间范围 onMounted(async () => { boxStart(); boxStart2(); boxStart3(); boxStart4(); requestAnimationFrame(animate); // boxStart(); // boxStart2() // boxStart3() // boxStart4(); // requestAnimationFrame(animate); socket = initializeWebSocket(socketUrl, handleMessage); socket1 = initializeWebSocket(socketUrl1, handleMessage1); socket2 = initializeWebSocket(socketUrl2, handleMessage2); @@ -648,194 +539,197 @@ closeWebSocket(socket5); } }); onBeforeUnmount(() => { closeWebSocket(); }); const numBoxes = ref(5); const numBoxes2 = ref(5); const numBoxes3 = ref(5); const numBoxes = ref(1); const numBoxes2 = ref(1); const numBoxes3 = ref(1); const numBoxes4 = ref(1); const speed = 0.1; const maxX = 200; // 终点X坐标 const maxY = -75; // 终点Y坐标 const maxX2 = 313; // 终点X坐标 const maxY2 = -165; // 终点Y坐标 const maxX3 = 95; // 终点X坐标 const maxY3 = -85; // 终点Y坐标 const maxX4 = 60; // 终点X坐标 const maxY4 = 0; // 终点Y坐标 const delayFrames = 600; // 每个 div 的延迟帧数 const boxes = ref([]); const boxes2 = ref([]); const boxes3 = ref([]); const boxes4 = ref([]); // 初始化 div 数据 const boxStart = () => { boxes.value = []; for (let i = 0; i < numBoxes.value; i++) { boxes.value.push({ const delayFrames = 600; const maxCoords = { box1: { x: 250, y: -165 }, box2: { x: 190, y: -75 }, box3: { x: 95, y: -85 }, box4: { x: 60, y: 0 }, }; let boxes = ref([]); let boxes2 = ref([]); let boxes3 = ref([]); let boxes4 = ref([]); const boxRefs = []; const boxRefs2 = []; const boxRefs3 = []; const boxRefs4 = []; let rafId = null; // ✅ 初始化 boxes,去除 style,保留 el const initBoxes = (arr, countRef, direction) => { const count = countRef.value; const existing = arr.value; for (let i = 0; i < count; i++) { if (!existing[i]) { existing.push({ x: 0, y: 0, // 初始位置在底部 direction: 'up', y: 0, direction, delay: i * delayFrames, style: { width: '15px', height: '15px', backgroundColor: i % 2 === 0 ? '#911005' : '#911005', position: 'absolute', transform: `translate(0px, 0px)` } frameCount: 0, el: null }); } else { // 重置已有的 box 数据 existing[i].x = 0; existing[i].y = 0; existing[i].direction = direction; existing[i].delay = i * delayFrames; existing[i].frameCount = 0; } } const boxStart2 = () => { boxes2.value = []; for (let i = 0; i < numBoxes2.value; i++) { boxes2.value.push({ x: 0, y: 0, // 初始位置在底部 direction: 'up', delay: i * delayFrames, style: { width: '15px', height: '15px', backgroundColor: i % 2 === 0 ? '#911005' : '#911005', position: 'absolute', transform: `translate(0px, 0px)` if (existing.length > count) { existing.length = count; } }); } } const boxStart3 = () => { boxes3.value = []; for (let i = 0; i < numBoxes3.value; i++) { boxes3.value.push({ x: 0, y: 0, // 初始位置在底部 direction: 'left', delay: i * delayFrames, style: { width: '15px', height: '15px', backgroundColor: i % 2 === 0 ? '#911005' : '#911005', position: 'absolute', transform: `translate(0px, 0px)` } }); } } const boxStart4 = () => { boxes4.value = []; for (let i = 0; i < numBoxes4.value; i++) { boxes4.value.push({ x: 0, y: 0, // 初始位置在底部 direction: 'right', delay: i * delayFrames, style: { width: '15px', height: '15px', backgroundColor: i % 2 === 0 ? '#911005' : '#911005', position: 'absolute', transform: `translate(0px, 0px)` } }); } } const animate = () => { boxes.value.forEach((box) => { }; // ✅ 动画函数 const animateBox = (box, maxX, maxY) => { if (box.delay > 0) { box.delay--; return; } if (box.direction === 'up') { switch (box.direction) { case 'firstup': box.y -= speed; if (box.y <= maxY) { // box.y = 0; // 确保不会超出界限 box.direction = 'left'; } } else if (box.direction === 'left') { if (box.y <= maxY) box.direction = 'firstleft'; break; case 'firstleft': box.x -= speed; if (box.x <= -maxX) { box.x = 0; box.y = 0; // 重新回到底部 box.direction = 'up'; box.y = 0; box.direction = 'firstup'; } } box.style = { ...box.style, transform: `translate(${box.x}px, ${box.y}px)` }; }); boxes2.value.forEach((box) => { if (box.delay > 0) { box.delay--; return; } if (box.direction === 'up') { break; case 'secondup': box.y -= speed; if (box.y <= maxY2) { // box.y = 0; // 确保不会超出界限 box.direction = 'left'; } } else if (box.direction === 'left') { box.x -= speed; if (box.x <= -maxX2) { if (box.y <= maxY) { box.x = 0; box.y = 0; // 重新回到底部 box.direction = 'up'; box.y = 0; box.direction = 'secondleft'; } } box.style = { ...box.style, transform: `translate(${box.x}px, ${box.y}px)` }; }); boxes3.value.forEach((box) => { if (box.delay > 0) { box.delay--; return; } if (box.direction === 'up') { box.y -= speed; if (box.y <= maxY3) { // box.y = 0; // 确保不会超出界限 box.direction = 'left'; box.x = 0; box.y = 0; // 重新回到底部 } } else if (box.direction === 'left') { break; case 'secondleft': box.x -= speed; if (box.x <= -maxX3) { box.direction = 'up'; if (box.x <= -maxX) { box.direction = 'secondup'; } } box.style = { ...box.style, transform: `translate(${box.x}px, ${box.y}px)` }; }); boxes4.value.forEach((box) => { if (box.delay > 0) { box.delay--; return; } if (box.direction === 'right') { break; case 'right': box.x += speed; if (box.x >= maxX4) { // box.y = 0; // 确保不会超出界限 if (box.x >= maxX) { box.x = 0; box.y = 0; // 重新回到底部 box.y = 0; } break; } box.frameCount++; if (box.frameCount % 2 === 0 && box.el) { box.el.style.top = `${box.y}px`; if (box.x > 0) { box.el.style.right = `${box.x}px`; box.el.style.left = ''; } else { box.el.style.left = `${box.x}px`; box.el.style.right = ''; } } box.style = { ...box.style, transform: `translate(${box.x}px, ${box.y}px)` }; const animate = () => { boxes.value.forEach(box => animateBox(box, maxCoords.box1.x, maxCoords.box1.y)); boxes2.value.forEach(box => animateBox(box, maxCoords.box2.x, maxCoords.box2.y)); boxes3.value.forEach(box => animateBox(box, maxCoords.box3.x, maxCoords.box3.y)); boxes4.value.forEach(box => animateBox(box, maxCoords.box4.x, maxCoords.box4.y)); rafId = requestAnimationFrame(animate); }; const boxStart = () => { initBoxes(boxes, numBoxes, 'firstup'); initBoxes(boxes2, numBoxes2, 'firstup'); initBoxes(boxes3, numBoxes3, 'secondleft'); initBoxes(boxes4, numBoxes4, 'right'); }; watch( () => boxes.value, async (newVal) => { await nextTick(); newVal.forEach((box, i) => { box.el = boxRefs[i]; }); requestAnimationFrame(animate); }; }, { deep: true, immediate: true } ); watch( () => boxes2.value, async (newVal) => { await nextTick(); newVal.forEach((box, i) => { box.el = boxRefs2[i]; }); }, { deep: true, immediate: true } ); watch( () => boxes3.value, async (newVal) => { await nextTick(); newVal.forEach((box, i) => { box.el = boxRefs3[i]; }); }, { deep: true, immediate: true } ); watch( () => boxes4.value, async (newVal) => { await nextTick(); newVal.forEach((box, i) => { box.el = boxRefs4[i]; }); }, { deep: true, immediate: true } ); onMounted(() => { boxStart(); animate(); }); onBeforeUnmount(() => { cancelAnimationFrame(rafId); rafId = null; boxes.value.length = 0; boxes2.value.length = 0; boxes3.value.length = 0; boxes4.value.length = 0; }); onUnmounted(() => { if (rafId) { cancelAnimationFrame(rafId); // 停止动画,防止内存泄漏 } }); // onBeforeUnmount(() => { // cancelAnimationFrame(rafId); // }); //嵌入历史任务 const iframeUrl1 = ref(''); const iframe1 = ref(false); @@ -896,6 +790,12 @@ const handlehistorical10 = () => { iframe10.value = true; iframeUrl10.value = `${window.location.origin}/#/largescreendisplay/statistics`; }; const iframeUrl11 = ref(''); const iframe11 = ref(false); const handlehistorical11 = () => { iframe11.value = true; iframeUrl11.value = `${window.location.origin}/#/largescreendisplay/productionstatistics`; }; const transposedData = computed(() => { const keys = Object.keys(fieldNames); // 按 fieldNames 的顺序 @@ -968,6 +868,10 @@ <iframe :src="iframeUrl10" marginwidth="2000px" marginheight="2000px" width="100%" height="750px" frameborder="0"></iframe> </el-dialog> <el-dialog v-model="iframe11" top="5vh" width="95%" @close="iframeUrl11 = ''"> <iframe :src="iframeUrl11" marginwidth="2000px" marginheight="2000px" width="100%" height="750px" frameborder="0"></iframe> </el-dialog> <div class="awatch" style="display: flex;"> <!-- 生产统计 --> @@ -976,60 +880,72 @@ <div ref="chartRef" style="width: 600px; height: 400px;" @dblclick="handlehistorical10()"></div> </div> <div style="width: 100%;height: 245px;display: flex;"> <div ref="chartOne" style="width: 100%;"></div> <div ref="chartLoad" style="width: 100%;"></div> </div> <div style="width: 100%;height: 245px;display: flex;"> <div ref="chartTwo" style="width: 100%;"></div> <div ref="chartEdg" style="width: 100%;"></div> </div> </div> <div style="width: 50%;"> <div class="img-screen" alt="Screen"> <div> <el-button type="primary" style="top:40px;left:670px;position: absolute;" @click="handlehistorical11()">{{ $t('large.statistics') }}</el-button> </div> <!-- 钢化半透明色块 --> <div style="width: 80px;height: 40px;top: 315px;left: 130px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOut : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOut : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaOut : 0 }}m²</div> </div> <!-- 中空一线半透明色块 --> <div style="width: 80px;height: 40px;top: 235px;left: 450px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].hollowCountOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].hollowCountOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].hollowTotalAreaOutOne : 0 }}m²</div> </div> <!-- 中空二线半透明色块 --> <div style="width: 80px;height: 40px;top: 130px;left: 450px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].hollowCountOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].hollowCountOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].hollowTotalAreaOutTwo : 0 }}m²</div> </div> <!-- 切割二线半透明色块 --> <div style="width: 80px;height: 40px;top: 542px;left: 410px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaOutOne : 0 }}m²</div> </div> <!-- 切割一线半透明色块 --> <div style="width: 80px;height: 40px;top: 490px;left: 410px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaOutTwo : 0 }}m²</div> </div> <!-- 磨边一线半透明色块 --> <div style="width: 80px;height: 40px;top: 369px;left: 450px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutOne : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaOutOne : 0 }}m²</div> </div> <!-- 磨边二线半透明色块 --> <div style="width: 80px;height: 40px;top: 410px;left: 450px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countOutTwo : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaOutTwo : 0 }}m²</div> </div> <!-- 钢化前大理{{ $t('large.slice') }}半透明色块 --> <div style="width: 80px;height: 40px;top: 380px;left: 290px;position: absolute;background-color: rgba(0, 0, 0, 0.5);color: white;font-size: 12px;z-index: 999;"> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countIn : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.quantity') }}:{{ productionVO.length > 0 ? productionVO[6].countIn : 0 }}{{ $t('large.slice') }}</div> <div>{{ $t('large.are') }}:{{ productionVO.length > 0 ? productionVO[6].totalAreaIn : 0 }}m²</div> </div> @@ -1073,21 +989,22 @@ <!-- 磨边色块 --> <div class="container" style="position: relative;width: 15px;height: 15px;top: 500px;left: 638px;position: absolute;"> <div v-for="(box, index) in boxes2" :key="index" class="box" :style="box.style"></div> <div v-for="(box, i) in boxes2" :key="`b1-${i}`" class="moving-rect" :ref="el => boxRefs2[i] = el" /> </div> <div class="container" style="position: relative;width: 15px;height: 15px;top: 548px;left: 690px;position: absolute;"> <div v-for="(box, index) in boxes" :key="index" class="box" :style="box.style"></div> <div v-for="(box, i) in boxes" :key="`b1-${i}`" class="moving-rect" :ref="el => boxRefs[i] = el" /> </div> <!-- 钢化运动色块 --> <div class="container" style="position: relative;width: 15px;height: 15px;top: 370px;left: 195px;position: absolute;background-color: red;"> <div v-for="(box, index) in boxes3" :key="index" class="box" :style="box.style"></div> style="position: relative;width: 15px;height: 15px;top: 370px;left: 195px;position: absolute;"> <div v-for="(box, i) in boxes3" :key="`b1-${i}`" class="moving-rect" :ref="el => boxRefs3[i] = el" /> </div> <div class="container" style="position: relative;width: 15px;height: 15px;top: 284px;left: 489px;position: absolute;"> <div v-for="(box, index) in boxes4" :key="index" class="box" :style="box.style"></div> <div v-for="(box, i) in boxes4" :key="`b1-${i}`" class="moving-rect" :ref="el => boxRefs4[i] = el" /> </div> <!-- <div class="moving-rect lipiana" v-show="true">1111111111</div> --> <!-- 钢化前大理片色块 --> <div class="container" v-for="(item, index) in bigStorageCageUsage.slice(0, 1)" :key="index" :style='"position: relative;width: " + (37 * item.percentage / 100) + "px;height: 13px;top: 374px;left: 309px;position: absolute;background-color: #911005;"'> @@ -1145,10 +1062,10 @@ <div ref="chartRef2" style="width: 600px; height: 400px;" @dblclick="handlehistorical10()"></div> </div> <div style="width: 100%;height: 245px;display: flex;"> <div ref="chartThree" style="width: 100%;"></div> <div ref="chartTemp" style="width: 100%;"></div> </div> <div style="width: 100%;height: 245px;display: flex;"> <div ref="chartFour" style="width: 100%;"></div> <div ref="chartHollow" style="width: 100%;"></div> </div> </div> </div> @@ -1287,4 +1204,31 @@ .box { transition: transform 0.016s linear; } .lipiana { width: 15px; height: 9px; background-color: #529b2e; top: 190px; right: 530px; transform: translateX(-50%); animation: move-lipiana 1s infinite; } @keyframes move-lipiana { 0% { right: 530px; } 100% { right: calc(100% - 350px); } } .moving-rect { width: 15px; height: 15px; background-color: #911005; position: absolute; } </style> UI-Project/src/views/largescreendisplay/statistics.vue
@@ -1,12 +1,12 @@ <template> <div> <div style="display: flex;width: 1770px;"> <el-date-picker v-model="timeRange" type="datetimerange" range-separator="至" :start-placeholder="$t('reportmanage.starttime')" style="margin-left: 15px;" value-format="YYYY-MM-DD hh:mm:ss" :end-placeholder="$t('reportmanage.endtime')"> <el-date-picker v-model="timeRange" type="daterange" range-separator="至" :start-placeholder="$t('reportmanage.starttime')" :end-placeholder="$t('reportmanage.endtime')" value-format="YYYY-MM-DD" style="margin-left: 15px;"> </el-date-picker> <el-button type="primary" style="margin-left: 10px;margin-bottom: 10px;" @click="sethistorical()">{{ $t('reportmanage.inquire') }}</el-button> <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' }"> @@ -20,7 +20,8 @@ <el-table-column prop="countOut" align="center" :label="$t('large.countOut')" min-width="40" /> <el-table-column prop="totalAreaOut" align="center" :label="$t('large.totalAreaOut')" min-width="40" /> <el-table-column prop="hollowCountOutOne" align="center" :label="$t('large.hollowCountOutOne')" min-width="40" /> <el-table-column prop="hollowTotalAreaOutOne" align="center" :label="$t('large.hollowTotalAreaOutOne')" min-width="40" /> <el-table-column prop="hollowTotalAreaOutOne" align="center" :label="$t('large.hollowTotalAreaOutOne')" min-width="40" /> <el-table-column prop="hollowCountOutTwo" align="center" :label="$t('large.hollowCountOutTwo')" min-width="40" /> <el-table-column prop="hollowTotalAreaOutTwo" align="center" :label="$t('large.hollowTotalAreaOutTwo')" min-width="40"/> hangzhoumesParent/common/servicebase/src/main/java/com/mes/largenscreen/entity/RunTime.java
New file @@ -0,0 +1,29 @@ package com.mes.largenscreen.entity; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @Author : zhoush * @Date: 2025/3/12 14:30 * @Description: */ @Data public class RunTime { @ApiModelProperty(value = "停机开始时间") private String firstTimestamp; @ApiModelProperty(value = "停机结束时间") private String secondTimestamp; @ApiModelProperty(value = "时间差") private String diffMinutes; @ApiModelProperty(value = "开始时间") private String startTimestamp; @ApiModelProperty(value = "结束时间按") private String endTimestamp; } hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/PushMessageToIndex.java
@@ -13,6 +13,7 @@ import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.DateRequest; import com.mes.largenscreen.entity.PieChartVO; import com.mes.largenscreen.entity.RunTime; import com.mes.largenscreen.service.LargenScreenService; import com.mes.opctask.entity.EdgStorageDeviceTaskHistory; import com.mes.opctask.service.EdgStorageDeviceTaskHistoryService; @@ -151,11 +152,10 @@ @Scheduled(fixedDelay = 1000) public void querySameDayProductionTask() { JSONObject jsonObject = new JSONObject(); List<DailyProductionVO> productionVO = largenScreenService.querySameDayProduction(new DateRequest()); jsonObject.append("productionVO", productionVO); ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreenProduction"); if (sendwServer != null) { List<DailyProductionVO> productionVO = largenScreenService.querySameDayProduction(new DateRequest()); jsonObject.append("productionVO", productionVO); for (WebSocketServer webserver : sendwServer) { if (webserver != null) { webserver.sendMessage(jsonObject.toString()); @@ -171,10 +171,13 @@ } } @Scheduled(fixedDelay = 1000) @Scheduled(fixedDelay = 500) public void largenScreen() { JSONObject jsonObject = new JSONObject(); //磨边信息 ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreen"); if (sendwServer != null) { List<EdgGlassTaskInfo> edgOneTasks = edgGlassTaskInfoService.list( new LambdaQueryWrapper<EdgGlassTaskInfo>() .lt(EdgGlassTaskInfo::getState, 2) @@ -201,8 +204,8 @@ jsonObject.append("engineeringTwo", engineeringTow); List<PieChartVO> pieChartVOS = edgStorageCageDetailsService.queryPieChart(); jsonObject.append("pieChartVOS", pieChartVOS); ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreen"); if (sendwServer != null) { List<RunTime> loadRunTimes = edgStorageDeviceTaskHistoryService.queryRunTimes(); jsonObject.append("loadRunTimes", loadRunTimes); for (WebSocketServer webserver : sendwServer) { if (webserver != null) { webserver.sendMessage(jsonObject.toString()); hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opctask/mapper/EdgStorageDeviceTaskHistoryMapper.java
@@ -2,8 +2,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import com.mes.opctask.entity.EdgStorageDeviceTaskHistory; import org.apache.ibatis.annotations.Param; import java.util.List; /** * (EdgStorageDeviceTaskHistory)表数据库访问层 @@ -14,5 +17,7 @@ public interface EdgStorageDeviceTaskHistoryMapper extends BaseMapper<EdgStorageDeviceTaskHistory> { DailyProductionVO queryEdgDailyProduction(@Param("beginDate") String beginDate, @Param("endDate") String endDate, @Param("deviceId") Integer deviceId); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opctask/service/EdgStorageDeviceTaskHistoryService.java
@@ -3,8 +3,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import com.mes.opctask.entity.EdgStorageDeviceTaskHistory; import com.mes.opctask.entity.request.TaskHistoryRequest; import java.util.List; /** * (EdgStorageDeviceTaskHistory)表服务接口 @@ -17,5 +20,7 @@ Page<EdgStorageDeviceTaskHistory> queryEdgStorageDeviceTaskHistory(TaskHistoryRequest request); DailyProductionVO queryEdgDailyProduction(TaskHistoryRequest request); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opctask/service/impl/EdgStorageDeviceTaskHistoryServiceImpl.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import com.mes.opctask.entity.EdgStorageDeviceTaskHistory; import com.mes.opctask.entity.request.TaskHistoryRequest; import com.mes.opctask.mapper.EdgStorageDeviceTaskHistoryMapper; @@ -12,6 +13,7 @@ import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.List; /** * (EdgStorageDeviceTaskHistory)表服务实现类 @@ -49,5 +51,10 @@ } return baseMapper.queryEdgDailyProduction(beginDate, endDate, request.getDeviceId()); } @Override public List<RunTime> queryRunTimes(){ return baseMapper.queryRunTimes(); } } hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/application-dev.yml
@@ -32,11 +32,11 @@ password: 123456 kangaroohy: milo: enabled: false enabled: true primary: default config: default: endpoint: opc.tcp://192.168.2.100:49320 endpoint: opc.tcp://10.153.19.150:49320 security-policy: basic256sha256 username: admin password: 1qaz2wsx3edc4rfv hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/mapper/EdgStorageDeviceTaskHistoryMapper.xml
@@ -18,8 +18,7 @@ <result column="hollow_total_area_out_two" property="hollowTotalAreaOutTwo"/> </resultMap> <select id="queryEdgDailyProduction" resultMap="baseMap"> <select id="queryDailyProduction" resultMap="baseMap"> SELECT count( t.glass_id_out ) AS count_out_one, round( sum( t1.width * t1.height )/ 1000000, 2 ) AS total_area_out_one @@ -36,6 +35,35 @@ AND device_id = #{deviceId} </if> </select> <select id="queryRunTimes" resultType="com.mes.largenscreen.entity.RunTime"> with edg_storage_cage_history_task_temp as ( select distinct create_time from edg_storage_device_task_history where task_type in (1,3) and create_time BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 DAY) ) SELECT t1.create_time AS first_timestamp, t2.create_time AS second_timestamp, TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) as diff_minutes ,(select min(create_time) from edg_storage_cage_history_task_temp) as start_timestamp ,(select max(create_time) from edg_storage_cage_history_task_temp) as end_timestamp FROM (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM edg_storage_cage_history_task_temp ) t1 JOIN (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM edg_storage_cage_history_task_temp ) t2 ON t1.next_timestamp = t2.create_time WHERE TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) between 6 and 500 GROUP BY t1.create_time,t2.create_time ; </select> </mapper> hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstoragecagetask/mapper/BigStorageCageHistoryTaskMapper.java
@@ -4,7 +4,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mes.bigstoragecagetask.entity.BigStorageCageHistoryTask; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import org.apache.ibatis.annotations.Param; import java.util.List; /** * (BigStorageCageHistoryTask)表数据库访问层 @@ -15,5 +18,7 @@ public interface BigStorageCageHistoryTaskMapper extends BaseMapper<BigStorageCageHistoryTask> { DailyProductionVO queryBigDailyProduction(@Param("beginDate") String beginDate, @Param("endDate") String endDate); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstoragecagetask/service/BigStorageCageHistoryTaskService.java
@@ -6,6 +6,9 @@ import com.mes.bigstoragecagetask.entity.BigStorageCageHistoryTask; import com.mes.bigstoragecagetask.entity.request.BigStorageCageHistoryRequest; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import java.util.List; /** * (BigStorageCageHistoryTask)表服务接口 @@ -18,5 +21,7 @@ Page<BigStorageCageHistoryTask> queryBigStorageCageHistoryTask(BigStorageCageHistoryRequest request); DailyProductionVO queryBigDailyProduction(BigStorageCageHistoryRequest request); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstoragecagetask/service/impl/BigStorageCageHistoryTaskServiceImpl.java
@@ -11,10 +11,12 @@ import com.mes.bigstoragecagetask.mapper.BigStorageCageHistoryTaskMapper; import com.mes.bigstoragecagetask.service.BigStorageCageHistoryTaskService; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import com.mes.tools.DateUtil; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.List; /** * (BigStorageCageHistoryTask)表服务实现类 @@ -54,5 +56,11 @@ } return baseMapper.queryBigDailyProduction(beginDate, endDate); } @Override public List<RunTime> queryRunTimes(){ return baseMapper.queryRunTimes(); } } hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/job/OPCPlcSlicecage.java
@@ -8,12 +8,15 @@ import com.mes.bigstorage.entity.dto.BigStorageSummaryDTO; import com.mes.bigstorage.service.BigStorageCageDetailsService; import com.mes.bigstorage.service.BigStorageCageService; import com.mes.bigstoragecagetask.entity.BigStorageCageHistoryTask; import com.mes.bigstoragecagetask.entity.BigStorageCageTask; import com.mes.bigstoragecagetask.entity.BigStorageTaskVO; import com.mes.bigstoragecagetask.service.BigStorageCageHistoryTaskService; import com.mes.bigstoragecagetask.service.BigStorageCageTaskService; import com.mes.common.config.Const; import com.mes.glassinfo.service.GlassInfoService; import com.mes.largenscreen.entity.PieChartVO; import com.mes.largenscreen.entity.RunTime; import com.mes.temperingglass.entity.TemperingGlassInfo; import com.mes.temperingglass.service.TemperingGlassInfoService; import com.mes.tools.WebSocketServer; @@ -47,6 +50,8 @@ private GlassInfoService glassInfoService; @Resource private BigStorageCageTaskService bigStorageCageTaskService; @Resource private BigStorageCageHistoryTaskService bigStorageCageHistoryTaskService; @Autowired(required = false) MiloService miloService; @@ -209,12 +214,14 @@ public void largenScreen() { JSONObject jsonObject = new JSONObject(); //理片笼使用情况 ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreen"); if (sendwServer != null) { List<Map<String, Object>> bigStorageCageUsage = bigStorageCageService.selectBigStorageCageUsage(); jsonObject.append("bigStorageCageUsage", bigStorageCageUsage); List<PieChartVO> pieChartVOS = bigStorageCageService.queryPieChart(); jsonObject.append("pieChartVOS", pieChartVOS); ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreen"); if (sendwServer != null) { List<RunTime> tempRunTimes = bigStorageCageHistoryTaskService.queryRunTimes(); jsonObject.append("tempRunTimes", tempRunTimes); for (WebSocketServer webserver : sendwServer) { if (webserver != null) { webserver.sendMessage(jsonObject.toString()); hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/application-dev.yml
@@ -30,7 +30,7 @@ password: 123456 kangaroohy: milo: enabled: true enabled: false primary: default config: default: hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/mapper/BigStorageCageHistoryTaskMapper.xml
@@ -42,7 +42,32 @@ select * from big_storage_in_temp INNER join big_storage_out_temp on 1 = 1 </select> <select id="queryRunTimes" resultType="com.mes.largenscreen.entity.RunTime"> with big_storage_cage_history_task_temp as ( select distinct create_time from big_storage_cage_history_task where task_type = 2 and create_time BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 DAY) ) SELECT t1.create_time AS first_timestamp, t2.create_time AS second_timestamp, TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) as diff_minutes , (select min(create_time) from big_storage_cage_history_task_temp) as start_timestamp , (select max(create_time) from big_storage_cage_history_task_temp) as end_timestamp FROM (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM big_storage_cage_history_task_temp) t1 JOIN (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM big_storage_cage_history_task_temp) t2 ON t1.next_timestamp = t2.create_time WHERE TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) between 11 and 500 GROUP BY t1.create_time, t2.create_time ; </select> </mapper> hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassTask.java
@@ -3,6 +3,7 @@ import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer; import com.kangaroohy.milo.model.ReadWriteEntity; import com.kangaroohy.milo.service.MiloService; import com.mes.common.config.Const; @@ -16,6 +17,8 @@ import com.mes.rawglassstation.service.RawGlassStorageStationService; import com.mes.rawglasstask.entity.RawGlassStorageTask; import com.mes.rawglasstask.service.RawGlassStorageTaskService; import com.mes.s7.entity.S7Data; import com.mes.s7.job.S7Job; import com.mes.uppattenusage.entity.UpPattenUsage; import com.mes.uppattenusage.entity.vo.UpPattenUsageVO; import com.mes.uppattenusage.mapper.UpPattenUsageMapper; @@ -57,6 +60,9 @@ @Autowired(required = false) private MiloService miloService; @Autowired(required = false) S7Serializer s7Serializer; private static final String LOAD_GLASS_DEVICE_ONE_TASK = "load_glass_device_one_task"; @@ -64,6 +70,7 @@ 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 Integer LOAD_GLASS_ONE_DEVICE = 5; @@ -71,23 +78,40 @@ @Scheduled(fixedDelay = 1000) public void rawStorageTask() throws Exception { ReadWriteEntity requestWord = miloService.readFromOpcUa("CC.CC.request"); ReadWriteEntity confireWord = miloService.readFromOpcUa("CC.CC.confirmation"); ReadWriteEntity reportWord = miloService.readFromOpcUa("CC.CC.reportWord"); ReadWriteEntity taskWord = miloService.readFromOpcUa("CC.CC.taskWord"); String requestValue = requestWord.getValue() + ""; String requestWord = S7Job.S7DataWL1.getRequest().toString(); String confireWord = S7Job.S7DataWL1.getConfirmation().toString(); String reportWord = S7Job.S7DataWL1.getReportWord().toString(); String taskWord = S7Job.S7DataWL1.getTaskWord().toString(); // ReadWriteEntity requestWord = miloService.readFromOpcUa("CC.CC.request"); // ReadWriteEntity confireWord = miloService.readFromOpcUa("CC.CC.confirmation"); // ReadWriteEntity reportWord = miloService.readFromOpcUa("CC.CC.reportWord"); // ReadWriteEntity taskWord = miloService.readFromOpcUa("CC.CC.taskWord"); String requestValue = requestWord; // String requestValue = requestWord.getValue() + ""; if ("0".equals(requestValue)) { if ("1".equals(confireWord.getValue() + "") && "0".equals(reportWord.getValue() + "")) { List<ReadWriteEntity> list = new ArrayList<>(); list.add(generateReadWriteEntity("CC.CC.confirmation", 0)); miloService.writeToOpcWord(list); if ("1".equals(confireWord) && "0".equals(reportWord)) { // if ("1".equals(confireWord.getValue() + "") && "0".equals(reportWord.getValue() + "")) { S7Data s7Data=new S7Data(); s7Data.setConfirmation((short)0); s7Serializer.write(s7Data); // List<ReadWriteEntity> list = new ArrayList<>(); // list.add(generateReadWriteEntity("CC.CC.confirmation", 0)); // miloService.writeToOpcWord(list); } if ("1".equals(taskWord.getValue() + "")) { List<ReadWriteEntity> list = new ArrayList<>(); list.add(generateReadWriteEntity("CC.CC.taskWord", 0)); list.add(generateReadWriteEntity("CC.CC.startSlot", 0)); list.add(generateReadWriteEntity("CC.CC.endSlot", 0)); miloService.writeToOpcWord(list); if ("1".equals(taskWord)) { // if ("1".equals(taskWord.getValue() + "")) { S7Data s7Data=new S7Data(); s7Data.setTaskWord((short)0); s7Data.setStartSlot((short)0); s7Data.setEndSlot((short)0); s7Serializer.write(s7Data); // List<ReadWriteEntity> list = new ArrayList<>(); // list.add(generateReadWriteEntity("CC.CC.taskWord", 0)); // list.add(generateReadWriteEntity("CC.CC.startSlot", 0)); // list.add(generateReadWriteEntity("CC.CC.endSlot", 0)); // miloService.writeToOpcWord(list); } return; } @@ -127,8 +151,9 @@ @Scheduled(fixedDelay = 1000) public void rawStorageInCar() throws Exception { ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.inCar"); String value = entity.getValue() + ""; String value = S7Job.S7DataWL1.getInCar().toString(); // ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.inCar"); // String value = entity.getValue() + ""; if (!"1".equals(value)) { log.info("大车上没有架子"); return; @@ -146,8 +171,9 @@ @Scheduled(fixedDelay = 1000) public void rawStorageFinish() throws Exception { ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.reportWord"); String value = entity.getValue() + ""; String value = S7Job.S7DataWL1.getReportWord().toString(); // ReadWriteEntity entity = miloService.readFromOpcUa("CC.CC.reportWord"); // String value = entity.getValue() + ""; if ("0".equals(value)) { log.info("当前任务未汇报,结束本次任务"); return; @@ -210,9 +236,12 @@ .set(RawGlassStorageTask::getTaskState, Const.RAW_GLASS_TASK_FAILURE)); } List<ReadWriteEntity> list = new ArrayList<>(); list.add(generateReadWriteEntity("CC.CC.confirmation", 1)); miloService.writeToOpcWord(list); 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() { @@ -405,6 +434,10 @@ if (CollectionUtils.isEmpty(loadStationList)) { log.info("1号上片位生成调度任务"); RawGlassStorageDetails rawDetails = getRawGlassStorageDetailsBySize(usageVOS.get(0), usageVOS.size()); if(CollectionUtils.isEmpty(loadStationList)){ 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>() @@ -546,6 +579,7 @@ .eq(RawGlassStorageDetails::getPatternWidth, usageVO.getWidth()) .eq(RawGlassStorageDetails::getPatternHeight, usageVO.getHeight()) .eq(RawGlassStorageDetails::getPatternThickness, usageVO.getThickness()) .notIn(RawGlassStorageDetails::getSlot, LOAD_STATION_ALL) .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN) .orderByAsc(RawGlassStorageDetails::getRemainQuantity) .last("order by abs(t.remain_quantity - " + remainQuantity + ") asc") hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application-dev.yml
@@ -5,7 +5,7 @@ strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候回抛出异常,不启动会使用默认数据源. datasource: northGlassMes: url: jdbc:mysql://127.0.0.1:3306/north_glass_mes?serverTimezone=GMT%2b8 url: jdbc:mysql://127.0.0.1:3306/north_glass_mes?serverTimezone=GMT%2b8&allowMultiQueries=true username: root password: beibo.123/ driver-class-name: com.mysql.cj.jdbc.Driver hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/application-dev.yml
@@ -10,7 +10,7 @@ password: beibo.123/ driver-class-name: com.mysql.cj.jdbc.Driver salve_northGlassMes: url: jdbc:sqlserver://10.153.19.150:1433;databasename=north_glass_mes url: jdbc:sqlserver://127.0.0.1:1433;databasename=north_glass_mes username: sa password: beibo.123/ driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver hangzhoumesParent/moduleService/hollowGlassModule/src/main/java/com/mes/hollowtask/mapper/HollowBigStorageCageHistoryTaskMapper.java
@@ -3,7 +3,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mes.hollowtask.entity.HollowBigStorageCageHistoryTask; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import org.apache.ibatis.annotations.Param; import java.util.List; /** * (HollowBigStorageCageHistoryTask)表数据库访问层 @@ -14,5 +17,7 @@ public interface HollowBigStorageCageHistoryTaskMapper extends BaseMapper<HollowBigStorageCageHistoryTask> { DailyProductionVO queryHollowDailyProduction(@Param("beginDate") String beginDate, @Param("endDate") String endDate); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/hollowGlassModule/src/main/java/com/mes/hollowtask/service/HollowBigStorageCageHistoryTaskService.java
@@ -5,6 +5,9 @@ import com.mes.hollowtask.entity.HollowBigStorageCageHistoryTask; import com.mes.hollowtask.entity.request.HollowBigStorageCageHistoryRequest; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import java.util.List; /** * (HollowBigStorageCageHistoryTask)表服务接口 @@ -17,5 +20,7 @@ Page<HollowBigStorageCageHistoryTask> queryHollowBigStorageCageHistoryTask(HollowBigStorageCageHistoryRequest request); DailyProductionVO queryHollowDailyProduction(HollowBigStorageCageHistoryRequest request); List<RunTime> queryRunTimes(); } hangzhoumesParent/moduleService/hollowGlassModule/src/main/java/com/mes/hollowtask/service/impl/HollowBigStorageCageHistoryTaskServiceImpl.java
@@ -10,10 +10,12 @@ import com.mes.hollowtask.mapper.HollowBigStorageCageHistoryTaskMapper; import com.mes.hollowtask.service.HollowBigStorageCageHistoryTaskService; import com.mes.largenscreen.entity.DailyProductionVO; import com.mes.largenscreen.entity.RunTime; import com.mes.tools.DateUtil; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.List; /** * (HollowBigStorageCageHistoryTask)表服务实现类 @@ -53,5 +55,10 @@ } return baseMapper.queryHollowDailyProduction(beginDate, endDate); } @Override public List<RunTime> queryRunTimes(){ return baseMapper.queryRunTimes(); } } hangzhoumesParent/moduleService/hollowGlassModule/src/main/java/com/mes/job/PushMessageToIndex.java
@@ -19,7 +19,9 @@ import com.mes.hollow.service.HollowGlassRelationInfoService; import com.mes.hollowqueue.entity.HollowGlassQueueInfo; import com.mes.hollowqueue.service.HollowGlassQueueInfoService; import com.mes.hollowtask.service.HollowBigStorageCageHistoryTaskService; import com.mes.largenscreen.entity.PieChartVO; import com.mes.largenscreen.entity.RunTime; import com.mes.tools.WebSocketServer; import com.mes.utils.RedisUtil; import lombok.extern.slf4j.Slf4j; @@ -54,6 +56,8 @@ BigStorageCageTaskService bigStorageCageTaskService; @Resource HollowGlassRelationInfoService hollowGlassRelationInfoService; @Resource HollowBigStorageCageHistoryTaskService hollowBigStorageCageHistoryTaskService; @Autowired(required = false) MiloService miloService; @@ -230,6 +234,8 @@ //钢化饼图数据 List<PieChartVO> pieChartVOS = hollowGlassOutRelationInfoService.queryPieChart(); jsonObject.append("pieChartVOS", pieChartVOS); List<RunTime> hollowRunTimes = hollowBigStorageCageHistoryTaskService.queryRunTimes(); jsonObject.append("hollowRunTimes", hollowRunTimes); ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("largenScreen"); if (sendwServer != null) { for (WebSocketServer webserver : sendwServer) { hangzhoumesParent/moduleService/hollowGlassModule/src/main/resources/mapper/HollowBigStorageCageHistoryTaskMapper.xml
@@ -47,4 +47,28 @@ from hollow_out_one_temp inner join hollow_out_two_temp on 1 = 1 </select> <select id="queryRunTimes" resultType="com.mes.largenscreen.entity.RunTime"> with big_storage_cage_history_task_temp as ( select distinct create_time from hollow_big_storage_cage_history_task where task_type = 5 and create_time BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 DAY) ) SELECT t1.create_time AS first_timestamp, t2.create_time AS second_timestamp, TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) as diff_minutes FROM (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM big_storage_cage_history_task_temp ) t1 JOIN (SELECT create_time, LEAD(create_time) OVER (ORDER BY create_time) AS next_timestamp FROM big_storage_cage_history_task_temp ) t2 ON t1.next_timestamp = t2.create_time WHERE TIMESTAMPDIFF(MINUTE, t1.create_time, t2.create_time) between 11 and 500; </select> </mapper>