liujie
2026-01-21 2d368b1f587edfe4e1c87e9dc1d5345cd43b8841
update
1个文件已添加
26个文件已修改
635 ■■■■■ 已修改文件
admin-server/pom.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/MainApplication.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/admin/CheckController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/admin/DeviceController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/admin/OnDutyController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/admin/ProjectController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/admin/ProjectInfoController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/business/check/CheckVo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/business/onduty/OnDutyVo.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/project/enums/ProjectType.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/project/enums/ProjectUsageType.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/HazardSourceType.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/ProjectInfo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/ProjectInfoDto.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/repository/CheckMapper.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/repository/OnDutyMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/enums/BizResultCode.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/CheckService.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/OnDutyService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/ReportService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/impl/CheckServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/impl/OnDutyServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/impl/ReportServiceImpl.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/utils/WebUtils.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/resources/mapper/CheckMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/resources/mapper/OnDutyMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/pom.xml
@@ -21,6 +21,18 @@
    </properties>
    <dependencies>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.0.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
@@ -145,7 +157,14 @@
            <artifactId>spring-expression</artifactId>
            <version>5.3.18</version>
        </dependency>
        <!-- Word to PDF conversion -->
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!-- MyBatis-Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
admin-server/src/main/java/com/estate/expert/admin/MainApplication.java
@@ -8,7 +8,9 @@
/**
 * 涓诲簲鐢ㄧ▼搴? */
@SpringBootApplication(scanBasePackages = {"com.estate.expert.admin"})
@SpringBootApplication(scanBasePackages = {"com.estate.expert.admin"},exclude = {
        org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.class
})
@EnableConfigurationProperties()
@EnableAsync
@MapperScan("com.estate.expert.admin.domain.repository")
admin-server/src/main/java/com/estate/expert/admin/controller/admin/CheckController.java
@@ -1,19 +1,27 @@
package com.estate.expert.admin.controller.admin;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.estate.expert.admin.domain.business.check.CheckVo;
import com.estate.expert.admin.domain.business.onduty.OnDutyVo;
import com.estate.expert.admin.domain.common.request.OnDutyRequest;
import com.estate.expert.admin.service.CheckService;
import com.estate.expert.admin.service.OnDutyService;
import com.estate.expert.admin.utils.WebUtils;
import com.estate.expert.common.rpc.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
@Slf4j
@@ -46,6 +54,41 @@
    }
    @ApiOperation(value = "批量删除")
    @PostMapping("/delete")
    public Result delete(@RequestBody List<Integer> ids) {
        return Result.success(checkService.removeByIds(ids));
    }
    @ApiOperation(value = "导出")
    @PostMapping(value = "/export")
    public void export(@RequestBody OnDutyRequest query){
        List<CheckVo> list = checkService.exportList(query);
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), CheckVo.class, list);
        HttpServletResponse response = WebUtils.response();
        assert response != null;
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("检查情况导出信息.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
//    @ApiOperation(value = "新增故事简讯")
//    @PostMapping("/add")
//    public Result add(@Validated @RequestBody AccidentBrief dto) {
admin-server/src/main/java/com/estate/expert/admin/controller/admin/DeviceController.java
@@ -6,16 +6,20 @@
import com.estate.expert.admin.domain.common.request.PageReq;
import com.estate.expert.admin.domain.user.User;
import com.estate.expert.admin.service.DeviceService;
import com.estate.expert.common.auth.IgnoreAuth;
import com.estate.expert.common.domain.Session;
import com.estate.expert.common.rpc.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags = "管理后台/设备管理")
@Slf4j
@@ -28,6 +32,7 @@
    @Resource
    private DeviceService deviceService;
    @ApiOperation(value = "设备列表")
    @PostMapping("/list")
    public Result list(@RequestParam(value = "keyword", required = false) String keyword,
admin-server/src/main/java/com/estate/expert/admin/controller/admin/OnDutyController.java
@@ -1,5 +1,7 @@
package com.estate.expert.admin.controller.admin;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.estate.expert.admin.domain.business.accidentbrief.AccidentBrief;
@@ -9,17 +11,26 @@
import com.estate.expert.admin.domain.common.request.PageReq;
import com.estate.expert.admin.service.AccidentBriefService;
import com.estate.expert.admin.service.OnDutyService;
import com.estate.expert.admin.utils.WebUtils;
import com.estate.expert.common.rpc.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
@CrossOrigin
@@ -51,6 +62,42 @@
    }
    @ApiOperation(value = "批量删除")
    @PostMapping("/delete")
    public Result delete(@RequestBody List<Integer> ids) {
        return Result.success(onDutyService.removeByIds(ids));
    }
    @ApiOperation(value = "导出")
    @PostMapping(value = "/export")
    public void export(@RequestBody OnDutyRequest query){
        List<OnDutyVo> list = onDutyService.exportList(query);
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), OnDutyVo.class, list);
        HttpServletResponse response = WebUtils.response();
        assert response != null;
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("在岗情况导出信息.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
//    @ApiOperation(value = "新增故事简讯")
//    @PostMapping("/add")
//    public Result add(@Validated @RequestBody AccidentBrief dto) {
admin-server/src/main/java/com/estate/expert/admin/controller/admin/ProjectController.java
@@ -7,6 +7,7 @@
import com.estate.expert.admin.domain.user.User;
import com.estate.expert.admin.service.ClientParamService;
import com.estate.expert.admin.service.ProjectService;
import com.estate.expert.common.auth.IgnoreAuth;
import com.estate.expert.common.domain.Session;
import com.estate.expert.common.rpc.Result;
import io.swagger.annotations.Api;
@@ -16,6 +17,8 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags = "管理后台/项目管理")
@Slf4j
admin-server/src/main/java/com/estate/expert/admin/controller/admin/ProjectInfoController.java
@@ -2,6 +2,7 @@
import com.estate.expert.admin.domain.common.request.BatchReq;
import com.estate.expert.admin.domain.common.request.PageReq;
import com.estate.expert.admin.domain.common.response.PageResp;
import com.estate.expert.admin.domain.project.info.ProjectInfoDto;
import com.estate.expert.admin.domain.project.info.ProjectInfoMapper;
import com.estate.expert.admin.domain.user.User;
@@ -17,6 +18,7 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "管理后台/项目信息")
@Slf4j
admin-server/src/main/java/com/estate/expert/admin/controller/stat/ReportController.java
@@ -73,6 +73,24 @@
        }
    }
    @ApiOperation("模糊评价报告PDF下载")
    @GetMapping("/fuzzyReportPdf")
    @IgnoreAuth
    public void fuzzyReportPdf(@ApiParam("检查任务ID") @RequestParam(value = "checkTaskId") Integer checkTaskId,
                               @ApiParam("报告模版ID") @RequestParam(value = "templateId") Integer templateId,
                               HttpServletResponse response) throws IOException {
        downloadPdf(checkTaskId, templateId, response, "模糊评价", true);
    }
    @ApiOperation("打分评价报告PDF下载")
    @GetMapping("/scoreReportPdf")
    @IgnoreAuth
    public void scoreReportPdf(@ApiParam("检查任务ID") @RequestParam(value = "checkTaskId") Integer checkTaskId,
                               @ApiParam("报告模版ID") @RequestParam(value = "templateId") Integer templateId,
                               HttpServletResponse response) throws IOException {
        downloadPdf(checkTaskId, templateId, response, "打分评价", false);
    }
    private void download(XWPFTemplate doc, HttpServletResponse response, String typeName,
                          Integer checkTaskId, Integer templateId) throws IOException {
        OutputStream out;
@@ -95,4 +113,31 @@
        out.flush();
    }
    private void downloadPdf(Integer checkTaskId, Integer templateId, HttpServletResponse response,
                             String typeName, boolean isFuzzy) throws IOException {
        OutputStream out;
        BufferedOutputStream bos;
        var checkTask = checkTaskService.get(checkTaskId, true);
        var reportTemplate = reportTemplateService.get(templateId);
        BizResultCode.TASK_NOT_FOUND.check(checkTask == null);
        var docName = checkTask.getProject().getName() + "_" + reportTemplate.getName() + "_" + typeName;
        String encodedFileName = URLEncoder.encode(docName, "UTF-8");
        response.setContentType("application/pdf");
        response.setHeader("Content-disposition", "attachment;filename=\"" + encodedFileName + ".pdf\"");
        out = response.getOutputStream();
        bos = new BufferedOutputStream(out);
        if (isFuzzy) {
            reportService.fuzzyReportPdf(checkTaskId, templateId, bos);
        } else {
            reportService.scoreReportPdf(checkTaskId, templateId, bos);
        }
        bos.flush();
        out.flush();
    }
}
admin-server/src/main/java/com/estate/expert/admin/domain/business/check/CheckVo.java
@@ -1,6 +1,7 @@
package com.estate.expert.admin.domain.business.check;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -36,6 +37,7 @@
    @ApiModelProperty("计划名称")
    @Excel(name = "计划名称")
    private String planName;
@@ -43,12 +45,14 @@
    private Integer projectId;
    @ApiModelProperty("项目名称")
    @Excel(name = "项目")
    private String projectName;
    @ApiModelProperty("委托方id")
    private Integer clientId;
    @ApiModelProperty("委托方名称")
    @Excel(name = "委托方")
    private String clientName;
    @ApiModelProperty("安全告知单")
@@ -61,6 +65,7 @@
    private String integrityNotification;
    @ApiModelProperty("检查时间")
    @Excel(name = "检查时间",format = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date time;
admin-server/src/main/java/com/estate/expert/admin/domain/business/onduty/OnDutyVo.java
@@ -1,6 +1,7 @@
package com.estate.expert.admin.domain.business.onduty;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -38,6 +39,7 @@
    @ApiModelProperty("计划名称")
    @Excel(name = "计划名称")
    private String planName;
@@ -45,7 +47,12 @@
    private Integer projectId;
    @ApiModelProperty("项目名称")
    @Excel(name = "项目")
    private String projectName;
    @ApiModelProperty("人员在岗(固定)")
    @Excel(name = "检查内容")
    private String content="人员在岗";
    @ApiModelProperty("委托方id")
    private Integer clientId;
@@ -53,16 +60,17 @@
    @ApiModelProperty("委托方名称")
    private String clientName;
    @ApiModelProperty("人员在岗(固定)")
    private String content;
    @ApiModelProperty("岗位id")
    private Integer positionId;
    @ApiModelProperty("岗位名称")
    @Excel(name = "岗位")
    private String positionName;
    @ApiModelProperty("问题备注")
    @Excel(name = "问题备注")
    private String remark;
    @ApiModelProperty("图片")
@@ -71,9 +79,11 @@
    @ApiModelProperty("检查时间")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @Excel(name = "检查时间",format = "yyyy-MM-dd")
    private Date time;
    @ApiModelProperty("1在岗 2未在岗 3请假")
    @Excel(name = "在岗情况",replace = {"在岗_1","未在岗_2","请假_3"})
    private Integer state;
    @ApiModelProperty("创建时间")
admin-server/src/main/java/com/estate/expert/admin/domain/project/enums/ProjectType.java
@@ -11,19 +11,11 @@
@Getter
public enum ProjectType implements IOptionVo {
    HOUSE_CONSTRUCTION("房建"), // 房建
    HOUSE_CONSTRUCTION("房建工程"), // 房建工程
    MUNICIPAL_ADMINISTRATION("市政"), // 市政
    MUNICIPAL_ADMINISTRATION("市政工程"), // 市政工程
    CONSTRUCTION_WORK("建筑工程"), // 建筑工程
    CIVIL_WORKS("土木工程"), // 土木工程
    ELECTRICAL_ENGINEERING("机电工程"),// 机电工程
    SUBSIDIARY("子公司"),// 子公司
    DECORATION("装饰装修"); //装饰装修
    FIXED_ASSETS("固定资产"); // 固定资产
    final String desc;
@@ -49,34 +41,26 @@
    }
    static {
        // 房建工程关联用途类型
        HOUSE_CONSTRUCTION.linkPurposeType(ProjectUsageType.RESIDENTIAL);
        HOUSE_CONSTRUCTION.linkPurposeType(ProjectUsageType.COMMERCIAL);
        // 市政工程关联用途类型
        MUNICIPAL_ADMINISTRATION.linkPurposeType(ProjectUsageType.ROAD);
        MUNICIPAL_ADMINISTRATION.linkPurposeType(ProjectUsageType.BRIDGE);
        MUNICIPAL_ADMINISTRATION.linkPurposeType(ProjectUsageType.TUNNEL_WORKS);
        CONSTRUCTION_WORK.linkPurposeType(ProjectUsageType.CIVIL_WORKS);
        CONSTRUCTION_WORK.linkPurposeType(ProjectUsageType.INDUSTRIAL_WORKS);
        CONSTRUCTION_WORK.linkPurposeType(ProjectUsageType.STRUCTURE_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.ROAD_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.RAIL_TRANSPORTATION);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.BRIDGE_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.TUNNEL_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.HYDRAULIC_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.MINING_WORKS);
        CIVIL_WORKS.linkPurposeType(ProjectUsageType.CABLE_PIPE_WORKS);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.MECHANICAL_EQUIPMENT);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.STATIC_EQUIPMENT);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.ELECTRICAL);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.BUILDING_AUTOMATION);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.PIPELINE);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.FIRE_PROTECTION);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.PURIFICATION);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.VENTILATION_AIR_CONDITIONING);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.EQUIPMENT_PIPE_ANTICORROSION_INSULATION);
        ELECTRICAL_ENGINEERING.linkPurposeType(ProjectUsageType.INDUSTRIAL_FURNACE);
        // 固定资产关联用途类型
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.RETAIL);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.FOOD);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.EDUCATION);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.MEDICAL_BEAUTY);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.ENTERTAINMENT);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.HOTEL);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.REFIT);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.PUBLIC_PLACE);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.ENERGY_STATION);
        FIXED_ASSETS.linkPurposeType(ProjectUsageType.MULTI_FUNCTION_COMPLEX);
    }
    @Override
admin-server/src/main/java/com/estate/expert/admin/domain/project/enums/ProjectUsageType.java
@@ -7,30 +7,26 @@
@ApiModel("项目用途类型")
@Getter
public enum ProjectUsageType implements IOptionVo {
    // 房建工程用途类型
    RESIDENTIAL("住宅"),
    COMMERCIAL("商业"),
    // 市政工程用途类型
    ROAD("道路"),
    BRIDGE("桥梁"),
    CIVIL_WORKS("民用建筑工程"),
    INDUSTRIAL_WORKS("工业建筑工程"),
    STRUCTURE_WORKS("构筑物工程"),
    ROAD_WORKS("道路工程"),
    RAIL_TRANSPORTATION("轨道交通工程"),
    BRIDGE_WORKS("桥涵工程"),
    TUNNEL_WORKS("隧道工程"),
    HYDRAULIC_WORKS("水工工程"),
    MINING_WORKS("矿山工程"),
    CABLE_PIPE_WORKS("架线与管沟工程"),
    MECHANICAL_EQUIPMENT("机械设备工程"),
    STATIC_EQUIPMENT("静置设备与工艺技术结构工程"),
    ELECTRICAL("电气工程"),
    BUILDING_AUTOMATION("建筑智能化工程"),
    PIPELINE("管道工程"),
    FIRE_PROTECTION("消防工程"),
    PURIFICATION("净化工程"),
    VENTILATION_AIR_CONDITIONING("通风与空调工程"),
    EQUIPMENT_PIPE_ANTICORROSION_INSULATION("设备及管道防腐蚀与绝热工程"),
    INDUSTRIAL_FURNACE("工业炉工程");
    TUNNEL_WORKS("隧道"),
    // 固定资产用途类型
    RETAIL("仓储"),
    FOOD("餐饮"),
    EDUCATION("教育"),
    MEDICAL_BEAUTY("医疗美容"),
    ENTERTAINMENT("娱乐"),
    HOTEL("酒店"),
    REFIT("翻新改造"),
    PUBLIC_PLACE("公共场所"),
    ENERGY_STATION("能源站"),
    MULTI_FUNCTION_COMPLEX("综合体");
    private final String desc;
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/HazardSourceType.java
@@ -12,23 +12,13 @@
@Getter
public enum HazardSourceType implements IOptionVo {
    FOUNDATION_PIT("基坑工程"),
    FORMWORK_SUPPORT("模板支撑工程"),
    STEEL_STRUCTURE_INSTALLATION_SUPPORT_SYSTEM("钢结构安装满堂支撑体系"),
    HOISTING_AND_LIFTING("起重吊装工程"),
    CRANE_INSTALLATION("起重机械进行安装的工程"),
    CRANE_INSTALLATION_AND_DISMANTLING("起重机械安装和拆卸工程"),
    GROUND_PIPE_SCAFFOLD("落地式钢管脚手架工程"),
    SUSPENDED_SCAFFOLD("附着式升降脚手架工程"),
    CANTILEVER_SCAFFOLD("悬挑式脚手架工程"),
    HIGH_ALTITUDE_OPERATION_GONDOLA("高处作业吊篮"),
    UNLOADING_PLATFORM_OPERATION_PLATFORM("卸料平台操作平台工程"),
    IRREGULAR_SCAFFOLD("异型脚手架工程"),
    DEMOLITION("拆除工程"),
    BUILDING_CURTAIN_WALL_INSTALLATION("建筑幕墙安装工程"),
    STEEL_STRUCTURE_GRID_AND_MEMBRANE_STRUCTURE_INSTALLATION("钢结构网架和索膜结构安装工程"),
    MANUAL_BORED_PILE("人工挖孔桩工程"),
    PREFABRICATED_COMPONENT_INSTALLATION("装配式建筑混凝土预制构件安装工程");
    HIGH_ALTITUDE_OPERATION("高处作业"),
    FIRE_OPERATION("动火作业"),
    LARGE_CONCRETE_CONSTRUCTION("大体积混凝土浇筑"),
    LIMITED_SPACE_OPERATION("有限空间作业"),
    OCCUPY_CONSTRUCTION("占道施工"),
    SINGLE_PERSON_OPERATION("单人操作及作业"),
    SPACE_INTERSECTION_OPERATION("空间交叉作业");
    private final String desc;
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/ProjectInfo.java
@@ -59,7 +59,10 @@
     */
    @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
    @Column(columnDefinition = "json")
    private HazardSourceType[] hazardSourceTypes;
    private HazardSourceType[] hazardSource;
    /**
admin-server/src/main/java/com/estate/expert/admin/domain/project/info/ProjectInfoDto.java
@@ -11,6 +11,7 @@
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
 * DTO for {@link ProjectInfo}
@@ -43,6 +44,10 @@
    @ApiModelProperty("超大危工程选项")
    ProjectSuperDangerousType[] superDangerousOptions;
    @ApiModelProperty("风险源")
    HazardSourceType[] hazardSource;
    @ApiModelProperty("更新时间")
    @NotNull
    LocalDate updateDate;
admin-server/src/main/java/com/estate/expert/admin/domain/repository/CheckMapper.java
@@ -25,4 +25,5 @@
    CheckVo detail(@Param("id") Integer id);
    List<CheckVo> exportList(@Param("request") OnDutyRequest request, @Param("sTime") String sTime, @Param("eTime") String eTime);
}
admin-server/src/main/java/com/estate/expert/admin/domain/repository/OnDutyMapper.java
@@ -24,4 +24,6 @@
    OnDutyVo detail(Integer id);
    List<OnDutyVo> exportList(@Param("request") OnDutyRequest query, @Param("sTime") String sTime, @Param("eTime") String eTime);
}
admin-server/src/main/java/com/estate/expert/admin/enums/BizResultCode.java
@@ -157,13 +157,16 @@
    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验证失败");
    LICENSE_VALIDATION_FAILED("License验证失败"),
    // 报告生成相关错误码
    BIZ_REPORT_GENERATE_FAILED("报告生成失败");
    private final String errorMsg;
admin-server/src/main/java/com/estate/expert/admin/service/CheckService.java
@@ -61,4 +61,5 @@
     */
    void deleteCheckInfoByIds(List<Integer> ids);
    List<CheckVo> exportList(OnDutyRequest query);
}
admin-server/src/main/java/com/estate/expert/admin/service/OnDutyService.java
@@ -64,4 +64,6 @@
     */
    void deleteByIds(List<Integer> ids);
    List<OnDutyVo> exportList(OnDutyRequest query);
}
admin-server/src/main/java/com/estate/expert/admin/service/ReportService.java
@@ -3,6 +3,8 @@
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import java.io.OutputStream;
/**
 * 报告服务
 **/
@@ -25,6 +27,14 @@
    XWPFTemplate fuzzyReport(Integer checkTaskId, Integer templateId);
    /**
     * 模糊评价PDF
     * @param checkTaskId 检查任务ID
     * @param templateId 模板ID
     * @param outputStream 输出流
     */
    void fuzzyReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream);
    /**
     * 打分评价
     * @param checkTaskId 检查任务ID
     * @param templateId 模板ID
@@ -39,4 +49,12 @@
     * @return 打分评价模板
     */
    XWPFTemplate scoreReport(Integer checkTaskId, Integer templateId);
    /**
     * 打分评价PDF
     * @param checkTaskId 检查任务ID
     * @param templateId 模板ID
     * @param outputStream 输出流
     */
    void scoreReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream);
}
admin-server/src/main/java/com/estate/expert/admin/service/impl/CheckServiceImpl.java
@@ -118,4 +118,16 @@
        // 使用 MyBatis Plus 的批量删除方法(逻辑删除,因为 Check 实体有 @TableLogic 注解)
        removeByIds(ids);
    }
    @Override
    public List<CheckVo> exportList(OnDutyRequest request) {
        String sTime =null;
        String eTime =null;
        if(request.getTime()!=null && !request.getTime().isEmpty()){
            sTime = request.getTime().split(" - ")[0] + " 00:00:00";
            eTime = request.getTime().split(" - ")[1] + " 23:59:59";
        }
        List<CheckVo> list = this.baseMapper.exportList( request,sTime,eTime);
        return list;
    }
}
admin-server/src/main/java/com/estate/expert/admin/service/impl/OnDutyServiceImpl.java
@@ -166,5 +166,17 @@
        // 使用 MyBatis-Plus 的批量删除方法(物理删除)
        this.removeByIds(ids);
    }
    @Override
    public List<OnDutyVo> exportList(OnDutyRequest query) {
        String sTime =null;
        String eTime =null;
        if(query.getTime()!=null && !query.getTime().isEmpty()){
            sTime = query.getTime().split(" - ")[0] + " 00:00:00";
            eTime = query.getTime().split(" - ")[1] + " 23:59:59";
        }
        List<OnDutyVo> list = this.baseMapper.exportList( query,sTime,eTime);
        return list;
    }
}
admin-server/src/main/java/com/estate/expert/admin/service/impl/ReportServiceImpl.java
@@ -18,10 +18,15 @@
import com.estate.expert.admin.stat.report.data.impl.SystemFuzzyReportData;
import com.estate.expert.admin.stat.report.data.impl.SystemScoreReportData;
import com.estate.expert.common.exception.BizException;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
/**
 * 报告数据服务实现类
@@ -116,6 +121,50 @@
        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);
admin-server/src/main/java/com/estate/expert/admin/utils/WebUtils.java
New file
@@ -0,0 +1,170 @@
package com.estate.expert.admin.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
 * web工具类
 *
 * @author liheng
 */
public final class WebUtils extends org.springframework.web.util.WebUtils {
    /**
     * 当前请求
     */
    public static HttpServletRequest request() {
        return contextHolder() == null ? null : contextHolder().getRequest();
    }
    /**
     * 当前响应
     */
    public static HttpServletResponse response() {
        return contextHolder() == null ? null : contextHolder().getResponse();
    }
    /**
     * 当前session
     */
    public static HttpSession session() {
        return request() == null ? null : request().getSession();
    }
    /**
     * 当前ServletRequest
     */
    public static ServletRequestAttributes contextHolder() {
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }
    /**
     * 判断请求是否为 AJAX
     *
     * @param request 当前请求
     */
    public static boolean isAjax(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
    /**
     * 获取操作系统,浏览器及浏览器版本信息
     *
     * @param request
     * @return
     */
    public static Map<String, String> getOsAndBrowserInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>(2);
        String browserDetails = request.getHeader("User-Agent");
        String userAgent = browserDetails;
        String user = userAgent.toLowerCase();
        String os = "";
        String browser = "";
        //=================OS Info=======================
        if (userAgent.toLowerCase().contains("windows")) {
            os = "Windows";
        } else if (userAgent.toLowerCase().contains("mac")) {
            os = "Mac";
        } else if (userAgent.toLowerCase().contains("x11")) {
            os = "Unix";
        } else if (userAgent.toLowerCase().contains("android")) {
            os = "Android";
        } else if (userAgent.toLowerCase().contains("iphone")) {
            os = "IPhone";
        } else {
            os = "UnKnown, More-Info: " + userAgent;
        }
        //===============Browser===========================
        if (user.contains("edge")) {
            browser = (userAgent.substring(userAgent.indexOf("Edge")).split(" ")[0]).replace("/", "-");
        } else if (user.contains("msie")) {
            String substring = userAgent.substring(userAgent.indexOf("MSIE")).split(";")[0];
            browser = substring.split(" ")[0].replace("MSIE", "IE") + "-" + substring.split(" ")[1];
        } else if (user.contains("safari") && user.contains("version")) {
            browser = (userAgent.substring(userAgent.indexOf("Safari")).split(" ")[0]).split("/")[0]
                    + "-" + (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
        } else if (user.contains("opr") || user.contains("opera")) {
            if (user.contains("opera")) {
                browser = (userAgent.substring(userAgent.indexOf("Opera")).split(" ")[0]).split("/")[0]
                        + "-" + (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
            } else if (user.contains("opr")) {
                browser = ((userAgent.substring(userAgent.indexOf("OPR")).split(" ")[0]).replace("/", "-"))
                        .replace("OPR", "Opera");
            }
        } else if (user.contains("chrome")) {
            browser = (userAgent.substring(userAgent.indexOf("Chrome")).split(" ")[0]).replace("/", "-");
        } else if ((user.contains("mozilla/7.0")) || (user.contains("netscape6")) ||
                (user.contains("mozilla/4.7")) || (user.contains("mozilla/4.78")) ||
                (user.contains("mozilla/4.08")) || (user.contains("mozilla/3"))) {
            browser = "Netscape-?";
        } else if (user.contains("firefox")) {
            browser = (userAgent.substring(userAgent.indexOf("Firefox")).split(" ")[0]).replace("/", "-");
        } else if (user.contains("rv")) {
            String IEVersion = (userAgent.substring(userAgent.indexOf("rv")).split(" ")[0]).replace("rv:", "-");
            browser = "IE" + IEVersion.substring(0, IEVersion.length() - 1);
        } else {
            browser = "UnKnown, More-Info: " + userAgent;
        }
        map.put("os", os);
        map.put("browser", browser);
        return map;
    }
    /**
     * 读取cookie
     *
     * @param name cookie name
     * @return cookie value
     */
    public String getCookieVal(String name) {
        return getCookieVal(request(), name);
    }
    /**
     * 读取cookie
     *
     * @param request HttpServletRequest
     * @param name    cookie name
     * @return cookie value
     */
    public String getCookieVal(HttpServletRequest request, String name) {
        Cookie cookie = getCookie(request, name);
        return cookie != null ? cookie.getValue() : null;
    }
    /**
     * 清除 某个指定的cookie
     *
     * @param response HttpServletResponse
     * @param key      cookie key
     */
    public void removeCookie(HttpServletResponse response, String key) {
        setCookie(response, key, null, 0);
    }
    /**
     * 设置cookie
     *
     * @param response        HttpServletResponse
     * @param name            cookie name
     * @param value           cookie value
     * @param maxAgeInSeconds maxage
     */
    public void setCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAgeInSeconds);
        //cookie.setHttpOnly(true);
        response.addCookie(cookie);
    }
}
admin-server/src/main/resources/mapper/CheckMapper.xml
@@ -8,7 +8,7 @@
        t2.name as plan_name,
        t3.name as project_name,
        t4.name as client_name
        from check t1
        from check_info t1
        left join plan t2 on t1.plan_id = t2.id
        left join project t3 on t1.project_id = t3.id
        left join client t4 on t1.client_id = t4.id
@@ -32,10 +32,34 @@
               t2.name as plan_name,
               t3.name as project_name,
               t4.name as client_name
        from check t1
        from check_info t1
                 left join plan t2 on t1.plan_id = t2.id
                 left join project t3 on t1.project_id = t3.id
                 left join client t4 on t1.client_id = t4.id
        where t1.id = #{id}
    </select>
    <select id="exportList" resultType="com.estate.expert.admin.domain.business.check.CheckVo">
        select t1.id,t1.plan_id,t1.project_id,t1.client_id,t1.safety_slip,t1.check_user_img,t1.integrity_notification,t1.time,t1.create_time,
        t2.name as plan_name,
        t3.name as project_name,
        t4.name as client_name
        from check_info t1
        left join plan t2 on t1.plan_id = t2.id
        left join project t3 on t1.project_id = t3.id
        left join client t4 on t1.client_id = t4.id
        where 1=1
        <if test="request.planId != null">
            and t1.plan_id = #{request.planId}
        </if>
        <if test="request.projectId != null">
            and t1.project_id = #{request.projectId}
        </if>
        <if test="request.clientId != null">
            and t1.client_id = #{request.clientId}
        </if>
        <if test="sTime !=null">
            and t1.time between #{sTime} and #{eTime}
        </if>
        order by t1.time desc
    </select>
</mapper>
admin-server/src/main/resources/mapper/OnDutyMapper.xml
@@ -38,4 +38,28 @@
                 left join client t4 on t1.client_id = t4.id
        where t1.id = #{id}
    </select>
    <select id="exportList" resultType="com.estate.expert.admin.domain.business.onduty.OnDutyVo">
        select t1.id,t1.plan_id,t1.project_id,t1.client_id,t1.content,t1.position_id,t1.position_name,t1.remark,t1.img,t1.time,t1.state,t1.create_time,
        t2.name as plan_name,
        t3.name as project_name,
        t4.name as client_name
        from on_duty t1
        left join plan t2 on t1.plan_id = t2.id
        left join project t3 on t1.project_id = t3.id
        left join client t4 on t1.client_id = t4.id
        where 1=1
        <if test="request.planId != null">
            and t1.plan_id = #{request.planId}
        </if>
        <if test="request.projectId != null">
            and t1.project_id = #{request.projectId}
        </if>
        <if test="request.clientId != null">
            and t1.client_id = #{request.clientId}
        </if>
        <if test="sTime !=null">
            and t1.time between #{sTime} and #{eTime}
        </if>
        order by t1.time desc
    </select>
</mapper>