This commit is contained in:
高云鹏 2024-11-08 17:51:27 +08:00
commit c0d34288e5
36 changed files with 1991 additions and 351 deletions

View File

@ -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>

View File

@ -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 {

View File

@ -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");
// }
//}

View 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;
}
}

View 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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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("缓存已清理");
}
}

View File

@ -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> {
}

View File

@ -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> {
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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 {

View File

@ -19,6 +19,8 @@ public class WindTurbinesPageVo {
private String model;
private String madeinfactory;
private String belongLine;
private Map<String,Object> attributeMap;

View File

@ -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);

View File

@ -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>

View 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',
})
}

View File

@ -12,4 +12,5 @@ export default {
max: '最大值',
min: '最小值',
average: '平均值',
madeinfatory: '理论曲线',
}

View File

@ -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;

View File

@ -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;

View File

@ -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(() => {

View File

@ -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%;

View File

@ -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);
}

View File

@ -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: {

View File

@ -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[]
}
}

View File

@ -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

View File

@ -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%;

View File

@ -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({

View File

@ -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 {

View File

@ -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=[]

View 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>

View File

@ -0,0 +1,6 @@
export enum theoreticalEnums {
'index' = '序号',
'madeinfactory' = '生产厂家',
'model' = '规格型号',
'nominalCapacity' = '额度容量MW',
}