Merge branch 'main' of https://git.jsspisoft.com/ry-das
@ -49,12 +49,12 @@ public class DataService {
|
|||||||
//为空查全部
|
//为空查全部
|
||||||
List<String> sysIotModelFields = sysIotModelFieldMapper.queryAllFiledNames(Long.valueOf(snapshotValueQueryParam.getDeviceId()));
|
List<String> sysIotModelFields = sysIotModelFieldMapper.queryAllFiledNames(Long.valueOf(snapshotValueQueryParam.getDeviceId()));
|
||||||
for (String item : sysIotModelFields) {
|
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);
|
keyList.add(key);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (String item : attributes) {
|
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);
|
keyList.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,12 +62,10 @@ public class DataService {
|
|||||||
List<Object> dataList = adminRedisTemplate.mGet(keyList);
|
List<Object> dataList = adminRedisTemplate.mGet(keyList);
|
||||||
for (int i = 0; i < keyList.size(); i++) {
|
for (int i = 0; i < keyList.size(); i++) {
|
||||||
String key = keyList.get(i);
|
String key = keyList.get(i);
|
||||||
int firstColonIndex = key.indexOf('[');
|
int firstColonIndex = key.indexOf(':');
|
||||||
int firstIndex = key.indexOf(']');
|
int secondColonIndex = key.indexOf(':', firstColonIndex + 1);
|
||||||
int secondIndex = key.indexOf(']', firstIndex + 1);
|
String deviceId = key.substring(firstColonIndex + 1, secondColonIndex);
|
||||||
int secondColonIndex = key.indexOf('[', firstColonIndex + 1);
|
String fieldName = key.substring(secondColonIndex + 1);
|
||||||
String deviceId = key.substring(firstColonIndex + 1, firstIndex);
|
|
||||||
String fieldName = key.substring(secondColonIndex + 1, secondIndex);
|
|
||||||
if (finalResult.get(deviceId) == null) {
|
if (finalResult.get(deviceId) == null) {
|
||||||
Map<String, Object> valueMap = new HashMap<>();
|
Map<String, Object> valueMap = new HashMap<>();
|
||||||
valueMap.put(fieldName, dataList.get(i));
|
valueMap.put(fieldName, dataList.get(i));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.das.modules.equipment.service.impl;
|
package com.das.modules.equipment.service.impl;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import cn.hutool.poi.excel.ExcelReader;
|
import cn.hutool.poi.excel.ExcelReader;
|
||||||
import cn.hutool.poi.excel.ExcelUtil;
|
import cn.hutool.poi.excel.ExcelUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
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.SysIotModelMapper;
|
||||||
import com.das.modules.equipment.mapper.SysIotModelServiceMapper;
|
import com.das.modules.equipment.mapper.SysIotModelServiceMapper;
|
||||||
import com.das.modules.equipment.service.SysIotModelService;
|
import com.das.modules.equipment.service.SysIotModelService;
|
||||||
|
import com.das.modules.node.service.TDEngineService;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -35,15 +37,13 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SysIotModelServiceImpl implements SysIotModelService {
|
public class SysIotModelServiceImpl implements SysIotModelService {
|
||||||
|
public static final int COMMIT_COUNT = 1000;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysIotModelMapper sysIotModelMapper;
|
private SysIotModelMapper sysIotModelMapper;
|
||||||
@ -54,6 +54,8 @@ public class SysIotModelServiceImpl implements SysIotModelService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SysIotModelServiceMapper sysIotModelServiceMapper;
|
private SysIotModelServiceMapper sysIotModelServiceMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TDEngineService tdEngineService;
|
||||||
|
|
||||||
public SysIotModelVo creatSysIotModel(SysIotModelDto sysIotModelDto) {
|
public SysIotModelVo creatSysIotModel(SysIotModelDto sysIotModelDto) {
|
||||||
SysIotModel sysIotModel = new SysIotModel();
|
SysIotModel sysIotModel = new SysIotModel();
|
||||||
@ -162,6 +164,8 @@ public class SysIotModelServiceImpl implements SysIotModelService {
|
|||||||
sysIotModelField.setDataType("tinyint");
|
sysIotModelField.setDataType("tinyint");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//动态执行创建td超级表,字段
|
||||||
|
createTdStableOrColumn(sysIotModelField);
|
||||||
sysIotModelFieldMapper.insert(sysIotModelField);
|
sysIotModelFieldMapper.insert(sysIotModelField);
|
||||||
SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo();
|
SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo();
|
||||||
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
|
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
|
||||||
@ -188,6 +192,15 @@ public class SysIotModelServiceImpl implements SysIotModelService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
sysIotModelFieldMapper.updateById(sysIotModelField);
|
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();
|
SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo();
|
||||||
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
|
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
|
||||||
return sysIotModelFieldVo;
|
return sysIotModelFieldVo;
|
||||||
@ -195,6 +208,8 @@ public class SysIotModelServiceImpl implements SysIotModelService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteSysIotModelField(SysIotModelFieldDto sysIotModelFieldDto) {
|
public void deleteSysIotModelField(SysIotModelFieldDto sysIotModelFieldDto) {
|
||||||
|
SysIotModelField sysIotModelField = sysIotModelFieldMapper.selectById(sysIotModelFieldDto.getId());
|
||||||
|
deleteTDStableOrColumn(sysIotModelField);
|
||||||
sysIotModelFieldMapper.deleteById(sysIotModelFieldDto.getId());
|
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)) {
|
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);
|
sysIotModelFieldMapper.updateBatchById(updateSysIotModelFieldList);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isNotEmpty(delSysIotModelFieldList)) {
|
if (CollectionUtils.isNotEmpty(delSysIotModelFieldList)) {
|
||||||
|
ListUtil.page(updateSysIotModelFieldList, COMMIT_COUNT, delete -> {
|
||||||
|
for (SysIotModelField item : delete){
|
||||||
|
deleteTDStableOrColumn(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
sysIotModelFieldMapper.deleteBatchIds(delSysIotModelFieldList);
|
sysIotModelFieldMapper.deleteBatchIds(delSysIotModelFieldList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,4 +467,70 @@ public class SysIotModelServiceImpl implements SysIotModelService {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void createTdStableOrColumn(SysIotModelField sysIotModelField){
|
||||||
|
//如果新增的是第一条记录 创建tdengine超级表 分为高频和低频
|
||||||
|
QueryWrapper<SysIotModelField> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("iot_model_id",sysIotModelField.getIotModelId());
|
||||||
|
queryWrapper.eq("highspeed",sysIotModelField.getHighSpeed());
|
||||||
|
List<SysIotModelField> sysIotModelFields = sysIotModelFieldMapper.selectList(queryWrapper);
|
||||||
|
if (CollectionUtils.isEmpty(sysIotModelFields)){
|
||||||
|
if (sysIotModelField.getHighSpeed() == 0){
|
||||||
|
SysIotModel sysIotModel = sysIotModelMapper.selectById(sysIotModelField.getIotModelId());
|
||||||
|
Map<String,String> 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<String,String> 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<String,String> 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<String,String> 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<SysIotModelField> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("iot_model_id",sysIotModelField.getIotModelId());
|
||||||
|
queryWrapper.eq("highspeed",sysIotModelField.getHighSpeed());
|
||||||
|
List<SysIotModelField> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ public class TDEngineService {
|
|||||||
/**
|
/**
|
||||||
* 创建超级表
|
* 创建超级表
|
||||||
*/
|
*/
|
||||||
|
@Async
|
||||||
public void createStable(String iotModelCode, String stableType, Map<String, String> fieldNameTypeMap) {
|
public void createStable(String iotModelCode, String stableType, Map<String, String> fieldNameTypeMap) {
|
||||||
try (Connection conn = hikariDataSource.getConnection();
|
try (Connection conn = hikariDataSource.getConnection();
|
||||||
Statement pstmt = conn.createStatement()) {
|
Statement pstmt = conn.createStatement()) {
|
||||||
@ -94,6 +95,7 @@ public class TDEngineService {
|
|||||||
/**
|
/**
|
||||||
* 新增超级表列
|
* 新增超级表列
|
||||||
*/
|
*/
|
||||||
|
@Async
|
||||||
public void addStableColumn(String iotModelCode, String stableType, Map<String, String> fieldNameTypeMap) {
|
public void addStableColumn(String iotModelCode, String stableType, Map<String, String> fieldNameTypeMap) {
|
||||||
try (Connection conn = hikariDataSource.getConnection();
|
try (Connection conn = hikariDataSource.getConnection();
|
||||||
Statement pstmt = conn.createStatement()) {
|
Statement pstmt = conn.createStatement()) {
|
||||||
@ -124,6 +126,7 @@ public class TDEngineService {
|
|||||||
/**
|
/**
|
||||||
* 删除超级表列
|
* 删除超级表列
|
||||||
*/
|
*/
|
||||||
|
@Async
|
||||||
public void deleteColumn(String stableName, String fieldCode) {
|
public void deleteColumn(String stableName, String fieldCode) {
|
||||||
try (Connection conn = hikariDataSource.getConnection();
|
try (Connection conn = hikariDataSource.getConnection();
|
||||||
Statement pstmt = conn.createStatement()) {
|
Statement pstmt = conn.createStatement()) {
|
||||||
@ -131,7 +134,7 @@ public class TDEngineService {
|
|||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
sb.append("ALTER STABLE ");
|
sb.append("ALTER STABLE ");
|
||||||
sb.append(stableName);
|
sb.append(stableName);
|
||||||
sb.append(" DROP COLUMN");
|
sb.append(" DROP COLUMN ");
|
||||||
;
|
;
|
||||||
sb.append(fieldCode);
|
sb.append(fieldCode);
|
||||||
sb.append(";");
|
sb.append(";");
|
||||||
@ -149,6 +152,7 @@ public class TDEngineService {
|
|||||||
/**
|
/**
|
||||||
* 删除超级表
|
* 删除超级表
|
||||||
*/
|
*/
|
||||||
|
@Async
|
||||||
public void deleteStable(String stableName) {
|
public void deleteStable(String stableName) {
|
||||||
try (Connection conn = hikariDataSource.getConnection();
|
try (Connection conn = hikariDataSource.getConnection();
|
||||||
Statement pstmt = conn.createStatement()) {
|
Statement pstmt = conn.createStatement()) {
|
||||||
|
@ -248,9 +248,8 @@ public class DataServiceImpl implements DataService {
|
|||||||
Iterator<String> keysHigh = values.fieldNames();
|
Iterator<String> keysHigh = values.fieldNames();
|
||||||
while (keysHigh.hasNext()) {
|
while (keysHigh.hasNext()) {
|
||||||
String fieldName = keysHigh.next();
|
String fieldName = keysHigh.next();
|
||||||
String key = String.format("RT:[%s]:[%s]", deviceId, fieldName);
|
String key = String.format("RT:%s:%s", deviceId, fieldName);
|
||||||
keyValueMap.put(key, values.get(fieldName).asDouble());
|
keyValueMap.put(key,values.get(fieldName));
|
||||||
|
|
||||||
}
|
}
|
||||||
adminRedisTemplate.mSet(keyValueMap);
|
adminRedisTemplate.mSet(keyValueMap);
|
||||||
// Long dataTime = data.getTime();
|
// Long dataTime = data.getTime();
|
||||||
|
@ -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"]]
|
VITE_APP_PROXY=[["/api","https://test.jsspisoft.com/api"]]
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export function enumValueAdd(params: object = {}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 枚举值新增
|
// 枚举值删除
|
||||||
export function enumValueDelete(params: object = {}) {
|
export function enumValueDelete(params: object = {}) {
|
||||||
return createAxios({
|
return createAxios({
|
||||||
url: '/api/enum/deleteEnumValues',
|
url: '/api/enum/deleteEnumValues',
|
||||||
@ -42,4 +42,12 @@ export function enumValueDelete(params: object = {}) {
|
|||||||
data: params,
|
data: params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 枚举值编辑
|
||||||
|
export function enumValuepageEdit(params: object = {}) {
|
||||||
|
return createAxios({
|
||||||
|
url: '/api/enum/updateEnumValues',
|
||||||
|
method: 'POST',
|
||||||
|
data: params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import createAxios from '/@/utils/axios'
|
import createAxios from '/@/utils/axios'
|
||||||
|
import {addDataType, getDataReturnType, getDataType, getTreeDataReturnType} from "/@/views/backend/auth/org/type";
|
||||||
|
|
||||||
export const url = '/admin/Dashboard/'
|
export const url = '/admin/Dashboard/'
|
||||||
|
|
||||||
@ -8,3 +9,11 @@ export function index() {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getInstitutionalListReq = (data: getDataType) => {
|
||||||
|
return createAxios<addDataType, getDataReturnType<getTreeDataReturnType>>({
|
||||||
|
url: '/api/org/query',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -142,8 +142,16 @@ export const downloadModelReq = (data: { id: string }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getDeviceTypeEnumReq = () => {
|
export const getDeviceTypeEnumReq = () => {
|
||||||
return createAxios<never,RequestReturnType<DeviceType[]>>({
|
return createAxios<never, RequestReturnType<DeviceType[]>>({
|
||||||
url: '/api/equipment/type',
|
url: '/api/equipment/type',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getRealValueListReq = (data: { deviceId: string, attributes: string[] }[]) => {
|
||||||
|
return createAxios<never, RequestReturnType<any>>({
|
||||||
|
url: '/api/data/snapshot',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
24
ui/dasadmin/src/api/backend/linkMonitor/request.ts
Normal file
@ -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<never, RequestReturnType<LinkMonitorTreeType[]>>({
|
||||||
|
url: '/api/node/list',
|
||||||
|
method: 'post',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 链路列表
|
||||||
|
export const getLinkListReq = (data: GetLinkMonitorTableParam) => {
|
||||||
|
return createAxios<never, RequestReturnRowType<LinkMonitorTableType[]>>({
|
||||||
|
url: '/api/node/link/list',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
})
|
||||||
|
}
|
BIN
ui/dasadmin/src/assets/dashboard/Standby.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
ui/dasadmin/src/assets/dashboard/bg1.png
Normal file
After Width: | Height: | Size: 877 KiB |
BIN
ui/dasadmin/src/assets/dashboard/biaogan.png
Normal file
After Width: | Height: | Size: 574 B |
BIN
ui/dasadmin/src/assets/dashboard/fanlist1.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
ui/dasadmin/src/assets/dashboard/fanlist2.png
Normal file
After Width: | Height: | Size: 844 B |
BIN
ui/dasadmin/src/assets/dashboard/fault.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
ui/dasadmin/src/assets/dashboard/fdl1.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
ui/dasadmin/src/assets/dashboard/fdl2.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
ui/dasadmin/src/assets/dashboard/fdl3.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
ui/dasadmin/src/assets/dashboard/fdl4.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
ui/dasadmin/src/assets/dashboard/offline.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
ui/dasadmin/src/assets/dashboard/run.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
ui/dasadmin/src/assets/dashboard/status1.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
ui/dasadmin/src/assets/dashboard/status2.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
ui/dasadmin/src/assets/dashboard/viewP.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
ui/dasadmin/src/assets/dashboard/viewR.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
ui/dasadmin/src/assets/dashboard/viewW.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
ui/dasadmin/src/assets/dashboard/viewY.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nav-menus" :class="configStore.layout.layoutMode">
|
<div class="nav-menus" :class="configStore.layout.layoutMode">
|
||||||
<router-link class="h100" target="_blank" :title="t('Home')" to="/">
|
<!-- <router-link class="h100" target="_blank" :title="t('Home')" to="/">
|
||||||
<div class="nav-menu-item">
|
<div class="nav-menu-item">
|
||||||
<Icon :color="configStore.getColorVal('headerBarTabColor')" class="nav-menu-icon" name="el-icon-Monitor" size="18" />
|
<Icon :color="configStore.getColorVal('headerBarTabColor')" class="nav-menu-icon" name="el-icon-Monitor" size="18" />
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link> -->
|
||||||
<!-- <el-dropdown
|
<!-- <el-dropdown
|
||||||
@visible-change="onCurrentNavMenu($event, 'lang')"
|
@visible-change="onCurrentNavMenu($event, 'lang')"
|
||||||
class="h100"
|
class="h100"
|
||||||
|
@ -70,11 +70,6 @@ const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
name: 'univer',
|
name: 'univer',
|
||||||
component: () => import('/@/views/backend/node/univer.vue'),
|
component: () => import('/@/views/backend/node/univer.vue'),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: adminBaseRoutePath +'/airBlower',
|
|
||||||
name: 'airBlower',
|
|
||||||
component: () => import('/@/views/backend/equipment/airBlower/index.vue'),
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const staticFiles: Record<string, Record<string, RouteRecordRaw>> = import.meta.glob('./static/*.ts', { eager: true })
|
const staticFiles: Record<string, Record<string, RouteRecordRaw>> = import.meta.glob('./static/*.ts', { eager: true })
|
||||||
|
@ -106,11 +106,12 @@ export const useConfig = defineStore(
|
|||||||
|
|
||||||
const getColorVal = function (name: keyof Layout): string {
|
const getColorVal = function (name: keyof Layout): string {
|
||||||
const colors = layout[name] as string[]
|
const colors = layout[name] as string[]
|
||||||
if (layout.isDark) {
|
// TODO 切换暗黑模式
|
||||||
return colors[1]
|
// if (layout.isDark) {
|
||||||
} else {
|
// return colors[1]
|
||||||
return colors[0]
|
// } else {
|
||||||
}
|
return colors[0]
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
|
return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
|
||||||
|
@ -3,26 +3,6 @@
|
|||||||
<el-container class="containerPart">
|
<el-container class="containerPart">
|
||||||
<el-aside class="defaultAside">
|
<el-aside class="defaultAside">
|
||||||
<el-main class="treeMain">
|
<el-main class="treeMain">
|
||||||
<!-- <div class="demo-collapse">-->
|
|
||||||
<!-- <el-collapse v-model="activeName" accordion>-->
|
|
||||||
<!-- <el-collapse-item name="1">-->
|
|
||||||
<!-- <template #title>-->
|
|
||||||
<!-- <span class="collapse-title">枚举类型配置</span>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <el-tree-->
|
|
||||||
<!-- style="max-width: 600px;margin-top: 2.2%"-->
|
|
||||||
<!-- ref="TypeTree"-->
|
|
||||||
<!-- :data="TypeData"-->
|
|
||||||
<!-- :props="defaultProps"-->
|
|
||||||
<!-- node-key="id"-->
|
|
||||||
<!-- @node-click="handleNodeClick"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </el-collapse-item>-->
|
|
||||||
<!-- </el-collapse>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <label class="treeTitle">枚举类型配置</label>-->
|
|
||||||
<el-tree
|
<el-tree
|
||||||
style="max-width: 600px;margin-top: 2.2%"
|
style="max-width: 600px;margin-top: 2.2%"
|
||||||
ref="TypeTree"
|
ref="TypeTree"
|
||||||
@ -93,7 +73,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="visibleTypeAdd = false"> 取消 </el-button>
|
<el-button @click="visibleTypeAdd = false">取消</el-button>
|
||||||
<el-button type="primary" @click="onSubmitType">提交</el-button>
|
<el-button type="primary" @click="onSubmitType">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -118,13 +98,16 @@
|
|||||||
<el-input-number :min="0" v-model="formInlineValue.orderNumber" placeholder="" />
|
<el-input-number :min="0" v-model="formInlineValue.orderNumber" placeholder="" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label=" 是否有效:">
|
<el-form-item label=" 是否有效:">
|
||||||
<el-switch v-model="formInlineValue.isActive" />
|
<el-switch @change="addhandleSwitchChange"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
v-model="formInlineValue.isActive" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="visibleValueAdd = false"> 取消 </el-button>
|
<el-button @click="visibleValueAdd = false">取消</el-button>
|
||||||
<el-button type="primary" @click="onSubmitvalue">提交</el-button>
|
<el-button type="primary" @click="onSubmitvalue">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -139,7 +122,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!--查看枚举值-->
|
<!--编辑枚举值-->
|
||||||
<el-dialog v-model="visibleValueEdit" title="查看枚举值" width="500" :before-close="edithandleClosevalue">
|
<el-dialog v-model="visibleValueEdit" title="查看枚举值" width="500" :before-close="edithandleClosevalue">
|
||||||
<el-form
|
<el-form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
@ -158,14 +141,17 @@
|
|||||||
<el-input-number :min="0" v-model="fromUpDate.orderNumber" placeholder="" />
|
<el-input-number :min="0" v-model="fromUpDate.orderNumber" placeholder="" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label=" 是否有效:">
|
<el-form-item label=" 是否有效:">
|
||||||
<el-switch v-model="fromUpDate.isActive" />
|
<el-switch @change="edithandleSwitchChange"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
v-model="fromUpDate.isActive" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="visibleValueEdit = false"> 取消 </el-button>
|
<el-button @click="visibleValueEdit = false"> 取消 </el-button>
|
||||||
<!-- <el-button type="primary" @click="onSubmitvalue">提交</el-button>-->
|
<el-button type="primary" @click="EditonSubmitvalue">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@ -182,13 +168,10 @@ import {
|
|||||||
enumTreeQuery,
|
enumTreeQuery,
|
||||||
enumTypeAdd,
|
enumTypeAdd,
|
||||||
enumValueAdd,
|
enumValueAdd,
|
||||||
enumValueDelete
|
enumValueDelete, enumValuepageEdit
|
||||||
} from "/@/api/backend/Enumeration/request";
|
} from "/@/api/backend/Enumeration/request";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const activeName = ref('1')
|
const activeName = ref('1')
|
||||||
interface Tree {
|
interface Tree {
|
||||||
enumId: number,
|
enumId: number,
|
||||||
@ -260,7 +243,6 @@ const handleNodeClick = (data: any) => {
|
|||||||
queryListData.description=queryName.value,
|
queryListData.description=queryName.value,
|
||||||
queryListData.pageNum=currentPage.value,
|
queryListData.pageNum=currentPage.value,
|
||||||
queryListData.pageSize=currentPageSize.value
|
queryListData.pageSize=currentPageSize.value
|
||||||
console.log(queryListData)
|
|
||||||
queryenumValueMethod(queryListData)
|
queryenumValueMethod(queryListData)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,13 +367,6 @@ const queryenumValueMethod = (data: any) => {
|
|||||||
const onSubmitvalue = () => {
|
const onSubmitvalue = () => {
|
||||||
formRef.value.validate((valid: any) => {
|
formRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if(formInlineValue.isActive==true){
|
|
||||||
formInlineValue.isActive=1
|
|
||||||
}else{
|
|
||||||
formInlineValue.isActive=0
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(formInlineValue)
|
|
||||||
enumValueAdd(formInlineValue).then((res: any) => {
|
enumValueAdd(formInlineValue).then((res: any) => {
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
queryListData.description =queryName.value
|
queryListData.description =queryName.value
|
||||||
@ -459,40 +434,66 @@ const dialogVisibleDelete1 = (done: () => void) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 菜单修改
|
// 编辑枚举值
|
||||||
const fromUpDate = reactive({
|
const fromUpDate = reactive({
|
||||||
id: '',
|
id: '',
|
||||||
enumTypeId: '',
|
enumTypeId: '',
|
||||||
value:'',
|
value:'',
|
||||||
description : '',
|
description : '',
|
||||||
orderNumber: 0,
|
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 visibleValueEdit = ref(false)
|
||||||
const enumValueEdit = (data: any) => {
|
const enumValueEdit = (data: any) => {
|
||||||
visibleValueEdit.value = true
|
visibleValueEdit.value = true
|
||||||
fromUpDate.id = data.row.id
|
fromUpDate.id = data.row.id
|
||||||
fromUpDate.enumTypeId = data.row.enumTypeId
|
fromUpDate.enumTypeId = data.row.enumTypeIdStr
|
||||||
fromUpDate.value = data.row.value
|
fromUpDate.value = data.row.value
|
||||||
fromUpDate.description = data.row.description
|
fromUpDate.description = data.row.description
|
||||||
fromUpDate.orderNumber = data.row.orderNumber
|
fromUpDate.orderNumber = data.row.orderNumber
|
||||||
if(data.row.isActive==1){
|
fromUpDate.isActive = data.row.isActive
|
||||||
fromUpDate.isActive = true
|
|
||||||
}else{
|
|
||||||
fromUpDate.isActive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const edithandleClosevalue = (done: () => void) => {
|
const edithandleClosevalue = (done: () => void) => {
|
||||||
visibleValueEdit.value = false
|
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(() => {
|
onMounted(() => {
|
||||||
enumTreeTypeList()
|
enumTreeTypeList()
|
||||||
const firstNode = TypeTree.value.store.root.childNodes[0];
|
|
||||||
/*if (firstNode) {
|
|
||||||
handleNodeClick(firstNode.data, null, TypeTree.value);
|
|
||||||
}*/
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="iotModelCode" :label="ModelFieldsEnums['iotModelCode']">
|
<el-form-item prop="iotModelCode" :label="ModelFieldsEnums['iotModelCode']">
|
||||||
<el-input
|
<el-input
|
||||||
:disabled="modelDialogState === ModelDialogTitleStateType['detail']"
|
:disabled="!(modelDialogState === ModelDialogTitleStateType['add'])"
|
||||||
v-model="modelForm.iotModelCode"
|
v-model="modelForm.iotModelCode"
|
||||||
:placeholder="'请输入' + ModelFieldsEnums['iotModelCode']"
|
:placeholder="'请输入' + ModelFieldsEnums['iotModelCode']"
|
||||||
></el-input>
|
></el-input>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="controlPage" v-loading="loading" element-loading-text="提交中...">
|
<div class="controlPage" v-loading="loading" element-loading-text="提交中...">
|
||||||
<h1 class="pageName">设备服务调试</h1>
|
<h1 class="pageName">遥调遥控调试</h1>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<el-form :model="serviceType147Form" :rules="validData(147)" ref="serviceType147Ref">
|
<el-form :model="serviceType147Form" :rules="validData(147)" ref="serviceType147Ref">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="1" :offset="2">
|
<el-col :span="2">
|
||||||
<div class="title">遥控</div>
|
<div class="title">遥控</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" :offset="1">
|
<el-col :span="10">
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<el-form-item label="服务名" prop="serviceName">
|
<el-form-item label="服务名" prop="serviceName">
|
||||||
<el-select v-model="serviceType147Form.serviceName" placeholder="请选择服务名">
|
<el-select v-model="serviceType147Form.serviceName" placeholder="请选择服务名">
|
||||||
@ -21,7 +21,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" :offset="1">
|
<el-col :span="7" :offset="1">
|
||||||
<el-form-item label="设定值" prop="opValue">
|
<el-form-item label="设定值" prop="opValue">
|
||||||
<el-select v-model="serviceType147Form.opValue" placeholder="请选择设定值">
|
<el-select v-model="serviceType147Form.opValue" placeholder="请选择设定值">
|
||||||
<el-option :value="0"></el-option>
|
<el-option :value="0"></el-option>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" :offset="1">
|
<el-col :span="2" :offset="1">
|
||||||
<el-button type="primary" @click="submit(147)">提交</el-button>
|
<el-button type="primary" @click="submit(147)">提交</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -37,10 +37,10 @@
|
|||||||
<br />
|
<br />
|
||||||
<el-form :model="serviceType146Form" :rules="validData(146)" ref="serviceType146Ref">
|
<el-form :model="serviceType146Form" :rules="validData(146)" ref="serviceType146Ref">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="1" :offset="2">
|
<el-col :span="2">
|
||||||
<div class="title">遥调</div>
|
<div class="title">遥调</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" :offset="1">
|
<el-col :span="10">
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<el-form-item label="服务名" prop="serviceName">
|
<el-form-item label="服务名" prop="serviceName">
|
||||||
<el-select v-model="serviceType146Form.serviceName" placeholder="请选择服务名">
|
<el-select v-model="serviceType146Form.serviceName" placeholder="请选择服务名">
|
||||||
@ -54,12 +54,12 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" :offset="1">
|
<el-col :span="7" :offset="1">
|
||||||
<el-form-item label="设定值" prop="opValue">
|
<el-form-item label="设定值" prop="opValue">
|
||||||
<el-input v-model="serviceType146Form.opValue" placeholder="请输入设定值"> </el-input>
|
<el-input v-model="serviceType146Form.opValue" placeholder="请输入设定值"> </el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" :offset="1">
|
<el-col :span="2" :offset="1">
|
||||||
<el-button type="primary" @click="submit(146)">提交</el-button>
|
<el-button type="primary" @click="submit(146)">提交</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -49,11 +49,13 @@
|
|||||||
<el-table-column property="model" label="规格型号" />
|
<el-table-column property="model" label="规格型号" />
|
||||||
<el-table-column property="address" label="操作">
|
<el-table-column property="address" label="操作">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span style="color: #0064aa; cursor: pointer" @click="openControl(scope)">调控 </span>
|
<span style="color: #0064aa; cursor: pointer" @click="openMeasure(scope)">量测</span>
|
||||||
<span style="color: #0064aa"> | </span>
|
<span style="color: #0064aa"> | </span>
|
||||||
<span style="color: #0064aa; cursor: pointer" @click="viewDeviceDetails(scope)">查看 </span>
|
<span style="color: #0064aa; cursor: pointer" @click="openControl(scope)">调控</span>
|
||||||
<span style="color: #0064aa"> | </span>
|
<span style="color: #0064aa"> | </span>
|
||||||
<span style="color: #0064aa; cursor: pointer" @click="deviceDeletion(scope)"> 删除 </span>
|
<span style="color: #0064aa; cursor: pointer" @click="viewDeviceDetails(scope)">查看</span>
|
||||||
|
<span style="color: #0064aa"> | </span>
|
||||||
|
<span style="color: #0064aa; cursor: pointer" @click="deviceDeletion(scope)">删除</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -420,16 +422,39 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-container>
|
</el-container>
|
||||||
<el-dialog v-model="showControlPage">
|
<el-dialog v-model="showControlPage" :width="800">
|
||||||
<div class="controlSlot">
|
<div class="controlSlot">
|
||||||
<ControlPage :deviceId="contorlData.deviceId" :iotModelId="contorlData.iotModelId" :show="showControlPage"></ControlPage>
|
<ControlPage :deviceId="contorlData.deviceId" :iotModelId="contorlData.iotModelId" :show="showControlPage"></ControlPage>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog v-model="showMeasure" title="量测" :width="800">
|
||||||
|
<template #header>
|
||||||
|
<div class="measureSlotHeader">
|
||||||
|
<span style="font-size: 20px">量测</span>
|
||||||
|
<div class="measureSlotHeaderRight">
|
||||||
|
<span>自动更新:</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="measureData.autoUpdate"
|
||||||
|
class="ml-2"
|
||||||
|
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
|
||||||
|
></el-switch>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="measureSlot">
|
||||||
|
<MeasurementPage
|
||||||
|
:show="showMeasure"
|
||||||
|
:deviceId="measureData.deviceId"
|
||||||
|
:iotModelId="measureData.iotModelId"
|
||||||
|
:autoUpdate="measureData.autoUpdate"
|
||||||
|
></MeasurementPage>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted, nextTick } from 'vue'
|
import { ref, reactive, onMounted, nextTick, watch } from 'vue'
|
||||||
import { Search, CirclePlusFilled, Upload, Download } from '@element-plus/icons-vue'
|
import { Search, CirclePlusFilled, Upload, Download } from '@element-plus/icons-vue'
|
||||||
import {
|
import {
|
||||||
equipTree,
|
equipTree,
|
||||||
@ -447,6 +472,7 @@ import { ElTable, ElMessage, ElMessageBox } from 'element-plus'
|
|||||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||||
import { encrypt_aes, generateRandomNumber } from '/@/utils/crypto'
|
import { encrypt_aes, generateRandomNumber } from '/@/utils/crypto'
|
||||||
import ControlPage from './control.vue'
|
import ControlPage from './control.vue'
|
||||||
|
import MeasurementPage from './measurement.vue'
|
||||||
|
|
||||||
const adminInfo = useAdminInfo()
|
const adminInfo = useAdminInfo()
|
||||||
interface Tree {
|
interface Tree {
|
||||||
@ -955,12 +981,34 @@ const contorlData = reactive({
|
|||||||
const openControl = (data: any) => {
|
const openControl = (data: any) => {
|
||||||
contorlData.deviceId = data.row.id
|
contorlData.deviceId = data.row.id
|
||||||
contorlData.iotModelId = data.row.iotModelId
|
contorlData.iotModelId = data.row.iotModelId
|
||||||
if(contorlData.iotModelId){
|
if (contorlData.iotModelId) {
|
||||||
showControlPage.value = true
|
showControlPage.value = true
|
||||||
}else{
|
} else {
|
||||||
ElMessage.warning('该设备没有绑定物模型!')
|
ElMessage.warning('该设备没有绑定物模型!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const measureData = reactive({
|
||||||
|
deviceId: '',
|
||||||
|
iotModelId: '',
|
||||||
|
autoUpdate: false,
|
||||||
|
})
|
||||||
|
const showMeasure = ref(false)
|
||||||
|
const openMeasure = (data: any) => {
|
||||||
|
measureData.deviceId = data.row.id
|
||||||
|
measureData.iotModelId = data.row.iotModelId
|
||||||
|
if (measureData.iotModelId) {
|
||||||
|
showMeasure.value = true
|
||||||
|
} else {
|
||||||
|
ElMessage.warning('该设备没有绑定物模型!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
showMeasure,
|
||||||
|
(newVal: boolean) => {
|
||||||
|
!newVal && (measureData.autoUpdate = false)
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -1052,4 +1100,10 @@ $paginationHeight: 32px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.measureSlotHeader {
|
||||||
|
display: flex;
|
||||||
|
.measureSlotHeaderRight {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -0,0 +1,233 @@
|
|||||||
|
<template>
|
||||||
|
<div class="measurement">
|
||||||
|
<el-table :columns="tableColumn" :data="tableData" @sort-change="sortChange" max-height="495">
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in tableColumn"
|
||||||
|
:key="item.prop"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.prop"
|
||||||
|
:width="item.width ?? ''"
|
||||||
|
:align="item.align"
|
||||||
|
:sortable="item.sortable"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="item.prop === 'realTimeValue'">
|
||||||
|
<el-button @click="openChart(scope.row)" text type="primary">{{ scope.row.realTimeValue }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="pageSetting.current"
|
||||||
|
v-model:page-size="pageSetting.pageSize"
|
||||||
|
:total="pageSetting.total"
|
||||||
|
:page-sizes="pageSetting.pageSizes"
|
||||||
|
background
|
||||||
|
:pager-count="7"
|
||||||
|
layout="prev, pager, next, jumper,sizes,total"
|
||||||
|
@change="getcurrentPage"
|
||||||
|
></el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import type { ModelAttributeFieldsEnums, GetModelAttributeType } from '/@/views/backend/auth/model/type'
|
||||||
|
import { getModelAttributeListReq, getRealValueListReq } from '/@/api/backend/deviceModel/request'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
iotModelId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
deviceId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
autoUpdate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const tableColumn = [
|
||||||
|
{
|
||||||
|
label: '序号',
|
||||||
|
prop: 'porder',
|
||||||
|
width: 76,
|
||||||
|
align: 'center',
|
||||||
|
sortable:'custom'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '属性名称',
|
||||||
|
prop: 'attributeName',
|
||||||
|
align: 'left',
|
||||||
|
sortable:'custom'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '属性编码',
|
||||||
|
prop: 'attributeCode',
|
||||||
|
align: 'left',
|
||||||
|
width: 200,
|
||||||
|
sortable:'custom'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '子系统',
|
||||||
|
prop: 'subSystem',
|
||||||
|
align: 'left',
|
||||||
|
width: 110,
|
||||||
|
sortable:false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '实时值',
|
||||||
|
prop: 'realTimeValue',
|
||||||
|
width: 140,
|
||||||
|
align: 'center',
|
||||||
|
sortable:false
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const tableData = ref<any[]>([])
|
||||||
|
|
||||||
|
const getAttributeList = () => {
|
||||||
|
const requestData: GetModelAttributeType = {
|
||||||
|
iotModelId: props.iotModelId,
|
||||||
|
pageNum: pageSetting.current,
|
||||||
|
pageSize: pageSetting.pageSize,
|
||||||
|
orderColumn: sortData.orderColumn,
|
||||||
|
orderType: sortData.orderType,
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
getModelAttributeListReq(requestData)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.rows && res.rows.length > 0) {
|
||||||
|
const codeList: any = []
|
||||||
|
const data = res.rows!.map((item) => {
|
||||||
|
codeList.push(item.attributeCode)
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
attributeTypeName:
|
||||||
|
item.attributeType === 138
|
||||||
|
? '模拟量'
|
||||||
|
: item.attributeType === 139
|
||||||
|
? '累积量'
|
||||||
|
: item.attributeType === 140
|
||||||
|
? '离散量'
|
||||||
|
: item.attributeType!,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pageSetting.total = res.total
|
||||||
|
resolve({ data, codeList })
|
||||||
|
} else {
|
||||||
|
if (res.rows && res.rows.length === 0) {
|
||||||
|
tableData.value = []
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getRealValueList = (data: { deviceId: string; attributes: string[] }, list?: any) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
getRealValueListReq([data]).then((res) => {
|
||||||
|
if (res.success && res.data) {
|
||||||
|
resolve({ realVal: res.data, list })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCompleteData = () => {
|
||||||
|
getAttributeList()
|
||||||
|
.then(({ data, codeList }: any) => {
|
||||||
|
return getRealValueList({ deviceId: props.deviceId, attributes: codeList }, data)
|
||||||
|
})
|
||||||
|
.then((realData: any) => {
|
||||||
|
const data = realData.list.map((item: any) => {
|
||||||
|
const realValItem = realData.realVal[props.deviceId]?.[item.attributeCode] ?? '-'
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
realTimeValue: realValItem % 1 === 0 ? realValItem : realValItem.toFixed(3),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tableData.value = data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortData = reactive<{ orderColumn?: keyof typeof ModelAttributeFieldsEnums; orderType?: 'asc' | 'desc' }>({
|
||||||
|
orderColumn: 'porder',
|
||||||
|
orderType: 'asc',
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortChange = ({ prop, order }: { prop: keyof typeof ModelAttributeFieldsEnums; order: 'ascending' | 'descending' | null }) => {
|
||||||
|
const propEnums = {
|
||||||
|
attributeCode: 'attribute_code',
|
||||||
|
attributeName: 'attribute_name',
|
||||||
|
attributeTypeName: 'attribute_type',
|
||||||
|
porder: 'porder',
|
||||||
|
serviceCode: 'service_code',
|
||||||
|
serviceName: 'service_name',
|
||||||
|
serviceTypeName: 'service_type',
|
||||||
|
}
|
||||||
|
const orderType = order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : undefined
|
||||||
|
const filed = propEnums[prop as keyof typeof propEnums] as keyof typeof ModelAttributeFieldsEnums
|
||||||
|
sortData.orderColumn = orderType ? filed : undefined
|
||||||
|
sortData.orderType = orderType
|
||||||
|
getCompleteData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageSetting = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
total: 0,
|
||||||
|
pageSizes: [10, 20, 30],
|
||||||
|
})
|
||||||
|
|
||||||
|
const getcurrentPage = () => {
|
||||||
|
getCompleteData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const openChart = (data: any) => {}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
(newVal) => {
|
||||||
|
newVal && getCompleteData()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let autoUpdateTimer: any = null
|
||||||
|
watch(
|
||||||
|
() => props.autoUpdate,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
if (!autoUpdateTimer) {
|
||||||
|
autoUpdateTimer = setInterval(() => {
|
||||||
|
console.log('刷新')
|
||||||
|
getCompleteData()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearInterval(autoUpdateTimer)
|
||||||
|
autoUpdateTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
237
ui/dasadmin/src/views/backend/home/windMatrix.vue
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<div class="FanList-content">
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="8" v-for="(item, index) in FanList" style="margin-bottom: 10px;">
|
||||||
|
<div class="grid-content ep-bg-purple">
|
||||||
|
<div class="FanList-panel" :class="item.standard==true ? 'wind-mark' : 'wind-default'">
|
||||||
|
<div class="fanlist-top">
|
||||||
|
<span :class="item.standard==true ? 'wind-mark-icon' : 'fanlist-icon'">
|
||||||
|
<img :class="item.standard==true ? '' : 'wind-picture'" src="~assets/dashboard/biaogan.png" alt="">
|
||||||
|
</span>
|
||||||
|
<span class="fanlist-name"> {{ item.windTurbine }}</span>
|
||||||
|
<el-tag class="tag-panel" :class="getItemClass(item)" type="primary">{{ item.windStatus }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="fanlist-main">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<div class="fanlist-pic">
|
||||||
|
<!-- <div class="mask">
|
||||||
|
<div class="leafs">
|
||||||
|
<div class="leaf_1"></div>
|
||||||
|
<div class="leaf_2"></div>
|
||||||
|
<div class="leaf_3"></div>
|
||||||
|
</div>
|
||||||
|
</div>-->
|
||||||
|
<img src="~assets/dashboard/fanlist1.png" alt="">
|
||||||
|
<!-- <img class="fc" src="~assets/dashboard/fanlist1.png" alt=""></img>-->
|
||||||
|
<!-- <img :style="{ transform: `rotate(${rotationDegrees}deg)` }" src="~assets/dashboard/fanlist1.png" alt="">-->
|
||||||
|
</div>
|
||||||
|
<div class="fanlist-pic">
|
||||||
|
<img src="~assets/dashboard/fanlist2.png" alt="">
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row class="fanlist-data">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="fanlist-text"><span class="content-number">{{ item.windSpeed }}</span><span>风速m/s</span></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="fanlist-text"><span class="content-number">{{ item.power }}</span><span>功率MW</span></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="fanlist-text"><span class="content-number">{{ item.dayGeneration }}</span><span>日发电量kWh</span></div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref ,onMounted,onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const FanList = ref([
|
||||||
|
{windSpeed:'10.34','power':'10.34','dayGeneration':'10.34',windStatus:'并网',windTurbine:'A-001',standard:true},
|
||||||
|
{windSpeed:'34','power':'10.34','dayGeneration':'10.34',windStatus:'待机',windTurbine:'A-002',standard:false},
|
||||||
|
{windSpeed:'11','power':'10.34','dayGeneration':'10.34',windStatus:'启动',windTurbine:'A-003',standard:false},
|
||||||
|
{windSpeed:'45','power':'10.34','dayGeneration':'10.34',windStatus:'解缆',windTurbine:'A-004',standard:false},
|
||||||
|
{windSpeed:'12','power':'10.34','dayGeneration':'10.34',windStatus:'电网故障停机',windTurbine:'A-005',standard:false},
|
||||||
|
{windSpeed:'10','power':'10.34','dayGeneration':'10.34',windStatus:'维护',windTurbine:'A-006',standard:false}
|
||||||
|
])
|
||||||
|
|
||||||
|
const getItemClass = (FanList) => {
|
||||||
|
switch (FanList.windStatus) {
|
||||||
|
case '并网':
|
||||||
|
return 'is-primary';
|
||||||
|
case '并网- AGC限功率':
|
||||||
|
return 'is-primary';
|
||||||
|
case '解缆':
|
||||||
|
return 'is-info';
|
||||||
|
case '待机':
|
||||||
|
return 'is-warning';
|
||||||
|
case '故障':
|
||||||
|
return 'is-warning';
|
||||||
|
case '启动':
|
||||||
|
return 'is-success';
|
||||||
|
case '电网故障停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '风速超限停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '故障停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '塔基手动停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '远程监控停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case 'AGC停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '集控停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '小风停机':
|
||||||
|
return 'is-danger';
|
||||||
|
case '维护':
|
||||||
|
return 'is-maintenance';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return { FanList, getItemClass };
|
||||||
|
};
|
||||||
|
|
||||||
|
const rotationDegrees = ref(0)
|
||||||
|
const speed = 5; // 设定一个基本旋转速度
|
||||||
|
function startRotation(speed) {
|
||||||
|
return setInterval(() => {
|
||||||
|
rotationDegrees.value += 100;
|
||||||
|
}, 100); // 每100毫秒旋转一次
|
||||||
|
}
|
||||||
|
let intervalId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 当组件挂载时开始旋转
|
||||||
|
intervalId = startRotation(speed);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// 当组件卸载时清除定时器
|
||||||
|
clearInterval(intervalId);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.wind-mark{
|
||||||
|
background-image: linear-gradient(140deg, #FFE3E3 0%, #FFFFFF 93%);
|
||||||
|
border: 1px solid #FFE3E3;
|
||||||
|
}
|
||||||
|
.wind-default{
|
||||||
|
background-image: linear-gradient(180deg, #F0F6FF 0%, #FFFFFF 50%);
|
||||||
|
border: 1px solid #E1EDF6;
|
||||||
|
}
|
||||||
|
.wind-picture{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.wind-mark-icon{
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid #FFE3E3;
|
||||||
|
border-radius: 8px 0 100px 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FanList-panel{
|
||||||
|
border-radius: 8px;
|
||||||
|
.fanlist-top{
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.fanlist-icon{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.fanlist-name{
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
.tag-panel{
|
||||||
|
border-radius: 0 8px 0 0;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.is-primary{
|
||||||
|
background: rgba(2,119,179,0.20);
|
||||||
|
border: 1px solid #0277B3;
|
||||||
|
color: #0277B3;
|
||||||
|
}
|
||||||
|
.is-success{
|
||||||
|
background: rgba(6,180,41,0.20);
|
||||||
|
border: 1px solid #06B429;
|
||||||
|
color: #06B429;
|
||||||
|
}
|
||||||
|
.is-info{
|
||||||
|
background: rgba(48,89,236,0.20);
|
||||||
|
border: 1px solid #3059EC;
|
||||||
|
color: #3059EC;
|
||||||
|
}
|
||||||
|
.is-warning{
|
||||||
|
background: rgba(255,126,0,0.20);
|
||||||
|
border: 1px solid #FF7E00;
|
||||||
|
color: #FF7E00;
|
||||||
|
}
|
||||||
|
.is-danger{
|
||||||
|
background: rgba(254,55,49,0.20);
|
||||||
|
border: 1px solid #FE3731;
|
||||||
|
color: #FE3731;
|
||||||
|
}
|
||||||
|
.is-offline{
|
||||||
|
background: rgba(153,153,153,0.20);
|
||||||
|
border: 1px solid #999999;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.is-maintenance{
|
||||||
|
background: rgba(0,160,150,0.20);
|
||||||
|
border: 1px solid #00A096;
|
||||||
|
color: #00A096;
|
||||||
|
}
|
||||||
|
.fanlist-main{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
.fanlist-pic{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: -10px;
|
||||||
|
.mask{
|
||||||
|
width: 43px;
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fanlist-text{
|
||||||
|
margin-top:30px;
|
||||||
|
.content-number{
|
||||||
|
color: #333333;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.fanlist-text span{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
459
ui/dasadmin/src/views/backend/linkMonitor/index.vue
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
<template>
|
||||||
|
<div class="linkMonitor">
|
||||||
|
<el-container class="containerPart">
|
||||||
|
<el-aside class="asidePart">
|
||||||
|
<el-header class="asideHeader">
|
||||||
|
<el-input
|
||||||
|
v-model="searchLinkTreeInputValue"
|
||||||
|
:suffix-icon="Search"
|
||||||
|
clearable
|
||||||
|
@input="debounceSearchLinkTree"
|
||||||
|
placeholder="搜索"
|
||||||
|
class="searchLinkTreeInput"
|
||||||
|
></el-input>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="treeMain">
|
||||||
|
<el-tree
|
||||||
|
ref="linkTreeRef"
|
||||||
|
node-key="id"
|
||||||
|
:data="treeData"
|
||||||
|
@node-click="linkTreeNodeClick"
|
||||||
|
@node-expand="linkTreeNodeExpand"
|
||||||
|
@node-collapse="linkTreeNodeCollapse"
|
||||||
|
:props="LinkTreePropReplace"
|
||||||
|
class="treePart"
|
||||||
|
highlight-current
|
||||||
|
:render-content="renderContent"
|
||||||
|
:default-expanded-keys="linkTreeNodeExpandKeys"
|
||||||
|
>
|
||||||
|
<!-- <template #default="{ node, data }">
|
||||||
|
<span>{{ node.label }}</span>
|
||||||
|
</template> -->
|
||||||
|
</el-tree>
|
||||||
|
</el-main>
|
||||||
|
</el-aside>
|
||||||
|
<el-container class="mainContainer">
|
||||||
|
<el-header class="mainHeader">
|
||||||
|
<div class="mainHeaderCenter">
|
||||||
|
<el-input clearable placeholder="请输入链路名称" class="linkMonitorInput" v-model="linkMonitorInputValue"></el-input>
|
||||||
|
<el-button :icon="Search" type="primary" @click="searchLinkMonitor">查询</el-button>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="mainMain">
|
||||||
|
<div class="tabsPart">
|
||||||
|
<el-table :data="linkMonitorTableData" class="tablePart" highlight-current-row>
|
||||||
|
<el-table-column prop="linkName" :label="LinkMonitorFieldsEnums['linkName']" align="left"> </el-table-column>
|
||||||
|
<el-table-column prop="status" :label="LinkMonitorFieldsEnums['status']" align="center" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="status-container">
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'status-dot-online': !scope.row.status,
|
||||||
|
'status-dot-offline': scope.row.status,
|
||||||
|
}"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="protocolName" :label="LinkMonitorFieldsEnums['protocolName']" align="center">
|
||||||
|
<template #default="scope"> </template>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- <el-table-column prop="remoteRegulation" :label="LinkMonitorFieldsEnums['remoteRegulation']" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span style="cursor: pointer; color: #0064aa; font-weight: 600">查看参数</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column> -->
|
||||||
|
<el-table-column label="操作" width="200" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="tableOperate">
|
||||||
|
<a @click="opneLog(scope.row)">日志</a>
|
||||||
|
<a>|</a>
|
||||||
|
<a @click="startLink(scope.row)">启动</a>
|
||||||
|
<a>|</a>
|
||||||
|
<el-popconfirm title="确定停止么?" @confirm="stopLink(scope.row)">
|
||||||
|
<template #reference>
|
||||||
|
<a style="color: red">停止</a>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="mainFooter">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="paginationOptions.current"
|
||||||
|
v-model:page-size="paginationOptions.pageSize"
|
||||||
|
:total="paginationOptions.total"
|
||||||
|
:page-sizes="paginationOptions.pageSizes"
|
||||||
|
background
|
||||||
|
:pager-count="7"
|
||||||
|
layout="prev, pager, next, jumper,sizes,total"
|
||||||
|
@change="getcurrentPage"
|
||||||
|
></el-pagination>
|
||||||
|
</div>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
<el-dialog v-model="linkLogVisible" title="日志" @close="closeLinklog" :width="900">
|
||||||
|
<template #footer> </template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, nextTick } from 'vue'
|
||||||
|
import { ElContainer, ElAside, ElHeader, ElMain, ElTree, ElInput, ElMessage, ElButton, ElTable, TreeInstance } from 'element-plus'
|
||||||
|
import { Search } from '@element-plus/icons-vue'
|
||||||
|
import { LinkMonitorFieldsEnums, LinkMonitorTreeType, LinkMonitorTableType } from './type'
|
||||||
|
import { getNodeListReq, getLinkListReq } from '/@/api/backend/linkMonitor/request'
|
||||||
|
import { debounce, cloneDeep } from 'lodash'
|
||||||
|
|
||||||
|
const LinkTreePropReplace = {
|
||||||
|
label: 'nodeName',
|
||||||
|
children: 'children',
|
||||||
|
}
|
||||||
|
const linkTreeRef = ref<TreeInstance>()
|
||||||
|
const treeData = ref<LinkMonitorTreeType[]>([])
|
||||||
|
const originTreeData = ref<LinkMonitorTreeType[]>([])
|
||||||
|
const curContextMenuTreeData = ref<LinkMonitorTreeType>()
|
||||||
|
const searchLinkTreeInputValue = ref('')
|
||||||
|
const getlinkTreeList = () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
getNodeListReq()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
originTreeData.value = res.data!
|
||||||
|
treeData.value = res.data!
|
||||||
|
// originTreeData.value = res.data!
|
||||||
|
// const other = [
|
||||||
|
// {
|
||||||
|
// id: '5555',
|
||||||
|
// nodeName: '鱼丸吃人111112222222222222222222222222222222',
|
||||||
|
// nodeIp: '',
|
||||||
|
// orgName: '',
|
||||||
|
// orgId: '',
|
||||||
|
// revision: 0,
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// id: '1111',
|
||||||
|
// nodeName: '鱼丸吃人22222',
|
||||||
|
// nodeIp: '',
|
||||||
|
// orgName: '',
|
||||||
|
// orgId: '',
|
||||||
|
// revision: 0,
|
||||||
|
// children: [],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
// originTreeData.value[0].children = [...other]
|
||||||
|
// originTreeData.value[1] = {
|
||||||
|
// id: '55654',
|
||||||
|
// nodeName: '鱼丸吃人33',
|
||||||
|
// nodeIp: '',
|
||||||
|
// orgName: '',
|
||||||
|
// orgId: '',
|
||||||
|
// revision: 0,
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// id: '324232',
|
||||||
|
// nodeName: '鱼丸吃人11',
|
||||||
|
// nodeIp: '',
|
||||||
|
// orgName: '',
|
||||||
|
// orgId: '',
|
||||||
|
// revision: 0,
|
||||||
|
// children: [],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// }
|
||||||
|
// const tree: LinkMonitorTreeType[] = [...originTreeData.value]
|
||||||
|
// treeData.value = tree
|
||||||
|
|
||||||
|
resolve(res.data![0])
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getlinkTreeList().then((res) => {
|
||||||
|
curContextMenuTreeData.value = cloneDeep(res as LinkMonitorTreeType)
|
||||||
|
linkTreeRef.value?.setCurrentKey(curContextMenuTreeData.value!.id!)
|
||||||
|
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const searchLinkTree = () => {
|
||||||
|
if (searchLinkTreeInputValue.value === '') {
|
||||||
|
treeData.value = originTreeData.value
|
||||||
|
nextTick(() => {
|
||||||
|
linkTreeRef.value?.setCurrentKey(curContextMenuTreeData.value!.id!)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
treeData.value = filterAndHighlightTreeArray(cloneDeep(originTreeData.value), searchLinkTreeInputValue.value) as LinkMonitorTreeType[]
|
||||||
|
linkTreeNodeExpandKeys.value = Array.from(new Set([...linkTreeNodeExpandKeys.value, ...getAllIds(treeData.value)]))
|
||||||
|
nextTick(() => {
|
||||||
|
linkTreeRef.value?.setCurrentKey(curContextMenuTreeData.value!.id!)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getAllIds = (nodes: LinkMonitorTreeType[]) => {
|
||||||
|
let ids: any = []
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
ids.push(node.id)
|
||||||
|
if (node.children && node.children.length > 0) {
|
||||||
|
ids = ids.concat(getAllIds(node.children))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
const filterAndHighlightTreeArray = (treeArray: LinkMonitorTreeType[], searchQuery: string) => {
|
||||||
|
return treeArray.map((tree: LinkMonitorTreeType) => filterAndHighlightTree(tree, searchQuery)).filter(Boolean)
|
||||||
|
}
|
||||||
|
const filterAndHighlightTree = (tree: LinkMonitorTreeType, searchQuery: string): (LinkMonitorTreeType & { isMatch?: boolean }) | null => {
|
||||||
|
const isMatch = tree.nodeName.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
|
if (isMatch) {
|
||||||
|
return {
|
||||||
|
...tree,
|
||||||
|
children: tree?.children?.map((child) => filterAndHighlightTree(child, searchQuery)).filter(Boolean) as LinkMonitorTreeType[],
|
||||||
|
isMatch: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tree.children && tree.children.length > 0) {
|
||||||
|
const filteredChildren = tree.children.map((child) => filterAndHighlightTree(child, searchQuery)).filter(Boolean) as LinkMonitorTreeType[]
|
||||||
|
|
||||||
|
if (filteredChildren.length > 0) {
|
||||||
|
return { ...tree, children: filteredChildren }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const debounceSearchLinkTree = debounce(searchLinkTree, 200)
|
||||||
|
|
||||||
|
const linkTreeNodeExpandKeys = ref([] as any)
|
||||||
|
const linkTreeNodeExpand = (node: any) => {
|
||||||
|
if (!linkTreeNodeExpandKeys.value.includes(node.id)) {
|
||||||
|
linkTreeNodeExpandKeys.value.push(node.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const linkTreeNodeCollapse = (node: any) => {
|
||||||
|
const index = linkTreeNodeExpandKeys.value.indexOf(node.id)
|
||||||
|
if (index > -1) {
|
||||||
|
linkTreeNodeExpandKeys.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const linkTreeNodeClick = (target: LinkMonitorTreeType) => {
|
||||||
|
curContextMenuTreeData.value = cloneDeep(target)
|
||||||
|
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
|
||||||
|
}
|
||||||
|
const renderContent = (h: any, { node, data }: any) => {
|
||||||
|
const label = node.label || ''
|
||||||
|
const searchTerm = searchLinkTreeInputValue.value.toLowerCase()
|
||||||
|
const startIndex = label.toLowerCase().indexOf(searchTerm)
|
||||||
|
if (startIndex === -1) {
|
||||||
|
return h('span', {}, label)
|
||||||
|
}
|
||||||
|
const beforeMatch = label.substring(0, startIndex)
|
||||||
|
const matchText = label.substring(startIndex, startIndex + searchLinkTreeInputValue.value.length)
|
||||||
|
const afterMatch = label.substring(startIndex + searchLinkTreeInputValue.value.length)
|
||||||
|
return h('span', {}, [beforeMatch, h('span', { style: { color: '#f14c4c', fontWeight: 'bold' } }, matchText), afterMatch])
|
||||||
|
}
|
||||||
|
const linkMonitorInputValue = ref('')
|
||||||
|
const searchLinkMonitor = () => {
|
||||||
|
if (linkMonitorInputValue.value === '') {
|
||||||
|
getlinkMonitorList(curContextMenuTreeData.value!.id!)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkMonitorTableData = ref<LinkMonitorTableType[]>([])
|
||||||
|
|
||||||
|
// 链路监视列表
|
||||||
|
const paginationOptions = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
pageSizes: [10, 20, 30],
|
||||||
|
})
|
||||||
|
const getcurrentPage = () => {
|
||||||
|
getlinkMonitorList(curContextMenuTreeData.value!.id!, linkMonitorInputValue.value)
|
||||||
|
}
|
||||||
|
const protocolList = [
|
||||||
|
{ label: 'IEC104主 *', value: 8 },
|
||||||
|
{ label: 'IEC104从 *', value: 9 },
|
||||||
|
{ label: 'MODBUSRTU主 *', value: 12 },
|
||||||
|
{ label: 'MODBUSTCP主 *', value: 16 },
|
||||||
|
]
|
||||||
|
const getlinkMonitorList = (nodeId: string, linkName?: string) => {
|
||||||
|
getLinkListReq({ nodeId, linkName, pageNum: paginationOptions.current, pageSize: paginationOptions.pageSize })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.rows) {
|
||||||
|
linkMonitorTableData.value = res.rows.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
protocolName: protocolList.find((i) => i.value === item.protocol)?.label,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
paginationOptions.total = res.total
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg ?? '查询失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkLogVisible = ref(false)
|
||||||
|
const closeLinklog = () => {
|
||||||
|
linkLogVisible.value = false
|
||||||
|
}
|
||||||
|
const opneLog = (val: LinkMonitorTableType) => {
|
||||||
|
// linkLogVisible.value = true
|
||||||
|
}
|
||||||
|
const startLink = (val: LinkMonitorTableType) => {
|
||||||
|
console.log('startLink')
|
||||||
|
}
|
||||||
|
const stopLink = (val: LinkMonitorTableType) => {
|
||||||
|
console.log('stopLink')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$headerHeight: 60px;
|
||||||
|
$defaultBackgroundColor: #fff;
|
||||||
|
$defaultAsideWidth: 260px;
|
||||||
|
$paginationHeight: 32px;
|
||||||
|
.linkMonitor {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
.containerPart {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
.asidePart {
|
||||||
|
width: $defaultAsideWidth;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #eaebed;
|
||||||
|
.asideHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.searchLinkTreeInput {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.treeMain {
|
||||||
|
height: calc(100% - $headerHeight);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.treePart {
|
||||||
|
min-width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: $defaultBackgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mainContainer {
|
||||||
|
width: calc(100% - $defaultAsideWidth);
|
||||||
|
height: 100%;
|
||||||
|
.mainHeader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: $headerHeight;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-bottom: 1px solid #eaebed;
|
||||||
|
.linkMonitorInput {
|
||||||
|
height: 40px;
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
.mainHeaderCenter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 320px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mainMain {
|
||||||
|
height: calc(100% - $headerHeight);
|
||||||
|
.tabsPart {
|
||||||
|
height: calc(100% - $paginationHeight);
|
||||||
|
padding-bottom: 5px;
|
||||||
|
:deep(.el-tabs__content) {
|
||||||
|
height: calc(100% - 55px);
|
||||||
|
.el-tab-pane {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tablePart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.tableOperate {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
a {
|
||||||
|
margin: 5px;
|
||||||
|
color: #0064aa;
|
||||||
|
font-weight: 600;
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mainFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.modelOperate {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 80px;
|
||||||
|
height: 150px;
|
||||||
|
.el-button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
.status-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.status-dot-online,
|
||||||
|
.status-dot-offline {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot-online {
|
||||||
|
background-color: #06b429;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot-offline {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.highlight {
|
||||||
|
background-color: yellow; /* 高亮背景颜色 */
|
||||||
|
color: red; /* 字体颜色 */
|
||||||
|
font-weight: bold; /* 加粗字体 */
|
||||||
|
}
|
||||||
|
</style>
|
45
ui/dasadmin/src/views/backend/linkMonitor/type.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
export type RequestReturnType<T = never> = Promise<{
|
||||||
|
code: number
|
||||||
|
msg: string
|
||||||
|
success: boolean
|
||||||
|
data?: T
|
||||||
|
}>
|
||||||
|
|
||||||
|
export type RequestReturnRowType<T = never> = 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' = '协议类型',
|
||||||
|
}
|
@ -103,7 +103,8 @@ let timer: number
|
|||||||
|
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const adminInfo = useAdminInfo()
|
const adminInfo = useAdminInfo()
|
||||||
toggleDark(config.layout.isDark)
|
|
||||||
|
// TODO 切换暗黑 toggleDark(config.layout.isDark)
|
||||||
|
|
||||||
const formRef = ref<FormInstance>()
|
const formRef = ref<FormInstance>()
|
||||||
const usernameRef = ref<InputInstance>()
|
const usernameRef = ref<InputInstance>()
|
||||||
|