浏览代码

sop预警

haogh 9 月之前
父节点
当前提交
aa0d84175f

+ 3 - 1
sop-api/src/main/java/com/qmth/sop/server/api/ServiceUnitAnalyseController.java

@@ -69,10 +69,12 @@ public class ServiceUnitAnalyseController {
             @ApiParam(value = "客户所在省份", required = false) @RequestParam(required = false) String province,
             @ApiParam(value = "客户所在省份", required = false) @RequestParam(required = false) String province,
             @ApiParam(value = "项目经理所在人力商", required = false) @RequestParam(required = false) Long supplierId,
             @ApiParam(value = "项目经理所在人力商", required = false) @RequestParam(required = false) Long supplierId,
             @ApiParam(value = "区域协调人ID", required = false) @RequestParam(required = false) Long coordinatorId,
             @ApiParam(value = "区域协调人ID", required = false) @RequestParam(required = false) Long coordinatorId,
+            @ApiParam(value = "类型", required = false) @RequestParam(required = false) String type,
+            @ApiParam(value = "预警字段", required = false) @RequestParam(required = false) String fieldObj,
             @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
             @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
             @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
             @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
         return ResultUtil.ok(serviceUnitAnalyseService.pageSop(new Page<>(pageNumber, pageSize), serviceUnitId, crmUserId, customName, process,
         return ResultUtil.ok(serviceUnitAnalyseService.pageSop(new Page<>(pageNumber, pageSize), serviceUnitId, crmUserId, customName, process,
-                leadId, province, supplierId, coordinatorId));
+                leadId, province, supplierId, coordinatorId, type, fieldObj));
     }
     }
 
 
     @ApiOperation(value = "详情导出")
     @ApiOperation(value = "详情导出")

+ 29 - 0
sop-api/src/main/java/com/qmth/sop/server/api/SopWarnMonitorController.java

@@ -1,10 +1,39 @@
 package com.qmth.sop.server.api;
 package com.qmth.sop.server.api;
 
 
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.sop.business.bean.result.SopWarnMonitorResult;
+import com.qmth.sop.business.service.SopWarnMonitorService;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.util.Result;
+import com.qmth.sop.common.util.ResultUtil;
+import io.swagger.annotations.*;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
 /**
 /**
  * @Description sop预警监控
  * @Description sop预警监控
  * @Author haoguanghui
  * @Author haoguanghui
  * @date 2024/09/12
  * @date 2024/09/12
  */
  */
+@Api(tags = "sop预警 Controller")
+@RestController
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_SOP_WARN_MONITOR)
 public class SopWarnMonitorController {
 public class SopWarnMonitorController {
 
 
+    @Resource
+    SopWarnMonitorService sopWarnMonitorService;
+
+    @ApiOperation(value = "按大区预警统计")
+    @RequestMapping(value = "/region", method = RequestMethod.POST)
+    @ApiResponses({ @ApiResponse(code = 200, message = "返回信息", response = SopWarnMonitorResult.class) })
+    public Result region(@ApiParam(value = "服务单元ID", required = true) @RequestParam(required = true) Long serviceUnitId) {
+        return ResultUtil.ok(sopWarnMonitorService.listWarnByRegion(serviceUnitId));
+    }
+
+
+
 }
 }

+ 11 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/result/ProjectMonitorResult.java

@@ -49,6 +49,9 @@ public class ProjectMonitorResult implements Serializable {
     @ApiModelProperty(value = "流程id")
     @ApiModelProperty(value = "流程id")
     private String flowId;
     private String flowId;
 
 
+    @ApiModelProperty(value = "预警字段")
+    private String fieldObj;
+
     @ApiModelProperty(value = "区域协调人")
     @ApiModelProperty(value = "区域协调人")
     private ProjectMonitorUserResult regionCoordinator;
     private ProjectMonitorUserResult regionCoordinator;
 
 
@@ -161,4 +164,12 @@ public class ProjectMonitorResult implements Serializable {
     public void setLeadId(Long leadId) {
     public void setLeadId(Long leadId) {
         this.leadId = leadId;
         this.leadId = leadId;
     }
     }
+
+    public String getFieldObj() {
+        return fieldObj;
+    }
+
+    public void setFieldObj(String fieldObj) {
+        this.fieldObj = fieldObj;
+    }
 }
 }

+ 66 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/result/SopWarnMonitorDetailResult.java

@@ -0,0 +1,66 @@
+package com.qmth.sop.business.bean.result;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description sop预警监控-数据查询结果
+ * @Author haoguanghui
+ * @date 2024/09/14
+ */
+public class SopWarnMonitorDetailResult {
+
+    @ApiModelProperty(value = "派单号")
+    private String crmNo;
+
+    @ApiModelProperty(value = "sop编号")
+    private String sopNo;
+
+    @ApiModelProperty(value = "预警字段")
+    private String fieldObj;
+
+    @ApiModelProperty(value = "大区经理ID")
+    private Long leadId;
+
+    @ApiModelProperty(value = "大区经理名称")
+    private String leadName;
+
+    public String getCrmNo() {
+        return crmNo;
+    }
+
+    public void setCrmNo(String crmNo) {
+        this.crmNo = crmNo;
+    }
+
+    public String getSopNo() {
+        return sopNo;
+    }
+
+    public void setSopNo(String sopNo) {
+        this.sopNo = sopNo;
+    }
+
+    public String getFieldObj() {
+        return fieldObj;
+    }
+
+    public void setFieldObj(String fieldObj) {
+        this.fieldObj = fieldObj;
+    }
+
+    public Long getLeadId() {
+        return leadId;
+    }
+
+    public void setLeadId(Long leadId) {
+        this.leadId = leadId;
+    }
+
+    public String getLeadName() {
+        return leadName;
+    }
+
+    public void setLeadName(String leadName) {
+        this.leadName = leadName;
+    }
+}

+ 183 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/result/SopWarnMonitorResult.java

@@ -0,0 +1,183 @@
+package com.qmth.sop.business.bean.result;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description sop预警返回结果
+ * @Author haoguanghui
+ * @date 2024/09/14
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class SopWarnMonitorResult {
+
+    @ApiModelProperty(value = "大区经理ID")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long leadId;
+
+    @ApiModelProperty(value = "大区经理名称")
+    private String leadName;
+
+    @ApiModelProperty(value = "人力供应商ID")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long supplierId;
+
+    @ApiModelProperty(value = "人力供应商名字")
+    private String supplierName;
+
+    @ApiModelProperty(value = "区域协调人ID")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long coordinatorId;
+
+    @ApiModelProperty(value = "区域协调人名称")
+    private String coordinatorName;
+
+    @ApiModelProperty(value = "预警总数")
+    private Integer total;
+
+    @ApiModelProperty(value = "扫描开始时间预警数")
+    private Integer scanStartTimeNum;
+
+    @ApiModelProperty(value = "扫描开始时间预警占比")
+    private String scanStarTimeRatio;
+
+    @ApiModelProperty(value = "扫描结束时间预警")
+    private Integer scanEndTimeNum;
+
+    @ApiModelProperty(value = "扫描结束时间预警占比")
+    private String scanEndTimeRatio;
+
+    @ApiModelProperty(value = "评卷开始时间预警")
+    private Integer markStartTimeNum;
+
+    @ApiModelProperty(value = "评卷开始时间预警占比")
+    private String markStartTimeRatio;
+
+    @ApiModelProperty(value = "评卷结束时间预警")
+    private Integer markEndTimeNum;
+
+    @ApiModelProperty(value = "评卷结束时间预警占比")
+    private String markEndTimeRatio;
+
+    public String getLeadName() {
+        return leadName;
+    }
+
+    public void setLeadName(String leadName) {
+        this.leadName = leadName;
+    }
+
+    public Long getLeadId() {
+        return leadId;
+    }
+
+    public void setLeadId(Long leadId) {
+        this.leadId = leadId;
+    }
+
+    public Long getSupplierId() {
+        return supplierId;
+    }
+
+    public void setSupplierId(Long supplierId) {
+        this.supplierId = supplierId;
+    }
+
+    public String getSupplierName() {
+        return supplierName;
+    }
+
+    public void setSupplierName(String supplierName) {
+        this.supplierName = supplierName;
+    }
+
+    public Long getCoordinatorId() {
+        return coordinatorId;
+    }
+
+    public void setCoordinatorId(Long coordinatorId) {
+        this.coordinatorId = coordinatorId;
+    }
+
+    public String getCoordinatorName() {
+        return coordinatorName;
+    }
+
+    public void setCoordinatorName(String coordinatorName) {
+        this.coordinatorName = coordinatorName;
+    }
+
+    public Integer getTotal() {
+        return total;
+    }
+
+    public void setTotal(Integer total) {
+        this.total = total;
+    }
+
+    public Integer getScanStartTimeNum() {
+        return scanStartTimeNum;
+    }
+
+    public void setScanStartTimeNum(Integer scanStartTimeNum) {
+        this.scanStartTimeNum = scanStartTimeNum;
+    }
+
+    public String getScanStarTimeRatio() {
+        return scanStarTimeRatio;
+    }
+
+    public void setScanStarTimeRatio(String scanStarTimeRatio) {
+        this.scanStarTimeRatio = scanStarTimeRatio;
+    }
+
+    public Integer getScanEndTimeNum() {
+        return scanEndTimeNum;
+    }
+
+    public void setScanEndTimeNum(Integer scanEndTimeNum) {
+        this.scanEndTimeNum = scanEndTimeNum;
+    }
+
+    public String getScanEndTimeRatio() {
+        return scanEndTimeRatio;
+    }
+
+    public void setScanEndTimeRatio(String scanEndTimeRatio) {
+        this.scanEndTimeRatio = scanEndTimeRatio;
+    }
+
+    public Integer getMarkStartTimeNum() {
+        return markStartTimeNum;
+    }
+
+    public void setMarkStartTimeNum(Integer markStartTimeNum) {
+        this.markStartTimeNum = markStartTimeNum;
+    }
+
+    public String getMarkStartTimeRatio() {
+        return markStartTimeRatio;
+    }
+
+    public void setMarkStartTimeRatio(String markStartTimeRatio) {
+        this.markStartTimeRatio = markStartTimeRatio;
+    }
+
+    public Integer getMarkEndTimeNum() {
+        return markEndTimeNum;
+    }
+
+    public void setMarkEndTimeNum(Integer markEndTimeNum) {
+        this.markEndTimeNum = markEndTimeNum;
+    }
+
+    public String getMarkEndTimeRatio() {
+        return markEndTimeRatio;
+    }
+
+    public void setMarkEndTimeRatio(String markEndTimeRatio) {
+        this.markEndTimeRatio = markEndTimeRatio;
+    }
+}

+ 2 - 1
sop-business/src/main/java/com/qmth/sop/business/mapper/ServiceUnitAnalyseMapper.java

@@ -75,7 +75,8 @@ public interface ServiceUnitAnalyseMapper extends BaseMapper<TBService> {
      */
      */
     IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, @Param(value = "serviceUnitId") Long serviceUnitId,
     IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, @Param(value = "serviceUnitId") Long serviceUnitId,
             @Param(value = "crmUserId") Long crmUserId, @Param(value = "customName") String customName, @Param(value = "process") CrmProcessEnum process,
             @Param(value = "crmUserId") Long crmUserId, @Param(value = "customName") String customName, @Param(value = "process") CrmProcessEnum process,
-            @Param(value = "leadId") Long leadId, @Param(value = "province") String province, @Param(value = "prList") List<String> processList);
+            @Param(value = "leadId") Long leadId, @Param(value = "province") String province, @Param(value = "prList") List<String> processList,
+            @Param(value = "type") String type, @Param(value = "fieldObj") String fieldObj);
 
 
     /**
     /**
      * 过服务单元等条件查询sop列表
      * 过服务单元等条件查询sop列表

+ 14 - 0
sop-business/src/main/java/com/qmth/sop/business/mapper/SopWarnMonitorMapper.java

@@ -0,0 +1,14 @@
+package com.qmth.sop.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.sop.business.bean.result.SopWarnMonitorDetailResult;
+import com.qmth.sop.business.entity.TBDelayWarn;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface SopWarnMonitorMapper extends BaseMapper<TBDelayWarn> {
+
+    List<SopWarnMonitorDetailResult> listDelayWarn(@Param(value = "serviceUnitId") Long serviceUnitId,
+            @Param(value = "warnFieldList") List<String> warnFieldList);
+}

+ 1 - 1
sop-business/src/main/java/com/qmth/sop/business/service/ServiceUnitAnalyseService.java

@@ -26,7 +26,7 @@ public interface ServiceUnitAnalyseService extends IService<TBService> {
     List<ServiceUnitProvinceResult> province(Long serviceUnitId);
     List<ServiceUnitProvinceResult> province(Long serviceUnitId);
 
 
     IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process,
     IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process,
-            Long leadId, String province, Long supplierId, Long coordinatorId);
+            Long leadId, String province, Long supplierId, Long coordinatorId, String type, String fieldObj);
 
 
     void export(Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process, Long leadId, String province, Long supplierId,
     void export(Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process, Long leadId, String province, Long supplierId,
             Long coordinatorId);
             Long coordinatorId);

+ 12 - 0
sop-business/src/main/java/com/qmth/sop/business/service/SopWarnMonitorService.java

@@ -0,0 +1,12 @@
+package com.qmth.sop.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.sop.business.bean.result.SopWarnMonitorResult;
+import com.qmth.sop.business.entity.TBDelayWarn;
+
+import java.util.List;
+
+public interface SopWarnMonitorService extends IService<TBDelayWarn> {
+
+    List<SopWarnMonitorResult> listWarnByRegion(Long serviceUnitId);
+}

+ 4 - 4
sop-business/src/main/java/com/qmth/sop/business/service/impl/ServiceUnitAnalyseServiceImpl.java

@@ -159,7 +159,7 @@ public class ServiceUnitAnalyseServiceImpl extends ServiceImpl<ServiceUnitAnalys
 
 
     @Override
     @Override
     public IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process,
     public IPage<ProjectMonitorResult> pageSop(Page<ProjectMonitorResult> page, Long serviceUnitId, Long crmUserId, String customName, CrmProcessEnum process,
-            Long leadId, String province, Long supplierId, Long coordinatorId) {
+            Long leadId, String province, Long supplierId, Long coordinatorId, String type, String fieldObj) {
         List<String> processList = new ArrayList<>();
         List<String> processList = new ArrayList<>();
         if (process != null) {
         if (process != null) {
             processList = getProcessList(process);
             processList = getProcessList(process);
@@ -173,11 +173,11 @@ public class ServiceUnitAnalyseServiceImpl extends ServiceImpl<ServiceUnitAnalys
         }
         }
 
 
         IPage<ProjectMonitorResult> pageSop;
         IPage<ProjectMonitorResult> pageSop;
-        // 人力供应商、区域协调人
+        // 其他
         if (supplierId == null && coordinatorId == null) {
         if (supplierId == null && coordinatorId == null) {
             pageSop = baseMapper.pageSop(new Page<>(page.getCurrent(), page.getSize()), serviceUnitId, crmUserId,
             pageSop = baseMapper.pageSop(new Page<>(page.getCurrent(), page.getSize()), serviceUnitId, crmUserId,
-                    customName, process, leadId, province, processList);
-        } else { // 其他
+                    customName, process, leadId, province, processList, type, fieldObj);
+        } else { // 人力供应商、区域协调人
             pageSop = baseMapper.pageSopByUserAllocation(new Page<>(page.getCurrent(), page.getSize()), serviceUnitId, crmUserId,
             pageSop = baseMapper.pageSopByUserAllocation(new Page<>(page.getCurrent(), page.getSize()), serviceUnitId, crmUserId,
                     customName, process, leadId, province, processList, supplierId, coordinatorId, roleType);
                     customName, process, leadId, province, processList, supplierId, coordinatorId, roleType);
         }
         }

+ 147 - 0
sop-business/src/main/java/com/qmth/sop/business/service/impl/SopWarnMonitorServiceImpl.java

@@ -0,0 +1,147 @@
+package com.qmth.sop.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.business.bean.result.SopWarnMonitorDetailResult;
+import com.qmth.sop.business.bean.result.SopWarnMonitorResult;
+import com.qmth.sop.business.entity.TBDelayWarn;
+import com.qmth.sop.business.mapper.SopWarnMonitorMapper;
+import com.qmth.sop.business.service.SopWarnMonitorService;
+import com.qmth.sop.common.enums.WarnFieldEnum;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.NumberFormat;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Service
+public class SopWarnMonitorServiceImpl extends ServiceImpl<SopWarnMonitorMapper, TBDelayWarn> implements SopWarnMonitorService {
+
+    @Override
+    public List<SopWarnMonitorResult> listWarnByRegion(Long serviceUnitId) {
+        List<SopWarnMonitorResult> resultList = new ArrayList<>();
+        List<String> warnFieldList = getWarnField();
+
+        List<SopWarnMonitorDetailResult> warnDetailList = baseMapper.listDelayWarn(serviceUnitId, warnFieldList);
+        //按照大区经理分组
+        Function<SopWarnMonitorDetailResult, List<Object>> compositeKey = warn -> Arrays.asList(warn.getLeadId(), warn.getLeadName());
+        Map<List<Object>, List<SopWarnMonitorDetailResult>> warnMap = warnDetailList.stream().collect(Collectors.groupingBy(compositeKey, Collectors.toList()));
+
+        Set<Map.Entry<List<Object>, List<SopWarnMonitorDetailResult>>> entries = warnMap.entrySet();
+        for (Map.Entry<List<Object>, List<SopWarnMonitorDetailResult>> entry : entries) {
+            SopWarnMonitorResult result = new SopWarnMonitorResult();
+            List<Object> leadList = entry.getKey();
+            List<SopWarnMonitorDetailResult> detailList = entry.getValue();
+
+            result.setLeadId(Long.parseLong(leadList.get(0).toString()));
+            result.setLeadName(leadList.get(1).toString());
+            result.setTotal(detailList.size());
+            resultList.add(result);
+        }
+
+        //排序
+        List<SopWarnMonitorResult> warnOrderList = resultList.stream()
+                .sorted(Comparator.comparing(SopWarnMonitorResult::getTotal).reversed())
+                .collect(Collectors.toList());
+        //设置预警数量和占比
+        for (SopWarnMonitorResult result : warnOrderList) {
+            List<SopWarnMonitorDetailResult> filterWarnList = warnDetailList.stream()
+                    .filter(item -> item.getLeadId().equals(result.getLeadId()))
+                    .collect(Collectors.toList());
+            getWarnFieldNum(result, filterWarnList);
+        }
+
+        //合计
+        getSum(resultList);
+
+        return resultList;
+    }
+
+    private void getSum(List<SopWarnMonitorResult> resultList) {
+        if(CollectionUtils.isNotEmpty(resultList)) {
+            SopWarnMonitorResult result = new SopWarnMonitorResult();
+            //总量
+            int sum = resultList.stream().mapToInt(SopWarnMonitorResult::getTotal).sum();
+            //扫描起始时间的预警总量
+            int scanStartTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getScanStartTimeNum).sum();
+            //扫描结束时间的预警总量
+            int scanEndTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getScanEndTimeNum).sum();
+            //评卷起始时间的预警总量
+            int markStartTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getMarkStartTimeNum).sum();
+            //评卷结束时间的预警总量
+            int markEndTimeSum = resultList.stream().mapToInt(SopWarnMonitorResult::getMarkEndTimeNum).sum();
+
+            result.setTotal(sum);
+            result.setScanStartTimeNum(scanStartTimeSum);
+            result.setScanStarTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(scanStartTimeSum)));
+            result.setScanEndTimeNum(scanEndTimeSum);
+            result.setScanEndTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(scanEndTimeSum)));
+            result.setMarkStartTimeNum(markStartTimeSum);
+            result.setMarkStartTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(markStartTimeSum)));
+            result.setMarkEndTimeNum(markEndTimeSum);
+            result.setMarkEndTimeRatio(getRatio(BigDecimal.valueOf(sum), BigDecimal.valueOf(markEndTimeSum)));
+
+            resultList.add(result);
+        }
+    }
+
+    private void getWarnFieldNum(SopWarnMonitorResult result, List<SopWarnMonitorDetailResult> filterWarnList) {
+        //按照预警字段分组,统计数量
+        Map<String, List<SopWarnMonitorDetailResult>> map = filterWarnList.stream().collect(Collectors.groupingBy(SopWarnMonitorDetailResult::getFieldObj));
+        for (WarnFieldEnum field : WarnFieldEnum.values()) {
+            int warnNum = 0;
+            String ratio = "";
+            //设置预警数量和占比
+            if (map.containsKey(field.getTitle())) {
+                warnNum = map.get(field.getTitle()).size();
+                //计算占比
+                BigDecimal num = BigDecimal.valueOf(warnNum);
+                BigDecimal totalNum = BigDecimal.valueOf(result.getTotal());
+                ratio = getRatio(totalNum, num);
+            }
+            switch (field) {
+            case SCAN_START_TIME:
+                result.setScanStartTimeNum(warnNum);
+                result.setScanStarTimeRatio(ratio);
+                break;
+            case SCAN_END_TIME:
+                result.setScanEndTimeNum(warnNum);
+                result.setScanEndTimeRatio(ratio);
+                break;
+            case MARK_START_TIME:
+                result.setMarkStartTimeNum(warnNum);
+                result.setMarkStartTimeRatio(ratio);
+                break;
+            case MARK_END_TIME:
+                result.setMarkEndTimeNum(warnNum);
+                result.setMarkEndTimeRatio(ratio);
+                break;
+            }
+        }
+
+    }
+
+    private String getRatio(BigDecimal total, BigDecimal num) {
+        String ratio = "";
+        //计算占比
+        if (total.intValue() != 0) {
+            num = num.divide(total, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
+            NumberFormat formatter = NumberFormat.getPercentInstance();
+            formatter.setMinimumFractionDigits(2);
+            ratio = formatter.format(num.doubleValue() / 100);
+        }
+        return ratio;
+    }
+
+    private List<String> getWarnField() {
+        List<String> fieldList = new ArrayList<>();
+        WarnFieldEnum[] fieldEnums = WarnFieldEnum.values();
+        for (WarnFieldEnum fieldEnum : fieldEnums) {
+            fieldList.add(fieldEnum.getTitle());
+        }
+        return fieldList;
+    }
+}

+ 10 - 1
sop-business/src/main/resources/mapper/ServiceUnitAnalyseMapper.xml

@@ -70,7 +70,8 @@
         tbcd.id AS crmDetailId,
         tbcd.id AS crmDetailId,
         IF ( sc.type = 'OFFICE', '教务处', '研究生' ) AS customManagerTypeStr,
         IF ( sc.type = 'OFFICE', '教务处', '研究生' ) AS customManagerTypeStr,
         cast( tfcfe.flow_id AS CHAR ) AS flowId,
         cast( tfcfe.flow_id AS CHAR ) AS flowId,
-        tbsi.update_time AS updateTime
+        tbsi.update_time AS updateTime,
+        tbdw.field_obj AS fieldObj
         FROM
         FROM
         t_b_sop_info tbsi
         t_b_sop_info tbsi
         LEFT JOIN t_b_crm tbc ON tbc.crm_no = tbsi.crm_no
         LEFT JOIN t_b_crm tbc ON tbc.crm_no = tbsi.crm_no
@@ -83,6 +84,7 @@
         LEFT JOIN t_f_custom_flow tfcf ON tfcf.id = tfcfe.t_f_custom_flow_id
         LEFT JOIN t_f_custom_flow tfcf ON tfcf.id = tfcfe.t_f_custom_flow_id
         LEFT JOIN t_b_crm_detail tbcd ON tbcd.sop_no = tbsi.sop_no
         LEFT JOIN t_b_crm_detail tbcd ON tbcd.sop_no = tbsi.sop_no
         LEFT JOIN sys_user su3 ON su3.id = tbc.lead_id
         LEFT JOIN sys_user su3 ON su3.id = tbc.lead_id
+        LEFT JOIN t_b_delay_warn tbdw on tbdw.crm_no=tbc.crm_no and tbdw.sop_no=tbcd.sop_no
         <where>
         <where>
             <if test="serviceUnitId != null">
             <if test="serviceUnitId != null">
                 AND tbsi.service_id=#{serviceUnitId}
                 AND tbsi.service_id=#{serviceUnitId}
@@ -99,6 +101,13 @@
             <if test="province != null and province != '' ">
             <if test="province != null and province != '' ">
                 AND sc.province=#{province}
                 AND sc.province=#{province}
             </if>
             </if>
+             <!-- 预警字段 -->
+            <if test="type != null and type != '' ">
+                AND tbdw.field_obj is not null
+            </if>
+            <if test="fieldObj != null and fieldObj != '' ">
+                AND tbdw.field_obj = #{fieldObj}
+            </if>
 
 
             <if test="process != null">
             <if test="process != null">
                 <choose>
                 <choose>

+ 25 - 0
sop-business/src/main/resources/mapper/SopWarnMonitorMapper.xml

@@ -0,0 +1,25 @@
+<?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.qmth.sop.business.mapper.SopWarnMonitorMapper">
+
+    <select id="listDelayWarn" resultType="com.qmth.sop.business.bean.result.SopWarnMonitorDetailResult">
+        SELECT
+        tbdw.crm_no AS crmNo,
+        tbdw.sop_no AS sopNo,
+        tbdw.field_obj AS fieldObj,
+        tbc.lead_id AS leadId,
+        su.real_name AS leadName
+        FROM
+        t_b_delay_warn tbdw
+        LEFT JOIN t_b_crm tbc ON tbdw.crm_no = tbc.crm_no
+        LEFT JOIN sys_user su ON su.id = tbc.lead_id
+        WHERE
+        tbdw.service_id = #{serviceUnitId}
+        <if test="warnFieldList != null and warnFieldList.size() > 0">
+            AND tbdw.field_obj IN
+            <foreach collection="warnFieldList" item="item" index="index" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+        </if>
+    </select>
+</mapper>

+ 2 - 0
sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

@@ -447,6 +447,8 @@ public class SystemConstant {
 
 
     public static final String PREFIX_URL_RESOURCE_SECURITY = "/admin/resource/security";
     public static final String PREFIX_URL_RESOURCE_SECURITY = "/admin/resource/security";
 
 
+    public static final String PREFIX_URL_SOP_WARN_MONITOR = "/admin/sop/warn/monitor";
+
     /**
     /**
      * 缓存配置
      * 缓存配置
      */
      */

+ 33 - 0
sop-common/src/main/java/com/qmth/sop/common/enums/WarnFieldEnum.java

@@ -0,0 +1,33 @@
+package com.qmth.sop.common.enums;
+
+/**
+ * @Description 预警字段
+ * @Author haoguanghui
+ * @date 2024/09/14
+ */
+public enum WarnFieldEnum {
+    SCAN_START_TIME("scan_start_time", "扫描开始时间"),
+
+    SCAN_END_TIME("scan_end_time", "扫描结束时间"),
+
+    MARK_START_TIME("mark_start_time", "评卷开始时间"),
+
+    MARK_END_TIME("mark_end_time", "评卷结束时间");
+
+    private String title;
+
+    private String desc;
+
+    WarnFieldEnum(String title, String desc) {
+        this.title = title;
+        this.desc = desc;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}