zxl
2025-10-29 fea22e82e7e49691f6e0c20a29b228d0ab3173e9
修改问题
12个文件已修改
7个文件已添加
1053 ■■■■ 已修改文件
ycl-pojo/src/main/java/com/ycl/platform/domain/dto/MonitorConstructionDTO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/DemeritRecord.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/MonitorConstruction.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/vo/TMonitorVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/vo/screen/DemeritRecordVO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/controller/MonitorConstructionController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/mapper/IMonitorConstructionMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/IMonitorConstructionService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/CheckScoreServiceImpl.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/IMonitorConstructionServiceImpl.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/DemeritRecordTask.java 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/task/UYTask.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/DemeritREcordMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/IMonitorConstructionMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml 120 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/dto/MonitorConstructionDTO.java
New file
@@ -0,0 +1,22 @@
package com.ycl.platform.domain.dto;
import annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
/**
 * zgyw
 *
 * @author : zxl
 * @date : 2025-10-20 14:20
 **/
@Data
public class MonitorConstructionDTO {
    @Excel(name = "设备编码")
    private String serialNumber;
    @Excel(name = "建设类型标签")
    private String tag;
}
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/DemeritRecord.java
@@ -8,6 +8,7 @@
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
 * zgyw
@@ -27,4 +28,8 @@
    @TableField("construction_type")
    private String constructionType;
    //录像计算生成时间
    @TableField("record_time")
    private Date recordTime;
}
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/MonitorConstruction.java
New file
@@ -0,0 +1,32 @@
package com.ycl.platform.domain.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ycl.platform.base.AbsEntity;
import com.ycl.system.entity.BaseEntity;
import lombok.Data;
/**
 * zgyw
 *
 * @author : zxl
 * @date : 2025-10-20 11:37
 **/
@Data
@TableName("t_monitor_construction")
public class MonitorConstruction extends AbsEntity {
    /**
     * 设备编号
     */
    @TableField(value = "serial_number")
    private String serialNumber;
    /**
     * 设备标签json字符串
     */
    @TableField(value = "tag")
    private String tag;
}
ycl-pojo/src/main/java/com/ycl/platform/domain/vo/TMonitorVO.java
@@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ycl.system.entity.BaseEntity;
import lombok.Data;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.time.LocalDate;
@@ -342,4 +343,10 @@
     * 设备厂商: 0海康  1大华  2宇视
     */
    private Integer deviceType;
    List<String> ids;
    /**
     * 建设类型标签
     */
    private String tag;
}
ycl-pojo/src/main/java/com/ycl/platform/domain/vo/screen/DemeritRecordVO.java
@@ -1,9 +1,11 @@
package com.ycl.platform.domain.vo.screen;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ycl.platform.base.AbsVo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
 * zgyw
@@ -33,4 +35,8 @@
     */
    private BigDecimal demerit;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date recordTime;
}
ycl-server/src/main/java/com/ycl/platform/controller/MonitorConstructionController.java
New file
@@ -0,0 +1,35 @@
package com.ycl.platform.controller;
import com.ycl.platform.service.IMonitorConstructionService;
import com.ycl.system.Result;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
 * zgyw
 *
 * @author : zxl
 * @date : 2025-10-20 13:55
 **/
@RestController
@RequestMapping("/monitorConstruction")
@RequiredArgsConstructor
public class MonitorConstructionController {
    private final IMonitorConstructionService monitorConstructionService;
    @PostMapping("/import")
    public Result importExcel(@RequestBody MultipartFile file) {
        return monitorConstructionService.importExcel(file);
    }
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse httpServletResponse) {
        monitorConstructionService.getImportTemplate(httpServletResponse);
    }
}
ycl-server/src/main/java/com/ycl/platform/controller/TMonitorController.java
@@ -39,7 +39,7 @@
    @GetMapping("/list")
    public TableDataInfo list(TMonitorVO tMonitor)
    {
        startPage();
        List<TMonitorVO> list = tMonitorService.selectTMonitorList(tMonitor);
        return getDataTable(list);
    }
ycl-server/src/main/java/com/ycl/platform/mapper/IMonitorConstructionMapper.java
New file
@@ -0,0 +1,14 @@
package com.ycl.platform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ycl.platform.domain.entity.MonitorConstruction;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface IMonitorConstructionMapper extends BaseMapper<MonitorConstruction> {
    int insertBatch(@Param("list") List<MonitorConstruction> list);
}
ycl-server/src/main/java/com/ycl/platform/mapper/TMonitorMapper.java
@@ -45,7 +45,7 @@
     * @return 设备资产集合
     */
    public List<TMonitorVO> selectTMonitorList(TMonitorVO tMonitor);
    public List<TMonitorVO> selectTMonitorListAndIds(TMonitorVO tMonitor);
    /**
     * 查询设备资产列表
     *
ycl-server/src/main/java/com/ycl/platform/service/IMonitorConstructionService.java
New file
@@ -0,0 +1,29 @@
package com.ycl.platform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ycl.platform.domain.entity.MonitorConstruction;
import com.ycl.system.Result;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface IMonitorConstructionService extends IService<MonitorConstruction> {
    /**
     * 导入设备标签
     * @param file
     * @return
     */
    Result importExcel(MultipartFile file);
    /**
     * 导出设备模板
     * @return
     */
    void getImportTemplate(HttpServletResponse httpServletResponse);
    List<MonitorConstruction> getSerialNumberListByConstructionType(String constructionType);
}
ycl-server/src/main/java/com/ycl/platform/service/impl/CheckScoreServiceImpl.java
@@ -565,21 +565,21 @@
    //大屏展示考核得分
    @Override
    public Map<String, Map<String, Object>> dashboard(DashboardQuery dashboardQuery) {
//        Date now = new Date();
        Date now = new Date();
        Calendar cal = Calendar.getInstance();
// 2. 设置为今年10月12号 00:00:00(清除时分秒,避免当前时间干扰)
        cal.set(Calendar.MONTH, Calendar.OCTOBER);  // 10月(用常量更直观,避免记0基)
// cal.set(Calendar.MONTH, 9);  // 也可以用数字9(不推荐,可读性差)
        cal.set(Calendar.DAY_OF_MONTH, 12);         // 日期设为12号
        cal.set(Calendar.HOUR_OF_DAY, 12);           // 小时设为0(24小时制)
        cal.set(Calendar.MINUTE, 0);                // 分钟设为0
        cal.set(Calendar.SECOND, 0);                // 秒设为0
        cal.set(Calendar.MILLISECOND, 0);           // 毫秒设为0
// 3. 转成Date对象
        Date now = cal.getTime();
//        Calendar cal = Calendar.getInstance();
//
//// 2. 设置为今年10月12号 00:00:00(清除时分秒,避免当前时间干扰)
//        cal.set(Calendar.MONTH, Calendar.OCTOBER);  // 10月(用常量更直观,避免记0基)
//// cal.set(Calendar.MONTH, 9);  // 也可以用数字9(不推荐,可读性差)
//        cal.set(Calendar.DAY_OF_MONTH, 12);         // 日期设为12号
//        cal.set(Calendar.HOUR_OF_DAY, 12);           // 小时设为0(24小时制)
//        cal.set(Calendar.MINUTE, 0);                // 分钟设为0
//        cal.set(Calendar.SECOND, 0);                // 秒设为0
//        cal.set(Calendar.MILLISECOND, 0);           // 毫秒设为0
//
//// 3. 转成Date对象
//        Date now = cal.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ycl-server/src/main/java/com/ycl/platform/service/impl/IMonitorConstructionServiceImpl.java
New file
@@ -0,0 +1,142 @@
package com.ycl.platform.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ycl.platform.domain.dto.MonitorConstructionDTO;
import com.ycl.platform.domain.dto.ReportImportDTO;
import com.ycl.platform.domain.entity.MonitorConstruction;
import com.ycl.platform.mapper.IMonitorConstructionMapper;
import com.ycl.platform.service.IMonitorConstructionService;
import com.ycl.system.Result;
import com.ycl.utils.StringUtils;
import com.ycl.utils.poi.ExcelUtil;
import enumeration.ConstructionTypeEnum;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * zgyw
 *
 * @author : zxl
 * @date : 2025-10-20 13:58
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class IMonitorConstructionServiceImpl extends ServiceImpl<IMonitorConstructionMapper, MonitorConstruction>
        implements IMonitorConstructionService {
    private final IMonitorConstructionMapper monitorConstructionMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result importExcel(MultipartFile file) {
        log.info("进入导入逻辑");
        ExcelUtil<MonitorConstructionDTO> excelUtil = new ExcelUtil<>(MonitorConstructionDTO.class);
        List<MonitorConstructionDTO> list = null;
        List<MonitorConstructionDTO> distinctList = null;
        try {
            list = excelUtil.importExcel(file.getInputStream());
            distinctList = list.stream()
                    .filter(Objects::nonNull)//过滤掉null的对象
                    .filter(dto -> dto.getSerialNumber() != null)//过滤掉 getSerialNumber为null的对象
                    .collect(Collectors.toMap(
                            MonitorConstructionDTO::getSerialNumber,
                            dto -> dto,
                            (existing, replacement) -> existing
                    ))
                    .values()
                    .stream()
                    .collect(Collectors.toList());
        } catch (IOException e) {
            log.error("请检查导入excel表格内容");
            throw new RuntimeException("请检查导入excel表格内容");
        }
        List<MonitorConstruction> data = new ArrayList<>();
        for (MonitorConstructionDTO dto : distinctList) {
            MonitorConstruction monitorConstruction = new MonitorConstruction();
            monitorConstruction.setSerialNumber(dto.getSerialNumber());
            monitorConstruction.setTag(dto.getTag());
            data.add(monitorConstruction);
        }
        List<String> serialNumbers = data.stream()
                .map(MonitorConstruction::getSerialNumber)
                .collect(Collectors.toList());
        //删除已存在的设备对应标签
        if (CollectionUtils.isNotEmpty(serialNumbers)) {
            log.info("删除标签数据行数:{}",serialNumbers.size());
            QueryWrapper<MonitorConstruction> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("serial_number", serialNumbers);
            queryWrapper.eq("deleted",false);
            baseMapper.delete(queryWrapper);
        }
        if (CollectionUtils.isNotEmpty(data)) {
            //插入标签表中
            log.info("插入标签数据行数:{}",data.size());
            saveBatch(data);
        }
        return Result.ok();
    }
    @Override
    public void getImportTemplate(HttpServletResponse httpServletResponse){
        ExcelUtil<MonitorConstructionDTO> excelUtil = new ExcelUtil<>(MonitorConstructionDTO.class);
        excelUtil.exportExcel(httpServletResponse, null, "设备标签模板");
    }
    @Override
    public List<MonitorConstruction> getSerialNumberListByConstructionType(String constructionType) {
        List<MonitorConstruction> list = new ArrayList<>();
        if (ConstructionTypeEnum.PHASE_ONE_TWO.name().equals(constructionType)){
            //一二期
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.PHASE_ONE_TWO.getDesc())
                    .list();
        }else if (ConstructionTypeEnum.PHASE_THREE.name().equals(constructionType)){
            //三期
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.PHASE_THREE.getDesc())
                    .list();
        }else if (ConstructionTypeEnum.PHASE_FOURTH.name().equals(constructionType)){
            //四期人脸
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.PHASE_FOURTH.getDesc())
                    .list();
        }else if (ConstructionTypeEnum.EASTERN_NEW_CITY.name().equals(constructionType)){
            //东部新城
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.EASTERN_NEW_CITY.getDesc())
                    .list();
        }else if (ConstructionTypeEnum.CHECK_ENTER_SICHUAN.name().equals(constructionType)){
            //入川即检
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.CHECK_ENTER_SICHUAN.getDesc())
                    .list();
        }else if (ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.name().equals(constructionType)){
            //沿滩二期人脸
            list = new LambdaQueryChainWrapper<>(baseMapper).eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                    .eq(MonitorConstruction::getTag, ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.getDesc())
                    .list();
        }
        return list;
    }
}
ycl-server/src/main/java/com/ycl/platform/service/impl/TMonitorServiceImpl.java
@@ -6,6 +6,7 @@
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.ycl.platform.domain.entity.MonitorConstruction;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.excel.*;
import com.ycl.platform.domain.form.VideoExportForm;
@@ -31,6 +32,7 @@
import com.ycl.platform.mapper.TMonitorMapper;
import com.ycl.platform.mapper.WorkOrderMapper;
import com.ycl.platform.mapper.YwPointMapper;
import com.ycl.platform.service.IMonitorConstructionService;
import com.ycl.platform.service.ITMonitorService;
import com.ycl.system.Result;
import com.ycl.system.entity.SysDictData;
@@ -74,6 +76,8 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.ycl.utils.PageUtils.startPage;
/**
 * 设备资产Service业务层处理
 *
@@ -99,7 +103,8 @@
    private DynamicColumnMapper dynamicColumnMapper;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private IMonitorConstructionService monitorConstructionService;
    /**
     * 查询设备资产
     *
@@ -129,156 +134,173 @@
            }
            tMonitor.setTime(time);
        }
        List<TMonitorVO> monitors = tMonitorMapper.selectTMonitorList(tMonitor);
        // 异常恢复监控
        if (Objects.equals(tMonitor.getRecovery(), 1L)) {
            //工单号
            List<String> orders = monitors.stream().map(TMonitorVO::getWorkOrderNo).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(orders)) {
        List<TMonitorVO> monitors = new ArrayList<>();
        if (StringUtils.isNotBlank(tMonitor.getConstructionType())){
            List<MonitorConstruction> list =
                    monitorConstructionService.getSerialNumberListByConstructionType(tMonitor.getConstructionType());
            log.info("打印查询设备标签数:{},建设类型标签:{}",list.size(), tMonitor.getConstructionType() );
            //获得设备编号集合 通过建设类型标签
            if(!CollectionUtils.isEmpty(list)){
                tMonitor.setIds(
                        list.stream().map(MonitorConstruction::getSerialNumber).collect(Collectors.toList()));
                startPage();
                monitors = tMonitorMapper.selectTMonitorListAndIds(tMonitor);
            }
        }else{
            startPage();
            monitors = tMonitorMapper.selectTMonitorList(tMonitor);
        }
            // 异常恢复监控
            if (Objects.equals(tMonitor.getRecovery(), 1L)) {
                //工单号
                List<String> orders = monitors.stream().map(TMonitorVO::getWorkOrderNo).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(orders)) {
                    return monitors;
                }
                List<WorkOrderVO> voList = workOrderMapper.getRecoveryInfo(orders);
                for (TMonitorVO monitor : monitors) {
                    if (!CollectionUtils.isEmpty(voList)) {
                        for (WorkOrderVO workOrderVO : voList) {
                            if (monitor.getWorkOrderNo() != null && monitor.getWorkOrderNo().equals(workOrderVO.getWorkOrderNo())) {
                                monitor.setUnitContact(workOrderVO.getUnitContact());
                                monitor.setUnitContactPhone(workOrderVO.getUnitContactPhone());
                                monitor.setYwPeopleName(workOrderVO.getYwPeopleName());
                                monitor.setErrorType(workOrderVO.getErrorType());
                            }
                        }
                    }
                }
                return monitors;
            }
            List<WorkOrderVO> voList = workOrderMapper.getRecoveryInfo(orders);
            for (TMonitorVO monitor : monitors) {
                if (!CollectionUtils.isEmpty(voList)) {
                    for (WorkOrderVO workOrderVO : voList) {
                        if (monitor.getWorkOrderNo() != null && monitor.getWorkOrderNo().equals(workOrderVO.getWorkOrderNo())) {
                            monitor.setUnitContact(workOrderVO.getUnitContact());
                            monitor.setUnitContactPhone(workOrderVO.getUnitContactPhone());
                            monitor.setYwPeopleName(workOrderVO.getYwPeopleName());
                            monitor.setErrorType(workOrderVO.getErrorType());
            //设备编号
            List<String> numbers = monitors.stream().map(TMonitorVO::getSerialNumber).collect(Collectors.toList());
            Query query = new Query();
            Date now = new Date();
            query.addCriteria(Criteria.where("no").in(numbers)
                    .and("mongoCreateTime").gte(DateUtils.getDayStart(now)).lt(DateUtils.getDayEnd(now))
            );
            //一机一档信息
            List<MonitorQualifyResult> monitorQualifyResults = mongoTemplate.find(query, MonitorQualifyResult.class);
            // 视频监控设备
            if (Objects.equals(tMonitor.getCameraFunType(), "1")) {
                //OSD信息
                List<OsdCheckResult> osdCheckResults = mongoTemplate.find(query, OsdCheckResult.class);
                //录像可用信息
                List<RecordMetaDSumResult> videoResults = mongoTemplate.find(query, RecordMetaDSumResult.class);
                for (TMonitorVO monitor : monitors) {
                    monitor.setMongoCreateTime(now);
                    //一机一档
                    setOneFile(monitorQualifyResults, monitor);
                    //录像
                    if (!CollectionUtils.isEmpty(videoResults)) {
                        for (RecordMetaDSumResult videoResult : videoResults) {
                            if (monitor.getSerialNumber().equals(videoResult.getNo())) {
                                monitor.setVideoComplete(videoResult.getRecordStatus());
                                monitor.setVideoLoseTime(videoResult.getMissDuration());
                            }
                        }
                    }
                    //OSD
                    if (!CollectionUtils.isEmpty(osdCheckResults)) {
                        for (OsdCheckResult osdCheckResult : osdCheckResults) {
                            if (monitor.getSerialNumber().equals(osdCheckResult.getNo())) {
                                monitor.setOSD(OsdCheckResult.checkOsd(osdCheckResult));
                                monitor.setOSDTime(OsdCheckResult.checkTime(osdCheckResult));
                            }
                        }
                    }
                }
            }
            return monitors;
        }
        //设备编号
        List<String> numbers = monitors.stream().map(TMonitorVO::getSerialNumber).collect(Collectors.toList());
        Query query = new Query();
        Date now = new Date();
        query.addCriteria(Criteria.where("no").in(numbers)
                .and("mongoCreateTime").gte(DateUtils.getDayStart(now)).lt(DateUtils.getDayEnd(now))
        );
        //一机一档信息
        List<MonitorQualifyResult> monitorQualifyResults = mongoTemplate.find(query, MonitorQualifyResult.class);
        // 视频监控设备
        if (Objects.equals(tMonitor.getCameraFunType(), "1")) {
            //OSD信息
            List<OsdCheckResult> osdCheckResults = mongoTemplate.find(query, OsdCheckResult.class);
            //录像可用信息
            List<RecordMetaDSumResult> videoResults = mongoTemplate.find(query, RecordMetaDSumResult.class);
            for (TMonitorVO monitor : monitors) {
                monitor.setMongoCreateTime(now);
                //一机一档
                setOneFile(monitorQualifyResults, monitor);
                //录像
                if (!CollectionUtils.isEmpty(videoResults)) {
                    for (RecordMetaDSumResult videoResult : videoResults) {
                        if (monitor.getSerialNumber().equals(videoResult.getNo())) {
                            monitor.setVideoComplete(videoResult.getRecordStatus());
                            monitor.setVideoLoseTime(videoResult.getMissDuration());
                        }
                    }
                }
                //OSD
                if (!CollectionUtils.isEmpty(osdCheckResults)) {
                    for (OsdCheckResult osdCheckResult : osdCheckResults) {
                        if (monitor.getSerialNumber().equals(osdCheckResult.getNo())) {
                            monitor.setOSD(OsdCheckResult.checkOsd(osdCheckResult));
                            monitor.setOSDTime(OsdCheckResult.checkTime(osdCheckResult));
                        }
                    }
                }
            }
        }
        // 车辆监控设备
        if (Objects.equals(tMonitor.getCameraFunType(), "2")) {
            //属性一致率、大图
            List<VehicleDeviceSamplingResult> sampleResults = mongoTemplate.find(query, VehicleDeviceSamplingResult.class);
            List<PicAccessResult> picAccessResults = mongoTemplate.find(query, PicAccessResult.class);
            //抓拍量、时钟、上传
            List<VehicleDeviceInspectionResult> inspectResults = mongoTemplate.find(query, VehicleDeviceInspectionResult.class);
            for (TMonitorVO monitor : monitors) {
                monitor.setMongoCreateTime(now);
                //一机一档
                setOneFile(monitorQualifyResults, monitor);
                //url
                if (!CollectionUtils.isEmpty(sampleResults)) {
                    for (PicAccessResult picAccessResult : picAccessResults) {
                        if (monitor.getSerialNumber().equals(picAccessResult.getNo())) {
                            BigDecimal bigDecimal = PicAccessResult.calUrl(picAccessResult);
                            monitor.setUrlPercent(bigDecimal);
                        }
                    }
                }
            // 车辆监控设备
            if (Objects.equals(tMonitor.getCameraFunType(), "2")) {
                //属性一致率、大图
                if (!CollectionUtils.isEmpty(sampleResults)) {
                    for (VehicleDeviceSamplingResult sampleResult : sampleResults) {
                        if (monitor.getSerialNumber().equals(sampleResult.getNo())) {
                            if (sampleResult.getBigUseful() != null) {
                                monitor.setBigUsefulPercent(sampleResult.getBigUseful().getBigUsefulPercent());
                            }
                            if (sampleResult.getVehDiff() != null) {
                                monitor.setImportantConPercent(sampleResult.getVehDiff().getImportantConPercent());
                                monitor.setMajorConPercent(sampleResult.getVehDiff().getMajorConPercent());
                            }
                        }
                    }
                }
                List<VehicleDeviceSamplingResult> sampleResults = mongoTemplate.find(query, VehicleDeviceSamplingResult.class);
                List<PicAccessResult> picAccessResults = mongoTemplate.find(query, PicAccessResult.class);
                //抓拍量、时钟、上传
                if (!CollectionUtils.isEmpty(inspectResults)) {
                    for (VehicleDeviceInspectionResult inspectResult : inspectResults) {
                        if (monitor.getSerialNumber().equals(inspectResult.getNo())) {
                            monitor.setSnapResult(inspectResult.getSnapResult());
                            monitor.setSnapCount(inspectResult.getDataCount());
                            if (inspectResult.getSnapClock() != null)
                                monitor.setClockPercent(inspectResult.getSnapClock().getClockPercent());
                            if (inspectResult.getSnapTimely() != null)
                                monitor.setUploadPercent(inspectResult.getSnapTimely().getTimelyPercent());
                        }
                    }
                }
            }
        }
        // 人脸监控设备
        if (Objects.equals(tMonitor.getCameraFunType(), "3")) {
            //人脸合格、大图、url访问异常
            List<FaceDeviceSamplingResult> sampleResults = mongoTemplate.find(query, FaceDeviceSamplingResult.class);
            //抓拍量、时钟、上传
            List<FaceDeviceInspectionResult> inspectResults = mongoTemplate.find(query, FaceDeviceInspectionResult.class);
            for (TMonitorVO monitor : monitors) {
                monitor.setMongoCreateTime(now);
                //一机一档
                setOneFile(monitorQualifyResults, monitor);
                //人脸合格、大图
                if (!CollectionUtils.isEmpty(sampleResults)) {
                    for (FaceDeviceSamplingResult sampleResult : sampleResults) {
                        if (monitor.getSerialNumber().equals(sampleResult.getNo())) {
                            if (sampleResult.getBigUseful() != null) {
                                monitor.setBigUsefulPercent(sampleResult.getBigUseful().getBigUsefulPercent());
                List<VehicleDeviceInspectionResult> inspectResults = mongoTemplate.find(query, VehicleDeviceInspectionResult.class);
                for (TMonitorVO monitor : monitors) {
                    monitor.setMongoCreateTime(now);
                    //一机一档
                    setOneFile(monitorQualifyResults, monitor);
                    //url
                    if (!CollectionUtils.isEmpty(sampleResults)) {
                        for (PicAccessResult picAccessResult : picAccessResults) {
                            if (monitor.getSerialNumber().equals(picAccessResult.getNo())) {
                                BigDecimal bigDecimal = PicAccessResult.calUrl(picAccessResult);
                                monitor.setUrlPercent(bigDecimal);
                            }
                            if (sampleResult.getFaceEligibility() != null)
                                monitor.setFacePercent(sampleResult.getFaceEligibility().getFaceEligPercent());
                        }
                    }
                }
                //抓拍量、时钟、上传、建模失败率
                if (!CollectionUtils.isEmpty(inspectResults)) {
                    for (FaceDeviceInspectionResult inspectResult : inspectResults) {
                        if (monitor.getSerialNumber().equals(inspectResult.getNo())) {
                            monitor.setSnapResult(inspectResult.getSnapResult());
                            monitor.setSnapCount(inspectResult.getDataCount());
                            if (inspectResult.getSnapClock() != null)
                                monitor.setClockPercent(inspectResult.getSnapClock().getClockPercent());
                            if (inspectResult.getSnapTimely() != null)
                                monitor.setUploadPercent(inspectResult.getSnapTimely().getTimelyPercent());
                            if (inspectResult.getSnapValidity() != null)
                                monitor.setFailPercent(inspectResult.getSnapValidity().getFailPercent());
                    //属性一致率、大图
                    if (!CollectionUtils.isEmpty(sampleResults)) {
                        for (VehicleDeviceSamplingResult sampleResult : sampleResults) {
                            if (monitor.getSerialNumber().equals(sampleResult.getNo())) {
                                if (sampleResult.getBigUseful() != null) {
                                    monitor.setBigUsefulPercent(sampleResult.getBigUseful().getBigUsefulPercent());
                                }
                                if (sampleResult.getVehDiff() != null) {
                                    monitor.setImportantConPercent(sampleResult.getVehDiff().getImportantConPercent());
                                    monitor.setMajorConPercent(sampleResult.getVehDiff().getMajorConPercent());
                                }
                            }
                        }
                    }
                    //抓拍量、时钟、上传
                    if (!CollectionUtils.isEmpty(inspectResults)) {
                        for (VehicleDeviceInspectionResult inspectResult : inspectResults) {
                            if (monitor.getSerialNumber().equals(inspectResult.getNo())) {
                                monitor.setSnapResult(inspectResult.getSnapResult());
                                monitor.setSnapCount(inspectResult.getDataCount());
                                if (inspectResult.getSnapClock() != null)
                                    monitor.setClockPercent(inspectResult.getSnapClock().getClockPercent());
                                if (inspectResult.getSnapTimely() != null)
                                    monitor.setUploadPercent(inspectResult.getSnapTimely().getTimelyPercent());
                            }
                        }
                    }
                }
            }
        }
            // 人脸监控设备
            if (Objects.equals(tMonitor.getCameraFunType(), "3")) {
                //人脸合格、大图、url访问异常
                List<FaceDeviceSamplingResult> sampleResults = mongoTemplate.find(query, FaceDeviceSamplingResult.class);
                //抓拍量、时钟、上传
                List<FaceDeviceInspectionResult> inspectResults = mongoTemplate.find(query, FaceDeviceInspectionResult.class);
                for (TMonitorVO monitor : monitors) {
                    monitor.setMongoCreateTime(now);
                    //一机一档
                    setOneFile(monitorQualifyResults, monitor);
                    //人脸合格、大图
                    if (!CollectionUtils.isEmpty(sampleResults)) {
                        for (FaceDeviceSamplingResult sampleResult : sampleResults) {
                            if (monitor.getSerialNumber().equals(sampleResult.getNo())) {
                                if (sampleResult.getBigUseful() != null) {
                                    monitor.setBigUsefulPercent(sampleResult.getBigUseful().getBigUsefulPercent());
                                }
                                if (sampleResult.getFaceEligibility() != null)
                                    monitor.setFacePercent(sampleResult.getFaceEligibility().getFaceEligPercent());
                            }
                        }
                    }
                    //抓拍量、时钟、上传、建模失败率
                    if (!CollectionUtils.isEmpty(inspectResults)) {
                        for (FaceDeviceInspectionResult inspectResult : inspectResults) {
                            if (monitor.getSerialNumber().equals(inspectResult.getNo())) {
                                monitor.setSnapResult(inspectResult.getSnapResult());
                                monitor.setSnapCount(inspectResult.getDataCount());
                                if (inspectResult.getSnapClock() != null)
                                    monitor.setClockPercent(inspectResult.getSnapClock().getClockPercent());
                                if (inspectResult.getSnapTimely() != null)
                                    monitor.setUploadPercent(inspectResult.getSnapTimely().getTimelyPercent());
                                if (inspectResult.getSnapValidity() != null)
                                    monitor.setFailPercent(inspectResult.getSnapValidity().getFailPercent());
                            }
                        }
                    }
                }
            }
        return monitors;
    }
@@ -346,6 +368,13 @@
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public Map<String, String> getVideoCount(TMonitorVO tMonitor) {
        List<MonitorConstruction> list =
                monitorConstructionService.getSerialNumberListByConstructionType(tMonitor.getConstructionType());
        //获得设备编号集合 通过建设类型标签
        tMonitor.setIds(
                list.stream().map(MonitorConstruction::getSerialNumber).collect(Collectors.toList()));
        return tMonitorMapper.getVideoCount(tMonitor);
    }
@@ -556,8 +585,6 @@
        ExcelUtilManySheet<List<ExcelExp>> util = new ExcelUtilManySheet<>(mysheet);
        util.exportExcelManySheet(response, mysheet);
    }
    /**
     * 导出每日在线数据
     */
@@ -578,9 +605,34 @@
        // 使用线程安全的List,预先指定容量
        List<ExcelExp> mysheet = Collections.synchronizedList(new ArrayList<>());
        VideoExportForm.convertTags(exportForm);
        Query query = getQuery(exportForm);
        Query query = getQuery(exportForm);//装配条件
        // 月份每日在线数据
        List<TMonitorResult> onlineResult = mongoTemplate.find(query, TMonitorResult.class);
        log.info("大小:{}",onlineResult.size());
        //此处需要过滤掉设备全景在线 细节不在线的情况  可以按 point分组 分我许多组之后再做处理
        Map<String, List<TMonitorResult>> ipToDevices = onlineResult.stream()
                .collect(Collectors.groupingBy(TMonitorResult::getIp));
//        onlineResult = ipToDevices.values().stream()
//                .map(devices -> {
//                    // 检查分组中是否有 online = true 的设备
//                    List<TMonitorResult> onlineDevices = devices.stream()
//                            .filter(monitor -> monitor.getOnline() == 1) // 假设online字段的getter是isOnline()
//                            .collect(Collectors.toList());
//
//                    if (!onlineDevices.isEmpty()) {
//                        // 若存在online=true的设备,只保留第一个(或取任意一个,按需调整)
//                        return onlineDevices.get(0);
//                    } else {
//                        // 若全为online=false,只保留第一个
//                        return devices.get(0);
//                    }
//                })
//                .collect(Collectors.toList());
        log.info("月份在线数据:{}条数", onlineResult.size());
        // 使用Collectors.toMap去重,保留每个No的第一个遇到的元素
        Map<String, TMonitorResult> uniqueResultsMap = onlineResult.stream()
@@ -589,9 +641,14 @@
                        Function.identity(),  // valueMapper,直接使用对象本身
                        (existing, replacement) -> existing // mergeFunction,如果有重复,保留第一个
                ));
        // 将 Map 转换为 List
        List<TMonitorResult> tMonitorResults = new ArrayList<>(uniqueResultsMap.values());
        log.info("去重后大小:{}", tMonitorResults.size());
        // 获取动态列数据并构建缓存Map
        Map<Integer, List<DynamicColumnVO>> dynamicColumnMap = new HashMap<>();
        if (!tMonitorResults.isEmpty()) {
@@ -600,6 +657,8 @@
                    .map(TMonitorResult::getPointId)
                    .distinct() // 去重,减少数据库查询
                    .collect(Collectors.toList());
            //获取集合点位的补充列信息
            List<DynamicColumnVO> dynamics = dynamicColumnMapper.getDynamicsByIds("t_yw_point", pointIds);
            if (!CollectionUtils.isEmpty(dynamics)) {
@@ -631,6 +690,9 @@
            CompletableFuture<ExcelExp> future = CompletableFuture.supplyAsync(() -> {
                // 直接从预分组的Map中获取,避免每次过滤
                List<TMonitorResult> monitors = deptMonitorMap.getOrDefault(currentDeptId, Collections.emptyList());
                if (monitors.isEmpty()) {
                    return null;
                }
@@ -1458,6 +1520,22 @@
    @Override
    public void export(HttpServletResponse response, TMonitorVO tMonitor) {
        List<TMonitorExp> monitors = tMonitorMapper.exportTMonitorList(tMonitor);
        //过滤出设备建设类型
        if (StringUtils.isNotBlank(tMonitor.getConstructionType())){
            List<MonitorConstruction> list =
                    monitorConstructionService.getSerialNumberListByConstructionType(tMonitor.getConstructionType());
            //获得设备编号集合 通过建设类型标签
            List<String> serialNumberList = list.stream().map(MonitorConstruction::getSerialNumber).collect(Collectors.toList());
            monitors = monitors.stream()
                    .filter(result -> {
                        String sn = result.getSerialNumber();
                        // 任一字段非空且在集合中即可
                        return (sn != null && serialNumberList.contains(sn));
                    })
                    .collect(Collectors.toList());
        }
        //获取动态列数据
        List<Integer> pointIds = monitors.stream().map(TMonitorExp::getPointId).collect(Collectors.toList());
        List<DynamicColumnVO> dynamics = dynamicColumnMapper.getDynamicsByIds("t_yw_point", pointIds);
ycl-server/src/main/java/com/ycl/platform/service/impl/WorkOrderServiceImpl.java
@@ -1303,10 +1303,23 @@
        }
        // 是否报备
        boolean hasReport = new LambdaQueryChainWrapper<>(reportMapper)
                .eq(Report::getSerialNumber, workOrder.getSerialNumber())
                .exists();
        workOrder.setHasReport(hasReport);
        Date target = workOrder.getCreateTime();
        Report reports = new LambdaQueryChainWrapper<>(reportMapper)
                .eq(Report::getSerialNumber,workOrder.getWorkOrderNo())
                .eq(Report::getStatus,1)
                .orderByDesc(Report::getCreateTime)
                .last("LIMIT 1")
                .one();
        boolean isInRange = false;
        if (reports != null){
            Date start = reports.getBeginCreateTime();
            Date end = reports.getEndCreateTime();
            isInRange = target.after(start) || target.equals(start)  // target >= start
                    && target.before(end) || target.equals(end);
        }
        workOrder.setHasReport(isInRange);
        // 故障类型
        List<SysDictData> errorList = workOrderErrorTypeService.getBaseMapper().getErrorList(workOrder.getWorkOrderNo());
        List<String> errList = errorList.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
ycl-server/src/main/java/com/ycl/task/DemeritRecordTask.java
@@ -5,9 +5,11 @@
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.util.concurrent.AtomicDouble;
import com.ycl.platform.domain.entity.DemeritRecord;
import com.ycl.platform.domain.entity.MonitorConstruction;
import com.ycl.platform.domain.entity.Report;
import com.ycl.platform.domain.result.UY.RecordMetaDSumResult;
import com.ycl.platform.mapper.DemeritRecordMapper;
import com.ycl.platform.mapper.IMonitorConstructionMapper;
import com.ycl.platform.mapper.ReportMapper;
import com.ycl.platform.service.IDemeritRecordService;
import com.ycl.utils.DateUtils;
@@ -50,6 +52,8 @@
    private final ReportMapper reportMapper;
    private final IMonitorConstructionMapper monitorConstructionMapper;
    private static final ExecutorService executorService = new ThreadPoolExecutor(16,
            128,
            5000,
@@ -59,21 +63,12 @@
    );
    private final IDemeritRecordService demeritRecordService;
    // 提取公共过滤方法
    private Predicate<RecordMetaDSumResult> deviceNameStartsWith(String prefix) {
        return result -> result.getDeviceName() != null && result.getDeviceName().startsWith(prefix);
    }
    private Predicate<RecordMetaDSumResult> deviceNameStartsWithAny(String... prefixes) {
        return result -> result.getDeviceName() != null &&
                Arrays.stream(prefixes).anyMatch(prefix -> result.getDeviceName().startsWith(prefix));
    }
    private DemeritRecord buildDemeritRecord(String constructionType,BigDecimal demerit,Integer deptId) {
    private DemeritRecord buildDemeritRecord(String constructionType,BigDecimal demerit,Integer deptId,Date recordTime) {
        DemeritRecord record = new DemeritRecord();
        record.setConstructionType(constructionType);
        record.setDemerit(demerit);
        record.setDeptId(deptId);
        record.setRecordTime(recordTime);
        return record;
    }
    private BigDecimal calculateTotalDeduction(List<RecordMetaDSumResult> records) {
@@ -126,7 +121,7 @@
        log.info("日期:{},查询出的设备录像记录数{}",today,results.size());
        //过滤掉非全景的设备 且 1则为细节,如果是0则为全景
        results.stream().filter(obj ->
        results = results.stream().filter(obj ->
        {
            String deviceId = obj.getDeviceId();
            if (deviceId == null || deviceId.length() < 7) {
@@ -135,7 +130,7 @@
            // 获取倒数第七位的字符
            char seventhFromEnd = deviceId.charAt(deviceId.length() - 7);
            return seventhFromEnd != '1'; //为1 则会 false 去除掉
        });
        }).collect(Collectors.toList());
        log.info("过滤后剩余全景设备数{}",results.size());
        //只考核LT_、(三期)
@@ -143,28 +138,43 @@
        // DX_R、(四区人脸)
        // DX_RS、(四区人脸)
        // (需要排除DX_R2、DX_RD、J_、T1、T3以及没有前缀的设备)
        List<String> prefixes = Arrays.asList("LT_", "DX_", "DX_R", "DX_RS");
        results.stream()
//        List<String> prefixes = Arrays.asList("LT_", "DX_", "DX_R", "DX_RS");
        //查询设备标签表中的MonitorConstruction列表
        List<MonitorConstruction> monitorConstructionList = new LambdaQueryChainWrapper<>(monitorConstructionMapper)
                .eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                .list();
        List<String> serialNumberList = monitorConstructionList.stream()
                .map(MonitorConstruction::getSerialNumber).collect(Collectors.toList());
        //过滤获得包含了这些标签的设备录像情况集合
        results = results.stream()
                .filter(result -> {
                    String deviceName = result.getDeviceName();
                    if (deviceName == null) {
                        return false;
                    }
                    return prefixes.stream().anyMatch(deviceName::startsWith);
                    String sn = result.getNo();
                    // 任一字段非空且在集合中即可
                    return (sn != null && serialNumberList.contains(sn));
                })
                .collect(Collectors.toList());
        log.info("剩余考核设备过滤后设备数{}",results.size());
        //过滤掉报备的设备
        //查询在当前时间有报备的所有设备,
        //因为录像数据的时间
        List<String> deviceIds = new LambdaQueryChainWrapper<>(reportMapper)
        Date yesterday =new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(yesterday);
        calendar.add(Calendar.DAY_OF_YEAR, -1); // 减去1天 测试用
        yesterday = calendar.getTime();
        log.info("测试时间:{}",yesterday);
        List<Report> list = new LambdaQueryChainWrapper<>(reportMapper)
                .eq(Report::getStatus, 1)
                .ge(Report::getBeginCreateTime, today)
                .le(Report::getEndCreateTime, today)
                .list().stream()
                .ge(Report::getBeginCreateTime, DateUtils.getDayStart(yesterday))
                .le(Report::getEndCreateTime,  DateUtils.getDayEnd(yesterday))
                .list();
        log.info("报备记录:{}",list);
        List<String> deviceIds = list.stream()
                .collect(Collectors.toMap(
                        Report::getSerialNumber,  // key: serialNumber
                        Function.identity(),      // value: Report对象本身
@@ -177,7 +187,7 @@
        Set<String> deviceIdSet = new HashSet<>(deviceIds);
        log.info("报备设备数{}",deviceIdSet.size());
        results.stream()
        results = results.stream()
                .filter(result -> {
                    // 获取当前对象的deviceId
                    String resultDeviceId = result.getDeviceId();
@@ -202,6 +212,24 @@
        Map<String,List<RecordMetaDSumResult>> groupByArealayerno = results.stream()
                .collect(Collectors.groupingBy(RecordMetaDSumResult::getArealayerno));
        //按建设类型标签分组设备NO monitorConstructionList
        //按标签分组
        Map<String, List<String>> groupByTag = monitorConstructionList.stream()
                // 分组键:提取每个对象的 tag(注意处理 tag 为 null 的情况,避免键为 null)
                .collect(Collectors.groupingBy(
                        mc -> mc.getTag() != null ? mc.getTag() : "DEFAULT_TAG",
                        Collectors.mapping(MonitorConstruction::getSerialNumber, Collectors.toList())
                ));
        List<String> phaseOneTwoSerials = groupByTag.getOrDefault(ConstructionTypeEnum.PHASE_ONE_TWO.getDesc(), Collections.emptyList());
        List<String> phaseThreeSerials = groupByTag.getOrDefault(ConstructionTypeEnum.PHASE_THREE.getDesc(), Collections.emptyList());
        List<String> phaseFourthSerials = groupByTag.getOrDefault(ConstructionTypeEnum.PHASE_FOURTH.getDesc(), Collections.emptyList());
        List<String> checkEnterSichuan = groupByTag.getOrDefault(ConstructionTypeEnum.CHECK_ENTER_SICHUAN.getDesc(), Collections.emptyList());
        List<String> easternNewCity= groupByTag.getOrDefault(ConstructionTypeEnum.EASTERN_NEW_CITY.getDesc(), Collections.emptyList());
        List<String> yanTanPhaseTwoFace = groupByTag.getOrDefault(ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.getDesc(), Collections.emptyList());
        //循环分组后的map
        for (Map.Entry<String, List<RecordMetaDSumResult>> entry : groupByArealayerno.entrySet()) {
            String arealayerno = entry.getKey();
@@ -218,65 +246,62 @@
            if (CollectionUtils.isNotEmpty(resultList)) {
                // 对每个List进行处理 分建类型处理集合
                List<RecordMetaDSumResult> phase_one_two = resultList.stream()
                        .filter(deviceNameStartsWith("DX_"))
                        .filter(result -> {
                            String no = result.getNo();
                            return no != null && phaseOneTwoSerials.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("一二期考核记录数{}",phase_one_two.size());
                log.info("一二期考核记录数{}", phase_one_two.size());
                List<RecordMetaDSumResult> phase_three = resultList.stream()
                        .filter(deviceNameStartsWith("LT_"))
                        .filter(result -> {
                            String no = result.getNo();
                            return no != null && phaseThreeSerials.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("三期考核记录数{}",phase_three.size());
                log.info("三期考核记录数{}", phase_three.size());
                List<RecordMetaDSumResult> phase_fourth = resultList.stream()
                        .filter(deviceNameStartsWithAny("DX_R", "DX_RS"))
                        .filter(result -> {
                            String no = result.getNo();
                            return no != null && phaseFourthSerials.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("四期考核记录数{}",phase_fourth.size());
                if (CollectionUtils.isNotEmpty(phase_one_two)){
                    BigDecimal phaseOneTwoDeduction = calculateTotalDeduction(phase_one_two);
                    DemeritRecord demeritRecordPhaseOneTwo = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_ONE_TWO.name(),
                            phaseOneTwoDeduction,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(demeritRecordPhaseOneTwo);
                }else{
                    DemeritRecord phaseOneTwoDeduction = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_ONE_TWO.name(),
                            BigDecimal.ZERO,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(phaseOneTwoDeduction);
                }
                log.info("四期考核记录数{}", phase_fourth.size());
                List<RecordMetaDSumResult> check_enter_sichuan = resultList.stream()
                        .filter(result ->{
                            String no = result.getNo();
                            return  no != null && checkEnterSichuan.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("入川即检{}", check_enter_sichuan.size());
                if (CollectionUtils.isNotEmpty(phase_three)){
                    BigDecimal phaseThreeDeduction = calculateTotalDeduction(phase_three);
                    DemeritRecord demeritRecordPhaseThree = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_THREE.name(),
                            phaseThreeDeduction,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(demeritRecordPhaseThree);
                }else {
                    DemeritRecord phaseThreeDeduction = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_THREE.name(),
                            BigDecimal.ZERO,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(phaseThreeDeduction);
                }
                if (CollectionUtils.isNotEmpty(phase_fourth)){
                    BigDecimal phaseFourthDeduction = calculateTotalDeduction(phase_fourth);
                    DemeritRecord demeritRecordPhaseFourth = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_FOURTH.name(),
                            phaseFourthDeduction,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(demeritRecordPhaseFourth);
                }else{
                    DemeritRecord phaseFourthDeduction = buildDemeritRecord(
                            ConstructionTypeEnum.PHASE_FOURTH.name(),
                            BigDecimal.ZERO,
                            areaDeptEnum.getDeptId());
                    demeritRecords.add(phaseFourthDeduction);
                }
                List<RecordMetaDSumResult> eastern_new_city = resultList.stream()
                        .filter(result ->{
                            String no = result.getNo();
                            return  no != null && easternNewCity.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("东部新城{}", eastern_new_city.size());
                List<RecordMetaDSumResult> yan_tan_phase_two_face = resultList.stream()
                        .filter(result ->{
                            String no = result.getNo();
                            return  no != null && yanTanPhaseTwoFace.contains(no);
                        })
                        .collect(Collectors.toList());
                log.info("沿滩二期人脸{}", yan_tan_phase_two_face.size());
                //一二期
                buildAndAddDemeritRecords(phase_one_two, ConstructionTypeEnum.PHASE_ONE_TWO.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                //三期
                buildAndAddDemeritRecords(phase_three, ConstructionTypeEnum.PHASE_THREE.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                //四期
                buildAndAddDemeritRecords(phase_fourth, ConstructionTypeEnum.PHASE_FOURTH.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                //入川即检
                buildAndAddDemeritRecords(check_enter_sichuan, ConstructionTypeEnum.CHECK_ENTER_SICHUAN.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                //东部新城
                buildAndAddDemeritRecords(eastern_new_city, ConstructionTypeEnum.EASTERN_NEW_CITY.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                //沿滩二期人脸
                buildAndAddDemeritRecords(yan_tan_phase_two_face, ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
            }
        }
@@ -292,4 +317,25 @@
        log.info("结束计算每日扣分记录情况:插入数据量{},数据信息:{}",demeritRecords.size(),demeritRecords);
    }
    public void buildAndAddDemeritRecords(List<RecordMetaDSumResult> constructionByRecordMetaList,
                                          String constructionType,Integer areaDeptId,Date recordTime,
                                          List<DemeritRecord> demeritRecords) {
        if (CollectionUtils.isNotEmpty(constructionByRecordMetaList)) {
                    BigDecimal deduction = calculateTotalDeduction(constructionByRecordMetaList);
                    DemeritRecord demeritRecord = buildDemeritRecord(
                            constructionType,
                            deduction,
                            areaDeptId,
                            DateUtils.getDayStart(recordTime));
                    demeritRecords.add(demeritRecord);
                }else{
                    DemeritRecord demeritRecord = buildDemeritRecord(
                            constructionType,
                            BigDecimal.ZERO,
                            areaDeptId,
                            DateUtils.getDayStart(recordTime));
                    demeritRecords.add(demeritRecord);
        }
    }
}
ycl-server/src/main/java/com/ycl/task/UYTask.java
@@ -182,6 +182,8 @@
     * online字段来自于优云,pingOnline为主动ping检测的。存入mongo给数据中心查阅
     */
    public void pointOnline() throws ExecutionException, InterruptedException {
        log.info("开始检测点位在线");
        Integer times = 2;
        SysConfig config = new SysConfig();
@@ -261,6 +263,11 @@
                unKnownList.add(item.getIp());
            }
        });
        if(!CollectionUtils.isEmpty(onLineList)){
            log.error("在线点位集合:{}",onLineList);
        }
        log.error("unKnownList:{}",unKnownList);
        if(!CollectionUtils.isEmpty(offLineList)) {
            log.error("修改离线的点位集合:{}",offLineList);
@@ -289,6 +296,10 @@
                        }else if("3".equals(type)){
                            mongoData.setProvinceTag(mongoData.getProvinceTagFace());
                        }
                        //修改线上
                        if(mongoData.getPingOnline()){
                            mongoData.setOnline(1);
                        }
                        mongoList.add(mongoData);
                    }
                }
ycl-server/src/main/resources/mapper/zgyw/DemeritREcordMapper.xml
@@ -18,7 +18,8 @@
            ter.dept_id,
            ter.create_time,
            ter.construction_type,
            ter.demerit
            ter.demerit,
            ter.record_time
        from t_demerit_record ter where ter.deleted = 0
        <if test="query.deptId != null and query.deptId != ''">
            AND ter.dept_id = #{query.deptId}
@@ -28,13 +29,14 @@
        </if>
        <!-- 时间范围筛选:按日查询 -->
        <if test="query.searchType == 'day' and query.dayDate != null">
            AND ter.create_time >= #{query.dayDate}  <!-- 当天00:00:00 -->
            AND ter.create_time &lt;DATE_ADD(#{query.dayDate}, INTERVAL 1 DAY)  <!-- 次日00:00:00(不包含) -->
            AND ter.record_time >= #{query.dayDate}  <!-- 当天00:00:00 -->
            AND ter.record_time &lt;DATE_ADD(#{query.dayDate}, INTERVAL 1 DAY)  <!-- 次日00:00:00(不包含) -->
        </if>
        <!-- 时间范围筛选:按月查询 -->
        <if test="query.searchType == 'month' and query.monthDate != null">
            AND ter.create_time >= #{query.monthDate}  <!-- 当月1日00:00:00 -->
            AND ter.create_time &lt;DATE_ADD(LAST_DAY(#{query.monthDate}), INTERVAL 1 DAY)  <!-- 下月1日00:00:00(不包含) -->
        </if>
            ORDER BY ter.record_time DESC
    </select>
</mapper>
ycl-server/src/main/resources/mapper/zgyw/IMonitorConstructionMapper.xml
New file
@@ -0,0 +1,13 @@
<?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.ycl.platform.mapper.IMonitorConstructionMapper">
    <insert id="insertBatch">
        INSERT INTO t_monitor_construction(serial_number,tag,deleted) values
        <foreach collection="list" item="item" index="index" separator=",">
            ( #{item.serialNumber},#{item.tag},0)
        </foreach>
    </insert>
</mapper>
ycl-server/src/main/resources/mapper/zgyw/TMonitorMapper.xml
@@ -106,7 +106,8 @@
        WHEN p.online = -1 OR p.ping_online = -1 THEN -1
        ELSE 0
        END AS onState, civil_code, d.dept_id, d.dept_name, d.area, p.province_tag_video,p.province_tag_car,p.province_tag_face,p.dept_tag,
        IF(COUNT(w.id) OVER() > 0, '是', '否') AS error, u.unit_name,p.recovery_time,p.reason,p.start_time,p.end_time, w.work_order_no
        IF(COUNT(w.id) OVER() > 0, '是', '否') AS error, u.unit_name,p.recovery_time,p.reason,p.start_time,p.end_time, w.work_order_no,
        tmc.tag
        from t_monitor m
        left join t_yw_point p on m.serial_number = p.serial_number and p.deleted = 0
        left join sys_dept d on p.dept_id = d.dept_id and d.del_flag = 0
@@ -117,6 +118,7 @@
        ) SELECT * FROM cte WHERE rn=1
        ) w on m.serial_number = w.serial_number and w.deleted = 0
        left join t_yw_unit u on p.unit_id = u.id and u.deleted = 0
        LEFT JOIN t_monitor_construction tmc on m.serial_number = tmc.serial_number and tmc.deleted = 0
        <where>
            p.examine_status = 1
            <if test="serialNumber != null  and serialNumber != ''">and m.serial_number = #{serialNumber}</if>
@@ -166,35 +168,94 @@
            <if test="cameraDept != null  and cameraDept != ''">and camera_dept = #{cameraDept}</if>
            <if test="hybm != null  and hybm != ''">and hybm = #{hybm}</if>
            <if test="lxbm != null ">and lxbm = #{lxbm}</if>
            <if test="constructionType != null and constructionType != ''">
                <choose>
                    <when test="constructionType == 'PHASE_ONE_TWO'">
                        and m.name LIKE 'DX_%'
                    </when>
                    <when test="constructionType == 'PHASE_THREE'">
                        and m.name LIKE 'LT_%'
                    </when>
                    <when test="constructionType == 'PHASE_FOURTH'">
                        and (
                        m.name LIKE 'DX_R%'
                        OR
                        m.name LIKE 'DX_RS%'
                        )
                    </when>
                    <when test="constructionType == 'EASTERN_NEW_CITY'">
                        and m.name LIKE 'DX_RD%'
                    </when>
                    <when test="constructionType == 'YAN_TAN_PHASE_TWO_FACE'">
                        and m.name LIKE 'DX_R2%'
                    </when>
                </choose>
            </if>
            ${params.dataScope}
        </where>
    </select>
    <select id="selectTMonitorListAndIds" resultType="com.ycl.platform.domain.vo.TMonitorVO">
        select m.id, m.serial_number, name, site_type, mac_addr, ip, camera_fun_type, longitude, latitude,
        camera_capture_area,
        CASE
        WHEN p.online = 1 AND p.ping_online = 1 THEN 1
        WHEN p.online = -1 OR p.ping_online = -1 THEN -1
        ELSE 0
        END AS onState, civil_code, d.dept_id, d.dept_name, d.area, p.province_tag_video,p.province_tag_car,p.province_tag_face,p.dept_tag,
        IF(COUNT(w.id) OVER() > 0, '是', '否') AS error, u.unit_name,p.recovery_time,p.reason,p.start_time,p.end_time, w.work_order_no,
        tmc.tag
        from t_monitor m
        left join t_yw_point p on m.serial_number = p.serial_number and p.deleted = 0
        left join sys_dept d on p.dept_id = d.dept_id and d.del_flag = 0
        left join (
        WITH cte AS (
        SELECT *,row_number() OVER(PARTITION BY serial_number ORDER BY create_time DESC) rn FROM t_work_order
        WHERE deleted = 0 AND status != 'AUDITING_SUCCESS'
        ) SELECT * FROM cte WHERE rn=1
        ) w on m.serial_number = w.serial_number and w.deleted = 0
        left join t_yw_unit u on p.unit_id = u.id and u.deleted = 0
        LEFT JOIN t_monitor_construction tmc on m.serial_number = tmc.serial_number and tmc.deleted = 0
        <where>
            p.examine_status = 1
            <if test="ids != null and ids.size() > 0">
                and m.serial_number in
                <foreach collection="ids" item="id" open="(" separator="," close=")">
                    #{id}
                </foreach>
            </if>
            <if test="serialNumber != null  and serialNumber != ''">and m.serial_number = #{serialNumber}</if>
            <if test="name != null  and name != ''">
                and (name like concat('%', #{name}, '%')
                or m.ip like concat('%', #{name}, '%')
                or m.serial_number like concat('%', #{name}, '%')
                or u.unit_name like concat('%', #{name}, '%'))
            </if>
            <if test="provinceTag != null and cameraFunType == 1">and p.province_tag_video = #{provinceTag}</if>
            <if test="provinceTag != null and cameraFunType == 2">and p.province_tag_car = #{provinceTag}</if>
            <if test="provinceTag != null and cameraFunType == 3">and p.province_tag_face = #{provinceTag}</if>
            <if test="provinceTag != null and recovery == 1">and (p.province_tag_face = #{provinceTag} or p.province_tag_video = #{provinceTag} or p.province_tag_car = #{provinceTag})</if>
            <if test="deptTag != null ">and p.dept_tag = #{deptTag}</if>
            <if test="siteType != null ">and site_type = #{siteType}</if>
            <if test="macAddr != null  and macAddr != ''">and mac_addr = #{macAddr}</if>
            <if test="ip != null  and ip != ''">and ip = #{ip}</if>
            <if test="cameraFunType != null  and cameraFunType != ''">and camera_fun_type like concat('%',
                #{cameraFunType}, '%')
            </if>
            <if test="longitude != null  and longitude != ''">and longitude = #{longitude}</if>
            <if test="latitude != null  and latitude != ''">and latitude = #{latitude}</if>
            <if test="cameraCaptureArea != null  and cameraCaptureArea != ''">and camera_capture_area =
                #{cameraCaptureArea}
            </if>
            <if test="time !=null and time !=''">and TIMESTAMPDIFF(DAY, p.recovery_time, NOW()) <![CDATA[<=]]> #{time}</if>
            <if test="onState != null and onState == 1">and (p.online = #{onState} and p.ping_online = #{onState})</if>
            <if test="onState != null and onState == -1">and (p.online = #{onState} or p.ping_online = #{onState})</if>
            <if test="onState != null and onState == 0">and (p.online = #{onState} and p.ping_online = #{onState})</if>
            <if test="civilCode != null  and civilCode != ''">and civil_code = #{civilCode}</if>
            <if test="integratedDevice != null ">and integrated_device = #{integratedDevice}</if>
            <if test="cameraBrand != null ">and camera_brand = #{cameraBrand}</if>
            <if test="address != null  and address != ''">and d.dept_id = #{address}</if>
            <if test="netWorking != null ">and net_working = #{netWorking}</if>
            <if test="publicSecurity != null  and publicSecurity != ''">and public_security = #{publicSecurity}</if>
            <if test="installedTime != null ">and installed_time = #{installedTime}</if>
            <if test="managementUnit != null  and managementUnit != ''">and management_unit = #{managementUnit}</if>
            <if test="muContactInfo != null  and muContactInfo != ''">and mu_contact_info = #{muContactInfo}</if>
            <if test="storageDays != null ">and storage_days = #{storageDays}</if>
            <if test="monitorAzimuth != null ">and monitor_azimuth = #{monitorAzimuth}</if>
            <if test="scenePhotoAddr != null  and scenePhotoAddr != ''">and scene_photo_addr = #{scenePhotoAddr}</if>
            <if test="model != null  and model != ''">and model = #{model}</if>
            <if test="siteVulgo != null  and siteVulgo != ''">and site_vulgo = #{siteVulgo}</if>
            <if test="cameraType != null ">and camera_type = #{cameraType}</if>
            <if test="cameraLightType != null ">and camera_light_type = #{cameraLightType}</if>
            <if test="encodedFormat != null ">and encoded_format = #{encodedFormat}</if>
            <if test="cameraDept != null  and cameraDept != ''">and camera_dept = #{cameraDept}</if>
            <if test="hybm != null  and hybm != ''">and hybm = #{hybm}</if>
            <if test="lxbm != null ">and lxbm = #{lxbm}</if>
            ${params.dataScope}
        </where>
    </select>
    <select id="exportTMonitorList" resultType="com.ycl.platform.domain.excel.TMonitorExp">
        select m.id, m.serial_number, name, ip, camera_fun_type,
        CASE
@@ -441,6 +502,12 @@
            <if test="address != null">
                and p.dept_id = #{address}
            </if>
            <if test="ids != null and ids.size() > 0">
                and m.serial_number in
                <foreach collection="ids" item="id" open="(" separator="," close=")">
                    #{id}
                </foreach>
            </if>
            <if test="constructionType != null and constructionType != ''">
                <choose>
                    <when test="constructionType == 'PHASE_ONE_TWO'">
@@ -464,6 +531,7 @@
                    </when>
                </choose>
            </if>
            ${params.dataScope}
        </where>
    </select>