map/ui/dasadmin/src/views/backend/home/windMatrix.vue
2024-12-16 13:55:39 +08:00

484 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="FanList-content">
<el-row :gutter="10">
<el-col :xs="12" :sm="8" :md="8" :lg="4" :xl="3" v-for="(item, index) in props.parentData" style="margin-bottom: 5px">
<div class="grid-content ep-bg-purple"
@click="handleClick(item)"
@contextmenu.prevent="windContextMenu($event,item)"
>
<div class="FanList-panel wind-default" :class="{
'': item.standard==1,
'': item.standard==0,
'wind-offline': item.attributeMap.processedoperationmode == 33
}">
<div class="fanlist-top">
<span :class="item.standard == 1 ? 'wind-mark-icon' : 'fanlist-icon'">
<img :class="item.standard == 1 ? '' : 'wind-picture'" src="~assets/dashboard/biaogan.png" alt="" />
</span>
<span class="fanlist-name"> {{ item.name }}</span>
<el-tag v-if="item.attributeMap.processedoperationmode === 20" class="tag-panel is-primary" type="primary">并网</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 11" class="tag-panel is-warning" type="primary">待机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 16" class="tag-panel is-success" type="primary">启动</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 10" class="tag-panel is-maintenance" type="primary"
>维护</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 0" class="tag-panel is-offline" type="primary">离线</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 8" class="tag-panel info" type="primary">限功率运行</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 6" class="tag-panel is-danger" type="primary">正常停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1" class="tag-panel is-danger" type="primary"
>外部因素导致停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 2" class="tag-panel is-danger" type="primary">停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1110" class="tag-panel is-info" type="primary">解缆状态</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1111" class="tag-panel is-danger" type="primary"
>电网故障停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 1112" class="tag-panel is-danger" type="primary"
>安全链停机</el-tag>
<el-tag v-if="item.attributeMap.processedoperationmode === 33" class="tag-panel is-offline" type="primary"
>通讯中断</el-tag>
</div>
<div class="fanlist-main">
<el-row>
<el-col :span="24">
<div class="fanlist-pic">
<div class="mask">
<div class="heart"><img src="~assets/dashboard/leaf2.png" alt="" /></div>
<div class="leafs" :style="getAnimationStyle(item)">
<div class="leaf_1"><img src="~assets/dashboard/leaf1.png" alt="" /></div>
<div class="leaf_2"><img src="~assets/dashboard/leaf1.png" alt="" /></div>
<div class="leaf_3"><img src="~assets/dashboard/leaf1.png" alt="" /></div>
</div>
</div>
</div>
<div class="fanlist-pic">
<img src="~assets/dashboard/fanlist2.png" alt="" />
</div>
</el-col>
</el-row>
<el-row class="fanlist-data">
<div class="fanlist-text">
<span class="content-number">{{ item.attributeMap.iwindspeed }}</span>
<span>m/s</span>
</div>
<div class="fanlist-text">
<span class="content-number">{{ item.attributeMap.igenpower }}</span>
<span>kW</span>
</div>
<div class="fanlist-text">
<span class="content-number">{{ item.attributeMap.ikwhthisday }}</span>
<span>kWh</span>
</div>
</el-row>
</div>
<div class="fanlist-bottom">
<!-- <el-tag class="tag-panel is-danger">已锁定</el-tag>-->
<el-tag v-if="item.attributeMap.locked === 1" class="tag-panel is-danger">已锁定</el-tag>
</div>
</div>
</div>
</el-col>
</el-row>
<ContextMenu :pos="contextMenuPos" v-model:visible="OperateVisible">
<template #default>
<div class="modelOperate">
<el-button
class="control-btn"
type="primary"
@click="sendCommand('setTurbineFastStart')"
v-if="realTimeData.processedoperationmode !== 16"
>启动</el-button>
<el-button @click="sendCommand('setTurbineStop')" v-else class="control-btn" type="primary">停机</el-button>
<el-button @click="sendCommand('setTurbineResetStatusCode')" class="control-btn" type="primary">复位</el-button>
<el-button
@click="sendManualCommand(1)"
v-if="realTimeData.locked !== 1"
class="control-btn"
type="primary">锁定</el-button>
<el-button @click="sendManualCommand(0)" v-else class="control-btn" type="primary">解锁</el-button>
<el-button
class="control-btn"
type="primary"
@click="sendCommand('setTurbineFastStart')"
v-if="realTimeData.standard == 0"
>标杆设置</el-button>
<el-button
class="control-btn"
type="primary"
@click="sendCommand('setTurbineFastStart')"
v-else
>标杆取消</el-button>
</div>
</template>
</ContextMenu>
</div>
</template>
<script setup lang="ts">
import {defineProps, defineEmits, onMounted, onUnmounted, ref} from 'vue'
import { useRouter } from 'vue-router'
import { adminBaseRoutePath } from '/@/router/static/adminBase'
import ContextMenu from '/@/views/backend/auth/model/contextMenu.vue'
import { sendCommandReq, sendManualCommandReq } from '/@/api/backend/control/request'
import {ElMessage, ElMessageBox} from "element-plus";
const router = useRouter()
const props = defineProps({
parentData: {
type: Array,
default: () => [],
},
})
const getAnimationStyle = (item) => {
const irotorspeed = item.attributeMap?.irotorspeed ?? 0
let animationDuration;
animationDuration = 60 / irotorspeed / 3
const processedoperationmode = item.attributeMap?.processedoperationmode ?? 0
if(processedoperationmode==33){
return {
'animation-duration': `0s`,
'animation-timing-function': 'linear',
'animation-iteration-count': 'infinite',
'animation-direction': 'normaL',
}
}else{
return {
'animation-duration': `${animationDuration}s`,
'animation-timing-function': 'linear',
'animation-iteration-count': 'infinite',
'animation-direction': 'normaL',
}
}
}
const handleClick = (row) => {
if (!router.hasRoute('windTurbine')) {
router.addRoute('admin', {
path: adminBaseRoutePath + '/windTurbine',
name: 'windTurbine',
component: () => import('/@/views/backend/WindBlower/index.vue'),
meta: {
title: '单风机详情',
menuDesc: '单风机详情',
addtab: true,
},
})
}
router.push({
name: 'windTurbine',
query: {
irn: row.irn,
iotModelId: row.modelId,
deviceCode: row.deviceCode,
name: row.name,
model: row.model,
},
})
}
const OperateVisible = ref(false)
const contextMenuPos = ref({
x: 0,
y: 0,
})
const realTimeData = ref<any>({
processedoperationmode: 1111,
locked: 0,
deviceId: '',
name:'',
standard:''
})
const windContextMenu = (event: any,curnodeData) => {
contextMenuPos.value.x = event.pageX
contextMenuPos.value.y = event.pageY
realTimeData.value.processedoperationmode=curnodeData.attributeMap.processedoperationmode
realTimeData.value.locked=curnodeData.attributeMap.locked
realTimeData.value.deviceId=curnodeData.irn
realTimeData.value.name=curnodeData.name
realTimeData.value.standard=curnodeData.standard
OperateVisible.value = true
}
const sendCommand = (type: 'setTurbineFastStart' | 'setTurbineStop' | 'setTurbineResetStatusCode') => {
const sendTypeEnum = {
setTurbineFastStart: '风机快速启动指令',
setTurbineStop: '风机停机指令',
setTurbineResetStatusCode: '风机复位故障代码指令',
}
ElMessageBox.confirm('确认发送' + sendTypeEnum[type] + '吗?', '', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
const serviceName = sendTypeEnum[type]
const optDesc = serviceName + ',设定值为1'
sendCommandReq({
deviceId: realTimeData.value.deviceId as string,
serviceCode: type,
serviceName,
optDesc,
opValue: 1,
}).then((res) => {
if (res.code == 200) {
ElMessage.success('指令发送成功')
} else {
ElMessage.error('指令发送失败')
}
})
})
}
const sendManualCommand = (type: 1 | 0) => {
const serviceName = type === 0 ? '风机解锁' : '风机锁定'
ElMessageBox.confirm('确认' + serviceName + '吗?', '', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
sendManualCommandReq({
deviceId: realTimeData.value.deviceId as string,
serviceCode: 'Locked',
serviceName,
optDesc: serviceName + ',设定值为:' + type,
opValue: type,
}).then((res) => {
if (res.code == 200) {
ElMessage.success('指令发送成功')
} else {
ElMessage.error('指令发送失败')
}
})
})
}
</script>
<style scoped lang="scss">
@keyframes leafRotate {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(90deg);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(270deg);
}
100% {
transform: rotate(360deg);
}
}
.wind-mark {
background-image: linear-gradient(140deg, #ffe3e3 0%, #ffffff 93%);
border: 1px solid #ffe3e3;
}
.wind-default {
background-image: linear-gradient(180deg, #f0f6ff 0%, #ffffff 50%);
border: 1px solid #e1edf6;
}
.wind-offline {
background-image: linear-gradient(180deg, #dddddd 0%, #ffffff 93%);
border: 1px solid #eeeeee;
}
.wind-picture {
display: none;
}
.wind-mark-icon {
background: #ffffff;
border: 1px solid #ffe3e3;
border-radius: 8px 0 100px 0;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 30px;
vertical-align: middle;
}
.FanList-content {
overflow-x: hidden;
.FanList-panel {
border-radius: 8px;
cursor: pointer;
.fanlist-top {
display: flex;
width: 100%;
}
.fanlist-icon {
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 30px;
vertical-align: middle;
}
.fanlist-name {
width: 100%;
margin-top: 5px;
}
.tag-panel {
border-radius: 0 8px 0 0;
line-height: 20px;
}
.is-primary {
background: rgba(2, 119, 179, 0.2);
border: 1px solid #0277b3;
color: #0277b3;
}
.is-success {
background: rgba(6, 180, 41, 0.2);
border: 1px solid #06b429;
color: #06b429;
}
.is-info {
background: rgba(48, 89, 236, 0.2);
border: 1px solid #3059ec;
color: #3059ec;
}
.is-warning {
background: rgba(255, 126, 0, 0.2);
border: 1px solid #ff7e00;
color: #ff7e00;
}
.is-danger {
background: rgba(254, 55, 49, 0.2);
border: 1px solid #fe3731;
color: #fe3731;
}
.is-offline {
background: rgba(153, 153, 153, 0.2);
border: 1px solid #999999;
color: #999999;
}
.is-maintenance {
background: rgba(0, 160, 150, 0.2);
border: 1px solid #00a096;
color: #00a096;
}
.fanlist-main {
width: 100%;
display: flex;
justify-content: space-between;
padding: 5px 10px 0 10px;
text-align: center;
.fanlist-pic {
display: flex;
justify-content: center;
align-items: center;
margin-top: -10px;
.mask {
width: 43px;
height: 38px;
.heart {
position: absolute;
text-align: center;
top: 5px;
left: 17px;
/* z-index: 3;*/
}
.leafs {
/* z-index: 1;*/
position: absolute;
/* animation: leafRotate 1s infinite linear;*/
transform-origin: center center;
width: 46px;
height: 46px;
/*animation-duration: 1s;*/
animation-name: leafRotate;
/*animation-iteration-count: infinite;
animation-timing-function: linear;*/
.leaf_1 {
width: 9px;
height: 19px;
position: absolute;
left: 17px;
top: -1px;
/* transform-origin: left top;*/
}
.leaf_2 {
width: 9px;
height: 19px;
position: absolute;
left: 31px;
top: 20px;
/* transform-origin: left top;*/
transform: rotate(120deg);
}
.leaf_3 {
width: 9px;
height: 19px;
position: absolute;
left: 5px;
top: 22px;
/*transform-origin: left top;*/
transform: rotate(240deg);
}
}
}
}
.fanlist-text {
margin-top: 5px;
width: 100%;
text-align: right;
.content-number {
color: #333333;
font-size: 20px;
padding-right: 5px;
}
}
.fanlist-text span {
display: inline-block;
}
}
.fanlist-bottom {
display: flex;
justify-content: end;
height: 24px;
.tag-panel {
border-radius: 0 0 8px 0;
line-height: 20px;
}
}
}
.modelOperate{
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
width: 80px;
/* height: 80px;*/
.el-button {
margin: 5px;
}
}
}
@media screen and (max-width: 1680px) {
.FanList-content {
.FanList-panel {
.fanlist-text {
font-size: 12px !important;
.content-number {
font-size: 16px !important;
}
}
}
}
}
@media screen and (max-width: 1280px) {
.FanList-content {
.FanList-panel {
.fanlist-text {
margin-top: 10px !important;
}
}
}
}
</style>