diff --git a/das/src/main/java/com/das/modules/auth/controller/SysMenusController.java b/das/src/main/java/com/das/modules/auth/controller/SysMenusController.java index 45b33017..75bd2071 100644 --- a/das/src/main/java/com/das/modules/auth/controller/SysMenusController.java +++ b/das/src/main/java/com/das/modules/auth/controller/SysMenusController.java @@ -41,6 +41,9 @@ public class SysMenusController { if(!hasPermission){ return R.fail("没有系统管理权限"); } + if (!sysMenuDto.getMenuName().matches("^[a-zA-Z]*$")){ + return R.fail("菜单名称,必须为英文"); + } return R.success(sysMenuService.createMenu(sysMenuDto)); } @@ -55,7 +58,7 @@ public class SysMenusController { if(!hasPermission){ return R.fail("没有系统管理权限"); } - if (StringUtils.isAllEnglishLetters(sysMenuDto.getMenuName())){ + if (!sysMenuDto.getMenuName().matches("^[a-zA-Z]*$")){ return R.fail("菜单名称,必须为英文"); } sysMenuService.updateMenu(sysMenuDto); diff --git a/das/src/main/java/com/das/modules/data/service/DataService.java b/das/src/main/java/com/das/modules/data/service/DataService.java index 7d1e75e6..4cd55fdc 100644 --- a/das/src/main/java/com/das/modules/data/service/DataService.java +++ b/das/src/main/java/com/das/modules/data/service/DataService.java @@ -49,12 +49,12 @@ public class DataService { //为空查全部 List sysIotModelFields = sysIotModelFieldMapper.queryAllFiledNames(Long.valueOf(snapshotValueQueryParam.getDeviceId())); for (String item : sysIotModelFields) { - String key = String.format("RT:[%s]:[%s]", snapshotValueQueryParam.getDeviceId(), item); + String key = String.format("RT:%s:%s", snapshotValueQueryParam.getDeviceId(), item); keyList.add(key); } } else { for (String item : attributes) { - String key = String.format("RT:[%s]:[%s]", snapshotValueQueryParam.getDeviceId(), item); + String key = String.format("RT:%s:%s", snapshotValueQueryParam.getDeviceId(), item); keyList.add(key); } } @@ -62,12 +62,10 @@ public class DataService { List dataList = adminRedisTemplate.mGet(keyList); for (int i = 0; i < keyList.size(); i++) { String key = keyList.get(i); - int firstColonIndex = key.indexOf('['); - int firstIndex = key.indexOf(']'); - int secondIndex = key.indexOf(']', firstIndex + 1); - int secondColonIndex = key.indexOf('[', firstColonIndex + 1); - String deviceId = key.substring(firstColonIndex + 1, firstIndex); - String fieldName = key.substring(secondColonIndex + 1, secondIndex); + int firstColonIndex = key.indexOf(':'); + int secondColonIndex = key.indexOf(':', firstColonIndex + 1); + String deviceId = key.substring(firstColonIndex + 1, secondColonIndex); + String fieldName = key.substring(secondColonIndex + 1); if (finalResult.get(deviceId) == null) { Map valueMap = new HashMap<>(); valueMap.put(fieldName, dataList.get(i)); diff --git a/das/src/main/java/com/das/modules/equipment/controller/SysEnumController.java b/das/src/main/java/com/das/modules/equipment/controller/SysEnumController.java index ba161a15..dda36d3f 100644 --- a/das/src/main/java/com/das/modules/equipment/controller/SysEnumController.java +++ b/das/src/main/java/com/das/modules/equipment/controller/SysEnumController.java @@ -62,6 +62,23 @@ public class SysEnumController { } + /** 更新枚举值 */ + @PostMapping("/updateEnumValues") + public R updateEnumValues(@RequestBody SysEnumValuesDto sysEnumValuesDto) { + //判断是否有权限 + boolean hasPermission = StpUtil.hasPermission(SysAuthorityIds.SYS_AUTHORITY_ID_DEVICE_MGR.toString()); + if(!hasPermission){ + return R.fail("没有设备管理权限"); + } + if (sysEnumValuesDto.getEnumTypeId() ==null && StringUtils.isBlank(sysEnumValuesDto.getValue()) + || sysEnumValuesDto.getOrderNumber() == null || sysEnumValuesDto.getIsActive() ==null || + sysEnumValuesDto.getId() ==null) { + throw new ServiceException("参数缺失"); + } + SysEnumValuesVo sysEnumValuesVo = sysEnumService.updateEnumValues(sysEnumValuesDto); + return R.success(sysEnumValuesVo); + } + /** * 查询枚举类型列表 * @@ -72,7 +89,7 @@ public class SysEnumController { } /** - * 查询枚举类型列表 + * 查询枚举值列表 * * */ @PostMapping("/queryEnumValuesList") diff --git a/das/src/main/java/com/das/modules/equipment/domain/vo/SysEnumValuesVo.java b/das/src/main/java/com/das/modules/equipment/domain/vo/SysEnumValuesVo.java index 836102ad..ff847d10 100644 --- a/das/src/main/java/com/das/modules/equipment/domain/vo/SysEnumValuesVo.java +++ b/das/src/main/java/com/das/modules/equipment/domain/vo/SysEnumValuesVo.java @@ -19,6 +19,10 @@ public class SysEnumValuesVo { * 关联到枚举类型表的ID */ private Long enumTypeId; + /** + * 关联到枚举类型表的ID字符串类型 + */ + private String enumTypeIdStr; /** * 枚举值的具体内容 diff --git a/das/src/main/java/com/das/modules/equipment/mapper/SysEnumTypesMapper.java b/das/src/main/java/com/das/modules/equipment/mapper/SysEnumTypesMapper.java index 1bbc8308..b1706778 100644 --- a/das/src/main/java/com/das/modules/equipment/mapper/SysEnumTypesMapper.java +++ b/das/src/main/java/com/das/modules/equipment/mapper/SysEnumTypesMapper.java @@ -1,9 +1,13 @@ package com.das.modules.equipment.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.das.modules.equipment.domain.dto.SysEnumTypesDto; import com.das.modules.equipment.entity.SysEnumTypes; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; @Mapper public interface SysEnumTypesMapper extends BaseMapper { + + Long queryEnumTypesByName(@Param("sysDto") SysEnumTypesDto sysDto); } diff --git a/das/src/main/java/com/das/modules/equipment/service/SysEnumService.java b/das/src/main/java/com/das/modules/equipment/service/SysEnumService.java index 596cc9c9..ce4f13e1 100644 --- a/das/src/main/java/com/das/modules/equipment/service/SysEnumService.java +++ b/das/src/main/java/com/das/modules/equipment/service/SysEnumService.java @@ -14,6 +14,8 @@ public interface SysEnumService { SysEnumValuesVo addEnumValues(SysEnumValuesDto sysEnumValuesDto); + SysEnumValuesVo updateEnumValues(SysEnumValuesDto sysEnumValuesDto); + List queryEnumTypesList(); PageDataInfo queryEnumValuesList(SysEnumValuesDto sysEnumValuesDto); diff --git a/das/src/main/java/com/das/modules/equipment/service/impl/SysEnumServiceImpl.java b/das/src/main/java/com/das/modules/equipment/service/impl/SysEnumServiceImpl.java index 1d2c7abe..12e9b263 100644 --- a/das/src/main/java/com/das/modules/equipment/service/impl/SysEnumServiceImpl.java +++ b/das/src/main/java/com/das/modules/equipment/service/impl/SysEnumServiceImpl.java @@ -1,8 +1,10 @@ package com.das.modules.equipment.service.impl; import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.das.common.config.SessionUtil; +import com.das.common.exceptions.ServiceException; import com.das.common.utils.BeanCopyUtils; import com.das.common.utils.PageDataInfo; import com.das.common.utils.PageQuery; @@ -35,13 +37,18 @@ public class SysEnumServiceImpl implements SysEnumService { /** 新增枚举类型 */ @Override public SysEnumTypesVo addEnumTypes(SysEnumTypesDto sysEnumTypesDto) { + //判断枚举类型,是否重复 + Long count = sysEnumTypesMapper.queryEnumTypesByName(sysEnumTypesDto); + if (count >0){ + throw new ServiceException("枚举类型,不可重复!"); + } SysEnumTypes sysEnumTypes = new SysEnumTypes(); BeanCopyUtils.copy(sysEnumTypesDto, sysEnumTypes); SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY); - sysEnumTypes.setCreatedTime(new Date()); - sysEnumTypes.setUpdatedTime(new Date()); sysEnumTypes.setCreatedBy(sysUserVo.getAccount()); sysEnumTypes.setUpdatedBy(sysUserVo.getAccount()); + sysEnumTypes.setCreatedTime(new Date()); + sysEnumTypes.setUpdatedTime(new Date()); sysEnumTypes.setRevision(1); sysEnumTypesMapper.insert(sysEnumTypes); SysEnumTypesVo sysEnumTypesVo = new SysEnumTypesVo(); @@ -54,11 +61,18 @@ public class SysEnumServiceImpl implements SysEnumService { public SysEnumValuesVo addEnumValues(SysEnumValuesDto sysEnumValuesDto) { SysEnumValues sysEnumValues = new SysEnumValues(); BeanCopyUtils.copy(sysEnumValuesDto,sysEnumValues); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("enum_type_id",sysEnumValuesDto.getEnumTypeId()); + queryWrapper.eq("description",sysEnumValuesDto.getDescription()); + Long count = sysEnumValuesMapper.selectCount(queryWrapper); + if (count >0){ + throw new ServiceException("枚举值描述,不可重复!"); + } SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY); - sysEnumValues.setCreatedTime(new Date()); - sysEnumValues.setUpdatedTime(new Date()); sysEnumValues.setCreatedBy(sysUserVo.getAccount()); sysEnumValues.setUpdatedBy(sysUserVo.getAccount()); + sysEnumValues.setCreatedTime(new Date()); + sysEnumValues.setUpdatedTime(new Date()); sysEnumValues.setRevision(1); sysEnumValuesMapper.insert(sysEnumValues); SysEnumValuesVo sysEnumValuesVo = new SysEnumValuesVo(); @@ -66,6 +80,26 @@ public class SysEnumServiceImpl implements SysEnumService { return sysEnumValuesVo; } + @Override + public SysEnumValuesVo updateEnumValues(SysEnumValuesDto sysEnumValuesDto) { + SysEnumValues sysEnumValues = new SysEnumValues(); + BeanCopyUtils.copy(sysEnumValuesDto,sysEnumValues); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("enum_type_id",sysEnumValuesDto.getEnumTypeId()); + queryWrapper.eq("description",sysEnumValuesDto.getDescription()); + Long count = sysEnumValuesMapper.selectCount(queryWrapper); + if (count >0){ + throw new ServiceException("枚举值描述,不可重复!"); + } + SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY); + sysEnumValues.setUpdatedBy(sysUserVo.getAccount()); + sysEnumValues.setUpdatedTime(new Date()); + sysEnumValuesMapper.updateById(sysEnumValues); + SysEnumValuesVo sysEnumValuesVo = new SysEnumValuesVo(); + BeanCopyUtils.copy(sysEnumValues, sysEnumValuesVo); + return sysEnumValuesVo; + } + /** * 查询枚举类型列表 * @return diff --git a/das/src/main/java/com/das/modules/equipment/service/impl/SysEquipmentServiceImpl.java b/das/src/main/java/com/das/modules/equipment/service/impl/SysEquipmentServiceImpl.java index c9be0752..159eb70a 100644 --- a/das/src/main/java/com/das/modules/equipment/service/impl/SysEquipmentServiceImpl.java +++ b/das/src/main/java/com/das/modules/equipment/service/impl/SysEquipmentServiceImpl.java @@ -60,6 +60,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService { @Override public SysEquipmentVo creatSysEquipment(SysEquipmentDto sysEquipmentDto) { + //去除空格 + sysEquipmentDto.setCode(sysEquipmentDto.getCode().replaceAll(" ", "")); SysEquipment sysEquipment = new SysEquipment(); BeanCopyUtils.copy(sysEquipmentDto, sysEquipment); @@ -81,6 +83,8 @@ public class SysEquipmentServiceImpl implements SysEquipmentService { @Override public SysEquipmentVo updateSysEquipment(SysEquipmentDto sysEquipmentDto) { + //去除空格 + sysEquipmentDto.setCode(sysEquipmentDto.getCode().replaceAll(" ", "")); SysEquipment sysEquipment = new SysEquipment(); BeanCopyUtils.copy(sysEquipmentDto, sysEquipment); SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY); diff --git a/das/src/main/java/com/das/modules/equipment/service/impl/SysIotModelServiceImpl.java b/das/src/main/java/com/das/modules/equipment/service/impl/SysIotModelServiceImpl.java index 18aed703..cddb1293 100644 --- a/das/src/main/java/com/das/modules/equipment/service/impl/SysIotModelServiceImpl.java +++ b/das/src/main/java/com/das/modules/equipment/service/impl/SysIotModelServiceImpl.java @@ -1,6 +1,7 @@ package com.das.modules.equipment.service.impl; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -25,6 +26,7 @@ import com.das.modules.equipment.mapper.SysIotModelFieldMapper; import com.das.modules.equipment.mapper.SysIotModelMapper; import com.das.modules.equipment.mapper.SysIotModelServiceMapper; import com.das.modules.equipment.service.SysIotModelService; +import com.das.modules.node.service.TDEngineService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -35,15 +37,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.List; +import java.util.*; @Transactional(rollbackFor = Exception.class) @Service @Slf4j public class SysIotModelServiceImpl implements SysIotModelService { + public static final int COMMIT_COUNT = 1000; @Autowired private SysIotModelMapper sysIotModelMapper; @@ -54,6 +54,8 @@ public class SysIotModelServiceImpl implements SysIotModelService { @Autowired private SysIotModelServiceMapper sysIotModelServiceMapper; + @Autowired + private TDEngineService tdEngineService; public SysIotModelVo creatSysIotModel(SysIotModelDto sysIotModelDto) { SysIotModel sysIotModel = new SysIotModel(); @@ -162,6 +164,8 @@ public class SysIotModelServiceImpl implements SysIotModelService { sysIotModelField.setDataType("tinyint"); } + //动态执行创建td超级表,字段 + createTdStableOrColumn(sysIotModelField); sysIotModelFieldMapper.insert(sysIotModelField); SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo(); BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo); @@ -188,6 +192,15 @@ public class SysIotModelServiceImpl implements SysIotModelService { } sysIotModelFieldMapper.updateById(sysIotModelField); + + SysIotModelField oldSysIotField = sysIotModelFieldMapper.selectById(sysIotModelFieldDto.getId()); + if (oldSysIotField == null){ + throw new ServiceException("未查找到该条记录"); + } + if (!oldSysIotField.getAttributeCode().equals(sysIotModelField.getAttributeCode()) && oldSysIotField.getDataType().equals(sysIotModelField.getDataType()) && Objects.equals(oldSysIotField.getHighSpeed(), sysIotModelField.getHighSpeed())){ + //更新td表结构 + updateTDStableOrColumn(sysIotModelField,oldSysIotField); + } SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo(); BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo); return sysIotModelFieldVo; @@ -195,6 +208,8 @@ public class SysIotModelServiceImpl implements SysIotModelService { @Override public void deleteSysIotModelField(SysIotModelFieldDto sysIotModelFieldDto) { + SysIotModelField sysIotModelField = sysIotModelFieldMapper.selectById(sysIotModelFieldDto.getId()); + deleteTDStableOrColumn(sysIotModelField); sysIotModelFieldMapper.deleteById(sysIotModelFieldDto.getId()); } @@ -401,11 +416,35 @@ public class SysIotModelServiceImpl implements SysIotModelService { } } } - sysIotModelFieldMapper.insertBatch(sysIotModelFieldList); + if (CollectionUtils.isNotEmpty(sysIotModelFieldList)) { + sysIotModelFieldMapper.insertBatch(sysIotModelFieldList); + ListUtil.page(sysIotModelFieldList, COMMIT_COUNT, create -> { + for (SysIotModelField item : create){ + createTdStableOrColumn(item); + } + }); + } if (CollectionUtils.isNotEmpty(updateSysIotModelFieldList)) { + ListUtil.page(updateSysIotModelFieldList, COMMIT_COUNT, update -> { + for (SysIotModelField item : update){ + SysIotModelField oldSysIotField = sysIotModelFieldMapper.selectById(item.getId()); + if (oldSysIotField != null){ + if (!oldSysIotField.getAttributeCode().equals(item.getAttributeCode()) && oldSysIotField.getDataType().equals(item.getDataType()) && Objects.equals(oldSysIotField.getHighSpeed(), item.getHighSpeed())){ + //更新td表结构 + updateTDStableOrColumn(item,oldSysIotField); + } + } + } + }); sysIotModelFieldMapper.updateBatchById(updateSysIotModelFieldList); + } if (CollectionUtils.isNotEmpty(delSysIotModelFieldList)) { + ListUtil.page(updateSysIotModelFieldList, COMMIT_COUNT, delete -> { + for (SysIotModelField item : delete){ + deleteTDStableOrColumn(item); + } + }); sysIotModelFieldMapper.deleteBatchIds(delSysIotModelFieldList); } } @@ -428,4 +467,70 @@ public class SysIotModelServiceImpl implements SysIotModelService { return list; } + public void createTdStableOrColumn(SysIotModelField sysIotModelField){ + //如果新增的是第一条记录 创建tdengine超级表 分为高频和低频 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("iot_model_id",sysIotModelField.getIotModelId()); + queryWrapper.eq("highspeed",sysIotModelField.getHighSpeed()); + List sysIotModelFields = sysIotModelFieldMapper.selectList(queryWrapper); + if (CollectionUtils.isEmpty(sysIotModelFields)){ + if (sysIotModelField.getHighSpeed() == 0){ + SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId()); + Map map = new HashMap<>(); + map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType()); + //创建低频超级表 + tdEngineService.createStable(sysIotModel.getIotModelCode(),"l_",map); + } + if (sysIotModelField.getHighSpeed() == 1){ + SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId()); + Map map = new HashMap<>(); + map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType()); + //创建高频超级表 + tdEngineService.createStable(sysIotModel.getIotModelCode(),"h_",map); + } + }else { + //stable已经存在,新增stable列 + if (sysIotModelField.getHighSpeed() == 0){ + SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId()); + Map map = new HashMap<>(); + map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType()); + //创建低频超级表 + tdEngineService.addStableColumn(sysIotModel.getIotModelCode(),"l_",map); + } + if (sysIotModelField.getHighSpeed() == 1){ + SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId()); + Map map = new HashMap<>(); + map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType()); + //创建高频超级表 + tdEngineService.addStableColumn(sysIotModel.getIotModelCode(),"h_",map); + } + } + } + + public void updateTDStableOrColumn(SysIotModelField sysIotModelField,SysIotModelField oldIotModelField){ + deleteTDStableOrColumn(oldIotModelField); + createTdStableOrColumn(sysIotModelField); + } + + public void deleteTDStableOrColumn(SysIotModelField sysIotModelField){ + String stableName = null; + SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId()); + if(sysIotModelField.getHighSpeed() == 0) { + stableName = "l_" + sysIotModel.getIotModelCode(); + } + if(sysIotModelField.getHighSpeed() == 1) { + stableName = "h_" + sysIotModel.getIotModelCode(); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("iot_model_id",sysIotModelField.getIotModelId()); + queryWrapper.eq("highspeed",sysIotModelField.getHighSpeed()); + List sysIotModelFields = sysIotModelFieldMapper.selectList(queryWrapper); + if (CollectionUtils.isNotEmpty(sysIotModelFields) && sysIotModelFields.size() > 1){ + tdEngineService.deleteColumn(stableName,sysIotModelField.getAttributeCode()); + } + //物模型属性只剩下最后一个删除表 + if (CollectionUtils.isNotEmpty(sysIotModelFields) && sysIotModelFields.size() == 1){ + tdEngineService.deleteStable(stableName); + } + } } diff --git a/das/src/main/java/com/das/modules/node/domain/vo/ConfigUpdateVo.java b/das/src/main/java/com/das/modules/node/domain/vo/ConfigUpdateVo.java index ac8e33e2..96c4713c 100644 --- a/das/src/main/java/com/das/modules/node/domain/vo/ConfigUpdateVo.java +++ b/das/src/main/java/com/das/modules/node/domain/vo/ConfigUpdateVo.java @@ -19,7 +19,7 @@ public class ConfigUpdateVo { private List links; - private List equipments; + private List equipments; public ConfigUpdateVo() { diff --git a/das/src/main/java/com/das/modules/node/mapper/SysImptabmappingMapper.java b/das/src/main/java/com/das/modules/node/mapper/SysImptabmappingMapper.java index b4e1a9ce..7bba68ef 100644 --- a/das/src/main/java/com/das/modules/node/mapper/SysImptabmappingMapper.java +++ b/das/src/main/java/com/das/modules/node/mapper/SysImptabmappingMapper.java @@ -28,7 +28,9 @@ public interface SysImptabmappingMapper extends BaseMapperPlus getEquipmentId(Long linkId); - List getIotModelFieldByEquipmentId(Long equipmentId); + List getIotModelFieldByDeviceId(@Param("deviceId") Long deviceId); + + List getIotModelServiceByDeviceId(@Param("deviceId") Long deviceId); List getIotModelServiceByEquipmentId(Long equipmentId); diff --git a/das/src/main/java/com/das/modules/node/service/TDEngineService.java b/das/src/main/java/com/das/modules/node/service/TDEngineService.java index d97ef9e2..44276b15 100644 --- a/das/src/main/java/com/das/modules/node/service/TDEngineService.java +++ b/das/src/main/java/com/das/modules/node/service/TDEngineService.java @@ -61,6 +61,7 @@ public class TDEngineService { /** * 创建超级表 */ + @Async public void createStable(String iotModelCode, String stableType, Map fieldNameTypeMap) { try (Connection conn = hikariDataSource.getConnection(); Statement pstmt = conn.createStatement()) { @@ -94,6 +95,7 @@ public class TDEngineService { /** * 新增超级表列 */ + @Async public void addStableColumn(String iotModelCode, String stableType, Map fieldNameTypeMap) { try (Connection conn = hikariDataSource.getConnection(); Statement pstmt = conn.createStatement()) { @@ -124,6 +126,7 @@ public class TDEngineService { /** * 删除超级表列 */ + @Async public void deleteColumn(String stableName, String fieldCode) { try (Connection conn = hikariDataSource.getConnection(); Statement pstmt = conn.createStatement()) { @@ -131,7 +134,7 @@ public class TDEngineService { sb.setLength(0); sb.append("ALTER STABLE "); sb.append(stableName); - sb.append(" DROP COLUMN"); + sb.append(" DROP COLUMN "); ; sb.append(fieldCode); sb.append(";"); @@ -149,6 +152,7 @@ public class TDEngineService { /** * 删除超级表 */ + @Async public void deleteStable(String stableName) { try (Connection conn = hikariDataSource.getConnection(); Statement pstmt = conn.createStatement()) { diff --git a/das/src/main/java/com/das/modules/node/service/impl/DataServiceImpl.java b/das/src/main/java/com/das/modules/node/service/impl/DataServiceImpl.java index 22eb2074..4d5a30a7 100644 --- a/das/src/main/java/com/das/modules/node/service/impl/DataServiceImpl.java +++ b/das/src/main/java/com/das/modules/node/service/impl/DataServiceImpl.java @@ -141,13 +141,12 @@ public class DataServiceImpl implements DataService { ObjectNode equipJsonNode = equipObjectMapper.convertValue(map, ObjectNode.class); List newIotModelFieldList = new ArrayList<>(); List newIotModelServiceList = new ArrayList<>(); - // 获取设备IOT地址 - String iotAddr = sysImptabmappingMapper.getIotAddrByEquipmentId(equipmentId); // 根据设备Id获取对应的物模型属性和动作 - List iotModelFieldList = sysImptabmappingMapper.getIotModelFieldByEquipmentId(equipmentId); + List iotModelFieldList = sysImptabmappingMapper.getIotModelFieldByDeviceId(equipmentId); + List iotModelServiceList = sysImptabmappingMapper.getIotModelServiceByDeviceId(equipmentId); if (!CollectionUtils.isEmpty(iotModelFieldList)) { for (IotModelVo info : iotModelFieldList) { - if (info.getServiceType() == null) { + NewIotModelVo newIotModelVo = new NewIotModelVo(); newIotModelVo.setName(info.getEquipmentAttribute()); newIotModelVo.setHighSpeed(info.getHighSpeed()); @@ -164,21 +163,23 @@ public class DataServiceImpl implements DataService { newIotModelVo.setType("yx"); } newIotModelFieldList.add(newIotModelVo); - } else if (info.getAttributeType() == null) { - NewIotModelVo newIotModelVo = new NewIotModelVo(); - newIotModelVo.setName(info.getEquipmentService()); - if (info.getParams() == null) { - newIotModelVo.setParams(equipJsonNode); - } else { - newIotModelVo.setParams(equipObjectMapper.readTree(info.getParams().toString())); - } - if (info.getServiceType() == BaseIotModelType.TYPE_PSR_SETPOINT) { - newIotModelVo.setType("yt"); - } else if (info.getServiceType() == BaseIotModelType.TYPE_PSR_CONTROL) { - newIotModelVo.setType("yk"); - } - newIotModelServiceList.add(newIotModelVo); + } + } + if (!CollectionUtils.isEmpty(iotModelServiceList)){ + for (IotModelVo info : iotModelServiceList) { + NewIotModelVo newIotModelVo = new NewIotModelVo(); + newIotModelVo.setName(info.getEquipmentService()); + if (info.getParams() == null) { + newIotModelVo.setParams(equipJsonNode); + } else { + newIotModelVo.setParams(equipObjectMapper.readTree(info.getParams().toString())); } + if (info.getServiceType() == BaseIotModelType.TYPE_PSR_SETPOINT) { + newIotModelVo.setType("yt"); + } else if (info.getServiceType() == BaseIotModelType.TYPE_PSR_CONTROL) { + newIotModelVo.setType("yk"); + } + newIotModelServiceList.add(newIotModelVo); } } EquipmentVo equipment = new EquipmentVo(); @@ -247,9 +248,8 @@ public class DataServiceImpl implements DataService { Iterator keysHigh = values.fieldNames(); while (keysHigh.hasNext()) { String fieldName = keysHigh.next(); - String key = String.format("RT:[%s]:[%s]", deviceId, fieldName); - keyValueMap.put(key, values.get(fieldName).asDouble()); - + String key = String.format("RT:%s:%s", deviceId, fieldName); + keyValueMap.put(key,values.get(fieldName)); } adminRedisTemplate.mSet(keyValueMap); // Long dataTime = data.getTime(); diff --git a/das/src/main/resources/mapper/SysEnumTypesMapper.xml b/das/src/main/resources/mapper/SysEnumTypesMapper.xml new file mode 100644 index 00000000..c73e9a36 --- /dev/null +++ b/das/src/main/resources/mapper/SysEnumTypesMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/das/src/main/resources/mapper/SysEnumValuesMapper.xml b/das/src/main/resources/mapper/SysEnumValuesMapper.xml index 39c00d79..e950eda3 100644 --- a/das/src/main/resources/mapper/SysEnumValuesMapper.xml +++ b/das/src/main/resources/mapper/SysEnumValuesMapper.xml @@ -4,6 +4,7 @@ + @@ -22,6 +23,7 @@ and e.is_active =#{sysEnumValuesDto.isActive} + order by e.order_number asc diff --git a/das/src/main/resources/mapper/SysImptabmappingMapper.xml b/das/src/main/resources/mapper/SysImptabmappingMapper.xml index 595e8290..af03a126 100644 --- a/das/src/main/resources/mapper/SysImptabmappingMapper.xml +++ b/das/src/main/resources/mapper/SysImptabmappingMapper.xml @@ -58,14 +58,6 @@ where sc.id = #{linkId} - - + + diff --git a/docs/_sidebar.md b/docs/_sidebar.md index b18bdbdb..24c993d0 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -4,4 +4,7 @@ - [设备管理接口](api/equipment.md) - [节点管理接口](api/node.md) - [数据访问接口](api/data.md) -- [数据采集](datacollect/) \ No newline at end of file +- [数据采集](datacollect/) +- [系统部署](deploy/) + - [Linux系统部署](deploy/linux.md) + - [TDEngine3部署](deploy/tdengine3.md) \ No newline at end of file diff --git a/docs/deploy/README.md b/docs/deploy/README.md new file mode 100644 index 00000000..121bbfcb --- /dev/null +++ b/docs/deploy/README.md @@ -0,0 +1,36 @@ +# 润阳系统部署 + + +## 硬件环境 + +> CPU: 24核 + +> 内存: 32GB + +> 硬盘: 16T + + +## 软件环境 + +> 操作系统: OpenEuler 24.03 (LTS) + +> JDK: OpenJDK 17 + +> 关系数据库: PostgreSQL 15.8 + +> 缓存数据库: Redis 6 + +> 时序数据库: TDEngine 3.3.2.0 + + +## 目录结构 + +`/das` - 系统根目录 + +`/das/data` - 系统数据目录 + +`/das/data/tddata` - TDEngine3数据目录 + +`/das/data/pgdata` - PostgreSQL数据目录 + +`/das/data/redis` - Redis数据目录 diff --git a/docs/deploy/_sidebar.md b/docs/deploy/_sidebar.md new file mode 100644 index 00000000..4d99ba2c --- /dev/null +++ b/docs/deploy/_sidebar.md @@ -0,0 +1 @@ +- [首页](/) \ No newline at end of file diff --git a/docs/deploy/linux.md b/docs/deploy/linux.md new file mode 100644 index 00000000..9f0b819d --- /dev/null +++ b/docs/deploy/linux.md @@ -0,0 +1,3 @@ +# OpenEuler 24.03 (LTS) 安装部署 + +!> 等待更新 \ No newline at end of file diff --git a/docs/deploy/tdengine3.md b/docs/deploy/tdengine3.md new file mode 100644 index 00000000..c5eb53e6 --- /dev/null +++ b/docs/deploy/tdengine3.md @@ -0,0 +1,4 @@ +# TDEngine3 安装部署 + +> 当前版本: 3.3.2.0 + diff --git a/ui/dasadmin/.env.development b/ui/dasadmin/.env.development index d5455a0b..0349de0f 100644 --- a/ui/dasadmin/.env.development +++ b/ui/dasadmin/.env.development @@ -6,7 +6,7 @@ VITE_BASE_PATH = './' # 代理配置(开发使用),必须在一行中 # 本地 -# VITE_APP_PROXY=[["/api","http://192.168.130.12:8080/api"]] +# VITE_APP_PROXY=[["/api","http://192.168.130.22:8080/api"]] # 线上 VITE_APP_PROXY=[["/api","https://test.jsspisoft.com/api"]] diff --git a/ui/dasadmin/src/api/backend/Enumeration/request.ts b/ui/dasadmin/src/api/backend/Enumeration/request.ts index 8fd2cbf8..688a5736 100644 --- a/ui/dasadmin/src/api/backend/Enumeration/request.ts +++ b/ui/dasadmin/src/api/backend/Enumeration/request.ts @@ -34,7 +34,7 @@ export function enumValueAdd(params: object = {}) { }) } -// 枚举值新增 +// 枚举值删除 export function enumValueDelete(params: object = {}) { return createAxios({ url: '/api/enum/deleteEnumValues', @@ -42,4 +42,12 @@ export function enumValueDelete(params: object = {}) { data: params, }) } +// 枚举值编辑 +export function enumValuepageEdit(params: object = {}) { + return createAxios({ + url: '/api/enum/updateEnumValues', + method: 'POST', + data: params, + }) +} diff --git a/ui/dasadmin/src/api/backend/control/request.ts b/ui/dasadmin/src/api/backend/control/request.ts new file mode 100644 index 00000000..fc9f1e37 --- /dev/null +++ b/ui/dasadmin/src/api/backend/control/request.ts @@ -0,0 +1,9 @@ +import createAxios from '/@/utils/axios' + +export const sendValueReq = (data: any) => { + return createAxios({ + url: '/api/node/link/deviceControl', + method: 'post', + data: data, + }) +} \ No newline at end of file diff --git a/ui/dasadmin/src/api/backend/dashboard.ts b/ui/dasadmin/src/api/backend/dashboard.ts index 5caef9de..21f901fd 100644 --- a/ui/dasadmin/src/api/backend/dashboard.ts +++ b/ui/dasadmin/src/api/backend/dashboard.ts @@ -1,4 +1,5 @@ import createAxios from '/@/utils/axios' +import {addDataType, getDataReturnType, getDataType, getTreeDataReturnType} from "/@/views/backend/auth/org/type"; export const url = '/admin/Dashboard/' @@ -8,3 +9,11 @@ export function index() { method: 'get', }) } + +export const getInstitutionalListReq = (data: getDataType) => { + return createAxios>({ + url: '/api/org/query', + method: 'post', + data: data, + }) +} diff --git a/ui/dasadmin/src/api/backend/deviceModel/request.ts b/ui/dasadmin/src/api/backend/deviceModel/request.ts index dead7a32..7a3cd1c9 100644 --- a/ui/dasadmin/src/api/backend/deviceModel/request.ts +++ b/ui/dasadmin/src/api/backend/deviceModel/request.ts @@ -142,8 +142,16 @@ export const downloadModelReq = (data: { id: string }) => { } export const getDeviceTypeEnumReq = () => { - return createAxios>({ + return createAxios>({ url: '/api/equipment/type', method: 'post', }) } + +export const getRealValueListReq = (data: { deviceId: string, attributes: string[] }[]) => { + return createAxios>({ + url: '/api/data/snapshot', + method: 'post', + data: data, + }) +} diff --git a/ui/dasadmin/src/api/backend/linkMonitor/request.ts b/ui/dasadmin/src/api/backend/linkMonitor/request.ts new file mode 100644 index 00000000..707e53f5 --- /dev/null +++ b/ui/dasadmin/src/api/backend/linkMonitor/request.ts @@ -0,0 +1,24 @@ +import createAxios from '/@/utils/axios' +import { + RequestReturnType, + RequestReturnRowType, + LinkMonitorTreeType, + GetLinkMonitorTableParam, + LinkMonitorTableType, +} from '/@/views/backend/linkMonitor/type' + +// 左侧树节点树结构 +export const getNodeListReq = () => { + return createAxios>({ + url: '/api/node/list', + method: 'post', + }) +} +// 链路列表 +export const getLinkListReq = (data: GetLinkMonitorTableParam) => { + return createAxios>({ + url: '/api/node/link/list', + method: 'post', + data: data, + }) +} diff --git a/ui/dasadmin/src/assets/dashboard/Standby.png b/ui/dasadmin/src/assets/dashboard/Standby.png new file mode 100644 index 00000000..e898970f Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/Standby.png differ diff --git a/ui/dasadmin/src/assets/dashboard/bg1.png b/ui/dasadmin/src/assets/dashboard/bg1.png new file mode 100644 index 00000000..f937021f Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/bg1.png differ diff --git a/ui/dasadmin/src/assets/dashboard/biaogan.png b/ui/dasadmin/src/assets/dashboard/biaogan.png new file mode 100644 index 00000000..a6bfcffb Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/biaogan.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fanlist1.png b/ui/dasadmin/src/assets/dashboard/fanlist1.png new file mode 100644 index 00000000..049ded0f Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fanlist1.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fanlist2.png b/ui/dasadmin/src/assets/dashboard/fanlist2.png new file mode 100644 index 00000000..e363af18 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fanlist2.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fault.png b/ui/dasadmin/src/assets/dashboard/fault.png new file mode 100644 index 00000000..3c4036f6 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fault.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fdl1.png b/ui/dasadmin/src/assets/dashboard/fdl1.png new file mode 100644 index 00000000..ac0b38d9 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fdl1.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fdl2.png b/ui/dasadmin/src/assets/dashboard/fdl2.png new file mode 100644 index 00000000..07b083f8 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fdl2.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fdl3.png b/ui/dasadmin/src/assets/dashboard/fdl3.png new file mode 100644 index 00000000..453ae972 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fdl3.png differ diff --git a/ui/dasadmin/src/assets/dashboard/fdl4.png b/ui/dasadmin/src/assets/dashboard/fdl4.png new file mode 100644 index 00000000..70069489 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/fdl4.png differ diff --git a/ui/dasadmin/src/assets/dashboard/offline.png b/ui/dasadmin/src/assets/dashboard/offline.png new file mode 100644 index 00000000..e043ccc2 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/offline.png differ diff --git a/ui/dasadmin/src/assets/dashboard/run.png b/ui/dasadmin/src/assets/dashboard/run.png new file mode 100644 index 00000000..c3e8cc4e Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/run.png differ diff --git a/ui/dasadmin/src/assets/dashboard/status1.png b/ui/dasadmin/src/assets/dashboard/status1.png new file mode 100644 index 00000000..ba7bde03 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/status1.png differ diff --git a/ui/dasadmin/src/assets/dashboard/status2.png b/ui/dasadmin/src/assets/dashboard/status2.png new file mode 100644 index 00000000..c8d8b118 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/status2.png differ diff --git a/ui/dasadmin/src/assets/dashboard/viewP.png b/ui/dasadmin/src/assets/dashboard/viewP.png new file mode 100644 index 00000000..29078a06 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/viewP.png differ diff --git a/ui/dasadmin/src/assets/dashboard/viewR.png b/ui/dasadmin/src/assets/dashboard/viewR.png new file mode 100644 index 00000000..52484464 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/viewR.png differ diff --git a/ui/dasadmin/src/assets/dashboard/viewW.png b/ui/dasadmin/src/assets/dashboard/viewW.png new file mode 100644 index 00000000..e78cbaf0 Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/viewW.png differ diff --git a/ui/dasadmin/src/assets/dashboard/viewY.png b/ui/dasadmin/src/assets/dashboard/viewY.png new file mode 100644 index 00000000..50b4ad9b Binary files /dev/null and b/ui/dasadmin/src/assets/dashboard/viewY.png differ diff --git a/ui/dasadmin/src/layouts/backend/components/navMenus.vue b/ui/dasadmin/src/layouts/backend/components/navMenus.vue index f22345b0..eaebdf11 100644 --- a/ui/dasadmin/src/layouts/backend/components/navMenus.vue +++ b/ui/dasadmin/src/layouts/backend/components/navMenus.vue @@ -1,10 +1,10 @@ - + - + @@ -182,13 +168,10 @@ import { enumTreeQuery, enumTypeAdd, enumValueAdd, - enumValueDelete + enumValueDelete, enumValuepageEdit } from "/@/api/backend/Enumeration/request"; - - - const activeName = ref('1') interface Tree { enumId: number, @@ -260,7 +243,6 @@ const handleNodeClick = (data: any) => { queryListData.description=queryName.value, queryListData.pageNum=currentPage.value, queryListData.pageSize=currentPageSize.value - console.log(queryListData) queryenumValueMethod(queryListData) } @@ -385,13 +367,6 @@ const queryenumValueMethod = (data: any) => { const onSubmitvalue = () => { formRef.value.validate((valid: any) => { if (valid) { - if(formInlineValue.isActive==true){ - formInlineValue.isActive=1 - }else{ - formInlineValue.isActive=0 - } - - console.log(formInlineValue) enumValueAdd(formInlineValue).then((res: any) => { if (res.code == 200) { queryListData.description =queryName.value @@ -459,40 +434,66 @@ const dialogVisibleDelete1 = (done: () => void) => { } }) } -// 菜单修改 +// 编辑枚举值 const fromUpDate = reactive({ id: '', enumTypeId: '', value:'', description : '', orderNumber: 0, - isActive: false + isActive: 0 }) +const addhandleSwitchChange = (value: any) => { + formInlineValue.isActive = value ? 1 : 0 +} +const edithandleSwitchChange = (value: any) => { + fromUpDate.isActive = value ? 1 : 0 +} const visibleValueEdit = ref(false) const enumValueEdit = (data: any) => { visibleValueEdit.value = true fromUpDate.id = data.row.id - fromUpDate.enumTypeId = data.row.enumTypeId + fromUpDate.enumTypeId = data.row.enumTypeIdStr fromUpDate.value = data.row.value fromUpDate.description = data.row.description fromUpDate.orderNumber = data.row.orderNumber - if(data.row.isActive==1){ - fromUpDate.isActive = true - }else{ - fromUpDate.isActive = false - } + fromUpDate.isActive = data.row.isActive + } + const edithandleClosevalue = (done: () => void) => { visibleValueEdit.value = false } +const EditonSubmitvalue = () => { + formRef.value.validate((valid: any) => { + if (valid) { + enumValuepageEdit(fromUpDate).then((res: any) => { + if (res.code == 200) { + queryListData.description =queryName.value + queryListData.enumTypeId = enumTypeId.value + queryListData.pageNum=currentPage.value, + queryListData.pageSize=currentPageSize.value + queryenumValueMethod(queryListData) + ElMessage({ + message: res.msg, + type: 'success', + }) + } else { + ElMessage.error({ + message: res.msg, + type: 'error', + }) + } + }) + + visibleValueEdit.value = false + } + }) +} onMounted(() => { enumTreeTypeList() - const firstNode = TypeTree.value.store.root.childNodes[0]; - /*if (firstNode) { - handleNodeClick(firstNode.data, null, TypeTree.value); - }*/ }) diff --git a/ui/dasadmin/src/views/backend/auth/model/index.vue b/ui/dasadmin/src/views/backend/auth/model/index.vue index bb831216..9fdcedd6 100644 --- a/ui/dasadmin/src/views/backend/auth/model/index.vue +++ b/ui/dasadmin/src/views/backend/auth/model/index.vue @@ -11,7 +11,7 @@ @@ -960,7 +960,7 @@ const downLoadModel = () => { } const currentPage = ref(1) -const currentPageSize = ref(10) +const currentPageSize = ref(20) const pageTotal = ref(0) const pagePagination = ref([10, 20, 30]) const getcurrentPage = () => { diff --git a/ui/dasadmin/src/views/backend/auth/org/index.vue b/ui/dasadmin/src/views/backend/auth/org/index.vue index b4f947bb..6548119b 100644 --- a/ui/dasadmin/src/views/backend/auth/org/index.vue +++ b/ui/dasadmin/src/views/backend/auth/org/index.vue @@ -379,9 +379,9 @@ const getInstitutionList = (data: getDataType = { name: null }) => { }) } -const pagePagination = [5, 10, 20, 30] +const pagePagination = [ 10, 20, 30] const currentPage = ref(1) -const currentPageSize = ref(pagePagination[0]) +const currentPageSize = ref(pagePagination[1]) const pageTotal = ref(0) const originData = ref() const tableData = computed(() => { diff --git a/ui/dasadmin/src/views/backend/auth/role/index.vue b/ui/dasadmin/src/views/backend/auth/role/index.vue index c9442f74..9c71a9ce 100644 --- a/ui/dasadmin/src/views/backend/auth/role/index.vue +++ b/ui/dasadmin/src/views/backend/auth/role/index.vue @@ -203,9 +203,9 @@ const tableData = computed(() => { return originData.value?.slice(start, end) }) -const pagePagination = [5, 10, 20, 30] +const pagePagination = [10, 20, 30] const currentPage = ref(1) -const currentPageSize = ref(pagePagination[0]) +const currentPageSize = ref(pagePagination[1]) const pageTotal = ref(0) const originData = ref[]>() const addClick = () => { diff --git a/ui/dasadmin/src/views/backend/auth/user/index.vue b/ui/dasadmin/src/views/backend/auth/user/index.vue index c26c7d44..4e0e44cf 100644 --- a/ui/dasadmin/src/views/backend/auth/user/index.vue +++ b/ui/dasadmin/src/views/backend/auth/user/index.vue @@ -546,9 +546,9 @@ const selectUpdataName = (data: string) => { formUserUpData.profilePicture = data } // 分页 -const pagePagination = [5, 10, 20, 30] +const pagePagination = [ 10, 20, 30] const currentPage = ref(1) -const currentPageSize = ref(pagePagination[0]) +const currentPageSize = ref(pagePagination[1]) const handleSizeChange = (val: number) => { formQuery.pageSize = val RyUserQuery(formQuery) diff --git a/ui/dasadmin/src/views/backend/dashboard.vue b/ui/dasadmin/src/views/backend/dashboard.vue index d50d1ea9..446a31c4 100644 --- a/ui/dasadmin/src/views/backend/dashboard.vue +++ b/ui/dasadmin/src/views/backend/dashboard.vue @@ -1,180 +1,301 @@ diff --git a/ui/dasadmin/src/views/backend/equipment/equipmentManagement/control.vue b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/control.vue new file mode 100644 index 00000000..ba81cf05 --- /dev/null +++ b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/control.vue @@ -0,0 +1,274 @@ + + + + + diff --git a/ui/dasadmin/src/views/backend/equipment/equipmentManagement/index.vue b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/index.vue index cba1ed83..16e50248 100644 --- a/ui/dasadmin/src/views/backend/equipment/equipmentManagement/index.vue +++ b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/index.vue @@ -49,9 +49,13 @@ @@ -418,11 +422,39 @@ + +
+ +
+
+ + +
+ +
+
diff --git a/ui/dasadmin/src/views/backend/equipment/equipmentManagement/measurement.vue b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/measurement.vue new file mode 100644 index 00000000..c111b895 --- /dev/null +++ b/ui/dasadmin/src/views/backend/equipment/equipmentManagement/measurement.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/ui/dasadmin/src/views/backend/home/windMatrix.vue b/ui/dasadmin/src/views/backend/home/windMatrix.vue new file mode 100644 index 00000000..7314248b --- /dev/null +++ b/ui/dasadmin/src/views/backend/home/windMatrix.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/ui/dasadmin/src/views/backend/linkMonitor/index.vue b/ui/dasadmin/src/views/backend/linkMonitor/index.vue new file mode 100644 index 00000000..a2a79381 --- /dev/null +++ b/ui/dasadmin/src/views/backend/linkMonitor/index.vue @@ -0,0 +1,459 @@ + + + + + diff --git a/ui/dasadmin/src/views/backend/linkMonitor/type.ts b/ui/dasadmin/src/views/backend/linkMonitor/type.ts new file mode 100644 index 00000000..74d87393 --- /dev/null +++ b/ui/dasadmin/src/views/backend/linkMonitor/type.ts @@ -0,0 +1,45 @@ +export type RequestReturnType = Promise<{ + code: number + msg: string + success: boolean + data?: T +}> + +export type RequestReturnRowType = Promise<{ + code: number + msg: string + rows: T + total: number +}> +export type LinkMonitorTreeType = { + id?: string + nodeName: string + nodeIp: string + orgName?: string + orgId: string + revision?: number + children?: LinkMonitorTreeType[] +} +export type LinkMonitorTableType = { + id?: string + linkName: string + protocol?: number + protocolName?: string + params: string + nodeName: string + nodeId: string + revision: number +} +export type GetLinkMonitorTableParam = { + nodeId: string + linkName?: string + pageNum: number + pageSize: number +} + +export enum LinkMonitorFieldsEnums { + 'id' = 'id', + 'linkName' = '链路名称', + 'status' = '状态', + 'protocolName' = '协议类型', +} diff --git a/ui/dasadmin/src/views/backend/login.vue b/ui/dasadmin/src/views/backend/login.vue index a45b14c1..9c890874 100644 --- a/ui/dasadmin/src/views/backend/login.vue +++ b/ui/dasadmin/src/views/backend/login.vue @@ -103,7 +103,8 @@ let timer: number const config = useConfig() const adminInfo = useAdminInfo() -toggleDark(config.layout.isDark) + +// TODO 切换暗黑 toggleDark(config.layout.isDark) const formRef = ref() const usernameRef = ref() diff --git a/ui/dasadmin/src/views/backend/node/index.vue b/ui/dasadmin/src/views/backend/node/index.vue index bd6211cb..7093f10b 100644 --- a/ui/dasadmin/src/views/backend/node/index.vue +++ b/ui/dasadmin/src/views/backend/node/index.vue @@ -484,7 +484,7 @@ const submitLinkForm = () => { const paginationOptions = reactive({ current: 1, - pageSize: 10, + pageSize: 20, total: 0, pageSizes: [10, 20, 30], }) diff --git a/ui/dasadmin/vite.config.ts.timestamp-1721615163299-e1531267e82f8.mjs b/ui/dasadmin/vite.config.ts.timestamp-1721615163299-e1531267e82f8.mjs deleted file mode 100644 index c5c5ce65..00000000 --- a/ui/dasadmin/vite.config.ts.timestamp-1721615163299-e1531267e82f8.mjs +++ /dev/null @@ -1,177 +0,0 @@ -// vite.config.ts -import vue from "file:///E:/softstoneFile/ry-das/ui/dasadmin/node_modules/@vitejs/plugin-vue/dist/index.mjs"; -import { resolve } from "path"; -import { loadEnv } from "file:///E:/softstoneFile/ry-das/ui/dasadmin/node_modules/vite/dist/node/index.js"; - -// src/utils/vite.ts -var customHotUpdate = () => { - const closeHmr = /* @__PURE__ */ new Map(); - return { - name: "vite-plugin-custom-hot-update", - configureServer(server) { - server.ws.on("custom:close-hot", (data) => { - closeHmr.set(data.type, true); - server.watcher.removeAllListeners("add"); - server.watcher.removeAllListeners("unlink"); - }); - server.ws.on("custom:open-hot", (data) => { - closeHmr.set(data.type, false); - server.watcher.on("add", () => { - server.restart(); - }); - server.watcher.on("unlink", () => { - server.restart(); - }); - }); - server.ws.on("custom:reload-hot", () => { - server.restart(); - }); - }, - handleHotUpdate() { - const closeHmrs = Array.from(closeHmr.values()); - let closeHmrsBool = false; - for (const key in closeHmrs) { - closeHmrsBool = closeHmrsBool || closeHmrs[key]; - } - if (closeHmrsBool) - return []; - } - }; -}; - -// src/components/icon/svg/index.ts -import { readFileSync, readdirSync } from "fs"; -var idPerfix = ""; -var iconNames = []; -var svgTitle = /+].*?)>/; -var clearHeightWidth = /(width|height)="([^>+].*?)"/g; -var hasViewBox = /(viewBox="[^>+].*?")/g; -var clearReturn = /(\r)|(\n)/g; -var clearFill = /(fill="[^>+].*?")/g; -function findSvgFile(dir) { - const svgRes = []; - const dirents = readdirSync(dir, { - withFileTypes: true - }); - for (const dirent of dirents) { - iconNames.push(`${idPerfix}-${dirent.name.replace(".svg", "")}`); - if (dirent.isDirectory()) { - svgRes.push(...findSvgFile(dir + dirent.name + "/")); - } else { - const svg = readFileSync(dir + dirent.name).toString().replace(clearReturn, "").replace(clearFill, 'fill=""').replace(svgTitle, ($1, $2) => { - let width = 0; - let height = 0; - let content = $2.replace(clearHeightWidth, (s1, s2, s3) => { - if (s2 === "width") { - width = s3; - } else if (s2 === "height") { - height = s3; - } - return ""; - }); - if (!hasViewBox.test($2)) { - content += `viewBox="0 0 ${width} ${height}"`; - } - return ``; - }).replace("", ""); - svgRes.push(svg); - } - } - return svgRes; -} -var svgBuilder = (path, perfix = "local") => { - if (path === "") - return; - idPerfix = perfix; - const res = findSvgFile(path); - return { - name: "svg-transform", - transformIndexHtml(html) { - return html.replace( - "", - ` - - - ${res.join("")} - - ` - ); - } - }; -}; - -// vite.config.ts -var __vite_injected_original_dirname = "E:\\softstoneFile\\ry-das\\ui\\dasadmin"; -var pathResolve = (dir) => { - return resolve(__vite_injected_original_dirname, ".", dir); -}; -var viteConfig = ({ mode }) => { - const { VITE_PORT, VITE_OPEN, VITE_BASE_PATH, VITE_OUT_DIR, VITE_APP_PROXY } = loadEnv(mode, process.cwd()); - const alias = { - "/@": pathResolve("./src/"), - assets: pathResolve("./src/assets"), - "vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js" - }; - const createProxy = (proxyList) => { - const ret = {}; - if (proxyList) { - proxyList = JSON.parse(proxyList); - for (const [prefix, target] of proxyList) { - ret[prefix] = { - target, - changeOrigin: true, - rewrite: (path) => path.replace(new RegExp(`^${prefix}`), "") - }; - } - } - return ret; - }; - return { - plugins: [vue(), svgBuilder("./src/assets/icons/"), customHotUpdate()], - root: process.cwd(), - resolve: { alias }, - base: VITE_BASE_PATH, - server: { - port: parseInt(VITE_PORT), - open: VITE_OPEN != "false", - proxy: { - ...createProxy(VITE_APP_PROXY) - } - }, - build: { - cssCodeSplit: false, - sourcemap: false, - outDir: VITE_OUT_DIR, - emptyOutDir: true, - chunkSizeWarningLimit: 1500, - terserOptions: { - compress: { - keep_infinity: true, - // Used to delete console in production environment - drop_console: true, - drop_debugger: true - }, - output: { - comments: true - // 去掉注释内容 - } - }, - rollupOptions: { - output: { - manualChunks: { - // 分包配置,配置完成自动按需加载 - vue: ["vue", "vue-router", "pinia", "vue-i18n", "element-plus"], - echarts: ["echarts"] - } - } - } - } - }; -}; -var vite_config_default = viteConfig; -export { - vite_config_default as default -}; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiLCAic3JjL3V0aWxzL3ZpdGUudHMiLCAic3JjL2NvbXBvbmVudHMvaWNvbi9zdmcvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxzb2Z0c3RvbmVGaWxlXFxcXHJ5LWRhc1xcXFx1aVxcXFxkYXNhZG1pblwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRTpcXFxcc29mdHN0b25lRmlsZVxcXFxyeS1kYXNcXFxcdWlcXFxcZGFzYWRtaW5cXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0U6L3NvZnRzdG9uZUZpbGUvcnktZGFzL3VpL2Rhc2FkbWluL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXHJcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdwYXRoJ1xyXG5pbXBvcnQgeyBsb2FkRW52IH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHR5cGUgeyBVc2VyQ29uZmlnLCBDb25maWdFbnYsIFByb3h5T3B0aW9ucyB9IGZyb20gJ3ZpdGUnXHJcbmltcG9ydCB7IGlzUHJvZCwgY3VzdG9tSG90VXBkYXRlIH0gZnJvbSAnL0AvdXRpbHMvdml0ZSdcclxuaW1wb3J0IHsgc3ZnQnVpbGRlciB9IGZyb20gJy9AL2NvbXBvbmVudHMvaWNvbi9zdmcvaW5kZXgnXHJcblxyXG5jb25zdCBwYXRoUmVzb2x2ZSA9IChkaXI6IHN0cmluZyk6IGFueSA9PiB7XHJcbiAgICByZXR1cm4gcmVzb2x2ZShfX2Rpcm5hbWUsICcuJywgZGlyKVxyXG59XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5jbi9jb25maWcvXHJcbmNvbnN0IHZpdGVDb25maWcgPSAoeyBtb2RlIH06IENvbmZpZ0Vudik6IFVzZXJDb25maWcgPT4ge1xyXG4gICAgY29uc3QgeyBWSVRFX1BPUlQsIFZJVEVfT1BFTiwgVklURV9CQVNFX1BBVEgsIFZJVEVfT1VUX0RJUiwgVklURV9BUFBfUFJPWFkgfSA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSlcclxuXHJcbiAgICBjb25zdCBhbGlhczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcclxuICAgICAgICAnL0AnOiBwYXRoUmVzb2x2ZSgnLi9zcmMvJyksXHJcbiAgICAgICAgYXNzZXRzOiBwYXRoUmVzb2x2ZSgnLi9zcmMvYXNzZXRzJyksXHJcbiAgICAgICAgJ3Z1ZS1pMThuJzogJ3Z1ZS1pMThuL2Rpc3QvdnVlLWkxOG4uY2pzLmpzJyxcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjcmVhdGVQcm94eSA9IChwcm94eUxpc3Q6IGFueSkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHJldCA9IHt9IGFzIFJlY29yZDxzdHJpbmcsIFByb3h5T3B0aW9ucz5cclxuICAgICAgICBpZiAocHJveHlMaXN0KSB7XHJcbiAgICAgICAgICAgIHByb3h5TGlzdCA9IEpTT04ucGFyc2UocHJveHlMaXN0KVxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtwcmVmaXgsIHRhcmdldF0gb2YgcHJveHlMaXN0KSB7XHJcbiAgICAgICAgICAgICAgICByZXRbcHJlZml4XSA9IHtcclxuICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IHRhcmdldCxcclxuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgcmV3cml0ZTogKHBhdGgpID0+IHBhdGgucmVwbGFjZShuZXcgUmVnRXhwKGBeJHtwcmVmaXh9YCksICcnKSxcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJldFxyXG4gICAgfVxyXG5cclxuICAgIC8vIGxldCBwcm94eTogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgUHJveHlPcHRpb25zPiA9IHt9XHJcbiAgICAvLyBpZiAoVklURV9QUk9YWV9VUkwpIHtcclxuICAgIC8vICAgICBwcm94eSA9IHtcclxuICAgIC8vICAgICAgICAgJy8nOiB7XHJcbiAgICAvLyAgICAgICAgICAgICB0YXJnZXQ6IFZJVEVfUFJPWFlfVVJMLFxyXG4gICAgLy8gICAgICAgICAgICAgY2hhbmdlT3JpZ2luOiB0cnVlLFxyXG4gICAgLy8gICAgICAgICB9LFxyXG4gICAgLy8gICAgIH1cclxuICAgIC8vIH1cclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIHBsdWdpbnM6IFt2dWUoKSwgc3ZnQnVpbGRlcignLi9zcmMvYXNzZXRzL2ljb25zLycpLCBjdXN0b21Ib3RVcGRhdGUoKV0sXHJcbiAgICAgICAgcm9vdDogcHJvY2Vzcy5jd2QoKSxcclxuICAgICAgICByZXNvbHZlOiB7IGFsaWFzIH0sXHJcbiAgICAgICAgYmFzZTogVklURV9CQVNFX1BBVEgsXHJcbiAgICAgICAgc2VydmVyOiB7XHJcbiAgICAgICAgICAgIHBvcnQ6IHBhcnNlSW50KFZJVEVfUE9SVCksXHJcbiAgICAgICAgICAgIG9wZW46IFZJVEVfT1BFTiAhPSAnZmFsc2UnLFxyXG4gICAgICAgICAgICBwcm94eToge1xyXG4gICAgICAgICAgICAgICAgLi4uY3JlYXRlUHJveHkoVklURV9BUFBfUFJPWFkpLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgYnVpbGQ6IHtcclxuICAgICAgICAgICAgY3NzQ29kZVNwbGl0OiBmYWxzZSxcclxuICAgICAgICAgICAgc291cmNlbWFwOiBmYWxzZSxcclxuICAgICAgICAgICAgb3V0RGlyOiBWSVRFX09VVF9ESVIsXHJcbiAgICAgICAgICAgIGVtcHR5T3V0RGlyOiB0cnVlLFxyXG4gICAgICAgICAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IDE1MDAsXHJcbiAgICAgICAgICAgIHRlcnNlck9wdGlvbnM6IHtcclxuICAgICAgICAgICAgICAgIGNvbXByZXNzOiB7XHJcbiAgICAgICAgICAgICAgICAgICAga2VlcF9pbmZpbml0eTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgICAgICAvLyBVc2VkIHRvIGRlbGV0ZSBjb25zb2xlIGluIHByb2R1Y3Rpb24gZW52aXJvbm1lbnRcclxuICAgICAgICAgICAgICAgICAgICBkcm9wX2NvbnNvbGU6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgZHJvcF9kZWJ1Z2dlcjogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBvdXRwdXQ6IHtcclxuICAgICAgICAgICAgICAgICAgICBjb21tZW50czogdHJ1ZSwgLy8gXHU1M0JCXHU2Mzg5XHU2Q0U4XHU5MUNBXHU1MTg1XHU1QkI5XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICByb2xsdXBPcHRpb25zOiB7XHJcbiAgICAgICAgICAgICAgICBvdXRwdXQ6IHtcclxuICAgICAgICAgICAgICAgICAgICBtYW51YWxDaHVua3M6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gXHU1MjA2XHU1MzA1XHU5MTREXHU3RjZFXHVGRjBDXHU5MTREXHU3RjZFXHU1QjhDXHU2MjEwXHU4MUVBXHU1MkE4XHU2MzA5XHU5NzAwXHU1MkEwXHU4RjdEXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZ1ZTogWyd2dWUnLCAndnVlLXJvdXRlcicsICdwaW5pYScsICd2dWUtaTE4bicsICdlbGVtZW50LXBsdXMnXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWNoYXJ0czogWydlY2hhcnRzJ10sXHJcbiAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgdml0ZUNvbmZpZ1xyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHNvZnRzdG9uZUZpbGVcXFxccnktZGFzXFxcXHVpXFxcXGRhc2FkbWluXFxcXHNyY1xcXFx1dGlsc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRTpcXFxcc29mdHN0b25lRmlsZVxcXFxyeS1kYXNcXFxcdWlcXFxcZGFzYWRtaW5cXFxcc3JjXFxcXHV0aWxzXFxcXHZpdGUudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0U6L3NvZnRzdG9uZUZpbGUvcnktZGFzL3VpL2Rhc2FkbWluL3NyYy91dGlscy92aXRlLnRzXCI7aW1wb3J0IHsgUGx1Z2luIH0gZnJvbSAndml0ZSdcclxuXHJcbi8qKlxyXG4gKiBcdTY2MkZcdTU0MjZcdTU3MjhcdTVGMDBcdTUzRDFcdTczQUZcdTU4ODNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0Rldihtb2RlOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBtb2RlID09PSAnZGV2ZWxvcG1lbnQnXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBcdTY2MkZcdTU0MjZcdTU3MjhcdTc1MUZcdTRFQTdcdTczQUZcdTU4ODNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1Byb2QobW9kZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gbW9kZSA9PT0gJ3Byb2R1Y3Rpb24nXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBcdTgxRUFcdTVCOUFcdTRFNDlcdTcwRURcdTY2RjRcdTY1QjBcdTU5MDRcdTc0MDZcdTYzRDJcdTRFRjZcclxuICovXHJcbmV4cG9ydCBjb25zdCBjdXN0b21Ib3RVcGRhdGUgPSAoKTogUGx1Z2luID0+IHtcclxuICAgIGNvbnN0IGNsb3NlSG1yID0gbmV3IE1hcDxzdHJpbmcsIGJvb2xlYW4+KClcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIG5hbWU6ICd2aXRlLXBsdWdpbi1jdXN0b20taG90LXVwZGF0ZScsXHJcbiAgICAgICAgY29uZmlndXJlU2VydmVyKHNlcnZlcikge1xyXG4gICAgICAgICAgICBzZXJ2ZXIud3Mub24oJ2N1c3RvbTpjbG9zZS1ob3QnLCAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY2xvc2VIbXIuc2V0KGRhdGEudHlwZSwgdHJ1ZSlcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBcdTUxNzNcdTk1RURcdTY1ODdcdTRFRjZcdTZERkJcdTUyQTBcdTU0OENcdTUyMjBcdTk2NjRcdTc2ODRcdTc2RDFcdTU0MkNcclxuICAgICAgICAgICAgICAgIHNlcnZlci53YXRjaGVyLnJlbW92ZUFsbExpc3RlbmVycygnYWRkJylcclxuICAgICAgICAgICAgICAgIHNlcnZlci53YXRjaGVyLnJlbW92ZUFsbExpc3RlbmVycygndW5saW5rJylcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgc2VydmVyLndzLm9uKCdjdXN0b206b3Blbi1ob3QnLCAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY2xvc2VIbXIuc2V0KGRhdGEudHlwZSwgZmFsc2UpXHJcblxyXG4gICAgICAgICAgICAgICAgc2VydmVyLndhdGNoZXIub24oJ2FkZCcsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIucmVzdGFydCgpXHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgc2VydmVyLndhdGNoZXIub24oJ3VubGluaycsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIucmVzdGFydCgpXHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICBzZXJ2ZXIud3Mub24oJ2N1c3RvbTpyZWxvYWQtaG90JywgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgc2VydmVyLnJlc3RhcnQoKVxyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgaGFuZGxlSG90VXBkYXRlKCkge1xyXG4gICAgICAgICAgICBjb25zdCBjbG9zZUhtcnMgPSBBcnJheS5mcm9tKGNsb3NlSG1yLnZhbHVlcygpKVxyXG4gICAgICAgICAgICBsZXQgY2xvc2VIbXJzQm9vbCA9IGZhbHNlXHJcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIGNsb3NlSG1ycykge1xyXG4gICAgICAgICAgICAgICAgY2xvc2VIbXJzQm9vbCA9IGNsb3NlSG1yc0Jvb2wgfHwgY2xvc2VIbXJzW2tleV1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoY2xvc2VIbXJzQm9vbCkgcmV0dXJuIFtdXHJcbiAgICAgICAgfSxcclxuICAgIH1cclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHNvZnRzdG9uZUZpbGVcXFxccnktZGFzXFxcXHVpXFxcXGRhc2FkbWluXFxcXHNyY1xcXFxjb21wb25lbnRzXFxcXGljb25cXFxcc3ZnXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxzb2Z0c3RvbmVGaWxlXFxcXHJ5LWRhc1xcXFx1aVxcXFxkYXNhZG1pblxcXFxzcmNcXFxcY29tcG9uZW50c1xcXFxpY29uXFxcXHN2Z1xcXFxpbmRleC50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovc29mdHN0b25lRmlsZS9yeS1kYXMvdWkvZGFzYWRtaW4vc3JjL2NvbXBvbmVudHMvaWNvbi9zdmcvaW5kZXgudHNcIjtpbXBvcnQgeyByZWFkRmlsZVN5bmMsIHJlYWRkaXJTeW5jIH0gZnJvbSAnZnMnXHJcblxyXG5sZXQgaWRQZXJmaXggPSAnJ1xyXG5jb25zdCBpY29uTmFtZXM6IHN0cmluZ1tdID0gW11cclxuY29uc3Qgc3ZnVGl0bGUgPSAvPHN2ZyhbXj4rXS4qPyk+L1xyXG5jb25zdCBjbGVhckhlaWdodFdpZHRoID0gLyh3aWR0aHxoZWlnaHQpPVwiKFtePitdLio/KVwiL2dcclxuY29uc3QgaGFzVmlld0JveCA9IC8odmlld0JveD1cIltePitdLio/XCIpL2dcclxuY29uc3QgY2xlYXJSZXR1cm4gPSAvKFxccil8KFxcbikvZ1xyXG4vLyBcdTZFMDVcdTc0MDYgc3ZnIFx1NzY4NCBmaWxsXHJcbmNvbnN0IGNsZWFyRmlsbCA9IC8oZmlsbD1cIltePitdLio/XCIpL2dcclxuXHJcbmZ1bmN0aW9uIGZpbmRTdmdGaWxlKGRpcjogc3RyaW5nKTogc3RyaW5nW10ge1xyXG4gICAgY29uc3Qgc3ZnUmVzID0gW11cclxuICAgIGNvbnN0IGRpcmVudHMgPSByZWFkZGlyU3luYyhkaXIsIHtcclxuICAgICAgICB3aXRoRmlsZVR5cGVzOiB0cnVlLFxyXG4gICAgfSlcclxuICAgIGZvciAoY29uc3QgZGlyZW50IG9mIGRpcmVudHMpIHtcclxuICAgICAgICBpY29uTmFtZXMucHVzaChgJHtpZFBlcmZpeH0tJHtkaXJlbnQubmFtZS5yZXBsYWNlKCcuc3ZnJywgJycpfWApXHJcbiAgICAgICAgaWYgKGRpcmVudC5pc0RpcmVjdG9yeSgpKSB7XHJcbiAgICAgICAgICAgIHN2Z1Jlcy5wdXNoKC4uLmZpbmRTdmdGaWxlKGRpciArIGRpcmVudC5uYW1lICsgJy8nKSlcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zdCBzdmcgPSByZWFkRmlsZVN5bmMoZGlyICsgZGlyZW50Lm5hbWUpXHJcbiAgICAgICAgICAgICAgICAudG9TdHJpbmcoKVxyXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoY2xlYXJSZXR1cm4sICcnKVxyXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoY2xlYXJGaWxsLCAnZmlsbD1cIlwiJylcclxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKHN2Z1RpdGxlLCAoJDEsICQyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHdpZHRoID0gMFxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBoZWlnaHQgPSAwXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSAkMi5yZXBsYWNlKGNsZWFySGVpZ2h0V2lkdGgsIChzMTogc3RyaW5nLCBzMjogc3RyaW5nLCBzMzogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMiA9PT0gJ3dpZHRoJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSBzM1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHMyID09PSAnaGVpZ2h0Jykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gczNcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJydcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghaGFzVmlld0JveC50ZXN0KCQyKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50ICs9IGB2aWV3Qm94PVwiMCAwICR7d2lkdGh9ICR7aGVpZ2h0fVwiYFxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYDxzeW1ib2wgaWQ9XCIke2lkUGVyZml4fS0ke2RpcmVudC5uYW1lLnJlcGxhY2UoJy5zdmcnLCAnJyl9XCIgJHtjb250ZW50fT5gXHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoJzwvc3ZnPicsICc8L3N5bWJvbD4nKVxyXG4gICAgICAgICAgICBzdmdSZXMucHVzaChzdmcpXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHN2Z1Jlc1xyXG59XHJcblxyXG5leHBvcnQgY29uc3Qgc3ZnQnVpbGRlciA9IChwYXRoOiBzdHJpbmcsIHBlcmZpeCA9ICdsb2NhbCcpID0+IHtcclxuICAgIGlmIChwYXRoID09PSAnJykgcmV0dXJuXHJcbiAgICBpZFBlcmZpeCA9IHBlcmZpeFxyXG4gICAgY29uc3QgcmVzID0gZmluZFN2Z0ZpbGUocGF0aClcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmFtZTogJ3N2Zy10cmFuc2Zvcm0nLFxyXG4gICAgICAgIHRyYW5zZm9ybUluZGV4SHRtbChodG1sOiBzdHJpbmcpIHtcclxuICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgKi9cclxuICAgICAgICAgICAgcmV0dXJuIGh0bWwucmVwbGFjZShcclxuICAgICAgICAgICAgICAgICc8Ym9keT4nLFxyXG4gICAgICAgICAgICAgICAgYFxyXG4gICAgICAgICAgICAgICAgPGJvZHk+XHJcbiAgICAgICAgICAgICAgICA8c3ZnIGlkPVwibG9jYWwtaWNvblwiIGRhdGEtaWNvbi1uYW1lPVwiJHtpY29uTmFtZXMuam9pbihcclxuICAgICAgICAgICAgICAgICAgICAnLCdcclxuICAgICAgICAgICAgICAgICl9XCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHhtbG5zOnhsaW5rPVwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiIHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyB3aWR0aDogMDsgaGVpZ2h0OiAwXCI+XHJcbiAgICAgICAgICAgICAgICAke3Jlcy5qb2luKCcnKX1cclxuICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgYFxyXG4gICAgICAgICAgICApXHJcbiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgKi9cclxuICAgICAgICB9LFxyXG4gICAgfVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBcVMsT0FBTyxTQUFTO0FBQ3JULFNBQVMsZUFBZTtBQUN4QixTQUFTLGVBQWU7OztB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