import {useRouter} from "next/router"; import React, {useEffect, useMemo, useRef, useState} from "react"; import {Carousel} from 'antd' import _ from "lodash"; import Footer from "../../../components/screen/Footer"; import Header from "../../../components/screen/Header"; import Chart from "../../../components/screen/Chart"; import Row from "../../../components/screen/Row"; import Card from '../../../components/screen/Card'; import ProcessTaskCard from "../../components/processTaskCard"; import {useSocket} from "../../../utils/hooks"; import moment from "moment/moment"; /** * 生产分工序 */ const socketScreenType = 'BranchOperationType'; const gutter = 20; const bottom = 0; const chartsBgColor = '#102242'; //关键生产信息 const getProdOpt = ({xData, yData}) => { let opt = { xAxis: { type: 'category', data: [] }, title: { text: "L7车间生产进度", textStyle: { fontSize: "14px" }, top: 10, left: 60 }, yAxis: { type: 'value' }, grid: { top: 40, left: 55 }, series: [ { data: [], type: 'bar' } ] }; opt.xAxis.data = xData opt.series[0].data = yData return opt; }; //车间OEE const getOEEOpt = (data = {}, params = []) => { const {oeeOfMonth = {}, oeeOfDay = {}} = data; // passRate 良品率, performanceRate 性能稼动率, timeRate 时间稼动率, oee OEE if (params.length > 0) { params[0].values = [oeeOfDay.timeRate || 0, oeeOfDay.performanceRate || 0, oeeOfDay.passRate || 0] //当日 params[0].result = [oeeOfDay.oee || 0] params[1].values = [oeeOfMonth.timeRate || 0, oeeOfMonth.performanceRate || 0, oeeOfMonth.passRate || 0] //当日 params[1].result = [oeeOfMonth.oee || 0] } let opt = { title: { text: "", left: "center", top: 180, }, graphic: { elements: [ { type: "text", left: "center", top: 85, style: { fill: "#fff", text: "", fontSize: 16, fontWeight: "bold", }, }, ], }, legend: { // icon: "rect", data: ["时间稼动率", "性能稼动率", "良品率"], bottom: 10, orient: "vertical", itemHeight: 16, textStyle: { fontSize: 14, lineHeight: 14, }, }, polar: { radius: ["25%", "65%"], center: ["50%", "30%"], }, angleAxis: { show: false, max: 100, startAngle: 90, }, radiusAxis: { show: false, type: "category", data: ["%"], }, tooltip: { formatter: "{a}", }, series: [ { name: "时间稼动率", type: "bar", barGap: "0", barWidth: 14, data: [12], coordinateSystem: "polar", }, { name: "性能稼动率", type: "bar", barGap: "0", barWidth: 14, data: [13], coordinateSystem: "polar", }, { name: "良品率", type: "bar", barGap: "0", barWidth: 14, data: [14], coordinateSystem: "polar", }, ], }; let res = []; params.forEach(({name, values, result}) => { let newOpt = _.cloneDeep(opt); newOpt.title.text = name; newOpt.graphic.elements[0].style.text = result + "%"; const names = ["时间稼动率 ", "性能稼动率 ", "良品率 "]; newOpt.legend.data = names.map( (name, index) => (name = name + ` ${values[index]}%`) ); newOpt.series = newOpt.series.map((item, index) => { item.name = names[index] + ` ${values[index]}%`; item.data[0] = values[index]; return item; }); res.push(newOpt); }); return res; }; //能耗信息 const getUsedOpt = (data = {}, params = []) => { const { energyOfMonth = 0, //电(KW/H) 今日用量 energyOfDay = 0, // 当月累计用量 gasOfMonth = 0, //气 (m3) gasOfDay = 0, waterOfDay = 0, //水(T) waterOfMonth = 0, } = data; if (params.length > 0) { params[0].values[0].value = gasOfMonth; params[0].values[1].value = gasOfDay; params[1].values[0].value = waterOfMonth; params[1].values[1].value = waterOfDay; params[2].values[0].value = energyOfMonth; params[2].values[1].value = energyOfDay; } let opt = { title: { text: "", left: "center", top: 70, textStyle: { fontWeight: "normal", fontSize: "16px" }, }, tooltip: { trigger: "item", }, legend: { bottom: 15, left: "center", orient: "vertical", textStyle: { fontSize: 14, lineHeight: 14 }, }, series: [ { type: "pie", radius: ["45%", "70%"], center: ["50%", "40%"], avoidLabelOverlap: false, label: { show: false, position: "center", }, labelLine: { show: false, }, data: [], }, ], }; let res = []; let colors = ["#6FE621", "#FF005A", "#4D7BF3", "#4FCCFF"] params.forEach(({name, unit, values}, index) => { let newOpt = _.cloneDeep(opt); newOpt.color = [colors[index], "#FFC760"]; newOpt.title.text = `${name}\n(${unit})`; newOpt.series[0].data = values; newOpt.legend.formatter = name => { let {value = ""} = values.find(item => item.name === name) || {}; return `${name}: ${value}` } res.push(newOpt); }); return res; }; //设备监控参数 const getEquipMonitorOpt = (data = []) => { let option = { type: "equip", backgroundColor: chartsBgColor, grid: { top: 25, left: 60, right: "5%" }, title: { text: "", x: "center", y: "top", textStyle: { fontSize: "14px" } }, xAxis: { type: "category", data: [], }, yAxis: { type: "value", min: 0, }, series: [ { symbol: "circle", symbolSize: 5, data: [], type: "line", }, ], }; let newOpt = [] if (data.length > 0) { data.forEach((item, index) => { let opt = _.cloneDeep(option); opt.title.text = item.name; opt.xAxis.data = item.time.slice().reverse(); opt.series[0].data = item.data.slice().reverse(); newOpt.push(opt) }) } return newOpt; } //质量监控参数 const getQualityMonitorOpt = (data = {}) => { let res = []; let option = { type: "quality", backgroundColor: chartsBgColor, title: { show: false, /* text: '', x: 'right', textStyle: { color: '#ffffff', fontSize: "14px" }*/ }, tooltip: { trigger: 'axis' }, markLine: {}, legend: { x: 'left', y: 'bottom', // data: ['极差值', 'UCLmr', 'LCLmr', 'CLmr'], textStyle: { //文字 样式 color: '#ffffff', fontSize: "12px" }, itemStyle: { //圆点样式 opacity: 0 }, lineStyle: { //线样式 // type: [4, 4], dashOffset: 4 } }, grid: { top: 15, left: '3%', right: '3%', bottom: '15%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, data: [], axisLine: { show: true, lineStyle: { type: 'solid', color: '#ffffff' } } }, yAxis: { type: 'value', splitNumber: 8, //轴线 axisLine: { show: true, lineStyle: { type: 'solid', color: '#ffffff' } }, splitLine: { lineStyle: { color: '#ffffff' } } }, series: [] }; if (data.spcBasicDatas && data.topData) { let {spcBasicDatas = [], topData = {}} = data; let { usl = 0, lsl = 0, uclx = 0, averx = 0, lclx = 0, uclr = 0, averr = 0, lclr = 0, } = topData let xData = [], yValData = [], yMrValData = []; spcBasicDatas.forEach(item => { if (!item.seq) item.seq = 0 if (!item.value) item.value = 0 if (!item.mrValue) item.mrValue = 0 xData.push(item.seq) yValData.push(item.value) yMrValData.push(item.mrValue) }) //标准点数据处理 let basicOpt = _.cloneDeep(option); const basicName = ['数据点', 'USLi', 'UCli', 'CLi', 'LCLi', 'LSLi']; basicOpt.xAxis.data = xData let min = _.min(yValData) basicOpt.yAxis.min = min; basicName.forEach((item, index) => { basicOpt.series[index] = { type: 'line', smooth: true, //平滑 symbolSize: 4, symbol: 'circle', data: [], lineStyle: { type: 'dashed', //'dotted'点线 'dashed' 虚线 'solid' 实线 width: 1 }, markLine: { symbol: 'none', label: { show: false }, lineStyle: {}, data: [{ yAxis: 0, x: '6.8%' }] } } basicOpt.series[index].name = basicName[index] }) basicOpt.series[0].data = yValData; basicOpt.series[0].lineStyle.type = "solid"; basicOpt.series[1].markLine.data[0].yAxis = usl basicOpt.series[2].markLine.data[0].yAxis = lsl basicOpt.series[3].markLine.data[0].yAxis = uclx basicOpt.series[4].markLine.data[0].yAxis = averx basicOpt.series[5].markLine.data[0].yAxis = lclx //极差点数据处理 let mrOpt = _.cloneDeep(option); const mrName = ['极差点', 'UCLmr', 'CLmr', 'LCLmr']; mrOpt.xAxis.data = xData mrName.forEach((item, index) => { mrOpt.series[index] = { type: 'line', smooth: true, //平滑 symbolSize: 4, data: [], lineStyle: { type: 'dashed', //'dashed'点线 'dashed' 虚线 'solid' 实线 width: 1 }, markLine: { symbol: 'none', label: { show: false }, data: [{ yAxis: 0, x: '6.8%' }] } } mrOpt.series[index].name = mrName[index] }) mrOpt.series[0].data = yMrValData; mrOpt.series[0].lineStyle.type = "solid"; mrOpt.series[1].markLine.data[0].yAxis = uclr mrOpt.series[2].markLine.data[0].yAxis = averr mrOpt.series[3].markLine.data[0].yAxis = lclr res = _.concat([], [basicOpt], [mrOpt]) } return res; } const ProcessItem = () => { const tableTimeoutRef = useRef(); const equipMonitorRef = useRef(); const router = useRouter(); const [isClear, setClear] = useState(false) const [length, setLength] = useState(4) //卡片轮播个数 const [len, setLen] = useState(2) //监控轮播个数 const [height, setHeight] = useState(0); const [width, setWidth] = useState(0); const [monitorTitle, setMonitorTitle] = useState("设备") const [isQuality, setIsQuality] = useState(false) const {operationCode, workCenterCode, date = moment().format('YYYY-MM-DD')} = router.query; const { processItem: { reloadTime, cardAutoNext, pages = {}, energyParams = [], OEEParams = [] } = {} } = global.config || {}; //监控类型名,质量、设备 let title = ""; if (operationCode && pages[operationCode]) { title = pages[operationCode].title; } const [ { keyEnergy = {}, //关键能耗 keyProduction = {}, //关键生产 taskExecution = [], //任务执行状态 oee = {}, //车间OEE paramMonitor = {} //监控 } = {}, reload, ] = useSocket({socketScreenType, operationCode, workCenterCode, date}); const {iotEquipResultData = [], spcResultData = {}} = paramMonitor; //监控 const {topData = {}} = spcResultData; //质量监控检测项 let featureName = ""; if (topData.featureName) { featureName = topData.featureName } //工序任务执行状态 const taskExecutData = useMemo(() => { let res = []; taskExecution.forEach((item, index) => { let row = Math.ceil((index + 1) / length); let rowIndex = index % length; if (!res[row]) res[row] = []; res[row][rowIndex] = item; }) res = res.filter(item => item); return res; }, [taskExecution]); //设备、质量参数监控 const monitorOpt = useMemo(() => { let equipData = getEquipMonitorOpt(iotEquipResultData); let qualityData = getQualityMonitorOpt(spcResultData); let res = [], equipRes = [], qualityRes = []; //设备参数分组 equipData.forEach((item, index) => { let row = Math.ceil((index + 1) / len); let rowIndex = index % len; if (!equipRes[row]) equipRes[row] = []; equipRes[row][rowIndex] = item; }) //质量参数分组 qualityData.forEach((item, index) => { let row = Math.ceil((index + 1) / len); let rowIndex = index % len; if (!qualityRes[row]) qualityRes[row] = []; qualityRes[row][rowIndex] = item; }) res = _.concat([], equipRes, qualityRes) res = res.filter(item => item); return res }, [iotEquipResultData, spcResultData]) //关键生产信息 const prodOpt = useMemo(() => { return getProdOpt(keyProduction) }, [keyProduction]) //车间能耗信息 const usedOpt = useMemo(() => { return getUsedOpt(keyEnergy, energyParams); }, [keyEnergy]) //车间OEE const OEEOpt = useMemo(() => { return getOEEOpt(oee, OEEParams); }, [oee]); useEffect(() => { if (operationCode) { setClear(true); } }, [operationCode]); useEffect(() => { setTimeout(() => { //轮播图标的宽高设置 if (equipMonitorRef.current) { setHeight(equipMonitorRef.current.clientHeight) setWidth(equipMonitorRef.current.clientWidth) } }, 100) }, []) //整体刷新 useEffect(() => { tableTimeoutRef.current = setInterval(() => { reload() }, reloadTime); return () => { clearInterval(tableTimeoutRef.current) } }, [reload]) useEffect(() => { if (iotEquipResultData.length <= 0 && _.get(spcResultData, "spcBasicDatas.length") > 0) { setMonitorTitle('质量') setIsQuality(true) } }, [iotEquipResultData, spcResultData]) //当前轮播位置,更新标题 const afterChange = (current) => { let index = _.findIndex(monitorOpt, item => item[0].type == 'quality'); if (index == current) { setMonitorTitle('质量') setIsQuality(true) } else { setMonitorTitle('设备') setIsQuality(false) } } return (
{isClear && (
{taskExecutData.map((row, rowIndex) => { return
{row.map((item, index) => { return
})}
})}
{ isQuality &&
{`最新检测项:${featureName}`}
}
{monitorOpt.map((row, rowIndex) => { return
{row.map((item, index) => { return
})}
})}
{usedOpt.map((opt, index) => { return ( ); })} {OEEOpt.map((opt, index) => { return ( ); })}
); }; export default ProcessItem;