From 61c8656fd929ee33551e2a4985e517431fdf16b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=BE=E5=90=8C=E5=AD=A6?= Date: Wed, 26 Nov 2025 09:58:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(report):=20=E8=BF=81=E7=A7=BB=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=8A=A5=E8=A1=A8=E5=8A=9F=E8=83=BD=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/CsHarmonicResponseEnum.java | 11 + .../param/SensitiveUserReportQueryParam.java | 35 + .../pojo/dto/ReportTemplateDTO.java | 59 + .../pojo/param/ReportSearchParam.java | 42 + .../pojo/param/ReportTemplateParam.java | 59 + .../njcn/csharmonic/pojo/po/ExcelRptTemp.java | 37 + .../csharmonic/pojo/vo/ReportTemplateVO.java | 34 + .../njcn/csharmonic/pojo/vo/ReportTreeVO.java | 30 + .../csharmonic/pojo/vo/SysDeptTempVO.java | 37 + .../njcn/csharmonic/utils/DataChangeUtil.java | 46 + .../controller/CustomReportController.java | 282 +++ .../csharmonic/mapper/ExcelRptTempMapper.java | 36 + .../mapper/mapping/ExcelRptTempMapper.xml | 61 + .../service/CustomReportService.java | 134 ++ .../service/impl/CustomReportServiceImpl.java | 1652 +++++++++++++++++ 15 files changed, 2555 insertions(+) create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/param/SensitiveUserReportQueryParam.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/dto/ReportTemplateDTO.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportSearchParam.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportTemplateParam.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/po/ExcelRptTemp.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTemplateVO.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTreeVO.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/SysDeptTempVO.java create mode 100644 cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/utils/DataChangeUtil.java create mode 100644 cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/controller/CustomReportController.java create mode 100644 cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/ExcelRptTempMapper.java create mode 100644 cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/mapping/ExcelRptTempMapper.xml create mode 100644 cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/CustomReportService.java create mode 100644 cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CustomReportServiceImpl.java diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/enums/CsHarmonicResponseEnum.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/enums/CsHarmonicResponseEnum.java index d3655c5..8393abd 100644 --- a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/enums/CsHarmonicResponseEnum.java +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/enums/CsHarmonicResponseEnum.java @@ -20,7 +20,18 @@ public enum CsHarmonicResponseEnum { RECORD_MISSING("A00602","record.bin文件缺失,补召失败"), EVENT_FILE_NOT_SAME("A00603","cfg、dat文件名称不一致"), + CUSTOM_REPORT_REPEAT("A00552","自定义报表模板名称已存在"), + CUSTOM_REPORT_JSON("A00553","模板非严格json数据"), + + CUSTOM_REPORT_DEPT("A00554","该部门已存在绑定报表模板"), + CUSTOM_TYPE("A00555","字典中未查询到报表模板类型"), + CUSTOM_REPORT_ACTIVE("A00556","不存在激活的自定义报告模板"), + CUSTOM_REPORT_EMPTY("A00557","自定义报表模板异常,模板数据为空"), + CUSTOM_REPORT_FILE("A00558","上传文件服务器错误,请检查数据"), + + REPORT_DOWNLOAD_ERROR("A00559","报表文件下载异常"), + REPORT_TEMPLATE_DOWNLOAD_ERROR("A00560","报表模板下载异常") ; diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/param/SensitiveUserReportQueryParam.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/param/SensitiveUserReportQueryParam.java new file mode 100644 index 0000000..382c35f --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/param/SensitiveUserReportQueryParam.java @@ -0,0 +1,35 @@ +package com.njcn.csharmonic.param; + +import com.njcn.web.pojo.annotation.DateTimeStrValid; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class SensitiveUserReportQueryParam { + + @ApiModelProperty(name = "lineId",value = "监测对象id") + private String sensitiveUserId; + + @ApiModelProperty(name = "tempId",value = "模板ID") + private String tempId; + + + @ApiModelProperty(name = "searchBeginTime", value = "开始时间") + @NotBlank(message = "起始时间不可为空") + @DateTimeStrValid(message = "起始时间格式出错") + private String searchBeginTime; + + @ApiModelProperty(name = "searchEndTime", value = "结束时间") + @NotBlank(message = "结束时间不可为空") + private String searchEndTime; + + //目前用于区分不同系统资源,null默认 1.无线系统,配合cs-device + private Integer resourceType; + + //浙江无线报表特殊标识 null为通用报表 1.浙江无线报表 + private Integer customType; + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/dto/ReportTemplateDTO.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/dto/ReportTemplateDTO.java new file mode 100644 index 0000000..a41891a --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/dto/ReportTemplateDTO.java @@ -0,0 +1,59 @@ +package com.njcn.csharmonic.pojo.dto; + +import lombok.Data; + +/** + * pqs + * + * @author cdf + * @date 2022/8/22 + */ +@Data +public class ReportTemplateDTO { + /** + * $HA[_25]#B#max#classId#resourceId$ + */ + private String itemName; + + + /** + * 对应influxdb数据库中字段 + */ + private String templateName; + + /** + * 对应限值字段 + */ + private String limitName; + + /** + * 相别 + */ + private String phase; + + /** + * max min avg cp95 + */ + private String statMethod; + + /** + * 对应influxdb数据库的表名 + */ + private String classId; + + /** + * 对应mysql数据库的表名 + */ + private String resourceId; + + /** + * 标识指标是否越限 0.否 1.是 + */ + private Integer overLimitFlag; + + /** + * 填入的value值 + */ + private String value; + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportSearchParam.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportSearchParam.java new file mode 100644 index 0000000..796a63b --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportSearchParam.java @@ -0,0 +1,42 @@ +package com.njcn.csharmonic.pojo.param; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 模板动态更新数据 + * + * @author qijian + * @date 2022/10/11 + */ +@Data +public class ReportSearchParam { + + @ApiModelProperty(name = "lineId",value = "监测点id") + private String lineId; + + @ApiModelProperty(name = "tempId",value = "模板ID") + private String tempId; + + @ApiModelProperty(name = "activation",value = "激活状态") + private Integer activation; + + @ApiModelProperty(name = "type",value = "报表类型") + private Integer type; + + @ApiModelProperty(name = "startTime",value = "开始时间") + private String startTime; + + @ApiModelProperty(name = "endTime",value = "结束时间") + private String endTime; + + @ApiModelProperty(name = "deptId",value = "部门ID") + private String deptId; + + //目前用于区分不同系统资源,null默认 1.无线系统,配合cs-device + private Integer resourceType; + + //浙江无线报表特殊标识 null为通用报表 1.浙江无线报表 + private Integer customType; + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportTemplateParam.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportTemplateParam.java new file mode 100644 index 0000000..2a1f7ad --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/param/ReportTemplateParam.java @@ -0,0 +1,59 @@ +package com.njcn.csharmonic.pojo.param; + +import com.njcn.common.pojo.constant.PatternRegex; +import com.njcn.web.constant.ValidMessage; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import java.util.List; + +/** + * pqs + * + * @author cdf + * @date 2022/8/16 + */ +@Data +public class ReportTemplateParam { + + @ApiModelProperty(name = "name",value = "模板名称",required = true) + @NotBlank(message = "模板名称不可为空") + private String name; + + @ApiModelProperty(name = "fileContent",value = "json文件",required = true) + @NotNull(message = "模板文件不可为空") + private MultipartFile fileContent; + + @ApiModelProperty(name = "content",value = "json文件内容") + private String content; + + @ApiModelProperty(name = "deptId",value = "部门id") + private List deptId; + + @ApiModelProperty(name = "valueTitle",value = "存取库中") + private String valueTitle; + + @ApiModelProperty(name = "reportType",value = "模板类型",required = true) + @NotBlank(message = "模板类型不可为空") + private String reportType; + + @ApiModelProperty(name = "reportForm",value = "报表类型",required = true) + private String reportForm; + + + @Data + @EqualsAndHashCode(callSuper = true) + public static class UpdateReportTemplateParam extends ReportTemplateParam { + + @ApiModelProperty(name = "id",required = true) + @NotBlank(message = ValidMessage.ID_NOT_BLANK) + @Pattern(regexp = PatternRegex.SYSTEM_ID, message = ValidMessage.ID_FORMAT_ERROR) + private String id; + } + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/po/ExcelRptTemp.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/po/ExcelRptTemp.java new file mode 100644 index 0000000..c03e095 --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/po/ExcelRptTemp.java @@ -0,0 +1,37 @@ +package com.njcn.csharmonic.pojo.po; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.db.bo.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +/** + * pqs + * 自定义报表 + * @author cdf + * @date 2022/8/16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName(value = "sys_excel_rpt_temp") +public class ExcelRptTemp extends BaseEntity { + private String id; + + private String name; + + private String content; + + private Integer activation; + + private Integer state; + + private String valueTitle; + + private String reportType; + + private String reportForm; + + private Integer sort; + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTemplateVO.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTemplateVO.java new file mode 100644 index 0000000..b3cc2e8 --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTemplateVO.java @@ -0,0 +1,34 @@ +package com.njcn.csharmonic.pojo.vo; + +import com.njcn.db.bo.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * pqs + * 自定义报表 + * @author cdf + * @date 2022/8/16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ReportTemplateVO extends BaseEntity { + private String id; + + private String name; + + private String content; + + private String deptId; + + private Integer activation; + + private Integer state; + + private String deptName; + + private String reportType; + + private String reportForm; + +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTreeVO.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTreeVO.java new file mode 100644 index 0000000..6c2fe7b --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/ReportTreeVO.java @@ -0,0 +1,30 @@ +package com.njcn.csharmonic.pojo.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * pqs + * + * @author cdf + * @date 2022/8/18 + */ +@Data +public class ReportTreeVO { + + @ApiModelProperty(name = "id",value = "模板索引") + private String id; + + @ApiModelProperty(name = "name",value = "模板字段名") + private String name; + + @ApiModelProperty(name = "showName",value = "模板中文展示名") + private String showName; + + @ApiModelProperty(name = "flag",value = "用于标识最底层对象 1.表示已经没有子级") + private Integer flag; + + private List children; +} diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/SysDeptTempVO.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/SysDeptTempVO.java new file mode 100644 index 0000000..4de27b8 --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/pojo/vo/SysDeptTempVO.java @@ -0,0 +1,37 @@ +package com.njcn.csharmonic.pojo.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * @author qijian + * @since 2022-10-19 09:31:39 + */ +@Data +public class SysDeptTempVO implements Serializable { + private static final long serialVersionUID = -35391150359300949L; + /** + * 主键 + */ + private String id; + /** + * 部门主键 + */ + private String deptId; + + /** + * 模板主键 + */ + private String tempId; + + /** + * 激活状态 + */ + private Integer activation; + + //部门名称 + private String deptName; +} + diff --git a/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/utils/DataChangeUtil.java b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/utils/DataChangeUtil.java new file mode 100644 index 0000000..8e15c14 --- /dev/null +++ b/cs-harmonic/cs-harmonic-api/src/main/java/com/njcn/csharmonic/utils/DataChangeUtil.java @@ -0,0 +1,46 @@ +package com.njcn.csharmonic.utils; + +public class DataChangeUtil { + + /** + * 用来将二次值转成一次值 + */ + public static double secondaryToPrimary(String formula, Double data,Double pt, Double ct) { + switch (formula) { + + case "*PT": + data = data * pt; + break; + case "*CT": + data = data * ct; + break; + case "*PT*CT": + data = data * pt * ct; + break; + default: + break; + } + return data; + } + + /** + * 用来将一次值转成二次值 + */ + public static double primaryToSecondary(String formula, Double data,Double pt, Double ct) { + switch (formula) { + case "*PT": + data = data / pt; + break; + case "*CT": + data = data / ct; + break; + case "*PT*CT": + data = data / pt / ct; + break; + default: + break; + } + return data; + } + +} diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/controller/CustomReportController.java b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/controller/CustomReportController.java new file mode 100644 index 0000000..4552529 --- /dev/null +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/controller/CustomReportController.java @@ -0,0 +1,282 @@ +package com.njcn.csharmonic.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.common.pojo.annotation.OperateInfo; +import com.njcn.common.pojo.constant.OperateType; +import com.njcn.common.pojo.enums.common.LogEnum; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.response.HttpResult; +import com.njcn.common.utils.HttpResultUtil; +import com.njcn.csharmonic.param.SensitiveUserReportQueryParam; +import com.njcn.csharmonic.pojo.param.ReportSearchParam; +import com.njcn.csharmonic.pojo.param.ReportTemplateParam; +import com.njcn.csharmonic.pojo.po.ExcelRptTemp; +import com.njcn.csharmonic.pojo.vo.ReportTemplateVO; +import com.njcn.csharmonic.pojo.vo.ReportTreeVO; +import com.njcn.csharmonic.pojo.vo.SysDeptTempVO; +import com.njcn.csharmonic.service.CustomReportService; +import com.njcn.web.controller.BaseController; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * pqs + * 用户自定义报表 + * @author cdf + * @date 2022/8/15 + */ + +@Slf4j +@RestController +@RequestMapping("/customReport") +@Api(tags = "用户自定义报表") +@AllArgsConstructor +public class CustomReportController extends BaseController { + + private final CustomReportService customReportService; + + + /** + * 替换报表数据并返回 + * @author qijian + * @date 2022/10/19 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/getCustomReport") + @ApiOperation("获取报表") + @ApiImplicitParam(name = "reportSearchParam", value = "查询体", required = false) + public void getCustomReport(@RequestBody ReportSearchParam reportSearchParam, HttpServletResponse response) { + customReportService.getCustomReport(reportSearchParam,response); + } + + + /** + * 新增自定义报表模板 + * @author cdf + * @date 2022/10/19 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType=OperateType.ADD) + @PostMapping("/addTemplate") + @ApiOperation("新增自定义报表模板") + public HttpResult addCustomReportTemplate(@Validated ReportTemplateParam reportTemplateParam){ + String methodDescribe = getMethodDescribe("addCustomReportTemplate"); + boolean res = customReportService.addCustomReportTemplate(reportTemplateParam); + if(res){ + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + }else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 查询所有模板 + * @author qijian + * @date 2022/10/14 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/getTemplateList") + @ApiOperation("查询报表模板") + @ApiImplicitParam(name = "reportSearchParam", value = "实体参数", required = false) + public HttpResult> getTemplateList(@RequestBody ReportSearchParam reportSearchParam){ + String methodDescribe = getMethodDescribe("getTemplateList"); + List list = customReportService.getTemplateList(reportSearchParam); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + /** + * 根据部门查询模板 + * @author qijian + * @date 2022/10/19 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/getTemplateByDept") + @ApiOperation("根据部门查询模板") + @ApiImplicitParam(name = "id", value = "id", required = true) + public HttpResult> getTemplateByDept(@RequestParam("id") String id){ + String methodDescribe = getMethodDescribe("getTemplateList"); + List list = customReportService.getTemplateByDept(id); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + /** + * 删除模板 + * @author qijian + * @date 2022/10/18 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType=OperateType.DELETE) + @PostMapping("/delTemplate") + @ApiOperation("删除报表模板") + @ApiImplicitParam(name = "reportSearchParam", value = "实体参数", required = false) + public HttpResult delTemplate(@RequestBody ReportSearchParam reportSearchParam){ + String methodDescribe = getMethodDescribe("delTemplate"); + boolean res = customReportService.delTemplate(reportSearchParam); + if(res){ + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + }else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 根据id查询模板详情 + * @author qijian + * @date 2022/10/14 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/getCustomReportTemplateById") + @ApiOperation("根据id查询模板详情") + @ApiImplicitParam(name = "id", value = "id", required = true) + public HttpResult getCustomReportTemplateById(@RequestParam("id") String id){ + String methodDescribe = getMethodDescribe("getCustomReportTemplateById"); + ExcelRptTemp excelRptTemp = customReportService.getCustomReportTemplateById(id); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, excelRptTemp, methodDescribe); + } + + /** + * 根据id回显模板 + * @author qijian + * @date 2022/10/14 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/viewCustomReportTemplateById") + @ApiOperation("根据id查询模板详情") + @ApiImplicitParam(name = "id", value = "id", required = true) + public void viewCustomReportTemplateById(@RequestParam("id") String id,HttpServletResponse response){ + customReportService.viewCustomReportTemplateById(id,response); + } + + /** + * 修改自定义报表模板 + * @author qijian + * @date 2022/10/18 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType=OperateType.UPDATE) + @PostMapping("/updateTemplate") + @ApiOperation("修改自定义报表模板") + public HttpResult updateCustomReportTemplate(@Validated ReportTemplateParam.UpdateReportTemplateParam reportTemplateParam){ + String methodDescribe = getMethodDescribe("updateCustomReportTemplate"); + boolean res = customReportService.updateCustomReportTemplate(reportTemplateParam); + if(res){ + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + }else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 绑定/解绑模板数据 + * @author qijian + * @date 2022/10/19 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType=OperateType.UPDATE) + @PostMapping("/updateBindTemplate") + @ApiOperation("绑定/解绑模板数据") + @ApiImplicitParam(name = "reportSearchParams", value = "实体参数", required = false) + public HttpResult updateBindTemplate(@RequestBody List reportSearchParams){ + String methodDescribe = getMethodDescribe("updateBindTemplate"); + boolean res = customReportService.updateBindTemplate(reportSearchParams); + if(res){ + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + }else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 根据模板ID查询数据 + * @author qijian + * @date 2022/10/19 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/getDataByTempId") + @ApiOperation("根据模板ID查询数据") + @ApiImplicitParam(name = "id", value = "id", required = true) + public HttpResult> getDataByTempId(@RequestParam("id")String id){ + String methodDescribe = getMethodDescribe("getDataByTempId"); + List list = customReportService.getDataByTempId(id); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + + /** + * 修改激活状态 + * @author qijian + * @date 2022/10/17 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON,operateType=OperateType.UPDATE) + @PostMapping("/updateTemplateActive") + @ApiOperation("修改激活状态") + @ApiImplicitParam(name = "reportSearchParam", value = "实体参数", required = false) + public HttpResult> updateTemplateActive(@RequestBody ReportSearchParam reportSearchParam){ + String methodDescribe = getMethodDescribe("updateTemplateActive"); + boolean res = customReportService.updateStatus(reportSearchParam); + if(res){ + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + }else { + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe); + } + } + + /** + * 获取报表模板树 + * @author cdf + * @date 2022/8/16 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/reportChooseTree") + @ApiOperation("获取报表模板树") + public HttpResult> reportChooseTree(){ + String methodDescribe = getMethodDescribe("reportChooseTree"); + List res = customReportService.reportChooseTree(); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, res, methodDescribe); + } + + + + + /** + * 获取报表指标是否合格模板树 + * @author cdf + * @date 2023/10/11 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/targetLimitChooseTree") + @ApiOperation("获取报表指标是否合格模板树") + public HttpResult> targetLimitChooseTree(){ + String methodDescribe = getMethodDescribe("targetLimitChooseTree"); + List res = customReportService.targetLimitChooseTree(); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, res, methodDescribe); + } + + + /** + * 获取报表台账模板树 + * @author cdf + * @date 2023/10/11 + */ + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/terminalChooseTree") + @ApiOperation("获取报表台账模板树") + public HttpResult> terminalChooseTree(){ + String methodDescribe = getMethodDescribe("terminalChooseTree"); + List res = customReportService.terminalChooseTree(); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, res, methodDescribe); + } + + + + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @PostMapping("/getSensitiveUserReport") + @ApiOperation("获取监测对象治理报表") + @ApiImplicitParam(name = "queryParam", value = "查询体", required = true) + public void getSensitiveUserReport(@RequestBody SensitiveUserReportQueryParam queryParam, HttpServletResponse response) { + customReportService.getSensitiveUserReport(queryParam,response); + } +} diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/ExcelRptTempMapper.java b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/ExcelRptTempMapper.java new file mode 100644 index 0000000..076f10f --- /dev/null +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/ExcelRptTempMapper.java @@ -0,0 +1,36 @@ +package com.njcn.csharmonic.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.csharmonic.pojo.param.ReportSearchParam; +import com.njcn.csharmonic.pojo.po.ExcelRptTemp; +import com.njcn.csharmonic.pojo.vo.ReportTemplateVO; +import com.njcn.influx.pojo.dto.StatisticalDataDTO; +import com.njcn.web.pojo.param.BaseParam; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; + +/** + * pqs + * + * @author cdf + * @date 2022/8/16 + */ +public interface ExcelRptTempMapper extends BaseMapper { + + Page getReportTemplateListPage(Page page, @Param("baseParam")BaseParam baseParam); + + List getReportTemplateList(@Param("reportSearchParam")ReportSearchParam reportSearchParam); + + List getReportTemplateByDept(@Param("ids") List ids); + + + @Select("${sqlStr}") + StatisticalDataDTO dynamicSql(@Param("sqlStr")String sql); + + @Select("${sqlStr}") + Map dynamicSqlMap(@Param("sqlStr")String sql); +} diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/mapping/ExcelRptTempMapper.xml b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/mapping/ExcelRptTempMapper.xml new file mode 100644 index 0000000..7f742e5 --- /dev/null +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/mapper/mapping/ExcelRptTempMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/CustomReportService.java b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/CustomReportService.java new file mode 100644 index 0000000..7895c67 --- /dev/null +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/CustomReportService.java @@ -0,0 +1,134 @@ +package com.njcn.csharmonic.service; + +import com.njcn.csharmonic.param.SensitiveUserReportQueryParam; +import com.njcn.csharmonic.pojo.param.ReportSearchParam; +import com.njcn.csharmonic.pojo.param.ReportTemplateParam; +import com.njcn.csharmonic.pojo.po.ExcelRptTemp; +import com.njcn.csharmonic.pojo.vo.ReportTemplateVO; +import com.njcn.csharmonic.pojo.vo.ReportTreeVO; +import com.njcn.csharmonic.pojo.vo.SysDeptTempVO; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * pqs + * 自定义报表 + * + * @author cdf + * @date 2022/8/16 + */ +public interface CustomReportService { + + + /** + * 新增自定义报表模板 + * + * @author qijian + * @date 2022/10/18 + */ + boolean addCustomReportTemplate(ReportTemplateParam reportTemplateParam); + + + /** + * 修改自定义报表模板 + * + * @author qijian + * @date 2022/10/18 + */ + boolean updateCustomReportTemplate(ReportTemplateParam.UpdateReportTemplateParam reportTemplateParam); + + /** + * 根据id获取模板 + * + * @author qijian + * @date 2022/10/18 + */ + ExcelRptTemp getCustomReportTemplateById(String id); + + + /** + * 模板列表 + * + * @author qijian + * @date 2022/10/18 + */ + List getTemplateList(ReportSearchParam reportSearchParam); + + /** + * 删除模板 + * + * @author qijian + * @date 2022/10/18 + */ + boolean delTemplate(ReportSearchParam reportSearchParam); + + + /** + * 切换模板激活状态 + * + * @author qijian + * @date 2022/10/18 + */ + boolean updateStatus(ReportSearchParam reportSearchParam); + + + /** + * 替换报表数据并返回 + * + * @param reportSearchParam 请求参数 + * @param response + * @author qijian + * @date 2022/10/18 + */ + void getCustomReport(ReportSearchParam reportSearchParam, HttpServletResponse response); + + + /** + * 查询报告模板树节点 + * + * @author cdf + * @date 2022/8/26 + */ + List reportChooseTree(); + + List targetLimitChooseTree(); + + /** + * 台账类型树 + * + * @author cdf + * @date 2023/10/23 + */ + List terminalChooseTree(); + + /** + * 绑定/解绑模板数据 + * + * @author qijian + * @date 2022/10/18 + */ + boolean updateBindTemplate(List reportSearchParams); + + /** + * 根据模板ID查询数据 + * + * @author qijian + * @date 2022/10/18 + */ + List getDataByTempId(String id); + + /** + * 根据部门查询模板 + * + * @author qijian + * @date 2022/10/18 + */ + List getTemplateByDept(String id); + + void viewCustomReportTemplateById(String id, HttpServletResponse response); + + + void getSensitiveUserReport(SensitiveUserReportQueryParam queryParam, HttpServletResponse response); + +} diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CustomReportServiceImpl.java b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CustomReportServiceImpl.java new file mode 100644 index 0000000..380ba24 --- /dev/null +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CustomReportServiceImpl.java @@ -0,0 +1,1652 @@ +package com.njcn.csharmonic.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.TimeInterval; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONConfig; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONTokener; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; +import com.njcn.common.pojo.enums.common.DataStateEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.utils.FileUtil; +import com.njcn.csdevice.api.CsCommTerminalFeignClient; +import com.njcn.csdevice.api.WlRecordFeignClient; +import com.njcn.csdevice.pojo.po.WlRecord; +import com.njcn.csharmonic.enums.CsHarmonicResponseEnum; +import com.njcn.csharmonic.mapper.ExcelRptTempMapper; +import com.njcn.csharmonic.param.SensitiveUserReportQueryParam; +import com.njcn.csharmonic.pojo.dto.ReportTemplateDTO; +import com.njcn.csharmonic.pojo.param.ReportSearchParam; +import com.njcn.csharmonic.pojo.param.ReportTemplateParam; +import com.njcn.csharmonic.pojo.po.ExcelRptTemp; +import com.njcn.csharmonic.pojo.vo.ReportTemplateVO; +import com.njcn.csharmonic.pojo.vo.ReportTreeVO; +import com.njcn.csharmonic.pojo.vo.SysDeptTempVO; +import com.njcn.csharmonic.service.CustomReportService; +import com.njcn.csharmonic.utils.DataChangeUtil; +import com.njcn.device.biz.commApi.CommTerminalGeneralClient; +import com.njcn.device.biz.pojo.po.PqsDeviceUnit; +import com.njcn.influx.constant.InfluxDbSqlConstant; +import com.njcn.influx.pojo.constant.InfluxDBTableConstant; +import com.njcn.influx.utils.InfluxDbUtils; +import com.njcn.oss.constant.OssPath; +import com.njcn.oss.enums.OssResponseEnum; +import com.njcn.oss.utils.FileStorageUtil; +import com.njcn.system.api.DicDataFeignClient; +import com.njcn.system.api.EpdFeignClient; +import com.njcn.system.enums.DicDataEnum; +import com.njcn.system.enums.DicDataTypeEnum; +import com.njcn.system.pojo.po.DictData; +import com.njcn.system.pojo.po.EleEpdPqd; +import com.njcn.user.api.DeptFeignClient; +import com.njcn.user.api.UserFeignClient; +import com.njcn.user.pojo.po.User; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 自定义报表 + * + * @author qijian + * @date 2022/10/15 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class CustomReportServiceImpl implements CustomReportService { + + private final ExcelRptTempMapper excelRptTempMapper; + + private final EpdFeignClient epdFeignClient; + + private final FileStorageUtil fileStorageUtil; + + private final DicDataFeignClient dicDataFeignClient; + + private final DeptFeignClient deptFeignClient; + + private final InfluxDbUtils influxDbUtils; + + private final CommTerminalGeneralClient commTerminalGeneralClient; + + private final CsCommTerminalFeignClient csCommTerminalFeignClient; + + private final WlRecordFeignClient wlRecordFeignClient; + private final UserFeignClient userFeignClient; + + private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1); + + private final String CELL_DATA = "celldata"; + private final String V = "v"; + private final String STR_ONE = "#"; + private final String STR_TWO = "$"; + private final String STR_THREE = "&"; + private final String STR_FOUR = "%"; + + @Override + public void getCustomReport(ReportSearchParam reportSearchParam, HttpServletResponse response) { + TimeInterval timeInterval = new TimeInterval(); + ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(reportSearchParam.getTempId()); + if (Objects.isNull(excelRptTemp)) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_ACTIVE); + } + if (Objects.isNull(reportSearchParam.getCustomType())) { + //通用报表 + analyzeReport(reportSearchParam, excelRptTemp, response); + } else { + //浙江无线报表 + analyzeReportZhejiang(reportSearchParam, excelRptTemp, response); + } + + log.info("报表执行时间{}秒", timeInterval.intervalSecond()); + } + + + @Override + public boolean addCustomReportTemplate(ReportTemplateParam reportTemplateParam) { + checkName(reportTemplateParam, false); + MultipartFile fileContent = reportTemplateParam.getFileContent(); + //检验模板json数据规范 + try { + String content = FileUtil.multipartFileToString(fileContent); + new JSONArray(content); + } catch (Exception e) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE)); + //新增模板表 + ExcelRptTemp excelRptTemp = new ExcelRptTemp(); + BeanUtils.copyProperties(reportTemplateParam, excelRptTemp); + excelRptTemp.setState(DataStateEnum.ENABLE.getCode()); + excelRptTemp.setActivation(DataStateEnum.ENABLE.getCode()); + excelRptTempMapper.insert(excelRptTemp); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateCustomReportTemplate(ReportTemplateParam.UpdateReportTemplateParam reportTemplateParam) { + checkName(reportTemplateParam, true); + MultipartFile fileContent = reportTemplateParam.getFileContent(); + //检验模板json数据规范 + try { + String content = FileUtil.multipartFileToString(fileContent); + new JSONArray(content); + } catch (Exception e) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + + //删除之前的文件 + ExcelRptTemp excelRptTempOld = excelRptTempMapper.selectById(reportTemplateParam.getId()); + fileStorageUtil.deleteFile(excelRptTempOld.getContent()); + reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE)); + //修改模板数据 + ExcelRptTemp excelRptTemp = new ExcelRptTemp(); + BeanUtils.copyProperties(reportTemplateParam, excelRptTemp); + excelRptTemp.setUpdateTime(LocalDateTime.now()); + excelRptTempMapper.updateById(excelRptTemp); + + return true; + } + + @Override + public boolean updateBindTemplate(List reportSearchParams) { + + return true; + } + + @Override + public List getDataByTempId(String id) { + return CollUtil.newArrayList(); + } + + @Override + public List getTemplateByDept(String id) { + List deptIds = deptFeignClient.getDepSonIdtByDeptId(id).getData(); + return excelRptTempMapper.getReportTemplateByDept(deptIds); + } + + @Override + public ExcelRptTemp getCustomReportTemplateById(String id) { + ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id); + return excelRptTemp; + } + + @Override + public void viewCustomReportTemplateById(String id, HttpServletResponse response) { + ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id); + try { + fileStorageUtil.downloadStream(response, excelRptTemp.getContent()); + } catch (Exception exception) { + throw new BusinessException(CsHarmonicResponseEnum.REPORT_TEMPLATE_DOWNLOAD_ERROR); + } + + } + + @Override + public void getSensitiveUserReport(SensitiveUserReportQueryParam queryParam, HttpServletResponse response) { + + } + + + @Override + public List getTemplateList(ReportSearchParam reportSearchParam) { + List list = excelRptTempMapper.getReportTemplateList(reportSearchParam); + List updateByList = list.stream().map(ReportTemplateVO::getUpdateBy).distinct().collect(Collectors.toList()); + Map userNameMap = userFeignClient.getUserByIdList(updateByList).getData().stream().collect(Collectors.toMap(User::getId, User::getName)); + list.forEach(template -> { + template.setUpdateBy(userNameMap.getOrDefault(template.getUpdateBy(), "")); + }); + return list; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean delTemplate(ReportSearchParam reportSearchParam) { + excelRptTempMapper.deleteById(reportSearchParam.getTempId()); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateStatus(ReportSearchParam reportSearchParam) { + return true; + } + + + @Override + public List reportChooseTree() { + DictData dic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.CS_DATA_TYPE.getName(), DicDataEnum.EPD.getName()).getData(); + + List list = epdFeignClient.dictMarkByDataType(dic.getId()).getData(); + list.sort(Comparator.comparingInt(EleEpdPqd::getSort)); + Map> map = list.stream().collect(Collectors.groupingBy(EleEpdPqd::getName, LinkedHashMap::new, Collectors.toList())); + + List tree = new ArrayList<>(); + map.forEach((key, value) -> { + + ReportTreeVO reportTreeVO = new ReportTreeVO(); + reportTreeVO.setName(value.get(0).getOtherName()); + reportTreeVO.setShowName(value.get(0).getShowName()); + + //存在1-50次 2-50次情况 + if (Objects.nonNull(value.get(0).getHarmStart()) && Objects.nonNull(value.get(0).getHarmEnd())) { + List reHarm = new ArrayList<>(); + for (int i = value.get(0).getHarmStart(); i <= value.get(0).getHarmEnd(); i++) { + ReportTreeVO reportTreeCount = new ReportTreeVO(); + reportTreeCount.setName(value.get(0).getOtherName() + "_" + i); + reportTreeCount.setShowName(i + "次" + value.get(0).getShowName()); + reportTreeVO.setFlag(1); + assPhase(value, reportTreeCount, reportTreeCount.getName()); + reHarm.add(reportTreeCount); + } + reportTreeVO.setChildren(reHarm); + } else { + assPhase(value, reportTreeVO, value.get(0).getOtherName()); + } + tree.add(reportTreeVO); + }); + return tree; + } + + @Override + public List targetLimitChooseTree() { + List result = new ArrayList<>(); + DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.EPD.getCode()).getData(); + List list = epdFeignClient.dictMarkByDataType(dic.getId()).getData() + .stream().filter(eleEpdPqd -> eleEpdPqd.getLimitTable().equals("pq_overlimit")).collect(Collectors.toList()); + list.sort(Comparator.comparingInt(EleEpdPqd::getSort)); + Map> map = list.stream().collect(Collectors.groupingBy(EleEpdPqd::getLimitName)); + map.forEach((key, val) -> { + ReportTreeVO reportTreeVO = new ReportTreeVO(); + reportTreeVO.setShowName(val.get(0).getShowName()); + + if (Objects.nonNull(val.get(0).getHarmStart()) && Objects.nonNull(val.get(0).getHarmEnd())) { + String one = val.get(0).getLimitName(); + List temList = new ArrayList<>(); + for (int i = val.get(0).getHarmStart(); i <= val.get(0).getHarmEnd(); i++) { + double count; + ReportTreeVO reportTreeItem = new ReportTreeVO(); + + if (val.get(0).getHarmStart() == 1) { + count = i + 0.5; + reportTreeItem.setShowName(count + "次" + val.get(0).getShowName()); + reportTreeItem.setName(STR_FOUR + one + count + STR_ONE + val.get(0).getFormula() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR); + } else { + reportTreeItem.setShowName(i + "次" + val.get(0).getShowName()); + reportTreeItem.setName(STR_FOUR + one + i + STR_ONE + val.get(0).getFormula() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR); + } + + reportTreeItem.setFlag(1); + temList.add(reportTreeItem); + } + reportTreeVO.setChildren(temList); + } else { + reportTreeVO.setName(STR_FOUR + val.get(0).getLimitName() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR + val.get(0).getFormula() + STR_FOUR); + reportTreeVO.setFlag(1); + } + + result.add(reportTreeVO); + }); + return result; + } + + @Override + public List terminalChooseTree() { + List result = new ArrayList<>(); + DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.TERMINAL_SORT.getCode()).getData(); + List list = epdFeignClient.dictMarkByDataType(dic.getId()).getData(); + list.sort(Comparator.comparingInt(EleEpdPqd::getSort)); + list.forEach(item -> { + ReportTreeVO reportTreeVO = new ReportTreeVO(); + reportTreeVO.setId(item.getId()); + reportTreeVO.setName(STR_THREE + item.getName() + STR_THREE); + reportTreeVO.setFlag(1); + reportTreeVO.setShowName(item.getShowName()); + result.add(reportTreeVO); + }); + return result; + } + + /*组装相别*/ + private void assPhase(List value, ReportTreeVO reportTreeItem, String key) { + List phaseTree = new ArrayList<>(); + value.forEach(item -> { + if (Objects.nonNull(item.getPhase()) && !"M".equals(item.getPhase())) { + List statTree = new ArrayList<>(); + ReportTreeVO reportTreePhase = new ReportTreeVO(); + reportTreePhase.setName(item.getPhase()); + reportTreePhase.setShowName(item.getPhase()); + + assStatMethod(item, statTree, key, item.getPhase()); + reportTreePhase.setChildren(statTree); + phaseTree.add(reportTreePhase); + reportTreeItem.setChildren(phaseTree); + + } else { + List statTree = new ArrayList<>(); + assStatMethod(item, statTree, key, ""); + reportTreeItem.setChildren(statTree); + } + }); + + } + + + private void assStatMethod(EleEpdPqd item, List statTree, String oneKey, String twoKey) { + //存在向别为M但是Stat_Method不为空 + if (StrUtil.isNotBlank(item.getStatMethod())) { + String[] arr = item.getStatMethod().split(","); + List stat = Stream.of(arr).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(stat)) { + stat.forEach(statItem -> { + ReportTreeVO reportTreeStat = new ReportTreeVO(); + String tem = ""; + if (Objects.nonNull(item.getLimitName())) { + tem = STR_ONE + item.getLimitName(); + } else { + tem = "#NO"; + } + if (StrUtil.isNotBlank(twoKey)) { + reportTreeStat.setName(STR_TWO + oneKey + STR_ONE + twoKey + STR_ONE + statItem + STR_ONE + item.getResourcesId().trim() + tem.trim() + STR_TWO); + } else { + reportTreeStat.setName(STR_TWO + oneKey + STR_ONE + statItem + STR_ONE + item.getResourcesId().trim() + tem.trim() + STR_TWO); + } + + reportTreeStat.setShowName(statItem); + statTree.add(reportTreeStat); + }); + } + } + } + + + /** + * 检查名称是否已存在 + * + * @param reportTemplateParam,isUpdate 参数 + * @return 结果 + */ + private void checkName(ReportTemplateParam reportTemplateParam, boolean isUpdate) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + //条件组合:where state = 1 and name = ? + lambdaQueryWrapper.eq(ExcelRptTemp::getState, DataStateEnum.ENABLE.getCode()).eq(ExcelRptTemp::getName, reportTemplateParam.getName()); + + //and id <> ? + if (isUpdate) { + if (reportTemplateParam instanceof ReportTemplateParam.UpdateReportTemplateParam) { + lambdaQueryWrapper.ne(ExcelRptTemp::getId, ((ReportTemplateParam.UpdateReportTemplateParam) reportTemplateParam).getId()); + } + } + + //若存在条件数据抛出异常 + int count = excelRptTempMapper.selectCount(lambdaQueryWrapper); + if (count > 0) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_REPEAT); + } + + } + + + /** + * 数据单位信息 + * + * @param reportSearchParam + * @return + */ + private Map unitMap(ReportSearchParam reportSearchParam) { + PqsDeviceUnit deviceUnit; + if (Objects.isNull(reportSearchParam.getResourceType())) { + deviceUnit = commTerminalGeneralClient.lineUnitDetail(reportSearchParam.getLineId()).getData(); + } else { + deviceUnit = csCommTerminalFeignClient.lineUnitDetail(reportSearchParam.getLineId()).getData(); + } + List dictData = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEVICE_UNIT.getCode()).getData(); + Map unit = new HashMap<>(); + List list = dictData.stream().map(DictData::getCode).collect(Collectors.toList()); + for (String s : list) { + //有效值 + if (s.equals(DicDataEnum.EFFECTIVE.getCode())) { + unit.put(s + "#i", deviceUnit.getIeffective()); + unit.put(s + "#v", deviceUnit.getLineVoltage()); + } + //功率 + if (s.equals(DicDataEnum.POWER.getCode())) { + unit.put(s + "#p", deviceUnit.getTotalActiveP()); + unit.put(s + "#q", deviceUnit.getTotalNoP()); + unit.put(s + "#s", deviceUnit.getTotalViewP()); + } + //畸变率 + if (s.equals(DicDataEnum.DISTORTION.getCode())) { + unit.put(s + "#v", deviceUnit.getVdistortion()); + } + //电压偏差 + if (s.equals(DicDataEnum.VOLTAGE.getCode())) { + unit.put(s + "#v", deviceUnit.getVoltageDev()); + } + //频率 + if (s.equals(DicDataEnum.UNIT_FREQUENCY.getCode())) { + unit.put(s + "#freq", deviceUnit.getUnitFrequency()); + unit.put(s + "#freqDev", deviceUnit.getUnitFrequencyDev()); + } + //三项不平衡度 + if (s.equals(DicDataEnum.UNBALANCE.getCode())) { + unit.put(s + "#v", STR_FOUR); + unit.put(s + "#vPos", deviceUnit.getPositiveV()); + unit.put(s + "#vNeg", deviceUnit.getNoPositiveV()); + unit.put(s + "#vZero", deviceUnit.getNoPositiveV()); + unit.put(s + "#i", STR_FOUR); + unit.put(s + "#iPos", "A"); + unit.put(s + "#iNeg", "A"); + unit.put(s + "#iZero", "A"); + } + //基波 + if (s.equals(DicDataEnum.FUND.getCode())) { + unit.put(s + "#i", deviceUnit.getIfund()); + unit.put(s + "#v", deviceUnit.getVfundEffective()); + + } + } + return unit; + } + + + /** + * @param data 同类型的cell模板 + * @param sql 单个cell模板 + * @param endList 用于返回最终组装好的数据,类似data + * @param limitMap 指标是否合格模板 + * @param assNoPassMap 用于存储不合格的指标 + * @date 2023/10/20 + */ + private void assSqlNew(List data, StringBuilder sql, List endList, String method, ReportSearchParam reportSearchParam, Map limitMap, Map overLimitMap, Map assNoPassMap) { + //sql拼接示例:select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai') + + + //cp95函数特殊处理 PERCENTILE(field_key, N) + if (InfluxDbSqlConstant.CP95.equals(method)) { + + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(InfluxDbSqlConstant.PERCENTILE) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.NUM_95) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM); + } else { + sql.append(InfluxDbSqlConstant.PERCENTILE) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.NUM_95) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA); + } + } + + } else { + + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM); + } else { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA); + } + } + + } + + sql.append(StrPool.C_SPACE); + String temS = data.get(0).getResourceId().replace("r_stat_data", "day").replace("_d", ""); + sql.append(InfluxDbSqlConstant.FROM).append(temS); + + sql.append(InfluxDbSqlConstant.WHERE) + .append(InfluxDBTableConstant.LINE_ID) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(reportSearchParam.getLineId()) + .append(InfluxDbSqlConstant.QM); + //相别特殊处理 + if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) { + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.PHASIC_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getPhase()) + .append(InfluxDbSqlConstant.QM); + } + + + //data_flicker、data_fluc、data_plt 无 value_type + if (!InfluxDBTableConstant.DATA_FLICKER.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_FLUC.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_PLT.equals(data.get(0).getClassId())) { + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.VALUE_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getStatMethod()) + .append(InfluxDbSqlConstant.QM); + } + + //频率和频率偏差仅统计T相 + if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) { + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.PHASIC_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(InfluxDBTableConstant.PHASE_TYPE_T) + .append(InfluxDbSqlConstant.QM); + } + //时间范围处理 + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM); + + sql.append(InfluxDbSqlConstant.TZ); + + long a = System.currentTimeMillis(); + List> mapList = influxDbUtils.getMapResult(sql.toString()); + long b = System.currentTimeMillis(); + System.out.println(sql); + System.out.println("当前sql执行了:" + (b - a) + "ms"); + if (CollUtil.isEmpty(mapList)) { + data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList()); + } else { + Map map = mapList.get(0); + for (ReportTemplateDTO item : data) { + if (Objects.nonNull(map) && map.containsKey(item.getItemName())) { + double v = Double.parseDouble(map.get(item.getItemName()).toString()); + item.setValue(String.format("%.3f", v)); + + if (overLimitMap.containsKey(item.getLimitName())) { + Float tagVal = overLimitMap.get(item.getLimitName()); + if (v > tagVal) { + item.setOverLimitFlag(1); + } else { + item.setOverLimitFlag(0); + } + } + + //判断是否越限 + if (limitMap.size() != 0) { + String key = item.getLimitName() + STR_ONE + item.getStatMethod().toLowerCase() + "#pq_overlimit"; + if (limitMap.containsKey(key)) { + ReportTemplateDTO tem = limitMap.get(key); + double limitVal = Double.parseDouble(tem.getValue()); + if (v > limitVal) { + tem.setOverLimitFlag(1); + assNoPassMap.put(key, tem); + } else if (!assNoPassMap.containsKey(key)) { + tem.setOverLimitFlag(0); + assNoPassMap.put(key, tem); + } + } + } + } else { + item.setValue("/"); + } + } + } + endList.addAll(data); + } + + + /** + * @param data 同类型的cell模板 + * @param sql 单个cell模板 + * @param endList 用于返回最终组装好的数据,类似data + * @param limitMap 指标是否合格模板 + * @param assNoPassMap 用于存储不合格的指标 + * @date 2023/10/20 + */ + + private void assSqlByMysql(List data, StringBuilder sql, List endList, String method, ReportSearchParam reportSearchParam, Map limitMap, Map overLimitMap, Map assNoPassMap) { + //sql拼接示例:select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai') + if (InfluxDbSqlConstant.CP95.equals(method)) { + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(InfluxDbSqlConstant.MAX) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS) + .append("\"" + data.get(i).getItemName() + "\""); + } else { + sql.append(InfluxDbSqlConstant.MAX) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS) + .append("\"" + data.get(i).getItemName() + "\"").append(StrUtil.COMMA); + } + } + } else { + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS) + .append("\"" + data.get(i).getItemName() + "\""); + } else { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS) + .append("\"" + data.get(i).getItemName() + "\"").append(StrUtil.COMMA); + } + } + + } + + //拼接表名 + sql.append(StrPool.C_SPACE) + .append(InfluxDbSqlConstant.FROM) + .append(data.get(0).getResourceId()); + + + sql.append(InfluxDbSqlConstant.WHERE) + .append(InfluxDBTableConstant.LINE_ID) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(reportSearchParam.getLineId()) + .append(InfluxDbSqlConstant.QM); + //相别特殊处理 + if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) { + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.PHASIC_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getPhase()) + .append(InfluxDbSqlConstant.QM); + } + + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.VALUE_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getStatMethod()) + .append(InfluxDbSqlConstant.QM); + + + //频率和频率偏差仅统计T相 + if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) { + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.PHASIC_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(InfluxDBTableConstant.PHASE_TYPE_T) + .append(InfluxDbSqlConstant.QM); + } + //时间范围处理 + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM); + + System.out.println(sql); + + List> mapList = SqlRunner.DEFAULT.selectList(sql.toString()); + if (CollUtil.isEmpty(mapList) || Objects.isNull(mapList.get(0))) { + data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList()); + } else { + Map map = convertKeysToUpperCase(mapList.get(0)); + for (ReportTemplateDTO item : data) { + if (map.containsKey(item.getItemName())) { + double v = Double.parseDouble(map.get(item.getItemName()).toString()); + item.setValue(String.format("%.3f", v)); + if (overLimitMap.containsKey(item.getLimitName())) { + Float tagVal = overLimitMap.get(item.getLimitName()); + if (v > tagVal) { + item.setOverLimitFlag(1); + } else { + item.setOverLimitFlag(0); + } + } + + //判断是否越限 + if (!limitMap.isEmpty()) { + String key = item.getLimitName() + STR_ONE + item.getStatMethod() + "#PQ_OVERLIMIT"; + if (limitMap.containsKey(key)) { + ReportTemplateDTO tem = limitMap.get(key); + double limitVal = Double.parseDouble(tem.getValue()); + if (v > limitVal) { + tem.setOverLimitFlag(1); + assNoPassMap.put(key, tem); + } else if (!assNoPassMap.containsKey(key)) { + tem.setOverLimitFlag(0); + assNoPassMap.put(key, tem); + } + } + } + } else { + item.setValue("/"); + } + } + } + endList.addAll(data); + } + + + /** + * map key转大写 + */ + public static Map convertKeysToUpperCase(Map originalMap) { + Map newMap = new HashMap<>(); + if (CollUtil.isNotEmpty(originalMap)) { + for (Map.Entry entry : originalMap.entrySet()) { + newMap.put(entry.getKey().toUpperCase(), entry.getValue()); + } + } + + return newMap; + } + + + /** + * 处理 + * + * @author cdf + * @date 2023/10/8 + */ + + private void analyzeReport(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp, HttpServletResponse response) { + //定义一个线程集合 + List> futures = new ArrayList<>(); + //指标 + List reportTemplateDTOList = new ArrayList<>(); + //限值 + List reportLimitList = new ArrayList<>(); + //台账 + List terminalList = new ArrayList<>(); + JSONArray jsonArray; + try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) { + jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig())); + parseTemplate(jsonArray, reportTemplateDTOList, reportLimitList, terminalList); + } catch (Exception e) { + if (e instanceof BusinessException) { + throw new BusinessException(e.getMessage()); + } else { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + } + //处理指标是否合格 + reportLimitList = new LinkedHashSet<>(reportLimitList).stream().sorted(Comparator.comparing(ReportTemplateDTO::getItemName)).collect(Collectors.toList()); + Map limitMap = overLimitDeal(reportLimitList, reportSearchParam); + //存放限值指标的map + Map limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity())); + + List endList = new CopyOnWriteArrayList<>(); + if (CollUtil.isNotEmpty(reportTemplateDTOList)) { + //开始组织sql + reportTemplateDTOList = new LinkedHashSet<>(reportTemplateDTOList).stream().sorted(Comparator.comparing(ReportTemplateDTO::getItemName)).collect(Collectors.toList()); + Map> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId)); + //定义存放越限指标的map + Map assNoPassMap = new HashMap<>(); + classMap.forEach((classKey, templateValue) -> { + Map> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod)); + //每张表开启一个独立线程查询 + futures.add(executorService.submit(() -> { + //avg.max,min,cp95 + valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> { + //相别分组 + Map> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase)); + phaseMap.forEach((phaseKey, phaseVal) -> { + StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT); + if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) { + assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap); + } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) { + assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap); + } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) { + assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.AVG_WEB, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap); + } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) { + assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.CP95, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap); + } + + }); + }); + })); + + }); + + // 等待所有任务完成 + for (Future future : futures) { + try { + future.get(); // 这会阻塞直到任务完成或抛出异常 + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + log.error("自定义报表多线程查询流程出错!错误信息{}", e.getMessage()); + } + } + + //处理指标最终判定合格还是不合格 + dealTargetResult(assNoPassMap, limitTargetMapX, endList); + } + if (CollUtil.isNotEmpty(endList)) { + //数据单位信息 + Map unit = unitMap(reportSearchParam); + //进行反向赋值到模板 + //1、根据itemName分组 + Map> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName)); + //处理台账信息 + Map finalTerminalMap; + if (CollUtil.isNotEmpty(terminalList)) { + finalTerminalMap = convertKeysToUpperCase(commTerminalGeneralClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData()); + } else { + finalTerminalMap = new HashMap<>(); + } + //2、把itemName的value赋给v和m + jsonArray.forEach(item -> { + JSONObject jsonObject = (JSONObject) item; + JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA); + itemArr.forEach((it) -> { + if (Objects.nonNull(it) && !"null".equals(it.toString())) { + //获取到1列 + JSONObject data = (JSONObject) it; + JSONObject son = (JSONObject) data.get(V); + if (son.containsKey(V)) { + String v = son.getStr(V); + //数据格式:$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$ + if (v.charAt(0) == '$' && v.contains(STR_ONE)) { + String str = ""; + List rDto = assMap.get(v.replace(STR_TWO, "").toUpperCase()); + if (Objects.nonNull(rDto)) { + str = rDto.get(0).getValue(); + //没有值,赋"/" + if (StringUtils.isBlank(str)) { + str = "/"; + } + son.set(V, str); + if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) { + son.set("fc", "#990000"); + } + } + } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) { + //指标合格情况 + String str = ""; + List rDto = assMap.get(v.replace(STR_FOUR, "").toUpperCase()); + if (Objects.nonNull(rDto)) { + str = rDto.get(0).getValue(); + //没有值,赋"/" + if (StringUtils.isBlank(str)) { + str = "/"; + } + son.set(V, str); + if ("不合格".equals(str)) { + son.set("fc", "#990000"); + } + } + } else if (v.charAt(0) == '&') { + //结论 + String tem = v.replace(STR_THREE, "").toUpperCase(); + if (Objects.nonNull(finalTerminalMap)) { + if ("STATIS_TIME".equals(tem)) { + //如何时间是大于当前时间则用当前时间 + String localTime = InfluxDbSqlConstant.END_TIME; + LocalDate localDate = LocalDateTimeUtil.parseDate(reportSearchParam.getEndTime(), DatePattern.NORM_DATE_PATTERN); + LocalDate nowDate = LocalDate.now(); + if (nowDate.isAfter(localDate)) { + son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + localTime); + } else { + localTime = " " + LocalTime.now().format(DatePattern.NORM_TIME_FORMATTER); + son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + nowDate + localTime); + } + } else { + //台账信息 + son.set(V, finalTerminalMap.getOrDefault(tem, "/")); + } + } + } + //解决数据单位问题 @指标#类型@ + if (v.charAt(0) == '@' && v.contains(STR_ONE)) { + String replace = v.replace("@", ""); + son.set(V, unit.getOrDefault(replace, "/")); + + } + } + } + }); + }); + } + //导出自定义报表 + downReport(jsonArray, response); + } + + + /** + * 解析模板 + * + * @author cdf + * @date 2023/10/20 + */ + private void parseTemplate(JSONArray jsonArray, List reportTemplateDTOList, List reportLimitList, List terminalList) { + try { + //通过文件服务器获取 + jsonArray.forEach(item -> { + JSONObject jsonObject = (JSONObject) item; + JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA); + itemArr.forEach((it) -> { + if (Objects.nonNull(it) && !"null".equals(it.toString())) { + //获取到1列 + JSONObject data = (JSONObject) it; + JSONObject son = (JSONObject) data.get(V); + if (son.containsKey(V)) { + String v = son.getStr(V); + //数据格式:$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$ + if (v.charAt(0) == '$' && v.contains(STR_ONE)) { + //剔除前后$ + v = v.replace(STR_TWO, ""); + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + reportTemplateDTO.setItemName(v.toUpperCase()); + //根据#分割数据 + String[] vItem = v.split(STR_ONE); + if (vItem.length == 5) { + //$HA[_25]#B#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0].toUpperCase()); + reportTemplateDTO.setPhase(vItem[1].substring(0, 1).toUpperCase()); + reportTemplateDTO.setStatMethod(vItem[2].toUpperCase()); + reportTemplateDTO.setResourceId(vItem[3].toUpperCase()); + reportTemplateDTO.setLimitName(vItem[4].toUpperCase()); + } else if (vItem.length == 4) { + //$HA[_25]#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0].toUpperCase()); + reportTemplateDTO.setPhase("M"); + reportTemplateDTO.setStatMethod(vItem[1].toUpperCase()); + reportTemplateDTO.setResourceId(vItem[2].toUpperCase()); + reportTemplateDTO.setLimitName(vItem[3].toUpperCase()); + } + + reportTemplateDTOList.add(reportTemplateDTO); + } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) { + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + v = v.replace(STR_FOUR, ""); + reportTemplateDTO.setItemName(v.toUpperCase()); + //根据#分割数据 + String[] vItem = v.split(STR_ONE); + if (vItem.length == 3) { + //$HA[_25]#B#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0].toUpperCase()); + reportTemplateDTO.setStatMethod(vItem[1].toUpperCase()); + reportTemplateDTO.setResourceId(vItem[2].toUpperCase()); + } + reportLimitList.add(reportTemplateDTO); + } else if (v.charAt(0) == '&') { + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + v = v.replace(STR_THREE, ""); + reportTemplateDTO.setItemName(v.toUpperCase()); + reportTemplateDTO.setTemplateName(v.toUpperCase()); + terminalList.add(reportTemplateDTO); + } + } + } + }); + }); + } catch (Exception e) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + } + + + /** + * 获取测点限值 + * + * @author cdf + * @date 2023/10/23 + */ + private Map overLimitDeal(List reportLimitList, ReportSearchParam + reportSearchParam) { + Map limitMap = new HashMap<>(); + if (CollUtil.isNotEmpty(reportLimitList)) { + StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT); + for (int i = 0; i < reportLimitList.size(); i++) { + if (i == reportLimitList.size() - 1) { + sql.append(reportLimitList.get(i).getTemplateName()).append(StrUtil.C_SPACE); + } else { + sql.append(reportLimitList.get(i).getTemplateName()).append(StrUtil.COMMA); + } + } + sql.append(InfluxDbSqlConstant.FROM).append(reportLimitList.get(0).getResourceId()).append(InfluxDbSqlConstant.WHERE).append("id ='").append(reportSearchParam.getLineId()).append("'"); + limitMap = excelRptTempMapper.dynamicSqlMap(sql.toString()); + if (Objects.isNull(limitMap)) { + throw new BusinessException("当前报表测点限值缺失!"); + } + + for (ReportTemplateDTO item : reportLimitList) { + if (limitMap.containsKey(item.getTemplateName())) { + item.setValue(limitMap.get(item.getTemplateName()).toString()); + } + } + } + limitMap = convertKeysToUpperCase(limitMap); + return limitMap; + } + + /** + * 报告下载 + */ + private void downReport(JSONArray jsonArray, HttpServletResponse response) { + InputStream reportStream = IoUtil.toStream(jsonArray.toString(), CharsetUtil.UTF_8); + response.setContentType("application/octet-stream;charset=UTF-8"); + response.setHeader("Content-Disposition", "attachment;filename=" + "aa"); + OutputStream toClient = null; + try { + toClient = new BufferedOutputStream(response.getOutputStream()); + //通过IOUtils对接输入输出流,实现文件下载 + IOUtils.copy(reportStream, toClient); + toClient.flush(); + } catch (Exception e) { + throw new BusinessException(OssResponseEnum.DOWNLOAD_FILE_STREAM_ERROR); + } finally { + IOUtils.closeQuietly(reportStream); + IOUtils.closeQuietly(toClient); + } + } + + + private void analyzeReportZhejiang(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp, HttpServletResponse response) { + //指标 + List reportTemplateDTOList = new ArrayList<>(); + //限值 + List reportLimitList = new ArrayList<>(); + //台账 + List terminalList = new ArrayList<>(); + JSONArray jsonArray; + try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) { + jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig())); + parseTemplateZhejiang(jsonArray, reportTemplateDTOList, reportLimitList, terminalList); + } catch (Exception e) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + + DictData pqdDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.PQD.getCode(), DicDataTypeEnum.CS_DATA_TYPE.getCode()).getData(); + List eleEpdPqdList = epdFeignClient.dictMarkByDataType(pqdDic.getId()).getData() + .stream().filter(item -> StrUtil.isNotEmpty(item.getPrimaryFormula())).collect(Collectors.toList()); + eleEpdPqdList.sort(Comparator.comparingInt(EleEpdPqd::getSort)); + Map> pqdMap = eleEpdPqdList.stream().collect(Collectors.groupingBy(EleEpdPqd::getName)); + + //处理指标是否合格 + reportLimitList = new LinkedHashSet<>(reportLimitList) + .stream() + .sorted(Comparator.comparing(ReportTemplateDTO::getItemName)) + .collect(Collectors.toList()); + + Map limitMap = overLimitDeal(reportLimitList, reportSearchParam); + //存放限值指标的map + Map limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity())); + + //组装最后监测点条件 + List temList = wlRecordFeignClient.getWlAssByWlId(reportSearchParam.getLineId()).getData(); + //List wlRecordList = temList.stream().filter(it -> it.getType() == 1).collect(Collectors.toList()); + if (CollUtil.isEmpty(temList) && temList.size() == 1) { + throw new BusinessException("当前测试项无测试数据"); + } + + List endList = new ArrayList<>(); + if (CollUtil.isNotEmpty(reportTemplateDTOList)) { + + //开始组织sql + reportTemplateDTOList = new LinkedHashSet<>(reportTemplateDTOList) + .stream() + .sorted(Comparator.comparing(ReportTemplateDTO::getItemName)) + .collect(Collectors.toList()); + + + Map> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId)); + Map assNoPassMap = new HashMap<>(); + long deal = System.currentTimeMillis(); + classMap.forEach((classKey, templateValue) -> { + Map> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod)); + + //avg.max,min,cp95 + valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> { + + //相别分组 + Map> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase)); + phaseMap.forEach((phaseKey, phaseVal) -> { + StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT); + if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) { + assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap); + } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) { + assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap); + } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) { + assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.AVG, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap); + } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) { + assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.PERCENTILE, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap); + } + }); + }); + + }); + //处理指标最终判定合格还是不合格 + dealTargetResult(assNoPassMap, limitTargetMapX, endList); + long dealEnd = System.currentTimeMillis(); + System.out.println("查询数据库花费时间" + (dealEnd - deal) / 1000 + "S"); + } + if (CollUtil.isNotEmpty(endList)) { + long jie = System.currentTimeMillis(); + //数据单位信息 + Map unit = unitMap(reportSearchParam); + //进行反向赋值到模板 + //1、根据itemName分组 + Map> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName)); + //处理台账信息 + Map finalTerminalMap; + if (CollUtil.isNotEmpty(terminalList)) { + if (Objects.nonNull(reportSearchParam.getCustomType()) && reportSearchParam.getCustomType() == 1) { + WlRecord wlRecordMain = temList.stream().filter(it -> it.getType() == 0).collect(Collectors.toList()).get(0); + finalTerminalMap = new HashMap<>(); + finalTerminalMap.put("lineName", wlRecordMain.getItemName()); + //finalTerminalMap.put("statis_time",wlRecordMain.getStartTime()+"_"+wlRecordMain.getEndTime()); + finalTerminalMap.put("pt", wlRecordMain.getCt().toString()); + finalTerminalMap.put("ct", wlRecordMain.getPt().toString()); + + finalTerminalMap.put("Standard_Capacity", wlRecordMain.getCapacitySscb().toString()); + finalTerminalMap.put("Short_Capacity", wlRecordMain.getCapacitySscmin().toString()); + finalTerminalMap.put("Deal_Capacity", wlRecordMain.getCapacitySi().toString()); + finalTerminalMap.put("Dev_Capacity", wlRecordMain.getCapacitySt().toString()); + } else { + finalTerminalMap = commTerminalGeneralClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData(); + } + } else { + finalTerminalMap = new HashMap<>(); + } + //2、把itemName的value赋给v和m + dealExcelResult(jsonArray, assMap, unit, finalTerminalMap); + long jieEnd = System.currentTimeMillis(); + System.out.println("组装信息耗时 " + (jieEnd - jie) / 1000 + "S"); + } + + long daochu = System.currentTimeMillis(); + //导出自定义报表 + downReport(jsonArray, response); + long daochuEnd = System.currentTimeMillis(); + System.out.println("导出耗时 " + (daochuEnd - daochu) / 1000 + "S"); + } + + + private void assSqlZhejiang(List data, StringBuilder + sql, List endList, String method, ReportSearchParam reportSearchParam, Map limitMap, Map overLimitMap, Map assNoPassMap, List wlRecordList, Map> pqdMap) { + + //sql拼接示例:select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai') + //cp95函数特殊处理 PERCENTILE(field_key, N) + if (InfluxDbSqlConstant.PERCENTILE.equals(method)) { + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(InfluxDbSqlConstant.PERCENTILE) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()).append(InfluxDbSqlConstant.NUM_95) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM); + } else { + sql.append(InfluxDbSqlConstant.PERCENTILE) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()).append(InfluxDbSqlConstant.NUM_95) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA); + } + } + } else { + for (int i = 0; i < data.size(); i++) { + if (i == data.size() - 1) { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM); + } else { + sql.append(method) + .append(InfluxDbSqlConstant.LBK) + .append(data.get(i).getTemplateName()) + .append(InfluxDbSqlConstant.RBK) + .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM) + .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA); + } + } + + } + + sql.append(StrPool.C_SPACE).append(InfluxDbSqlConstant.FROM).append("pqd_data"); + //相别特殊处理 + sql.append(InfluxDbSqlConstant.WHERE) + .append(InfluxDBTableConstant.PHASIC_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getPhase()) + .append(InfluxDbSqlConstant.QM); + + //data_flicker、data_fluc、data_plt 无 value_type + sql.append(InfluxDbSqlConstant.AND) + .append(InfluxDBTableConstant.VALUE_TYPE) + .append(InfluxDbSqlConstant.EQ) + .append(InfluxDbSqlConstant.QM) + .append(data.get(0).getStatMethod().toLowerCase()) + .append(InfluxDbSqlConstant.QM); + + List> allList = new ArrayList<>(); + + WlRecord ceShiItem = wlRecordList.stream().filter(it -> it.getType() == 0).collect(Collectors.toList()).get(0); + for (WlRecord wlRecord : wlRecordList) { + if (wlRecord.getType().equals(1)) { + StringBuilder temSql = new StringBuilder(sql); + String start = LocalDateTimeUtil.format(wlRecord.getStartTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + String end = LocalDateTimeUtil.format(wlRecord.getEndTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)); + temSql.append(" and line_id = '").append(wlRecord.getLineId()).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(start).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.AND) + .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(end).append(InfluxDbSqlConstant.QM) + .append(InfluxDbSqlConstant.TZ); + + List> temMapList = influxDbUtils.getMapResult(temSql.toString()); + if (CollUtil.isNotEmpty(temMapList)) { + Map tem = temMapList.get(0); + //需要吧测点为二次值的转换为一次值 + if (wlRecord.getDataLevel().equals("Secondary")) { + for (Map.Entry entry : tem.entrySet()) { + if (Objects.nonNull(entry.getValue()) && !entry.getKey().equals("time")) { + String key = entry.getKey(); + double val = (double) entry.getValue(); + String zi = key.substring(0, key.indexOf(STR_ONE)); + String[] temStrArr = zi.split("_"); + boolean flag = isInteger(temStrArr[temStrArr.length - 1]); + if (flag) { + zi = zi.substring(0, zi.lastIndexOf("_")); + } + if (pqdMap.containsKey(zi)) { + EleEpdPqd eleEpdPqd = pqdMap.get(zi).get(0); + if (!eleEpdPqd.getPrimaryFormula().equals("*CT")) { + val = val / 1000; + } + double vRes = DataChangeUtil.secondaryToPrimary(eleEpdPqd.getPrimaryFormula(), val, (double) ceShiItem.getPt(), (double) ceShiItem.getCt()); + entry.setValue(vRes); + } + } + } + } + + allList.add(temMapList.get(0)); + } + } + } + + Map resultMap = dealResultMap(method, allList); + if (resultMap.isEmpty()) { + data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList()); + } else { + //遍历模板对查询出来的数据进行赋值 + for (ReportTemplateDTO item : data) { + if (resultMap.containsKey(item.getItemName())) { + double v = (Double) resultMap.get(item.getItemName()); + item.setValue(String.format("%.3f", v)); + + if (overLimitMap.containsKey(item.getLimitName())) { + Float tagVal = overLimitMap.get(item.getLimitName()); + if (v > tagVal) { + item.setOverLimitFlag(1); + } else { + item.setOverLimitFlag(0); + } + } + + //结论判断是否越限 + String key = item.getLimitName() + STR_ONE + item.getStatMethod().toLowerCase() + "#pq_overlimit"; + if (limitMap.containsKey(key)) { + ReportTemplateDTO tem = limitMap.get(key); + double limitVal = Double.parseDouble(tem.getValue()); + if (v > limitVal) { + tem.setOverLimitFlag(1); + tem.setValue(tem.getValue()); + assNoPassMap.put(key, tem); + } else if (!assNoPassMap.containsKey(key)) { + tem.setOverLimitFlag(0); + tem.setValue(tem.getValue()); + assNoPassMap.put(key, tem); + } + } + } else { + item.setValue("/"); + } + } + } + + endList.addAll(data); + } + + + /** + * 对多测点数据进行计算求出一组数据 + * + * @param method + * @param allList + * @return + */ + private Map dealResultMap(String method, List> allList) { + Map resultMap = new HashMap<>(); + // 遍历列表中的每个Map + if (method.equals(InfluxDbSqlConstant.MIN)) { + for (Map map : allList) { + // 遍历当前Map的键值对 + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + if (Objects.nonNull(entry.getValue()) && !key.equals("time")) { + double value = (double) entry.getValue(); + // 检查结果Map中是否已包含该键 + if (!resultMap.containsKey(key) || (double) resultMap.get(key) > value) { + // 如果不包含,或当前值更大,则更新结果Map + resultMap.put(key, value); + } + } + } + } + } else if (method.equals(InfluxDbSqlConstant.MAX) || method.equals(InfluxDbSqlConstant.PERCENTILE)) { + for (Map map : allList) { + // 遍历当前Map的键值对 + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + if (Objects.nonNull(entry.getValue()) && !key.equals("time")) { + double value = (double) entry.getValue(); + // 检查结果Map中是否已包含该键 + if (!resultMap.containsKey(key) || (double) resultMap.get(key) < value) { + // 如果不包含,或当前值更大,则更新结果Map + resultMap.put(key, value); + } + } + } + } + } else if (method.equals(InfluxDbSqlConstant.AVG)) { + Map sumMap = new HashMap<>(); + Map countMap = new HashMap<>(); + // 遍历列表中的每个Map + for (Map map : allList) { + // 遍历当前Map的键值对 + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + if (Objects.nonNull(entry.getValue()) && !key.equals("time")) { + double value = (double) entry.getValue(); + + // 更新累计和 + sumMap.put(key, sumMap.getOrDefault(key, 0.0) + value); + // 更新计数 + countMap.put(key, countMap.getOrDefault(key, 0) + 1); + } + } + } + + // 计算平均值并存储到结果Map中 + for (String key : sumMap.keySet()) { + double sum = sumMap.get(key); + int count = countMap.get(key); + double average = BigDecimal.valueOf(sum / count).setScale(3, RoundingMode.HALF_UP).doubleValue(); + resultMap.put(key, average); + } + } + + return resultMap; + } + + + private void dealExcelResult(JSONArray + jsonArray, Map> assMap, Map unit, Map finalTerminalMap) { + jsonArray.forEach(item -> { + JSONObject jsonObject = (JSONObject) item; + JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA); + itemArr.forEach((it) -> { + if (Objects.nonNull(it) && !"null".equals(it.toString())) { + //获取到1列 + JSONObject data = (JSONObject) it; + JSONObject son = (JSONObject) data.get(V); + if (son.containsKey(V)) { + String v = son.getStr(V); + //数据格式:$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$ + if (v.charAt(0) == '$' && v.contains(STR_ONE)) { + String str = ""; + List rDto = assMap.get(v.replace(STR_TWO, "")); + if (Objects.nonNull(rDto)) { + str = rDto.get(0).getValue(); + //没有值,赋"/" + if (StringUtils.isBlank(str)) { + str = "/"; + } + son.set(V, str); + if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) { + son.set("fc", "#990000"); + } + } + } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) { + //指标合格情况 + String str = ""; + List rDto = assMap.get(v.replace(STR_FOUR, "")); + if (Objects.nonNull(rDto)) { + str = rDto.get(0).getValue(); + //没有值,赋"/" + if (StringUtils.isBlank(str)) { + str = "/"; + } + son.set(V, str); + if ("不合格".equals(str)) { + son.set("fc", "#990000"); + } + } + } else if (v.charAt(0) == '&') { + //结论 + String tem = v.replace(STR_THREE, ""); + if (Objects.nonNull(finalTerminalMap)) { + if ("statis_time".equals(tem)) { + // son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + InfluxDbSqlConstant.END_TIME); + } else { + //台账信息 + son.set(V, finalTerminalMap.getOrDefault(tem, "/")); + } + } + } else if (v.charAt(0) == '@' && v.contains(STR_ONE)) { + //解决数据单位问题 @指标#类型@ + String replace = v.replace("@", ""); + son.set(V, unit.getOrDefault(replace, "/")); + + } + } + } + }); + }); + } + + + /** + * 处理指标超标结论 + */ + private void dealTargetResult + (Map assNoPassMap, Map limitTargetMapX, List endList) { + assNoPassMap.forEach((key, val) -> { + limitTargetMapX.remove(key); + if ("Voltage_Dev".toUpperCase().equals(val.getTemplateName()) || "Freq_Dev".toUpperCase().equals(val.getTemplateName())) { + val.setValue("±" + val.getValue()); + } + if (val.getOverLimitFlag() == 1) { + val.setValue("不合格 (" + val.getValue() + ")"); + } else { + val.setValue("合格 (" + val.getValue() + ")"); + } + endList.add(val); + }); + + limitTargetMapX.forEach((key, val) -> { + if (Objects.isNull(val.getOverLimitFlag())) { + val.setValue("/"); + } else { + val.setValue("合格"); + } + endList.add(val); + }); + } + + + /** + * 解析模板 + * + * @author cdf + * @date 2023/10/20 + */ + private void parseTemplateZhejiang(JSONArray + jsonArray, List reportTemplateDTOList, List reportLimitList, List terminalList) { + try { + //通过文件服务器获取 + + jsonArray.forEach(item -> { + JSONObject jsonObject = (JSONObject) item; + JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA); + itemArr.forEach((it) -> { + if (Objects.nonNull(it) && !"null".equals(it.toString())) { + //获取到1列 + JSONObject data = (JSONObject) it; + JSONObject son = (JSONObject) data.get(V); + if (son.containsKey(V)) { + String v = son.getStr(V); + //数据格式:$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$ + if (v.charAt(0) == '$' && v.contains(STR_ONE)) { + //剔除前后$ + v = v.replace(STR_TWO, ""); + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + reportTemplateDTO.setItemName(v); + //根据#分割数据 + String[] vItem = v.split(STR_ONE); + if (vItem.length == 5) { + //$HA[_25]#B#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0]); + reportTemplateDTO.setPhase(vItem[1]); + reportTemplateDTO.setStatMethod(vItem[2]); + reportTemplateDTO.setResourceId(vItem[3]); + reportTemplateDTO.setLimitName(vItem[4]); + } else if (vItem.length == 4) { + //$HA[_25]#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0]); + reportTemplateDTO.setPhase("M"); + reportTemplateDTO.setStatMethod(vItem[1]); + reportTemplateDTO.setResourceId(vItem[2]); + reportTemplateDTO.setLimitName(vItem[3]); + } + + reportTemplateDTOList.add(reportTemplateDTO); + } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) { + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + + v = v.replace(STR_FOUR, ""); + reportTemplateDTO.setItemName(v); + //根据#分割数据 + String[] vItem = v.split(STR_ONE); + if (vItem.length == 3) { + //$HA[_25]#B#max#classId$ + reportTemplateDTO.setTemplateName(vItem[0]); + reportTemplateDTO.setStatMethod(vItem[1]); + reportTemplateDTO.setResourceId(vItem[2]); + } + reportLimitList.add(reportTemplateDTO); + } else if (v.charAt(0) == '&') { + //封装ReportTemplateDTO + ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO(); + v = v.replace(STR_THREE, ""); + reportTemplateDTO.setItemName(v); + reportTemplateDTO.setTemplateName(v); + terminalList.add(reportTemplateDTO); + } + } + } + }); + }); + } catch (Exception e) { + throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON); + } + } + + public static boolean isInteger(String str) { + try { + Integer.parseInt(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +