Kaynağa Gözat

Merge branch 'master' of http://116.63.33.55/git/industry-data-platform into master

lhy 11 ay önce
ebeveyn
işleme
aa27f58074

+ 1 - 0
industry-system/industry-da/src/main/java/com/example/opc_da/util/calculate/CalculateDataFactory.java

@@ -20,6 +20,7 @@ public class CalculateDataFactory {
         calculateDataMap.put(4, new InstantaneousCalculate());
         calculateDataMap.put(5, new SumCalculate());
         calculateDataMap.put(6, new CountCalculate());
+        calculateDataMap.put(7, new DifferenceCalculate());
     }
 
     public static CalculateData getCalculateData(Integer type) {

+ 20 - 0
industry-system/industry-da/src/main/java/com/example/opc_da/util/calculate/DifferenceCalculate.java

@@ -0,0 +1,20 @@
+package com.example.opc_da.util.calculate;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+
+public class DifferenceCalculate implements CalculateData {
+    @Override
+    public String calculateData(List<String> valueList, Integer scale, Integer defaultScale) {
+        // 如果值列表为空,则返回null,或根据业务逻辑返回合适的默认值
+        if (valueList == null || valueList.isEmpty()) {
+            return null;
+        } else {
+            BigDecimal start  = new BigDecimal(valueList.get(0));
+            BigDecimal end  = new BigDecimal(valueList.get(valueList.size() - 1));
+            BigDecimal rond = end.subtract(start).setScale(scale, RoundingMode.HALF_UP);
+            return String.valueOf(rond);
+        }
+    }
+}

+ 60 - 8
industry-system/industry-da/src/main/java/com/example/opc_da/validate/reportTable/DeviceMaReportTableValidate.java

@@ -1,6 +1,10 @@
 package com.example.opc_da.validate.reportTable;
 
 import cn.hutool.extra.servlet.ServletUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.example.opc_common.entity.DictType;
+import com.example.opc_common.entity.ReportDataPolicyItem;
 import com.example.opc_common.entity.ReportTable;
 import com.example.opc_common.enums.ResultEnum;
 import com.example.opc_common.exception.CustomException;
@@ -8,44 +12,91 @@ import com.example.opc_common.util.Blank;
 import com.example.opc_common.util.ConstantStr;
 import com.example.opc_common.util.Result;
 import com.example.opc_da.config.SpringContextUtils;
+import com.example.opc_da.dao.DictDao;
 import com.example.opc_da.dao.ReportTableDao;
+import com.example.opc_da.task.AutoTableQuartzTask;
+import com.example.opc_da.task.AutoTableTimerTask;
+import com.example.opc_da.timer.PeriodTimerFactory;
+import com.example.opc_da.timer.QuartzTimerFactory;
 import org.quartz.CronExpression;
 
 import javax.servlet.http.HttpServletRequest;
 import java.time.LocalDateTime;
-import java.util.UUID;
+import java.util.*;
 
 /**
- * 设备主报表验证具体类
+ * 自动主报表验证具体类
  */
 public class DeviceMaReportTableValidate extends DeviceReportTableValidate {
     ReportTableDao reportTableDao = SpringContextUtils.getBean(ReportTableDao.class);
+    DictDao dictDao = SpringContextUtils.getBean(DictDao.class);
 
     @Override
     public ReportTable getData(ReportTable reportTable) {
         Integer runState = reportTable.getRunState();
         if (ConstantStr.START_UP.equals(runState)) {
-            return reportTable.setReportTableData(resolveDeviceTableData(reportTable.getReportTableData(), LocalDateTime.now()));
+            // 数据组未配置点位数据的小数位数,从字典中获取默认小数位数
+            DictType dictType = dictDao.queryDictTypeByKeyType("item_scale", null);
+            Integer defaultScale = Integer.parseInt(dictType.getDictKeyValue());
+            List<ReportDataPolicyItem> itemScaleList = reportTableDao.getItemScaleByReportTableIdOrPolicyIdOrItemId(reportTable.getId(), null, null);
+            //待完成。。。
+            return reportTable.setReportTableData(resolveAutoTableData(reportTable.getReportTableData(), LocalDateTime.now(), itemScaleList, defaultScale));
         }
-        return reportTable;
+        //解析自动报表结构
+        JSONObject reportTableData = JSONObject.parseObject(reportTable.getReportTableData());
+        //得到sheet数据
+        JSONObject sheet = reportTableData.getJSONObject("sheet");
+        JSONArray sheetData = sheet.getJSONArray("data");
+        echoSheet(sheetData, new HashMap<>());
+        sheet.put("data", sheetData);
+        reportTableData.put("sheet", sheet);
+
+        return reportTable.setReportTableData(reportTableData.toJSONString());
     }
 
     @Override
     public Result runTable(String id, Integer runState, ReportTable reportTable) {
         Integer oldRunState = reportTable.getRunState();
+        String cronId = reportTable.getCronId();
+        String cron = reportTable.getCron();
+        if (Blank.isEmpty(cronId, cron)) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "请先配置定时时间");
+        }
+        if (Blank.isEmpty(oldRunState)) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "未知报表运行状态,请刷新重试");
+        }
         reportTableDao.runAutoTableById(id, runState);
         if (runState.equals(ConstantStr.START_UP)) {
             if (oldRunState.equals(ConstantStr.START_UP)) {
-                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此报表已经处于启动状态");
+                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此自动报表已经处于启动状态");
+            }
+            //新增定时器任务
+            Map<String, Object> map = new HashMap<>();
+            Integer type = reportTable.getType();
+            map.put("reportTable", reportTable);
+            if (type.equals(0)) {
+                PeriodTimerFactory.creteTimer().addTask(cronId, AutoTableTimerTask.class, cron, map);
+            } else if (type.equals(1)) {
+                QuartzTimerFactory.creteTimer().addTask(cronId, AutoTableQuartzTask.class, cron, map);
+            } else {
+                throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "目前没有此种类型的定时器");
             }
             return Result.ok("启动成功");
         } else if (runState.equals(ConstantStr.STOP_IT)) {
             if (oldRunState.equals(ConstantStr.STOP_IT)) {
-                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此报表已经处于停止状态");
+                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此自动报表已经处于停止状态");
+            }
+            Integer type = reportTable.getType();
+            if (type.equals(0)) {
+                PeriodTimerFactory.creteTimer().delTask(cronId);
+            } else if (type.equals(1)) {
+                QuartzTimerFactory.creteTimer().delTask(cronId);
+            } else {
+                throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "目前没有此种类型的定时器");
             }
             return Result.ok("停止成功");
         } else {
-            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "报表的状态只有启动或停止");
+            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "自动报表的状态只有启动或停止");
         }
     }
 
@@ -53,7 +104,7 @@ public class DeviceMaReportTableValidate extends DeviceReportTableValidate {
     public Result setAutoTableTime(ReportTable reportTable, HttpServletRequest request) {
         ReportTable oldReportTable = reportTableDao.getReportTableNoDataById(reportTable.getId());
         if (oldReportTable.getRunState().equals(ConstantStr.START_UP)) {
-            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "设备报表现在处于启动状态,不允许修改定时时间");
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "自动报表现在处于启动状态,不允许修改定时时间");
         }
         if (reportTable.getIsRunPrint().equals(ConstantStr.START_UP)) {
             if (Blank.isEmpty(reportTable.getPrintConfigId())) {
@@ -80,4 +131,5 @@ public class DeviceMaReportTableValidate extends DeviceReportTableValidate {
         }
         return Result.ok("修改成功");
     }
+
 }

+ 98 - 0
industry-system/industry-da/src/main/java/com/example/opc_da/validate/reportTable/DeviceMaReportTableValidate_bak.java

@@ -0,0 +1,98 @@
+package com.example.opc_da.validate.reportTable;
+
+import cn.hutool.extra.servlet.ServletUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.example.opc_common.entity.ReportTable;
+import com.example.opc_common.enums.ResultEnum;
+import com.example.opc_common.exception.CustomException;
+import com.example.opc_common.util.Blank;
+import com.example.opc_common.util.ConstantStr;
+import com.example.opc_common.util.Result;
+import com.example.opc_da.config.SpringContextUtils;
+import com.example.opc_da.dao.ReportTableDao;
+import org.quartz.CronExpression;
+
+import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * 设备主报表验证具体类
+ */
+public class DeviceMaReportTableValidate_bak extends DeviceReportTableValidate {
+    ReportTableDao reportTableDao = SpringContextUtils.getBean(ReportTableDao.class);
+
+    @Override
+    public ReportTable getData(ReportTable reportTable) {
+        Integer runState = reportTable.getRunState();
+        if (ConstantStr.START_UP.equals(runState)) {
+            return null;
+//            return reportTable.setReportTableData(resolveDeviceTableData(reportTable.getReportTableData(), LocalDateTime.now()));
+        }
+        //解析自动报表结构
+        JSONObject reportTableData = JSONObject.parseObject(reportTable.getReportTableData());
+        //得到sheet数据
+        JSONObject sheet = reportTableData.getJSONObject("sheet");
+        JSONArray sheetData = sheet.getJSONArray("data");
+        echoSheet(sheetData, new HashMap<>());
+        sheet.put("data", sheetData);
+        reportTableData.put("sheet", sheet);
+
+        return reportTable.setReportTableData(reportTableData.toJSONString());
+    }
+
+    @Override
+    public Result runTable(String id, Integer runState, ReportTable reportTable) {
+        Integer oldRunState = reportTable.getRunState();
+        reportTableDao.runAutoTableById(id, runState);
+        if (runState.equals(ConstantStr.START_UP)) {
+            if (oldRunState.equals(ConstantStr.START_UP)) {
+                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此报表已经处于启动状态");
+            }
+            return Result.ok("启动成功");
+        } else if (runState.equals(ConstantStr.STOP_IT)) {
+            if (oldRunState.equals(ConstantStr.STOP_IT)) {
+                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "此报表已经处于停止状态");
+            }
+            return Result.ok("停止成功");
+        } else {
+            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "报表的状态只有启动或停止");
+        }
+    }
+
+    @Override
+    public Result setAutoTableTime(ReportTable reportTable, HttpServletRequest request) {
+        ReportTable oldReportTable = reportTableDao.getReportTableNoDataById(reportTable.getId());
+        if (oldReportTable.getRunState().equals(ConstantStr.START_UP)) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "设备报表现在处于启动状态,不允许修改定时时间");
+        }
+        if (reportTable.getIsRunPrint().equals(ConstantStr.START_UP)) {
+            if (Blank.isEmpty(reportTable.getPrintConfigId())) {
+                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "报表配置打印时,需要配置打印配置");
+            }
+        }
+        String clientIP = ServletUtil.getClientIP(request, "");
+        clientIP = "0:0:0:0:0:0:0:1".equals(clientIP) ? "127.0.0.1" : clientIP;
+        reportTable.setPrintIp(clientIP);
+        String cron = reportTable.getCron();
+        if (Blank.isEmpty(cron)) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "定时器配置不能为空");
+        }
+        if (reportTable.getType().equals(1) && !CronExpression.isValidExpression(cron)) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "定时任务配置不正确,请重新配置");
+        }
+        String cronId = oldReportTable.getCronId();
+        if (Blank.isEmpty(cronId)) {
+            cronId = UUID.randomUUID().toString().replace("-", "");
+            reportTable.setCronId(cronId);
+        }
+        if (reportTableDao.setAutoTableTime(reportTable) <= 0) {
+            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "修改失败");
+        }
+        return Result.ok("修改成功");
+    }
+}

+ 509 - 13
industry-system/industry-da/src/main/java/com/example/opc_da/validate/reportTable/DeviceReportTableValidate.java

@@ -1,42 +1,538 @@
 package com.example.opc_da.validate.reportTable;
 
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.cqcy.ei.influxdb.entity.Item;
+import com.cqcy.ei.influxdb.service.InFluxDBService;
+import com.example.opc_common.entity.ReportDataPolicyItem;
+import com.example.opc_common.util.Blank;
+import com.example.opc_da.config.SpringContextUtils;
+import com.example.opc_da.task.ReportTableBasicItemEnum;
+import com.example.opc_da.util.calculate.CalculateDataFactory;
+import com.example.opc_da.util.cycleTime.CycleTimeFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
 
 import javax.validation.constraints.NotBlank;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 /**
- * 设备报表验证抽象类
+ * 自动报表验证抽象类
  */
+@Slf4j
 public abstract class DeviceReportTableValidate implements ReportTableValidate {
 
+    private static final String timePattern = "yyyy-MM-dd HH:mm:ss.SSS";//秒
+    private static final String timePattern_hour = "yyyy-MM-dd HH:00";//小时
+    private static final String timePattern_min = "yyyy-MM-dd HH:mm";//分
+    private static final String timePattern_day = "yyyy-MM-dd";//日
+    private static final String timePattern_month = "yyyy-MM";//月
+    private static final String timePattern_year = "yyyy";//年
+    String timePattern_str;
+
+    InFluxDBService inFluxDBService = SpringContextUtils.getBean(InFluxDBService.class);
+    String bucket = SpringContextUtils.getYamlProperty("influxdb.bucket");
+
     /**
-     * 解析设备表格数据
+     * 将自动报表的reportTableData解析出来,并赋值相应的数据
      *
-     * @param reportTableDataStr 报表数据字符串
-     * @param referTime 参考时间
-     * @return 解析后的报表数据
+     * @param reportTableDataStr 报表字符串
+     * @param referTime          参考时间
+     * @return
      */
-    public String resolveDeviceTableData(@NotBlank String reportTableDataStr, LocalDateTime referTime) {
+    public String resolveAutoTableData(@NotBlank String reportTableDataStr, LocalDateTime referTime, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale) {
         //解析自动报表结构
         JSONObject reportTableData = JSONObject.parseObject(reportTableDataStr);
         //得到sheet数据
         JSONObject sheet = reportTableData.getJSONObject("sheet");
-        reportTableData.put("sheet", resolveDeviceTableSheetData(sheet, referTime));
+        reportTableData.put("sheet", resolveAutoTableSheetData(sheet, referTime, itemScaleList, defaultScale));
+
 
         //将生成的数据重新转换为json
         return reportTableData.toJSONString();
     }
 
-    private JSONObject resolveDeviceTableSheetData(JSONObject sheet, LocalDateTime referTime) {
-        //解析sheet数据
-        JSONObject sheetData = sheet.getJSONObject("data");
-        //解析sheet的每一行数据
-        for (String key : sheetData.keySet()) {
+    /**
+     * 解析周期报表sheet数据
+     *
+     * @param sheet
+     * @param referTime 参考时间
+     * @return
+     */
+    private JSONObject resolveAutoTableSheetData(JSONObject sheet, LocalDateTime referTime, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale) {
+        JSONArray sheetData = sheet.getJSONArray("data");
+        String sheetIndex = sheet.getString("index");
+        //遍历sheet所有单元格,并存为Map<tableId,Map<uid,JSONObject>>格式
+        Map<String, Map<String, JSONObject>> sheetTableMap = getAutoStringMapMap(sheetData, sheetIndex);
+        //
+        if (Blank.isNotEmpty(sheetTableMap.get("calcChain"))) {
+            //处理公式
+            sheet.put("calcChain", sheetTableMap.get("calcChain").values().toArray());
+            //清除公式
+            sheetTableMap.remove("calcChain");
+        }
+        Map<String, JSONObject> settingMap = new HashMap<>();
+        // ws拿出配置
+        for (Map.Entry<String, Map<String, JSONObject>> sheetTable : sheetTableMap.entrySet()) {
+            if (sheetTable.getKey().endsWith("_deviceIndex")) {
+                settingMap.put(sheetTable.getKey(), sheetTable.getValue().get("data"));
+            }
+        }
+        for (Map.Entry<String, JSONObject> setting : settingMap.entrySet()) {
+            sheetTableMap.remove(setting.getKey());
+        }
+        //遍历生成的sheetTableMap,根据配置获取数据,并存为Map<tableId, Map<uid,List<Item>>>格式
+        Map<String, List<Map<String, String>>> sheetTableDataMap = new HashMap<>();
+        for (Map.Entry<String, Map<String, JSONObject>> sheetTable : sheetTableMap.entrySet()) {
+            sheetTableDataMap.put(sheetTable.getKey(),
+                    generateSheetTableDataMap(sheetTable.getValue(), referTime, itemScaleList, defaultScale, settingMap.get(sheetTable.getKey() + "_deviceIndex")));
         }
         //sheet数据最后往Json中存为data[0].data,回填数据
-//        echoSheet(sheetData, sheetTableDataMap);
+        echoSheet(sheetData, sheetTableDataMap);
         sheet.put("data", sheetData);
         return sheet;
     }
+
+    /**
+     * 回填表格数据
+     *
+     * @param sheetData
+     * @param sheetTableDataMap
+     */
+    protected void echoSheet(JSONArray sheetData, Map<String, List<Map<String, String>>> sheetTableDataMap) {
+        JSONObject json = new JSONObject();
+        for (int i = 0; i < sheetData.size(); i++) {
+            JSONArray row = sheetData.getJSONArray(i);
+            for (int j = row.size() - 1; j >= 0; j--) {
+                JSONObject rowCol = row.getJSONObject(j);
+                if (Blank.isNotEmpty(rowCol)) {
+                    //能解析的数据才赋值
+                    try {
+                        JSONObject rowColJson = JSONObject.parseObject(rowCol.getString("celldata"));
+                        String type = rowColJson.getString("type");
+                        String tableId = rowColJson.getString("tableId");
+                        List<Map<String, String>> itemList = sheetTableDataMap.get(tableId);
+
+                        if (json.get(tableId + "_row") == null) {
+                            json.put(tableId + "_row", 0);
+                            json.put(tableId + "_row_i", i);
+                        } else {
+                            if (json.getInteger(tableId + "_row_i") != i) {
+                                json.put(tableId + "_row_i", i);
+                                json.put(tableId + "_row", json.getInteger(tableId + "_row") + 1);
+                            }
+                        }
+                        Map<String, String> item = null;
+                        if (itemList != null && json.getInteger(tableId + "_row") < itemList.size()) {
+                            item = itemList.get(json.getInteger(tableId + "_row"));
+                        }
+                        if (Blank.isEmpty(item)) {
+                            rowCol.put("v", null);
+                            rowCol.put("m", null);
+                            continue;
+                        }
+                        //如果类型为数据,则存入数据
+                        if (type.equals("data")) {
+                            JSONObject rowColData = rowColJson.getJSONObject("data");
+                            rowCol.put("v", item.get(rowColData.getString("itemId")));
+                            rowCol.put("m", item.get(rowColData.getString("itemId")));
+                            //如果类型为时间,则存入时间
+                        } else if (type.equals("index")) {
+                            rowCol.put("v", json.getInteger(tableId + "_row") + 1);
+                            rowCol.put("m", json.getInteger(tableId + "_row") + 1);
+                        } else if (type.equals("starttime")) {
+                            rowCol.put("v", item.get("startTime"));
+                            rowCol.put("m", item.get("startTime"));
+                        } else if (type.equals("stoptime")) {
+                            rowCol.put("v", item.get("endTime"));
+                            rowCol.put("m", item.get("endTime"));
+                        } else if (type.equals("runtime")) {
+                            rowCol.put("v", item.get("countTime"));
+                            rowCol.put("m", item.get("countTime"));
+                        }
+                    } catch (Exception e) {
+                        String v = rowCol.getString("v");
+                        String regex = "^\\$\\{.*\\}$";
+                        //赋值基础数据项
+                        if (v != null && v.matches(regex)) {
+                            if (Arrays.stream(ReportTableBasicItemEnum.values())
+                                    .filter(b -> b.name().equals(v.substring(2, v.length() - 1))).findFirst().orElse(null) != null) {
+                                String value = Objects.requireNonNull(Arrays.stream(ReportTableBasicItemEnum.values())
+                                        .filter(b -> b.name().equals(v.substring(2, v.length() - 1))).findFirst().orElse(null)).getValue();
+                                rowCol.put("v", value);
+                                rowCol.put("m", value);
+                            } else {
+                                rowCol.put("v", null);
+                                rowCol.put("m", null);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 遍历sheet所有单元格,并存为Map<tableId,Map<uid,JSONObject>>格式
+     *
+     * @param sheetData
+     * @return
+     */
+    @NotNull
+    private static Map<String, Map<String, JSONObject>> getAutoStringMapMap(JSONArray sheetData, String index) {
+        Map<String, Map<String, JSONObject>> sheetTableMap = new HashMap<>();
+        for (int i = 0; i < sheetData.size(); i++) {
+            JSONArray row = sheetData.getJSONArray(i);
+            for (int j = 0; j < row.size(); j++) {
+                JSONObject rowCol = row.getJSONObject(j);
+                if (Blank.isNotEmpty(rowCol)) {
+                    try {
+                        JSONObject rowColJson = JSONObject.parseObject(rowCol.getString("celldata"));
+                        if (rowColJson != null) {
+                            String tableId = rowColJson.getString("tableId");
+                            String type = rowColJson.getString("type");
+                            if (type.equals("data")) {
+                                JSONObject rowColData = rowColJson.getJSONObject("data");
+                                String uid = rowColData.getString("uid");
+                                Map<String, JSONObject> sheetUidMap = sheetTableMap.get(tableId);
+                                if (Blank.isEmpty(sheetUidMap)) sheetUidMap = new HashMap<>();
+                                //得到所有sheet数据生成条件
+                                if (Blank.isEmpty(sheetUidMap.get(uid)) && Blank.isNotEmpty(uid)) {
+                                    sheetUidMap.put(uid, rowColJson);
+                                    sheetTableMap.put(tableId, sheetUidMap);
+                                }
+                            } else if ("index".equals(type)) {
+                                // ws新增设备逻辑
+                              if (Blank.isEmpty(sheetTableMap.get(tableId + "_deviceIndex"))) {
+
+                                  sheetTableMap.put(tableId + "_deviceIndex", new HashMap<String, JSONObject>() {
+                                          {
+                                              put("data", rowColJson);
+                                          }
+                                  });
+                              }
+                            }
+                        }
+                        String calcCell = rowCol.getString("f");
+                        if (Blank.isNotEmpty(calcCell)) {
+                            JSONObject calcChain = new JSONObject();
+                            calcChain.put("r", i);
+                            calcChain.put("c", j);
+                            calcChain.put("index", index);
+
+                            Map<String, JSONObject> sheetCalcMap = sheetTableMap.get("calcChain");
+                            if (Blank.isEmpty(sheetCalcMap)) sheetCalcMap = new HashMap<>();
+                            String cell = String.format("%d_%d", i, j);
+                            if (Blank.isEmpty(sheetCalcMap.get(cell)) && Blank.isNotEmpty(cell)) {
+                                sheetCalcMap.put(cell, calcChain);
+                                sheetTableMap.put("calcChain", sheetCalcMap);
+                            }
+
+                        }
+                    } catch (Exception e) {
+                        log.error("遍历sheet所有单元格失败", e);
+                    }
+                }
+            }
+        }
+        return sheetTableMap;
+    }
+
+    /**
+     * 此方法适合,简单场景,单个区域中,点位来源于同一报表采集策略,每个点位配置一样
+     *
+     * @param sheetUidMap
+     * @param referTime
+     * @return
+     */
+    public List<Map<String, String>> generateSheetTableDataMap(
+            Map<String, JSONObject> sheetUidMap, LocalDateTime referTime, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale, JSONObject settingMap) {
+        //得到区域所有的点位配置信息
+        List<JSONObject> tableJsonObjectList = new ArrayList<>(sheetUidMap.values());
+
+
+
+        //因为单个区域内的配置一样,且归属于同一个报表采集策略,所以直接查询
+        //得到此配置信息中,所有的数据
+        List<Item> allitemList = getItems(referTime, tableJsonObjectList, tableJsonObjectList.get(0), settingMap);
+
+        return countUidData(allitemList, referTime, itemScaleList, defaultScale, settingMap);
+    }
+
+
+
+    /**
+     * 计算单个uid,分割之后的数据
+     *
+     * @param jsonObject
+     * @param itemList
+     * @param referTime
+     * @return
+     */
+    private List<Map<String, String>> countUidData(List<Item> itemList, LocalDateTime referTime, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale, JSONObject settingMap) {
+        JSONObject setting = settingMap.getJSONObject("setting");
+        //Integer scale = jsonObject.getJSONObject("data").getInteger("itemScale");
+        //根据上面时间类型,生成sTime,eTime
+        LocalDateTime sTime = getSheetStartTime(setting, referTime);
+        LocalDateTime eTime = getSheetEndTime(setting, referTime);
+        //0数据集,1单值
+        String dataValueType = setting.getString("dataValueType");
+        //取值模式:1平均值,2最大值,3最小值,4瞬时值,5求和,6计数
+        Integer valueTakingMode = setting.getInteger("valueTakingMode");
+        //时段值
+        Integer bucketValue = setting.getInteger("bucketValue");
+        return splitData(dataValueType, itemList, sTime, eTime,
+                valueTakingMode, 3, bucketValue, itemScaleList, defaultScale, settingMap);
+    }
+
+    /**
+     * 查询单个分组的所有数据
+     *
+     * @param referTime      参考时间
+     * @param jsonObjectList
+     * @param jsonObject
+     * @return
+     */
+    private List<Item> getItems(LocalDateTime referTime, List<JSONObject> jsonObjectList, JSONObject jsonObject, JSONObject settingMap) {
+        //得到单个分组的所有点位id
+        List<String> policyItemIdList = jsonObjectList.stream()
+                .map(j -> j.getJSONObject("data").getString("itemId"))
+                .collect(Collectors.toList());
+        // ws添加开关点位
+        JSONObject setting = settingMap.getJSONObject("setting");
+        policyItemIdList.add(setting.getString("var1"));
+        if (!setting.getString("var1").equals(setting.getString("var2"))) {
+            policyItemIdList.add(setting.getString("var2"));
+        }
+        //得到单个分组的配置信息
+        JSONObject data = jsonObject.getJSONObject("data");
+        String policyId = data.getString("policyId");
+
+        String valueType = setting.getString("valueType");
+
+        //根据上面时间类型,生成sTime,eTime
+        LocalDateTime sTime = getSheetStartTime(setting, referTime);
+        LocalDateTime eTime = getSheetEndTime(setting, referTime);
+        //根据配置信息查询过滤数据库的所有数据
+        List<Item> items = new ArrayList<>();
+        try {
+            items = inFluxDBService.queryHistory(bucket, policyId, sTime, eTime, policyItemIdList, valueType);
+        } catch (Exception e) {
+            log.error("查询数据库失败", e);
+        }
+        return items;
+    }
+
+    @NotNull
+    private static Function<JSONObject, JSONObject> getSheetJSONObjectFunction() {
+        return j -> {
+            JSONObject data = j.getJSONObject("data");
+            JSONObject jsonObject = new JSONObject();
+            JSONObject dataJsonObject = new JSONObject();
+            dataJsonObject.put("policyId", data.get("policyId"));
+
+            JSONObject setting = j.getJSONObject("setting");
+            JSONObject setJsonObject = new JSONObject();
+            setJsonObject.put("valueType", setting.getString("valueType"));
+
+            setJsonObject.put("bucketType", setting.getString("bucketType"));
+
+            setJsonObject.put("timeType1", setting.getString("timeType1"));
+            setJsonObject.put("timeValue1", setting.getString("timeValue1"));
+            setJsonObject.put("dateTimeType1", setting.getString("dateTimeType1"));
+            setJsonObject.put("startTime", setting.getString("startTime"));
+
+            setJsonObject.put("timeType2", setting.getString("timeType2"));
+            setJsonObject.put("timeValue2", setting.getString("timeValue2"));
+            setJsonObject.put("dateTimeType2", setting.getString("dateTimeType2"));
+            setJsonObject.put("endTime", setting.getString("endTime"));
+
+            jsonObject.put("data", dataJsonObject);
+            jsonObject.put("setting", setJsonObject);
+            return jsonObject;
+        };
+    }
+
+    /**
+     * 获取sheet单个区域的开始时间
+     *
+     * @param setting   sheet单个区域的配置
+     * @param referTime 参考时间
+     * @return
+     */
+    private LocalDateTime getSheetStartTime(JSONObject setting, LocalDateTime referTime) {
+        //开始时间
+        Integer timeType1 = setting.getInteger("timeType1");
+        Integer timeValue1 = setting.getInteger("timeValue1");
+        Integer dateTimeType1 = setting.getInteger("dateTimeType1");
+        //结束时间
+        Integer timeType2 = setting.getInteger("timeType2");
+        Integer timeValue2 = setting.getInteger("timeValue2");
+        Integer dateTimeType2 = setting.getInteger("dateTimeType2");
+        //时间区间
+        String startTime = setting.getString("startTime");
+        String endTime = setting.getString("endTime");
+
+        return CycleTimeFactory.getCycleTime(1)
+                .getLocalDateTime(referTime, 4, timeType1, timeValue1, dateTimeType1, startTime,
+                        timeType2, timeValue2, dateTimeType2, endTime);
+    }
+
+    /**
+     * 获取sheet单个区域的结束时间
+     *
+     * @param setting   sheet单个区域的配置
+     * @param referTime 参考时间
+     * @return
+     */
+    private LocalDateTime getSheetEndTime(JSONObject setting, LocalDateTime referTime) {
+        //开始时间
+        Integer timeType1 = setting.getInteger("timeType1");
+        Integer timeValue1 = setting.getInteger("timeValue1");
+        Integer dateTimeType1 = setting.getInteger("dateTimeType1");
+        //结束时间
+        Integer timeType2 = setting.getInteger("timeType2");
+        Integer timeValue2 = setting.getInteger("timeValue2");
+        Integer dateTimeType2 = setting.getInteger("dateTimeType2");
+        //时间范围
+        String startTime = setting.getString("startTime");
+        String endTime = setting.getString("endTime");
+
+        LocalDateTime localDateTime = CycleTimeFactory.getCycleTime(2)
+                .getLocalDateTime(referTime, 4, timeType1, timeValue1, dateTimeType1, startTime,
+                        timeType2, timeValue2, dateTimeType2, endTime);
+        return localDateTime.isBefore(LocalDateTime.now()) ? localDateTime : LocalDateTime.now();
+    }
+
+
+
+
+
+    /**
+     * 通过开始时间和结束时间分割数据,并计算
+     *
+     * @param dataValueType   0数据集,1单值,空也为数据集
+     * @param itemList        全部点位集合
+     * @param startDateTime   开始时间
+     * @param endDateTime     结束时间
+     * @param valueTakingMode 取值模式:1平均值,2最大值,3最小值,4瞬时值,5求和,6计数
+     * @param bucketType      时段类型:0天,1时,2分,3秒
+     * @param bucketValue     时段值
+     * @return
+     */
+    private List<Map<String, String>> splitData(String dataValueType, List<Item> itemList, LocalDateTime startDateTime, LocalDateTime endDateTime,
+                                 Integer valueTakingMode, Integer bucketType, Integer bucketValue, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale, JSONObject settingMap) {
+        List<Map<String, String>> newItemList = new ArrayList<>();
+        JSONObject setting = settingMap.getJSONObject("setting");
+        String var1 = setting.getString("var1");
+        String var2 = setting.getString("var2");
+        // 状态1等于的值
+        String ipt1 = setting.getString("ipt1");
+        // 状态2等于的值
+        String ipt2 = setting.getString("ipt2");
+        // 是否计算时间
+        Integer isGenCountTime = setting.getInteger("isGenCountTime");
+        LocalDateTime time1 = null;
+        LocalDateTime time2 = null;
+        if (var1.equals(var2)) {
+            // 单变量
+            List<Item> varList1 = itemList.stream().filter(item -> item.getName().equals(var1))
+                    .sorted(Comparator.comparing(item -> LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern)))).collect(Collectors.toList());
+           
+            for (Item item : varList1) {
+                if (time1 == null) {
+                    if (ipt1.equals(item.getValue())) {
+                        time1 = LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern));
+                    }
+                } else {
+                    if (ipt2.equals(item.getValue())) {
+                        time2 = LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern));
+                        newItemList.add(handleItemList(time1, time2, isGenCountTime, var1, var2, itemList, valueTakingMode, true, itemScaleList, defaultScale));
+                        time1 = null;
+                    }
+                }
+            }
+            if (time1 != null) {
+                newItemList.add(handleItemList(time1, endDateTime, isGenCountTime, var1, var2, itemList, valueTakingMode, false, itemScaleList, defaultScale));
+                time1 = null;
+            }
+        } else {
+            // 双变量
+            List<Item> varList1 = itemList.stream().filter(item -> item.getName().equals(var1))
+                    .sorted(Comparator.comparing(item -> LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern)))).collect(Collectors.toList());
+            List<Item> varList2 = itemList.stream().filter(item -> item.getName().equals(var2))
+                    .sorted(Comparator.comparing(item -> LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern)))).collect(Collectors.toList());
+            for (Item item : varList1) {
+                if (time1 == null) {
+                    if (ipt1.equals(item.getValue())) {
+                        time1 = LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern));
+                        if (time2 != null && time1.isBefore(time2)) {
+                            time1 = null;
+                            continue;
+                        }
+                        for (int i = 0; i < varList2.size(); i++) {
+                            if (time1.isBefore(LocalDateTime.parse(varList2.get(i).getTime(), DateTimeFormatter.ofPattern(timePattern)))) {
+                                if (ipt2.equals(varList2.get(i).getValue())) {
+                                    time2 = LocalDateTime.parse(varList2.get(i).getTime(), DateTimeFormatter.ofPattern(timePattern));
+                                    newItemList.add(handleItemList(time1, time2, isGenCountTime, var1, var2, itemList, valueTakingMode, true, itemScaleList, defaultScale));
+                                    time1 = null;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (time1 != null) {
+                newItemList.add(handleItemList(time1, endDateTime, isGenCountTime, var1, var2, itemList, valueTakingMode, false, itemScaleList, defaultScale));
+                time1 = null;
+            }
+        }
+        return newItemList;
+    }
+
+    private Map<String, String> handleItemList(LocalDateTime time1, LocalDateTime time2, Integer isGenCountTime, String var1, String var2,
+                                List<Item> itemList, Integer valueTakingMode, boolean status, List<ReportDataPolicyItem> itemScaleList, Integer defaultScale) {
+        Map<String, List<Item>> map = itemList.stream().filter(item -> {
+            LocalDateTime time = LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern));
+            return !item.getName().equals(var1) && !item.getName().equals(var2) && (time.isAfter(time1) || time.isEqual(time1))
+                    && (time.isBefore(time2) || time.isEqual(time2));
+        }).collect(Collectors.groupingBy(
+                Item::getName
+        ));
+        Map<String, String> data = map.entrySet().stream().collect(Collectors.toMap(Map.Entry<String, List<Item>>::getKey, entry -> {
+                    Optional<ReportDataPolicyItem> first = itemScaleList.stream()
+                            .filter(item -> entry.getValue().get(0).getName().equals(item.getItemName()))
+                            .findFirst();
+                    Integer scale = null;
+                    if (first.isPresent()) {
+                        scale = first.get().getScale();
+                    }
+                  return CalculateDataFactory.getCalculateData(valueTakingMode).calculateData(
+                            entry.getValue().stream().filter(distinctByKey1(Item::getTime))
+                                    .sorted(Comparator.comparing(item -> LocalDateTime.parse(item.getTime(), DateTimeFormatter.ofPattern(timePattern))))
+                                    .map(Item::getValue).collect(Collectors.toList()), scale, defaultScale);
+                }
+        ));
+        data.put("startTime", LocalDateTimeUtil.format(time1, timePattern));
+        data.put("endTime", status ? LocalDateTimeUtil.format(time2, timePattern) : "");
+        if (isGenCountTime == 1) {
+            data.put("countTime", Convert.toStr(LocalDateTimeUtil.between(time1, time2).toMinutes()));
+        }
+        return data;
+    }
+
+    static <T> Predicate<T> distinctByKey1(Function<? super T, ?> keyExtractor) {
+        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
+        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
+    }
 }

+ 114 - 0
industry-system/industry-da/src/main/java/com/example/opc_da/validate/reportTable/DeviceReportTableValidate_bak.java

@@ -0,0 +1,114 @@
+package com.example.opc_da.validate.reportTable;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.cqcy.ei.influxdb.entity.Item;
+import com.example.opc_common.util.Blank;
+import com.example.opc_da.task.ReportTableBasicItemEnum;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * 设备报表验证抽象类
+ */
+public abstract class DeviceReportTableValidate_bak implements ReportTableValidate {
+
+    /**
+     * 解析设备表格数据
+     *
+     * @param reportTableDataStr 报表数据字符串
+     * @param referTime 参考时间
+     * @return 解析后的报表数据
+     */
+    public String resolveDeviceTableData(@NotBlank String reportTableDataStr, LocalDateTime referTime) {
+        //解析自动报表结构
+        JSONObject reportTableData = JSONObject.parseObject(reportTableDataStr);
+        //得到sheet数据
+        JSONObject sheet = reportTableData.getJSONObject("sheet");
+        reportTableData.put("sheet", resolveDeviceTableSheetData(sheet, referTime));
+
+        //将生成的数据重新转换为json
+        return reportTableData.toJSONString();
+    }
+
+    private JSONObject resolveDeviceTableSheetData(JSONObject sheet, LocalDateTime referTime) {
+        //解析sheet数据
+        JSONObject sheetData = sheet.getJSONObject("data");
+        //解析sheet的每一行数据
+        for (String key : sheetData.keySet()) {
+        }
+        //sheet数据最后往Json中存为data[0].data,回填数据
+//        echoSheet(sheetData, sheetTableDataMap);
+        sheet.put("data", sheetData);
+        return sheet;
+    }
+
+    /**
+     * 回填表格数据
+     *
+     * @param sheetData
+     * @param sheetTableDataMap
+     */
+    protected void echoSheet(JSONArray sheetData, Map<String, Map<String, List<Item>>> sheetTableDataMap) {
+        for (int i = 0; i < sheetData.size(); i++) {
+            JSONArray row = sheetData.getJSONArray(i);
+            for (int j = 0; j < row.size(); j++) {
+                JSONObject rowCol = row.getJSONObject(j);
+                if (Blank.isNotEmpty(rowCol)) {
+                    //能解析的数据才赋值
+                    try {
+                        JSONObject rowColJson = JSONObject.parseObject(rowCol.getString("celldata"));
+                        String type = rowColJson.getString("type");
+                        String tableId = rowColJson.getString("tableId");
+                        //如果类型为数据,则存入数据
+                        if (type.equals("data")) {
+                            JSONObject rowColData = rowColJson.getJSONObject("data");
+                            String uid = rowColData.getString("uid");
+                            if (Blank.isEmpty(uid) || sheetTableDataMap.get(tableId) == null || sheetTableDataMap.get(tableId).get(uid) == null
+                                    || sheetTableDataMap.get(tableId).get(uid).isEmpty()) {
+                                rowCol.put("v", null);
+                                rowCol.put("m", null);
+                            } else {
+                                List<Item> itemList = sheetTableDataMap.get(tableId).get(uid);
+                                String value = itemList.get(0).getValue();
+                                rowCol.put("v", value);
+                                rowCol.put("m", value);
+                                itemList.remove(0);
+                            }
+                            //如果类型为时间,则存入时间
+                        } else if (type.equals("datatime")) {
+                            if (Blank.isEmpty(sheetTableDataMap.get(tableId))
+                                    || sheetTableDataMap.get(tableId).values().stream().findFirst().orElse(new ArrayList<>()).isEmpty()) {
+                                rowCol.put("v", null);
+                                rowCol.put("m", null);
+                            } else {
+                                List<Item> itemList = sheetTableDataMap.get(tableId).values().stream().findFirst().orElse(new ArrayList<>());
+                                String time = itemList.get(0).getTime();
+                                rowCol.put("v", time);
+                                rowCol.put("m", time);
+                            }
+                        }
+                    } catch (Exception e) {
+                        String v = rowCol.getString("celldata");
+                        String regex = "^\\$\\{.*\\}$";
+                        //赋值基础数据项
+                        if (v != null && v.matches(regex)) {
+                            if (Arrays.stream(ReportTableBasicItemEnum.values())
+                                    .filter(b -> b.name().equals(v.substring(2, v.length() - 1))).findFirst().orElse(null) != null) {
+                                String value = Objects.requireNonNull(Arrays.stream(ReportTableBasicItemEnum.values())
+                                        .filter(b -> b.name().equals(v.substring(2, v.length() - 1))).findFirst().orElse(null)).getValue();
+                                rowCol.put("v", value);
+                                rowCol.put("m", value);
+                            } else {
+                                rowCol.put("v", null);
+                                rowCol.put("m", null);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 14 - 8
industry-system/industry-da/src/main/resources/static/reportSheet/js/src/model/data-setting-window.js

@@ -137,7 +137,10 @@ layui.define(['layer', 'form'], function(exports) {
 						<div class="layui-form-item">
 							<label class="layui-form-label form-required-label">取值模式:</label>
 							<div class="layui-input-block">
-								<input type="radio" name="valueTakingMode" value="5" title="求和" checked /	>
+								<input type="radio" name="valueTakingMode" value="1" title="平均值" checked>
+								<input type="radio" name="valueTakingMode" value="2" title="最大值"> 
+								<input type="radio" name="valueTakingMode" value="3" title="最小值">
+								<input type="radio" name="valueTakingMode" value="7" title="差值">
 							</div>
 						</div>
 						<div class="layui-form-item">
@@ -343,17 +346,12 @@ layui.define(['layer', 'form'], function(exports) {
 				},
 				yes: function(index) {
 					let data = form.val('dataSettingForm')
-					
-					if (type == 1) {
-						if (data.dataValueType == 0 && (!data.bucketValue || parseInt(data.bucketValue) < 1)) {
-							layer.msg('请设置正确的数据切换周期!', {icon: 2})
-							return
-						}
+					if (type == 1 || type == 5) {
 						if (data.dateTimeType1 == 2 && data.dateTimeType2 == 1) {
 							layer.msg('数据区域时间范围设置错误!', {icon: 2})
 							return
 						}
-						if (data.bucketType > 1) {
+						if (data.bucketType > 1 || type == 5) {
 							if (!$('#data-setting-data-1').val() || !$('#data-setting-data-2').val()) {
 								layer.msg('请设置数据区域时间范围!', {icon: 2})
 								return
@@ -387,6 +385,13 @@ layui.define(['layer', 'form'], function(exports) {
 								}
 							}
 						}
+					}
+					if (type == 1) {
+						if (data.dataValueType == 0 && (!data.bucketValue || parseInt(data.bucketValue) < 1)) {
+							layer.msg('请设置正确的数据切换周期!', {icon: 2})
+							return
+						}
+						
 						if (data.dataValueType == 0) {
 							const count = parseInt(event.countCycle(data) / parseInt(data.bucketValue))
 							if (count <= 0) {
@@ -396,6 +401,7 @@ layui.define(['layer', 'form'], function(exports) {
 							data.count = count
 						}
 					}
+					
 					if (params.success) {
 						data.startTime = $('#data-setting-data-1').val()
 						data.endTime = $('#data-setting-data-2').val()

+ 8 - 2
industry-system/industry-da/src/main/resources/static/reportSheet/js/src/model/item-list-table.js

@@ -659,7 +659,7 @@ layui.define(['layer', 'form', 'table', 'util', 'dataSettingw', 'sheetUtil', 'it
 							_this.data.deviceDataSetting.valueType = _this.data.dataSetting.valueType
 							layui.itemUtil.clearCell(_this.data.tableId, function() {
 								layui.itemUtil.deviceReport(_this.data.itemList, {
-									valLine: layui.sheetTypew.templateEventReportNum,
+									valLine: _this.data.deviceDataSetting.rowNumber,
 									isGenCountTime: _this.data.deviceDataSetting.isGenCountTime,
 								}, _this.data.deviceDataSetting, _this.data.tableId, function() {
 									layer.close(index)
@@ -746,7 +746,13 @@ layui.define(['layer', 'form', 'table', 'util', 'dataSettingw', 'sheetUtil', 'it
 								ipt1: $('#itemvar-input-1').val(),
 								ipt2: $('#itemvar-input-2').val(),
 								isGenCountTime: $('input[type="radio"][name="isGenCountTime"]:checked').val(),
-								valueType: _this.data.dataSetting.valueType
+								valueType: _this.data.dataSetting.valueType,
+								valueTakingMode: _this.data.dataSetting.valueTakingMode,
+								dateTimeType1: _this.data.dataSetting.dateTimeType1,
+								dateTimeType2: _this.data.dataSetting.dateTimeType2,
+								startTime: _this.data.dataSetting.startTime,
+								endTime: _this.data.dataSetting.endTime,
+								rowNumber: itemForm.rowNumber,
 							}, _this.data.tableId, function() {
 								layer.close(index)
 							}, function() {