瀏覽代碼

生产绩效日报功能完成

wukai 7 月之前
父節點
當前提交
527ed6b2ce
共有 18 個文件被更改,包括 1088 次插入84 次删除
  1. 31 19
      ruoyi-admin/src/main/java/com/ruoyi/biz/controller/ApiController.java
  2. 31 1
      ruoyi-admin/src/main/java/com/ruoyi/biz/controller/DataController.java
  3. 127 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/controller/TwinCalcHourSpecController.java
  4. 1 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/controller/TwinEmpCalcController.java
  5. 98 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/domain/TwinCalcHourSpec.java
  6. 61 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/mapper/TwinCalcHourSpecMapper.java
  7. 70 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/ITwinCalcHourSpecService.java
  8. 0 22
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/ApiServiceImpl.java
  9. 42 4
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/AsyncServiceImpl.java
  10. 19 9
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TaskServiceImpl.java
  11. 116 0
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TwinCalcHourSpecServiceImpl.java
  12. 38 29
      ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TwinEmpCalcServiceImpl.java
  13. 100 0
      ruoyi-admin/src/main/resources/mapper/biz/TwinCalcHourSpecMapper.xml
  14. 90 0
      ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/add.html
  15. 146 0
      ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/bizHourSpec.html
  16. 91 0
      ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/edit.html
  17. 18 0
      ruoyi-admin/src/main/resources/templates/biz/data/data.html
  18. 9 0
      ruoyi-admin/src/main/resources/templates/biz/emp/emp.html

+ 31 - 19
ruoyi-admin/src/main/java/com/ruoyi/biz/controller/ApiController.java

@@ -609,6 +609,7 @@ public class ApiController extends BaseController {
             CreationHelper creationHelper = wb.getCreationHelper();
             CellStyle percentStyle = wb.createCellStyle();
             percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
+            percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
             CellStyle p2 = wb.createCellStyle();
             p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
             List<TwinEmpCalc> list = empCalcService.selectTwinEmpCalcListByDate(DateUtils.parseDate(date));
@@ -652,6 +653,7 @@ public class ApiController extends BaseController {
             CreationHelper creationHelper = wb.getCreationHelper();
             CellStyle percentStyle = wb.createCellStyle();
             percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
+            percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
             CellStyle p2 = wb.createCellStyle();
             p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
             XSSFCellStyle bk = wb.createCellStyle();
@@ -755,28 +757,38 @@ public class ApiController extends BaseController {
     private void processJx(Sheet sheet, Map<String, List<TwinEmpCalc>> map, CellStyle percentStyle, CellStyle p2) {
         int rowNum = 2;
         for (String name : map.keySet()) {
-            List<TwinEmpCalc> calcs = map.get(name);
+            List<TwinEmpCalc> calcList = map.get(name);
+            Map<Long, List<TwinEmpCalc>> calcMap = calcList.stream().collect(Collectors.groupingBy(TwinEmpCalc::getDeviceId, LinkedHashMap::new, Collectors.toList()));
             int sr = rowNum;
-            for (TwinEmpCalc calc : calcs) {
-                Row row = sheet.createRow(rowNum);
-                Cell[] cells = new Cell[9];
-                for (int i = 0; i < cells.length; i++) {
-                    cells[i] = row.createCell(i);
-                }
-                cells[0].setCellValue(name);
-                cells[1].setCellValue(calc.getDeviceId());
-                cells[2].setCellValue(calc.getEfficiency().setScale(2, RoundingMode.HALF_UP).doubleValue());
-                cells[2].setCellStyle(percentStyle);
+            for (Long deviceId : calcMap.keySet()) {
+                List<TwinEmpCalc> list = calcMap.get(deviceId);
+                int ssr = rowNum;
+                for (TwinEmpCalc calc : list) {
+                    Row row = sheet.createRow(rowNum);
+                    Cell[] cells = new Cell[9];
+                    for (int i = 0; i < cells.length; i++) {
+                        cells[i] = row.createCell(i);
+                    }
+                    cells[0].setCellValue(name);
+                    cells[1].setCellValue(calc.getDeviceId());
+                    cells[2].setCellValue(calc.getEfficiency().setScale(2, RoundingMode.HALF_UP).doubleValue());
+                    cells[2].setCellStyle(percentStyle);
 //                    cells[3].setCellValue();
-                cells[4].setCellValue(calc.getMick());
-                cells[5].setCellValue(calc.getDensity().setScale(2, RoundingMode.HALF_UP).doubleValue());
-                cells[5].setCellStyle(p2);
-                cells[6].setCellValue(calc.getLength().doubleValue());
-                if (calc.getPrice() != null) {
-                    cells[7].setCellValue(calc.getPrice().doubleValue());
-                    cells[8].setCellValue(calc.getTotalPrice().doubleValue());
+                    cells[4].setCellValue(calc.getMick());
+                    cells[5].setCellValue(calc.getDensity().setScale(2, RoundingMode.HALF_UP).doubleValue());
+                    cells[5].setCellStyle(p2);
+                    cells[6].setCellValue(calc.getLength().doubleValue());
+                    if (calc.getPrice() != null) {
+                        cells[7].setCellValue(calc.getPrice().doubleValue());
+                        cells[8].setCellValue(calc.getTotalPrice().doubleValue());
+                    }
+                    rowNum++;
+                }
+                int eer = rowNum - 1;
+                if (list.size() > 1) {
+                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, 1, 1));
+                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, 2, 2));
                 }
-                rowNum++;
             }
             int er = rowNum - 1;
             sheet.addMergedRegion(new CellRangeAddress(sr, er, 0, 0));

+ 31 - 1
ruoyi-admin/src/main/java/com/ruoyi/biz/controller/DataController.java

@@ -11,7 +11,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.annotation.Resource;
-import java.time.*;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 
 /**
@@ -58,6 +62,32 @@ public class DataController extends BaseController {
         return success();
     }
 
+    @GetMapping("/bl3")
+    @ResponseBody
+    public AjaxResult bl3(String sd, String ed) {
+        LocalDate sld = LocalDate.parse(sd);
+        LocalDate eld = LocalDate.parse(ed);
+        do {
+            for (int i = 0; i < 24; i++) {
+                //先删除数据,再进行
+                LocalDateTime start = LocalDateTime.of(sld, LocalTime.MIN).plusHours(i);
+                String date = start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+                LocalDateTime edt = start.plusHours(1);
+                Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+                Long endTime = edt.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+                String sql = "DELETE FROM TWIN_CALC_HOUR WHERE DATA_DATE=? AND HOUR=?";
+                jdbcTemplate.update(sql, date, i);
+                sql = "DELETE FROM TWIN_RECORD_ALARMS WHERE START_TIME<=? AND END_TIME>=?";
+                jdbcTemplate.update(sql, new Date(startTime), new Date(endTime));
+                sql = "DELETE FROM TWIN_PAN_HEAD_INFO WHERE RECORD_TIME>=? AND RECORD_TIME<=?";
+                jdbcTemplate.update(sql, new Date(startTime), new Date(endTime));
+                taskService.calc(date, i);
+            }
+            sld = sld.plusDays(1);
+        } while (!sld.isAfter(eld));
+        return success();
+    }
+
     @GetMapping("/bl2")
     @ResponseBody
     public AjaxResult bl2(String sd, String ed) {

+ 127 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/controller/TwinCalcHourSpecController.java

@@ -0,0 +1,127 @@
+package com.ruoyi.biz.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.biz.domain.TwinCalcHourSpec;
+import com.ruoyi.biz.service.ITwinCalcHourSpecService;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 按配方1小时统计数据Controller
+ * 
+ * @author ruoyi
+ * @date 2024-12-20
+ */
+@Controller
+@RequestMapping("/biz/bizHourSpec")
+public class TwinCalcHourSpecController extends BaseController
+{
+    private String prefix = "biz/bizHourSpec";
+
+    @Autowired
+    private ITwinCalcHourSpecService twinCalcHourSpecService;
+
+    @RequiresPermissions("biz:bizHourSpec:view")
+    @GetMapping()
+    public String bizHourSpec()
+    {
+        return prefix + "/bizHourSpec";
+    }
+
+    /**
+     * 查询按配方1小时统计数据列表
+     */
+    @RequiresPermissions("biz:bizHourSpec:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(TwinCalcHourSpec twinCalcHourSpec)
+    {
+        startPage();
+        List<TwinCalcHourSpec> list = twinCalcHourSpecService.selectTwinCalcHourSpecList(twinCalcHourSpec);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出按配方1小时统计数据列表
+     */
+    @RequiresPermissions("biz:bizHourSpec:export")
+    @Log(title = "按配方1小时统计数据", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult export(TwinCalcHourSpec twinCalcHourSpec)
+    {
+        List<TwinCalcHourSpec> list = twinCalcHourSpecService.selectTwinCalcHourSpecList(twinCalcHourSpec);
+        ExcelUtil<TwinCalcHourSpec> util = new ExcelUtil<TwinCalcHourSpec>(TwinCalcHourSpec.class);
+        return util.exportExcel(list, "按配方1小时统计数据数据");
+    }
+
+    /**
+     * 新增按配方1小时统计数据
+     */
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存按配方1小时统计数据
+     */
+    @RequiresPermissions("biz:bizHourSpec:add")
+    @Log(title = "按配方1小时统计数据", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(TwinCalcHourSpec twinCalcHourSpec)
+    {
+        return toAjax(twinCalcHourSpecService.insertTwinCalcHourSpec(twinCalcHourSpec));
+    }
+
+    /**
+     * 修改按配方1小时统计数据
+     */
+    @RequiresPermissions("biz:bizHourSpec:edit")
+    @GetMapping("/edit/{id}")
+    public String edit(@PathVariable("id") Long id, ModelMap mmap)
+    {
+        TwinCalcHourSpec twinCalcHourSpec = twinCalcHourSpecService.selectTwinCalcHourSpecById(id);
+        mmap.put("twinCalcHourSpec", twinCalcHourSpec);
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存按配方1小时统计数据
+     */
+    @RequiresPermissions("biz:bizHourSpec:edit")
+    @Log(title = "按配方1小时统计数据", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(TwinCalcHourSpec twinCalcHourSpec)
+    {
+        return toAjax(twinCalcHourSpecService.updateTwinCalcHourSpec(twinCalcHourSpec));
+    }
+
+    /**
+     * 删除按配方1小时统计数据
+     */
+    @RequiresPermissions("biz:bizHourSpec:remove")
+    @Log(title = "按配方1小时统计数据", businessType = BusinessType.DELETE)
+    @PostMapping( "/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(twinCalcHourSpecService.deleteTwinCalcHourSpecByIds(ids));
+    }
+}

+ 1 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/controller/TwinEmpCalcController.java

@@ -71,6 +71,7 @@ public class TwinEmpCalcController extends BaseController {
     }
 
     @GetMapping("/calc")
+    @ResponseBody
     public AjaxResult calc(String date) {
         return toAjax(twinEmpCalcService.calc(DateUtils.parseDate(date)));
     }

+ 98 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/domain/TwinCalcHourSpec.java

@@ -0,0 +1,98 @@
+package com.ruoyi.biz.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 按配方1小时统计数据对象 twin_calc_hour_spec
+ *
+ * @author ruoyi
+ * @date 2024-12-20
+ */
+@ApiModel(value = "ITwinCalcHourSpec", description = "按配方1小时统计数据")
+@Data
+public class TwinCalcHourSpec extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    private Long id;
+
+    /**
+     * 日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "日期", width = 30, dateFormat = "yyyy-MM-dd")
+    @ApiModelProperty("日期")
+    private Date dataDate;
+
+    /**
+     * 小时;0-23
+     */
+    @Excel(name = "小时;0-23")
+    @ApiModelProperty("小时;0-23")
+    private Integer hour;
+
+    /**
+     * 设备ID
+     */
+    @Excel(name = "设备ID")
+    @ApiModelProperty("设备ID")
+    private Long deviceId;
+
+    /**
+     * 织造米数
+     */
+    @Excel(name = "织造米数")
+    @ApiModelProperty("织造米数")
+    private BigDecimal length;
+
+    /**
+     * 规格
+     */
+    @Excel(name = "规格")
+    @ApiModelProperty("规格")
+    private String spec;
+
+    /**
+     * 米克重
+     */
+    @Excel(name = "米克重")
+    @ApiModelProperty("米克重")
+    private Integer mick;
+
+    /**
+     * 密度
+     */
+    @Excel(name = "密度")
+    @ApiModelProperty("密度")
+    private BigDecimal density;
+
+    /**
+     * 单价
+     */
+    @Excel(name = "单价")
+    @ApiModelProperty("单价")
+    private BigDecimal price;
+
+    @ApiModelProperty("班组")
+    private String team;
+
+    public void setTeam() {
+        if (this.hour >= 7 && this.hour < 19) {
+            //A班
+            this.team = "A";
+        } else {
+            //B班
+            this.team = "B";
+        }
+    }
+}

+ 61 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/mapper/TwinCalcHourSpecMapper.java

@@ -0,0 +1,61 @@
+package com.ruoyi.biz.mapper;
+
+import java.util.List;
+import com.ruoyi.biz.domain.TwinCalcHourSpec;
+
+/**
+ * 按配方1小时统计数据Mapper接口
+ * 
+ * @author ruoyi
+ * @date 2024-12-20
+ */
+public interface TwinCalcHourSpecMapper 
+{
+    /**
+     * 查询按配方1小时统计数据
+     * 
+     * @param id 按配方1小时统计数据主键
+     * @return 按配方1小时统计数据
+     */
+    public TwinCalcHourSpec selectTwinCalcHourSpecById(Long id);
+
+    /**
+     * 查询按配方1小时统计数据列表
+     * 
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 按配方1小时统计数据集合
+     */
+    public List<TwinCalcHourSpec> selectTwinCalcHourSpecList(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 新增按配方1小时统计数据
+     * 
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 修改按配方1小时统计数据
+     * 
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 删除按配方1小时统计数据
+     * 
+     * @param id 按配方1小时统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcHourSpecById(Long id);
+
+    /**
+     * 批量删除按配方1小时统计数据
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcHourSpecByIds(String[] ids);
+}

+ 70 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/service/ITwinCalcHourSpecService.java

@@ -0,0 +1,70 @@
+package com.ruoyi.biz.service;
+
+import com.ruoyi.biz.domain.TwinCalcHourSpec;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 按配方1小时统计数据Service接口
+ *
+ * @author ruoyi
+ * @date 2024-12-20
+ */
+public interface ITwinCalcHourSpecService {
+    /**
+     * 查询按配方1小时统计数据
+     *
+     * @param id 按配方1小时统计数据主键
+     * @return 按配方1小时统计数据
+     */
+    public TwinCalcHourSpec selectTwinCalcHourSpecById(Long id);
+
+    /**
+     * 查询按配方1小时统计数据列表
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 按配方1小时统计数据集合
+     */
+    public List<TwinCalcHourSpec> selectTwinCalcHourSpecList(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 新增按配方1小时统计数据
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 修改按配方1小时统计数据
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec);
+
+    /**
+     * 批量删除按配方1小时统计数据
+     *
+     * @param ids 需要删除的按配方1小时统计数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcHourSpecByIds(String ids);
+
+    /**
+     * 删除按配方1小时统计数据信息
+     *
+     * @param id 按配方1小时统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcHourSpecById(Long id);
+
+    /**
+     * 根据日期获取统计数据
+     *
+     * @param date 日期
+     * @return 结果
+     */
+    List<TwinCalcHourSpec> selectTwinCalcHourSpecListByDate(Date date);
+}

+ 0 - 22
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/ApiServiceImpl.java

@@ -116,9 +116,6 @@ public class ApiServiceImpl implements IApiService {
         List<GramMass> gramMasses = new ArrayList<>();
         //平方米克重明细数据
         List<GramMassDetail> gramMassDetails = new ArrayList<>();
-        //TODO
-        List<TwinDeviceSpec> specs = specService.selectTwinDeviceSpecList(new TwinDeviceSpec());
-        Map<Long, TwinDeviceSpec> specMap = specs.stream().collect(Collectors.toMap(TwinDeviceSpec::getDeviceId, o -> o));
         iotService.getToken();
         TwinDevice searchDevice = new TwinDevice();
         searchDevice.setOnline("1");
@@ -159,25 +156,6 @@ public class ApiServiceImpl implements IApiService {
                 stopList.add(sdVO);
                 //处理配方明细数据
                 FormulaDetail detail = new FormulaDetail(map);
-                if (specMap.get(device.getDeviceId()) == null) {
-                    TwinDeviceSpec spec = new TwinDeviceSpec();
-                    spec.setDeviceId(device.getDeviceId());
-                    spec.setMick(detail.getFormula_data_3());
-                    BigDecimal density = BigDecimal.valueOf(detail.getFormula_data_24()).setScale(2, RoundingMode.HALF_UP);
-                    spec.setDensity(density);
-                    specService.insertTwinDeviceSpec(spec);
-                } else {
-                    TwinDeviceSpec old = specMap.get(device.getDeviceId());
-                    BigDecimal density = BigDecimal.valueOf(detail.getFormula_data_24()).setScale(2, RoundingMode.HALF_UP);
-                    if (old.getDensity().compareTo(density) != 0 || !old.getMick().equals(detail.getFormula_data_3())) {
-                        TwinDeviceSpec spec = new TwinDeviceSpec();
-                        spec.setDeviceId(device.getDeviceId());
-                        spec.setMick(detail.getFormula_data_3());
-                        spec.setDensity(density);
-                        specService.insertTwinDeviceSpec(spec);
-                    }
-
-                }
                 formulaDetail.add(detail);
 
                 //处理送经量数据

+ 42 - 4
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/AsyncServiceImpl.java

@@ -68,6 +68,13 @@ public class AsyncServiceImpl {
         List<TwinPanHeadInfo> panHeadInfo = (List<TwinPanHeadInfo>) map.get("panHead");
         panHeadInfo.forEach(info -> info.setDeviceId(twinDevice.getDeviceId()));
 
+        List<TwinCalcHourSpec> specs = (List<TwinCalcHourSpec>) map.get("specList");
+        specs.forEach(spec -> {
+            spec.setDeviceId(twinDevice.getDeviceId());
+            spec.setDataDate(date);
+            spec.setHour(period);
+        });
+
         List<TwinRecordStop> stopRecord = (List<TwinRecordStop>) map.get("stopRecord");
         stopRecord.forEach(stop -> {
             stop.setDeviceId(twinDevice.getDeviceId());
@@ -85,6 +92,7 @@ public class AsyncServiceImpl {
         result.put("stopRecord", stopRecord);
         result.put("alarmRecord", alarmRecord);
         result.put("panHead", panHeadInfo);
+        result.put("specList", specs);
         return new AsyncResult<>(result);
     }
 
@@ -135,9 +143,11 @@ public class AsyncServiceImpl {
         //初始时间点数据
         //0-data2,1-data37,2-data38,3-data39,4-data42,5-data-43,6data-44
         //2024-06-26 1-6不要了 0织造米长 1.电量
-        float[] first = new float[2];
+        List<TwinCalcHourSpec> specList = new ArrayList<>();
+        //1.米长 2.电量  3.密度
+        float[] first = new float[3];
         //上一个时间点数据
-        float[] last = new float[2];
+        float[] last = new float[3];
         //统计数据,后面2个分别代表0.织造米长,1.电量 2.重量,3.开机时间,4.停机时间
         float[] total = new float[5];
         //上一个时间点盘头数据
@@ -146,6 +156,8 @@ public class AsyncServiceImpl {
         int lastMkz = 0;
         //卷曲幅宽
         float lastFk = 0f;
+        //上次密度记录的米长
+        float lastSpecLength = 0f;
         //开始不为0的电能
         //不为0的电能结束
         float startKwh = 0f, endKwh = 0f;
@@ -169,7 +181,7 @@ public class AsyncServiceImpl {
             JSONArray da = values.getJSONArray(i);
             //0-data2,1-data37,2-data38,3-data39,4-data42,5-data-43,6data-44
             //当前时间数据
-            float[] curr = {da.getFloat(0), da.getFloat(fieldList.indexOf("Capacity_data_34"))};
+            float[] curr = {da.getFloat(0), da.getFloat(fieldList.indexOf("Capacity_data_34")), da.getFloat(fieldList.indexOf("Formula_data_24"))};
             int[] currPan = {da.getInt(fieldList.indexOf("Capacity_data_15")), da.getInt(fieldList.indexOf("Capacity_data_16")), da.getInt(fieldList.indexOf("Capacity_data_17")),
                     da.getInt(fieldList.indexOf("Capacity_data_18")), da.getInt(fieldList.indexOf("Capacity_data_19"))};
             int curr48 = da.getInt(7);
@@ -187,7 +199,11 @@ public class AsyncServiceImpl {
             }
             //计算盘头
             calcPan(currPan, lastPanHead, panHeadInfo, timestamps.getLong(i));
-
+            //计算规格米长
+            if (last[2] != curr[2]) {
+                calcSpec(total[0], lastSpecLength, last[2], lastMkz, specList);
+                lastSpecLength = total[0];
+            }
             //处理电量跳点
             float currKwh = da.getFloat(fieldList.indexOf("Capacity_data_34"));
             if (startKwh == 0) {
@@ -225,6 +241,7 @@ public class AsyncServiceImpl {
 //        }
         //还是只计算米长
         calcTotal(0, last, first, total, lastMkz, lastFk);
+        calcSpec(total[0], lastSpecLength, last[2], lastMkz, specList);
         //计算电量
         total[1] = endKwh - startKwh;
 
@@ -241,10 +258,31 @@ public class AsyncServiceImpl {
         result.put("stopRecord", stopRecord);
         result.put("alarmRecord", alarmRecord);
         result.put("panHead", panHeadInfo);
+        result.put("specList", specList);
         return result;
     }
 
     /**
+     * 按规格计算米长
+     *
+     * @param len         当前米长
+     * @param lastLen     上次记录时米长
+     * @param lastDensity 密度
+     * @param lastMkz     米克重
+     * @param specList    列表
+     */
+    private void calcSpec(float len, float lastLen, float lastDensity, int lastMkz, List<TwinCalcHourSpec> specList) {
+        //计算规格米长
+        //如果密度有变化,就记录下来
+        TwinCalcHourSpec spec = new TwinCalcHourSpec();
+        spec.setDensity(BigDecimal.valueOf(lastDensity));
+        float len1 = len - lastLen;
+        spec.setLength(BigDecimal.valueOf(len1));
+        spec.setMick(lastMkz);
+        specList.add(spec);
+    }
+
+    /**
      * 计算盘头信息
      * 数组 分别是GB1-GB5
      *

+ 19 - 9
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TaskServiceImpl.java

@@ -1,10 +1,14 @@
 package com.ruoyi.biz.service.impl;
 
 import com.ruoyi.biz.domain.*;
+import com.ruoyi.biz.mapper.TwinCalcHourSpecMapper;
 import com.ruoyi.biz.service.*;
 import com.ruoyi.biz.tools.Tools;
 import com.ruoyi.common.utils.DateUtils;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
@@ -34,8 +38,6 @@ public class TaskServiceImpl implements ITaskService {
     @Resource
     private ITwinDeviceService deviceService;
     @Resource
-    private ITwinCalc2hrService calc2hrService;
-    @Resource
     private IIotService iotService;
     @Resource
     private JdbcTemplate jdbcTemplate;
@@ -49,6 +51,8 @@ public class TaskServiceImpl implements ITaskService {
     private ITwinCalcAlarmsService alarmsService;
     @Resource
     private ITwinCalcHourService hourService;
+    @Resource
+    private SqlSessionFactory factory;
 
     /**
      * 从数据库最后一个时间段统计至当前的上一个偶数时间点
@@ -167,6 +171,7 @@ public class TaskServiceImpl implements ITaskService {
         List<Object[]> calcHours = new ArrayList<>();
         List<TwinRecordStop> stopList = new ArrayList<>();
         List<TwinRecordAlarms> alarmsList = new ArrayList<>();
+        List<TwinCalcHourSpec> specList = new ArrayList<>();
         List<Object[]> panList = new ArrayList<>();
         Date s = new Date();
         //为了避免多线程同时获取token导致重复执行,先执行一次获取token
@@ -175,22 +180,26 @@ public class TaskServiceImpl implements ITaskService {
         //查询所有在线的设备
         search.setOnline("1");
         List<TwinDevice> list = deviceService.selectTwinDeviceList(search);
-        List<TwinDevice> errList = exec(list, date, startTime, endTime, period, calcHours, stopList, panList, alarmsList);
+        List<TwinDevice> errList = exec(list, date, startTime, endTime, period, calcHours, stopList, panList, alarmsList, specList);
         //重试2次
         int repTimes = 1;
         while (errList.size() != 0) {
-            errList = exec(errList, date, startTime, endTime, period, calcHours, stopList, panList, alarmsList);
+            errList = exec(errList, date, startTime, endTime, period, calcHours, stopList, panList, alarmsList, specList);
             if (repTimes++ > 1) {
                 break;
             }
         }
-
+        if (specList != null && specList.size() > 0) {
+            try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
+                TwinCalcHourSpecMapper mapper = sqlSession.getMapper(TwinCalcHourSpecMapper.class);
+                specList.forEach(mapper::insertTwinCalcHourSpec);
+                sqlSession.commit();
+            }
+        }
         dbProcess(endTime, calcHours, stopList, alarmsList, panList);
         stopService.process(ldt, list);
         alarmsService.process(ldt, list);
         Date d = new Date();
-//        Date s_time = Date.from(ldt.toLocalDate().atStartOfDay(ZoneOffset.of("+8")).toInstant());
-//        Date e_time=Date.
         log.info("总共消耗:{}ms", d.getTime() - s.getTime());
 
     }
@@ -210,7 +219,7 @@ public class TaskServiceImpl implements ITaskService {
      * @return 返回未获取成功的数据列表
      */
 
-    private List<TwinDevice> exec(List<TwinDevice> list, Date date, Long startTime, Long endTime, int period, List<Object[]> calcHourList, List<TwinRecordStop> stopList, List<Object[]> panList, List<TwinRecordAlarms> alarmsList) {
+    private List<TwinDevice> exec(List<TwinDevice> list, Date date, Long startTime, Long endTime, int period, List<Object[]> calcHourList, List<TwinRecordStop> stopList, List<Object[]> panList, List<TwinRecordAlarms> alarmsList, List<TwinCalcHourSpec> specList) {
         List<Future<Map<String, List<?>>>> futureList = new ArrayList<>();
         for (int i = 0; i < list.size(); i++) {
             TwinDevice twinDevice = list.get(i);
@@ -228,7 +237,8 @@ public class TaskServiceImpl implements ITaskService {
 
                     List<TwinRecordAlarms> alarms = (List<TwinRecordAlarms>) map.get("alarmRecord");
                     List<TwinPanHeadInfo> panHeadInfoList = (List<TwinPanHeadInfo>) map.get("panHead");
-
+                    List<TwinCalcHourSpec> specs = (List<TwinCalcHourSpec>) map.get("specList");
+                    specList.addAll(specs);
                     calcHours.forEach(calcHour -> calcHourList.add(calcHour.toArray()));
                     stopList.addAll(stops);
                     alarmsList.addAll(alarms);

+ 116 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TwinCalcHourSpecServiceImpl.java

@@ -0,0 +1,116 @@
+package com.ruoyi.biz.service.impl;
+
+import com.ruoyi.biz.domain.TwinCalcHourSpec;
+import com.ruoyi.biz.mapper.TwinCalcHourSpecMapper;
+import com.ruoyi.biz.service.ITwinCalcHourSpecService;
+import com.ruoyi.biz.tools.Tools;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.DateUtils;
+import javafx.util.Pair;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 按配方1小时统计数据Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2024-12-20
+ */
+@Service
+public class TwinCalcHourSpecServiceImpl implements ITwinCalcHourSpecService {
+    @Resource
+    private TwinCalcHourSpecMapper twinCalcHourSpecMapper;
+
+    /**
+     * 查询按配方1小时统计数据
+     *
+     * @param id 按配方1小时统计数据主键
+     * @return 按配方1小时统计数据
+     */
+    @Override
+    public TwinCalcHourSpec selectTwinCalcHourSpecById(Long id) {
+        return twinCalcHourSpecMapper.selectTwinCalcHourSpecById(id);
+    }
+
+    /**
+     * 查询按配方1小时统计数据列表
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 按配方1小时统计数据
+     */
+    @Override
+    public List<TwinCalcHourSpec> selectTwinCalcHourSpecList(TwinCalcHourSpec twinCalcHourSpec) {
+        return twinCalcHourSpecMapper.selectTwinCalcHourSpecList(twinCalcHourSpec);
+    }
+
+    /**
+     * 新增按配方1小时统计数据
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    @Override
+    public int insertTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec) {
+        return twinCalcHourSpecMapper.insertTwinCalcHourSpec(twinCalcHourSpec);
+    }
+
+    /**
+     * 修改按配方1小时统计数据
+     *
+     * @param twinCalcHourSpec 按配方1小时统计数据
+     * @return 结果
+     */
+    @Override
+    public int updateTwinCalcHourSpec(TwinCalcHourSpec twinCalcHourSpec) {
+        return twinCalcHourSpecMapper.updateTwinCalcHourSpec(twinCalcHourSpec);
+    }
+
+    /**
+     * 批量删除按配方1小时统计数据
+     *
+     * @param ids 需要删除的按配方1小时统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcHourSpecByIds(String ids) {
+        return twinCalcHourSpecMapper.deleteTwinCalcHourSpecByIds(Convert.toStrArray(ids));
+    }
+
+    /**
+     * 删除按配方1小时统计数据信息
+     *
+     * @param id 按配方1小时统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcHourSpecById(Long id) {
+        return twinCalcHourSpecMapper.deleteTwinCalcHourSpecById(id);
+    }
+
+    /**
+     * 根据日期获取统计数据
+     *
+     * @param date 日期
+     * @return 结果
+     */
+    @Override
+    public List<TwinCalcHourSpec> selectTwinCalcHourSpecListByDate(Date date) {
+        LocalDate localDate = DateUtils.toLocalDate(date);
+        //计算统计时间
+        Pair<Date, Date> pair = Tools.calcDay(localDate);
+        Date sTime = pair.getKey();
+        Date eTime = pair.getValue();
+        TwinCalcHourSpec hour = new TwinCalcHourSpec();
+        Map<String, Object> params = new HashMap<>(16);
+        params.put("sTime", sTime);
+        params.put("eTime", eTime);
+        hour.setParams(params);
+        return selectTwinCalcHourSpecList(hour);
+    }
+}

+ 38 - 29
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/TwinEmpCalcServiceImpl.java

@@ -102,7 +102,7 @@ public class TwinEmpCalcServiceImpl implements ITwinEmpCalcService {
     }
 
     @Resource
-    private ITwinDeviceSpecService specService;
+    private ITwinCalcHourSpecService hourSpecService;
 
     /**
      * 按日统计
@@ -112,7 +112,14 @@ public class TwinEmpCalcServiceImpl implements ITwinEmpCalcService {
      */
     @Override
     public int calc(Date date) {
+        //先删除
         twinEmpCalcMapper.deleteTwinEmpCalcByDate(date);
+
+        //获取统计数据
+        List<TwinCalcHourSpec> specHourList = hourSpecService.selectTwinCalcHourSpecListByDate(date);
+        specHourList.forEach(obj -> obj.setTeam());
+        // 按照deviceId、density、mick、team,并统计每组的length总和
+        Map<String, List<TwinCalcHourSpec>> specHourMap = specHourList.stream().collect(Collectors.groupingBy(o -> o.getDeviceId() + "-" + o.getTeam(), LinkedHashMap::new, Collectors.toList()));
         List<TwinCalcDay> twinCalcDays = twinCalcDayService.selectTwinCalcDayListByTime(date, date);
         Map<Long, TwinCalcDay> calcMap = twinCalcDays.stream().collect(Collectors.toMap(TwinCalcDay::getDeviceId, o -> o));
         TwinEmp emp = empService.selectTwinEmpByDate(date);
@@ -120,13 +127,10 @@ public class TwinEmpCalcServiceImpl implements ITwinEmpCalcService {
         List<TwinEmpConfig> configs = empConfigService.selectTwinEmpConfigList(new TwinEmpConfig());
         Map<BigDecimal, BigDecimal> configMap = configs.stream().collect(Collectors.toMap(o -> o.getDensity().setScale(2, RoundingMode.HALF_UP), TwinEmpConfig::getPrice));
 
-        List<TwinDeviceSpec> specs = specService.selectTwinDeviceSpecList(new TwinDeviceSpec());
-        Map<Long, TwinDeviceSpec> specMap = specs.stream().collect(Collectors.toMap(TwinDeviceSpec::getDeviceId, o -> o));
-
         List<TwinEmpCalc> calcList = new ArrayList<>();
-        process(true, emp, calcMap, specMap, configMap, calcList);
-        process(false, emp, calcMap, specMap, configMap, calcList);
-        if (calcList != null && calcList.size() > 0) {
+        process(true, emp, calcMap, configMap, calcList, specHourMap);
+        process(false, emp, calcMap, configMap, calcList, specHourMap);
+        if (calcList.size() > 0) {
             try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
                 TwinEmpCalcMapper mapper = sqlSession.getMapper(TwinEmpCalcMapper.class);
                 calcList.forEach(mapper::insertTwinEmpCalc);
@@ -140,35 +144,40 @@ public class TwinEmpCalcServiceImpl implements ITwinEmpCalcService {
     /**
      * @param flag true为A班false为B班
      */
-    private void process(boolean flag, TwinEmp emp, Map<Long, TwinCalcDay> calcMap, Map<Long, TwinDeviceSpec> specMap, Map<BigDecimal, BigDecimal> configMap, List<TwinEmpCalc> calcList) {
+    private void process(boolean flag, TwinEmp emp, Map<Long, TwinCalcDay> calcMap, Map<BigDecimal, BigDecimal> configMap, List<TwinEmpCalc> calcList, Map<String, List<TwinCalcHourSpec>> specHourMap) {
         List<TwinEmpDetail> list = emp.getTwinEmpDetailListA();
+        String team = "A";
         if (!flag) {
+            team = "B";
             list = emp.getTwinEmpDetailListB();
         }
         for (TwinEmpDetail d : list) {
             Long[] devices = getDevices(d.getDevices());
             for (int i = 0; i < devices.length; i++) {
                 Long deviceId = devices[i];
-                TwinDeviceSpec spec = specMap.get(deviceId);
-                TwinCalcDay td = calcMap.get(deviceId);
-                TwinEmpCalc calc = new TwinEmpCalc();
-                calc.setDeviceId(deviceId);
-                calc.setEfficiency(td.getEfficiencyA());
-                calc.setEmpDate(td.getTime());
-                BigDecimal length = td.getLengthA();
-                if (!flag) {
-                    calc.setEfficiency(td.getEfficiencyB());
-                    length = td.getLengthB();
-                }
-                if (length.compareTo(BigDecimal.ZERO) == 0) {
-                    continue;
-                }
-                calc.setLength(length);
-                calc.setEmpTeam(d.getEmpTeam());
-                calc.setEmpName(d.getEmpName());
-                if (spec != null) {
-                    calc.setMick(spec.getMick());
-                    BigDecimal density = spec.getDensity().setScale(2, RoundingMode.HALF_UP);
+                List<TwinCalcHourSpec> specs = specHourMap.get(deviceId + "-" + team);
+                //按密度和米克重分组统计
+                Map<String, BigDecimal> resultMap = specs.stream().collect(Collectors.groupingBy(t -> t.getDensity() + "-" + t.getMick(), Collectors.reducing(BigDecimal.ZERO, TwinCalcHourSpec::getLength, BigDecimal::add)));
+                for (String ss : resultMap.keySet()) {
+                    String[] temp = ss.split("-");
+                    BigDecimal density = new BigDecimal(temp[0]).setScale(2, RoundingMode.HALF_UP);
+                    Integer mick = Integer.parseInt(temp[1]);
+                    TwinCalcDay td = calcMap.get(deviceId);
+                    TwinEmpCalc calc = new TwinEmpCalc();
+                    calc.setDeviceId(deviceId);
+                    calc.setEfficiency(td.getEfficiencyA());
+                    calc.setEmpDate(td.getTime());
+                    BigDecimal length = resultMap.get(ss);
+                    if (!flag) {
+                        calc.setEfficiency(td.getEfficiencyB());
+                    }
+                    if (length.compareTo(BigDecimal.ZERO) == 0) {
+                        continue;
+                    }
+                    calc.setLength(length);
+                    calc.setEmpTeam(d.getEmpTeam());
+                    calc.setEmpName(d.getEmpName());
+                    calc.setMick(mick);
                     calc.setDensity(density);
                     BigDecimal price = configMap.get(Tools.density(density));
                     calc.setPrice(price);
@@ -176,8 +185,8 @@ public class TwinEmpCalcServiceImpl implements ITwinEmpCalcService {
                         BigDecimal total = length.multiply(price);
                         calc.setTotalPrice(total);
                     }
+                    calcList.add(calc);
                 }
-                calcList.add(calc);
             }
         }
     }

+ 100 - 0
ruoyi-admin/src/main/resources/mapper/biz/TwinCalcHourSpecMapper.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.biz.mapper.TwinCalcHourSpecMapper">
+
+    <resultMap type="TwinCalcHourSpec" id="TwinCalcHourSpecResult">
+        <result property="id"    column="ID"    />
+        <result property="dataDate"    column="DATA_DATE"    />
+        <result property="hour"    column="HOUR"    />
+        <result property="deviceId"    column="DEVICE_ID"    />
+        <result property="length"    column="LENGTH"    />
+        <result property="spec"    column="SPEC"    />
+        <result property="mick"    column="MICK"    />
+        <result property="density"    column="DENSITY"    />
+        <result property="price"    column="PRICE"    />
+        <result property="remark"    column="REMARK"    />
+    </resultMap>
+
+    <sql id="selectTwinCalcHourSpecVo">
+        select ID, DATA_DATE, HOUR, DEVICE_ID, LENGTH, SPEC, MICK, DENSITY, PRICE, REMARK from twin_calc_hour_spec
+    </sql>
+
+    <select id="selectTwinCalcHourSpecList" parameterType="TwinCalcHourSpec" resultMap="TwinCalcHourSpecResult">
+        <include refid="selectTwinCalcHourSpecVo"/>
+        <where>
+            <if test="dataDate != null "> and DATA_DATE = #{dataDate}</if>
+            <if test="hour != null "> and HOUR = #{hour}</if>
+            <if test="deviceId != null "> and DEVICE_ID = #{deviceId}</if>
+            <if test="length != null "> and LENGTH = #{length}</if>
+            <if test="spec != null  and spec != ''"> and SPEC = #{spec}</if>
+            <if test="mick != null "> and MICK = #{mick}</if>
+            <if test="density != null "> and DENSITY = #{density}</if>
+            <if test="price != null "> and PRICE = #{price}</if>
+            <if test="remark != null  and remark != ''"> and REMARK = #{remark}</if>
+            <if test="params.sTime != null and params.eTime != null">
+                and DATE_ADD(data_date, INTERVAL `HOUR` HOUR) between #{params.sTime} and #{params.eTime}
+            </if>
+        </where>
+    </select>
+
+    <select id="selectTwinCalcHourSpecById" parameterType="Long" resultMap="TwinCalcHourSpecResult">
+        <include refid="selectTwinCalcHourSpecVo"/>
+        where ID = #{id}
+    </select>
+
+    <insert id="insertTwinCalcHourSpec" parameterType="TwinCalcHourSpec" useGeneratedKeys="true" keyProperty="id">
+        insert into twin_calc_hour_spec
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="dataDate != null">DATA_DATE,</if>
+            <if test="hour != null">HOUR,</if>
+            <if test="deviceId != null">DEVICE_ID,</if>
+            <if test="length != null">LENGTH,</if>
+            <if test="spec != null">SPEC,</if>
+            <if test="mick != null">MICK,</if>
+            <if test="density != null">DENSITY,</if>
+            <if test="price != null">PRICE,</if>
+            <if test="remark != null">REMARK,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="dataDate != null">#{dataDate},</if>
+            <if test="hour != null">#{hour},</if>
+            <if test="deviceId != null">#{deviceId},</if>
+            <if test="length != null">#{length},</if>
+            <if test="spec != null">#{spec},</if>
+            <if test="mick != null">#{mick},</if>
+            <if test="density != null">#{density},</if>
+            <if test="price != null">#{price},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTwinCalcHourSpec" parameterType="TwinCalcHourSpec">
+        update twin_calc_hour_spec
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="dataDate != null">DATA_DATE = #{dataDate},</if>
+            <if test="hour != null">HOUR = #{hour},</if>
+            <if test="deviceId != null">DEVICE_ID = #{deviceId},</if>
+            <if test="length != null">LENGTH = #{length},</if>
+            <if test="spec != null">SPEC = #{spec},</if>
+            <if test="mick != null">MICK = #{mick},</if>
+            <if test="density != null">DENSITY = #{density},</if>
+            <if test="price != null">PRICE = #{price},</if>
+            <if test="remark != null">REMARK = #{remark},</if>
+        </trim>
+        where ID = #{id}
+    </update>
+
+    <delete id="deleteTwinCalcHourSpecById" parameterType="Long">
+        delete from twin_calc_hour_spec where ID = #{id}
+    </delete>
+
+    <delete id="deleteTwinCalcHourSpecByIds" parameterType="String">
+        delete from twin_calc_hour_spec where ID in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 90 - 0
ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/add.html

@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('新增按配方1小时统计数据')" />
+    <th:block th:include="include :: datetimepicker-css" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-bizHourSpec-add">
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">日期:</label>
+                <div class="col-sm-8">
+                    <div class="input-group date">
+                        <input name="dataDate" class="form-control" placeholder="yyyy-MM-dd" type="text">
+                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">小时;0-23:</label>
+                <div class="col-sm-8">
+                    <input name="hour" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">设备ID:</label>
+                <div class="col-sm-8">
+                    <input name="deviceId" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">织造米数:</label>
+                <div class="col-sm-8">
+                    <input name="length" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">规格:</label>
+                <div class="col-sm-8">
+                    <input name="spec" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">米克重:</label>
+                <div class="col-sm-8">
+                    <input name="mick" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">密度:</label>
+                <div class="col-sm-8">
+                    <input name="density" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">单价:</label>
+                <div class="col-sm-8">
+                    <input name="price" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">备注:</label>
+                <div class="col-sm-8">
+                    <textarea name="remark" class="form-control"></textarea>
+                </div>
+            </div>
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: datetimepicker-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "biz/bizHourSpec"
+        $("#form-bizHourSpec-add").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/add", $('#form-bizHourSpec-add').serialize());
+            }
+        }
+
+        $("input[name='dataDate']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+    </script>
+</body>
+</html>

+ 146 - 0
ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/bizHourSpec.html

@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('按配方1小时统计数据列表')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
+                            <li>
+                                <label>日期:</label>
+                                <input type="text" class="time-input" placeholder="请选择日期" name="dataDate"/>
+                            </li>
+                            <li>
+                                <label>小时;0-23:</label>
+                                <input type="text" name="hour"/>
+                            </li>
+                            <li>
+                                <label>设备ID:</label>
+                                <input type="text" name="deviceId"/>
+                            </li>
+                            <li>
+                                <label>织造米数:</label>
+                                <input type="text" name="length"/>
+                            </li>
+                            <li>
+                                <label>规格:</label>
+                                <input type="text" name="spec"/>
+                            </li>
+                            <li>
+                                <label>米克重:</label>
+                                <input type="text" name="mick"/>
+                            </li>
+                            <li>
+                                <label>密度:</label>
+                                <input type="text" name="density"/>
+                            </li>
+                            <li>
+                                <label>单价:</label>
+                                <input type="text" name="price"/>
+                            </li>
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="biz:bizHourSpec:add">
+                    <i class="fa fa-plus"></i> 添加
+                </a>
+                <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="biz:bizHourSpec:edit">
+                    <i class="fa fa-edit"></i> 修改
+                </a>
+                <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="biz:bizHourSpec:remove">
+                    <i class="fa fa-remove"></i> 删除
+                </a>
+                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="biz:bizHourSpec:export">
+                    <i class="fa fa-download"></i> 导出
+                </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-table"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var editFlag = [[${@permission.hasPermi('biz:bizHourSpec:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('biz:bizHourSpec:remove')}]];
+        var prefix = ctx + "biz/bizHourSpec";
+
+        $(function() {
+            var options = {
+                url: prefix + "/list",
+                createUrl: prefix + "/add",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove",
+                exportUrl: prefix + "/export",
+                modalName: "按配方1小时统计数据",
+                columns: [{
+                    checkbox: true
+                },
+                {
+                    field: 'id',
+                    title: 'ID',
+                    visible: false
+                },
+                {
+                    field: 'dataDate',
+                    title: '日期'
+                },
+                {
+                    field: 'hour',
+                    title: '小时;0-23'
+                },
+                {
+                    field: 'deviceId',
+                    title: '设备ID'
+                },
+                {
+                    field: 'length',
+                    title: '织造米数'
+                },
+                {
+                    field: 'spec',
+                    title: '规格'
+                },
+                {
+                    field: 'mick',
+                    title: '米克重'
+                },
+                {
+                    field: 'density',
+                    title: '密度'
+                },
+                {
+                    field: 'price',
+                    title: '单价'
+                },
+                {
+                    field: 'remark',
+                    title: '备注'
+                },
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
+            };
+            $.table.init(options);
+        });
+    </script>
+</body>
+</html>

+ 91 - 0
ruoyi-admin/src/main/resources/templates/biz/bizHourSpec/edit.html

@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('修改按配方1小时统计数据')" />
+    <th:block th:include="include :: datetimepicker-css" />
+</head>
+<body class="white-bg">
+    <div class="wrapper wrapper-content animated fadeInRight ibox-content">
+        <form class="form-horizontal m" id="form-bizHourSpec-edit" th:object="${twinCalcHourSpec}">
+            <input name="id" th:field="*{id}" type="hidden">
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">日期:</label>
+                <div class="col-sm-8">
+                    <div class="input-group date">
+                        <input name="dataDate" th:value="${#dates.format(twinCalcHourSpec.dataDate, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
+                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">小时;0-23:</label>
+                <div class="col-sm-8">
+                    <input name="hour" th:field="*{hour}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">设备ID:</label>
+                <div class="col-sm-8">
+                    <input name="deviceId" th:field="*{deviceId}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">织造米数:</label>
+                <div class="col-sm-8">
+                    <input name="length" th:field="*{length}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">规格:</label>
+                <div class="col-sm-8">
+                    <input name="spec" th:field="*{spec}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">米克重:</label>
+                <div class="col-sm-8">
+                    <input name="mick" th:field="*{mick}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">密度:</label>
+                <div class="col-sm-8">
+                    <input name="density" th:field="*{density}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">单价:</label>
+                <div class="col-sm-8">
+                    <input name="price" th:field="*{price}" class="form-control" type="text">
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label">备注:</label>
+                <div class="col-sm-8">
+                    <textarea name="remark" class="form-control">[[*{remark}]]</textarea>
+                </div>
+            </div>
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: datetimepicker-js" />
+    <script th:inline="javascript">
+        var prefix = ctx + "biz/bizHourSpec";
+        $("#form-bizHourSpec-edit").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/edit", $('#form-bizHourSpec-edit').serialize());
+            }
+        }
+
+        $("input[name='dataDate']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+    </script>
+</body>
+</html>

+ 18 - 0
ruoyi-admin/src/main/resources/templates/biz/data/data.html

@@ -30,6 +30,16 @@
         <a class="btn btn-primary btn-rounded btn-sm" onclick="bl2()"><i class="fa fa-database"></i>&nbsp;补录</a>
     </label>
 </div>
+<div class="form-group">
+    <label class="col-sm-3 control-label">按天补录:</label>
+    <label class="col-sm-6">
+        <input id="ssd" class="time-input" placeholder="开始时间" type="text">&nbsp;
+        <input id="eed" class="time-input" placeholder="结束时间" type="text">&nbsp;
+    </label>
+    <label class="col-sm-2 control-label">
+        <a class="btn btn-primary btn-rounded btn-sm" onclick="bl3()"><i class="fa fa-database"></i>&nbsp;补录</a>
+    </label>
+</div>
 <th:block th:include="include :: footer"/>
 <th:block th:include="include :: datetimepicker-js"/>
 <script th:inline="javascript">
@@ -50,6 +60,14 @@
             }
         })
     }
+
+    function bl3() {
+        $.getJSON(prefix + "/bl3", {sd: $("#ssd").val(), ed: $("#eed").val()}, function (data) {
+            if (data.code == 0) {
+                $.modal.msgSuccess("操作成功!");
+            }
+        })
+    }
 </script>
 </body>
 </html>

+ 9 - 0
ruoyi-admin/src/main/resources/templates/biz/emp/emp.html

@@ -73,6 +73,7 @@
                     align: 'center',
                     formatter: function(value, row, index) {
                         var actions = [];
+                        actions.push('<a class="btn btn-info btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="calc(\'' + row.empDate + '\')"><i class="fa fa-amazon"></i>统计</a> ');
                         actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editFull(\'' + row.empId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                         actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.empId + '\')"><i class="fa fa-remove"></i>删除</a>');
                         return actions.join('');
@@ -81,6 +82,14 @@
             };
             $.table.init(options);
         });
+
+        function calc(empDate) {
+            $.getJSON(ctx + "biz/empCalc/calc", {date: empDate}, function (data) {
+                if (data.code == 0) {
+                    $.modal.msgSuccess("统计成功!");
+                }
+            })
+        }
     </script>
 </body>
 </html>