Merge branch 'main' of https://git.jsspisoft.com/ry-das
This commit is contained in:
commit
c0d34288e5
14
das/pom.xml
14
das/pom.xml
@ -24,7 +24,7 @@
|
||||
|
||||
<postgresql.version>42.7.3</postgresql.version>
|
||||
<sa.version>1.38.0</sa.version>
|
||||
<easyexcel.version>4.0.1</easyexcel.version>
|
||||
<easyexcel.version>3.2.1</easyexcel.version>
|
||||
<annotations.version>4.8.6</annotations.version>
|
||||
<undertow.version>2.3.14.Final</undertow.version>
|
||||
<apache.poi>5.3.0</apache.poi>
|
||||
@ -189,6 +189,18 @@
|
||||
<version>${annotations.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>${easyexcel.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -60,6 +60,15 @@ public class DecryptingOncePerRequestFilter extends OncePerRequestFilter {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
// if (POST.matches(method) && StrUtil.isNotBlank(contentType) && contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE)){
|
||||
//
|
||||
// String iv = request.getHeader(IV_ATTR_NAME);
|
||||
// // 包装请求以修改参数
|
||||
// DecryptingRequestWrapper wrappedRequest = new DecryptingRequestWrapper(request,aesKey,iv);
|
||||
// filterChain.doFilter(wrappedRequest, response);
|
||||
// } else {
|
||||
// filterChain.doFilter(request, response);
|
||||
// }
|
||||
}
|
||||
|
||||
private String readRequestBody(HttpServletRequest request) throws IOException {
|
||||
|
@ -0,0 +1,67 @@
|
||||
//package com.das.common.interceptor;
|
||||
//
|
||||
//import com.das.common.utils.AESUtil;
|
||||
//import jakarta.servlet.http.HttpServletRequest;
|
||||
//import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
//
|
||||
//import java.io.IOException;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//public class DecryptingRequestWrapper extends HttpServletRequestWrapper {
|
||||
// private final Map<String, String[]> decryptedParameters = new HashMap<>();
|
||||
//
|
||||
// public DecryptingRequestWrapper(HttpServletRequest request,String aeskey,String iv) throws IOException {
|
||||
// super(request);
|
||||
//
|
||||
// // 提取并解密参数,忽略文件部分
|
||||
// request.getParameterMap().forEach((key, values) -> {
|
||||
// if (!isFileParameter(key)) {
|
||||
// String[] decryptedValues = new String[values.length];
|
||||
// for (int i = 0; i < values.length; i++) {
|
||||
// decryptedValues[i] = decrypt(values[i],aeskey,iv); // 对每个值进行解密
|
||||
// }
|
||||
// decryptedParameters.put(key, decryptedValues);
|
||||
// }
|
||||
// else {
|
||||
// decryptedParameters.put(key,values);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getParameter(String name) {
|
||||
// if (decryptedParameters.containsKey(name)) {
|
||||
// return decryptedParameters.get(name)[0];
|
||||
// }
|
||||
// return super.getParameter(name);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String[] getParameterValues(String name) {
|
||||
// if (decryptedParameters.containsKey(name)) {
|
||||
// return decryptedParameters.get(name);
|
||||
// }
|
||||
// return super.getParameterValues(name);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Map<String, String[]> getParameterMap() {
|
||||
// Map<String, String[]> parameterMap = new HashMap<>(super.getParameterMap());
|
||||
// parameterMap.putAll(decryptedParameters);
|
||||
// return parameterMap;
|
||||
// }
|
||||
//
|
||||
// // 解密
|
||||
// private String decrypt(String value,String aeskey,String iv) {
|
||||
// // 解密
|
||||
// return AESUtil.decrypt(aeskey, value, iv);
|
||||
// }
|
||||
//
|
||||
// //判断是否为文件参数
|
||||
// private boolean isFileParameter(String key) {
|
||||
// // 实现用于判断 key 是否代表文件参数的逻辑
|
||||
// // 比如通过检查命名约定或文件类型
|
||||
// return key.equalsIgnoreCase("file");
|
||||
// }
|
||||
//}
|
123
das/src/main/java/com/das/common/utils/CommonFunction.java
Normal file
123
das/src/main/java/com/das/common/utils/CommonFunction.java
Normal file
@ -0,0 +1,123 @@
|
||||
package com.das.common.utils;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 常用函数
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
public class CommonFunction {
|
||||
/**
|
||||
* description:定义一个System.out.println(纯属个人习惯)
|
||||
**/
|
||||
private static int objectNullSystemOutFlag = 0;
|
||||
|
||||
/**
|
||||
* description:判断当前对象是否为空(包括所有属性为空)
|
||||
*
|
||||
* @author 王凯
|
||||
* @param object 入参类
|
||||
* @return boolean
|
||||
* @create 2022-06-28
|
||||
**/
|
||||
public static boolean objCheckIsNull(Object object) {
|
||||
if (object == null) {
|
||||
return true;
|
||||
}
|
||||
// 得到类对象
|
||||
Class clazz = object.getClass();
|
||||
// 得到所有属性
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
//定义返回结果,默认为true
|
||||
boolean flag = true;
|
||||
for (Field field : fields) {
|
||||
//设置权限(很重要,否则获取不到private的属性,不了解的同学补习一下反射知识)
|
||||
field.setAccessible(true);
|
||||
Object fieldValue = null;
|
||||
String fieldName = null;
|
||||
try {
|
||||
//得到属性值
|
||||
fieldValue = field.get(object);
|
||||
//得到属性类型
|
||||
Type fieldType = field.getGenericType();
|
||||
//得到属性名
|
||||
fieldName = field.getName();
|
||||
//打印输出(调试用可忽略)
|
||||
if (objectNullSystemOutFlag == 1) {
|
||||
System.out.println("属性类型:" + fieldType + ",属性名:" + fieldName + ",属性值:" + fieldValue);
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//只要有一个属性值不为null 就返回false 表示对象不为null 忽略序列化
|
||||
if (fieldValue != null && !"serialVersionUID".equals(fieldName)) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断整行单元格数据是否均为空
|
||||
*/
|
||||
private static boolean isLineNullValue(Object data) {
|
||||
if (data instanceof String) {
|
||||
return isNull(data);
|
||||
}
|
||||
try {
|
||||
List<Field> fields = Arrays.stream(data.getClass().getDeclaredFields())
|
||||
.filter(f -> f.isAnnotationPresent(ExcelProperty.class))
|
||||
.collect(Collectors.toList());
|
||||
List<Boolean> lineNullList = new ArrayList<>(fields.size());
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(data);
|
||||
if (isNull(value)) {
|
||||
lineNullList.add(Boolean.TRUE);
|
||||
} else {
|
||||
lineNullList.add(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
return lineNullList.stream().allMatch(Boolean.TRUE::equals);
|
||||
} catch (Exception e) {
|
||||
log.error("读取数据行[{}]解析失败: {}", data, e.getMessage());
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断输入参数是否为空
|
||||
*
|
||||
* @param obj 输入参数
|
||||
* @return null is true
|
||||
*/
|
||||
public static boolean isNull(Object obj) {
|
||||
if (obj == null) {
|
||||
return true;
|
||||
}
|
||||
boolean isNull;
|
||||
if (obj instanceof String) {
|
||||
isNull = StringUtils.isEmpty((String) obj);
|
||||
} else if (obj instanceof Map) {
|
||||
isNull = ((Map<?, ?>) obj).isEmpty();
|
||||
} else if (obj instanceof Collection) {
|
||||
isNull = ((Collection<?>) obj).isEmpty();
|
||||
} else {
|
||||
isNull = false;
|
||||
}
|
||||
return isNull;
|
||||
}
|
||||
|
||||
}
|
41
das/src/main/java/com/das/common/utils/ExcelUtil.java
Normal file
41
das/src/main/java/com/das/common/utils/ExcelUtil.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.das.common.utils;
|
||||
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.converters.longconverter.LongStringConverter;
|
||||
import com.alibaba.excel.support.ExcelTypeEnum;
|
||||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* EXCEL处理工具类
|
||||
*
|
||||
* @author 王凯
|
||||
* @version 1.0.0
|
||||
* @since 2022-08-17
|
||||
*/
|
||||
public class ExcelUtil {
|
||||
|
||||
/** 导出 */
|
||||
public static void download(HttpServletResponse response, String fileName,
|
||||
Class cls, List dataList, String sheetName)
|
||||
throws IOException {
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
String encodeFileName = URLEncoder.encode(fileName, "utf-8");
|
||||
response.setHeader("Content-disposition",
|
||||
"attachment;filename=" + encodeFileName + ExcelTypeEnum.XLSX.getValue());
|
||||
LongestMatchColumnWidthStyleStrategy longestMatchColumnWidthStyleStrategy =
|
||||
new LongestMatchColumnWidthStyleStrategy();
|
||||
EasyExcel.write(response.getOutputStream(), cls)
|
||||
.sheet(sheetName)
|
||||
.registerWriteHandler(longestMatchColumnWidthStyleStrategy)
|
||||
.registerConverter(new LongStringConverter())
|
||||
.doWrite(dataList);
|
||||
response.flushBuffer();
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package com.das.modules.curve.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
|
||||
import com.das.common.constant.SysAuthorityIds;
|
||||
import com.das.common.result.R;
|
||||
import com.das.common.utils.PageDataInfo;
|
||||
import com.das.common.utils.PageQuery;
|
||||
import com.das.modules.curve.domain.dto.TheoreticalPowerCurveDto;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.domain.entity.TheoreticalPowerCurveEntity;
|
||||
import com.das.modules.curve.domain.excel.CurveItemExcel;
|
||||
import com.das.modules.curve.listener.CurveItemListener;
|
||||
import com.das.modules.curve.service.TheoreticalPowerCurveService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 风速功率曲线controller
|
||||
*/
|
||||
@Slf4j
|
||||
@RequestMapping("/api/curve")
|
||||
@RestController
|
||||
public class TheoreticalPowerCurveController {
|
||||
|
||||
@Autowired
|
||||
private TheoreticalPowerCurveService theoreticalPowerCurveService;
|
||||
|
||||
@Autowired
|
||||
private CurveItemListener curveItemListener;
|
||||
|
||||
/**
|
||||
* 新增制造商
|
||||
* @return 制造商
|
||||
*/
|
||||
@PostMapping("/create")
|
||||
public R<TheoreticalPowerCurveEntity> createTheoreticalPowerCurve(@RequestBody TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
//判断是否有权限
|
||||
boolean hasPermission = StpUtil.hasPermission(SysAuthorityIds.SYS_AUTHORITY_ID_DEVICE_MGR.toString());
|
||||
if(!hasPermission){
|
||||
return R.fail("没有设备管理权限");
|
||||
}
|
||||
return R.success(theoreticalPowerCurveService.createTheoreticalPowerCurve(theoreticalPowerCurveDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新制造商
|
||||
* @return 制造商
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public R<TheoreticalPowerCurveEntity> updateTheoreticalPowerCurve(@RequestBody TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
//判断是否有权限
|
||||
boolean hasPermission = StpUtil.hasPermission(SysAuthorityIds.SYS_AUTHORITY_ID_DEVICE_MGR.toString());
|
||||
if(!hasPermission){
|
||||
return R.fail("没有设备管理权限");
|
||||
}
|
||||
return R.success(theoreticalPowerCurveService.updateTheoreticalPowerCurve(theoreticalPowerCurveDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 阐述制造商
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public R<Void> deleteTheoreticalPowerCurve(@RequestBody TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
//判断是否有权限
|
||||
boolean hasPermission = StpUtil.hasPermission(SysAuthorityIds.SYS_AUTHORITY_ID_DEVICE_MGR.toString());
|
||||
if(!hasPermission){
|
||||
return R.fail("没有设备管理权限");
|
||||
}
|
||||
theoreticalPowerCurveService.deleteTheoreticalPowerCurve(theoreticalPowerCurveDto);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询制造商信息
|
||||
* @param id 制造商id
|
||||
* @return 制造商信息
|
||||
*/
|
||||
@GetMapping("/queryById")
|
||||
public R<TheoreticalPowerCurveEntity> queryTheoreticalPowerCurveById(String id) {
|
||||
return R.success(theoreticalPowerCurveService.queryTheoreticalPowerCurveById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有制造商
|
||||
* @return 所有制造商
|
||||
*/
|
||||
@PostMapping("/query")
|
||||
public PageDataInfo<TheoreticalPowerCurveEntity> queryAllCurve(@RequestBody PageQuery pageQuery) {
|
||||
return theoreticalPowerCurveService.getAllCurves(pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 速度功率曲线导出
|
||||
*/
|
||||
@PostMapping("/export")
|
||||
public void exportTheoreticalPowerCurve(@RequestBody TheoreticalPowerCurveDto theoreticalPowerCurveDto, HttpServletRequest request, HttpServletResponse response) {
|
||||
theoreticalPowerCurveService.exportTheoreticalPowerCurve(theoreticalPowerCurveDto,request, response);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 速度功率曲线导入
|
||||
*/
|
||||
@PostMapping("/import")
|
||||
public R<Void> importSysIotModel(String id, @RequestParam("file") MultipartFile file) throws IOException {
|
||||
curveItemListener.setParent(Long.valueOf(id));
|
||||
ExcelReaderBuilder read = EasyExcel.read(file.getInputStream(), CurveItemExcel.class,curveItemListener);
|
||||
read.sheet().doRead();
|
||||
return R.success("导入成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据制造商id查询速度功率曲线
|
||||
* @return 速度功率曲线
|
||||
*/
|
||||
@GetMapping("/queryItemByParent")
|
||||
public R<List<CurveItemEntity>> queryAllCurve(String madeinfactory,String model) {
|
||||
List<CurveItemEntity> curveItemEntityList = theoreticalPowerCurveService.queryCurveItemByParent(madeinfactory,model);
|
||||
return R.success(curveItemEntityList);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.das.modules.curve.domain.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TheoreticalPowerCurveDto {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String madeinfactory;
|
||||
|
||||
private String model;
|
||||
|
||||
private Float nominalCapacity;
|
||||
|
||||
private Integer revision;
|
||||
|
||||
private String createdBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createdTime;
|
||||
|
||||
private String updatedBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updatedTime;
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.das.modules.curve.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 风功率曲线数据
|
||||
*/
|
||||
@TableName("sys_theoretical_power_curve_item")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CurveItemEntity {
|
||||
|
||||
@TableId(value = "id")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@TableField(value = "parent")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long parent;
|
||||
|
||||
@TableField("speed")
|
||||
private Float speed;
|
||||
|
||||
@TableField("power")
|
||||
private Float power;
|
||||
|
||||
@TableField("revision")
|
||||
private Integer revision;
|
||||
|
||||
@TableField("created_by")
|
||||
private String createdBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField("created_time")
|
||||
private Date createdTime;
|
||||
|
||||
@TableField("updated_by")
|
||||
private String updatedBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField("updated_time")
|
||||
private Date updatedTime;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.das.modules.curve.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("sys_theoretical_power_curve")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TheoreticalPowerCurveEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@TableField("madeinfactory")
|
||||
private String madeinfactory;
|
||||
|
||||
@TableField("model")
|
||||
private String model;
|
||||
|
||||
@TableField("nominal_capacity")
|
||||
private Float nominalCapacity;
|
||||
|
||||
@TableField("revision")
|
||||
private Integer revision;
|
||||
|
||||
@TableField("created_by")
|
||||
private String createdBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField("created_time")
|
||||
private Date createdTime;
|
||||
|
||||
@TableField("updated_by")
|
||||
private String updatedBy;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField("updated_time")
|
||||
private Date updatedTime;
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.das.modules.curve.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class CurveItemExcel implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@ExcelProperty(value = "风速",index = 0)
|
||||
private Float speed;
|
||||
/**
|
||||
* 物模型ID
|
||||
*/
|
||||
@ExcelProperty(value = "功率",index = 1)
|
||||
private Float power;
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package com.das.modules.curve.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.das.common.exceptions.ServiceException;
|
||||
import com.das.common.utils.BeanCopyUtils;
|
||||
import com.das.common.utils.CommonFunction;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.domain.excel.CurveItemExcel;
|
||||
import com.das.modules.curve.service.impl.TheoreticalPowerCurveServiceImpl;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* 物模型属性监听器
|
||||
*
|
||||
* @author huguanghan
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@Data
|
||||
public class CurveItemListener extends AnalysisEventListener<CurveItemExcel> {
|
||||
@Autowired
|
||||
private TheoreticalPowerCurveServiceImpl theoreticalPowerCurveService;
|
||||
|
||||
public CurveItemListener(TheoreticalPowerCurveServiceImpl theoreticalPowerCurveService) {
|
||||
this.theoreticalPowerCurveService = theoreticalPowerCurveService;
|
||||
}
|
||||
|
||||
//parentId
|
||||
private Long parent;
|
||||
|
||||
/**计数标记*/
|
||||
private Integer flag=0;
|
||||
|
||||
/**存放插入*/
|
||||
ArrayList<CurveItemEntity> insertSysIotModelFieldList = new ArrayList<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void invoke(CurveItemExcel curveItemExcel, AnalysisContext analysisContext) {
|
||||
// 如果一行Excel数据均为空值,则不装载该行数据
|
||||
if (CommonFunction.objCheckIsNull(curveItemExcel)) {
|
||||
return;
|
||||
}
|
||||
log.info("解析到一条数据:{}", JSON.toJSONString(curveItemExcel));
|
||||
CurveItemEntity curveItem = new CurveItemEntity();
|
||||
BeanCopyUtils.copy(curveItemExcel, curveItem);
|
||||
curveItem.setParent(parent);
|
||||
//加入集合
|
||||
insertSysIotModelFieldList.add(curveItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
|
||||
//确保最后遗留的数据也存储到数据库
|
||||
if (!insertSysIotModelFieldList.isEmpty()){
|
||||
saveData();
|
||||
}
|
||||
log.info("所有数据解析完成!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 存储数据库
|
||||
* @return
|
||||
*/
|
||||
private void saveData() {
|
||||
log.info("{}条数据,开始存储数据库!", flag);
|
||||
try {
|
||||
theoreticalPowerCurveService.batchProcessing(insertSysIotModelFieldList,parent);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
throw new ServiceException(e.getMessage());
|
||||
}finally {
|
||||
clear();
|
||||
}
|
||||
log.info("存储数据库成功!");
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
//清理缓存
|
||||
insertSysIotModelFieldList.clear();
|
||||
flag=0;
|
||||
log.info("缓存已清理");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.das.modules.curve.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.domain.entity.TheoreticalPowerCurveEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CurveItemMapper extends BaseMapper<CurveItemEntity> {
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.das.modules.curve.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.das.modules.curve.domain.entity.TheoreticalPowerCurveEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TheoreticalPowerCurveMapper extends BaseMapper<TheoreticalPowerCurveEntity> {
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.das.modules.curve.service;
|
||||
|
||||
import com.das.common.utils.PageDataInfo;
|
||||
import com.das.common.utils.PageQuery;
|
||||
import com.das.modules.curve.domain.dto.TheoreticalPowerCurveDto;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.domain.entity.TheoreticalPowerCurveEntity;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TheoreticalPowerCurveService {
|
||||
PageDataInfo<TheoreticalPowerCurveEntity> getAllCurves(PageQuery pageQuery);
|
||||
|
||||
TheoreticalPowerCurveEntity createTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto);
|
||||
|
||||
TheoreticalPowerCurveEntity updateTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto);
|
||||
|
||||
void deleteTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto);
|
||||
|
||||
TheoreticalPowerCurveEntity queryTheoreticalPowerCurveById(String id);
|
||||
|
||||
void exportTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto, HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
List<CurveItemEntity> queryCurveItemByParent(String madeinfactory,String model);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package com.das.modules.curve.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.das.common.config.SessionUtil;
|
||||
import com.das.common.exceptions.ServiceException;
|
||||
import com.das.common.utils.*;
|
||||
import com.das.modules.auth.domain.vo.SysUserVo;
|
||||
import com.das.modules.curve.domain.dto.TheoreticalPowerCurveDto;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.domain.entity.TheoreticalPowerCurveEntity;
|
||||
import com.das.modules.curve.mapper.CurveItemMapper;
|
||||
import com.das.modules.curve.mapper.TheoreticalPowerCurveMapper;
|
||||
import com.das.modules.curve.service.TheoreticalPowerCurveService;
|
||||
import com.das.modules.equipment.domain.excel.SheetInfoBean;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class TheoreticalPowerCurveServiceImpl implements TheoreticalPowerCurveService {
|
||||
|
||||
@Autowired
|
||||
private TheoreticalPowerCurveMapper theoreticalPowerCurveMapper;
|
||||
|
||||
@Autowired
|
||||
private CurveItemMapper curveItemMapper;
|
||||
|
||||
@Override
|
||||
public PageDataInfo<TheoreticalPowerCurveEntity> getAllCurves(PageQuery pageQuery) {
|
||||
if (pageQuery.getPageNum() == null || pageQuery.getPageSize() == null){
|
||||
QueryWrapper<TheoreticalPowerCurveEntity> queryWrapper = new QueryWrapper<>();
|
||||
List<TheoreticalPowerCurveEntity> powerCurveEntityList = theoreticalPowerCurveMapper.selectList(queryWrapper);
|
||||
return PageDataInfo.build(powerCurveEntityList, powerCurveEntityList.size());
|
||||
}
|
||||
else {
|
||||
QueryWrapper<TheoreticalPowerCurveEntity> queryWrapper = new QueryWrapper<>();
|
||||
Page<TheoreticalPowerCurveEntity> pageList = theoreticalPowerCurveMapper.selectPage(pageQuery.build(), queryWrapper);
|
||||
return PageDataInfo.build(pageList.getRecords(), pageList.getTotal());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增厂家记录
|
||||
* @param theoreticalPowerCurveDto 参数dto
|
||||
* @return 新增厂家结果
|
||||
*/
|
||||
@Override
|
||||
public TheoreticalPowerCurveEntity createTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
//参数校验
|
||||
if (StringUtils.isAnyBlank(theoreticalPowerCurveDto.getMadeinfactory(),theoreticalPowerCurveDto.getModel())){
|
||||
throw new ServiceException("制造商,规格型号不能为空");
|
||||
}
|
||||
TheoreticalPowerCurveEntity theoreticalPowerCurveEntity = new TheoreticalPowerCurveEntity();
|
||||
BeanCopyUtils.copy(theoreticalPowerCurveDto, theoreticalPowerCurveEntity);
|
||||
theoreticalPowerCurveEntity.setId(IdWorker.getId());
|
||||
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
|
||||
theoreticalPowerCurveEntity.setCreatedTime(new Date());
|
||||
theoreticalPowerCurveEntity.setUpdatedTime(new Date());
|
||||
theoreticalPowerCurveEntity.setCreatedBy(sysUserVo.getAccount());
|
||||
theoreticalPowerCurveEntity.setUpdatedBy(sysUserVo.getAccount());
|
||||
theoreticalPowerCurveEntity.setRevision(1);
|
||||
|
||||
//校验制造商规格型号
|
||||
checkFactoryModelExsit(theoreticalPowerCurveEntity);
|
||||
theoreticalPowerCurveMapper.insert(theoreticalPowerCurveEntity);
|
||||
return theoreticalPowerCurveEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新厂家记录
|
||||
* @param theoreticalPowerCurveDto 参数dto
|
||||
* @return 更新厂家结果
|
||||
*/
|
||||
@Override
|
||||
public TheoreticalPowerCurveEntity updateTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
//参数校验
|
||||
if (StringUtils.isAnyBlank(theoreticalPowerCurveDto.getMadeinfactory(),theoreticalPowerCurveDto.getModel()) || theoreticalPowerCurveDto.getId() == null){
|
||||
throw new ServiceException("id,制造商,规格型号不能为空");
|
||||
}
|
||||
TheoreticalPowerCurveEntity theoreticalPowerCurveEntity = new TheoreticalPowerCurveEntity();
|
||||
BeanCopyUtils.copy(theoreticalPowerCurveDto, theoreticalPowerCurveEntity);
|
||||
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
|
||||
theoreticalPowerCurveEntity.setUpdatedTime(new Date());
|
||||
theoreticalPowerCurveEntity.setUpdatedBy(sysUserVo.getAccount());
|
||||
theoreticalPowerCurveEntity.setRevision(1);
|
||||
|
||||
//校验制造商规格型号
|
||||
checkFactoryModelExsit(theoreticalPowerCurveEntity);
|
||||
theoreticalPowerCurveMapper.updateById(theoreticalPowerCurveEntity);
|
||||
return theoreticalPowerCurveEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto) {
|
||||
if (theoreticalPowerCurveDto.getId() == null){
|
||||
throw new ServiceException("参数缺失");
|
||||
}
|
||||
|
||||
//删除关联曲线数据
|
||||
QueryWrapper<CurveItemEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("PARENT",theoreticalPowerCurveDto.getId());
|
||||
curveItemMapper.delete(queryWrapper);
|
||||
|
||||
//删除制造商数据
|
||||
theoreticalPowerCurveMapper.deleteById(theoreticalPowerCurveDto.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheoreticalPowerCurveEntity queryTheoreticalPowerCurveById(String id) {
|
||||
return theoreticalPowerCurveMapper.selectById(Long.valueOf(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportTheoreticalPowerCurve(TheoreticalPowerCurveDto theoreticalPowerCurveDto, HttpServletRequest request, HttpServletResponse response) {
|
||||
List<SheetInfoBean> exportList = new ArrayList<>();
|
||||
QueryWrapper<CurveItemEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("PARENT",theoreticalPowerCurveDto.getId());
|
||||
queryWrapper.orderByAsc("SPEED");
|
||||
List<CurveItemEntity> curveItemEntityList = curveItemMapper.selectList(queryWrapper);
|
||||
TheoreticalPowerCurveEntity theoreticalPowerCurve = theoreticalPowerCurveMapper.selectById(theoreticalPowerCurveDto.getId());
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
SheetInfoBean sheetDTO = new SheetInfoBean();
|
||||
map.put("speed", "风速");
|
||||
map.put("power", "功率");
|
||||
sheetDTO.setSheetName(theoreticalPowerCurve.getMadeinfactory());
|
||||
sheetDTO.setFieldAndAlias(map);
|
||||
sheetDTO.setCollection(curveItemEntityList);
|
||||
exportList.add(sheetDTO);
|
||||
HuExcelUtils.exportExcel(response, exportList, theoreticalPowerCurve.getMadeinfactory()+theoreticalPowerCurve.getModel()+"理论功率");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CurveItemEntity> queryCurveItemByParent(String madeinfactory,String model) {
|
||||
QueryWrapper<TheoreticalPowerCurveEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("madeinfactory",madeinfactory);
|
||||
queryWrapper.eq("MODEL",model);
|
||||
TheoreticalPowerCurveEntity theoreticalPowerCurveEntity = theoreticalPowerCurveMapper.selectOne(queryWrapper);
|
||||
QueryWrapper<CurveItemEntity> itemEntityQueryWrapper = new QueryWrapper<>();
|
||||
itemEntityQueryWrapper.eq("parent",theoreticalPowerCurveEntity.getId());
|
||||
itemEntityQueryWrapper.orderByAsc("SPEED");
|
||||
return curveItemMapper.selectList(itemEntityQueryWrapper);
|
||||
}
|
||||
|
||||
private void checkFactoryModelExsit(TheoreticalPowerCurveEntity theoreticalPowerCurveEntity){
|
||||
QueryWrapper<TheoreticalPowerCurveEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("madeinfactory",theoreticalPowerCurveEntity.getMadeinfactory());
|
||||
queryWrapper.eq("model",theoreticalPowerCurveEntity.getModel());
|
||||
TheoreticalPowerCurveEntity sameInfo = theoreticalPowerCurveMapper.selectOne(queryWrapper);
|
||||
if (sameInfo != null){
|
||||
throw new ServiceException("制造商规格型号已存在,请检查修改");
|
||||
}
|
||||
}
|
||||
|
||||
public void batchProcessing(List<CurveItemEntity> curveItemList, Long parent){
|
||||
//先删除制造商数据
|
||||
QueryWrapper<CurveItemEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("PARENT",parent);
|
||||
curveItemMapper.delete(queryWrapper);
|
||||
|
||||
//新增新的制造商数据
|
||||
for (CurveItemEntity item : curveItemList){
|
||||
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
|
||||
item.setCreatedTime(new Date());
|
||||
item.setUpdatedTime(new Date());
|
||||
item.setCreatedBy(sysUserVo.getAccount());
|
||||
item.setUpdatedBy(sysUserVo.getAccount());
|
||||
item.setRevision(1);
|
||||
curveItemMapper.insert(item);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import com.das.modules.equipment.mapper.SysEnumValuesMapper;
|
||||
import com.das.modules.equipment.service.SysEnumService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -29,6 +30,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Service
|
||||
public class SysEnumServiceImpl implements SysEnumService {
|
||||
|
||||
|
@ -19,6 +19,8 @@ public class WindTurbinesPageVo {
|
||||
|
||||
private String model;
|
||||
|
||||
private String madeinfactory;
|
||||
|
||||
private String belongLine;
|
||||
|
||||
private Map<String,Object> attributeMap;
|
||||
|
@ -104,6 +104,7 @@ public class WindTurbinesPageServiceImpl implements WindTurbinesPageService {
|
||||
windTurbinesPageVo.setIrn(item.getId());
|
||||
windTurbinesPageVo.setName(item.getName());
|
||||
windTurbinesPageVo.setModel(item.getModel());
|
||||
windTurbinesPageVo.setMadeinfactory(item.getMadeinFactory());
|
||||
windTurbinesPageVo.setModelId(item.getIotModelId());
|
||||
windTurbinesPageVo.setBelongLine(item.getBelongLine());
|
||||
windTurbinesPageVos.add(windTurbinesPageVo);
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
|
||||
<title>Loading...</title>
|
||||
</head>
|
||||
<body>
|
||||
|
68
ui/dasadmin/src/api/backend/theoreticalpowerCurve/request.ts
Normal file
68
ui/dasadmin/src/api/backend/theoreticalpowerCurve/request.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
import { encrypt_aes } from '/@/utils/crypto'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
const adminInfo = useAdminInfo()
|
||||
|
||||
export function theoreticalpowerCurveList(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/curve/query',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
export function saveData(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/curve/create',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
export function updateData(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/curve/update',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
export function deleteData(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/curve/delete',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
export const importData = (data: FormData, v: string) => {
|
||||
const token = encrypt_aes(adminInfo.token, v)
|
||||
return createAxios(
|
||||
{
|
||||
url: '/api/curve/import',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
v,
|
||||
token,
|
||||
},
|
||||
},
|
||||
{ customEncrypt: true }
|
||||
)
|
||||
}
|
||||
|
||||
// 导出
|
||||
export function exportData(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/curve/export',
|
||||
method: 'POST',
|
||||
data: params,
|
||||
responseType: 'blob',
|
||||
})
|
||||
}
|
||||
|
||||
export function powerCurveQuery(madeinfactory: any, model: any) {
|
||||
return createAxios({
|
||||
url: `/api/curve/queryItemByParent?madeinfactory=${madeinfactory}&model=${model}`,
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
@ -12,4 +12,5 @@ export default {
|
||||
max: '最大值',
|
||||
min: '最小值',
|
||||
average: '平均值',
|
||||
madeinfatory: '理论曲线',
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ const onMenuCollapse = function () {
|
||||
<style scoped lang="scss">
|
||||
.layout-logo {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
height: v-bind('config.headerHeight()');
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -25,10 +25,14 @@ import type { RouteRecordRaw } from 'vue-router'
|
||||
import { getFirstRoute, onClickMenu } from '/@/utils/router'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const config = useConfig()
|
||||
|
||||
const padding = computed(() => (window.screen.width < 1920 ? '10px' : '20px'))
|
||||
const height = computed(() => (window.screen.width < 1920 ? '40px' : '56px'))
|
||||
|
||||
interface Props {
|
||||
menus: RouteRecordRaw[]
|
||||
extends?: {
|
||||
@ -68,6 +72,16 @@ const onClickSubMenu = (menu: RouteRecordRaw) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-menu-item {
|
||||
padding: 0 v-bind(padding);
|
||||
height: v-bind(height);
|
||||
:deep(.el-menu-tooltip__trigger) {
|
||||
padding: 0 v-bind(padding);
|
||||
}
|
||||
}
|
||||
:deep(.el-sub-menu__title) {
|
||||
padding: 0 v-bind(padding);
|
||||
}
|
||||
.el-sub-menu .icon,
|
||||
.el-menu-item .icon {
|
||||
vertical-align: middle;
|
||||
|
@ -30,7 +30,7 @@ const state = reactive({
|
||||
})
|
||||
|
||||
const width = computed(() => {
|
||||
return config.layout.menuCollapse ? '5px' : '20px'
|
||||
return config.layout.menuCollapse ? '5px' : window.screen.width < 1920 ? '10px' : '20px'
|
||||
})
|
||||
|
||||
const verticalMenusScrollbarHeight = computed(() => {
|
||||
|
@ -15,9 +15,12 @@ import NavTabs from '/@/layouts/backend/components/navBar/tabs.vue'
|
||||
import { layoutNavTabsRef } from '/@/stores/refs'
|
||||
import NavMenus from '../navMenus.vue'
|
||||
import { showShade } from '/@/utils/pageShade'
|
||||
|
||||
import { computed } from 'vue'
|
||||
const config = useConfig()
|
||||
|
||||
const padding = computed(() => (window.screen.width < 1920 ? '10px' : '20px'))
|
||||
const height = computed(() => (window.screen.width < 1920 ? '36px' : '48px'))
|
||||
|
||||
const onMenuCollapse = () => {
|
||||
showShade('ba-aside-menu-shade', () => {
|
||||
config.setLayout('menuCollapse', true)
|
||||
@ -29,7 +32,7 @@ const onMenuCollapse = () => {
|
||||
<style scoped lang="scss">
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
height: 60px;
|
||||
height: v-bind('config.headerHeight()');
|
||||
width: 100%;
|
||||
background-color: v-bind('config.getColorVal("headerBarBackground")');
|
||||
:deep(.nav-tabs) {
|
||||
@ -75,11 +78,11 @@ const onMenuCollapse = () => {
|
||||
}
|
||||
.nav-route {
|
||||
display: flex;
|
||||
height: 48px;
|
||||
height: v-bind(height);
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
line-height: 48px;
|
||||
margin: 20px 0px;
|
||||
line-height: v-bind(height);
|
||||
margin: v-bind(padding) 0px;
|
||||
:deep(.nav-tabs) {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
@ -14,6 +14,7 @@
|
||||
</el-container>
|
||||
<CloseFullScreen v-if="navTabs.state.tabFullScreen" />
|
||||
</template>
|
||||
q
|
||||
|
||||
<script setup lang="ts">
|
||||
import Aside from '/@/layouts/backend/components/aside.vue'
|
||||
@ -22,8 +23,15 @@ import Main from '/@/layouts/backend/router-view/main.vue'
|
||||
import CloseFullScreen from '/@/layouts/backend/components/closeFullScreen.vue'
|
||||
import { useNavTabs } from '/@/stores/navTabs'
|
||||
import { useSiteConfig } from '/@/stores/siteConfig'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import { computed } from 'vue'
|
||||
const siteConfig = useSiteConfig()
|
||||
const navTabs = useNavTabs()
|
||||
const config = useConfig()
|
||||
|
||||
const padding = computed(() => (window.screen.width < 1920 ? '0px' : '10px'))
|
||||
|
||||
const bodyPadding = computed(() => (window.screen.width < 1920 ? '10px' : '20px'))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -35,16 +43,16 @@ const navTabs = useNavTabs()
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 20px;
|
||||
padding: 0 v-bind(bodyPadding);
|
||||
}
|
||||
.layout-logo {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
height: v-bind('config.headerHeight()');
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
padding: v-bind(padding);
|
||||
background-image: linear-gradient(170deg, #eaf6ff 0%, #fbfdff 94%);
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 100, 170, 0.09);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ export const useConfig = defineStore(
|
||||
menuTopBarBackground: ['#fcfcfc', '#1d1e1f'],
|
||||
// 侧边菜单宽度(展开时),单位px
|
||||
menuWidth: 260,
|
||||
headerHeight: 60,
|
||||
// 侧边菜单项默认图标
|
||||
menuDefaultIcon: 'fa fa-circle-o',
|
||||
// 是否水平折叠收起菜单
|
||||
@ -70,9 +71,19 @@ export const useConfig = defineStore(
|
||||
return layout.menuCollapse ? '0px' : layout.menuWidth + 'px'
|
||||
}
|
||||
// 菜单是否折叠
|
||||
if (window.screen.width < 1920) {
|
||||
layout.menuWidth = 180
|
||||
return layout.menuCollapse ? '54px' : layout.menuWidth + 'px'
|
||||
}
|
||||
layout.menuWidth = 260
|
||||
return layout.menuCollapse ? '74px' : layout.menuWidth + 'px'
|
||||
}
|
||||
|
||||
const headerHeight = function () {
|
||||
if (window.screen.width < 1920) return '46px'
|
||||
return layout.headerHeight + 'px'
|
||||
}
|
||||
|
||||
function setLang(val: string) {
|
||||
lang.defaultLang = val
|
||||
}
|
||||
@ -114,7 +125,7 @@ export const useConfig = defineStore(
|
||||
// }
|
||||
}
|
||||
|
||||
return { layout, lang, menuWidth, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
|
||||
return { layout, lang, menuWidth, headerHeight, setLang, setLayoutMode, setLayout, getColorVal, onSetLayoutColor }
|
||||
},
|
||||
{
|
||||
persist: {
|
||||
|
@ -8,6 +8,7 @@ export interface Layout {
|
||||
mainAnimation: string
|
||||
isDark: boolean
|
||||
menuWidth: number
|
||||
headerHeight: number
|
||||
menuDefaultIcon: string
|
||||
menuCollapse: boolean
|
||||
menuUniqueOpened: boolean
|
||||
@ -132,4 +133,4 @@ export interface Enums {
|
||||
[key: string]: { [k: string]: string }
|
||||
}
|
||||
keys: string[]
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export function mainHeight(extra = 0): CSSProperties {
|
||||
let height = extra
|
||||
const adminLayoutMainExtraHeight: anyObj = {
|
||||
Default: 70,
|
||||
Classic: 150,
|
||||
Classic: window.screen.width < 1920 ? 110 : 150,
|
||||
Streamline: 60,
|
||||
}
|
||||
if (isAdminApp()) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<el-dialog v-model="visible" title="测点选择" width="1000" :before-close="handleClose" :show-close="false">
|
||||
<!-- <el-transfer v-model="value" :data="data" />-->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14">
|
||||
<div class="transferLeft">
|
||||
@ -88,7 +87,7 @@
|
||||
<div class="realConter">
|
||||
<div class="header">
|
||||
<el-button type="primary" :icon="Crop" class="defaultBtn" @click="openMeasure">测点选择</el-button>
|
||||
<el-button style="color: rgb(0, 100, 170);;" :icon="Download" class="defaultBtn" @click="downFun(realtableColumn,realtableData)">数据导出</el-button>
|
||||
<el-button style="color: rgb(0, 100, 170);;" :icon="Download" class="defaultBtn" @click="downFun(tableColumn,tableData)">数据导出</el-button>
|
||||
<div class="selectPart">
|
||||
<span>自动更新:</span>
|
||||
<el-switch
|
||||
@ -99,8 +98,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="realTable">
|
||||
<el-table height="100%" :data="realtableData">
|
||||
<template v-for="item in realtableColumn">
|
||||
<el-table height="100%" :data="tableData">
|
||||
<template v-for="item in tableColumn">
|
||||
<el-table-column :prop="item.prop" :label="item.label" :align="item.align" />
|
||||
<!-- <el-table-column v-if="item.custom === 'default'" :prop="item.prop" :label="item.label" :align="item.align" />
|
||||
<el-table-column v-if="item.custom === 'header'" :prop="item.prop" :label="item.label+item.unit" :align="item.align" />-->
|
||||
@ -116,16 +115,19 @@ import {Crop,Download,Top,Bottom,Close} from '@element-plus/icons-vue'
|
||||
import {onMounted, onUnmounted, reactive, ref, watch,computed,nextTick} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {equipList,getModelAttributeList,getsnapshotData} from "/@/api/backend/realData/request.ts";
|
||||
import {getAllEnumData} from "/@/api/backend/Enumeration/request";
|
||||
import { useEnumStore } from '/@/stores/enums'
|
||||
const enumStore = useEnumStore()
|
||||
|
||||
const realtableData = ref()
|
||||
const tableData = ref()
|
||||
const tableItem0: any = [
|
||||
{
|
||||
label: '风机列表',
|
||||
unit:' ',
|
||||
prop: 'code',
|
||||
prop: 'name',
|
||||
align: 'center',
|
||||
custom: 'default',
|
||||
name:'',
|
||||
name:'name',
|
||||
title: '风机列表'
|
||||
}]
|
||||
const tableItem1: any = [
|
||||
@ -221,7 +223,7 @@ const tableItem1: any = [
|
||||
title: '变桨角度'
|
||||
}
|
||||
]
|
||||
const realtableColumn=ref(
|
||||
const tableColumn=ref(
|
||||
[...tableItem0,...tableItem1]
|
||||
)
|
||||
|
||||
@ -235,10 +237,23 @@ const objectType= ref(10002);
|
||||
const iotModelId=ref()
|
||||
const radioActiveName=ref('138')
|
||||
const selectedIndex=ref(0)
|
||||
|
||||
const newtableData=ref()
|
||||
const deviceQuery = (data: any) => {
|
||||
equipList(data).then((res) => {
|
||||
deviceList.value = res.data
|
||||
realtableData.value = res.data
|
||||
tableData.value = res.data.map((item) => {
|
||||
return {
|
||||
id:item.id,
|
||||
name: item.name ?? '-',
|
||||
}
|
||||
})
|
||||
newtableData.value = res.data.map((item) => {
|
||||
return {
|
||||
id:item.id,
|
||||
name: item.name ?? '-',
|
||||
}
|
||||
})
|
||||
iotModelId.value=res.data[0].iotModelId
|
||||
defaultdeviceQuery()
|
||||
})
|
||||
@ -248,7 +263,7 @@ const defaultdeviceQuery = () => {
|
||||
let attributesCode:any[]=[]
|
||||
deviceId.forEach((item,index) => {
|
||||
objparms.deviceId=item
|
||||
attributesCode=realtableColumn.value.map((item1)=>item1.prop)
|
||||
attributesCode=tableColumn.value.map((item1)=>item1.prop)
|
||||
attributesCode.push('iPitchAngle1','iPitchAngle2', 'iPitchAngle3')
|
||||
objparms.attributes=attributesCode
|
||||
snapshotParms.push({...objparms})
|
||||
@ -257,14 +272,14 @@ const defaultdeviceQuery = () => {
|
||||
if (res.code == 200) {
|
||||
const tsnapshotVoObject: any = res.data;
|
||||
const tsnapshotVoMap = new Map(Object.entries(tsnapshotVoObject));
|
||||
const updatedTableData = realtableColumn.value.reduce((acc, item1) => {
|
||||
const updatedTableData = tableColumn.value.reduce((acc, item1) => {
|
||||
acc.forEach((item, i) => {
|
||||
const itemKey = item.id;
|
||||
if (tsnapshotVoMap.has(itemKey)) {
|
||||
const tsnapshotVoItem = tsnapshotVoMap.get(itemKey);
|
||||
//const attributeCodeLower = item1.attributeCode?.toLowerCase();
|
||||
const attributeCodeLower = item1.prop;
|
||||
if(attributeCodeLower!='code'){
|
||||
if(attributeCodeLower!='name'){
|
||||
if (attributeCodeLower) {
|
||||
const ipitchangle=Math.min(tsnapshotVoItem.ipitchangle1, tsnapshotVoItem.ipitchangle2, tsnapshotVoItem.ipitchangle3)
|
||||
let ipitchanglevalue;
|
||||
@ -282,9 +297,8 @@ const defaultdeviceQuery = () => {
|
||||
}
|
||||
});
|
||||
return acc;
|
||||
}, [...realtableData.value]);
|
||||
realtableData.value = updatedTableData;
|
||||
debugger;
|
||||
}, [...tableData.value]);
|
||||
tableData.value = updatedTableData;
|
||||
} else {
|
||||
ElMessage.error({
|
||||
message: res.msg,
|
||||
@ -334,12 +348,11 @@ interface TableType {
|
||||
|
||||
const selectList=ref([])
|
||||
const getSel = () => {
|
||||
debugger
|
||||
selectList.value=[]
|
||||
try {
|
||||
if (realtableColumn.value && Array.isArray(realtableColumn.value)) {
|
||||
for (const item of realtableColumn.value) {
|
||||
if (item && item.prop && item.prop !== 'code') {
|
||||
if (tableColumn.value && Array.isArray(tableColumn.value)) {
|
||||
for (const item of tableColumn.value) {
|
||||
if (item && item.prop && item.prop !== 'name') {
|
||||
if(item.title!==undefined){
|
||||
selectList.value.push({
|
||||
attributeName: item.title || '',
|
||||
@ -426,6 +439,7 @@ const clearList=() => {
|
||||
Statistic.value=0
|
||||
multipleSelection.value = [];
|
||||
RealtableRef.value.clearSelection()
|
||||
//tableData.value=[]
|
||||
queryListData.iotModelId=iotModelId.value
|
||||
queryListData.attributeType=radioActiveName.value
|
||||
modelAttributeList(queryListData)
|
||||
@ -496,12 +510,11 @@ const getTableData = () => {
|
||||
const deviceId=deviceList.value.map((item) => item.id);
|
||||
const tableColumnEnds = ref([]);
|
||||
if(multipleSelection.value.length === 0){
|
||||
realtableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
||||
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
||||
}else{
|
||||
multipleSelection.value.forEach(item => {
|
||||
if (item.attributeCode) {
|
||||
const attributeCodeLower = item.attributeCode.toLowerCase();
|
||||
//if (!tableColumnMap.has(attributeCodeLower)) {
|
||||
if(attributeCodeLower==='ipitchangle1'||attributeCodeLower==='ipitchangle2'||attributeCodeLower==='ipitchangle3'){
|
||||
tableColumnEnds.value.push({
|
||||
label: '变桨角度',
|
||||
@ -523,14 +536,10 @@ const getTableData = () => {
|
||||
title: item.attributeName,
|
||||
});
|
||||
}
|
||||
|
||||
//}
|
||||
}
|
||||
});
|
||||
realtableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
||||
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
|
||||
}
|
||||
|
||||
|
||||
deviceId.forEach((item,index) => {
|
||||
objparms.deviceId=item
|
||||
objparms.attributes=multipleSelection.value.map((item) => item.attributeCode)
|
||||
@ -539,10 +548,8 @@ const getTableData = () => {
|
||||
getsnapshotData(snapshotParms).then((res) => {
|
||||
if (res.code == 200) {
|
||||
const tsnapshotVoObject: any = res.data;
|
||||
//console.log(multipleSelection.value, tsnapshotVoObject, tableData.value, 'multipleSelection.valuemultipleSelection.value');
|
||||
multipleSelection.value.map((item1: any) => {
|
||||
// const newItem: any = { };
|
||||
realtableData.value.forEach((item: any, i: number, arr: any) => {
|
||||
tableData.value.forEach((item: any, i: number, arr: any) => {
|
||||
for (const itemKey in tsnapshotVoObject) {
|
||||
if (item.id === itemKey) {
|
||||
const attributeCodeLower = item1.attributeCode?.toLowerCase();
|
||||
@ -554,15 +561,19 @@ const getTableData = () => {
|
||||
}else{
|
||||
ipitchanglevalue=ipitchangle1 !== undefined ? (ipitchangle1 % 1 === 0 ? ipitchangle1 : ipitchangle1.toFixed(3)) : '-';
|
||||
}
|
||||
// for (const rowKey in item) {
|
||||
// if (attributeCodeLower == rowKey) {
|
||||
// newItem[rowKey] = item[rowKey];
|
||||
// }
|
||||
// }
|
||||
const value = tsnapshotVoObject[itemKey]?.[attributeCodeLower];
|
||||
const formattedValue = value !== undefined ? (value % 1 === 0 ? value : value.toFixed(3)) : '-';
|
||||
//arr[i] = { code: item.code, [attributeCodeLower]: formattedValue,[ipitchangle]: ipitchanglevalue};
|
||||
arr[i] = { ...item, [attributeCodeLower]: formattedValue,[ipitchangle]: ipitchanglevalue};
|
||||
let formattedValue = value !== undefined ? (value % 1 === 0 ? value : value.toFixed(3)) : '-';
|
||||
if (enumStore.keys.includes(item1.attributeCode)) {
|
||||
formattedValue = enumStore.data[item1.attributeCode][formattedValue]?enumStore.data[item1.attributeCode][formattedValue]:'-'
|
||||
}
|
||||
if(attributeCodeLower==='ipitchangle'||
|
||||
attributeCodeLower==='ipitchangle1'||
|
||||
attributeCodeLower==='ipitchangle2'||
|
||||
attributeCodeLower==='ipitchangle3'){
|
||||
arr[i] = { ...item, [attributeCodeLower]: formattedValue,[ipitchangle]: ipitchanglevalue};
|
||||
}else{
|
||||
arr[i] = { ...item, [attributeCodeLower]: formattedValue};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -580,18 +591,38 @@ const sureBtn = (done: () => void) => {
|
||||
getTableData()
|
||||
visible.value = false
|
||||
}
|
||||
const downFun=(tableColumn,realtableData)=>{
|
||||
const itemsWithoutAge = realtableData.map(item => {
|
||||
const { id, belongLine, iotModelId, location,madeinFactory,model,name,nominalCapacity,objectType,parentEquipmentId,remarks,standard,...rest } = item;
|
||||
const downFun=(tableColumn,tableData)=>{
|
||||
const itemsWithoutAge = tableData.map(item => {
|
||||
const { id, ...rest } = item;
|
||||
return rest;
|
||||
});
|
||||
if (!tableColumn.length || !itemsWithoutAge.length) {
|
||||
return [];
|
||||
}
|
||||
const columnSet = new Set(tableColumn.map(item => item.prop));
|
||||
const result = [];
|
||||
try {
|
||||
itemsWithoutAge.forEach((item) => {
|
||||
const newItem = {};
|
||||
for (const itemKey in item) {
|
||||
if (columnSet.has(itemKey)) {
|
||||
newItem[itemKey] = item[itemKey];
|
||||
}
|
||||
}
|
||||
if (Object.keys(newItem).length > 0) {
|
||||
result.push(newItem);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in code execution:', error);
|
||||
return [];
|
||||
}
|
||||
let addobj = {}
|
||||
tableColumn.map((v, i) => {
|
||||
addobj['rowData' + i] = v.label
|
||||
})
|
||||
let tableDatadown = JSON.parse(JSON.stringify(itemsWithoutAge))
|
||||
let tableDatadown = JSON.parse(JSON.stringify(result))
|
||||
tableDatadown.unshift(addobj)
|
||||
console.log(tableDatadown, 'tableDatadowntableDatadowntableDatadown')
|
||||
let str = ``;
|
||||
for(let i = 0; i < tableDatadown.length; i++) {
|
||||
for(let item in tableDatadown[i]) {
|
||||
@ -626,7 +657,7 @@ onMounted(() => {
|
||||
<style scoped lang="scss">
|
||||
$paginationHeight: 32px;
|
||||
.default-main {
|
||||
width: 100%;
|
||||
/* width: 100%;*/
|
||||
height: 100%;
|
||||
.realConter {
|
||||
width: 100%;
|
||||
|
@ -39,7 +39,7 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, defineEmits } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { ModelAttributeFieldsEnums, GetModelAttributeType } from '/@/views/backend/auth/model/type'
|
||||
import type { ModelAttributeFieldsEnums } from '/@/views/backend/auth/model/type'
|
||||
import { getModelAttributeListReq, getRealValueListReq } from '/@/api/backend/deviceModel/request'
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -36,6 +36,22 @@
|
||||
<el-option v-for="v in statAnalysisSelectOptions.interval" :key="v.value" :label="v.label" :value="v.value"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="selectPart">
|
||||
<span>{{ t('statAnalysis.madeinfatory') }}</span>
|
||||
<el-select
|
||||
v-model="statAnalysisFatory"
|
||||
:placeholder="'请选择' + t('statAnalysis.madeinfatory')"
|
||||
class="statAnalysisSelect"
|
||||
@change="factoryChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="v in statAnalysisFatoryList"
|
||||
:key="v.id"
|
||||
:label="v.madeinfactory + v.model"
|
||||
:value="`${v.madeinfactory}:${v.model}`"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -46,10 +62,14 @@
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { queryWindTurbinesPages, historyReq } from '/@/api/backend/statAnalysis/request'
|
||||
import { theoreticalpowerCurveList, powerCurveQuery } from '/@/api/backend/theoreticalpowerCurve/request'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import * as echarts from 'echarts'
|
||||
import { index } from '/@/api/backend'
|
||||
import { el } from 'element-plus/es/locales.mjs'
|
||||
const { t } = useI18n()
|
||||
|
||||
const statAnalysisFatory = ref('')
|
||||
const statAnalysisFatoryList: any = ref([])
|
||||
const statAnalysisTime = ref('')
|
||||
const statAnalysisInterval = ref('')
|
||||
const statAnalysisDeviceId = ref('')
|
||||
@ -85,6 +105,12 @@ const option: any = {
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: 'KW',
|
||||
@ -130,13 +156,55 @@ onMounted(() => {
|
||||
})
|
||||
}
|
||||
queryWindTurbines()
|
||||
queryfactoery()
|
||||
})
|
||||
|
||||
const queryfactoery = () => {
|
||||
theoreticalpowerCurveList().then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
statAnalysisFatoryList.value = res.rows
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const factoryChange = (val: any) => {
|
||||
if (!option.legend.data.includes('理论值')) {
|
||||
querytheoretical(val)
|
||||
} else {
|
||||
ElMessage.info('理论曲线已存在,无需选择!!')
|
||||
}
|
||||
}
|
||||
const querytheoretical = (val: any) => {
|
||||
const madeinfactory = val.split(':')[0]
|
||||
const model = val.split(':')[1]
|
||||
powerCurveQuery(madeinfactory, model).then((res) => {
|
||||
if (res.code == 200) {
|
||||
const resData = res.data
|
||||
if (resData.length) {
|
||||
const seriesData = resData.map((item: any) => {
|
||||
return [item.speed, item.power]
|
||||
})
|
||||
const series = {
|
||||
type: 'line',
|
||||
data: seriesData,
|
||||
name: '理论值',
|
||||
smooth: true,
|
||||
}
|
||||
option.series.push(series)
|
||||
option.legend.data.push('理论值')
|
||||
chart.value.setOption(option)
|
||||
}
|
||||
} else {
|
||||
ElMessage.warning('查询失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
const queryWindTurbines = () => {
|
||||
queryWindTurbinesPages().then((res) => {
|
||||
if (res.code == 200) {
|
||||
statAnalysisSelectOptions.deviceId = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.irn,
|
||||
value: `${item.madeinfactory}:${item.model}:${item.irn}`,
|
||||
label: item.name ?? '-',
|
||||
iotModelId: item.modelId,
|
||||
}
|
||||
@ -220,11 +288,11 @@ const getDateRange = (type: 'week' | 'month') => {
|
||||
const statAnalysisOperate = () => {
|
||||
option.series = []
|
||||
chart.value.setOption(option, { notMerge: true })
|
||||
|
||||
// chart.value.clear()
|
||||
const requestData = {
|
||||
devices: [
|
||||
{
|
||||
deviceId: statAnalysisDeviceId.value,
|
||||
deviceId: statAnalysisDeviceId.value.split(':')[2],
|
||||
attributes: ['iGenPower', 'iWindSpeed'],
|
||||
},
|
||||
],
|
||||
@ -232,28 +300,30 @@ const statAnalysisOperate = () => {
|
||||
startTime: new Date(statAnalysisTime.value[0]).getTime(),
|
||||
endTime: new Date(statAnalysisTime.value[1]).getTime(),
|
||||
}
|
||||
querytheoretical(statAnalysisDeviceId.value)
|
||||
historyDataReq(requestData)
|
||||
}
|
||||
const historyDataReq = (data: any) => {
|
||||
historyReq(data).then((res) => {
|
||||
if (res.code == 200) {
|
||||
const resData = res.data[statAnalysisDeviceId.value]
|
||||
const resData = res.data[statAnalysisDeviceId.value.split(':')[2]]
|
||||
if (resData) {
|
||||
const iGenPower = resData['iGenPower']['values']
|
||||
const iWindSpeed = resData['iWindSpeed']['values']
|
||||
const seriesData = iGenPower.map((item: any, index: number) => {
|
||||
return [iWindSpeed[index], item]
|
||||
})
|
||||
seriesData.sort((a, b) => {
|
||||
seriesData.sort((a: any, b: any) => {
|
||||
return a[0] - b[0]
|
||||
})
|
||||
const series = {
|
||||
type: 'line',
|
||||
data: seriesData,
|
||||
name: '实际值',
|
||||
smooth: true,
|
||||
}
|
||||
option.series.push(series)
|
||||
|
||||
option.legend.data.push('实际值')
|
||||
chart.value.setOption(option)
|
||||
}
|
||||
} else {
|
||||
|
@ -103,6 +103,7 @@ const inittemperatureChar = () => {
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
interval: 10,
|
||||
z:10,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
@ -131,29 +132,27 @@ const inittemperatureChar = () => {
|
||||
yAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
nameTextStyle: {
|
||||
color: '#4E5969',
|
||||
},
|
||||
z: 10,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#ffffff',
|
||||
width: 0,
|
||||
width: 1,
|
||||
type: 'solid',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
//x轴文字的配置
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#4E5969',
|
||||
},
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisTick: { show: true },
|
||||
splitLine: {
|
||||
interval: 50,
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
width:1,
|
||||
color: '#ffffff',
|
||||
},
|
||||
},
|
||||
@ -164,10 +163,10 @@ const inittemperatureChar = () => {
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
barWidth: 40,
|
||||
//barWidth: 40,
|
||||
itemStyle: {
|
||||
color: '#0064AA',
|
||||
barBorderRadius: 2
|
||||
barBorderRadius: 2,
|
||||
},
|
||||
label:{
|
||||
show:true,
|
||||
@ -180,32 +179,35 @@ const inittemperatureChar = () => {
|
||||
{
|
||||
name: '上限值',
|
||||
type: 'bar',
|
||||
barWidth: 40,
|
||||
//barWidth: 40,
|
||||
barGap: '-100%',
|
||||
data: temperatureData.limit1High,
|
||||
itemStyle: {
|
||||
color: '#ccecea',
|
||||
//borderColor: '#ffffff',
|
||||
},
|
||||
z:2
|
||||
},
|
||||
{
|
||||
name: '下限值',
|
||||
type: 'bar',
|
||||
barWidth: 40,
|
||||
//barWidth: 40,
|
||||
barGap: '-100%',
|
||||
data: temperatureData.limit1Low,
|
||||
itemStyle: {
|
||||
color: '#ccecea',
|
||||
//borderColor: '#ffffff',
|
||||
},
|
||||
z:2
|
||||
},
|
||||
{
|
||||
name: '上上限值',
|
||||
type: 'bar',
|
||||
barWidth: 40,
|
||||
//barWidth: 40,
|
||||
barGap: '-100%',
|
||||
itemStyle: {
|
||||
color: '#fff0cc',
|
||||
borderColor: '#ffffff',
|
||||
},
|
||||
data: temperatureData.limit2High,
|
||||
z:1
|
||||
@ -213,11 +215,12 @@ const inittemperatureChar = () => {
|
||||
{
|
||||
name: '下下限值',
|
||||
type: 'bar',
|
||||
barWidth: 40,
|
||||
//barWidth: 40,
|
||||
barGap: '-100%',
|
||||
data: temperatureData.limit2Low,
|
||||
itemStyle: {
|
||||
color: '#fff0cc',
|
||||
borderColor: '#ffffff',
|
||||
},
|
||||
z:1
|
||||
},
|
||||
@ -231,7 +234,6 @@ const attributesCode:any[]=[]
|
||||
const getChartData = (data: any) => {
|
||||
console.log(JSON.stringify(data))
|
||||
getTemperatureLimitByDeviceId(data).then((res) => {
|
||||
debugger
|
||||
if (res.code=='200') {
|
||||
temperatureData.name=[]
|
||||
temperatureData.values=[]
|
||||
|
485
ui/dasadmin/src/views/backend/theoreticalpowerCurve/index.vue
Normal file
485
ui/dasadmin/src/views/backend/theoreticalpowerCurve/index.vue
Normal file
@ -0,0 +1,485 @@
|
||||
<template>
|
||||
<div class="theoreticalpowerCurve">
|
||||
<el-container class="mainContainer">
|
||||
<el-header class="mainHeader">
|
||||
<el-button type="primary" @click="addItem">新增</el-button>
|
||||
</el-header>
|
||||
<el-main class="mainMain">
|
||||
<div class="tabsPart">
|
||||
<el-table :data="theoreticalTableData" class="tablePart" @current-change="handleCurrentChange">
|
||||
<el-table-column prop="index" :label="theoreticalEnums['index']" align="center"> </el-table-column>
|
||||
<el-table-column prop="madeinfactory" :label="theoreticalEnums['madeinfactory']" align="center"> </el-table-column>
|
||||
<el-table-column prop="model" :label="theoreticalEnums['model']" align="center"> </el-table-column>
|
||||
<el-table-column prop="nominalCapacity" :label="theoreticalEnums['nominalCapacity']" align="center"> </el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="400" align="center">
|
||||
<template #default="scope">
|
||||
<div class="tableOperate">
|
||||
<a @click="viewDetails(scope.row)">查看 </a>
|
||||
<el-upload :show-file-list="false" :http-request="update">
|
||||
<template #trigger>
|
||||
<a>更新 </a>
|
||||
</template>
|
||||
</el-upload>
|
||||
<a @click="download(scope.row)">下载</a>
|
||||
<a @click="deleteDetails(scope.row)">删除</a>
|
||||
</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>
|
||||
<div ref="chartContainer" class="chartContainer"></div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-dialog v-model="dialogOpen" :title="dialogTitle" width="720">
|
||||
<el-form
|
||||
ref="factoryDetails"
|
||||
:inline="true"
|
||||
label-width="auto"
|
||||
:model="factoryData"
|
||||
:rules="factoryRules"
|
||||
style="padding: 5px 15px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="theoreticalEnums['madeinfactory']" prop="madeinfactory">
|
||||
<el-input v-model="factoryData.madeinfactory" placeholder="请输入生产厂家" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="theoreticalEnums['model']" prop="model">
|
||||
<el-input v-model="factoryData.model" placeholder="请输入规格型号" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="theoreticalEnums['nominalCapacity']">
|
||||
<el-input v-model="factoryData.nominalCapacity" placeholder="请输入额定容量" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="saveFactory">保存</el-button>
|
||||
<el-button @click="dialogOpen = false">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, markRaw } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { encrypt_aes, generateRandomNumber } from '/@/utils/crypto'
|
||||
import { theoreticalEnums } from './type'
|
||||
import {
|
||||
theoreticalpowerCurveList,
|
||||
saveData,
|
||||
updateData,
|
||||
deleteData,
|
||||
importData,
|
||||
exportData,
|
||||
powerCurveQuery,
|
||||
} from '/@/api/backend/theoreticalpowerCurve/request'
|
||||
import * as echarts from 'echarts'
|
||||
// 导入
|
||||
const update = (file: any) => {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file)
|
||||
const v = generateRandomNumber(16)
|
||||
const id = encrypt_aes(currentRow.value.id, v)
|
||||
formData.append('id', currentRow.value.id)
|
||||
return importData(formData, v)
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
ElMessage.success('更新成功')
|
||||
getpowerCurve()
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err?.response?.data?.msg ?? '更新失败')
|
||||
})
|
||||
}
|
||||
|
||||
// 导出
|
||||
const download = (val: any) => {
|
||||
exportData({ id: val.id }).then((res: any) => {
|
||||
const downloadUrl = window.URL.createObjectURL(res)
|
||||
const a = document.createElement('a')
|
||||
a.href = downloadUrl
|
||||
a.download = '理论风速曲线' + new Date().getTime()
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
window.URL.revokeObjectURL(downloadUrl)
|
||||
document.body.removeChild(a)
|
||||
})
|
||||
}
|
||||
|
||||
const option: any = reactive({
|
||||
tooltip: {
|
||||
formatter: function (params: any) {
|
||||
return '风速:' + params.value[0] + 'm/s ' + ' <br/>' + '功率:' + params.value[1] + 'KW'
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
icon: 'circle',
|
||||
itemGap: 20,
|
||||
itemWidth: 8,
|
||||
itemHeight: 8,
|
||||
data: [],
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
name: 'm/s',
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: 'KW',
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
series: [],
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '3%',
|
||||
},
|
||||
})
|
||||
const chart: any = ref(null)
|
||||
const chartContainer = ref<HTMLElement | null>(null)
|
||||
const dialogOpen = ref(false)
|
||||
const dialogTitle = ref('新增厂家')
|
||||
const factoryDetails = ref()
|
||||
const factoryData: any = ref({})
|
||||
const factoryRules = ref({
|
||||
madeinfactory: [{ required: true, message: '请输入生产厂家', trigger: 'blur' }],
|
||||
model: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入规格型号',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
const actionFlag = ref(1)
|
||||
|
||||
const addItem = () => {
|
||||
factoryData.value = {
|
||||
madeinfactory: '',
|
||||
model: '',
|
||||
nominalCapacity: '',
|
||||
}
|
||||
dialogTitle.value = '新增厂家'
|
||||
actionFlag.value = 1
|
||||
dialogOpen.value = true
|
||||
}
|
||||
|
||||
const saveFactory = () => {
|
||||
factoryDetails.value.validate((valid: any, fields: any) => {
|
||||
if (valid) {
|
||||
if (actionFlag.value == 1) {
|
||||
saveData(factoryData.value)
|
||||
.then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
getList()
|
||||
ElMessage.success(res.msg ?? '新增成功')
|
||||
dialogOpen.value = false
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '新增失败')
|
||||
dialogOpen.value = false
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err?.response?.data?.msg ?? '新增失败')
|
||||
dialogOpen.value = false
|
||||
})
|
||||
} else if (actionFlag.value == 2) {
|
||||
updateData(factoryData.value)
|
||||
.then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
getList()
|
||||
ElMessage.success(res.msg ?? '修改成功')
|
||||
dialogOpen.value = false
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '修改失败')
|
||||
dialogOpen.value = false
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err?.response?.data?.msg ?? '修改失败')
|
||||
dialogOpen.value = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.log('error submit!', fields)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const viewDetails = (val: any) => {
|
||||
dialogTitle.value = '编辑厂家'
|
||||
actionFlag.value = 2
|
||||
dialogOpen.value = true
|
||||
factoryData.value = { ...val }
|
||||
}
|
||||
|
||||
const deleteDetails = (val: any) => {
|
||||
const id = val.id
|
||||
ElMessageBox.confirm('是否确认删除?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteData({ id })
|
||||
.then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
ElMessage.success(res.msg ?? '删除成功')
|
||||
getList()
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '删除失败')
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err?.response?.data?.msg ?? '删除失败')
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '取消确认',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const theoreticalTableData: any = ref([])
|
||||
|
||||
const getList = () => {
|
||||
const transparams = searchParams()
|
||||
theoreticalpowerCurveList(transparams)
|
||||
.then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
paginationOptions.total = res.total
|
||||
theoreticalTableData.value = res.rows.map((item: any, index: number) => {
|
||||
return {
|
||||
...item,
|
||||
index: index + 1,
|
||||
}
|
||||
})
|
||||
getpowerCurve()
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '查询失败')
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
|
||||
})
|
||||
}
|
||||
|
||||
const searchParams = (): any => {
|
||||
return {
|
||||
pageNum: paginationOptions.current,
|
||||
pageSize: paginationOptions.pageSize,
|
||||
}
|
||||
}
|
||||
const currentRow = ref()
|
||||
|
||||
const handleCurrentChange = (val: any) => {
|
||||
currentRow.value = val
|
||||
chart.value.clear()
|
||||
getpowerCurve()
|
||||
}
|
||||
const getpowerCurve = () => {
|
||||
currentRow.value = currentRow.value ?? theoreticalTableData.value[0]
|
||||
powerCurveQuery(currentRow.value.madeinfactory, currentRow.value.model).then((res) => {
|
||||
if (res.code == 200) {
|
||||
const resData = res.data
|
||||
if (resData) {
|
||||
const seriesData = resData.map((item: any) => {
|
||||
return [item.speed, item.power]
|
||||
})
|
||||
const series = {
|
||||
type: 'line',
|
||||
data: seriesData,
|
||||
name: currentRow.value.madeinfactory + currentRow.value.model,
|
||||
smooth: true,
|
||||
}
|
||||
option.series = series
|
||||
option.legend.data = [currentRow.value.madeinfactory + currentRow.value.model]
|
||||
chart.value.setOption(option)
|
||||
}
|
||||
} else {
|
||||
ElMessage.warning('查询失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const paginationOptions = reactive({
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
pageSizes: [20, 50, 100],
|
||||
})
|
||||
const getcurrentPage = () => {
|
||||
getList()
|
||||
}
|
||||
window.onresize = () => {
|
||||
chart.value.resize()
|
||||
}
|
||||
onMounted(() => {
|
||||
if (chartContainer.value) {
|
||||
chart.value = markRaw(echarts.init(chartContainer.value))
|
||||
chart.value.setOption({ option })
|
||||
}
|
||||
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$headerHeight: 60px;
|
||||
$defaultBackgroundColor: #fff;
|
||||
$defaultAsideWidth: 260px;
|
||||
$paginationHeight: 32px;
|
||||
.theoreticalpowerCurve {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mainContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mainHeader {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
height: $headerHeight;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #eaebed;
|
||||
}
|
||||
.mainMain {
|
||||
height: calc(100% - $headerHeight);
|
||||
.tabsPart {
|
||||
height: calc(100% - $paginationHeight - 290px);
|
||||
padding-bottom: 5px;
|
||||
:deep(.el-tabs__content) {
|
||||
height: calc(100% - 55px);
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.tablePart {
|
||||
height: 100%;
|
||||
.alarm {
|
||||
border: 1px solid rgb(228, 161, 18);
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
color: rgb(228, 161, 18);
|
||||
}
|
||||
.fault {
|
||||
border: 1px solid #a03b1d;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
color: #a03b1d;
|
||||
}
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.chartContainer {
|
||||
width: 100%;
|
||||
height: 280px;
|
||||
border: 1px solid rgb(217, 217, 217);
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.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>
|
@ -0,0 +1,6 @@
|
||||
export enum theoreticalEnums {
|
||||
'index' = '序号',
|
||||
'madeinfactory' = '生产厂家',
|
||||
'model' = '规格型号',
|
||||
'nominalCapacity' = '额度容量MW',
|
||||
}
|
Loading…
Reference in New Issue
Block a user