This commit is contained in:
高云鹏 2024-12-06 09:33:05 +08:00
commit c90c7d297b
14 changed files with 482 additions and 133 deletions

View File

@ -218,6 +218,9 @@ size_t Socket::write(const Frame& frame) const
LOG_ERROR("frame length: " << frame.size() << " exceeds maximum length for sockets"); LOG_ERROR("frame length: " << frame.size() << " exceeds maximum length for sockets");
return 0; return 0;
} }
if (m_Socket == INVALID_SOCKET) return 0;
if (m_DestAddr == 0) return 0;
if (m_DestAddrLen <= 0) return 0;
const int bufferLength = static_cast<int>(frame.size()); const int bufferLength = static_cast<int>(frame.size());
const char* const buffer = reinterpret_cast<const char*>(frame.data()); const char* const buffer = reinterpret_cast<const char*>(frame.data());

View File

@ -0,0 +1,11 @@
package com.das.modules.cache.domain;
import lombok.Data;
@Data
public class WindSpeedCoefValue {
private Double minValue;
private Double maxValue;
private Double coef;
private Double base;
}

View File

@ -16,4 +16,6 @@ public interface CacheService {
* @return * @return
*/ */
IotModelCache getIotModelCache(); IotModelCache getIotModelCache();
CalcCache getCalcCache();
} }

View File

@ -0,0 +1,10 @@
package com.das.modules.cache.service;
import com.das.modules.cache.domain.WindSpeedCoefValue;
import java.util.List;
public interface CalcCache {
List<WindSpeedCoefValue> getWindSpeedCoef(Long deviceId);
void refreshWindSpeedCoef();
}

View File

@ -1,6 +1,7 @@
package com.das.modules.cache.service.impl; package com.das.modules.cache.service.impl;
import com.das.modules.cache.service.CacheService; import com.das.modules.cache.service.CacheService;
import com.das.modules.cache.service.CalcCache;
import com.das.modules.cache.service.EquipmentCache; import com.das.modules.cache.service.EquipmentCache;
import com.das.modules.cache.service.IotModelCache; import com.das.modules.cache.service.IotModelCache;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -15,6 +16,9 @@ public class CacheServiceImpl implements CacheService {
@Autowired @Autowired
IotModelCache iotModelCache; IotModelCache iotModelCache;
@Autowired
CalcCache calcCache;
@Override @Override
public EquipmentCache getEquipmentCache() { public EquipmentCache getEquipmentCache() {
return equipmentCache; return equipmentCache;
@ -25,5 +29,10 @@ public class CacheServiceImpl implements CacheService {
return iotModelCache; return iotModelCache;
} }
@Override
public CalcCache getCalcCache() {
return calcCache;
}
} }

View File

@ -0,0 +1,50 @@
package com.das.modules.cache.service.impl;
import com.das.modules.cache.domain.WindSpeedCoefValue;
import com.das.modules.cache.service.CalcCache;
import com.das.modules.page.domian.dto.SysPowerCurveFactorDto;
import com.das.modules.page.domian.vo.SysPowerCurveFactorVo;
import com.das.modules.page.mapper.SysPowerCurveFactorMapper;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class CalcCacheImpl implements CalcCache {
@Autowired
SysPowerCurveFactorMapper sysPowerCurveFactorMapper;
private ConcurrentHashMap<Long, List<WindSpeedCoefValue>> windSpeedCoefMap = new ConcurrentHashMap<>();
@PostConstruct
private void init(){
refreshWindSpeedCoef();
}
@Override
public List<WindSpeedCoefValue> getWindSpeedCoef(Long deviceId) {
return windSpeedCoefMap.get(deviceId);
}
@Override
public void refreshWindSpeedCoef() {
List<SysPowerCurveFactorVo> sysPowerCurveFactorVos = sysPowerCurveFactorMapper.querySysPowerCurveFactorList(new SysPowerCurveFactorDto());
for (SysPowerCurveFactorVo sysPowerCurveFactorVo : sysPowerCurveFactorVos) {
WindSpeedCoefValue windSpeedCoefValue = new WindSpeedCoefValue();
windSpeedCoefValue.setMinValue(sysPowerCurveFactorVo.getSpeedMin());
windSpeedCoefValue.setMaxValue(sysPowerCurveFactorVo.getSpeedMax());
windSpeedCoefValue.setCoef(sysPowerCurveFactorVo.getFactorK());
windSpeedCoefValue.setBase(sysPowerCurveFactorVo.getFactorB());
List<WindSpeedCoefValue> windSpeedCoefValues = windSpeedCoefMap.get(sysPowerCurveFactorVo.getTurbineId());
if (windSpeedCoefValues == null) {
windSpeedCoefValues = new java.util.ArrayList<>();
}
windSpeedCoefValues.add(windSpeedCoefValue);
windSpeedCoefMap.put(sysPowerCurveFactorVo.getTurbineId(), windSpeedCoefValues);
}
}
}

View File

@ -0,0 +1,59 @@
package com.das.modules.calc.functions;
import cn.hutool.core.collection.CollectionUtil;
import com.das.modules.cache.domain.DeviceInfoCache;
import com.das.modules.cache.domain.WindSpeedCoefValue;
import com.das.modules.cache.service.CacheService;
import com.das.modules.data.service.DataService;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.type.AviatorNil;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Aviator扩展函数 - 获取时间维度内平均
* 函数格式: avg(deviceId, attr, timedim)
* timedim: day - month - year -
* 返回值数值 nil - 获取错误
*/
@Slf4j
public class FunctionWindSpeedFactor extends AbstractFunction {
private DataService dataService = null;
private CacheService cacheService = null;
public FunctionWindSpeedFactor(DataService dataService, CacheService cacheService) {
this.dataService = dataService;
this.cacheService = cacheService;
}
@Override
public String getName() {
return "windSpeedFactor";
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject deviceCode) {
//设备Code
String code = (String)deviceCode.getValue(env);
DeviceInfoCache deviceInfoCache = cacheService.getEquipmentCache().getDeviceInfoCacheByCode(code);
if (deviceInfoCache == null) {
return AviatorNil.NIL;
}
List<WindSpeedCoefValue> windSpeedCoef = cacheService.getCalcCache().getWindSpeedCoef(deviceInfoCache.getDeviceId());
if (CollectionUtil.isEmpty(windSpeedCoef)){
return AviatorNil.NIL;
}
//未找到缓存查询时序API获取数据
return AviatorRuntimeJavaType.valueOf(windSpeedCoef);
}
}

View File

@ -12,6 +12,8 @@ import com.das.common.utils.BeanCopyUtils;
import com.das.common.utils.PageDataInfo; import com.das.common.utils.PageDataInfo;
import com.das.common.utils.PageQuery; import com.das.common.utils.PageQuery;
import com.das.modules.auth.domain.vo.SysUserVo; import com.das.modules.auth.domain.vo.SysUserVo;
import com.das.modules.cache.domain.WindSpeedCoefValue;
import com.das.modules.cache.service.CacheService;
import com.das.modules.equipment.entity.SysEquipment; import com.das.modules.equipment.entity.SysEquipment;
import com.das.modules.equipment.mapper.SysEquipmentMapper; import com.das.modules.equipment.mapper.SysEquipmentMapper;
import com.das.modules.page.domian.dto.IntervalDto; import com.das.modules.page.domian.dto.IntervalDto;
@ -52,6 +54,9 @@ public class WindSpeedCorrectServiceImpl implements WindSpeedCorrectService {
@Autowired @Autowired
private SysPowerCurveFactorMapper sysPowerCurveFactorMapper; private SysPowerCurveFactorMapper sysPowerCurveFactorMapper;
@Autowired
private CacheService cacheService;
@Override @Override
public void importWindSpeedCorrect(MultipartFile file) throws IOException { public void importWindSpeedCorrect(MultipartFile file) throws IOException {
// 通过文件获取输入流 // 通过文件获取输入流
@ -90,6 +95,8 @@ public class WindSpeedCorrectServiceImpl implements WindSpeedCorrectService {
} }
//批量插入数据库 //批量插入数据库
sysPowerCurveFactorMapper.insertBatch(listData); sysPowerCurveFactorMapper.insertBatch(listData);
//更新缓存数据
cacheService.getCalcCache().refreshWindSpeedCoef();
} }
@Override @Override

View File

@ -24,7 +24,7 @@
and t.turbine_id = #{info.turbineId} and t.turbine_id = #{info.turbineId}
</if> </if>
</where> </where>
order by sq.name asc order by sq.name asc, t.speed_min asc
</select> </select>
<select id="querySysPowerCurveFactorList" resultMap="resultMap"> <select id="querySysPowerCurveFactorList" resultMap="resultMap">
@ -46,7 +46,7 @@
</foreach> </foreach>
</if> </if>
</where> </where>
order by sq.name asc order by sq.name asc, t.speed_min asc
</select> </select>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -3,79 +3,114 @@
<el-row style="margin: 0px;"> <el-row style="margin: 0px;">
<el-col :md="24" :lg="24" class="col-top"> <el-col :md="24" :lg="24" class="col-top">
<el-row class="overview"> <el-row class="overview">
<el-col :xs="12" :sm="8" :md="8" :lg="4"> <el-col :xs="24" :sm="24" :md="24" :lg="16">
<div class="overviewItem" style="margin-left: 0px;"> <div class="overviewItem" style="margin-left: 0px;">
<img class="small-panel-pic" src="~assets/dashboard/overview01.png" alt="" /> <el-col :xs="1" :sm="1" :md="1" :lg="1">
<div class="small-base"> <img class="small-panel-pic" src="~assets/dashboard/overview07.png" alt="" />
<div class="small-title">全场平均风速</div> </el-col>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmavgwindspeed}}</span>
<span>m/s</span>
</div>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="8" :md="8" :lg="4">
<div class="overviewItem">
<img class="small-panel-pic" src="~assets/dashboard/overview02.png" alt="" />
<div class="small-base">
<div class="small-title">全场实时有功</div>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmactivepower}}</span>
<span>kW</span>
</div>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="8" :md="8" :lg="4"> <el-col :xs="4" :sm="3" :md="3" :lg="3">
<div class="overviewItem"> <div class="small-base">
<img class="small-panel-pic" src="~assets/dashboard/overview03.png" alt="" />
<div class="small-base">
<div class="small-title">全场实时无功</div>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmreactivepower}}</span>
<span>kvar</span>
</div>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="8" :md="8" :lg="4"> <div class="small-value">
<div class="overviewItem"> <span class="content-number">{{realData.attributeMap.windfarmavgwindspeed}}</span>
<img class="small-panel-pic" src="~assets/dashboard/overview04.png" alt="" /> <span>m/s</span>
<div class="small-base"> </div>
<div class="small-title">日发电量</div> <div class="small-title">平均风速</div>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmdayprodenergy}}</span>
<span>kWh</span>
</div> </div>
</div> </el-col>
</div> <el-col :xs="3" :sm="4" :md="4" :lg="4">
</el-col> <div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmactivepower}}</span>
<span>kW</span>
</div>
<div class="small-title">实时有功</div>
</div>
</el-col>
<el-col :xs="4" :sm="4" :md="4" :lg="4">
<div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmreactivepower}}</span>
<span>kvar</span>
</div>
<div class="small-title">实时无功</div>
</div>
</el-col>
<el-col :xs="4" :sm="4" :md="4" :lg="4">
<div class="small-base">
<el-col :xs="12" :sm="8" :md="8" :lg="4"> <div class="small-value">
<div class="overviewItem"> <span class="content-number">{{realData.attributeMap.windfarmdayprodenergy}}</span>
<img class="small-panel-pic" src="~assets/dashboard/overview05.png" alt="" /> <span>万kWh</span>
<div class="small-base"> </div>
<div class="small-title">本月发电量</div> <div class="small-title">日发电量</div>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmmonthprodenergy}}</span>
<span>kWh</span>
</div> </div>
</div> </el-col>
<el-col :xs="4" :sm="4" :md="4" :lg="4">
<div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmmonthprodenergy}}</span>
<span>万kWh</span>
</div>
<div class="small-title">本月发电量</div>
</div>
</el-col>
<el-col :xs="4" :sm="4" :md="4" :lg="4">
<div class="small-base" style="border: none;">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmyearprodenergy}}</span>
<span>万kWh</span>
</div>
<div class="small-title">年发电量</div>
</div>
</el-col>
</div> </div>
</el-col> </el-col>
<el-col :xs="12" :sm="8" :md="8" :lg="4"> <el-col :xs="24" :sm="24" :md="24" :lg="8">
<div class="overviewItem" style="margin-right: 0px;"> <div class="overviewItem">
<img class="small-panel-pic" src="~assets/dashboard/overview06.png" alt="" /> <el-col :xs="3" :sm="3" :md="3" :lg="3">
<div class="small-base"> <img class="small-panel-pic" src="~assets/dashboard/overview08.png" alt="" />
<div class="small-title">年发电量</div> </el-col>
<div class="small-value">
<span class="content-number">{{realData.attributeMap.windfarmyearprodenergy}}</span> <el-col :xs="4" :sm="4" :md="4" :lg="4">
<span>kWh</span> <div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.turbinecountpowerprod}}</span>
<span></span>
</div>
<div class="small-title">并网台数</div>
</div> </div>
</div> </el-col>
<el-col :xs="6" :sm="6" :md="6" :lg="6">
<div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.turbinecountidle}}</span>
<span></span>
</div>
<div class="small-title">待机台数</div>
</div>
</el-col>
<el-col :xs="6" :sm="6" :md="6" :lg="6">
<div class="small-base">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.turbinecountdisconnected}}</span>
<span></span>
</div>
<div class="small-title">断联台数</div>
</div>
</el-col>
<el-col :xs="6" :sm="5" :md="5" :lg="5">
<div class="small-base" style="border: none;">
<div class="small-value">
<span class="content-number">{{realData.attributeMap.turbinecountservice}}</span>
<span></span>
</div>
<div class="small-title">维护台数</div>
</div>
</el-col>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
@ -125,9 +160,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, onActivated, onMounted, reactive, ref, onBeforeMount, onUnmounted, VNodeRef } from 'vue' import { onMounted, reactive, ref, onUnmounted } from 'vue'
import * as echarts from 'echarts'
import { useTemplateRefsList, useEventListener } from '@vueuse/core'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import WindContent from '/@/views/backend/home/windMatrix.vue' import WindContent from '/@/views/backend/home/windMatrix.vue'
import { equipList } from '/@/api/backend/realData/request' import { equipList } from '/@/api/backend/realData/request'
@ -156,6 +189,11 @@ const attributeList = ref({
'windfarmdayprodenergy', 'windfarmdayprodenergy',
'windfarmmonthprodenergy', 'windfarmmonthprodenergy',
'windfarmyearprodenergy', 'windfarmyearprodenergy',
'turbinecountpowerprod',
'turbinecountidle',
'turbinecountdisconnected',
'turbinecountservice'
] ]
}) })
@ -174,9 +212,33 @@ const overviewList = () => {
res.data.attributeMap.windfarmactivepower = formatAttributeValue(res.data.attributeMap.windfarmactivepower) res.data.attributeMap.windfarmactivepower = formatAttributeValue(res.data.attributeMap.windfarmactivepower)
res.data.attributeMap.windfarmreactivepower = formatAttributeValue(res.data.attributeMap.windfarmreactivepower) res.data.attributeMap.windfarmreactivepower = formatAttributeValue(res.data.attributeMap.windfarmreactivepower)
res.data.attributeMap.windfarmavgwindspeed = formatAttributeValue(res.data.attributeMap.windfarmavgwindspeed) res.data.attributeMap.windfarmavgwindspeed = formatAttributeValue(res.data.attributeMap.windfarmavgwindspeed)
res.data.attributeMap.windfarmdayprodenergy = formatAttributeValue(res.data.attributeMap.windfarmdayprodenergy) res.data.attributeMap.windfarmdayprodenergy = formatAttributeValue(res.data.attributeMap.windfarmdayprodenergy/10000)
res.data.attributeMap.windfarmmonthprodenergy = formatAttributeValue(res.data.attributeMap.windfarmmonthprodenergy) res.data.attributeMap.windfarmmonthprodenergy = formatAttributeValue(res.data.attributeMap.windfarmmonthprodenergy/10000)
res.data.attributeMap.windfarmyearprodenergy = formatAttributeValue(res.data.attributeMap.windfarmyearprodenergy) res.data.attributeMap.windfarmyearprodenergy = formatAttributeValue(res.data.attributeMap.windfarmyearprodenergy/10000)
res.data.attributeMap.turbinecountpowerprod =
res.data.attributeMap.turbinecountpowerprod !== undefined
? res.data.attributeMap.turbinecountpowerprod % 1 === 0
? res.data.attributeMap.turbinecountpowerprod
: res.data.attributeMap.turbinecountpowerprod.toFixed(0)
: '0'
res.data.attributeMap.turbinecountidle =
res.data.attributeMap.turbinecountidle !== undefined
? res.data.attributeMap.turbinecountidle % 1 === 0
? res.data.attributeMap.turbinecountidle
: res.data.attributeMap.turbinecountidle.toFixed(0)
: '0'
res.data.attributeMap.turbinecountdisconnected =
res.data.attributeMap.turbinecountdisconnected !== undefined
? res.data.attributeMap.turbinecountdisconnected % 1 === 0
? res.data.attributeMap.turbinecountdisconnected
: res.data.attributeMap.turbinecountdisconnected.toFixed(0)
: '0'
res.data.attributeMap.turbinecountservice =
res.data.attributeMap.turbinecountservice !== undefined
? res.data.attributeMap.turbinecountservice % 1 === 0
? res.data.attributeMap.turbinecountservice
: res.data.attributeMap.turbinecountservice.toFixed(0)
: '0'
const data: any = { const data: any = {
windFarmId: res.data.windFarmId, windFarmId: res.data.windFarmId,
attributeMap: { attributeMap: {
@ -185,7 +247,11 @@ const overviewList = () => {
windfarmavgwindspeed: res.data.attributeMap.windfarmavgwindspeed, windfarmavgwindspeed: res.data.attributeMap.windfarmavgwindspeed,
windfarmdayprodenergy: res.data.attributeMap.windfarmdayprodenergy, windfarmdayprodenergy: res.data.attributeMap.windfarmdayprodenergy,
windfarmmonthprodenergy: res.data.attributeMap.windfarmmonthprodenergy, windfarmmonthprodenergy: res.data.attributeMap.windfarmmonthprodenergy,
windfarmyearprodenergy: res.data.attributeMap.windfarmyearprodenergy windfarmyearprodenergy: res.data.attributeMap.windfarmyearprodenergy,
turbinecountpowerprod: res.data.attributeMap.turbinecountpowerprod,
turbinecountidle: res.data.attributeMap.turbinecountidle,
turbinecountdisconnected: res.data.attributeMap.turbinecountdisconnected,
turbinecountservice: res.data.attributeMap.turbinecountservice
}, },
} }
@ -327,9 +393,6 @@ const StatusListData = () => {
}) })
} }
const timestampToTime = (timestamp: any) => { const timestampToTime = (timestamp: any) => {
timestamp = timestamp ? timestamp : null timestamp = timestamp ? timestamp : null
let date = new Date(timestamp) let date = new Date(timestamp)
@ -510,13 +573,13 @@ $labelHeight: 30px;
background-color: #f2f3f5; background-color: #f2f3f5;
.el-row { .el-row {
width: calc(100% - 0px); width: calc(100% - 0px);
.el-col { /* .el-col {
height: calc(100% - 10px); height: calc(100% - 10px);
} }*/
} }
.content-number { .content-number {
color: #333333; color: #333333;
font-size: 24px; font-size: 22px;
} }
.homelabel { .homelabel {
font-family: PingFangSC-Semibold; font-family: PingFangSC-Semibold;
@ -529,7 +592,7 @@ $labelHeight: 30px;
display: block; display: block;
} }
.overview { .overview {
width: calc(100% - 10px); width: calc(100% - 5px);
height: 100%; height: 100%;
.overviewItem{ .overviewItem{
height: 100px; height: 100px;
@ -543,6 +606,10 @@ $labelHeight: 30px;
width: 80px; width: 80px;
height: 80px; height: 80px;
} }
.small-base{
text-align: center;
border-right: 1px #eeeeee solid;
}
} }
} }
@ -612,7 +679,21 @@ $labelHeight: 30px;
} }
} }
} }
@media screen and (max-width: 1280px) {
.default-main {
font-size: 12px !important;
.content-number {
font-size: 16px !important;
}
.overviewItem{
.small-panel-pic{
width: 40px!important;
height: 40px!important;
}
}
}
}
@media screen and (max-width: 1360px) { @media screen and (max-width: 1360px) {
@ -632,7 +713,14 @@ $labelHeight: 30px;
.default-main { .default-main {
/*font-size: 12px !important;*/ /*font-size: 12px !important;*/
.content-number { .content-number {
font-size: 18px !important; font-size: 16px !important;
}
.overviewItem{
.small-panel-pic{
width: 60px!important;
height: 60px!important;
}
} }
.homelabel { .homelabel {

View File

@ -157,54 +157,54 @@
</el-table> </el-table>
</el-main> </el-main>
</el-container> </el-container>
<el-dialog v-model="multiTaskVisible" :title="mutiTaskTitle" width="400" :close-on-click-modal="false">
<el-row v-for="item in mutiTaskList" :key="item.sendData.deviceId">
<el-col :span="18">
<div class="mutiTaskName">
{{ item.deviceName }}
</div>
</el-col>
<el-col :span="6">
<div class="mutiTaskStatus">
<el-icon style="color: #f56c6c" size="30" v-if="item.loading === 3">
<CircleClose />
</el-icon>
<el-icon style="color: #06b429" size="30" v-if="item.loading === 2">
<CircleCheck />
</el-icon>
<el-icon style="color: #4fa5ff" size="30" class="mutiTaskLoading" v-if="item.loading === 1">
<Loading />
</el-icon>
<div v-if="item.loading === 0">等待发送</div>
</div>
</el-col>
</el-row>
</el-dialog>
<el-dialog v-model="selectPointVisible" title="选择测点" width="1000">
<SelectPoint ref="selectPointDialogRef" :defaultAttr="defaultAttr" :visible="selectPointVisible"></SelectPoint>
<template #footer>
<div class="selectPointDialogFooter">
<el-button type="primary" @click="saveSelectPoint">保存</el-button>
<el-button @click="selectPointVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="realDataLineChartVisible" title="实时曲线" @close="closeLineChart" width="1000">
<RealDataChart
ref="realDataChartRef"
:visible="realDataLineChartVisible"
:id="clickRow!.irn"
@clearChart="() => (linePause = false)"
></RealDataChart>
<template #header>
<div>
<span style="font-size: 18px">实时曲线</span>
<el-button class="saveBtn" @click="saveLineChart" type="primary" plain>保存</el-button>
<el-button v-if="linePause" class="continueBtn" @click="continueLineChart" type="primary" plain>继续</el-button>
</div>
</template>
</el-dialog>
</div> </div>
<el-dialog v-model="multiTaskVisible" :title="mutiTaskTitle" width="400" :close-on-click-modal="false">
<el-row v-for="item in mutiTaskList" :key="item.sendData.deviceId">
<el-col :span="18">
<div class="mutiTaskName">
{{ item.deviceName }}
</div>
</el-col>
<el-col :span="6">
<div class="mutiTaskStatus">
<el-icon style="color: #f56c6c" size="30" v-if="item.loading === 3">
<CircleClose />
</el-icon>
<el-icon style="color: #06b429" size="30" v-if="item.loading === 2">
<CircleCheck />
</el-icon>
<el-icon style="color: #4fa5ff" size="30" class="mutiTaskLoading" v-if="item.loading === 1">
<Loading />
</el-icon>
<div v-if="item.loading === 0">等待发送</div>
</div>
</el-col>
</el-row>
</el-dialog>
<el-dialog v-model="selectPointVisible" title="选择测点" width="1000">
<SelectPoint ref="selectPointDialogRef" :defaultAttr="defaultAttr" :visible="selectPointVisible"></SelectPoint>
<template #footer>
<div class="selectPointDialogFooter">
<el-button type="primary" @click="saveSelectPoint">保存</el-button>
<el-button @click="selectPointVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="realDataLineChartVisible" title="实时曲线" @close="closeLineChart" width="1000">
<RealDataChart
ref="realDataChartRef"
:visible="realDataLineChartVisible"
:id="clickRow!.irn"
@clearChart="() => (linePause = false)"
></RealDataChart>
<template #header>
<div>
<span style="font-size: 18px">实时曲线</span>
<el-button class="saveBtn" @click="saveLineChart" type="primary" plain>保存</el-button>
<el-button v-if="linePause" class="continueBtn" @click="continueLineChart" type="primary" plain>继续</el-button>
</div>
</template>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -694,7 +694,6 @@ const openMeasure = () => {
const saveSelectPoint = () => { const saveSelectPoint = () => {
const list = selectPointDialogRef.value?.getSelectList() const list = selectPointDialogRef.value?.getSelectList()
if (list) { if (list) {
const addCoulmn = list.map((item: any) => { const addCoulmn = list.map((item: any) => {
return { return {
label: item.unit ? item.attributeName + item.unit : item.attributeName, label: item.unit ? item.attributeName + item.unit : item.attributeName,

View File

@ -2,7 +2,10 @@
<div class="FanList-content"> <div class="FanList-content">
<el-row :gutter="10"> <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"> <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)"> <div class="grid-content ep-bg-purple"
@click="handleClick(item)"
@contextmenu.prevent="windContextMenu($event,item)"
>
<div class="FanList-panel" :class="item.standard == true ? 'wind-mark' : 'wind-default'"> <div class="FanList-panel" :class="item.standard == true ? 'wind-mark' : 'wind-default'">
<div class="fanlist-top"> <div class="fanlist-top">
<span :class="item.standard == true ? 'wind-mark-icon' : 'fanlist-icon'"> <span :class="item.standard == true ? 'wind-mark-icon' : 'fanlist-icon'">
@ -71,13 +74,37 @@
</div> </div>
</el-col> </el-col>
</el-row> </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.iturbineoperationmode !== 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>
</div>
</template>
</ContextMenu>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, defineEmits, onMounted, onUnmounted } from 'vue' import {defineProps, defineEmits, onMounted, onUnmounted, ref} from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { adminBaseRoutePath } from '/@/router/static/adminBase' 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 router = useRouter()
const props = defineProps({ const props = defineProps({
@ -126,6 +153,79 @@ const handleClick = (row) => {
}, },
}) })
} }
const OperateVisible = ref(false)
const contextMenuPos = ref({
x: 0,
y: 0,
})
const realTimeData = ref<any>({
iturbineoperationmode: 1111,
locked: 0,
deviceId: '',
name:''
})
const windContextMenu = (event: any,curnodeData) => {
contextMenuPos.value.x = event.pageX
contextMenuPos.value.y = event.pageY
realTimeData.value.iturbineoperationmode=curnodeData.attributeMap.iturbineoperationmode
realTimeData.value.locked=curnodeData.attributeMap.locked
realTimeData.value.deviceId=curnodeData.irn
realTimeData.value.name=curnodeData.name
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> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -247,10 +347,10 @@ const handleClick = (row) => {
text-align: center; text-align: center;
top: 5px; top: 5px;
left: 17px; left: 17px;
z-index: 3; /* z-index: 3;*/
} }
.leafs { .leafs {
z-index: 1; /* z-index: 1;*/
position: absolute; position: absolute;
/* animation: leafRotate 1s infinite linear;*/ /* animation: leafRotate 1s infinite linear;*/
transform-origin: center center; transform-origin: center center;
@ -313,6 +413,17 @@ const handleClick = (row) => {
} }
} }
} }
.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) { @media screen and (max-width: 1680px) {