Browse Source

可视化大屏合格率、年/月/日各sku产量、班组工作量开发

zhangxin 1 year ago
parent
commit
e8d921528a
19 changed files with 1693 additions and 57 deletions
  1. 14 0
      pom.xml
  2. 7 13
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
  3. 32 21
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/wms/asn/WmsDocAsnHeaderController.java
  4. 1 1
      ruoyi-admin/src/main/resources/application.yml
  5. 9 0
      ruoyi-common/pom.xml
  6. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
  7. 10 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
  8. 43 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/Granularity.java
  9. 38 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/TimeHorizon.java
  10. 264 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DateTimeUtils.java
  11. 924 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/TimeUtils.java
  12. 18 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/params/SplitedTimeParam.java
  13. 21 4
      warewms-ams/src/main/java/com/ruoyi/ams/asn/domain/WmsDocAsnDetails.java
  14. 16 0
      warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/TotalInfoDTO.java
  15. 31 0
      warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/WmsDetailsReqDTO.java
  16. 16 0
      warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/WmsDetailsTotalDTO.java
  17. 5 4
      warewms-ams/src/main/java/com/ruoyi/ams/asn/mapper/WmsDocAsnDetailsMapper.java
  18. 34 5
      warewms-ams/src/main/java/com/ruoyi/ams/asn/service/IWmsDocAsnDetailsService.java
  19. 205 8
      warewms-ams/src/main/java/com/ruoyi/ams/asn/service/impl/WmsDocAsnDetailsServiceImpl.java

+ 14 - 0
pom.xml

@@ -35,6 +35,8 @@
         <velocity.version>2.3</velocity.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
         <jwt.version>0.9.1</jwt.version>
         <skipTests>true</skipTests>
         <skipTests>true</skipTests>
+        <guava.version>20.0</guava.version>
+        <joda.time.version>2.9.9</joda.time.version>
     </properties>
     </properties>
 
 
     <!-- 依赖声明 -->
     <!-- 依赖声明 -->
@@ -220,6 +222,18 @@
                 <version>${warewms.version}</version>
                 <version>${warewms.version}</version>
             </dependency>
             </dependency>
 
 
+            <!-- guava-->
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>joda-time</groupId>
+                <artifactId>joda-time</artifactId>
+                <version>${joda.time.version}</version>
+            </dependency>
         </dependencies>
         </dependencies>
     </dependencyManagement>
     </dependencyManagement>
 
 

+ 7 - 13
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java

@@ -1,18 +1,5 @@
 package com.ruoyi.web.controller.system;
 package com.ruoyi.web.controller.system;
 
 
-import java.util.List;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-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.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.controller.BaseController;
@@ -22,6 +9,13 @@ import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.system.domain.SysConfig;
 import com.ruoyi.system.domain.SysConfig;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 
 
 /**
 /**
  * 参数配置 信息操作处理
  * 参数配置 信息操作处理

+ 32 - 21
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/wms/asn/WmsDocAsnHeaderController.java

@@ -1,28 +1,29 @@
 package com.ruoyi.web.controller.warewms.wms.asn;
 package com.ruoyi.web.controller.warewms.wms.asn;
 
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.servlet.http.HttpServletResponse;
-
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
-import com.ruoyi.ams.asn.form.DelDocAsnDetailsForm;
+import com.ruoyi.ams.asn.domain.WmsDocAsnHeader;
+import com.ruoyi.ams.asn.dto.WmsDetailsReqDTO;
 import com.ruoyi.ams.asn.service.IWmsDocAsnDetailsService;
 import com.ruoyi.ams.asn.service.IWmsDocAsnDetailsService;
-import com.ruoyi.base.domain.BaseIdsequence;
+import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
 import com.ruoyi.base.service.IBaseIdsequenceService;
 import com.ruoyi.base.service.IBaseIdsequenceService;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.ams.asn.domain.WmsDocAsnHeader;
-import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
+import com.ruoyi.common.enums.Granularity;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.common.core.page.TableDataInfo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 
 /**
 /**
  * 入库单Controller
  * 入库单Controller
@@ -202,12 +203,22 @@ public class WmsDocAsnHeaderController extends BaseController {
         return toAjax(wmsDocAsnHeaderService.updateWmsDocAsnHeader(wmsDocAsnHeader));
         return toAjax(wmsDocAsnHeaderService.updateWmsDocAsnHeader(wmsDocAsnHeader));
     }
     }
 
 
-    @PostMapping(value = "/updateDocAsnDetails")
-    public AjaxResult updateDocAsnDetails(@RequestBody WmsDocAsnDetails wmsDocAsnDetails) {
-        LoginUser loginUser = this.getLoginUser();
-        wmsDocAsnDetails.setUpdateTime(new Date());
-        wmsDocAsnDetails.setUpdateBy(loginUser.getUsername());
-        return toAjax(wmsDocAsnDetailsService.updateWmsDocAsnDetails(wmsDocAsnDetails));
+
+    @GetMapping(value = "/getPassRate")
+    @ApiOperation("可视化大屏合格率")
+    public AjaxResult getPassRate(@RequestParam String field, @RequestParam String beginTime, @RequestParam String endTime, @RequestParam String status, Granularity granularity) {
+        return AjaxResult.success(wmsDocAsnDetailsService.getPassRate(field, beginTime, endTime, status, granularity));
+    }
+
+    @GetMapping(value = "/queryAllGranularityTotal")
+    @ApiOperation("可视化大屏根据字段名获取时间段内年/月/日总量")
+    public AjaxResult queryAllGranularityTotal(@RequestParam String field, @RequestParam String beginTime, @RequestParam String endTime) {
+        return AjaxResult.success(wmsDocAsnDetailsService.queryAllGranularityTotal(field, beginTime, endTime));
+    }
+    @PostMapping(value = "/queryFieldTotalList")
+    @ApiOperation("可视化大屏根据字段field获取时间段根据时间粒度切割后产量 data不传即获取总量")
+    public AjaxResult queryFieldTotalList(@RequestBody WmsDetailsReqDTO wmsDetailsReqDTO) {
+        return AjaxResult.success(wmsDocAsnDetailsService.queryFieldTotalList(wmsDetailsReqDTO));
     }
     }
 
 
 }
 }

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -37,7 +37,7 @@ spring:
     # 国际化资源文件路径
     # 国际化资源文件路径
     basename: i18n/messages
     basename: i18n/messages
   profiles:
   profiles:
-    active: prod
+    active: dev
   # 文件上传
   # 文件上传
   servlet:
   servlet:
     multipart:
     multipart:

+ 9 - 0
ruoyi-common/pom.xml

@@ -161,6 +161,15 @@
             <version>4.5.2</version>
             <version>4.5.2</version>
         </dependency>
         </dependency>
 
 
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
     </dependencies>
     </dependencies>
 
 
 </project>
 </project>

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -214,4 +214,9 @@ public class Constants
      * 是
      * 是
      */
      */
     public static final String YES = "Y";
     public static final String YES = "Y";
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String WMS_LARGE_SCREEN_DATA = "wms.largeScreen.data";
 }
 }

+ 10 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java

@@ -1,10 +1,12 @@
 package com.ruoyi.common.core.domain;
 package com.ruoyi.common.core.domain;
 
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
 import java.io.Serializable;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
-import com.fasterxml.jackson.annotation.JsonFormat;
 
 
 /**
 /**
  * Entity基类
  * Entity基类
@@ -16,26 +18,33 @@ public class BaseEntity implements Serializable
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
     /** 搜索值 */
     /** 搜索值 */
+    @TableField(exist = false)
     private String searchValue;
     private String searchValue;
 
 
     /** 创建者 */
     /** 创建者 */
+    @TableField(exist = false)
     private String createBy;
     private String createBy;
 
 
     /** 创建时间 */
     /** 创建时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(exist = false)
     private Date createTime;
     private Date createTime;
 
 
     /** 更新者 */
     /** 更新者 */
+    @TableField(exist = false)
     private String updateBy;
     private String updateBy;
 
 
     /** 更新时间 */
     /** 更新时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(exist = false)
     private Date updateTime;
     private Date updateTime;
 
 
     /** 备注 */
     /** 备注 */
+    @TableField(exist = false)
     private String remark;
     private String remark;
 
 
     /** 请求参数 */
     /** 请求参数 */
+    @TableField(exist = false)
     private Map<String, Object> params;
     private Map<String, Object> params;
 
 
     public String getSearchValue()
     public String getSearchValue()

+ 43 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/Granularity.java

@@ -0,0 +1,43 @@
+package com.ruoyi.common.enums;
+
+import org.apache.commons.compress.utils.Lists;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public enum Granularity {
+    //以小时计
+    HOUR("hh"),
+
+    //以天计
+    DAY("dd"),
+
+    //以月计
+    MONTH("mm"),
+
+    //以年计
+    YEAR("yy");
+
+    private String suffix;
+
+    Granularity(String suffix) {
+        this.suffix = suffix;
+    }
+
+    public String getSuffix() {
+        return suffix;
+    }
+
+
+    public static List<Map<String, Object>> mapList() {
+        List<Map<String, Object>> list = Lists.newArrayList();
+        for (Granularity granularity : Granularity.values()) {
+            Map<String, Object> map = new HashMap<>();
+            map.put("code", granularity.getSuffix());
+            map.put("granularity", granularity);
+            list.add(map);
+        }
+        return list;
+    }
+}

+ 38 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/TimeHorizon.java

@@ -0,0 +1,38 @@
+package com.ruoyi.common.enums;
+
+public enum TimeHorizon {
+    /**
+     * 当天
+     */
+    CURRENT_DAY("1", "当天"),
+    /**
+     * 24小时
+     */
+    LAST_HOURS("2", "24小时"),
+    /**
+     * 最近7天
+     */
+    LAST_DAYS("3", "最近7天"),
+
+    /**
+     * 最近30天
+     */
+    LAST_MONTHS("4", "最近30天");
+
+    private String code;
+
+    private String desc;
+
+    TimeHorizon(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 264 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateTimeUtils.java

@@ -0,0 +1,264 @@
+package com.ruoyi.common.utils;
+
+import cn.hutool.core.lang.Assert;
+
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjuster;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author zhenghh. 2022-05-07
+ **/
+public class DateTimeUtils {
+
+    /**
+     * UTC +8
+     */
+    public final static ZoneId ZONE_ID = ZoneId.of("+8");
+    public final static ZoneOffset ZONE_OFFSET = ZoneOffset.ofHours(8);
+
+    /**
+     * 时间格式(yyyy-MM-dd)
+     */
+    public final static DateTimeFormatter DATE_PATTERN = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    /**
+     * 时间格式(yyyy-MM-dd HH:mm:ss)
+     */
+    private static final DateTimeFormatter DATE_TIME_PATTERN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+    /**
+     * 时间戳转分区日期时间
+     *
+     * @param localDateTime 时间
+     * @return 时间戳
+     */
+    public static long parse(LocalDateTime localDateTime) {
+        Assert.notNull(localDateTime, "时间不能为空");
+        return localDateTime.toInstant(ZONE_OFFSET).toEpochMilli();
+    }
+
+    /**
+     * 时间戳转分区日期时间
+     *
+     * @param timestamp 时间戳
+     * @return ZonedDateTime
+     */
+    public static ZonedDateTime parse(Long timestamp) {
+        Assert.notNull(timestamp, "时间戳不能为空");
+        return Instant.ofEpochMilli(timestamp).atZone(ZONE_ID);
+    }
+
+    /**
+     * 毫秒时间戳转时间
+     *
+     * @param timestamp 毫秒时间戳
+     * @return LocalDateTime
+     */
+    public static LocalDateTime parseDateTime(Long timestamp) {
+        return parse(timestamp).toLocalDateTime();
+    }
+
+
+    /**
+     * 时间字符串转分区日期时间
+     *
+     * @param date 时间 2021-10-10 10:10:10
+     * @return ZonedDateTime
+     */
+    public static LocalDateTime parseDateTime(String date) {
+        Assert.notNull(date, "时间不能为空");
+        return LocalDateTime.parse(date, DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 毫秒时间戳转时间
+     *
+     * @param timestamp 毫秒时间戳
+     * @return LocalDate
+     */
+    public static LocalDate parseDate(Long timestamp) {
+        return parse(timestamp).toLocalDate();
+    }
+
+    /**
+     * 时间格式化
+     *
+     * @param currentTime 当前时间戳
+     * @param localTime   时间
+     * @return LocalDateTime
+     */
+    public static LocalDateTime getDayDateTime(Long currentTime, LocalTime localTime) {
+        return LocalDateTime.of(parseDate(currentTime), localTime);
+    }
+
+    /**
+     * 时间格式化
+     *
+     * @param currentTime 当前时间戳
+     * @param localTime   时间
+     * @return LocalDateTime
+     */
+    public static long getDayTimestamp(Long currentTime, LocalTime localTime) {
+        return getDayDateTime(currentTime, localTime).toInstant(ZONE_OFFSET).toEpochMilli();
+    }
+
+    /**
+     * 时间格式化
+     *
+     * @param currentTime 当前时间戳
+     * @param localTime   时间
+     * @return LocalDateTime
+     */
+    public static LocalDateTime getDayDateTime(Long currentTime, LocalTime localTime, TemporalAdjuster adjuster) {
+        return getDayDateTime(currentTime, localTime).with(adjuster);
+    }
+
+    /**
+     * 时间格式化
+     *
+     * @param currentTime 当前时间戳
+     * @param localTime   时间
+     * @return LocalDateTime
+     */
+    public static long getDayTimestamp(Long currentTime, LocalTime localTime, TemporalAdjuster adjuster) {
+        return getDayDateTime(currentTime, localTime, adjuster).toInstant(ZONE_OFFSET).toEpochMilli();
+    }
+
+    /**
+     * 获得当前时间的所在天的第一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getDayBeginTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MIN);
+    }
+
+    /**
+     * 获得当前时间的所在天的最后一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getDayEndTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MAX);
+    }
+
+    /**
+     * 获得当前时间的所在月的第一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getMonthBeginTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MIN, TemporalAdjusters.firstDayOfMonth());
+    }
+
+    /**
+     * 获得当前时间的所在月的最后一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getMonthEndTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MAX, TemporalAdjusters.lastDayOfMonth());
+    }
+
+    /**
+     * 获得当前时间的所在年的第一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getYearBeginTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MIN, TemporalAdjusters.firstDayOfYear());
+    }
+
+    /**
+     * 获得当前时间的所在年的最后一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getYearEndTimestamp(Long currentTime) {
+        return getDayTimestamp(currentTime, LocalTime.MAX, TemporalAdjusters.lastDayOfYear());
+    }
+
+    /**
+     * 获得当前时间的所在周的第一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getWeekBeginTimestamp(Long currentTime) {
+        LocalDate localDate = parseDate(currentTime);
+        return parse(localDate.minusDays(localDate.getDayOfWeek().getValue() - 1).atStartOfDay().with(LocalTime.MIN));
+    }
+
+    /**
+     * 获得当前时间的所在周的最后一秒
+     *
+     * @param currentTime 当前时间戳
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static long getWeekEndTimestamp(Long currentTime) {
+        LocalDate localDate = parseDate(currentTime);
+        return parse(localDate.plusDays(7 - localDate.getDayOfWeek().getValue()).atStartOfDay().with(LocalTime.MAX));
+    }
+
+    /**
+     * 获取区间计算的开始时间
+     *
+     * @param dateTime       时间
+     * @param interval 时间间隔分钟(例:15,30,60)
+     * @return 第一笔时间
+     */
+    public static long getStartTime(LocalDateTime dateTime, int interval) {
+        int minute = dateTime.getMinute();
+        int j = minute / interval;
+        int startMinute = j * interval;
+        return parse(dateTime.withMinute(startMinute).withSecond(0).withNano(0));
+    }
+
+    /**
+     * 获取区间时间内的采集时间
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param interval  时间间隔分钟(例:15,30,60)
+     * @return 第一笔时间
+     */
+    public static List<Long> getIntervalTimeList(long startTime, long endTime, int interval) {
+        List<Long> list = new ArrayList<>();
+        long start = getStartTime(parseDateTime(startTime), interval);
+        int millisecond = interval * 60000;
+        while (start <= endTime) {
+            list.add(start);
+            start += millisecond;
+        }
+        return list;
+    }
+
+    /**
+     * 获取区间时间内的采集时间
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param interval  时间间隔分钟(例:15,30,60)
+     * @return 第一笔时间
+     */
+    public static List<Long> getIntervalTimeList(LocalDateTime startTime, LocalDateTime endTime, int interval) {
+        List<Long> list = new ArrayList<>();
+        long start = getStartTime(startTime, interval), end = parse(endTime);
+        int millisecond = interval * 60000;
+        while (start <= end) {
+            list.add(start);
+            start += millisecond;
+        }
+        return list;
+    }
+}

+ 924 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/TimeUtils.java

@@ -0,0 +1,924 @@
+package com.ruoyi.common.utils;
+
+import cn.hutool.core.comparator.CompareUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.google.common.collect.Lists;
+import com.ruoyi.common.enums.Granularity;
+import com.ruoyi.common.enums.TimeHorizon;
+import com.ruoyi.common.utils.params.SplitedTimeParam;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class TimeUtils {
+
+    /**
+     * 时间格式(yyyyMMdd)
+     */
+    public final static String YEARMONTHDAY_PATTERN = "yyyyMMdd";
+    /**
+     * 时间格式(yyyy)
+     */
+    public final static String YEAR_PATTERN = "yyyy";
+    /**
+     * 时间格式(yyyyMM)
+     */
+    public final static String MONTHS_PATTERN = "yyyyMM";
+    /**
+     * 时间格式(yyyy-MM)
+     */
+    public final static String MONTH_PATTERN = "yyyy-MM";
+    /**
+     * 时间格式(yyyy-MM-dd)
+     */
+    public final static String DATE_PATTERN = "yyyy-MM-dd";
+    /**
+     * 时间格式(yyyy-MM-dd HH)
+     */
+    public static final String DATE_HOUR_PATTERN = "yyyy-MM-dd HH";
+    /**
+     * 时间格式(yyyy-MM-dd HH:mm:ss)
+     */
+    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    /**
+     * 时间格式(yyyy-MM-dd HH:mm:ss)
+     */
+    public final static String DATE_TIME_PATTERN_MSG = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+
+
+    /**
+     * 日期解析
+     *
+     * @param date    日期
+     * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
+     * @return 返回Date
+     */
+    @SneakyThrows
+    public static Date parse(String date, String pattern) {
+        return new SimpleDateFormat(pattern).parse(date);
+    }
+
+
+    /**
+     * 日期格式化 日期格式为:yyyy-MM-dd
+     *
+     * @param date    日期
+     * @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
+     * @return 返回yyyy-MM-dd格式日期
+     */
+    public static String format(Date date, String pattern) {
+        if (ObjectUtil.isNull(date)) {
+            return null;
+        }
+        SimpleDateFormat df = new SimpleDateFormat(pattern);
+        return df.format(date);
+    }
+
+
+    /**
+     * 获取起始时间之间包含的小时,返回一个小时的开始时间,以yyyy-MM-dd HH:mm:ss格式返回
+     *
+     * @param startTm
+     * @param endTm
+     * @return ["2021-10-01 01:00:00","2021-10-01 02:00:00","2021-10-01 03:00:00"]
+     */
+    public static List<String> getHourListBetween(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        //重置成了开始时间的月初时间
+        Date resetDate = parse(format(parse(startTm, DATE_HOUR_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        resetDate = beginDate.compareTo(resetDate) > 0 ? org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1) : resetDate;
+
+        List<String> hourList = Lists.newArrayList();
+        while (resetDate.compareTo(endDate) <= 0) {
+            hourList.add(format(resetDate, DATE_TIME_PATTERN));
+            resetDate = org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1);
+        }
+
+        return hourList;
+    }
+
+
+    /**
+     * 获取起始时间之间包含的日期,返回一天的开始时间,以yyyy-MM-dd HH:mm:ss格式返回
+     *
+     * @param startTm
+     * @param endTm
+     * @return ["2021-10-01 00:00:00","2021-10-02 00:00:00","2021-10-03 00:00:00"]
+     */
+    @SneakyThrows
+    public static List<String> getDateListBetween(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        //重置成了开始时间的每天开始时间
+        Date resetDate = parse(format(parse(startTm, DATE_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        resetDate = beginDate.compareTo(resetDate) > 0 ? org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1) : resetDate;
+
+        List<String> dateList = Lists.newArrayList();
+        while (resetDate.compareTo(endDate) <= 0) {
+            dateList.add(format(resetDate, DATE_TIME_PATTERN));
+            resetDate = org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1);
+        }
+
+        return dateList;
+    }
+
+
+    /**
+     * 获取起始时间之间包含的月份,返回月初的时间,以yyyy-MM-dd HH:mm:ss格式返回
+     *
+     * @param startTm
+     * @param endTm
+     * @return ["2021-10-01 00:00:00","2021-11-01 00:00:00","2021-12-01 00:00:00"]
+     */
+    @SneakyThrows
+    public static List<String> getMonthListBetween(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        //重置成了开始时间的月初时间
+        Date resetDate = parse(format(parse(startTm, MONTH_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        resetDate = beginDate.compareTo(resetDate) > 0 ? org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1) : resetDate;
+
+        List<String> monthList = Lists.newArrayList();
+        while (resetDate.compareTo(endDate) <= 0) {
+            monthList.add(format(resetDate, DATE_TIME_PATTERN));
+            resetDate = org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1);
+        }
+
+        return monthList;
+    }
+
+
+    /**
+     * 获取起始时间之间包含的年份,返回年初的时间,以yyyy-MM-dd HH:mm:ss格式返回
+     *
+     * @param startTm 2019-09-28 16:34:00
+     * @param endTm   2021-12-19 10:36:11
+     * @return ["2020-01-01 00:00:00","2021-01-01 00:00:00"]
+     */
+    @SneakyThrows
+    public static List<String> getYearListBetween(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        //重置成了开始时间的月初时间
+        Date resetDate = parse(format(parse(startTm, YEAR_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        resetDate = beginDate.compareTo(resetDate) > 0 ? org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1) : resetDate;
+
+        List<String> yearList = Lists.newArrayList();
+        while (resetDate.compareTo(endDate) <= 0) {
+            yearList.add(format(resetDate, DATE_TIME_PATTERN));
+            resetDate = org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1);
+        }
+
+        return yearList;
+    }
+
+    /**
+     * 切割时间,返回时间列表
+     *
+     * @param startTime   开始时间
+     * @param endTime     结束时间
+     * @param granularity 切割时间的粒度 小时-Granularity.HOUR 天-Granularity.DAY 月-Granularity.MONTH
+     * @return
+     */
+    public static List<SplitedTimeParam> getSplitedTimeList(Long startTime, Long endTime, Granularity granularity) {
+        Map<String, SplitedTimeParam> splitedTimeGroupByTime = getSplitedTimeGroupByTime(timestampToDate(startTime), timestampToDate(endTime), granularity);
+        return splitedTimeGroupByTime.entrySet().stream().map(item -> item.getValue()).collect(Collectors.toList());
+    }
+
+    /**
+     * 切割时间
+     *
+     * @param startTime   开始时间
+     * @param endTime     结束时间
+     * @param granularity 切割时间的粒度 小时-Granularity.HOUR 天-Granularity.DAY 月-Granularity.MONTH
+     * @return
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeGroupByTime(Long startTime, Long endTime, Granularity granularity) {
+        return getSplitedTimeGroupByTime(timestampToDate(startTime), timestampToDate(endTime), granularity);
+    }
+
+    /**
+     * 切割时间
+     *
+     * @param startTm     开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm       结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @param granularity 切割时间的粒度 小时-Granularity.HOUR 天-Granularity.DAY 月-Granularity.MONTH
+     * @return
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeGroupByTime(String startTm, String endTm, Granularity granularity) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        return getSplitedTimeGroupByTime(beginDate, endDate, granularity);
+    }
+
+    /**
+     * 切割时间  20211109-仅支持小时日月的切割
+     *
+     * @param beginDate   开始时间
+     * @param endDate     结束时间
+     * @param granularity 切割时间的粒度 小时-Granularity.HOUR 天-Granularity.DAY 月-Granularity.MONTH
+     * @return
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeGroupByTime(Date beginDate, Date endDate, Granularity granularity) {
+        switch (granularity) {
+            case HOUR:
+                return getSplitedTimeMapByHour(beginDate, endDate);
+            case DAY:
+                return getSplitedTimeMapByDay(beginDate, endDate);
+            case MONTH:
+                return getSplitedTimeMapByMonth(beginDate, endDate);
+            case YEAR:
+                return getSplitedTimeMapByYear(beginDate, endDate);
+            default:
+                return getSplitedTimeMapByDay(beginDate, endDate);
+        }
+    }
+
+    /**
+     * 按小时切割时间,返回一个列表
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return [{"beginTime":"2021-11-03 22:28:59","endTime":"2021-11-03 22:59:59"},{"beginTime":"2021-11-03 23:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByHour(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByHour(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+    /**
+     * 按小时切割时间,返回一个列表
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return [{"beginTime":"2021-11-03 22:28:59","endTime":"2021-11-03 22:59:59"},{"beginTime":"2021-11-03 23:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByHour(Date beginDate, Date endDate) {
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByHour(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+    /**
+     * 按小时切割时间,返回一个映射
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return {"2021-11-03 22:00:00":{"beginTime":"2021-11-03 22:28:59","endTime":"2021-11-03 22:59:59"},"2021-11-03 23:00:00":{"beginTime":"2021-11-03 23:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByHour(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        return getSplitedTimeMapByHour(beginDate, endDate);
+    }
+
+    /**
+     * 按小时切割时间,返回一个映射
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return {"2021-11-03 22:00:00":{"beginTime":"2021-11-03 22:28:59","endTime":"2021-11-03 22:59:59"},"2021-11-03 23:00:00":{"beginTime":"2021-11-03 23:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByHour(Date beginDate, Date endDate) {
+        String startTm = format(beginDate, DATE_TIME_PATTERN);
+        String endTm = format(endDate, DATE_TIME_PATTERN);
+
+        Map<String, SplitedTimeParam> splitedTimeMap = new LinkedHashMap<>();
+        if (CompareUtil.compare(endDate, beginDate) < 0) {
+            log.warn("endDate is earlier than beginDate, beginDate:{}, endDate:{}", startTm, endTm);
+            return splitedTimeMap;
+        }
+        Date resetDate = parse(format(parse(startTm, DATE_HOUR_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        while (CompareUtil.compare(resetDate, endDate) <= 0) {
+            SplitedTimeParam splitedTimeParam = new SplitedTimeParam();
+            if (CompareUtil.compare(resetDate, beginDate) <= 0) {
+                splitedTimeParam.setBeginTime(startTm);
+            } else if (CompareUtil.compare(resetDate, beginDate) > 0) {
+                splitedTimeParam.setBeginTime(format(resetDate, DATE_TIME_PATTERN));
+            }
+            if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1), endDate) > 0) {
+                splitedTimeParam.setEndTime(endTm);
+            } else if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1), endDate) <= 0) {
+                Date timePeriodEndDate = org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1), -1);
+                splitedTimeParam.setEndTime(format(timePeriodEndDate, DATE_TIME_PATTERN));
+            }
+            splitedTimeMap.put(format(resetDate, DATE_TIME_PATTERN), splitedTimeParam);
+            resetDate = org.apache.commons.lang3.time.DateUtils.addHours(resetDate, 1);
+        }
+        return splitedTimeMap;
+    }
+
+    /**
+     * 按天切割时间,返回一个列表
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return [{"beginTime":"2021-11-02 22:28:59","endTime":"2021-11-02 23:59:59"},{"beginTime":"2021-11-03 00:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByDay(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByDay(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+
+    /**
+     * 按天切割时间,返回一个列表
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return [{"beginTime":"2021-11-02 22:28:59","endTime":"2021-11-02 23:59:59"},{"beginTime":"2021-11-03 00:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByDay(Date beginDate, Date endDate) {
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByDay(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+
+    /**
+     * 按天分割时间,返回一个映射
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return {"2021-11-02 00:00:00":{"beginTime":"2021-11-02 22:28:59","endTime":"2021-11-02 23:59:59"},"2021-11-03 00:00:00":{"beginTime":"2021-11-03 00:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByDay(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        return getSplitedTimeMapByDay(beginDate, endDate);
+    }
+
+
+    /**
+     * 按天分割时间,返回一个映射
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return {"2021-11-02 00:00:00":{"beginTime":"2021-11-02 22:28:59","endTime":"2021-11-02 23:59:59"},"2021-11-03 00:00:00":{"beginTime":"2021-11-03 00:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByDay(Date beginDate, Date endDate) {
+        String startTm = format(beginDate, DATE_TIME_PATTERN);
+        String endTm = format(endDate, DATE_TIME_PATTERN);
+
+        Map<String, SplitedTimeParam> splitedTimeMap = new LinkedHashMap<>();
+        if (CompareUtil.compare(endDate, beginDate) < 0) {
+            log.warn("endDate is earlier than beginDate, beginDate:{}, endDate:{}", startTm, endTm);
+            return splitedTimeMap;
+        }
+        Date resetDate = parse(format(parse(startTm, DATE_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        while (CompareUtil.compare(resetDate, endDate) <= 0) {
+            SplitedTimeParam splitedTimeParam = new SplitedTimeParam();
+            if (CompareUtil.compare(resetDate, beginDate) <= 0) {
+                splitedTimeParam.setBeginTime(startTm);
+            } else if (CompareUtil.compare(resetDate, beginDate) > 0) {
+                splitedTimeParam.setBeginTime(format(resetDate, DATE_TIME_PATTERN));
+            }
+
+            if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1), endDate) > 0) {
+                splitedTimeParam.setEndTime(endTm);
+            } else if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1), endDate) <= 0) {
+                Date timePeriodEndDate = org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1), -1);
+                splitedTimeParam.setEndTime(format(timePeriodEndDate, DATE_TIME_PATTERN));
+            }
+            splitedTimeMap.put(format(resetDate, DATE_TIME_PATTERN), splitedTimeParam);
+            resetDate = org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1);
+        }
+        return splitedTimeMap;
+    }
+
+
+    /**
+     * 按月切割时间,返回一个列表
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return [{"beginTime":"2021-10-02 22:28:59","endTime":"2021-10-31 23:59:59"},{"beginTime":"2021-11-01 00:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByMonth(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByMonth(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+
+    /**
+     * 按月切割时间,返回一个列表
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return [{"beginTime":"2021-10-02 22:28:59","endTime":"2021-10-31 23:59:59"},{"beginTime":"2021-11-01 00:00:00","endTime":"2021-11-03 23:56:50"}]
+     */
+    public static List<SplitedTimeParam> getSplitedTimeListByMonth(Date beginDate, Date endDate) {
+        Map<String, SplitedTimeParam> splitedTimeParamMap = getSplitedTimeMapByMonth(beginDate, endDate);
+        return Lists.newArrayList(splitedTimeParamMap.values());
+    }
+
+
+    /**
+     * 按月分割时间,返回一个映射
+     *
+     * @param startTm 开始时间 "yyyy-MM-dd HH:mm:ss"
+     * @param endTm   结束时间 "yyyy-MM-dd HH:mm:ss"
+     * @return {"2021-10-01 00:00:00":{"beginTime":"2021-10-02 22:28:59","endTime":"2021-10-31 23:59:59"},"2021-11-01 00:00:00":{"beginTime":"2021-11-01 00:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByMonth(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        return getSplitedTimeMapByMonth(beginDate, endDate);
+    }
+
+
+    /**
+     * 按月分割时间,返回一个映射
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return {"2021-10-01 00:00:00":{"beginTime":"2021-10-02 22:28:59","endTime":"2021-10-31 23:59:59"},"2021-11-01 00:00:00":{"beginTime":"2021-11-01 00:00:00","endTime":"2021-11-03 23:56:50"}}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByMonth(Date beginDate, Date endDate) {
+        String startTm = format(beginDate, DATE_TIME_PATTERN);
+        String endTm = format(endDate, DATE_TIME_PATTERN);
+
+        Map<String, SplitedTimeParam> splitedTimeMap = new LinkedHashMap<>();
+        if (CompareUtil.compare(endDate, beginDate) < 0) {
+            log.warn("endDate is earlier than beginDate, beginDate:{}, endDate:{}", startTm, endTm);
+            return splitedTimeMap;
+        }
+        Date resetDate = parse(format(parse(startTm, MONTH_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        while (CompareUtil.compare(resetDate, endDate) <= 0) {
+            SplitedTimeParam splitedTimeParam = new SplitedTimeParam();
+            if (CompareUtil.compare(resetDate, beginDate) <= 0) {
+                splitedTimeParam.setBeginTime(startTm);
+            } else if (CompareUtil.compare(resetDate, beginDate) > 0) {
+                splitedTimeParam.setBeginTime(format(resetDate, DATE_TIME_PATTERN));
+            }
+            if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1), endDate) > 0) {
+                splitedTimeParam.setEndTime(endTm);
+            } else if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1), endDate) <= 0) {
+                Date timePeriodEndDate = org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1), -1);
+                splitedTimeParam.setEndTime(format(timePeriodEndDate, DATE_TIME_PATTERN));
+            }
+            splitedTimeMap.put(format(resetDate, DATE_TIME_PATTERN), splitedTimeParam);
+            resetDate = org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1);
+        }
+        return splitedTimeMap;
+    }
+
+    /**
+     * 按年分割时间,返回一个映射
+     *
+     * @param startTm 开始时间
+     * @param endTm   结束时间
+     * @return {2022-01-01 00:00:00=SplitedTimeParam(beginTime=2022-04-03 00:00:00, endTime=2022-12-31 23:59:59), 2023-01-01 00:00:00=SplitedTimeParam(beginTime=2023-01-01 00:00:00, endTime=2023-04-03 00:00:00)}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByYear(String startTm, String endTm) {
+        Date beginDate = parse(startTm, DATE_TIME_PATTERN);
+        Date endDate = parse(endTm, DATE_TIME_PATTERN);
+        return getSplitedTimeMapByYear(beginDate, endDate);
+    }
+
+    /**
+     * 按年分割时间,返回一个映射
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return {2022-01-01 00:00:00=SplitedTimeParam(beginTime=2022-04-03 00:00:00, endTime=2022-12-31 23:59:59), 2023-01-01 00:00:00=SplitedTimeParam(beginTime=2023-01-01 00:00:00, endTime=2023-04-03 00:00:00)}
+     */
+    public static Map<String, SplitedTimeParam> getSplitedTimeMapByYear(Date beginDate, Date endDate) {
+        String startTm = format(beginDate, DATE_TIME_PATTERN);
+        String endTm = format(endDate, DATE_TIME_PATTERN);
+
+        Map<String, SplitedTimeParam> splitedTimeMap = new LinkedHashMap<>();
+        if (CompareUtil.compare(endDate, beginDate) < 0) {
+            log.warn("endDate is earlier than beginDate, beginDate:{}, endDate:{}", startTm, endTm);
+            return splitedTimeMap;
+        }
+        Date resetDate = parse(format(parse(startTm, YEAR_PATTERN), DATE_TIME_PATTERN), DATE_TIME_PATTERN);
+        while (CompareUtil.compare(resetDate, endDate) <= 0) {
+            SplitedTimeParam splitedTimeParam = new SplitedTimeParam();
+            if (CompareUtil.compare(resetDate, beginDate) <= 0) {
+                splitedTimeParam.setBeginTime(startTm);
+            } else if (CompareUtil.compare(resetDate, beginDate) > 0) {
+                splitedTimeParam.setBeginTime(format(resetDate, DATE_TIME_PATTERN));
+            }
+            if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1), endDate) > 0) {
+                splitedTimeParam.setEndTime(endTm);
+            } else if (CompareUtil.compare(org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1), endDate) <= 0) {
+                Date timePeriodEndDate = org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1), -1);
+                splitedTimeParam.setEndTime(format(timePeriodEndDate, DATE_TIME_PATTERN));
+            }
+            splitedTimeMap.put(format(resetDate, DATE_TIME_PATTERN), splitedTimeParam);
+            resetDate = org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1);
+        }
+        return splitedTimeMap;
+    }
+
+    /**
+     * 获得当前时间的所在天的第一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayBeginTime() {
+        return getDayBeginTime(new Date());
+    }
+
+    /**
+     * 获得当前时间的所在天的第一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayBeginTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getDayBeginTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在天的起始时间
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayBeginTime(String currentTime) {
+        return format(parse(currentTime, DATE_PATTERN), DATE_TIME_PATTERN);
+    }
+
+
+    /**
+     * 获得当前时间的所在天的最后一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayEndTime() {
+        String currentTime = format(new Date(), DATE_TIME_PATTERN);
+        return getDayEndTime(currentTime);
+    }
+
+
+    /**
+     * 获得当前时间的所在天的最后一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayEndTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getDayEndTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在天的最后一秒
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getDayEndTime(String currentTime) {
+        Date resetDate = parse(getDayBeginTime(currentTime), DATE_TIME_PATTERN);
+        return format(org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addDays(resetDate, 1), -1), DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 获得当前时间的所在月的第一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthBeginTime() {
+        String currentTime = format(new Date(), DATE_TIME_PATTERN);
+        return getMonthBeginTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在月的第一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthBeginTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getMonthBeginTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在月的第一秒
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthBeginTime(String currentTime) {
+        return format(parse(currentTime, MONTH_PATTERN), DATE_TIME_PATTERN);
+    }
+
+
+    /**
+     * 获得当前时间的所在月的最后一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthEndTime() {
+        String currentTime = format(new Date(), DATE_TIME_PATTERN);
+        return getMonthEndTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在月的最后一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthEndTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getMonthEndTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在月的最后一秒
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getMonthEndTime(String currentTime) {
+        Date resetDate = parse(getMonthBeginTime(currentTime), DATE_TIME_PATTERN);
+        return format(org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addMonths(resetDate, 1), -1), DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 获得当前时间的所在年的第一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearBeginTime() {
+        String currentTime = format(new Date(), DATE_TIME_PATTERN);
+        return getYearBeginTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在年的第一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearBeginTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getYearBeginTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在年的第一秒
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearBeginTime(String currentTime) {
+        return format(parse(currentTime, YEAR_PATTERN), DATE_TIME_PATTERN);
+    }
+
+
+    /**
+     * 获得当前时间的所在年的最后一秒
+     *
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearEndTime() {
+        String currentTime = format(new Date(), DATE_TIME_PATTERN);
+        return getYearEndTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在年的最后一秒
+     *
+     * @param currentDate 当前时间
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearEndTime(Date currentDate) {
+        String currentTime = format(currentDate, DATE_TIME_PATTERN);
+        return getYearEndTime(currentTime);
+    }
+
+    /**
+     * 获得当前时间的所在年的最后一秒
+     *
+     * @param currentTime 当前时间 yyyy-MM-dd HH:mm:ss
+     * @return yyyy-MM-dd HH:mm:ss
+     */
+    public static String getYearEndTime(String currentTime) {
+        Date resetDate = parse(getYearBeginTime(currentTime), DATE_TIME_PATTERN);
+        return format(org.apache.commons.lang3.time.DateUtils.addSeconds(org.apache.commons.lang3.time.DateUtils.addYears(resetDate, 1), -1), DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 字符串时间转时间戳
+     *
+     * @param currentTime 当前时间
+     * @param pattern     日期格式
+     * @return 返回时间戳
+     */
+    public static Long dateToTimestamp(String currentTime, String pattern) {
+        return parse(currentTime, pattern).getTime();
+    }
+
+    /**
+     * 时间转时间戳
+     *
+     * @param currentDate 当前时间
+     * @return 返回时间戳
+     */
+    public static Long dateToTimestamp(Date currentDate) {
+        return currentDate.getTime();
+    }
+
+    /**
+     * 时间戳转时间
+     *
+     * @param currentTimestamp 当前时间戳
+     * @return 返回日期
+     */
+    public static Date timestampToDate(Long currentTimestamp) {
+        return new Date(currentTimestamp);
+    }
+
+    /**
+     * 时间戳转时间
+     *
+     * @param currentTimestamp 当前时间戳
+     * @param pattern          字符串格式
+     * @return 返回日期
+     */
+    public static String timestampToDate(Long currentTimestamp, String pattern) {
+        Date date = new Date(currentTimestamp);
+        return format(date, pattern);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的开始时间
+     *
+     * @param currentDate 传入的时间
+     * @param interval    传入读数的频率,不能大于60
+     * @return
+     */
+    public static Date getBeginTime(Date currentDate, Integer interval) {
+        interval = interval > 60 ? 60 : interval;
+        Calendar currentCalendar = Calendar.getInstance();
+        currentCalendar.setTime(currentDate);
+
+        int beginTimeMinute = currentCalendar.get(Calendar.MINUTE) / interval * interval;
+        currentCalendar.set(Calendar.MINUTE, beginTimeMinute);
+        return currentCalendar.getTime();
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的开始时间
+     *
+     * @param currentDate 传入的时间 yyyy-MM-dd HH:mm:ss
+     * @param interval    传入读数的频率,不能大于60
+     * @return
+     */
+    public static Date getBeginTime(String currentDate, Integer interval) {
+        return getBeginTime(parse(currentDate, DATE_TIME_PATTERN), interval);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的开始时间
+     *
+     * @param currentTimeStamp 传入的时间戳
+     * @param interval         传入读数的频率,不能大于60
+     * @return
+     */
+    public static Date getBeginTime(Long currentTimeStamp, Integer interval) {
+        return getBeginTime(new Date(currentTimeStamp), interval);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的开始时间,间隔时间默认为15
+     *
+     * @param currentDate 传入的时间 yyyy-MM-dd HH:mm:ss
+     * @return
+     */
+    public static Date getBeginTime(Date currentDate) {
+        return getBeginTime(currentDate, 15);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的结束时间
+     *
+     * @param currentDate 传入的时间 yyyy-MM-dd HH:mm:ss
+     * @param interval    传入读数的频率,不能大于60
+     * @return
+     */
+    public static Date getEndTime(Date currentDate, Integer interval) {
+        interval = interval > 60 ? 60 : interval;
+        Calendar currentCalendar = Calendar.getInstance();
+        currentCalendar.setTime(currentDate);
+
+        int beginTimeMinute = currentCalendar.get(Calendar.MINUTE) / interval * (interval + 1);
+        currentCalendar.set(Calendar.MINUTE, beginTimeMinute);
+        return currentCalendar.getTime();
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的结束时间
+     *
+     * @param currentDate 传入的时间 yyyy-MM-dd HH:mm:ss
+     * @param interval    传入读数的频率,不能大于60
+     * @return
+     */
+    public static Date getEndTime(String currentDate, Integer interval) {
+        return getEndTime(parse(currentDate, DATE_TIME_PATTERN), interval);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的结束时间
+     *
+     * @param currentTimeStamp 传入的时间戳
+     * @param interval         传入读数的频率,不能大于60
+     * @return
+     */
+    private static Date getEndTime(Long currentTimeStamp, Integer interval) {
+        return getEndTime(new Date(currentTimeStamp), interval);
+    }
+
+
+    /**
+     * 传入一个时间,获取此时间在tb中属于哪个时间段的读数,则获取的这个时间段的结束时间,间隔时间默认为15
+     *
+     * @param currentDate 传入的时间 yyyy-MM-dd HH:mm:ss
+     * @return
+     */
+    private static Date getEndTime(Date currentDate) {
+        return getEndTime(currentDate, 15);
+    }
+
+
+    /**
+     * 对日期的【小时】进行加/减
+     *
+     * @param date  日期
+     * @param hours 小时数,负数为减
+     * @return 加/减几小时后的日期
+     */
+    public static String addDateHours(Date date, int hours) {
+        DateTime dateTime = new DateTime(date);
+        return format(dateTime.plusHours(hours).toDate(), DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 对日期的【天】进行加/减
+     *
+     * @param date 日期
+     * @param days 天数,负数为减
+     * @return 加/减几天后的日期
+     */
+    public static String addDateDays(Date date, int days) {
+        DateTime dateTime = new DateTime(date);
+        return format(dateTime.plusDays(days).toDate(), DATE_TIME_PATTERN);
+    }
+
+    /**
+     * 根据时间范围获取时间
+     *
+     * @param timeHorizon
+     * @return
+     */
+    public static Map<String, String> getDateTimeByTimeHorizon(String timeHorizon) {
+        Date date = Calendar.getInstance().getTime();
+        Map<String, String> dateMap = new HashMap<>();
+        if (StringUtils.equals(timeHorizon, TimeHorizon.CURRENT_DAY.getCode())) {
+            dateMap.put("beginTime", getDayBeginTime(date));
+            dateMap.put("endTime", getDayEndTime(date));
+            return dateMap;
+        }
+
+        if (StringUtils.equals(timeHorizon, TimeHorizon.LAST_HOURS.getCode())) {
+            dateMap.put("beginTime", addDateHours(date, -24));
+            dateMap.put("endTime", format(date, DATE_TIME_PATTERN));
+            return dateMap;
+        }
+
+        if (StringUtils.equals(timeHorizon, TimeHorizon.LAST_DAYS.getCode())) {
+            dateMap.put("beginTime", addDateDays(date, -7));
+            dateMap.put("endTime", format(date, DATE_TIME_PATTERN));
+            return dateMap;
+        }
+        dateMap.put("beginTime", addDateDays(date, -30));
+        dateMap.put("endTime", format(date, DATE_TIME_PATTERN));
+        return dateMap;
+    }
+
+
+}

+ 18 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/params/SplitedTimeParam.java

@@ -0,0 +1,18 @@
+package com.ruoyi.common.utils.params;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 切割完成的时间
+ */
+@Data
+public class SplitedTimeParam implements Serializable {
+
+    private static final long serialVersionUID = 8136854862084752561L;
+
+    private String beginTime;
+
+    private String endTime;
+}

+ 21 - 4
warewms-ams/src/main/java/com/ruoyi/ams/asn/domain/WmsDocAsnDetails.java

@@ -1,10 +1,12 @@
 package com.ruoyi.ams.asn.domain;
 package com.ruoyi.ams.asn.domain;
 
 
-import java.math.BigDecimal;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.ruoyi.common.annotation.Excel;
 import com.ruoyi.common.annotation.Excel;
 import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.math.BigDecimal;
 
 
 /**
 /**
  * 入库单明细对象 wms_doc_asn_details
  * 入库单明细对象 wms_doc_asn_details
@@ -103,7 +105,7 @@ public class WmsDocAsnDetails extends BaseEntity
     private String lotatt10;
     private String lotatt10;
 
 
     /**  */
     /**  */
-    @Excel(name = "")
+    @Excel(name = "班组")
     private String lotatt11;
     private String lotatt11;
 
 
     /**  */
     /**  */
@@ -144,62 +146,77 @@ public class WmsDocAsnDetails extends BaseEntity
 
 
     /** 归还人 */
     /** 归还人 */
     @Excel(name = "归还人")
     @Excel(name = "归还人")
+    @TableField("d_edi_01")
     private String dEdi01;
     private String dEdi01;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_02")
     private String dEdi02;
     private String dEdi02;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_03")
     private String dEdi03;
     private String dEdi03;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_04")
     private String dEdi04;
     private String dEdi04;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_05")
     private String dEdi05;
     private String dEdi05;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_06")
     private String dEdi06;
     private String dEdi06;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_07")
     private String dEdi07;
     private String dEdi07;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_08")
     private String dEdi08;
     private String dEdi08;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_09")
     private String dEdi09;
     private String dEdi09;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_10")
     private String dEdi10;
     private String dEdi10;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_11")
     private String dEdi11;
     private String dEdi11;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_12")
     private String dEdi12;
     private String dEdi12;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_13")
     private String dEdi13;
     private String dEdi13;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_14")
     private String dEdi14;
     private String dEdi14;
 
 
     /**  */
     /**  */
     @Excel(name = "")
     @Excel(name = "")
+    @TableField("d_edi_15")
     private String dEdi15;
     private String dEdi15;
 
 
     public void setAsnLineNo(Long asnLineNo) 
     public void setAsnLineNo(Long asnLineNo) 

+ 16 - 0
warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/TotalInfoDTO.java

@@ -0,0 +1,16 @@
+package com.ruoyi.ams.asn.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class TotalInfoDTO implements Serializable {
+
+    private static final long serialVersionUID = 4857035237485972793L;
+
+    private String time;
+
+    private BigDecimal total;
+}

+ 31 - 0
warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/WmsDetailsReqDTO.java

@@ -0,0 +1,31 @@
+package com.ruoyi.ams.asn.dto;
+
+import com.ruoyi.common.enums.Granularity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+public class WmsDetailsReqDTO implements Serializable {
+    private static final long serialVersionUID = -4951727500668394848L;
+
+    @ApiModelProperty(value = "具体字段值类型")
+    private String data;
+
+    @NotBlank(message = "字段名不能为空!")
+    private String field;
+
+    @NotBlank(message = "起始时间不能为空!")
+    private String beginTime;
+
+    @NotBlank(message = "结束时间不能为空!")
+    private String endTime;
+
+    @ApiModelProperty(value = "质检状态 默认总量 HG: 合格 BHG:不合格 DJ:待检")
+    private String status;
+
+    @ApiModelProperty(value = "时间粒度")
+    private Granularity granularity;
+}

+ 16 - 0
warewms-ams/src/main/java/com/ruoyi/ams/asn/dto/WmsDetailsTotalDTO.java

@@ -0,0 +1,16 @@
+package com.ruoyi.ams.asn.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class WmsDetailsTotalDTO implements Serializable {
+    private static final long serialVersionUID = 1853526301723047994L;
+
+    private String name;
+
+    private List<TotalInfoDTO> totalInfoDTOList;
+
+}

+ 5 - 4
warewms-ams/src/main/java/com/ruoyi/ams/asn/mapper/WmsDocAsnDetailsMapper.java

@@ -1,18 +1,19 @@
 package com.ruoyi.ams.asn.mapper;
 package com.ruoyi.ams.asn.mapper;
 
 
-import java.math.BigDecimal;
-import java.util.List;
-
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
 import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 
 
+import java.math.BigDecimal;
+import java.util.List;
+
 /**
 /**
  * 入库单明细Mapper接口
  * 入库单明细Mapper接口
  *
  *
  * @author ruoyi
  * @author ruoyi
  * @date 2022-11-03
  * @date 2022-11-03
  */
  */
-public interface WmsDocAsnDetailsMapper {
+public interface WmsDocAsnDetailsMapper extends BaseMapper<WmsDocAsnDetails> {
     /**
     /**
      * 查询入库明细
      * 查询入库明细
      * @param asnNo
      * @param asnNo

+ 34 - 5
warewms-ams/src/main/java/com/ruoyi/ams/asn/service/IWmsDocAsnDetailsService.java

@@ -1,11 +1,13 @@
 package com.ruoyi.ams.asn.service;
 package com.ruoyi.ams.asn.service;
 
 
+import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
+import com.ruoyi.ams.asn.dto.WmsDetailsReqDTO;
+import com.ruoyi.ams.asn.dto.WmsDetailsTotalDTO;
+import com.ruoyi.common.enums.Granularity;
+
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
-
-import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
-import com.ruoyi.ams.asn.form.DelDocAsnDetailsForm;
-import com.ruoyi.ams.asn.form.StockForm;
+import java.util.Map;
 
 
 /**
 /**
  * 入库单明细Service接口
  * 入库单明细Service接口
@@ -81,8 +83,35 @@ public interface IWmsDocAsnDetailsService {
 
 
     /**
     /**
      * 批量删除
      * 批量删除
-     * @param arr
+     * @param list
      * @return
      * @return
      */
      */
     int deleteWmsDocAsnDetailsByAsnNoLineNos(List<HashMap<String,Object>> list);
     int deleteWmsDocAsnDetailsByAsnNoLineNos(List<HashMap<String,Object>> list);
+
+    /**
+     * 根据status获取字段状态率
+     * @param field 字段名
+     * @param beginTime 起始时间
+     * @param endTime 结束时间
+     * @param status  默认总量 HG: 合格 BHG:不合格 DJ:待检
+     * @param granularity 时间粒度
+     * @return
+     */
+    List<WmsDetailsTotalDTO> getPassRate(String field, String beginTime, String endTime, String status, Granularity granularity);
+
+    /**
+     * 根据字段名获取时间段内年/月/日总量
+     * @param field 字段名
+     * @param beginTime 起始时间
+     * @param endTime 结束时间
+     * @return
+     */
+    Map<String, List<WmsDetailsTotalDTO>> queryAllGranularityTotal(String field, String beginTime, String endTime);
+
+    /**
+     * 根据字段field获取时间段根据时间粒度切割后产量 data不传即获取总量
+     * @param wmsDetailsReqDTO
+     * @return
+     */
+    List<WmsDetailsTotalDTO> queryFieldTotalList(WmsDetailsReqDTO wmsDetailsReqDTO);
 }
 }

+ 205 - 8
warewms-ams/src/main/java/com/ruoyi/ams/asn/service/impl/WmsDocAsnDetailsServiceImpl.java

@@ -1,18 +1,36 @@
 package com.ruoyi.ams.asn.service.impl;
 package com.ruoyi.ams.asn.service.impl;
 
 
-import java.util.HashMap;
-import java.util.List;
-
-import com.ruoyi.ams.asn.form.DelDocAsnDetailsForm;
-import com.ruoyi.ams.asn.form.StockForm;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.comparator.CompareUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
+import com.ruoyi.ams.asn.dto.TotalInfoDTO;
+import com.ruoyi.ams.asn.dto.WmsDetailsReqDTO;
+import com.ruoyi.ams.asn.dto.WmsDetailsTotalDTO;
+import com.ruoyi.ams.asn.mapper.WmsDocAsnDetailsMapper;
+import com.ruoyi.ams.asn.service.IWmsDocAsnDetailsService;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.enums.Granularity;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.TimeUtils;
+import com.ruoyi.common.utils.params.SplitedTimeParam;
+import com.ruoyi.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
-import com.ruoyi.ams.asn.mapper.WmsDocAsnDetailsMapper;
-import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
-import com.ruoyi.ams.asn.service.IWmsDocAsnDetailsService;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 /**
 /**
  * 入库单明细Service业务层处理
  * 入库单明细Service业务层处理
  *
  *
@@ -26,6 +44,9 @@ public class WmsDocAsnDetailsServiceImpl implements IWmsDocAsnDetailsService {
     @Autowired
     @Autowired
     private IWmsDocAsnDetailsService wmsDocAsnDetailsService;
     private IWmsDocAsnDetailsService wmsDocAsnDetailsService;
 
 
+    @Autowired
+    private ISysConfigService sysConfigService;
+
     /**
     /**
      * 查询入库单明细
      * 查询入库单明细
      *
      *
@@ -134,4 +155,180 @@ public class WmsDocAsnDetailsServiceImpl implements IWmsDocAsnDetailsService {
         }
         }
         return 1;
         return 1;
     }
     }
+
+/*************************************************************************可视化大屏*********************************************************************************/
+
+    /**
+     * 根据status获取字段状态率
+     * @param field 字段名
+     * @param beginTime 起始时间
+     * @param endTime 结束时间
+     * @param status  默认总量 HG: 合格 BHG:不合格 DJ:待检
+     * @param granularity 时间粒度
+     * @return
+     */
+    @Override
+    public List<WmsDetailsTotalDTO> getPassRate(String field, String beginTime, String endTime, String status, Granularity granularity){
+        List<WmsDetailsTotalDTO> result = new ArrayList<>();
+        if (ObjectUtil.isNull(granularity)) {
+            granularity = Granularity.DAY;
+        }
+        List<WmsDetailsTotalDTO> wmsDetailsTotalDTOByDayList = queryFieldTotalList(field, beginTime, endTime, granularity);
+        List<WmsDetailsTotalDTO> wmsDetailsTotalByStatusList = queryFieldTotalList(field, beginTime, endTime, status, granularity);
+        for (WmsDetailsTotalDTO item : wmsDetailsTotalDTOByDayList) {
+            WmsDetailsTotalDTO wmsDetailsTotalDTO = new WmsDetailsTotalDTO();
+            List<TotalInfoDTO> totalInfoByStatusList = wmsDetailsTotalByStatusList.stream().filter(wmsDetailsTotalByStatus -> item.getName().equals(wmsDetailsTotalByStatus.getName())).map(WmsDetailsTotalDTO::getTotalInfoDTOList).findFirst().orElseGet(() -> null);
+            if (CollectionUtil.isEmpty(totalInfoByStatusList)) continue;
+            List<TotalInfoDTO> passRateTotalList = totalInfoByStatusList.stream().map(totalInfoByStatus -> {
+                TotalInfoDTO totalInfo = new TotalInfoDTO();
+                TotalInfoDTO totalInfoDTOByDay = item.getTotalInfoDTOList().stream().filter(totalInfoByDay -> totalInfoByDay.getTime().equals(totalInfoByStatus.getTime())).findFirst().orElseGet(() -> null);
+                //合格率
+                BigDecimal passRate = CompareUtil.compare(totalInfoByStatus.getTotal(), BigDecimal.ZERO) == 0 || CompareUtil.compare(totalInfoDTOByDay.getTotal(), BigDecimal.ZERO) == 0 ?
+                        BigDecimal.ZERO : totalInfoByStatus.getTotal().multiply(new BigDecimal("100")).divide(totalInfoDTOByDay.getTotal()).setScale(2, RoundingMode.HALF_UP);
+                totalInfo.setTotal(passRate);
+                totalInfo.setTime(totalInfoByStatus.getTime());
+                return totalInfo;
+            }).collect(Collectors.toList());
+            wmsDetailsTotalDTO.setName(item.getName());
+            wmsDetailsTotalDTO.setTotalInfoDTOList(passRateTotalList);
+            result.add(wmsDetailsTotalDTO);
+        }
+        return result;
+    }
+
+    /**
+     * 根据字段名获取时间段内年/月/日总量
+     * @param field 字段名
+     * @param beginTime 起始时间
+     * @param endTime 结束时间
+     * @return
+     */
+    @Override
+    public Map<String, List<WmsDetailsTotalDTO>> queryAllGranularityTotal(String field, String beginTime, String endTime){
+        List<WmsDetailsTotalDTO> result = new ArrayList<>();
+        for (Granularity granularity : Granularity.values()) {
+            if (granularity.equals(Granularity.HOUR)) continue;
+            List<WmsDetailsTotalDTO> wmsDetailsTotalDTOByDayList = queryFieldTotalList(field, beginTime, endTime, granularity);
+            result.addAll(wmsDetailsTotalDTOByDayList);
+        }
+        Map<String, List<WmsDetailsTotalDTO>> wmsDetailsTotalDTOMap = result.stream().collect(Collectors.groupingBy(WmsDetailsTotalDTO::getName));
+        return wmsDetailsTotalDTOMap;
+    }
+
+    /**
+     * 根据字段field获取时间段按天切割后产量 data不传即获取总量
+     *
+     * @param data        字段具体值
+     * @param field       字段名称
+     * @param beginTime   起始时间
+     * @param endTime     结束时间
+     * @param status      默认总量 HG: 合格 BHG:不合格 DJ:待检
+     * @return
+     */
+    public List<WmsDetailsTotalDTO> queryFieldTotalList(String data, String field, String beginTime, String endTime, String status) {
+        return queryFieldTotalList(data, field, beginTime, endTime, status, Granularity.DAY);
+    }
+
+    /**
+     * 根据字段field获取时间段根据时间粒度切割后产量 data不传即获取总量
+     * @param wmsDetailsReqDTO
+     * @return
+     */
+    @Override
+    public List<WmsDetailsTotalDTO> queryFieldTotalList(WmsDetailsReqDTO wmsDetailsReqDTO) {
+        return queryFieldTotalList(wmsDetailsReqDTO.getData(), wmsDetailsReqDTO.getField(), wmsDetailsReqDTO.getBeginTime(), wmsDetailsReqDTO.getEndTime(), wmsDetailsReqDTO.getStatus(), wmsDetailsReqDTO.getGranularity());
+    }
+
+
+    public List<WmsDetailsTotalDTO> queryFieldTotalList(String field, String beginTime, String endTime, Granularity granularity) {
+        return queryFieldTotalList(null, field, beginTime, endTime, null, granularity);
+    }
+
+    public List<WmsDetailsTotalDTO> queryFieldTotalList(String field, String beginTime, String endTime, String status, Granularity granularity) {
+        return queryFieldTotalList(null, field, beginTime, endTime, status, granularity);
+    }
+
+    /**
+     * 根据字段field获取时间段根据时间粒度切割后产量 data不传即获取总量
+     *
+     * @param data        字段具体值
+     * @param field       字段名称
+     * @param beginTime   起始时间
+     * @param endTime     结束时间
+     * @param status      默认总量 HG: 合格 BHG:不合格 DJ:待检
+     * @param granularity 时间粒度
+     * @return
+     */
+    public List<WmsDetailsTotalDTO> queryFieldTotalList(String data, String field, String beginTime, String endTime, String status, Granularity granularity) {
+        List<WmsDetailsTotalDTO> result = new ArrayList<>();
+        Map<String, SplitedTimeParam> splitTimeMap = TimeUtils.getSplitedTimeGroupByTime(beginTime, endTime, granularity);
+        if (StringUtils.isNotBlank(data)) {
+            List<WmsDocAsnDetails> wmsDocAsnDetailsList = queryWmsDocAsnDetailsList(data, field, beginTime, endTime, status);
+            if (CollectionUtil.isEmpty(wmsDocAsnDetailsList)) return result;
+            WmsDetailsTotalDTO wmsDetailsTotalDTO = buildWmsDetailsTotalDTOList(data, wmsDocAsnDetailsList, splitTimeMap);
+            result.add(wmsDetailsTotalDTO);
+            return result;
+        }
+        String configValue = sysConfigService.selectConfigByKey(Constants.WMS_LARGE_SCREEN_DATA);
+        Map<String, List<String>> configMap = JSONObject.parseObject(configValue, Map.class);
+        List<String> dataList = configMap.get(field);
+        if (CollectionUtil.isEmpty(dataList)) throw new BaseException("配置为空!");
+        for (String item : dataList) {
+            List<WmsDocAsnDetails> wmsDocAsnDetailsList = queryWmsDocAsnDetailsList(item, field, beginTime, endTime, status);
+            if (CollectionUtil.isEmpty(wmsDocAsnDetailsList)) continue;
+            WmsDetailsTotalDTO wmsDetailsTotalDTO = buildWmsDetailsTotalDTOList(item, wmsDocAsnDetailsList, splitTimeMap);
+            result.add(wmsDetailsTotalDTO);
+        }
+        return result;
+    }
+
+    /**
+     *
+     * @param data                  字段具体值
+     * @param wmsDocAsnDetailsList  根据某一字段分类的入库单集合
+     * @param beginTime             起始时间
+     * @param endTime               结束时间
+     * @param granularity           时间粒度
+     * @return
+     */
+    private WmsDetailsTotalDTO buildWmsDetailsTotalDTOList(String data, List<WmsDocAsnDetails> wmsDocAsnDetailsList, String beginTime, String endTime, Granularity granularity) {
+        Map<String, SplitedTimeParam> splitTimeMap = TimeUtils.getSplitedTimeGroupByTime(beginTime, endTime, granularity);
+        return buildWmsDetailsTotalDTOList(data, wmsDocAsnDetailsList, splitTimeMap);
+    }
+
+
+    /**
+     * 构建传入时间段根据时间粒度切割某一字段分类后的产量
+     *
+     * @param data                  字段具体值
+     * @param wmsDocAsnDetailsList  根据某一字段分类的入库单集合
+     * @param splitTimeMap          根据时间粒度对时间段切割集合
+     * @return
+     */
+    private WmsDetailsTotalDTO buildWmsDetailsTotalDTOList(String data, List<WmsDocAsnDetails> wmsDocAsnDetailsList, Map<String, SplitedTimeParam> splitTimeMap) {
+        WmsDetailsTotalDTO wmsDetailsTotalDTO = new WmsDetailsTotalDTO();
+        wmsDetailsTotalDTO.setName(data);
+        List<TotalInfoDTO> totalInfoDTOList = new ArrayList<>();
+        for (Map.Entry<String, SplitedTimeParam> splitTimeParamEntry : splitTimeMap.entrySet()) {
+            SplitedTimeParam splitedTimeParam = splitTimeParamEntry.getValue();
+            TotalInfoDTO totalInfoDTO = new TotalInfoDTO();
+            List<WmsDocAsnDetails> wmsDocAsnDetailsBetweenTimeList = wmsDocAsnDetailsList.stream().filter(item -> TimeUtils.dateToTimestamp(item.getLotatt03(), TimeUtils.DATE_TIME_PATTERN) >= TimeUtils.dateToTimestamp(splitedTimeParam.getBeginTime(), TimeUtils.DATE_TIME_PATTERN)
+                    && TimeUtils.dateToTimestamp(item.getLotatt03(), TimeUtils.DATE_TIME_PATTERN) <= TimeUtils.dateToTimestamp(splitedTimeParam.getEndTime(), TimeUtils.DATE_TIME_PATTERN)).collect(Collectors.toList());
+            //总数
+            BigDecimal total = wmsDocAsnDetailsBetweenTimeList.stream().filter(item -> ObjectUtil.isNotEmpty(item.getExpectedQtyEach())).map(WmsDocAsnDetails::getExpectedQtyEach).reduce(BigDecimal.ZERO, BigDecimal::add);
+            totalInfoDTO.setTotal(total);
+            totalInfoDTO.setTime(splitTimeParamEntry.getKey());
+            totalInfoDTOList.add(totalInfoDTO);
+        }
+        wmsDetailsTotalDTO.setTotalInfoDTOList(totalInfoDTOList);
+        return wmsDetailsTotalDTO;
+    }
+
+    private List<WmsDocAsnDetails> queryWmsDocAsnDetailsList(String data, String field, String beginTime, String endTime, String status) {
+        QueryWrapper<WmsDocAsnDetails> queryWrapper = new QueryWrapper<>();
+        queryWrapper.between("lotatt03", beginTime, endTime)
+                .eq(StringUtils.isNotBlank(data), field, data).eq(StringUtils.isNotBlank(status), "lotatt05", status).orderByAsc("lotatt03");
+        return wmsDocAsnDetailsMapper.selectList(queryWrapper);
+    }
+
 }
 }