“mitao”
2026-01-23 b9a5b68fab3428bb23c05ba3e0cab83afa1a82cb
Merge remote-tracking branch 'origin/master'
2个文件已添加
6个文件已修改
620 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/EntrustProjectController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/enums/BizResultCode.java 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/DeviceDetailCheckListQuery.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProjectInfoServiceImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ReportServiceImpl.java 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/ProjectMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/EntrustProjectController.java
@@ -164,82 +164,13 @@
        recordService.updateById(record);
        return R.ok();
    }
    @ApiOperation(value = "隐患详情")
    @GetMapping("/errorDetail")
    public R errorDetail(Integer id) {
        Record record = recordService.getById(id);
        return R.ok();
    }
    @ApiOperation(value = "获取项目详情", response = Project.class)
    @GetMapping("/getProjectDetail/{id}")
    public R<ProjectVo> getStoryDetail(@PathVariable Integer id) {
        ProjectVo projectVo = new ProjectVo();
        Project project = projectService.getById(id);
        BeanUtils.copyProperties(project, projectVo);
        List<String> properties = deviceUsageService.getDeviceUsageList(id);
        projectVo.setProperties(properties);
        ProjectInfo projectInfo = projectInfoService.getOne(new LambdaUpdateWrapper<ProjectInfo>().eq(ProjectInfo::getProjectId, id));
        if (projectInfo != null) {
            projectVo.setProgress(projectInfo.getProgress());
        }
        Task task = taskService.getOne(new LambdaUpdateWrapper<Task>().eq(Task::getProjectId, id).orderByDesc(Task::getUpdateTime).last("limit 1"));
        if (task != null) {
            projectVo.setCheckTime(task.getUpdateTime());
        }
        return R.ok(projectVo);
    }
    @ApiOperation(value = "获取项目隐患数量", response = Project.class)
    @GetMapping("/getProjectHiddenDangerCount/{id}")
    public R<HiddenDangerVo> getProjectHiddenDangerCount(@PathVariable Integer id) {
        HiddenDangerVo hiddenDangerVo = new HiddenDangerVo();
        List<Task> list = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getProjectId, id));
        if (!list.isEmpty()) {
            List<Integer> taskIds = list.stream().map(Task::getId).collect(Collectors.toList());
            // 0是一级隐患
            List<Record> records = recordService.list(new LambdaQueryWrapper<Record>().eq(Record::getLevel, 0).eq(Record::getDeleted, 0).in(Record::getCheckTaskId, taskIds));
            hiddenDangerVo.setSerious(records.size());
            int rectified = records.stream().filter(Record::getReformed).collect(Collectors.toList()).size();
            hiddenDangerVo.setRectified(rectified);
            hiddenDangerVo.setUnRectified(records.size() - rectified);
        }
        return R.ok(hiddenDangerVo);
    }
    @ApiOperation(value = "获取隐患列表", response = HiddenDangerListVo.class)
    @PostMapping("/getHiddenDangerList")
    public R<Page<HiddenDangerListVo>> getHiddenDangerList(@RequestBody @Valid HiddenDangerListQuery query) {
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getProjectId, query.getProjectId()));
        if (tasks.isEmpty()) {
            return R.ok(new Page<>());
        }
        List<Integer> taskIds = tasks.stream().map(Task::getId).collect(Collectors.toList());
        Page<HiddenDangerListVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        List<HiddenDangerListVo> list = recordService.getHiddenDangerList(page, query, taskIds);
        page.setRecords(list);
        return R.ok(page);
    }
    @ApiOperation(value = "编辑隐患责任人")
    @PostMapping("/editHiddenDangerResponsiblePerson")
    public R<Void> editHiddenDangerResponsiblePerson(@RequestBody @Valid EditHiddenDangerResponsiblePersonDto dto) {
        Record record = recordService.getById(dto.getId());
        if (record == null) {
            return R.fail("隐患不存在");
        }
        record.setResponsiblePerson(dto.getResponsiblePerson());
        recordService.updateById(record);
        return R.ok();
    }
//    @ApiOperation(value = "隐患详情")
//    @GetMapping("/errorDetail")
//    public R errorDetail(Integer id) {
//        Record record = recordService.getById(id);
//
//        return R.ok();
//    }
    @ApiOperation(value = "获取隐患详情")
    @GetMapping("/getHiddenDangerDetail/{problemId}")
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java
@@ -212,13 +212,13 @@
        return R.ok(list);
    }
    @ApiOperation(value = "获取检查资料详情")
    @GetMapping("/getDeviceDetailCheckPlanDetail")
    public R<Check> getDeviceDetailCheckPlanDetail(@RequestParam Integer id) {
        Check check = checkService.getDeviceDetailCheckPlanDetail(id);
        return R.ok(check);
    }
    @ApiOperation(value = "获取大屏人员在岗信息")
@@ -260,6 +260,7 @@
        return R.ok(list);
    }
    @ApiOperation(value = "获取人员在岗列表",response = ProjectPersonOnDutyListVo.class)
    @PostMapping("/getProjectOnDutyList")
    public R<Page<ProjectPersonOnDutyListVo>> getProjectOnDutyList(@RequestBody @Valid ProjectPersonListQuery query) {
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -1,6 +1,7 @@
package com.ruoyi.framework.web.service;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
@@ -15,8 +16,10 @@
import com.ruoyi.common.exception.user.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
@@ -90,8 +93,14 @@
            log.info("登录用户:{} 不存在.", username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        }
        if (!user.getPassword().equals(SecureUtil.md5( password)))
        {
            log.info("登录用户:{} 密码错误", username);
            throw new UserPasswordNotMatchException();
        }
        if(user.getState()!=1){
            log.info("登录用户:{} 已被停用.", username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(Long.valueOf(user.getId()));
ruoyi-system/src/main/java/com/ruoyi/system/enums/BizResultCode.java
New file
@@ -0,0 +1,227 @@
package com.ruoyi.system.enums;
import lombok.Getter;
/**
 * @description: 弹窗消息的定义
 * @author: code
 **/
@Getter
public enum BizResultCode implements ApiResultCode {
    INVALID_OPERATION("无效操作"),
    MOBILE_ALREADY_EXIST("手机号已存在"),
    USERNAME_ALREADY_EXIST("用户名已存在"),
    ACCOUNT_NOT_FOUND("帐号不存在"),
    SYS_VALIDATION_FAILED_ERROR("验证失败,无效请求"),
    APP_CLIENT_NOT_EXIST("登录客户端不存在"),
    SESSION_EXPIRED("会话已过期"),
    SESSION_INVALID("会话无效"),
    NO_LOGIN_ERROR("未登录"),
    ACCOUNT_FORBIDDEN("帐号被禁用"),
    H_CAPTCHA_CODE_NULL_ERROR("图形验证码不能为空"),
    CAPTCHA_CODE_NOT_NULL(""),
    H_CAPTCHA_CODE_VALIDATE_ERROR("图形验证失败"),
    VERIFICATION_CODE_INVALID("图形验证码验证失败"),
    BIZ_PASSWORD_INVALID("密码错误"),
//    BIZ_CLIENT_NOT_FOUND("委托方不存在"),
//    BIZ_CLIENT_NAME_ALREADY_EXISTS("委托方名称已存在"),
//    BIZ_CONTRACT_NOT_EXIST("合同不存在"),
    BIZ_CAR_NOT_EXIST("车辆不存在"),
    BIZ_DATE_FORMAT_ERROR("日期格式错误"),
    BIZ_PROJECT_NOT_EXIST("项目不存在"),
    BIZ_DEVICE_NOT_EXIST("设备不存在"),
    BIZ_SCORE_WEIGHT_CAN_NOT_NULL("分数和权重不能为空"),
    BIZ_HIERARCHY_SYSTEM_NOT_EXIST("体系不存在"),
    BIZ_PARENT_HIERARCHY_SYSTEM_NOT_EXIST("父ID体系不存在"),
    BIZ_PLAN_NOT_EXIST("计划不存在"),
    BIZ_PROBLEM_NUM_CANNOT_NULL("问题数量集合不能为空"),
    BIZ_PROBLEM_SCALE_CANNOT_NULL("对应规模集合不能为空"),
    BIZ_REAL_RULE_NOT_EXIST("实测实量规则不存在"),
    BIZ_EXPERT_NOT_EXIST("专家不存在"),
    EXPERT_FUNCTIONS_MUST_ENABLE("专家功能必须启用"),
    BIZ_MODEL_NOT_EXIST("模型不存在"),
    BIZ_PROJECT_STATUS_NOT_MATCH("项目状态不匹配"),
    BIZ_EXPERT_SCORE_SYS_NOT_EXIST("专家评分体系不存在"),
    BIZ_MEMBERSHIP_DEGREE_NOT_EXIST("隐患等级不存在"),
    BIZ_PROJECT_SUPERVISOR_HIS_NOT_EXIST("项目监督历史不存在"),
    BIZ_PROJECT_DEVICE_NOT_EXIST("项目设备不存在"),
    BIZ_REPORT_TEMPLATE_NOT_EXIST("报告模板不存在"),
    BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST("报告模板类型不存在"),
    BIZ_ARCHIVE_NOT_EXIST("档案不存在"),
    BIZ_PROJECT_NOT_CLOSED("项目未关闭"),
    BIZ_PROJECT_ALREADY_CLOSED("项目已关闭"),
    BIZ_PLAN_CLIENT_EXIST("该委托方对应的计划已存在"),
    BIZ_PLAN_PROJECT_RELATION_NOT_EXIST("计划项目关系不存在"),
    BIZ_PROJECT_NAME_EXIST("同一个委托方下已存在相同名称的项目"),
    HIERARCHY_PARENT_NOT_FOUND("父级体系不存在"),
    HIERARCHY_NODE_NOT_FOUND("节点不存在"),
    HIERARCHY_NODE_NAME_ALREADY_EXISTS("节点名称已存在"),
    BIZ_MODEL_NOT_FOUND("模型不存在"),
    DRIVER_CAR_NOT_MATCH("司机和车辆数量不匹配"),
    PARAM_ERROR("参数错误"),
    CAR_NOT_EXIST("车辆不存在"),
    PROBLEM_NOT_EXIST("问题不存在"),
    ID_CANNOT_NULL("ID不能为空"),
    MODEL_NOT_FOUND("模型不存在"),
    PROJECT_INFO_NOT_EXIST("项目信息不存在"),
    DEVICE_NOT_FOUND("设备不存在"),
    DEVICE_IS_BUSY("设备正在使用中"),
    PLAN_NOT_EXIST("计划不存在"),
    ARCHIVE_NOT_EXIST("档案不存在"),
    ENTITY_NOT_FOUND("实体不存在"),
    ENTITY_NAME_ALREADY_EXISTS("实体名称已存在"),
    ENTITY_CANNOT_NULL("实体不能为空"),
    MODEL_PUBLISHED_CANNOT_MODIFY("已发布的模型不可修改"),
    ACCOUNT_ALREADY_EXISTS("登录账号已存在"),
    //无权修改他人信息
    NO_PERMISSION_MODIFY_OTHERS_INFO("无权修改他人信息"),
    DEVICE_USAGE_NOT_FOUND("设备使用记录不存在"),
    MEMBERSHIP_MATRIX_LOAD_ERROR("隶属度矩阵加载失败"),
    TASK_NOT_FOUND("任务不存在"),
    TASK_ALREADY_EXIST("任务已存在"),
    TASK_STATUS_ERROR("任务状态错误"),
    NUMBER_FACTOR_NOT_EXIST("问题数量集合不存在"),
    NUMBER_FACTOR_INDEX_ERROR("问题数量索引错误"),
    SCALE_FACTOR_NOT_EXIST("对应规模集合不存在"),
    SCALE_FACTOR_INDEX_ERROR("对应规模索引错误"),
    INDEX_COLS_EMPTY("索引列为空"),
    COMPARE_MATRIX_EMPTY("比较矩阵为空"),
    MATRIX_SIZE_ERROR("矩阵大小错误"),
    MATRIX_ERROR("所有的数字都应该是正数,且沿着主对角线对称的元素应该是彼此的相反数"),
    NUMBER_NON_NEGATIVE("所有的数字都应该是非负数"),
    INDEX_RANGE_ERROR("索引范围错误"),
    MEMBERSHIP_MATRIX_ERROR("隶属度矩阵每一行的和应该等于1"),
    SIGN_RECORD_EXIST("重复签到"),
    PLAN_NAME_EXIST("计划名称已存在"),
    CAR_LICENSE_NO_EXIST("车牌号已存在"),
    HIERARCHY_NOT_FOUND("体系数据不存在"),
    PLAN_NOT_FOUND("计划不存在"),
    RECORD_NOT_FOUND("问题记录不存在"),
    RECORD_REVIEW_EXISTED("问题已经复核"),
    REVIEW_ALREADY_REFORMED("问题已经整改,无须复查"),
    UPLOAD_FILE_FAILED("上传文件失败"),
    UPLOAD_FILE_CONTAINS_ILLEGAL_CHARACTERS("上传文件名包含非法字符"),
    FILE_NOT_FOUND("文件不存在"),
    EVAL_FUZZY_RESULT_NOT_EXIST("模糊评价结果不存在"),
    EVAL_SCORE_RESULT_NOT_EXIST("评分评价结果不存在"),
    USER_IS_DISABLE("用户已被禁用"),
    EXPERT_MODEL_NOT_EXIST("专家对应的模型不存在"),
    MEMBERSHIP_MATRIX_NOT_EXIST("隶属度矩阵不存在"),
    EXPERT_NOT_FOUND("专家不存在"),
    MOBILE_FORMAT_ERROR("手机号格式错误"),
    HIERARCHY_NOT_EXIST("体系不存在"),
    PlAN_MODEL_EXPERT_SHOULD_PAIRED("计划模型和专家模型不匹配"),
    PLAN_SYSTEM_MODEL_NOT_EXIST("综合体系模型不存在"),
    PLAN_DEVICE_MODEL_NOT_EXIST("设备体系模型不存在"),
    REVIEW_TASK_NOT_EXIST("复核任务不存在"),
    ERROR_RECORD_ALL_REVIEWD("问题已全部复核"),
    PROJECT_INFO_EXISTS("检查任务对应的项目信息已存在"),
    IMPORT_DATA_EMPTY("导入数据为空"),
    IMPORT_DATA_COLUMN_COUNT("导入数据列数不正确"),
    CLIENT_NOT_FOUND("委托方不存在"),
    DEVICE_ALREADY_EXISTS("设备名称已存在"),
    ROLE_NOT_FOUND("角色不存在"),
    CHECK_TASK_NOT_EXIST("检查任务不存在"),
    DEVICE_USAGE_NOT_EXISTED("设备使用记录不存在"),
    PASSWORD_ERROR("密码输入错误"),
    PASSWORD_FORMAT_ERROR("密码需要6到16位长度"),
    // License相关错误码
    LICENSE_NOT_CONFIGURED("License密钥未配置"),
    LICENSE_INVALID_FORMAT("License格式错误"),
    LICENSE_SIGNATURE_INVALID("License签名验证失败"),
    LICENSE_EXPIRED("License已过期"),
    LICENSE_VALIDATION_FAILED("License验证失败"),
    // 报告生成相关错误码
    BIZ_REPORT_GENERATE_FAILED("报告生成失败");
    private final String errorMsg;
    BizResultCode(String errorMsg) {
        this.errorMsg = errorMsg;
    }
    /**
     * 得到 message 的值.
     *
     * @return 属性 message 的值.
     */
    @Override
    public String getErrorMsg() {
        return errorMsg + "(" + getAppId() + ")";
    }
    /**
     * @return 当前服务的AppId
     */
    @Override
    public String getAppId() {
        return "1001";
    }
    /**
     * 校验方法
     *
     * @param expect
     */
    public void check(boolean expect) {
        if (expect) {
            throw new BizException(this.errorMsg);
        }
    }
    /**
     * 校验方法
     * @param expect
     * @param code
     */
    public void check(boolean expect, String code) {
        if (expect) {
            throw new BizException(code);
        }
    }
    /**
     * 校验方法
     * @param expect
     * @param code
     * @param message
     */
    public void check(boolean expect, String code, String message) {
        if (expect) {
            throw new BizException(message);
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/query/DeviceDetailCheckListQuery.java
@@ -15,8 +15,8 @@
    @NotNull(message = "项目id不能为空")
    private Integer projectId;
    @ApiModelProperty("计划id")
    private Integer planId;
    @ApiModelProperty("计划类型")
    private Integer planType;
    @ApiModelProperty("开始时间")
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProjectInfoServiceImpl.java
@@ -1,20 +1,16 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.ProjectInfoMapper;
import com.ruoyi.system.model.Project;
import com.ruoyi.system.model.ProjectInfo;
import com.ruoyi.system.mapper.ProjectInfoMapper;
import com.ruoyi.system.model.Record;
import com.ruoyi.system.query.ProjectDangerousTrendQuery;
import com.ruoyi.system.query.ProjectHiddenDangerTrendListQuery;
import com.ruoyi.system.service.ProjectCategoryCalculator;
import com.ruoyi.system.service.ProjectInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.service.ProjectService;
import com.ruoyi.system.service.RecordService;
import com.ruoyi.system.vo.ProjectDangerousTrendVo;
import com.ruoyi.system.vo.ProjectHiddenDangerList;
import com.ruoyi.system.vo.ProjectHiddenDangerNextList;
@@ -30,7 +26,10 @@
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.groupingBy;
@@ -230,18 +229,5 @@
        // 计算月份差 + 1(包含结束月份)
        return (int) ChronoUnit.MONTHS.between(start, end) + 1;
    }
    public static void main(String[] args) {
        LocalDate monthBoundaries = getMonthBoundaries("2025-03", true);
        System.out.println(monthBoundaries);
        System.out.println(getMonthBoundaries("2025-02",false));
        System.out.println(calculateMonthsBetween("2025-03", "2026-01"));
        for (int count = 0; count < 11; count++) {
            // 根据2025-03 根据循环获取下一个月的时间
            LocalDate monthBoundaries1 = getMonthBoundaries("2025-03", true).plusMonths(count);
            System.out.println(monthBoundaries1.toString().substring(0,7));
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ReportServiceImpl.java
New file
@@ -0,0 +1,264 @@
package com.ruoyi.system.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.system.enums.BizResultCode;
import com.ruoyi.system.model.ReportTemplate;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
/**
 * 报告数据服务实现类
 **/
@Slf4j
@Service
public class ReportServiceImpl implements ReportService {
    @Resource
    private ReportTemplateService reportTemplateService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private DeviceUsageService deviceUsageService;
    @Resource
    private EvalFuzzyService evalFuzzyService;
    @Resource
    private EvalScoreService evalScoreService;
    @Resource
    private ErrorRecordService errorRecordService;
    @Resource
    private DeviceService deviceService;
    @Resource
    private UserFileService userFileService;
    @Override
    public JSONObject fuzzyReportData(Integer checkTaskId, Integer templateId) {
        var evalFuzzyResult = evalFuzzyService.getByCheckTaskId(checkTaskId);
        BizResultCode.EVAL_FUZZY_RESULT_NOT_EXIST.check(evalFuzzyResult == null);
        var evalScoreResult =  evalScoreService.getByCheckTaskId(checkTaskId);
        BizResultCode.EVAL_SCORE_RESULT_NOT_EXIST.check(evalScoreResult == null);
        var reportTemplate = reportTemplateService.get(templateId);
        BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
        switch (reportTemplate.getType()) {
            case ThirdPartyReport:
                return buildFuzzySystemReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
            case DeviceReport:
                return buildFuzzyDeviceReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
            default:
                throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
        }
    }
    @Override
    public JSONObject scoreReportData(Integer checkTaskId, Integer templateId) {
        var evalFuzzyResult = evalFuzzyService.getByCheckTaskId(checkTaskId);
        BizResultCode.EVAL_FUZZY_RESULT_NOT_EXIST.check(evalFuzzyResult == null);
        var evalScoreResult =  evalScoreService.getByCheckTaskId(checkTaskId);
        BizResultCode.EVAL_SCORE_RESULT_NOT_EXIST.check(evalScoreResult == null);
        var reportTemplate = reportTemplateService.get(templateId);
        BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
        switch (reportTemplate.getType()) {
            case ThirdPartyReport:
                return buildScoreSystemReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
            case DeviceReport:
                return buildScoreDeviceReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
            default:
                throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
        }
    }
    @Override
    public XWPFTemplate fuzzyReport(Integer checkTaskId, Integer templateId) {
        var reportData = fuzzyReportData(checkTaskId, templateId);
        var builder = getReportBuilder(templateId);
        var template = reportTemplateService.get(templateId);
        // reportData to JSONObject
        return builder.buildReport(reportData, template.getConfig());
    }
    @Override
    public XWPFTemplate scoreReport(Integer checkTaskId, Integer templateId) {
        var reportData = scoreReportData(checkTaskId, templateId);
        var builder = getReportBuilder(templateId);
        var template = reportTemplateService.get(templateId);
        // reportData to JSONObject
        return builder.buildReport(reportData, template.getConfig());
    }
    @Override
    public void fuzzyReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream) {
        try (var doc = fuzzyReport(checkTaskId, templateId)) {
            convertToPdf(doc, outputStream);
        } catch (Exception e) {
            log.error("生成模糊评价PDF报告失败", e);
            throw new BizException("生成模糊评价PDF报告失败");
        }
    }
    @Override
    public void scoreReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream) {
        try (var doc = scoreReport(checkTaskId, templateId)) {
            convertToPdf(doc, outputStream);
        } catch (Exception e) {
            log.error("生成打分评价PDF报告失败", e);
            throw new BizException("生成打分评价PDF报告失败");
        }
    }
    /**
     * 将Word文档转换为PDF
     * @param template Word模板
     * @param outputStream 输出流
     */
    private void convertToPdf(XWPFTemplate template, OutputStream outputStream) throws Exception {
        // 先将Word模板写入字节数组
        ByteArrayOutputStream docOutputStream = new ByteArrayOutputStream();
        template.write(docOutputStream);
        // 从字节数组读取Word文档
        ByteArrayInputStream docInputStream = new ByteArrayInputStream(docOutputStream.toByteArray());
        org.apache.poi.xwpf.usermodel.XWPFDocument document = new org.apache.poi.xwpf.usermodel.XWPFDocument(docInputStream);
        // 转换为PDF
        PdfOptions options = PdfOptions.create();
        PdfConverter.getInstance().convert(document, outputStream, options);
        // 关闭资源
        document.close();
        docInputStream.close();
        docOutputStream.close();
    }
    private ReportBuilderBase getReportBuilder(Integer templateId) {
        var reportTemplate = reportTemplateService.get(templateId);
        BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
        switch (reportTemplate.getType()) {
            case ThirdPartyReport:
                return new SystemReportBuilder(userFileService);
            case DeviceReport:
                return new DeviceReportBuilder(userFileService);
            default:
                throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
        }
    }
    private JSONObject buildFuzzySystemReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult, ReportTemplate reportTemplate) {
        // 查询必须要的数据
        var records = errorRecordService.listSystemErrors(evalFuzzyResult.getTask().getId());
        var project = evalFuzzyResult.getProject();
        var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
//        var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
        var deviceUsages = deviceUsageService.listUsages(project.getId(), null);
        var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
        var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
        // 生成报告数据
        return SystemFuzzyReportData.builder()
                .reportId(evalFuzzyResult.getId())
                .systemHierarchy(hierarchy)
                .sysResult(evalFuzzyResult.getSystemRes())
                .scoreResult(scoreResult.getSystemRes())
                .template(reportTemplate)
                .project(project)
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .build()
                .generate();
    }
    private JSONObject buildScoreSystemReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult, ReportTemplate reportTemplate) {
        // 查询必须要的数据
        var records = errorRecordService.listSystemErrors(evalFuzzyResult.getTask().getId());
        var project = evalFuzzyResult.getProject();
//        var projectInfo = projectInfoService.latest(evalFuzzyResult.getProject().getId());
        var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
        var deviceUsages = deviceUsageService.listUsages(project.getId(), null);
        var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
        var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
        // 生成报告数据
        return SystemScoreReportData.builder()
                .reportId(evalFuzzyResult.getId())
                .systemHierarchy(hierarchy)
                .sysResult(evalFuzzyResult.getSystemRes())
                .scoreResult(scoreResult.getSystemRes())
                .template(reportTemplate)
                .project(project)
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .build()
                .generate();
    }
    private JSONObject buildFuzzyDeviceReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult,  ReportTemplate reportTemplate) {
        var records = errorRecordService.listDeviceErrors(evalFuzzyResult.getTask().getId());
        var project = evalFuzzyResult.getProject();
        var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
//        var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
        var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
        var devices = deviceService.findAllById(deviceIds);
        var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
        // 生成报告数据
        return DeviceFuzzyReportData.builder()
                .reportId(evalFuzzyResult.getId())
                .deviceResMap(evalFuzzyResult.getDeviceResMap())
                .deviceHierarchy(hierarchy)
                .template(reportTemplate)
                .project(project)
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .build()
                .generate();
    }
    private JSONObject buildScoreDeviceReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult evalScoreResult, ReportTemplate reportTemplate) {
        var records = errorRecordService.listDeviceErrors(evalFuzzyResult.getTask().getId());
        var project = evalFuzzyResult.getProject();
//        var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
        var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
        var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
        var devices = deviceService.findAllById(deviceIds);
        var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
        // 生成报告数据
        return DeviceScoreReportData.builder()
                .reportId(evalFuzzyResult.getId())
                .deviceResMap(evalFuzzyResult.getDeviceResMap())
                .deviceScoreResMap(evalScoreResult.getDeviceResMap())
                .deviceHierarchy(hierarchy)
                .template(reportTemplate)
                .project(project)
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .build()
                .generate();
    }
}
ruoyi-system/src/main/resources/mapper/system/ProjectMapper.xml
@@ -34,8 +34,8 @@
            <if test="query.planName != null and query.planName != ''">
                and t2.name like concat('%',#{query.planName},'%')
            </if>
            <if test="query.planId != null">
                and t2.id = #{query.planId}
            <if test="query.planType != null">
                and t2.type = #{query.planType}
            </if>
            <if test="query.startTime != null and query.startTime != ''">
                and t1.date >= #{query.startTime}