Merge branch 'main' of https://git.jsspisoft.com/ry-das
This commit is contained in:
commit
1f01735820
13
das/src/main/java/com/das/modules/cache/domain/IotFieldInfoCache.java
vendored
Normal file
13
das/src/main/java/com/das/modules/cache/domain/IotFieldInfoCache.java
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.das.modules.cache.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class IotFieldInfoCache {
|
||||||
|
private String attributeCode;
|
||||||
|
private String attributeName;
|
||||||
|
private Integer attributeType;
|
||||||
|
private Integer porder;
|
||||||
|
private Integer highspeed;
|
||||||
|
private Integer datatype;
|
||||||
|
}
|
12
das/src/main/java/com/das/modules/cache/domain/IotModelInfoCache.java
vendored
Normal file
12
das/src/main/java/com/das/modules/cache/domain/IotModelInfoCache.java
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.das.modules.cache.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class IotModelInfoCache {
|
||||||
|
private Long iotModelId;
|
||||||
|
private String iodModelCode;
|
||||||
|
private ConcurrentHashMap<String,IotFieldInfoCache> fieldInfoCache;
|
||||||
|
}
|
@ -10,4 +10,10 @@ public interface CacheService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
EquipmentCache getEquipmentCache();
|
EquipmentCache getEquipmentCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取物模型缓存接口
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IotModelCache getIotModelCache();
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,10 @@ public interface EquipmentCache {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
DeviceInfoCache getDeviceInfoCacheById(Long deviceId);
|
DeviceInfoCache getDeviceInfoCacheById(Long deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除指定设备缓存
|
||||||
|
* @param deviceId
|
||||||
|
*/
|
||||||
|
void removeDeviceCache(Long deviceId);
|
||||||
}
|
}
|
||||||
|
5
das/src/main/java/com/das/modules/cache/service/IotModelCache.java
vendored
Normal file
5
das/src/main/java/com/das/modules/cache/service/IotModelCache.java
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.das.modules.cache.service;
|
||||||
|
|
||||||
|
public interface IotModelCache {
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ 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.EquipmentCache;
|
import com.das.modules.cache.service.EquipmentCache;
|
||||||
|
import com.das.modules.cache.service.IotModelCache;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -9,10 +10,20 @@ import org.springframework.stereotype.Service;
|
|||||||
public class CacheServiceImpl implements CacheService {
|
public class CacheServiceImpl implements CacheService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
EquipmentCache equipmentCache;;
|
EquipmentCache equipmentCache;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
IotModelCache iotModelCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EquipmentCache getEquipmentCache() {
|
public EquipmentCache getEquipmentCache() {
|
||||||
return equipmentCache;
|
return equipmentCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IotModelCache getIotModelCache() {
|
||||||
|
return iotModelCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -110,4 +110,13 @@ public class EquipmentCacheImpl implements EquipmentCache {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeDeviceCache(Long deviceId) {
|
||||||
|
Integer index = deviceIdIndex.get(deviceId);
|
||||||
|
if (index != null) {
|
||||||
|
deviceInfoCaches.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
24
das/src/main/java/com/das/modules/cache/service/impl/IotModelCacheImpl.java
vendored
Normal file
24
das/src/main/java/com/das/modules/cache/service/impl/IotModelCacheImpl.java
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.das.modules.cache.service.impl;
|
||||||
|
|
||||||
|
import com.das.modules.cache.service.IotModelCache;
|
||||||
|
import com.das.modules.equipment.mapper.SysIotModelMapper;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class IotModelCacheImpl implements IotModelCache {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
SysIotModelMapper sysIotModelMapper;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void destroy(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package com.das.modules.calc.functions;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUnit;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.das.modules.cache.domain.DeviceInfoCache;
|
||||||
|
import com.das.modules.cache.service.CacheService;
|
||||||
|
import com.das.modules.data.domain.SnapshotValueQueryParam;
|
||||||
|
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.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aviator扩展函数 - 获取时间维度内最早的一条数据
|
||||||
|
* 函数格式: topv(deviceId, attr, timedim)
|
||||||
|
* timedim: day - 天, month - 月, year - 年
|
||||||
|
* 返回值:数值, nil - 获取错误
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FunctionTopValue extends AbstractFunction {
|
||||||
|
|
||||||
|
private DataService dataService = null;
|
||||||
|
private CacheService cacheService = null;
|
||||||
|
|
||||||
|
private ConcurrentHashMap<String,CacheValue> cacheValues = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public FunctionTopValue(DataService dataService, CacheService cacheService) {
|
||||||
|
this.dataService = dataService;
|
||||||
|
this.cacheService = cacheService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "topv";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AviatorObject call(Map<String, Object> env, AviatorObject deviceCode, AviatorObject attr, AviatorObject timeDim) {
|
||||||
|
//设备Code
|
||||||
|
String code = (String)deviceCode.getValue(env);
|
||||||
|
String attrName = (String)attr.getValue(env);
|
||||||
|
String timeDimName = (String)timeDim.getValue(env);
|
||||||
|
|
||||||
|
DeviceInfoCache deviceInfoCache = cacheService.getEquipmentCache().getDeviceInfoCacheByCode(code);
|
||||||
|
if (deviceInfoCache == null) {
|
||||||
|
return AviatorNil.NIL;
|
||||||
|
}
|
||||||
|
String key = String.format("%d_%s_%s", deviceInfoCache.getDeviceId(), attrName, timeDimName);
|
||||||
|
//根据维度,获取维度时间
|
||||||
|
Date curTimeValue = null;
|
||||||
|
switch (timeDimName) {
|
||||||
|
case "day":
|
||||||
|
curTimeValue = DateUtil.beginOfDay(DateUtil.date());
|
||||||
|
break;
|
||||||
|
case "month":
|
||||||
|
curTimeValue = DateUtil.beginOfMonth(DateUtil.date());
|
||||||
|
break;
|
||||||
|
case "year":
|
||||||
|
curTimeValue = DateUtil.beginOfYear(DateUtil.date());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AviatorNil.NIL;
|
||||||
|
}
|
||||||
|
CacheValue cacheValue = cacheValues.get(key);
|
||||||
|
if (cacheValue != null) {
|
||||||
|
//缓存中存在,检查是否过期
|
||||||
|
if (cacheValue.getCurTimeValue() != null && DateUtil.compare(cacheValue.getCurTimeValue(), curTimeValue) == 0) {
|
||||||
|
return AviatorRuntimeJavaType.valueOf(cacheValue.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//未找到缓存,查询时序API获取数据
|
||||||
|
return AviatorRuntimeJavaType.valueOf(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class CacheValue{
|
||||||
|
private Double value;
|
||||||
|
private Date curTimeValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ public class CalcJob implements Job {
|
|||||||
}
|
}
|
||||||
Expression expression = instance.getCachedExpressionByKey(calcModule.getName());
|
Expression expression = instance.getCachedExpressionByKey(calcModule.getName());
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
|
log.error("expression is null, calcModule={}", calcModule.getName());
|
||||||
throw new JobExecutionException("expression is null");
|
throw new JobExecutionException("expression is null");
|
||||||
}
|
}
|
||||||
Map<String,Object> envs = expression.newEnv("G_DEVICES", cacheService.getEquipmentCache().getDevicesCache());
|
Map<String,Object> envs = expression.newEnv("G_DEVICES", cacheService.getEquipmentCache().getDevicesCache());
|
||||||
|
@ -126,6 +126,7 @@ public class CalcService {
|
|||||||
try{
|
try{
|
||||||
//预编译脚本
|
//预编译脚本
|
||||||
aviator.compile(scriptModule.getName(), scriptModule.getScript(), true);
|
aviator.compile(scriptModule.getName(), scriptModule.getScript(), true);
|
||||||
|
log.info("[预编译脚本] - {}", scriptModule.getName());
|
||||||
startCalcJob(scriptModule);
|
startCalcJob(scriptModule);
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.das.modules.data.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RTValue {
|
||||||
|
private Object value;
|
||||||
|
private Long time;
|
||||||
|
}
|
@ -17,5 +17,5 @@ public interface DataService {
|
|||||||
|
|
||||||
void updateCalFieldData(List<CalculateRTData> values);
|
void updateCalFieldData(List<CalculateRTData> values);
|
||||||
|
|
||||||
|
Double getTimeTopValue(Long devcieId, String attr, long startTime, long endTime);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.das.common.utils.PageDataInfo;
|
import com.das.common.utils.PageDataInfo;
|
||||||
import com.das.modules.data.domain.DeviceEventInfo;
|
import com.das.modules.data.domain.DeviceEventInfo;
|
||||||
|
import com.das.modules.data.domain.RTValue;
|
||||||
import com.das.modules.equipment.domain.vo.IotModelFieldVo;
|
import com.das.modules.equipment.domain.vo.IotModelFieldVo;
|
||||||
import com.das.modules.node.domain.bo.CalculateRTData;
|
import com.das.modules.node.domain.bo.CalculateRTData;
|
||||||
import com.das.modules.node.domain.bo.RTData;
|
import com.das.modules.node.domain.bo.RTData;
|
||||||
@ -681,7 +682,7 @@ public class TDEngineService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pageSize != null) {
|
if (pageSize != null) {
|
||||||
sb.append(" limit ").append(offset).append(",").append(pageSize);
|
sb.append(" desc limit ").append(offset).append(",").append(pageSize);
|
||||||
total = getEventCount(eventLevel, startTime, endTime, deviceCodeList);
|
total = getEventCount(eventLevel, startTime, endTime, deviceCodeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,6 +703,7 @@ public class TDEngineService {
|
|||||||
deviceEventInfo.setConfirmTime(rs.getLong("confirm_time"));
|
deviceEventInfo.setConfirmTime(rs.getLong("confirm_time"));
|
||||||
deviceEventInfo.setDeviceCode(rs.getString("device_code"));
|
deviceEventInfo.setDeviceCode(rs.getString("device_code"));
|
||||||
deviceEventInfo.setDeviceId(rs.getString("device_id"));
|
deviceEventInfo.setDeviceId(rs.getString("device_id"));
|
||||||
|
deviceEventInfo.setDeviceName(rs.getString("device_name"));
|
||||||
result.add(deviceEventInfo);
|
result.add(deviceEventInfo);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -781,4 +783,27 @@ public class TDEngineService {
|
|||||||
hikariDataSource.close();
|
hikariDataSource.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Double getTimeTopValue(String tableName, String attr, long startTime, long endTime) {
|
||||||
|
StringBuffer sb = new StringBuffer(256);
|
||||||
|
sb.append("select ");
|
||||||
|
sb.append("first(");
|
||||||
|
sb.append(attr);
|
||||||
|
sb.append(") as value");
|
||||||
|
sb.append(" from ");
|
||||||
|
sb.append(tableName);
|
||||||
|
sb.append(" where ");
|
||||||
|
sb.append(String.format(" updatetime >= %d and updatetime < %d ", startTime, endTime));
|
||||||
|
Double result = null;
|
||||||
|
try (Connection conn = hikariDataSource.getConnection();
|
||||||
|
Statement smt = conn.createStatement();
|
||||||
|
ResultSet rs = smt.executeQuery(sb.toString())) {
|
||||||
|
if (rs.next()) {
|
||||||
|
result = rs.getDouble("value");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取数据异常", e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollectionUtil;
|
|||||||
import cn.hutool.core.collection.ListUtil;
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import com.das.common.exceptions.ServiceException;
|
import com.das.common.exceptions.ServiceException;
|
||||||
import com.das.common.utils.AdminRedisTemplate;
|
import com.das.common.utils.AdminRedisTemplate;
|
||||||
|
import com.das.modules.cache.domain.DeviceInfoCache;
|
||||||
|
import com.das.modules.cache.service.CacheService;
|
||||||
import com.das.modules.data.domain.SnapshotValueQueryParam;
|
import com.das.modules.data.domain.SnapshotValueQueryParam;
|
||||||
import com.das.modules.data.domain.TSValueQueryParam;
|
import com.das.modules.data.domain.TSValueQueryParam;
|
||||||
import com.das.modules.data.service.DataService;
|
import com.das.modules.data.service.DataService;
|
||||||
@ -19,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StopWatch;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -45,6 +48,9 @@ public class DataServiceImpl implements DataService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
SysIotModelMapper sysIotModelMapper;
|
SysIotModelMapper sysIotModelMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CacheService cacheService;
|
||||||
|
|
||||||
//key:deviceId value:modelCode
|
//key:deviceId value:modelCode
|
||||||
public ConcurrentHashMap<String, String> deviceModelMap = new ConcurrentHashMap<>(10000);
|
public ConcurrentHashMap<String, String> deviceModelMap = new ConcurrentHashMap<>(10000);
|
||||||
|
|
||||||
@ -141,7 +147,8 @@ public class DataServiceImpl implements DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Map<String, Map<String, Object>>> queryHistoryCurveValues(Long irn, Date startTime, Date endTime, String interval, String fill, List<String> attributes) {
|
private Map<String, Map<String, Map<String, Object>>> queryHistoryCurveValues(Long irn, Date startTime, Date endTime, String interval, String fill, List<String> attributes) {
|
||||||
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
stopWatch.start("prepare resources");
|
||||||
String iotModelCode = sysIotModelFieldMapper.queryModelCodeByDeviceId(irn);
|
String iotModelCode = sysIotModelFieldMapper.queryModelCodeByDeviceId(irn);
|
||||||
Map<String, Object> highSpeedFieldMap = highIotFieldMap.get(iotModelCode);
|
Map<String, Object> highSpeedFieldMap = highIotFieldMap.get(iotModelCode);
|
||||||
Map<String, Object> lowSpeedFieldMap = lowIotFieldMap.get(iotModelCode);
|
Map<String, Object> lowSpeedFieldMap = lowIotFieldMap.get(iotModelCode);
|
||||||
@ -160,11 +167,15 @@ public class DataServiceImpl implements DataService {
|
|||||||
calField.add(field);
|
calField.add(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
stopWatch.start("HighSpeedValues");
|
||||||
Map<String, Map<String, Map<String, Object>>> result = new HashMap<>();
|
Map<String, Map<String, Map<String, Object>>> result = new HashMap<>();
|
||||||
if (!CollectionUtils.isEmpty(highSpeedField)) {
|
if (!CollectionUtils.isEmpty(highSpeedField)) {
|
||||||
Map<String, Map<String, Map<String, Object>>> highHistoryCurve = tdEngineService.fetchHighHistoryCurve(irn, startTime, endTime, interval, highSpeedField);
|
Map<String, Map<String, Map<String, Object>>> highHistoryCurve = tdEngineService.fetchHighHistoryCurve(irn, startTime, endTime, interval, highSpeedField);
|
||||||
result.putAll(highHistoryCurve);
|
result.putAll(highHistoryCurve);
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
stopWatch.start("LowSpeedValues");
|
||||||
if (!CollectionUtils.isEmpty(lowSpeedField)) {
|
if (!CollectionUtils.isEmpty(lowSpeedField)) {
|
||||||
Map<String, Map<String, Map<String, Object>>> lowHistoryCurve = tdEngineService.fetchLowHistoryCurve(irn, startTime, endTime, interval, lowSpeedField);
|
Map<String, Map<String, Map<String, Object>>> lowHistoryCurve = tdEngineService.fetchLowHistoryCurve(irn, startTime, endTime, interval, lowSpeedField);
|
||||||
if (result.get(irn.toString()) == null) {
|
if (result.get(irn.toString()) == null) {
|
||||||
@ -173,6 +184,8 @@ public class DataServiceImpl implements DataService {
|
|||||||
result.get(irn.toString()).putAll(lowHistoryCurve.get(irn.toString()));
|
result.get(irn.toString()).putAll(lowHistoryCurve.get(irn.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
stopWatch.start("CalculateValues");
|
||||||
if (!CollectionUtils.isEmpty(calField)){
|
if (!CollectionUtils.isEmpty(calField)){
|
||||||
ListUtil.page(calField,COMMIT_COUNT,list -> {
|
ListUtil.page(calField,COMMIT_COUNT,list -> {
|
||||||
for (String item : list){
|
for (String item : list){
|
||||||
@ -185,6 +198,8 @@ public class DataServiceImpl implements DataService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
log.debug("查询历史数据耗时: {}", stopWatch.prettyPrint());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,4 +251,21 @@ public class DataServiceImpl implements DataService {
|
|||||||
tdEngineService.initIotModel(allIotModel, highIotFieldMap, lowIotFieldMap, calculateIotFieldMap);
|
tdEngineService.initIotModel(allIotModel, highIotFieldMap, lowIotFieldMap, calculateIotFieldMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定时间区间内的最早的数据
|
||||||
|
* @param devcieId
|
||||||
|
* @param attr
|
||||||
|
* @param startTime
|
||||||
|
* @param endTime
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Double getTimeTopValue(Long devcieId, String attr, long startTime, long endTime){
|
||||||
|
DeviceInfoCache deviceInfoCacheById = cacheService.getEquipmentCache().getDeviceInfoCacheById(devcieId);
|
||||||
|
if (deviceInfoCacheById == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String tableName = "";
|
||||||
|
return tdEngineService.getTimeTopValue(tableName, attr, startTime, endTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import com.das.common.utils.PageQuery;
|
|||||||
import com.das.common.utils.SequenceUtils;
|
import com.das.common.utils.SequenceUtils;
|
||||||
import com.das.modules.auth.domain.vo.SysUserVo;
|
import com.das.modules.auth.domain.vo.SysUserVo;
|
||||||
import com.das.modules.auth.mapper.SysOrgMapper;
|
import com.das.modules.auth.mapper.SysOrgMapper;
|
||||||
|
import com.das.modules.cache.service.CacheService;
|
||||||
import com.das.modules.data.service.impl.DataServiceImpl;
|
import com.das.modules.data.service.impl.DataServiceImpl;
|
||||||
import com.das.modules.equipment.domain.dto.SysEquipmentDto;
|
import com.das.modules.equipment.domain.dto.SysEquipmentDto;
|
||||||
import com.das.modules.equipment.domain.excel.SysEquipmentExcel;
|
import com.das.modules.equipment.domain.excel.SysEquipmentExcel;
|
||||||
@ -62,6 +63,9 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DataServiceImpl dataService;
|
private DataServiceImpl dataService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CacheService cacheService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysEquipmentVo creatSysEquipment(SysEquipmentDto sysEquipmentDto) {
|
public SysEquipmentVo creatSysEquipment(SysEquipmentDto sysEquipmentDto) {
|
||||||
//去除空格
|
//去除空格
|
||||||
@ -84,6 +88,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
if (sysEquipment.getIotModelId() != null){
|
if (sysEquipment.getIotModelId() != null){
|
||||||
dataService.deviceModelMap.put(sysEquipment.getId().toString(),dataService.iotModelMap.get(sysEquipment.getIotModelId().toString()));
|
dataService.deviceModelMap.put(sysEquipment.getId().toString(),dataService.iotModelMap.get(sysEquipment.getIotModelId().toString()));
|
||||||
}
|
}
|
||||||
|
//更新设备缓存
|
||||||
|
cacheService.getEquipmentCache().refreshDeviceCache(sysEquipment.getId());
|
||||||
SysEquipmentVo sysEquipmentVo = new SysEquipmentVo();
|
SysEquipmentVo sysEquipmentVo = new SysEquipmentVo();
|
||||||
BeanCopyUtils.copy(sysEquipment, sysEquipmentVo);
|
BeanCopyUtils.copy(sysEquipment, sysEquipmentVo);
|
||||||
return sysEquipmentVo;
|
return sysEquipmentVo;
|
||||||
@ -111,6 +117,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
if (oldModelSysEquipInfo.getIotModelId() == null && sysEquipment.getIotModelId() != null){
|
if (oldModelSysEquipInfo.getIotModelId() == null && sysEquipment.getIotModelId() != null){
|
||||||
dataService.deviceModelMap.put(sysEquipment.getId().toString(),dataService.iotModelMap.get(sysEquipment.getIotModelId().toString()));
|
dataService.deviceModelMap.put(sysEquipment.getId().toString(),dataService.iotModelMap.get(sysEquipment.getIotModelId().toString()));
|
||||||
}
|
}
|
||||||
|
//更新设备缓存
|
||||||
|
cacheService.getEquipmentCache().refreshDeviceCache(sysEquipment.getId());
|
||||||
SysEquipmentVo sysEquipmentVo = new SysEquipmentVo();
|
SysEquipmentVo sysEquipmentVo = new SysEquipmentVo();
|
||||||
BeanCopyUtils.copy(sysEquipment, sysEquipmentVo);
|
BeanCopyUtils.copy(sysEquipment, sysEquipmentVo);
|
||||||
return sysEquipmentVo;
|
return sysEquipmentVo;
|
||||||
@ -124,6 +132,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
}
|
}
|
||||||
sysEquipmentMapper.deleteById(sysEquipmentDto.getId());
|
sysEquipmentMapper.deleteById(sysEquipmentDto.getId());
|
||||||
//删除缓存
|
//删除缓存
|
||||||
|
//更新设备缓存
|
||||||
|
cacheService.getEquipmentCache().refreshDeviceCache(sysEquipmentDto.getId());
|
||||||
dataService.deviceModelMap.remove(sysEquipmentDto.getId().toString());
|
dataService.deviceModelMap.remove(sysEquipmentDto.getId().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +307,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
String modelCode = dataService.iotModelMap.get(item.getIotModelId().toString());
|
String modelCode = dataService.iotModelMap.get(item.getIotModelId().toString());
|
||||||
dataService.deviceModelMap.put(item.getId().toString(),modelCode);
|
dataService.deviceModelMap.put(item.getId().toString(),modelCode);
|
||||||
}
|
}
|
||||||
|
//更新设备缓存
|
||||||
|
cacheService.getEquipmentCache().refreshDeviceCache(item.getId());
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(updateSysEquipmentList)) {
|
if (CollectionUtils.isNotEmpty(updateSysEquipmentList)) {
|
||||||
sysEquipmentMapper.updateBatchById(updateSysEquipmentList);
|
sysEquipmentMapper.updateBatchById(updateSysEquipmentList);
|
||||||
@ -305,16 +317,17 @@ public class SysEquipmentServiceImpl implements SysEquipmentService {
|
|||||||
String modelCode = dataService.iotModelMap.get(item.getIotModelId().toString());
|
String modelCode = dataService.iotModelMap.get(item.getIotModelId().toString());
|
||||||
dataService.deviceModelMap.put(item.getId().toString(),modelCode);
|
dataService.deviceModelMap.put(item.getId().toString(),modelCode);
|
||||||
}
|
}
|
||||||
|
//更新设备缓存
|
||||||
|
cacheService.getEquipmentCache().refreshDeviceCache(item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(delSysEquipmentList)) {
|
if (CollectionUtils.isNotEmpty(delSysEquipmentList)) {
|
||||||
// 删除设备
|
// 删除设备
|
||||||
sysEquipmentMapper.deleteBatchIds(delSysEquipmentList);
|
sysEquipmentMapper.deleteBatchIds(delSysEquipmentList);
|
||||||
for (SysEquipment item : updateSysEquipmentList){
|
for (SysEquipment item : delSysEquipmentList){
|
||||||
if (item.getIotModelId() != null){
|
dataService.deviceModelMap.remove(item.getId().toString());
|
||||||
String modelCode = dataService.iotModelMap.get(item.getIotModelId().toString());
|
//更新设备缓存
|
||||||
dataService.deviceModelMap.put(item.getId().toString(),modelCode);
|
cacheService.getEquipmentCache().removeDeviceCache(item.getId());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.lmax.disruptor.BlockingWaitStrategy;
|
||||||
import com.lmax.disruptor.RingBuffer;
|
import com.lmax.disruptor.RingBuffer;
|
||||||
import com.lmax.disruptor.YieldingWaitStrategy;
|
import com.lmax.disruptor.YieldingWaitStrategy;
|
||||||
import com.lmax.disruptor.dsl.Disruptor;
|
import com.lmax.disruptor.dsl.Disruptor;
|
||||||
@ -95,7 +96,7 @@ public class NodeMessageServiceImpl extends TextWebSocketHandler implements Node
|
|||||||
//初始化高性能队列
|
//初始化高性能队列
|
||||||
int cpu = Runtime.getRuntime().availableProcessors();
|
int cpu = Runtime.getRuntime().availableProcessors();
|
||||||
int bufferSize = 1024 * 4;
|
int bufferSize = 1024 * 4;
|
||||||
disruptor = new Disruptor<>(TerminalMessage::new, bufferSize, DaemonThreadFactory.INSTANCE, ProducerType.MULTI, new YieldingWaitStrategy());
|
disruptor = new Disruptor<>(TerminalMessage::new, bufferSize, DaemonThreadFactory.INSTANCE, ProducerType.MULTI, new BlockingWaitStrategy());
|
||||||
//
|
//
|
||||||
TerminalMessageWorkerHandler[] workerHandlers = new TerminalMessageWorkerHandler[cpu];
|
TerminalMessageWorkerHandler[] workerHandlers = new TerminalMessageWorkerHandler[cpu];
|
||||||
for (int i = 0; i < cpu; i++) {
|
for (int i = 0; i < cpu; i++) {
|
||||||
|
@ -34,5 +34,11 @@ public class HomeWindTurbineMatrixDataVoVo {
|
|||||||
*/
|
*/
|
||||||
private Double nominalCapacity;
|
private Double nominalCapacity;
|
||||||
|
|
||||||
|
private String deviceCode;
|
||||||
|
|
||||||
private Map<String,Object> attributeMap;
|
private Map<String,Object> attributeMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import java.util.List;
|
|||||||
public interface TemperatureDashboardService {
|
public interface TemperatureDashboardService {
|
||||||
/**
|
/**
|
||||||
* 根据设备id获取该设备对应的温度相关测点的限制配置信息
|
* 根据设备id获取该设备对应的温度相关测点的限制配置信息
|
||||||
* @param deviceId 设备id
|
* @param temperatureLimitDto 设备信息
|
||||||
* @return 限制配置列表(如果限制未设置 则不返回对应测点信息)
|
* @return 限制配置列表(如果限制未设置 则不返回对应测点信息)
|
||||||
*/
|
*/
|
||||||
List<TemperatureLimitVo> getTemperatureLimitByDeviceId(TemperatureLimitDto temperatureLimitDto);
|
List<TemperatureLimitVo> getTemperatureLimitByDeviceId(TemperatureLimitDto temperatureLimitDto);
|
||||||
|
@ -82,6 +82,7 @@ public class HomeServiceImpl implements HomeService {
|
|||||||
homeWindRealTimeVoResult.setIrn(item.getId());
|
homeWindRealTimeVoResult.setIrn(item.getId());
|
||||||
homeWindRealTimeVoResult.setName(item.getName());
|
homeWindRealTimeVoResult.setName(item.getName());
|
||||||
homeWindRealTimeVoResult.setModel(item.getModel());
|
homeWindRealTimeVoResult.setModel(item.getModel());
|
||||||
|
homeWindRealTimeVoResult.setDeviceCode(item.getCode());
|
||||||
homeWindRealTimeVoResult.setModelId(item.getIotModelId());
|
homeWindRealTimeVoResult.setModelId(item.getIotModelId());
|
||||||
homeWindRealTimeVoResult.setBelongLine(item.getBelongLine());
|
homeWindRealTimeVoResult.setBelongLine(item.getBelongLine());
|
||||||
homeWindRealTimeVoResult.setStandard(item.getStandard());
|
homeWindRealTimeVoResult.setStandard(item.getStandard());
|
||||||
|
@ -9,10 +9,7 @@ import com.das.modules.page.service.TemperatureDashboardService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class TemperatureDashboardServiceImpl implements TemperatureDashboardService {
|
public class TemperatureDashboardServiceImpl implements TemperatureDashboardService {
|
||||||
@ -62,7 +59,8 @@ public class TemperatureDashboardServiceImpl implements TemperatureDashboardServ
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ArrayList<TemperatureLimitVo> temperatureLimitVos = new ArrayList<>(map.values());
|
||||||
return new ArrayList<>(map.values());
|
temperatureLimitVos.sort(Comparator.comparing(TemperatureLimitVo::getMeasPointName));
|
||||||
|
return temperatureLimitVos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,16 +40,16 @@ spring:
|
|||||||
# 多个文件总大小
|
# 多个文件总大小
|
||||||
max-request-size: 2048MB
|
max-request-size: 2048MB
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://192.168.109.102:5432/das
|
url: jdbc:postgresql://192.168.109.187:5432/das
|
||||||
username: das
|
username: das
|
||||||
password: qwaszx12
|
password: qwaszx12
|
||||||
# # redis相关配置
|
# # redis相关配置
|
||||||
data:
|
data:
|
||||||
redis:
|
redis:
|
||||||
host: 192.168.109.195
|
host: 192.168.109.187
|
||||||
database: 0
|
database: 0
|
||||||
port: 6379
|
port: 6379
|
||||||
password:
|
password: zaq12WSX
|
||||||
client-type: lettuce
|
client-type: lettuce
|
||||||
|
|
||||||
|
|
||||||
|
4
ui/.gitignore
vendored
Normal file
4
ui/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.idea
|
||||||
|
das-dn/.vscode
|
||||||
|
ui/**/dist
|
||||||
|
das/**/target
|
@ -43,8 +43,12 @@
|
|||||||
<div class="tabsPart">
|
<div class="tabsPart">
|
||||||
<el-table :data="alarmsTableData" class="tablePart" highlight-current-row>
|
<el-table :data="alarmsTableData" class="tablePart" highlight-current-row>
|
||||||
<el-table-column prop="eventTimeFormate" :label="AlarmsFieldsEnums['alarmTime']" align="center"> </el-table-column>
|
<el-table-column prop="eventTimeFormate" :label="AlarmsFieldsEnums['alarmTime']" align="center"> </el-table-column>
|
||||||
<el-table-column prop="deviceCode" :label="AlarmsFieldsEnums['airBlowerNumber']" align="center"> </el-table-column>
|
<el-table-column prop="devicecodeName" :label="AlarmsFieldsEnums['airBlowerNumber']" align="center"> </el-table-column>
|
||||||
<el-table-column prop="eventText" :label="AlarmsFieldsEnums['faultDescription']" align="center"> </el-table-column>
|
<el-table-column prop="eventText" :label="AlarmsFieldsEnums['faultDescription']" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-html="formatText(row.eventText)"></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="eventLevel" :label="AlarmsFieldsEnums['alarmType']" align="center">
|
<el-table-column prop="eventLevel" :label="AlarmsFieldsEnums['alarmType']" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="tip" v-if="scope.row.eventLevel === 0">提示</div>
|
<div class="tip" v-if="scope.row.eventLevel === 0">提示</div>
|
||||||
@ -199,6 +203,7 @@ const getalarmsList = () => {
|
|||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
eventTimeFormate: timestampToTime(item.eventTime),
|
eventTimeFormate: timestampToTime(item.eventTime),
|
||||||
|
devicecodeName: item.deviceName + item.deviceCode,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -209,6 +214,13 @@ const getalarmsList = () => {
|
|||||||
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatText = (text: any) => {
|
||||||
|
text = text.replace(/ 动作/g, '<span style="color:#a03b1d;"> 动作</span>')
|
||||||
|
text = text.replace(/复归/g, '<span style="color:#39baf4;">复归</span>')
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
@mouseout="hideButton"
|
@mouseout="hideButton"
|
||||||
>
|
>
|
||||||
<span>{{item.eventTimeFormate}}</span>
|
<span>{{item.eventTimeFormate}}</span>
|
||||||
<span>{{item.deviceCode}}</span>
|
<span>{{item.deviceName}}</span>
|
||||||
<span>{{item.eventText}}</span>
|
<span>{{item.eventText}}</span>
|
||||||
<span v-show="showConfirmButton" >
|
<span v-show="showConfirmButton" >
|
||||||
<a style="color: #0277b3; cursor: pointer;" @click="open(item)" >确认</a>
|
<a style="color: #0277b3; cursor: pointer;" @click="open(item)" >确认</a>
|
||||||
@ -346,8 +346,7 @@ const getTableData = (deviceCode) => {
|
|||||||
startTime: new Date(new Date().toLocaleDateString()).getTime(),
|
startTime: new Date(new Date().toLocaleDateString()).getTime(),
|
||||||
endTime: Date.now(),
|
endTime: Date.now(),
|
||||||
deviceCode: deviceCode,
|
deviceCode: deviceCode,
|
||||||
limit: 100,
|
// eventLevel:2
|
||||||
eventLevel:2
|
|
||||||
}
|
}
|
||||||
// console.log(JSON.stringify(data))
|
// console.log(JSON.stringify(data))
|
||||||
getAlarmListReq(data).then((res) => {
|
getAlarmListReq(data).then((res) => {
|
||||||
|
@ -537,17 +537,17 @@ const getTableData = () => {
|
|||||||
multipleSelection.value.forEach(item => {
|
multipleSelection.value.forEach(item => {
|
||||||
if (item.attributeCode) {
|
if (item.attributeCode) {
|
||||||
const attributeCodeLower = item.attributeCode.toLowerCase();
|
const attributeCodeLower = item.attributeCode.toLowerCase();
|
||||||
// if(attributeCodeLower==='ipitchangle1'||attributeCodeLower==='ipitchangle2'||attributeCodeLower==='ipitchangle3'){
|
if(item.unit==""||item.unit==undefined){
|
||||||
/* tableColumnEnds.value.push({
|
tableColumnEnds.value.push({
|
||||||
label: '变桨角度',
|
label: item.attributeName,
|
||||||
unit:'',
|
unit:item.unit,
|
||||||
prop: 'ipitchangle',
|
prop: attributeCodeLower,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
custom: 'header',
|
custom: 'header',
|
||||||
name: 'ipitchangle',
|
name: item.attributeCode,
|
||||||
title: '变桨角度',
|
title: item.attributeName,
|
||||||
});*/
|
});
|
||||||
//}else{
|
}else{
|
||||||
tableColumnEnds.value.push({
|
tableColumnEnds.value.push({
|
||||||
label: item.attributeName+'\n'+item.unit,
|
label: item.attributeName+'\n'+item.unit,
|
||||||
unit:item.unit,
|
unit:item.unit,
|
||||||
@ -557,7 +557,8 @@ const getTableData = () => {
|
|||||||
name: item.attributeCode,
|
name: item.attributeCode,
|
||||||
title: item.attributeName,
|
title: item.attributeName,
|
||||||
});
|
});
|
||||||
//}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="statAnalysis">
|
<div class="statAnalysis">
|
||||||
<el-menu :default-active="activeIndex" class="headerList" mode="horizontal" @select="handleSelect">
|
<el-menu :default-active="activeIndex" class="headerList" mode="horizontal" @select="handleSelect">
|
||||||
<el-menu-item v-for="(item, index) in headerList" :index="index" :key="index"> {{ item }} </el-menu-item>
|
<el-menu-item index="0" key="0"> {{ headerList[0] }} </el-menu-item>
|
||||||
|
<el-popover placement="top-start" :width="200" popper-class="admin-info-box" trigger="hover" content="同一测点,不同时间段对比">
|
||||||
|
<template #reference>
|
||||||
|
<el-menu-item index="1" key="1"> {{ headerList[1] }} </el-menu-item>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
<el-popover placement="top-start" :width="200" popper-class="admin-info-box" trigger="hover" content="同一时间段,不同测点对比">
|
||||||
|
<template #reference>
|
||||||
|
<el-menu-item index="2" key="2"> {{ headerList[2] }} </el-menu-item>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<PowerCurveAnalysis v-if="activeIndex == 0"></PowerCurveAnalysis>
|
<PowerCurveAnalysis v-if="activeIndex == 0"></PowerCurveAnalysis>
|
||||||
<TrendAnalysis v-if="activeIndex == 1"></TrendAnalysis>
|
<TrendAnalysis v-if="activeIndex == 1"></TrendAnalysis>
|
||||||
@ -19,7 +29,6 @@ const config = useConfig()
|
|||||||
const activeIndex = ref(0)
|
const activeIndex = ref(0)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const headerList = [t('statAnalysis.PowerCurveAnalysis'), t('statAnalysis.trendAnalysis'), t('statAnalysis.trendComparison')]
|
const headerList = [t('statAnalysis.PowerCurveAnalysis'), t('statAnalysis.trendAnalysis'), t('statAnalysis.trendComparison')]
|
||||||
|
|
||||||
const handleSelect = (index: number) => {
|
const handleSelect = (index: number) => {
|
||||||
activeIndex.value = index
|
activeIndex.value = index
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -199,7 +199,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="timeColumns" :class="{ expand: isExpand }">
|
<div class="timeColumns">
|
||||||
<div class="headerPart" v-for="(time, index) in times" :key="index">
|
<div class="headerPart" v-for="(time, index) in times" :key="index">
|
||||||
<div class="topLeft">
|
<div class="topLeft">
|
||||||
<div class="selectPart">
|
<div class="selectPart">
|
||||||
@ -75,10 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="times.length > 2" class="ralIcon" @click="handleClick">
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
<el-icon :size="20" color="#0064AA"><DArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
|
||||||
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="measureSlotHeader">
|
<div class="measureSlotHeader">
|
||||||
@ -131,10 +128,6 @@ const timechange = (value: any) => {
|
|||||||
ElMessage.warning('查询时间点错误,请重新输入')
|
ElMessage.warning('查询时间点错误,请重新输入')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isExpand = ref(false)
|
|
||||||
const handleClick = () => {
|
|
||||||
isExpand.value = !isExpand.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const iotModelId = ref('')
|
const iotModelId = ref('')
|
||||||
const irn = ref('')
|
const irn = ref('')
|
||||||
@ -258,7 +251,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -396,14 +389,27 @@ const historyDataReq = (promises: any) => {
|
|||||||
const deviceId = statAnalysisSelect.deviceId
|
const deviceId = statAnalysisSelect.deviceId
|
||||||
const attributeCode = statAnalysisSelect.attributeCode
|
const attributeCode = statAnalysisSelect.attributeCode
|
||||||
results.forEach((res: any, index: number) => {
|
results.forEach((res: any, index: number) => {
|
||||||
|
console.log(times[index])
|
||||||
const resData = (res && deviceId in res && res[deviceId][attributeCode]) || undefined
|
const resData = (res && deviceId in res && res[deviceId][attributeCode]) || undefined
|
||||||
const xData = resData['times']
|
|
||||||
const yData = resData['values']
|
if (!resData['values'].length) {
|
||||||
if (!yData.length) {
|
|
||||||
ElMessage.info(`${customName[index]}数据为空`)
|
ElMessage.info(`${customName[index]}数据为空`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
calculate.value[index] = calculateStats(yData)
|
const alltimes = getTimestamps(
|
||||||
|
new Date(times[index][0]).getTime(),
|
||||||
|
new Date(times[index][1]).getTime(),
|
||||||
|
statAnalysisSelect.interval || '5m'
|
||||||
|
)
|
||||||
|
console.log(alltimes)
|
||||||
|
console.log('🚀 ~ results.forEach ~ resData:', resData)
|
||||||
|
const fillData = fillMissingData(alltimes, resData)
|
||||||
|
console.log('🚀 ~ results.forEach ~ fillData:', fillData)
|
||||||
|
|
||||||
|
const xData = fillData['times']
|
||||||
|
const yData = fillData['values']
|
||||||
|
console.log(xData)
|
||||||
|
calculate.value[index] = calculateStats(resData['values'])
|
||||||
xDatas.push({
|
xDatas.push({
|
||||||
series: String(customName[index]),
|
series: String(customName[index]),
|
||||||
data: xData,
|
data: xData,
|
||||||
@ -484,6 +490,52 @@ function calculateStats(numbers: any) {
|
|||||||
average: average.toFixed(2),
|
average: average.toFixed(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTimestamps = (start: any, end: any, interval: any) => {
|
||||||
|
let timestamps = []
|
||||||
|
let current = start
|
||||||
|
|
||||||
|
while (current < end) {
|
||||||
|
timestamps.push(current)
|
||||||
|
switch (interval) {
|
||||||
|
case '5m':
|
||||||
|
current += 5 * 60 * 1000
|
||||||
|
break
|
||||||
|
case '1d':
|
||||||
|
current += 24 * 60 * 60 * 1000
|
||||||
|
break
|
||||||
|
case '15m':
|
||||||
|
current += 15 * 60 * 1000
|
||||||
|
break
|
||||||
|
case 'NONE':
|
||||||
|
current += 40 * 1000
|
||||||
|
break
|
||||||
|
case '1h':
|
||||||
|
current += 60 * 60 * 1000
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported interval')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return timestamps
|
||||||
|
}
|
||||||
|
|
||||||
|
const fillMissingData = (intervals: any, data: any) => {
|
||||||
|
const { times, values } = data
|
||||||
|
const filledTimes: any = []
|
||||||
|
const filledValues: any = []
|
||||||
|
intervals.forEach((time: any) => {
|
||||||
|
const index = times.indexOf(time)
|
||||||
|
filledTimes.push(time)
|
||||||
|
if (index !== -1) {
|
||||||
|
filledValues.push(values[index])
|
||||||
|
} else {
|
||||||
|
filledValues.push('')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { times: filledTimes, values: filledValues }
|
||||||
|
}
|
||||||
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)
|
||||||
@ -498,6 +550,9 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.statAnalysis {
|
.statAnalysis {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.contain {
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
}
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -572,24 +627,11 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timeColumns {
|
.timeColumns {
|
||||||
max-height: 120px;
|
height: calc(100% - 480px);
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 10px 20px;
|
padding: 2px 20px;
|
||||||
}
|
}
|
||||||
&.expand {
|
|
||||||
max-height: max-content;
|
|
||||||
height: auto;
|
|
||||||
overflow: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.timeColumns.expand + div.ralIcon {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
.ralIcon {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
}
|
||||||
#myEChart {
|
#myEChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="timeColumns" :class="{ expand: isExpand }">
|
<div class="timeColumns">
|
||||||
<div class="headerPart" v-for="(deviceId, index) in statAnalysisDeviceId" :key="index">
|
<div class="headerPart" v-for="(deviceId, index) in statAnalysisDeviceId" :key="index">
|
||||||
<div class="topLeft">
|
<div class="topLeft">
|
||||||
<div class="selectPart">
|
<div class="selectPart">
|
||||||
@ -81,10 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="statAnalysisDeviceId.length > 2" class="ralIcon" @click="handleClick">
|
<div ref="chartContainer" style="position: absolute; bottom: 0px; width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
||||||
<el-icon :size="20" color="#0064AA"><DArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div ref="chartContainer" style="width: 100%; height: 400px; border: 1px solid rgb(217, 217, 217)"></div>
|
|
||||||
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="measureSlotHeader">
|
<div class="measureSlotHeader">
|
||||||
@ -141,10 +138,6 @@ const switchDevice = (index: number) => {
|
|||||||
calculate.value.splice(index, 1)
|
calculate.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExpand = ref(false)
|
|
||||||
const handleClick = () => {
|
|
||||||
isExpand.value = !isExpand.value
|
|
||||||
}
|
|
||||||
const iotModelId = ref('')
|
const iotModelId = ref('')
|
||||||
const irn = ref('')
|
const irn = ref('')
|
||||||
const selectAtteibutes = (index: number) => {
|
const selectAtteibutes = (index: number) => {
|
||||||
@ -260,7 +253,7 @@ const shortcuts = [
|
|||||||
text: '今天',
|
text: '今天',
|
||||||
value: () => {
|
value: () => {
|
||||||
const start = getFormattedDate(0) + ' 00:00:00'
|
const start = getFormattedDate(0) + ' 00:00:00'
|
||||||
const end = new Date()
|
const end = getFormattedDate(0) + ' 23:59:59'
|
||||||
return [start, end]
|
return [start, end]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -457,6 +450,9 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.statAnalysis {
|
.statAnalysis {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.contain {
|
||||||
|
height: calc(100% - 60px);
|
||||||
|
}
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -531,24 +527,11 @@ const timestampToTime = (timestamp: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timeColumns {
|
.timeColumns {
|
||||||
max-height: 120px;
|
height: calc(100% - 480px);
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
.headerPart {
|
.headerPart {
|
||||||
padding: 10px 20px;
|
padding: 2px 20px;
|
||||||
}
|
}
|
||||||
&.expand {
|
|
||||||
max-height: max-content;
|
|
||||||
height: auto;
|
|
||||||
overflow: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.timeColumns.expand + div.ralIcon {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
.ralIcon {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
}
|
||||||
#myEChart {
|
#myEChart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
Loading…
Reference in New Issue
Block a user