You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

721 lines
18 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="app-container">
<div class="headTitle">注塑车间设备运行监控平台</div>
<div class="subTitle" style="top: 20%;left: 88%;">设备OEE</div>
<div class="subTitle" style="top: 60%;left: 88%;">设备能耗</div>
<div class="top" style="top: 8%;left: 4%"></div>
<div class="top" style="top: 8%;left: 20%"></div>
<div class="top" style="top: 8%;left: 36%"></div>
<div class="top" style="top: 8%;left: 52%"></div>
<div class="top" style="top: 8%;left: 68%"></div>
<div class="top" style="top: 8%;left: 84%"></div>
<div class="topNum deviceNum">
<span class="text">设备数量</span>
<span></span>
<span class="num">{{ runningData.TOTALCOUNT }}</span>
<span class="unit"></span>
</div>
<div class="topNum bootRate">
<span class="text" style="width: 5vw;letter-spacing: 0.4vw">开机率</span>
<span></span>
<!-- <span class="num">{{ runningData.runningRate }}</span>-->
<span class="num">{{
((((Math.min((runningData.RUNNINGCOUNT || 0) + runNum, runningData.TOTALCOUNT) || 0) / runningData.TOTALCOUNT) || 0) * 100) < 100 ? (((((Math.min((runningData.RUNNINGCOUNT || 0) + runNum, runningData.TOTALCOUNT) || 0) / runningData.TOTALCOUNT) || 0) * 100).toFixed(2)) : '100'
}}%</span>
</div>
<div class="topNum runNum">
<span class="text">运行</span>
<span></span>
<span class="num">{{ Math.min((runningData.RUNNINGCOUNT || 0) + runNum, runningData.TOTALCOUNT) || 0 }}</span>
<span class="unit"></span>
</div>
<div class="topNum shutdownNum">
<!-- <span class="text">停机</span>-->
<span class="text">暂停</span>
<span></span>
<span class="num">{{ runningData.STOPPEDCOUNT }}</span>
<span class="unit"></span>
</div>
<div class="topNum standbyNum">
<span class="text">报警</span>
<span></span>
<span class="num">{{ runningData.STANDBYCOUNT }}</span>
<span class="unit"></span>
</div>
<!-- <div class="topNum waitMaterials">-->
<!-- <span class="text">待料</span>-->
<!-- <span></span>-->
<!-- <span class="num">00</span>-->
<!-- <span class="unit"></span>-->
<!-- </div>-->
<div class="topNum unactivatedNum">
<span class="text">未开机</span>
<span></span>
<span class="num">{{ Math.max((runningData.NOTSTARTEDCOUNT || 0) - runNum, 0) }}</span>
<span class="unit"></span>
</div>
<div class="centerContent">
<div class="item" v-for="i in form.table1">
<div class="itemTitle">{{ i.DEVICENAME }}</div>
<div class="itemImg"></div>
<div class="itemType itemType0" v-if="i.STATUSCODE===2">停机</div>
<div class="itemType itemType1" v-if="i.STATUSCODE===3">待机</div>
<div class="itemType itemType2" v-if="i.STATUSCODE===1">正常运行</div>
<div class="itemType itemType3" v-if="i.STATUSCODE===0">未开机</div>
<div class="itemTime itemTime0" v-if="i.STATUSCODE===2">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
parseFloat(i.value1 || '0').toFixed(1)
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime1" v-if="i.STATUSCODE===3">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
parseFloat(i.value1 || '0').toFixed(1)
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime2" v-if="i.STATUSCODE===1">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
parseFloat(i.value1 || '0').toFixed(1)
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime3" v-if="i.STATUSCODE===0">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
parseFloat(i.value1 || '0').toFixed(1)
}}</span>
<span>h</span>
</div>
<div class="itemText">待机时长</div>
</div>
<div class="item" v-for="i in deviceData">
<div class="itemTitle">{{ i.DEVICENAME }}</div>
<div class="itemImg"></div>
<div class="itemType itemType0" v-if="i.STATUSCODE===2">停机</div>
<div class="itemType itemType1" v-if="i.STATUSCODE===3">待机</div>
<div class="itemType itemType2" v-if="i.STATUSCODE===1">正常运行</div>
<div class="itemType itemType3" v-if="i.STATUSCODE===0">未开机</div>
<div class="itemTime itemTime0" v-if="i.STATUSCODE===2">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
timeData[i.DEVICECODE] || '0'
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime1" v-if="i.STATUSCODE===3">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
timeData[i.DEVICECODE] || '0'
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime2" v-if="i.STATUSCODE===1">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
timeData[i.DEVICECODE] || '0'
}}</span>
<span>h</span>
</div>
<div class="itemTime itemTime3" v-if="i.STATUSCODE===0">
<span style="font-size: 1.5vw;margin-right: 0.2vw;;font-weight: 700">{{
timeData[i.DEVICECODE] || '0'
}}</span>
<span>h</span>
</div>
<div class="itemText">待机时长</div>
</div>
</div>
<div class="oee">
<Chart ref="chart1"></Chart>
</div>
<div class="energy">
<Chart ref="chart2"></Chart>
</div>
<div class="config">
<el-button class="btn" @click="configDialogVisible = true">配置</el-button>
</div>
<div v-if="isData">
<el-dialog
title="提示"
:visible.sync="configDialogVisible"
width="70%">
<el-form :inline="true" :model="form" label-width="120px">
<el-form-item label="是否使用模拟数据">
<el-switch
v-model="form.isSimulate"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
</el-form-item>
<el-form-item label="质量追溯" class="fullLine" style="width: 100%">
<el-table
:data="form.table1"
style="width: 100%">
<el-table-column
prop="date"
label="名称"
>
<template slot-scope="scope">
<el-input v-model="form.table1[scope.$index].DEVICENAME"
autocomplete="off"></el-input>
</template>
</el-table-column>
<el-table-column
prop="date"
label="时间"
>
<template slot-scope="scope">
<el-input v-model="form.table1[scope.$index].value1"
autocomplete="off"></el-input>
</template>
</el-table-column>
<el-table-column
prop="date"
label="状态"
>
<template slot-scope="scope">
<el-select v-model="form.table1[scope.$index].STATUSCODE" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
</el-table-column>
</el-table>
<div>
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="configDialogVisible = false">预 览</el-button>
<el-button type="primary" @click="save">保 存</el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import Chart from "@/components/board/Chart.vue";
import * as echarts from "echarts";
import {getDeviceStartTimeList, getDeviceStatusList, getDeviceStatusStatistics} from "@/api/baseDeviceParamVal/val";
import {getSimulateData} from "@/api/board/getData";
import {updateCustomData} from "@/api/base/customData";
import {Message} from "element-ui";
let timer = null
const vw = (document.documentElement.clientWidth || document.body.clientWidth) / 100
export default {
components: {
Chart
},
name: "Liner",
data() {
return {
options: [
{
value: 0,
label: '未开机'
},
{
value: 1,
label: '正常运行'
},
{
value: 2,
label: '停机'
},
{
value: 3,
label: '待机'
},
],
isData: false,
configDialogVisible: false,
form: {},
runningData: {},
deviceData: [],
timeData: {},
runNum: 0,
}
},
async mounted() {
await this.getData()
this.$refs.chart1.setData({
title: [
{
text: "75%",
x: "center",
y: "center",
textStyle: {
fontSize: 2 * vw,
color: "#FFFFFF",
fontFamily: "DINAlternate-Bold, DINAlternate",
foontWeight: "600",
},
},
],
polar: {
radius: ["58%", "68%"],
center: ["50%", "50%"],
},
angleAxis: {
max: 133,
// startAngle: 225,
// endAngle: -180,
clockwise: true,
show: false
},
radiusAxis: {
type: "category",
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
name: "",
type: "bar",
roundCap: false,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: "rgba(66, 66, 66, .3)",
},
data: [100],
coordinateSystem: "polar",
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: "#16CEB9",
},
{
offset: 1,
color: "#6648FF",
},
]),
},
},
},
],
})
this.$refs.chart2.setData({
title: [
{
text: "75%",
x: "center",
y: "center",
textStyle: {
fontSize: 2 * vw,
color: "#FFFFFF",
fontFamily: "DINAlternate-Bold, DINAlternate",
fontWeight: "600",
},
},
],
polar: {
radius: ["58%", "68%"],
center: ["50%", "50%"],
},
angleAxis: {
max: 133,
// startAngle: 225,
// endAngle: -180,
clockwise: true,
show: false
},
radiusAxis: {
type: "category",
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
name: "",
type: "bar",
roundCap: false,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: "rgba(66, 66, 66, .3)",
},
data: [100],
coordinateSystem: "polar",
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: "#16CEB9",
},
{
offset: 1,
color: "#6648FF",
},
]),
},
},
},
],
})
timer = setInterval(() => {
this.getData()
}, 1000 * 60 * 3)
},
methods: {
async getData() {
await getDeviceStatusStatistics().then(e => {
this.runningData = e.data
})
await getDeviceStatusList().then(res => {
this.deviceData = res.data.filter(e => !(e.DEVICENAME === "5#" || e.DEVICENAME === "10#" || e.DEVICENAME === "12#" || e.DEVICENAME === "17#" || e.DEVICENAME === "18#"))
})
getDeviceStartTimeList().then(res => {
res.data.forEach(e => {
this.timeData[e.DEVICECODE] = ((e.STARTTIME / 60 / 60) || 0).toFixed(1)
})
})
getSimulateData({customCode: 'board-3' || '', customType: 1}).then(val => {
this.row = val.rows[0]
this.form = JSON.parse(val.rows[0].customData);
this.isData = true
this.runNum = this.form.table1.filter(v => v.STATUSCODE == 1).length
})
},
save() {
updateCustomData({
...this.row,
customData: JSON.stringify(this.form)
}).then(res => {
Message({message: '保存成功', type: 'success'})
this.configDialogVisible = false
this.runNum = this.form.table1.filter(v => v.STATUSCODE == 1).length
})
}
},
beforeDestroy() {
if (timer) {
clearInterval(timer)
}
timer = null
}
};
</script>
<style scoped lang="less">
.app-container {
background-image: url("../../../assets/board/boardBg1.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.top {
position: absolute;
width: 12vw;
height: 3.3vw;
background-image: url("../../../assets/board/board-top.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.subTitle {
position: absolute;
transform: translate(-50%, -50%);
font-size: 1.2vw;
color: #d6eaed;
letter-spacing: 0.1vw;
}
.headTitle {
position: absolute;
top: 5%;
left: 50%;
transform: translate(-50%, -100%);
font-size: 1.5vw;
color: #d6eaed;
letter-spacing: 0.3vw;
}
.topNum {
position: absolute;
top: calc(8% + 1.65vw);
transform: translateY(-50%);
font-size: 1.3vw;
vertical-align: middle;
.text {
color: #51A1D0;
display: inline-block;
width: 6vw;
white-space: nowrap;
}
.num {
letter-spacing: 0.2vw;
}
}
.deviceNum {
left: 4.5%;
color: #DCDFDF;
.text {
letter-spacing: 0.3vw;
}
}
.bootRate {
left: 20.5%;
color: #DCDFDF;
.text {
letter-spacing: 1vw;
}
}
.runNum {
left: 37.5%;
color: #DCDFDF;
.text {
width: 5vw;
letter-spacing: 2vw;
}
.num {
color: #01F437;
}
}
.shutdownNum {
left: 53.5%;
color: #DCDFDF;
.text {
width: 5vw;
letter-spacing: 2vw;
}
.num {
color: #FFEB3B;
}
}
.standbyNum {
left: 69.5%;
color: #DCDFDF;
.text {
width: 5vw;
letter-spacing: 2vw;
}
.num {
color: #D8070D;
//color: #E1B00D;
}
}
.waitMaterials {
left: 71.5%;
color: #DCDFDF;
.text {
width: 5vw;
letter-spacing: 2vw;
}
.num {
color: #E1B00D;
}
}
.unactivatedNum {
left: 85%;
color: #DCDFDF;
.text {
letter-spacing: 1vw;
}
}
.centerContent {
position: absolute;
top: 17%;
left: 3.3%;
width: 74.8%;
height: 78%;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
.item {
display: inline-block;
width: calc(33% - 1vw);
height: 13.91vw;
margin: 0.5vw;
position: relative;
background-image: url("../../../assets/board/boardItemBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
.itemTitle {
position: absolute;
color: #DCDFDF;
left: 10%;
top: 11%;
transform: translateY(-50%);
font-size: 1.3vw;
}
.itemType {
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
left: 78%;
top: 40%;
width: 8vw;
height: 2.22vw;
line-height: 2.22vw;
text-align: center;
transform: translate(-50%, -50%);
font-size: 1.2vw;
color: #DCDFDF;
}
.itemType0 {
background-image: url("../../../assets/board/boardDeviceStatus0.png");
letter-spacing: 0.5vw;
}
.itemType1 {
background-image: url("../../../assets/board/boardDeviceStatus1.png");
letter-spacing: 0.5vw;
}
.itemType2 {
background-image: url("../../../assets/board/boardDeviceStatus2.png");
}
.itemType3 {
background-image: url("../../../assets/board/boardDeviceStatus3.png");
letter-spacing: 0.5vw;
}
.itemImg {
position: absolute;
left: 4%;
top: 28%;
width: 51%;
height: 65%;
background-image: url("../../../assets/board/boardDevice.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.itemTime {
position: absolute;
left: 78%;
top: 65%;
transform: translate(-50%, -50%);
font-size: 1.2vw;
color: #DCDFDF;
}
.itemTime0 {
color: #FB0102;
}
.itemTime1 {
color: #FC7F03;
}
.itemTime2 {
color: #02FD56;
}
.itemTime3 {
color: #68CBFD;
}
.itemText {
position: absolute;
left: 78%;
top: 80%;
transform: translate(-50%, -50%);
font-size: 0.8vw;
color: #DCDFDF;
}
}
}
.oee {
position: absolute;
top: 23%;
left: 78%;
width: 20%;
height: 30%;
}
.energy {
position: absolute;
top: 63%;
left: 78%;
width: 20%;
height: 30%;
}
.config {
position: absolute;
top: 3%;
right: 3%;
width: 10%;
height: 5vw;
.btn {
display: none;
}
&:hover {
.btn {
display: inline-block;
}
}
}
.fullLine {
width: 100%;
/deep/ .el-form-item__content {
width: calc(100% - 120px);
}
}
</style>