810 lines
27 KiB
JavaScript
810 lines
27 KiB
JavaScript
|
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 (
|
|||
|
<div className="screen-container">
|
|||
|
{isClear && (
|
|||
|
<React.Fragment>
|
|||
|
<Header title={`${title}工序`}/>
|
|||
|
<div className="screen-container-content">
|
|||
|
<Row className='height-100' gutter={gutter} bottom={bottom}>
|
|||
|
<Row.Col span={5}>
|
|||
|
<Row className="height-55">
|
|||
|
<Card title={`${title}工序设备示意图`} overVisible={true}
|
|||
|
padding={"40px 20px 25px 20px"}>
|
|||
|
<div className='screen-img img-gxsb'/>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
|
|||
|
<Row className="height-45" style={{paddingTop: `${gutter}px`}}>
|
|||
|
<Card title={`${title}工序成品示意图`} overVisible={true}
|
|||
|
padding={"40px 20px 25px 20px"}>
|
|||
|
<div className='screen-img img-gxzzp'/>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
</Row.Col>
|
|||
|
|
|||
|
<Row.Col span={12}>
|
|||
|
<Row className="height-55">
|
|||
|
<Card title="工序任务执行状态" overVisible={true} padding={"40px 20px 25px 20px"}>
|
|||
|
<div className='process-task-list'>
|
|||
|
<Carousel autoplay dots={false} autoplaySpeed={cardAutoNext}>
|
|||
|
{taskExecutData.map((row, rowIndex) => {
|
|||
|
return <div key={Math.random()}>
|
|||
|
<div className='process-task'>
|
|||
|
{row.map((item, index) => {
|
|||
|
return <div className='process-task-item'
|
|||
|
key={item.code}>
|
|||
|
<ProcessTaskCard itemData={item}
|
|||
|
operationCode={operationCode}/>
|
|||
|
</div>
|
|||
|
})}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
})}
|
|||
|
</Carousel>
|
|||
|
</div>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
|
|||
|
<Row className="height-45" style={{paddingTop: `${gutter}px`}}>
|
|||
|
<Card title={`${monitorTitle}参数监控`} overVisible={true}
|
|||
|
padding={"35px 16px 16px 16px"}>
|
|||
|
{
|
|||
|
isQuality &&
|
|||
|
<div className='monitor-quality-item'>
|
|||
|
{`最新检测项:${featureName}`}
|
|||
|
</div>
|
|||
|
}
|
|||
|
<div className='equip-monitor-list' ref={equipMonitorRef}>
|
|||
|
<Row className='height-100'>
|
|||
|
<Carousel autoplay dots={false} dotPosition={"right"}
|
|||
|
autoplaySpeed={cardAutoNext} adaptiveHeight={true}
|
|||
|
afterChange={afterChange}>
|
|||
|
{monitorOpt.map((row, rowIndex) => {
|
|||
|
return <div>
|
|||
|
<div key={Math.random()}
|
|||
|
style={{height: height, width: width}}>
|
|||
|
{row.map((item, index) => {
|
|||
|
return <div className='equip-monitor-item'
|
|||
|
key={rowIndex + index}>
|
|||
|
<Chart option={item}/>
|
|||
|
</div>
|
|||
|
})}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
})}
|
|||
|
</Carousel>
|
|||
|
</Row>
|
|||
|
</div>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
</Row.Col>
|
|||
|
|
|||
|
<Row.Col span={7}>
|
|||
|
<Card>
|
|||
|
<div className="used-content">
|
|||
|
<Row className="height-30">
|
|||
|
<Card title="关键生产信息" titleSpace={true} overVisible={true}
|
|||
|
withBorder={false}>
|
|||
|
<Chart option={prodOpt}/>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
|
|||
|
<Row className="height-30">
|
|||
|
<Card title="关键能耗信息" titleSpace={true} overVisible={true}
|
|||
|
withBorder={false} padding={"0 16px"}>
|
|||
|
<Row className='height-100'>
|
|||
|
{usedOpt.map((opt, index) => {
|
|||
|
return (
|
|||
|
<Row.Col span={8} key={index}>
|
|||
|
<Chart option={opt}/>
|
|||
|
</Row.Col>
|
|||
|
);
|
|||
|
})}
|
|||
|
</Row>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
|
|||
|
<Row className="height-40">
|
|||
|
<Card title="车间OEE" titleSpace={true} overVisible={true}
|
|||
|
withBorder={false} padding={"0 16px"}>
|
|||
|
<Row className='height-100'>
|
|||
|
{OEEOpt.map((opt, index) => {
|
|||
|
return (
|
|||
|
<Row.Col span={12} key={index}>
|
|||
|
<Chart option={opt}/>
|
|||
|
</Row.Col>
|
|||
|
);
|
|||
|
})}
|
|||
|
</Row>
|
|||
|
</Card>
|
|||
|
</Row>
|
|||
|
</div>
|
|||
|
</Card>
|
|||
|
</Row.Col>
|
|||
|
</Row>
|
|||
|
</div>
|
|||
|
|
|||
|
<Footer/>
|
|||
|
</React.Fragment>
|
|||
|
)
|
|||
|
}
|
|||
|
<style jsx>{`
|
|||
|
.screen-container {
|
|||
|
font-family: PingFangSC-Semibold;
|
|||
|
height: 100vh;
|
|||
|
min-height: 1080px;
|
|||
|
min-width: 1920px;
|
|||
|
background: url("/img/bg.png") center center;
|
|||
|
position: relative;
|
|||
|
padding-top: 96px;
|
|||
|
padding-bottom: 82px;
|
|||
|
overflow: hidden;
|
|||
|
}
|
|||
|
|
|||
|
.screen-container-content {
|
|||
|
height: 100%;
|
|||
|
padding: ${gutter}px;
|
|||
|
}
|
|||
|
|
|||
|
.OEE-content {
|
|||
|
position: absolute;
|
|||
|
width: 900px;
|
|||
|
height: 320px;
|
|||
|
top: 660px;
|
|||
|
left: 460px;
|
|||
|
}
|
|||
|
|
|||
|
.monitor-quality-item {
|
|||
|
text-align: right;
|
|||
|
margin-top: -22px;
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
|
|||
|
.equip-monitor-list {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
overflow: hidden;
|
|||
|
}
|
|||
|
|
|||
|
.equip-monitor-item {
|
|||
|
width: 100%;
|
|||
|
height: 50%;;
|
|||
|
padding: 4px 0;
|
|||
|
}
|
|||
|
|
|||
|
.process-task-list {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
overflow: hidden;
|
|||
|
}
|
|||
|
|
|||
|
.process-task {
|
|||
|
display: flex;
|
|||
|
justify-content: space-around;
|
|||
|
}
|
|||
|
|
|||
|
.process-task-item {
|
|||
|
width: calc(100% / 4);
|
|||
|
padding: 0 16px;
|
|||
|
}
|
|||
|
|
|||
|
.used-content {
|
|||
|
overflow: hidden;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
.used-content :global(.screen-card) {
|
|||
|
border: none !important;
|
|||
|
}
|
|||
|
|
|||
|
.aaa {
|
|||
|
width: 50%;
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
}
|
|||
|
|
|||
|
.screen-img {
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
.img-gxsb {
|
|||
|
background: url(/img/process/${operationCode}-SB.png) center center no-repeat;
|
|||
|
}
|
|||
|
|
|||
|
.img-gxzzp {
|
|||
|
background: url(/img/process/${operationCode}-ZZP.png) center center no-repeat;
|
|||
|
}
|
|||
|
|
|||
|
`}</style>
|
|||
|
</div>
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
export default ProcessItem;
|