微工厂环境大屏
This commit is contained in:
parent
0878434b03
commit
5c00f76020
BIN
src/assets/indexImg/MicEnvironment.png
Normal file
BIN
src/assets/indexImg/MicEnvironment.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 KiB |
@ -33,3 +33,11 @@ export function getCuttingLineHistogramData(){
|
||||
export function getActivationData(){
|
||||
return get('/device/getActivation')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 微工厂环境
|
||||
*/
|
||||
export function getSensorByDeptId(data){
|
||||
return get('/device/getSensorByDeptId',data)
|
||||
}
|
||||
|
67
src/store/moduleSocketMicEnvironment.ts
Normal file
67
src/store/moduleSocketMicEnvironment.ts
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* @FilePath: \wwwd:\code\screenFront\src\store\moduleSocketjixie.ts
|
||||
* @Author: 王路平
|
||||
* @文件版本: V1.0.0
|
||||
* @Date: 2023-02-06 15:58:13
|
||||
* @Description:
|
||||
*
|
||||
* 版权信息 : 2023 by ${再登软件}, All Rights Reserved.
|
||||
*/
|
||||
import { defineStore } from "pinia";
|
||||
import { Names } from '@/store/storeName'
|
||||
import { gettime, clacendTime } from "@/utils/time"
|
||||
export const useSocketStore = defineStore(Names.socketMicEnvironment, {
|
||||
// 使用方式
|
||||
// const Index= useIndexStore()
|
||||
// 1、Index.{数据}++
|
||||
// 2、Index.$patch({数据:??})
|
||||
// 3、Index.$patch((state)=>{ state.数据=??})
|
||||
// 4、通过action修改
|
||||
state: () => {
|
||||
return {
|
||||
humiture:
|
||||
{ "devId": "", "name": "温湿度", "temp": "0", "humidity": "0" },
|
||||
|
||||
// humiture:{Humiture:[],bottom:{humidity:null,temp:null,name:null},top:{humidity:null,temp:null,name:null}}, //温湿度
|
||||
pm: { "devId": "", "name": "粉尘", "pm25": "0", "pm10": "0" },
|
||||
verticalArr:[]
|
||||
|
||||
}
|
||||
},
|
||||
//computed 修改一些值
|
||||
//需要使用return将数据抛出
|
||||
//getters内可相互使用计算结果
|
||||
//使用时可直接放入标签内<div>Index.方法()</div>
|
||||
getters: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
//初始化
|
||||
setVerticalArr(val){
|
||||
this.verticalArr=val
|
||||
},
|
||||
sethumiture(val){
|
||||
this.humiture=val
|
||||
},
|
||||
setpm(val){
|
||||
this.pm=val
|
||||
},
|
||||
changehumiture(val){
|
||||
this.humiture.temp = val.temp
|
||||
this.humiture.humidity = val.humidity
|
||||
},
|
||||
changePm(val){
|
||||
this.pm.pm25 = val.pm25
|
||||
this.pm.pm10 = val.pm10
|
||||
},
|
||||
changeVerticalArr(val){
|
||||
this.verticalArr.forEach(res=>{
|
||||
if(res.id==val.devId&&res.item.type==val.type){
|
||||
res.item.val=val.val
|
||||
res.item.status = val.status
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
})
|
@ -28,4 +28,5 @@ export const enum Names{
|
||||
MechanicalViewJingjia="MechanicalViewJingjia",
|
||||
MechanicalViewJingshi="MechanicalViewJingshi",
|
||||
socketMechanics='socketMechanics',
|
||||
socketMicEnvironment='socketMicEnvironment',
|
||||
}
|
232
src/views/MicEnvironment/components/humidity.vue
Normal file
232
src/views/MicEnvironment/components/humidity.vue
Normal file
@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<border13>
|
||||
<div class="container">
|
||||
<div class="echartbox" ref="humiture"></div>
|
||||
</div>
|
||||
</border13>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { getCurrentInstance, markRaw, onMounted, reactive, ref, watch, onUnmounted,computed } from "vue";
|
||||
import { useSocketStore } from "@/store/moduleSocketMicEnvironment";
|
||||
import border13 from '@/components/border/Border13.vue'
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useSocketStore();
|
||||
let index = 0;
|
||||
let humiture = ref();
|
||||
let chart = null
|
||||
// const props = defineProps<{
|
||||
// top: any;
|
||||
// bottom: any;
|
||||
// }>();
|
||||
const borderColor = ["#E43961","#E43961"]
|
||||
function init() {
|
||||
|
||||
if (!chart) {
|
||||
chart = proxy.$echarts.init(humiture.value, 'dark');
|
||||
}
|
||||
let option = {
|
||||
title: {
|
||||
text: store.humiture.name,
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 18,
|
||||
},
|
||||
top: '2%'
|
||||
},
|
||||
grid: {
|
||||
// 让图表占满容器
|
||||
top: "0px",
|
||||
left: "0px",
|
||||
right: "0px",
|
||||
bottom: "0px",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "gauge",
|
||||
center: ["50%", "90%"],
|
||||
startAngle: 190,
|
||||
endAngle: -10,
|
||||
radius: "50%",
|
||||
min: -30,
|
||||
max: 50,
|
||||
splitNumber: 10,
|
||||
progress: {
|
||||
show: false,
|
||||
width: 5
|
||||
},
|
||||
pointer: {
|
||||
itemStyle: {
|
||||
color: 'inherit'
|
||||
}
|
||||
},
|
||||
//刻度轴宽
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 10,
|
||||
color: [
|
||||
[0.575, '#1089E7'],
|
||||
[0.725, '#7CFFB2'],
|
||||
[1, '#FF6E76']
|
||||
]
|
||||
}
|
||||
},
|
||||
//刻度线
|
||||
axisTick: {
|
||||
show: false,
|
||||
distance: -5,
|
||||
splitNumber: 5,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#999'
|
||||
}
|
||||
},
|
||||
//刻度线
|
||||
splitLine: {
|
||||
distance: 5,
|
||||
length: 3,
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
color: '#999'
|
||||
}
|
||||
},
|
||||
//表刻度值
|
||||
axisLabel: {
|
||||
distance: 15,
|
||||
color: '#999',
|
||||
fontSize: 10
|
||||
},
|
||||
anchor: {
|
||||
show: false
|
||||
},
|
||||
title: {
|
||||
show: false
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
// width: '10%',
|
||||
// lineHeight: 5,
|
||||
// borderRadius: 8,
|
||||
offsetCenter: [0, '25%'],
|
||||
fontSize: 15,
|
||||
// fontWeight: 'bolder',
|
||||
formatter: '{value} °C',
|
||||
color: 'inherit'
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: store.humiture.temp
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "gauge",
|
||||
center: ["50%", "55%"],
|
||||
startAngle: 200,
|
||||
endAngle: -20,
|
||||
min: 0,
|
||||
max: 100,
|
||||
progress: {
|
||||
show: false,
|
||||
width: 5
|
||||
},
|
||||
pointer: {
|
||||
itemStyle: {
|
||||
color: 'inherit'
|
||||
}
|
||||
},
|
||||
//刻度轴宽
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 10,
|
||||
color: [
|
||||
[0.4, '#FF6E76'],
|
||||
[0.7, '#7CFFB2'],
|
||||
[1, '#1089E7']
|
||||
]
|
||||
}
|
||||
},
|
||||
//刻度线
|
||||
axisTick: {
|
||||
distance: 0,
|
||||
splitNumber: 5,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#999'
|
||||
}
|
||||
},
|
||||
//刻度线
|
||||
splitLine: {
|
||||
distance: 5,
|
||||
length: 3,
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
color: '#999'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
distance: 15,
|
||||
color: '#999',
|
||||
fontSize: 12
|
||||
},
|
||||
anchor: {
|
||||
show: false
|
||||
},
|
||||
title: {
|
||||
show: false
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
offsetCenter: [0, '15%'],
|
||||
fontSize: 20,
|
||||
formatter: '{value} %RH',
|
||||
color: 'inherit'
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: store.humiture.humidity
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
}
|
||||
watch(
|
||||
() => store.humiture,
|
||||
(newData) => {
|
||||
init()
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.errList {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.echartbox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
125
src/views/MicEnvironment/components/lineChart.vue
Normal file
125
src/views/MicEnvironment/components/lineChart.vue
Normal file
@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="chart" ref="chart"></div>
|
||||
<div class="math-box">
|
||||
<div class="math-content">
|
||||
<div style="height: 25%;"> </div>
|
||||
<div class="key">最大值</div>
|
||||
<div class="key">最小值</div>
|
||||
<div class="key">平均值</div>
|
||||
</div>
|
||||
<div class="math-content" v-for="(item,index) in calc.math">
|
||||
<div :style="{color:color[index]}">{{ item.key }}</div>
|
||||
<div>{{ item.value.max }}</div>
|
||||
<div>{{ item.value.min }}</div>
|
||||
<div>{{ item.value.avg }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { ref, onMounted, onUpdated, getCurrentInstance, watch } from "vue"
|
||||
const prop = defineProps<{
|
||||
calc: {
|
||||
name: string,
|
||||
math: {
|
||||
key: string,
|
||||
value: {
|
||||
max: number,
|
||||
min: number,
|
||||
avg: number,
|
||||
data: any[]
|
||||
}
|
||||
}[],
|
||||
data: any
|
||||
}
|
||||
}>()
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const chart = ref()
|
||||
let myChart = null
|
||||
let data = prop.calc.data
|
||||
let color = ['#4281E5','#78F7AE','#FF6E40']
|
||||
function init() {
|
||||
myChart = proxy.$echarts.init(chart.value, 'dark');
|
||||
const option = {
|
||||
title: {
|
||||
text: prop.calc.name,
|
||||
top: "5%",
|
||||
left: "5%"
|
||||
},
|
||||
color: color,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
grid: {
|
||||
top: "15%",
|
||||
left: "5%",
|
||||
right: "5%",
|
||||
bottom: "5%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: data
|
||||
};
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
watch(() => prop.calc.data, (newVal) => {
|
||||
data = newVal
|
||||
myChart.setOption({
|
||||
series: data
|
||||
})
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
box-shadow: rgb(2, 106, 181) 0px 8px 8px;
|
||||
}
|
||||
.container:hover {
|
||||
box-shadow: rgb(2, 106, 181) 0px 8px 16px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
height: calc(100% - 90px);
|
||||
width: 100%;
|
||||
}
|
||||
.math-box {
|
||||
height: 90px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
}
|
||||
.math-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
.key {
|
||||
color: #ff6e40;
|
||||
}
|
||||
</style>
|
225
src/views/MicEnvironment/components/pm.vue
Normal file
225
src/views/MicEnvironment/components/pm.vue
Normal file
@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<border13>
|
||||
<div class="container">
|
||||
<div class="echartbox" ref="dust">
|
||||
</div>
|
||||
</div>
|
||||
</border13>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { getCurrentInstance, markRaw, onMounted, onUnmounted, reactive, ref, watch,computed } from "vue";
|
||||
import { useSocketStore } from "@/store/moduleSocketMicEnvironment";
|
||||
import border13 from '@/components/border/Border13.vue'
|
||||
import { number } from "echarts/core";
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const store = useSocketStore();
|
||||
let index = 0;
|
||||
let dust = ref();
|
||||
let chart = ref(null)
|
||||
const props = defineProps({
|
||||
pm10limit:{
|
||||
type:Number,
|
||||
default:150
|
||||
},
|
||||
pm25limit:{
|
||||
type:Number,
|
||||
default:75
|
||||
}
|
||||
})
|
||||
const borderColor = ["#E43961","#E43961"]
|
||||
function init() {
|
||||
if (!chart.value) {
|
||||
chart.value = proxy.$echarts.init(dust.value, 'dark');
|
||||
}
|
||||
let option = {
|
||||
title: {
|
||||
text: store.pm.name,
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 18,
|
||||
},
|
||||
top: '2%'
|
||||
},
|
||||
grid: {
|
||||
// 让图表占满容器
|
||||
top: "0px",
|
||||
left: "0px",
|
||||
right: "0px",
|
||||
bottom: "0px",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "gauge",
|
||||
center: ["50%", "90%"],
|
||||
startAngle: 190,
|
||||
endAngle: -10,
|
||||
radius: "50%",
|
||||
min: 0,
|
||||
max: 100,
|
||||
splitNumber: 10,
|
||||
pointer: {
|
||||
icon: "path://M12.8,0.7l12,40.1H0.7L12.8,0.7z",
|
||||
length: "12%",
|
||||
width: 10,
|
||||
offsetCenter: [0, "-40%"],
|
||||
itemStyle: {
|
||||
color: "inherit",
|
||||
},
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 8,
|
||||
color: [
|
||||
[0.35, "#7CFFB2"],
|
||||
[0.75, "#FDDD60"],
|
||||
[1, "#FF6E76"],
|
||||
],
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
distance: 0,
|
||||
splitNumber: 5,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#999",
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
distance: 5,
|
||||
length: 8,
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
color: "#999",
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
distance: 12,
|
||||
color: "#999",
|
||||
fontSize: 10,
|
||||
},
|
||||
anchor: {
|
||||
show: false,
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
width: "60%",
|
||||
lineHeight: 20,
|
||||
borderRadius: 8,
|
||||
offsetCenter: [0, "20%"],
|
||||
fontSize: 15,
|
||||
fontWeight: "bolder",
|
||||
formatter: "{value} μg/m3",
|
||||
color: "inherit",
|
||||
},
|
||||
title: {
|
||||
// show: false,
|
||||
offsetCenter: [0, "-20%"],
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: store.pm.pm25,
|
||||
name: "PM2.5",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "gauge",
|
||||
center: ["50%", "55%"],
|
||||
startAngle: 200,
|
||||
endAngle: -20,
|
||||
min: 0,
|
||||
max: 200,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 10,
|
||||
color: [
|
||||
[0.35, "#7CFFB2"],
|
||||
[0.75, "#FDDD60"],
|
||||
[1, "#FF6E76"],
|
||||
],
|
||||
},
|
||||
},
|
||||
pointer: {
|
||||
itemStyle: {
|
||||
color: "inherit",
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
distance: -10,
|
||||
length: 6,
|
||||
lineStyle: {
|
||||
color: "#fff",
|
||||
width: 2,
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
distance: -10,
|
||||
length: 10,
|
||||
lineStyle: {
|
||||
color: "#fff",
|
||||
width: 4,
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
color: "inherit",
|
||||
distance: 20,
|
||||
fontSize: 10,
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
offsetCenter: [0, "20%"],
|
||||
fontSize: 20,
|
||||
formatter: "{value} μg/m3",
|
||||
color: "inherit",
|
||||
},
|
||||
title: {
|
||||
offsetCenter: [0, "-50%"],
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: store.pm.pm10,
|
||||
name: "PM10",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.value.setOption(option);
|
||||
}
|
||||
watch(
|
||||
() => store.pm,
|
||||
(newData) => {
|
||||
init()
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.echartbox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-red {
|
||||
color: #e43961;
|
||||
animation: redstart 2s infinite;
|
||||
font-size: 14px;
|
||||
/* position: relative; */
|
||||
/* top: -15px; */
|
||||
}
|
||||
|
||||
</style>
|
199
src/views/MicEnvironment/components/verticalNum.vue
Normal file
199
src/views/MicEnvironment/components/verticalNum.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<!--
|
||||
* @FilePath: \gitscreenFront\src\views\PaintShopView\components\verticalNum.vue
|
||||
* @Author: 王路平
|
||||
* @文件版本: V1.0.0
|
||||
* @Date: 2023-02-13 08:22:35
|
||||
* @Description:
|
||||
*
|
||||
* 版权信息 : 2023 by ${再登软件}, All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<div ref="numBox1" :style="{ height: '100%', width: '100%' }">
|
||||
<border6 ref="refborder3">
|
||||
<template v-slot>
|
||||
<div class="box" ref="classBox1">
|
||||
<h2>{{ props.title }}</h2>
|
||||
<h5 v-if="props.unit">{{ `${t('messages.NormalValue')}0-${props.quota}${props.unit}` }}</h5>
|
||||
<h5 v-else> </h5>
|
||||
<i :class="['iconfont', 'iconbig-size', icon, iconcolor]"></i>
|
||||
<p class="unit" v-if="props.unit && item.status">
|
||||
<p class="num">{{ item.val }} </p>
|
||||
<span>{{ props.unit }}</span>
|
||||
</p>
|
||||
<p class="unit" v-else>
|
||||
<p class="num"> </p>
|
||||
<span> </span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</border6>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, watch, computed, onUnmounted } from "vue";
|
||||
import border6 from "@/components/borderBox/border6.vue";
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
let { t } = useI18n();
|
||||
type itemType = {
|
||||
'id': string;
|
||||
"name": string;
|
||||
"val": string;
|
||||
"type": string;
|
||||
"status": boolean };
|
||||
let props = defineProps<{
|
||||
title: string;
|
||||
item:itemType;
|
||||
unit:string;
|
||||
quota:number | null;
|
||||
iconname:string;
|
||||
}>();
|
||||
let i = ref(0)
|
||||
let icon = computed(() => {
|
||||
return props.iconname
|
||||
});
|
||||
let iconcolor = computed(() => {
|
||||
//开始进入渲染是没有获取到该数据则需要判断 如果没有则返回空
|
||||
if (props.item) {
|
||||
return props.item.status ? +props.item.val > +props.quota ? "icon-red" : "icon-blue" : "icon-grey";
|
||||
} else {
|
||||
return "icon-grey"
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
let refborder3 = ref();
|
||||
let numBox1 = ref();
|
||||
const classBox1 = ref()
|
||||
onMounted(() => {
|
||||
|
||||
});
|
||||
onUnmounted(() => {
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@import "@/assets/css/iconfont.css";
|
||||
|
||||
|
||||
.box {
|
||||
height: 50%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.box>h5 {
|
||||
font-size: 15px;
|
||||
/* margin-bottom: 20px; */
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* .contentbox{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
} */
|
||||
h2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon-red {
|
||||
font-size: 100px;
|
||||
color: #E43961;
|
||||
animation: redstart 2s infinite;
|
||||
/* position: relative; */
|
||||
/* top: -15px; */
|
||||
}
|
||||
|
||||
.icon-blue {
|
||||
font-size: 100px;
|
||||
color: #20AEC5;
|
||||
/* position: relative; */
|
||||
/* top: -15px; */
|
||||
}
|
||||
|
||||
.icon-grey {
|
||||
color: rgb(167, 166, 189);
|
||||
font-size: 100px;
|
||||
/* position: relative; */
|
||||
/* top: -15px; */
|
||||
}
|
||||
|
||||
.iconsmall-size {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.num {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.unit {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
vertical-align: top;
|
||||
font-size: 16px;
|
||||
height: 5;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.box>h2 {
|
||||
font-size: 20px;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
|
||||
.icontip {
|
||||
display: flex;
|
||||
margin-top: -60px;
|
||||
width: 100px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.icontipBox li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.icontipBox li p:nth-child(1) {
|
||||
width: 40%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.icontipBox li p:nth-child(2) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@keyframes redstart {
|
||||
0% {}
|
||||
|
||||
50% {
|
||||
text-shadow: #fff 1px 0 10px;
|
||||
}
|
||||
|
||||
100% {}
|
||||
}
|
||||
</style>
|
||||
|
334
src/views/MicEnvironment/index.vue
Normal file
334
src/views/MicEnvironment/index.vue
Normal file
@ -0,0 +1,334 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="title">
|
||||
<header2 ref="headerref" :width="'100%'" :height="'150px'" :title="t('messages.微工厂环境实时监测系统')"
|
||||
:titleTip="titleTip" :typeFun="['time']" :alarmType="[]"></header2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" ref="Acontent">
|
||||
<div class="top">
|
||||
<div v-for="items in store.verticalArr" class="top-box-item">
|
||||
<verticalNum :title="items.name" :iconname="items.iconname" :item="items.item" :unit="items.unit"
|
||||
:quota="items.quota"></verticalNum>
|
||||
</div>
|
||||
<div class="top-box-item">
|
||||
<pm :pm10limit="150" :pm25limit="75"></pm>
|
||||
</div>
|
||||
<div class="top-box-item">
|
||||
<humidity></humidity>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<lineChart v-for="(calc, index) in calcArr"
|
||||
:style="{ width: width + 'px', height: height + 'px', 'min-width': 'calc(25% - 20px)' }" :calc="calc">
|
||||
</lineChart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import header2 from '@/components/headerBox/header2.vue'
|
||||
import verticalNum from './components/verticalNum.vue'
|
||||
import pm from './components/pm.vue';
|
||||
import humidity from './components/humidity.vue';
|
||||
import lineChart from './components/lineChart.vue';
|
||||
import { getSensorByDeptId } from '@/http/MicrofactoryDev'
|
||||
import { getCurrent24Trend } from '@/http/Trend/index'
|
||||
import { onMounted, onUnmounted, reactive, ref } from "vue"
|
||||
import { connectWebsocket, closeWebsocket } from "@/utils/websocket";
|
||||
import { useSocketStore } from "@/store/moduleSocketMicEnvironment";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
let { t } = useI18n();
|
||||
const store = useSocketStore();
|
||||
|
||||
let titleTip = [
|
||||
{
|
||||
color: "#E43961",
|
||||
name: t('messages.abnormal'),
|
||||
},
|
||||
{
|
||||
color: "#20AEC5",
|
||||
name: t('messages.NoAbnormal'),
|
||||
},
|
||||
{
|
||||
color: "#A7A6BD",
|
||||
name: t('messages.disconnection'),
|
||||
},
|
||||
];
|
||||
|
||||
const sensor_config: any = {
|
||||
'Noise_Reg': { 'icon': 'icon-shengyin', 'unit': 'dB', 'quota': 80, 'name': '噪声监测传感器', 'type': 'noise' },
|
||||
'Smoke_Reg': { 'icon': 'icon-yanwubaojingqi', 'unit': 'ppm', 'quota': 100, 'name': '烟雾监测传感器', 'type': 'smoke' },
|
||||
'CH2O': { 'icon': 'icon-app_icons--', 'unit': 'mg/m³', 'quota': 0.08, 'name': '甲醛监测传感器', 'type': 'CH2O' },
|
||||
'TVOC': { 'icon': 'icon-TVOC-Outlined', 'unit': 'mg/m³', 'quota': 0.5, 'name': 'TVOC监测传感器', 'type': 'TVOC' },
|
||||
'Methane_Reg': { 'icon': 'icon-ranqi', 'unit': '', 'quota': 0, 'name': '燃气监测传感器', 'type': 'Gas' },
|
||||
}
|
||||
let width = ref(1500)
|
||||
let height = ref(580)
|
||||
let trendObj = {}
|
||||
let sensor_arr = [];
|
||||
const sensor_keys = Object.keys(sensor_config)
|
||||
let noise_id = ''
|
||||
let timer = null;
|
||||
//趋势图
|
||||
type calcType = {
|
||||
name: string,
|
||||
math: {
|
||||
key: string,
|
||||
value: {
|
||||
max: number,
|
||||
min: number,
|
||||
avg: number,
|
||||
data: any[]
|
||||
}
|
||||
}[],
|
||||
data: any[]
|
||||
}
|
||||
let calcArr = ref<calcType[]>()
|
||||
async function getSensorData() {
|
||||
let res: any = await getSensorByDeptId({ ids: '20' })
|
||||
if (res.code === 200) {
|
||||
let data = res.data
|
||||
let temp_vertical = []
|
||||
let humiture = { "devId": "", "name": "温湿度", "temp": "", "humidity": "" }
|
||||
let pm = { "devId": "", "name": "粉尘", "pm25": "", "pm10": "" }
|
||||
|
||||
data.forEach(element => {
|
||||
if (sensor_keys.includes(element.type)) {
|
||||
sensor_arr.push(element.id)
|
||||
temp_vertical.push({
|
||||
id: element.id,
|
||||
name: sensor_config[element.type].name,
|
||||
iconname: sensor_config[element.type].icon,
|
||||
item: { "name": element.name, "val": element.data, "type": sensor_config[element.type].type, "status": JSON.parse(element.status) },
|
||||
unit: sensor_config[element.type].unit,
|
||||
quota: sensor_config[element.type].quota,
|
||||
})
|
||||
if (sensor_config[element.type].type == 'noise') {
|
||||
noise_id = element.id
|
||||
trendObj[element.id] = sensor_config[element.type].unit
|
||||
}
|
||||
if (sensor_config[element.type].type == 'CH2O') {
|
||||
trendObj[element.id] = sensor_config[element.type].unit
|
||||
}
|
||||
} else {
|
||||
if (element.type == 'HIGH_PM10_Reg') {
|
||||
pm.devId = element.id
|
||||
pm.pm10 = element.data
|
||||
trendObj[element.id] = 'μg/m3'
|
||||
}
|
||||
if (element.type == 'HIGH_PM25_Reg') {
|
||||
pm.devId = element.id
|
||||
pm.pm25 = element.data
|
||||
}
|
||||
if (element.type == 'AirHumi_Reg') {
|
||||
humiture.devId = element.id
|
||||
humiture.humidity = element.data
|
||||
trendObj[element.id] = '℃/%RH'
|
||||
}
|
||||
if (element.type == 'AirTemp_Reg') {
|
||||
humiture.devId = element.id
|
||||
humiture.temp = element.data
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
store.setVerticalArr(temp_vertical)
|
||||
store.sethumiture(humiture)
|
||||
store.setpm(pm)
|
||||
get24Trend()
|
||||
}
|
||||
}
|
||||
|
||||
async function get24Trend() {
|
||||
let trendIds = Object.keys(trendObj).toString()
|
||||
let trend: any = await getCurrent24Trend(trendIds)
|
||||
if (trend.code === 200) {
|
||||
let tempData = {}
|
||||
trend.data.forEach((item: any) => {
|
||||
if (trendObj[item.id]) {
|
||||
item.name = item.name + '(' + trendObj[item.id] + ')'
|
||||
}
|
||||
if (tempData.hasOwnProperty(item.id)) {
|
||||
let seriesData: any = {
|
||||
name: item.type,
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: item.date.map((key, value) => [key, item.value[value]]),
|
||||
smooth: true,
|
||||
}
|
||||
tempData[item.id].data.push(seriesData)
|
||||
tempData[item.id].math.push({
|
||||
key: item.type,
|
||||
value: {
|
||||
max: item.max,
|
||||
min: item.min,
|
||||
avg: item.avg
|
||||
}
|
||||
})
|
||||
} else {
|
||||
tempData[item.id] = {
|
||||
name: item.name,
|
||||
data: [{
|
||||
name: item.type,
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: item.date.map((key, value) => [key, item.value[value]]),
|
||||
smooth: true,
|
||||
}],
|
||||
math: [{
|
||||
key: item.type,
|
||||
value: {
|
||||
max: item.max,
|
||||
min: item.min,
|
||||
avg: item.avg
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
let data: any = Object.values(tempData)
|
||||
calcArr.value = data
|
||||
width.value = 1900 / data.length - (data.length - 1) * 20;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getWebsocket(val) {
|
||||
try {
|
||||
let data = JSON.parse(val);
|
||||
|
||||
//燃气监测
|
||||
if (data.type == "Gas") {
|
||||
if (sensor_arr.includes(data.msg.devId)) {
|
||||
store.changeVerticalArr({ devId: data.msg.devId, val: data.msg.methane.value, type: "Gas", status: true })
|
||||
}
|
||||
}
|
||||
//甲醛TVOC
|
||||
if (data.type == "TVOC_CH2O") {
|
||||
if (sensor_arr.includes(data.msg.CH2O.devId)) {
|
||||
store.changeVerticalArr({ devId: data.msg.CH2O.devId, val: data.msg.CH2O.value, type: "CH2O", status: true })
|
||||
store.changeVerticalArr({ devId: data.msg.TVOC.devId, val: data.msg.TVOC.value, type: "TVOC", status: true })
|
||||
}
|
||||
|
||||
}
|
||||
//声音
|
||||
if (data.type == "noise") {
|
||||
data.msg.listData.forEach(item => {
|
||||
if (item.devId == noise_id) {
|
||||
store.changeVerticalArr({ devId: item.devId, val: item.value, type: "noise", status: item.status })
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
//烟雾传感器
|
||||
if (data.type == "smoke") {
|
||||
if (sensor_arr.includes(data.msg.devId)) {
|
||||
store.changeVerticalArr({ devId: data.msg.devId, val: data.msg.smoke.value, type: "smoke", status: true })
|
||||
}
|
||||
}
|
||||
//温湿度
|
||||
if (data.type == "humiture") {
|
||||
data.msg.Humiture.forEach(item => {
|
||||
if (item.devId == store.humiture.devId) {
|
||||
store.changehumiture(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
//粉尘
|
||||
if (data.type == "dust") {
|
||||
if (data.msg.devId == store.pm.devId) {
|
||||
store.changePm(data.msg)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log(err, "报错了大哥", console.log(val) );
|
||||
|
||||
}
|
||||
}
|
||||
function errWebsocket(val) {
|
||||
// console.log(val);
|
||||
}
|
||||
onMounted(() => {
|
||||
getSensorData()
|
||||
connectWebsocket(null, null, getWebsocket, errWebsocket);
|
||||
timer = setInterval(() => {
|
||||
get24Trend()
|
||||
}, 1000 * 60 * 10)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer)
|
||||
closeWebsocket()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
height: 1080px;
|
||||
width: 1920px;
|
||||
color: #20aec5;
|
||||
background-color: #100c2a;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.title>h1 {
|
||||
font-size: 30px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header p {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
bottom: 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
--header: 150px;
|
||||
height: calc(1080px - var(--header))
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 330px;
|
||||
}
|
||||
|
||||
.top-box-item {
|
||||
width: 14%;
|
||||
height: 100%;
|
||||
margin: 0 5px 10px 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -170,7 +170,7 @@ async function getWaterFlowInfoFun() {
|
||||
if (code == 200) {
|
||||
allData.in = data.in
|
||||
allData.out = data.out
|
||||
allData.use = data.use
|
||||
allData.use = data.use.toFixed(2)
|
||||
allData.currentCount = data.currentCount
|
||||
allData.xl = data.xl.toFixed(1)
|
||||
allData.xy = data.xy.toFixed(1)
|
||||
|
@ -286,6 +286,12 @@ let routerList = [
|
||||
title: '智能货架物联管理系统',
|
||||
url: require("../assets/indexImg/intelligentShelves.png"),
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
path: "/MicEnvironment",
|
||||
title: '微工厂环境实时监测系统',
|
||||
url: require("../assets/indexImg/MicEnvironment.png"),
|
||||
},
|
||||
];
|
||||
let lang = ref(getStoredLanguage() || '简体中文')
|
||||
function changelang(val) {
|
||||
@ -314,7 +320,7 @@ onUnmounted(() => { });
|
||||
}
|
||||
|
||||
.itemlist {
|
||||
height: 1030px;
|
||||
height: 990px;
|
||||
width: 1920px;
|
||||
color: #20aec5;
|
||||
background-color: #100c2a;
|
||||
|
Loading…
Reference in New Issue
Block a user