gongchunyi
4 天以前 d2f07163fc4074f335986dd51eedbdc7be9e19ea
fix: 线路巡检调整
已修改11个文件
已添加10个文件
1402 ■■■■■ 文件已修改
doc/20260729_safe_line_inspection_task.sql 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionHazardController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionTaskController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/dto/SafeLineInspectionExecuteDto.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/mapper/SafeLineInspectionTaskMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/pojo/SafeLineInspection.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/pojo/SafeLineInspectionHazard.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/pojo/SafeLineInspectionTask.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/SafeLineInspectionService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/SafeLineInspectionTaskService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionHazardServiceImpl.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionServiceImpl.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskJob.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskScheduler.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskServiceImpl.java 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/safe/SafeLineInspectionHazardMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/safe/SafeLineInspectionMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/safe/SafeLineInspectionTaskMapper.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/20260729_safe_line_inspection_task.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
CREATE TABLE IF NOT EXISTS `safe_line_inspection_task` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
  `inspection_name` varchar(100) DEFAULT NULL COMMENT '巡检任务名称',
  `line_name` varchar(100) DEFAULT NULL COMMENT '线路名称',
  `inspection_project` varchar(1000) DEFAULT NULL COMMENT '巡检项目',
  `inspector_id` varchar(255) DEFAULT NULL COMMENT '巡检人ID,多个用逗号分隔',
  `frequency_type` varchar(20) DEFAULT NULL COMMENT '频率类型 DAILY/WEEKLY/MONTHLY',
  `frequency_detail` varchar(50) DEFAULT NULL COMMENT '频率详情:每日HH:mm;每周MON,HH:mm;每月DD,HH:mm',
  `next_execution_time` datetime DEFAULT NULL COMMENT '下次执行时间',
  `last_execution_time` datetime DEFAULT NULL COMMENT '最后执行时间',
  `is_enabled` tinyint DEFAULT '1' COMMENT '是否启用 0否 1是',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user` int DEFAULT NULL COMMENT '创建人ID',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_user` int DEFAULT NULL COMMENT '更新人ID',
  `tenant_id` bigint DEFAULT NULL COMMENT '租户ID',
  `dept_id` bigint DEFAULT NULL COMMENT '部门ID',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_safe_line_inspection_task_enabled` (`is_enabled`, `next_execution_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='安全生产-线路定时巡检任务';
ALTER TABLE `safe_line_inspection`
  ADD COLUMN `schedule_task_id` bigint DEFAULT NULL COMMENT '定时巡检任务ID' AFTER `id`,
  ADD COLUMN `inspection_project` varchar(1000) DEFAULT NULL COMMENT '巡检项目' AFTER `inspection_type`,
  ADD KEY `idx_safe_line_inspection_schedule_task` (`schedule_task_id`) USING BTREE;
ALTER TABLE `safe_line_inspection`
  ADD COLUMN `inspection_result` varchar(20) DEFAULT NULL COMMENT '巡检结果:正常/异常' AFTER `status`,
  ADD COLUMN `actual_inspection_time` datetime DEFAULT NULL COMMENT '实际巡检时间' AFTER `inspection_result`,
  ADD COLUMN `hidden_id` int DEFAULT NULL COMMENT '关联隐患排查上报ID' AFTER `actual_inspection_time`,
  ADD KEY `idx_safe_line_inspection_hidden` (`hidden_id`) USING BTREE;
ALTER TABLE `safe_line_inspection_hazard`
  ADD COLUMN `safe_hidden_id` int DEFAULT NULL COMMENT '关联隐患排查上报ID' AFTER `record_id`,
  ADD COLUMN `rectify_deadline` date DEFAULT NULL COMMENT '整改期限' AFTER `rectify_user_id`,
  ADD KEY `idx_safe_line_inspection_hazard_hidden` (`safe_hidden_id`) USING BTREE;
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -68,6 +68,7 @@
    SAFE_TRAINING("safe_training"),
    SAFE_HIDDEN_FILE("safe_hidden_file"),
    SAFE_LINE_INSPECTION_RECORD("safe_line_inspection_record"),
    SAFE_LINE_INSPECTION_HAZARD("safe_line_inspection_hazard"),
    SAFE_FACILITY_INSPECTION("safe_facility_inspection"),
    SPECIAL_EQUIPMENT_RECORD("special_equipment_record"),
    SPECIAL_EQUIPMENT_RECTIFICATION("special_equipment_rectification"),
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionController.java
@@ -5,6 +5,7 @@
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.safe.dto.SafeLineInspectionExecuteDto;
import com.ruoyi.safe.pojo.SafeLineInspection;
import com.ruoyi.safe.pojo.SafeLineInspectionHazard;
import com.ruoyi.safe.pojo.SafeLineInspectionRecord;
@@ -16,7 +17,6 @@
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -86,7 +86,7 @@
                .count() > 0;
    }
    @Operation(summary = "完成巡检")
    @Operation(summary = "废弃旧巡检完成接口")
    @Log(title = "线路巡检", businessType = BusinessType.UPDATE)
    @PutMapping("/complete/{id}")
    public R complete(@PathVariable Integer id) {
@@ -97,21 +97,18 @@
        if ("已完成".equals(inspection.getStatus())) {
            return R.fail("巡检任务已完成,请勿重复操作");
        }
        return R.fail("请通过执行巡检提交正常结果;异常记录请在整改跟踪中由整改责任人完成整改");
    }
        // æ ¡éªŒæ˜¯å¦æœ‰æœªæ•´æ”¹çš„隐患
        List<SafeLineInspectionHazard> hazards = safeLineInspectionHazardService.listByInspectionId(id);
        boolean hasUnrectified = hazards.stream()
                .anyMatch(h -> !"已整改".equals(h.getStatus()));
        if (hasUnrectified) {
            return R.fail("存在未整改的隐患,请先完成隐患整改");
    @Operation(summary = "执行巡检")
    @Log(title = "线路巡检", businessType = BusinessType.UPDATE)
    @PutMapping("/execute")
    public R execute(@RequestBody SafeLineInspectionExecuteDto executeDto) {
        try {
            return R.ok(safeLineInspectionService.executeInspection(executeDto));
        } catch (IllegalArgumentException e) {
            return R.fail(e.getMessage());
        }
        Long currentUserId = SecurityUtils.getUserId();
        inspection.setStatus("已完成");
        inspection.setUpdateTime(LocalDateTime.now());
        inspection.setUpdateUser(currentUserId.intValue());
        return R.ok(safeLineInspectionService.updateById(inspection));
    }
    @Operation(summary = "删除线路巡检任务")
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionHazardController.java
@@ -58,7 +58,11 @@
    @Log(title = "线路巡检隐患", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R update(@RequestBody SafeLineInspectionHazard safeLineInspectionHazard) {
        return R.ok(safeLineInspectionHazardService.updateById(safeLineInspectionHazard));
        try {
            return R.ok(safeLineInspectionHazardService.updateById(safeLineInspectionHazard));
        } catch (IllegalArgumentException e) {
            return R.fail(e.getMessage());
        }
    }
    @Operation(summary = "删除线路巡检隐患")
src/main/java/com/ruoyi/safe/controller/SafeLineInspectionTaskController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.ruoyi.safe.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import com.ruoyi.safe.service.SafeLineInspectionTaskService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.quartz.SchedulerException;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * <p>
 * å®‰å…¨ç”Ÿäº§--线路定时巡检任务 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 */
@RestController
@RequestMapping("/safeLineInspectionTask")
@AllArgsConstructor
@Tag(name = "安全生产--线路定时巡检任务")
public class SafeLineInspectionTaskController {
    private SafeLineInspectionTaskService safeLineInspectionTaskService;
    @GetMapping("/page")
    @Operation(summary = "分页查询")
    public R page(Page<SafeLineInspectionTask> page, SafeLineInspectionTask task) {
        return R.ok(safeLineInspectionTaskService.pageSafeLineInspectionTask(page, task));
    }
    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询")
    public R getById(@PathVariable Long id) {
        return R.ok(safeLineInspectionTaskService.getById(id));
    }
    @Operation(summary = "新增线路定时巡检任务")
    @Log(title = "线路定时巡检任务", businessType = BusinessType.INSERT)
    @PostMapping()
    public R add(@RequestBody SafeLineInspectionTask task) throws SchedulerException {
        return R.ok(safeLineInspectionTaskService.saveOrUpdateTask(task));
    }
    @Operation(summary = "修改线路定时巡检任务")
    @Log(title = "线路定时巡检任务", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R update(@RequestBody SafeLineInspectionTask task) throws SchedulerException {
        return R.ok(safeLineInspectionTaskService.saveOrUpdateTask(task));
    }
    @Operation(summary = "删除线路定时巡检任务")
    @Log(title = "线路定时巡检任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R delete(@PathVariable List<Long> ids) {
        return R.ok(safeLineInspectionTaskService.removeTaskByIds(ids));
    }
}
src/main/java/com/ruoyi/safe/dto/SafeLineInspectionExecuteDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.ruoyi.safe.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.basic.dto.StorageBlobDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Schema(name = "SafeLineInspectionExecuteDto", description = "线路巡检执行入参")
public class SafeLineInspectionExecuteDto {
    @Schema(description = "巡检记录实例ID")
    private Integer inspectionId;
    @Schema(description = "巡检结果(正常/异常)")
    private String checkResult;
    @Schema(description = "巡检说明")
    private String checkDesc;
    @Schema(description = "巡检时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime checkTime;
    @Schema(description = "现场照片")
    private List<StorageBlobDTO> storageBlobDTOs;
    @Schema(description = "隐患类型")
    private String hiddenType;
    @Schema(description = "隐患风险等级")
    private String riskLevel;
    @Schema(description = "隐患位置")
    private String hazardLocation;
    @Schema(description = "异常描述/整改要求")
    private String hazardDesc;
    @Schema(description = "整改责任人ID")
    private Integer rectifyUserId;
    @Schema(description = "整改责任人手机号")
    private String rectifyUserMobile;
    @Schema(description = "整改完成期限")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate rectifyTime;
}
src/main/java/com/ruoyi/safe/mapper/SafeLineInspectionTaskMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
package com.ruoyi.safe.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * å®‰å…¨ç”Ÿäº§--线路定时巡检任务 Mapper æŽ¥å£
 * </p>
 */
@Mapper
public interface SafeLineInspectionTaskMapper extends BaseMapper<SafeLineInspectionTask> {
}
src/main/java/com/ruoyi/safe/pojo/SafeLineInspection.java
@@ -33,6 +33,9 @@
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @Schema(description = "定时巡检任务ID")
    private Long scheduleTaskId;
    @Schema(description = "巡检编号")
    private String inspectionCode;
@@ -44,6 +47,9 @@
    @Schema(description = "巡检类型")
    private String inspectionType;
    @Schema(description = "巡检项目")
    private String inspectionProject;
    @Schema(description = "计划巡检时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -59,6 +65,17 @@
    @Schema(description = "状态(待巡检/巡检中/已完成)")
    private String status;
    @Schema(description = "巡检结果(正常/异常)")
    private String inspectionResult;
    @Schema(description = "实际巡检时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime actualInspectionTime;
    @Schema(description = "关联隐患排查上报ID")
    private Integer hiddenId;
    @Schema(description = "备注")
    private String remark;
src/main/java/com/ruoyi/safe/pojo/SafeLineInspectionHazard.java
@@ -5,8 +5,12 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.basic.dto.StorageBlobDTO;
import com.ruoyi.basic.dto.StorageBlobVO;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -39,6 +43,9 @@
    @Schema(description = "巡检记录ID")
    private Integer recordId;
    @Schema(description = "关联隐患排查上报ID")
    private Integer safeHiddenId;
    @Schema(description = "隐患编号")
    private String hazardCode;
@@ -59,6 +66,11 @@
    @Schema(description = "整改责任人ID")
    private Integer rectifyUserId;
    @Schema(description = "整改期限")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate rectifyDeadline;
    @Schema(description = "整改时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -86,4 +98,19 @@
    @TableField(exist = false)
    private String rectifyUserName;
    @TableField(exist = false)
    private String inspectionCode;
    @TableField(exist = false)
    private String inspectionName;
    @TableField(exist = false)
    private String lineName;
    @TableField(exist = false)
    private List<StorageBlobDTO> storageBlobDTOs;
    @TableField(exist = false)
    private List<StorageBlobVO> storageBlobVOs;
}
src/main/java/com/ruoyi/safe/pojo/SafeLineInspectionTask.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
package com.ruoyi.safe.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
 * <p>
 * å®‰å…¨ç”Ÿäº§--线路定时巡检任务
 * </p>
 */
@Data
@TableName("safe_line_inspection_task")
@Schema(name = "SafeLineInspectionTask对象", description = "安全生产--线路定时巡检任务")
public class SafeLineInspectionTask implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @Schema(description = "巡检任务名称")
    private String inspectionName;
    @Schema(description = "线路名称")
    private String lineName;
    @Schema(description = "巡检项目")
    private String inspectionProject;
    @Schema(description = "巡检人ID(多个用逗号分隔)")
    private String inspectorId;
    @Schema(description = "频率类型 DAILY/WEEKLY/MONTHLY")
    private String frequencyType;
    @Schema(description = "频率详情")
    private String frequencyDetail;
    @Schema(description = "下次执行时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime nextExecutionTime;
    @Schema(description = "最后执行时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastExecutionTime;
    @Schema(description = "是否启用 0否 1是")
    private Integer isEnabled;
    @Schema(description = "备注")
    private String remark;
    @Schema(description = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @Schema(description = "创建人ID")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @Schema(description = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    @Schema(description = "更新人ID")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @Schema(description = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @Schema(description = "部门ID")
    @TableField(fill = FieldFill.INSERT)
    private Long deptId;
    @TableField(exist = false)
    private String inspectorName;
    @TableField(exist = false)
    private List<String> inspector;
}
src/main/java/com/ruoyi/safe/service/SafeLineInspectionService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.safe.dto.SafeLineInspectionExecuteDto;
import com.ruoyi.safe.pojo.SafeLineInspection;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -16,4 +17,6 @@
public interface SafeLineInspectionService extends IService<SafeLineInspection> {
    IPage<SafeLineInspection> pageSafeLineInspection(Page page, SafeLineInspection safeLineInspection);
    boolean executeInspection(SafeLineInspectionExecuteDto executeDto);
}
src/main/java/com/ruoyi/safe/service/SafeLineInspectionTaskService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.safe.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import org.quartz.SchedulerException;
import java.time.LocalDateTime;
import java.util.List;
/**
 * <p>
 * å®‰å…¨ç”Ÿäº§--线路定时巡检任务 æœåŠ¡ç±»
 * </p>
 */
public interface SafeLineInspectionTaskService extends IService<SafeLineInspectionTask> {
    IPage<SafeLineInspectionTask> pageSafeLineInspectionTask(Page<SafeLineInspectionTask> page, SafeLineInspectionTask task);
    boolean saveOrUpdateTask(SafeLineInspectionTask task) throws SchedulerException;
    boolean removeTaskByIds(List<Long> ids);
    LocalDateTime calculateFirstExecutionTime(String frequencyType, String frequencyDetail);
    LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime);
}
src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
@@ -63,6 +63,9 @@
        safeHiddenMapper.updateById(safeHidden);
        String type = sysDictDataService.selectDictLabel("hidden_danger_type", safeHidden.getType());
        if (!StringUtils.hasText(type)) {
            type = safeHidden.getType();
        }
        sysNoticeService.simpleNoticeByUser("隐患排查上报整改",
                "隐患类型:" + type + "\t" +
                        "隐患风险等级:" + safeHidden.getRiskLevel() + "\t" +
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionHazardServiceImpl.java
@@ -2,16 +2,27 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.dto.StorageBlobVO;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.safe.mapper.SafeLineInspectionHazardMapper;
import com.ruoyi.safe.mapper.SafeLineInspectionMapper;
import com.ruoyi.safe.pojo.SafeHidden;
import com.ruoyi.safe.pojo.SafeLineInspection;
import com.ruoyi.safe.pojo.SafeLineInspectionHazard;
import com.ruoyi.safe.service.SafeHiddenService;
import com.ruoyi.safe.service.SafeLineInspectionHazardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@@ -29,17 +40,37 @@
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SafeHiddenService safeHiddenService;
    @Autowired
    private SafeLineInspectionMapper safeLineInspectionMapper;
    @Autowired
    private FileUtil fileUtil;
    @Override
    public IPage<SafeLineInspectionHazard> pageSafeLineInspectionHazard(Page page, SafeLineInspectionHazard safeLineInspectionHazard) {
        IPage<SafeLineInspectionHazard> result = this.lambdaQuery()
                .eq(safeLineInspectionHazard.getInspectionId() != null, SafeLineInspectionHazard::getInspectionId, safeLineInspectionHazard.getInspectionId())
                .like(safeLineInspectionHazard.getHazardCode() != null, SafeLineInspectionHazard::getHazardCode, safeLineInspectionHazard.getHazardCode())
                .eq(safeLineInspectionHazard.getStatus() != null, SafeLineInspectionHazard::getStatus, safeLineInspectionHazard.getStatus())
                .like(StringUtils.isNotBlank(safeLineInspectionHazard.getHazardCode()), SafeLineInspectionHazard::getHazardCode, safeLineInspectionHazard.getHazardCode())
                .like(StringUtils.isNotBlank(safeLineInspectionHazard.getHazardDesc()), SafeLineInspectionHazard::getHazardDesc, safeLineInspectionHazard.getHazardDesc())
                .eq(StringUtils.isNotBlank(safeLineInspectionHazard.getStatus()), SafeLineInspectionHazard::getStatus, safeLineInspectionHazard.getStatus())
                .orderByDesc(SafeLineInspectionHazard::getCreateTime)
                .page(page);
        fillRectifyUserName(result.getRecords());
        fillInspectionInfo(result.getRecords());
        fillRectifyAttachments(result.getRecords());
        return result;
    }
    @Override
    public SafeLineInspectionHazard getById(Serializable id) {
        SafeLineInspectionHazard record = super.getById(id);
        if (record != null) {
            fillRectifyUserName(Collections.singletonList(record));
            fillInspectionInfo(Collections.singletonList(record));
            fillRectifyAttachments(Collections.singletonList(record));
        }
        return record;
    }
    @Override
@@ -49,6 +80,8 @@
                .orderByDesc(SafeLineInspectionHazard::getCreateTime)
                .list();
        fillRectifyUserName(records);
        fillInspectionInfo(records);
        fillRectifyAttachments(records);
        return records;
    }
@@ -62,12 +95,65 @@
    @Override
    public boolean updateById(SafeLineInspectionHazard entity) {
        SafeLineInspectionHazard oldRecord = entity.getId() == null ? null : this.getById(entity.getId());
        if (oldRecord == null) {
            throw new IllegalArgumentException("整改记录不存在");
        }
        Integer safeHiddenId = entity.getSafeHiddenId() != null
                ? entity.getSafeHiddenId()
                : oldRecord.getSafeHiddenId();
        if ("已整改".equals(entity.getStatus())) {
            Long currentUserId = SecurityUtils.getUserId();
            entity.setRectifyUserId(currentUserId.intValue());
            validateRectify(entity, oldRecord);
            entity.setRectifyUserId(oldRecord.getRectifyUserId());
            entity.setRectifyTime(LocalDateTime.now());
        }
        return super.updateById(entity);
        boolean updated = super.updateById(entity);
        if (updated && "已整改".equals(entity.getStatus())) {
            syncRectifyAttachments(entity);
        }
        if (updated && "已整改".equals(entity.getStatus()) && safeHiddenId != null) {
            SafeHidden hidden = new SafeHidden();
            hidden.setId(safeHiddenId);
            hidden.setRectifyMeasures(entity.getRectifyDesc());
            hidden.setRectifyActualTime(LocalDate.now());
            safeHiddenService.updateById(hidden);
        }
        if (updated && "已整改".equals(entity.getStatus())) {
            Integer inspectionId = entity.getInspectionId() != null
                    ? entity.getInspectionId()
                    : oldRecord.getInspectionId();
            completeInspectionIfAllRectified(inspectionId);
        }
        return updated;
    }
    private void validateRectify(SafeLineInspectionHazard entity, SafeLineInspectionHazard oldRecord) {
        if ("已整改".equals(oldRecord.getStatus())) {
            throw new IllegalArgumentException("该隐患已整改,请勿重复操作");
        }
        Long currentUserId = SecurityUtils.getUserId();
        if (oldRecord.getRectifyUserId() == null || currentUserId == null
                || !oldRecord.getRectifyUserId().equals(currentUserId.intValue())) {
            throw new IllegalArgumentException("只有整改责任人可以进行整改");
        }
        if (StringUtils.isBlank(entity.getRectifyDesc())) {
            throw new IllegalArgumentException("请输入整改说明");
        }
        if (entity.getStorageBlobDTOs() == null || entity.getStorageBlobDTOs().isEmpty()) {
            throw new IllegalArgumentException("请上传整改后照片");
        }
    }
    private void syncRectifyAttachments(SafeLineInspectionHazard entity) {
        if (entity.getId() == null || entity.getStorageBlobDTOs() == null) {
            return;
        }
        fileUtil.saveStorageAttachment(
                ApplicationTypeEnum.IMAGE,
                RecordTypeEnum.SAFE_LINE_INSPECTION_HAZARD,
                entity.getId().longValue(),
                entity.getStorageBlobDTOs()
        );
    }
    private String generateHazardCode() {
@@ -96,4 +182,66 @@
            }
        });
    }
    private void fillInspectionInfo(List<SafeLineInspectionHazard> records) {
        if (records == null || records.isEmpty()) {
            return;
        }
        List<Integer> inspectionIds = records.stream()
                .map(SafeLineInspectionHazard::getInspectionId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (inspectionIds.isEmpty()) {
            return;
        }
        Map<Integer, SafeLineInspection> inspectionMap = safeLineInspectionMapper.selectBatchIds(inspectionIds).stream()
                .collect(Collectors.toMap(SafeLineInspection::getId, item -> item, (v1, v2) -> v1));
        records.forEach(record -> {
            SafeLineInspection inspection = inspectionMap.get(record.getInspectionId());
            if (inspection != null) {
                record.setInspectionCode(inspection.getInspectionCode());
                record.setInspectionName(inspection.getInspectionName());
                record.setLineName(inspection.getLineName());
            }
        });
    }
    private void fillRectifyAttachments(List<SafeLineInspectionHazard> records) {
        if (records == null || records.isEmpty()) {
            return;
        }
        records.forEach(record -> {
            if (record.getId() == null) {
                return;
            }
            List<StorageBlobVO> attachments = fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(
                    RecordTypeEnum.SAFE_LINE_INSPECTION_HAZARD,
                    record.getId().longValue()
            );
            record.setStorageBlobVOs(attachments == null ? Collections.emptyList() : attachments);
        });
    }
    private void completeInspectionIfAllRectified(Integer inspectionId) {
        if (inspectionId == null) {
            return;
        }
        long unrectifiedCount = this.lambdaQuery()
                .eq(SafeLineInspectionHazard::getInspectionId, inspectionId)
                .ne(SafeLineInspectionHazard::getStatus, "已整改")
                .count();
        if (unrectifiedCount > 0) {
            return;
        }
        SafeLineInspection inspection = safeLineInspectionMapper.selectById(inspectionId);
        if (inspection == null || "已完成".equals(inspection.getStatus())) {
            return;
        }
        Long currentUserId = SecurityUtils.getUserId();
        inspection.setStatus("已完成");
        inspection.setUpdateTime(LocalDateTime.now());
        inspection.setUpdateUser(currentUserId == null ? null : currentUserId.intValue());
        safeLineInspectionMapper.updateById(inspection);
    }
}
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionServiceImpl.java
@@ -2,15 +2,29 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.safe.dto.SafeLineInspectionExecuteDto;
import com.ruoyi.safe.pojo.SafeLineInspection;
import com.ruoyi.safe.mapper.SafeLineInspectionMapper;
import com.ruoyi.safe.pojo.SafeLineInspectionHazard;
import com.ruoyi.safe.pojo.SafeLineInspectionRecord;
import com.ruoyi.safe.pojo.SafeHidden;
import com.ruoyi.safe.service.SafeHiddenService;
import com.ruoyi.safe.service.SafeLineInspectionHazardService;
import com.ruoyi.safe.service.SafeLineInspectionRecordService;
import com.ruoyi.safe.service.SafeLineInspectionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -29,14 +43,24 @@
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SafeLineInspectionRecordService safeLineInspectionRecordService;
    @Autowired
    private SafeLineInspectionHazardService safeLineInspectionHazardService;
    @Autowired
    private SafeHiddenService safeHiddenService;
    @Autowired
    private FileUtil fileUtil;
    @Override
    public IPage<SafeLineInspection> pageSafeLineInspection(Page page, SafeLineInspection safeLineInspection) {
        IPage<SafeLineInspection> result = this.lambdaQuery()
                .like(safeLineInspection.getInspectionCode() != null, SafeLineInspection::getInspectionCode, safeLineInspection.getInspectionCode())
                .like(safeLineInspection.getInspectionName() != null, SafeLineInspection::getInspectionName, safeLineInspection.getInspectionName())
                .like(safeLineInspection.getLineName() != null, SafeLineInspection::getLineName, safeLineInspection.getLineName())
                .eq(safeLineInspection.getStatus() != null, SafeLineInspection::getStatus, safeLineInspection.getStatus())
                .eq(safeLineInspection.getScheduleTaskId() != null, SafeLineInspection::getScheduleTaskId, safeLineInspection.getScheduleTaskId())
                .like(StringUtils.isNotBlank(safeLineInspection.getInspectionCode()), SafeLineInspection::getInspectionCode, safeLineInspection.getInspectionCode())
                .like(StringUtils.isNotBlank(safeLineInspection.getInspectionName()), SafeLineInspection::getInspectionName, safeLineInspection.getInspectionName())
                .like(StringUtils.isNotBlank(safeLineInspection.getLineName()), SafeLineInspection::getLineName, safeLineInspection.getLineName())
                .like(StringUtils.isNotBlank(safeLineInspection.getInspectionProject()), SafeLineInspection::getInspectionProject, safeLineInspection.getInspectionProject())
                .eq(StringUtils.isNotBlank(safeLineInspection.getStatus()), SafeLineInspection::getStatus, safeLineInspection.getStatus())
                .orderByDesc(SafeLineInspection::getCreateTime)
                .page(page);
@@ -46,6 +70,144 @@
        return result;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean executeInspection(SafeLineInspectionExecuteDto executeDto) {
        if (executeDto == null || executeDto.getInspectionId() == null) {
            throw new IllegalArgumentException("巡检记录不能为空");
        }
        SafeLineInspection inspection = this.getById(executeDto.getInspectionId());
        if (inspection == null) {
            throw new IllegalArgumentException("巡检记录不存在");
        }
        if ("已完成".equals(inspection.getStatus())) {
            throw new IllegalArgumentException("巡检记录已完成,请勿重复执行");
        }
        if (!"正常".equals(executeDto.getCheckResult()) && !"异常".equals(executeDto.getCheckResult())) {
            throw new IllegalArgumentException("请选择巡检结果");
        }
        LocalDateTime checkTime = executeDto.getCheckTime() == null ? LocalDateTime.now() : executeDto.getCheckTime();
        SafeLineInspectionRecord record = buildInspectionRecord(inspection, executeDto, checkTime);
        safeLineInspectionRecordService.save(record);
        inspection.setInspectionResult(executeDto.getCheckResult());
        inspection.setActualInspectionTime(checkTime);
        inspection.setUpdateTime(LocalDateTime.now());
        inspection.setUpdateUser(SecurityUtils.getUserId().intValue());
        appendCurrentInspector(inspection);
        if ("异常".equals(executeDto.getCheckResult())) {
            validateHazard(executeDto);
            SafeHidden hidden = createSafeHidden(executeDto);
            safeHiddenService.add(hidden);
            fileUtil.saveStorageAttachment(
                    ApplicationTypeEnum.IMAGE,
                    RecordTypeEnum.SAFE_HIDDEN,
                    hidden.getId().longValue(),
                    executeDto.getStorageBlobDTOs()
            );
            SafeLineInspectionHazard hazard = buildLineHazard(inspection, record, hidden, executeDto);
            safeLineInspectionHazardService.save(hazard);
            inspection.setHiddenId(hidden.getId());
            inspection.setStatus("待整改");
        } else {
            inspection.setHiddenId(null);
            inspection.setStatus("已完成");
        }
        return this.updateById(inspection);
    }
    private SafeLineInspectionRecord buildInspectionRecord(SafeLineInspection inspection,
                                                           SafeLineInspectionExecuteDto executeDto,
                                                           LocalDateTime checkTime) {
        SafeLineInspectionRecord record = new SafeLineInspectionRecord();
        record.setInspectionId(inspection.getId());
        record.setCheckPoint(inspection.getLineName());
        record.setCheckContent(inspection.getInspectionProject());
        record.setCheckResult(executeDto.getCheckResult());
        record.setCheckDesc("异常".equals(executeDto.getCheckResult()) ? null : executeDto.getCheckDesc());
        record.setCheckTime(checkTime);
        record.setStorageBlobDTOs(executeDto.getStorageBlobDTOs());
        return record;
    }
    private void validateHazard(SafeLineInspectionExecuteDto executeDto) {
        if (executeDto.getStorageBlobDTOs() == null || executeDto.getStorageBlobDTOs().isEmpty()) {
            throw new IllegalArgumentException("巡检异常时请上传异常照片");
        }
        if (StringUtils.isBlank(executeDto.getHiddenType())) {
            throw new IllegalArgumentException("请选择隐患类型");
        }
        if (StringUtils.isBlank(executeDto.getRiskLevel())) {
            throw new IllegalArgumentException("请选择隐患风险等级");
        }
        if (StringUtils.isBlank(executeDto.getHazardLocation())) {
            throw new IllegalArgumentException("请输入隐患位置");
        }
        if (StringUtils.isBlank(executeDto.getHazardDesc())) {
            throw new IllegalArgumentException("请输入异常描述/整改要求");
        }
        if (executeDto.getRectifyUserId() == null) {
            throw new IllegalArgumentException("请选择整改责任人");
        }
        if (executeDto.getRectifyTime() == null) {
            throw new IllegalArgumentException("请选择整改完成期限");
        }
    }
    private SafeHidden createSafeHidden(SafeLineInspectionExecuteDto executeDto) {
        SafeHidden hidden = new SafeHidden();
        hidden.setType(executeDto.getHiddenType());
        hidden.setRiskLevel(executeDto.getRiskLevel());
        hidden.setLocation(executeDto.getHazardLocation());
        hidden.setHiddenDesc(executeDto.getHazardDesc());
        hidden.setRectifyUserId(executeDto.getRectifyUserId());
        hidden.setRectifyUserMobile(executeDto.getRectifyUserMobile());
        hidden.setRectifyTime(executeDto.getRectifyTime());
        return hidden;
    }
    private SafeLineInspectionHazard buildLineHazard(SafeLineInspection inspection,
                                                     SafeLineInspectionRecord record,
                                                     SafeHidden hidden,
                                                     SafeLineInspectionExecuteDto executeDto) {
        SafeLineInspectionHazard hazard = new SafeLineInspectionHazard();
        hazard.setInspectionId(inspection.getId());
        hazard.setRecordId(record.getId());
        hazard.setSafeHiddenId(hidden.getId());
        hazard.setHazardCode(hidden.getHiddenCode());
        hazard.setHazardDesc(executeDto.getHazardDesc());
        hazard.setHazardLevel(executeDto.getRiskLevel());
        hazard.setHazardLocation(executeDto.getHazardLocation());
        hazard.setStatus("待整改");
        hazard.setRectifyUserId(executeDto.getRectifyUserId());
        hazard.setRectifyDeadline(executeDto.getRectifyTime());
        return hazard;
    }
    private void appendCurrentInspector(SafeLineInspection inspection) {
        Long currentUserId = SecurityUtils.getUserId();
        if (currentUserId == null) {
            return;
        }
        String currentUserIdStr = String.valueOf(currentUserId);
        String inspectorId = inspection.getInspectorId();
        if (StringUtils.isBlank(inspectorId)) {
            inspection.setInspectorId(currentUserIdStr);
            return;
        }
        boolean exists = Arrays.stream(inspectorId.split(","))
                .map(String::trim)
                .anyMatch(currentUserIdStr::equals);
        if (!exists) {
            inspection.setInspectorId(inspectorId + "," + currentUserIdStr);
        }
    }
    /**
     * å¡«å……巡检人名称(支持多巡检人,逗号分隔)
     */
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,171 @@
package com.ruoyi.safe.service.impl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.safe.mapper.SafeLineInspectionMapper;
import com.ruoyi.safe.mapper.SafeLineInspectionTaskMapper;
import com.ruoyi.safe.pojo.SafeLineInspection;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.Set;
@Component
@DisallowConcurrentExecution
public class SafeLineInspectionTaskJob implements Job, Serializable {
    private static final long serialVersionUID = 1L;
    private static final DateTimeFormatter CODE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    @Autowired
    private SafeLineInspectionTaskMapper safeLineInspectionTaskMapper;
    @Autowired
    private SafeLineInspectionMapper safeLineInspectionMapper;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        Long taskId = jobDataMap.getLong("taskId");
        try {
            SafeLineInspectionTask task = safeLineInspectionTaskMapper.selectById(taskId);
            if (task == null || Integer.valueOf(0).equals(task.getIsEnabled())) {
                return;
            }
            LocalDateTime executionTime = LocalDateTime.now();
            SafeLineInspection inspection = createLineInspection(task, executionTime);
            safeLineInspectionMapper.insert(inspection);
            task.setLastExecutionTime(executionTime);
            task.setNextExecutionTime(calculateNextExecutionTime(
                    task.getFrequencyType(),
                    task.getFrequencyDetail(),
                    executionTime
            ));
            safeLineInspectionTaskMapper.updateById(task);
        } catch (Exception e) {
            throw new JobExecutionException(e);
        }
    }
    private SafeLineInspection createLineInspection(SafeLineInspectionTask task, LocalDateTime executionTime) {
        SafeLineInspection inspection = new SafeLineInspection();
        inspection.setScheduleTaskId(task.getId());
        inspection.setInspectionCode("XLXJ-" + executionTime.format(CODE_FORMATTER) + "-" + task.getId());
        inspection.setInspectionName(task.getInspectionName());
        inspection.setLineName(task.getLineName());
        inspection.setInspectionType("定期巡检");
        inspection.setInspectionProject(task.getInspectionProject());
        inspection.setPlanTime(task.getNextExecutionTime() != null ? task.getNextExecutionTime() : executionTime);
        inspection.setAssignUserId(task.getCreateUser());
        inspection.setInspectorId(task.getInspectorId());
        inspection.setStatus("待巡检");
        inspection.setRemark(buildRemark(task));
        inspection.setCreateUser(task.getCreateUser());
        inspection.setUpdateUser(task.getCreateUser());
        inspection.setCreateTime(executionTime);
        inspection.setUpdateTime(executionTime);
        inspection.setTenantId(task.getTenantId() == null ? null : task.getTenantId().intValue());
        inspection.setDeptId(task.getDeptId());
        return inspection;
    }
    private String buildRemark(SafeLineInspectionTask task) {
        String remark = "自动生成自定时任务ID: " + task.getId();
        if (StringUtils.isNotBlank(task.getRemark())) {
            remark = remark + ";" + task.getRemark();
        }
        return remark;
    }
    private LocalDateTime calculateNextExecutionTime(String frequencyType,
                                                     String frequencyDetail,
                                                     LocalDateTime currentTime) {
        return switch (frequencyType) {
            case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime);
            case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime);
            case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime);
            default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
        };
    }
    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
        LocalTime executionTime = LocalTime.parse(timeStr);
        LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime);
        return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1);
    }
    private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        LocalTime time = LocalTime.parse(parts[1].trim());
        Set<DayOfWeek> targetDays = parseDayOfWeeks(parts[0]);
        LocalDateTime nextTime = current;
        while (true) {
            nextTime = nextTime.plusDays(1);
            if (targetDays.contains(nextTime.getDayOfWeek())) {
                return LocalDateTime.of(nextTime.toLocalDate(), time);
            }
            if (nextTime.isAfter(current.plusYears(1))) {
                throw new RuntimeException("无法找到下次执行时间");
            }
        }
    }
    private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int dayOfMonth = Integer.parseInt(parts[0].trim());
        LocalTime time = LocalTime.parse(parts[1].trim());
        YearMonth currentMonth = YearMonth.from(current);
        for (int i = 0; i < 24; i++) {
            YearMonth targetMonth = currentMonth.plusMonths(i);
            if (dayOfMonth > targetMonth.lengthOfMonth()) {
                continue;
            }
            LocalDateTime candidate = LocalDateTime.of(
                    targetMonth.getYear(),
                    targetMonth.getMonthValue(),
                    dayOfMonth,
                    time.getHour(),
                    time.getMinute()
            );
            if (current.isBefore(candidate)) {
                return candidate;
            }
        }
        throw new IllegalArgumentException("无法计算下次执行时间");
    }
    private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
        Set<DayOfWeek> days = new HashSet<>();
        String[] dayStrs = dayOfWeekStr.split("\\|");
        for (String dayStr : dayStrs) {
            switch (dayStr.trim()) {
                case "MON" -> days.add(DayOfWeek.MONDAY);
                case "TUE" -> days.add(DayOfWeek.TUESDAY);
                case "WED" -> days.add(DayOfWeek.WEDNESDAY);
                case "THU" -> days.add(DayOfWeek.THURSDAY);
                case "FRI" -> days.add(DayOfWeek.FRIDAY);
                case "SAT" -> days.add(DayOfWeek.SATURDAY);
                case "SUN" -> days.add(DayOfWeek.SUNDAY);
                default -> throw new IllegalArgumentException("无效的星期几: " + dayStr);
            }
        }
        return days;
    }
}
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskScheduler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
package com.ruoyi.safe.service.impl;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import lombok.RequiredArgsConstructor;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class SafeLineInspectionTaskScheduler {
    private static final String JOB_GROUP = "safeLineInspectionTask";
    private static final String TRIGGER_GROUP = "safeLineInspectionTaskTrigger";
    private final Scheduler scheduler;
    public void scheduleTask(SafeLineInspectionTask task) throws SchedulerException {
        JobDetail jobDetail = buildJobDetail(task);
        if (scheduler.checkExists(jobDetail.getKey())) {
            scheduler.deleteJob(jobDetail.getKey());
        }
        scheduler.scheduleJob(jobDetail, buildJobTrigger(task, jobDetail));
    }
    public void rescheduleTask(SafeLineInspectionTask task) throws SchedulerException {
        TriggerKey triggerKey = getTriggerKey(task.getId());
        Trigger oldTrigger = scheduler.getTrigger(triggerKey);
        if (oldTrigger == null) {
            scheduleTask(task);
            return;
        }
        JobDetail jobDetail = scheduler.getJobDetail(oldTrigger.getJobKey());
        if (jobDetail == null) {
            scheduleTask(task);
            return;
        }
        scheduler.rescheduleJob(triggerKey, buildJobTrigger(task, jobDetail));
    }
    public void unscheduleTask(Long taskId) {
        try {
            scheduler.deleteJob(getJobKey(taskId));
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
    private JobDetail buildJobDetail(SafeLineInspectionTask task) {
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("taskId", task.getId());
        jobDataMap.put("taskName", task.getInspectionName());
        jobDataMap.put("frequencyType", task.getFrequencyType());
        return JobBuilder.newJob(SafeLineInspectionTaskJob.class)
                .withIdentity(getJobKey(task.getId()))
                .withDescription(task.getInspectionName())
                .usingJobData(jobDataMap)
                .storeDurably(true)
                .requestRecovery(true)
                .build();
    }
    private Trigger buildJobTrigger(SafeLineInspectionTask task, JobDetail jobDetail) {
        return TriggerBuilder.newTrigger()
                .withIdentity(getTriggerKey(task.getId()))
                .withDescription(task.getInspectionName() + "_TRIGGER")
                .forJob(jobDetail)
                .withSchedule(CronScheduleBuilder
                        .cronSchedule(convertToCronExpression(task))
                        .withMisfireHandlingInstructionDoNothing())
                .startAt(task.getNextExecutionTime() != null
                        ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())
                        : new Date())
                .build();
    }
    private JobKey getJobKey(Long taskId) {
        return new JobKey("safeLineInspectionTask_" + taskId, JOB_GROUP);
    }
    private TriggerKey getTriggerKey(Long taskId) {
        return new TriggerKey("safeLineInspectionTaskTrigger_" + taskId, TRIGGER_GROUP);
    }
    private String convertToCronExpression(SafeLineInspectionTask task) {
        if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) {
            throw new IllegalArgumentException("任务频率不能为空");
        }
        return switch (task.getFrequencyType().toUpperCase()) {
            case "DAILY" -> convertDailyToCron(task.getFrequencyDetail());
            case "WEEKLY" -> convertWeeklyToCron(task.getFrequencyDetail());
            case "MONTHLY" -> convertMonthlyToCron(task.getFrequencyDetail());
            default -> throw new IllegalArgumentException("不支持的频率类型: " + task.getFrequencyType());
        };
    }
    private String convertDailyToCron(String frequencyDetail) {
        LocalTime time = parseTime(frequencyDetail);
        return String.format("0 %d %d * * ?", time.getMinute(), time.getHour());
    }
    private String convertWeeklyToCron(String frequencyDetail) {
        String[] parts = validateAndSplit(frequencyDetail, 2);
        String daysOfWeek = Arrays.stream(parts[0].split("\\|"))
                .map(this::convertSingleDayName)
                .collect(Collectors.joining(","));
        LocalTime time = parseTime(parts[1]);
        return String.format("0 %d %d ? * %s", time.getMinute(), time.getHour(), daysOfWeek);
    }
    private String convertMonthlyToCron(String frequencyDetail) {
        String[] parts = validateAndSplit(frequencyDetail, 2);
        int day = validateDayOfMonth(parts[0]);
        LocalTime time = parseTime(parts[1]);
        return String.format("0 %d %d %d * ?", time.getMinute(), time.getHour(), day);
    }
    private String[] validateAndSplit(String input, int expectedParts) {
        String[] parts = input.split(",");
        if (parts.length != expectedParts) {
            throw new IllegalArgumentException("任务频率详情格式错误");
        }
        return Arrays.stream(parts).map(String::trim).toArray(String[]::new);
    }
    private LocalTime parseTime(String timeStr) {
        try {
            return LocalTime.parse(timeStr);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("时间格式必须为HH:mm", e);
        }
    }
    private int validateDayOfMonth(String dayStr) {
        int day = Integer.parseInt(dayStr);
        if (day < 1 || day > 31) {
            throw new IllegalArgumentException("日期必须在1-31之间");
        }
        return day;
    }
    private String convertSingleDayName(String dayName) {
        return switch (dayName.toUpperCase()) {
            case "MON" -> "MON";
            case "TUE" -> "TUE";
            case "WED" -> "WED";
            case "THU" -> "THU";
            case "FRI" -> "FRI";
            case "SAT" -> "SAT";
            case "SUN" -> "SUN";
            default -> throw new IllegalArgumentException("无效的星期几: " + dayName);
        };
    }
}
src/main/java/com/ruoyi/safe/service/impl/SafeLineInspectionTaskServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,312 @@
package com.ruoyi.safe.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.safe.mapper.SafeLineInspectionTaskMapper;
import com.ruoyi.safe.pojo.SafeLineInspectionTask;
import com.ruoyi.safe.service.SafeLineInspectionTaskService;
import lombok.RequiredArgsConstructor;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * <p>
 * å®‰å…¨ç”Ÿäº§--线路定时巡检任务 æœåŠ¡å®žçŽ°ç±»
 * </p>
 */
@Service
@RequiredArgsConstructor
public class SafeLineInspectionTaskServiceImpl extends ServiceImpl<SafeLineInspectionTaskMapper, SafeLineInspectionTask> implements SafeLineInspectionTaskService {
    private static final int ENABLED = 1;
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
    private static final Map<String, DayOfWeek> WEEK_DAY_MAP = new HashMap<>();
    static {
        WEEK_DAY_MAP.put("MON", DayOfWeek.MONDAY);
        WEEK_DAY_MAP.put("TUE", DayOfWeek.TUESDAY);
        WEEK_DAY_MAP.put("WED", DayOfWeek.WEDNESDAY);
        WEEK_DAY_MAP.put("THU", DayOfWeek.THURSDAY);
        WEEK_DAY_MAP.put("FRI", DayOfWeek.FRIDAY);
        WEEK_DAY_MAP.put("SAT", DayOfWeek.SATURDAY);
        WEEK_DAY_MAP.put("SUN", DayOfWeek.SUNDAY);
    }
    private final SafeLineInspectionTaskMapper safeLineInspectionTaskMapper;
    private final SafeLineInspectionTaskScheduler safeLineInspectionTaskScheduler;
    private final SysUserMapper sysUserMapper;
    @Override
    public IPage<SafeLineInspectionTask> pageSafeLineInspectionTask(Page<SafeLineInspectionTask> page, SafeLineInspectionTask task) {
        LambdaQueryWrapper<SafeLineInspectionTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(task.getInspectionName()), SafeLineInspectionTask::getInspectionName, task.getInspectionName())
                .like(StringUtils.isNotBlank(task.getLineName()), SafeLineInspectionTask::getLineName, task.getLineName())
                .like(StringUtils.isNotBlank(task.getInspectionProject()), SafeLineInspectionTask::getInspectionProject, task.getInspectionProject())
                .eq(task.getIsEnabled() != null, SafeLineInspectionTask::getIsEnabled, task.getIsEnabled())
                .orderByDesc(SafeLineInspectionTask::getId);
        IPage<SafeLineInspectionTask> result = safeLineInspectionTaskMapper.selectPage(page, queryWrapper);
        fillInspectorName(result.getRecords());
        return result;
    }
    @Override
    @Transactional
    public boolean saveOrUpdateTask(SafeLineInspectionTask task) throws SchedulerException {
        SafeLineInspectionTask oldTask = null;
        if (task.getId() != null) {
            oldTask = safeLineInspectionTaskMapper.selectById(task.getId());
            if (oldTask == null) {
                throw new IllegalArgumentException("定时巡检任务不存在");
            }
        }
        normalizeTask(task, oldTask);
        task.setNextExecutionTime(calculateFirstExecutionTime(task.getFrequencyType(), task.getFrequencyDetail()));
        boolean result;
        if (task.getId() == null) {
            result = safeLineInspectionTaskMapper.insert(task) > 0;
            if (result && isEnabled(task.getIsEnabled())) {
                safeLineInspectionTaskScheduler.scheduleTask(task);
            }
            return result;
        }
        result = safeLineInspectionTaskMapper.updateById(task) > 0;
        if (result) {
            boolean oldEnabled = oldTask != null && isEnabled(oldTask.getIsEnabled());
            boolean newEnabled = isEnabled(task.getIsEnabled());
            if (!newEnabled) {
                safeLineInspectionTaskScheduler.unscheduleTask(task.getId());
            } else if (oldEnabled) {
                safeLineInspectionTaskScheduler.rescheduleTask(task);
            } else {
                safeLineInspectionTaskScheduler.scheduleTask(task);
            }
        }
        return result;
    }
    @Override
    @Transactional
    public boolean removeTaskByIds(List<Long> ids) {
        boolean removed = removeBatchByIds(ids);
        if (removed) {
            for (Long id : ids) {
                safeLineInspectionTaskScheduler.unscheduleTask(id);
            }
        }
        return removed;
    }
    @Override
    public LocalDateTime calculateFirstExecutionTime(String frequencyType, String frequencyDetail) {
        LocalDateTime now = LocalDateTime.now();
        return calculateNextExecutionTime(frequencyType, frequencyDetail, now);
    }
    @Override
    public LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) {
        validateFrequency(frequencyType, frequencyDetail);
        return switch (frequencyType) {
            case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime);
            case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime);
            case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime);
            default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
        };
    }
    private void normalizeTask(SafeLineInspectionTask task, SafeLineInspectionTask oldTask) {
        if (StringUtils.isBlank(task.getInspectionName())) {
            throw new IllegalArgumentException("巡检任务名称不能为空");
        }
        if (StringUtils.isBlank(task.getLineName())) {
            throw new IllegalArgumentException("线路名称不能为空");
        }
        if (StringUtils.isBlank(task.getInspectionProject())) {
            throw new IllegalArgumentException("巡检项目不能为空");
        }
        if (StringUtils.isBlank(task.getInspectorId())) {
            throw new IllegalArgumentException("巡检人不能为空");
        }
        task.setIsEnabled(resolveEnabledValue(task.getIsEnabled(), oldTask));
        task.setFrequencyType(task.getFrequencyType() == null ? null : task.getFrequencyType().trim().toUpperCase());
        task.setFrequencyDetail(task.getFrequencyDetail() == null ? null : task.getFrequencyDetail().trim());
        validateFrequency(task.getFrequencyType(), task.getFrequencyDetail());
    }
    private void validateFrequency(String frequencyType, String frequencyDetail) {
        if (StringUtils.isBlank(frequencyType) || StringUtils.isBlank(frequencyDetail)) {
            throw new IllegalArgumentException("任务频率不能为空");
        }
        switch (frequencyType) {
            case "DAILY" -> parseTime(frequencyDetail);
            case "WEEKLY" -> {
                String[] parts = splitFrequencyDetail(frequencyDetail);
                if (!WEEK_DAY_MAP.containsKey(parts[0])) {
                    throw new IllegalArgumentException("无效的星期: " + parts[0]);
                }
                parseTime(parts[1]);
            }
            case "MONTHLY" -> {
                String[] parts = splitFrequencyDetail(frequencyDetail);
                validateDayOfMonth(parts[0]);
                parseTime(parts[1]);
            }
            default -> throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
        }
    }
    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime currentTime) {
        LocalTime executionTime = parseTime(timeStr);
        LocalDateTime candidate = LocalDateTime.of(currentTime.toLocalDate(), executionTime);
        return currentTime.isBefore(candidate) ? candidate : candidate.plusDays(1);
    }
    private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime currentTime) {
        String[] parts = splitFrequencyDetail(detail);
        DayOfWeek targetDay = WEEK_DAY_MAP.get(parts[0]);
        LocalTime targetTime = parseTime(parts[1]);
        int daysUntil = targetDay.getValue() - currentTime.getDayOfWeek().getValue();
        if (daysUntil < 0 || (daysUntil == 0 && !currentTime.toLocalTime().isBefore(targetTime))) {
            daysUntil += 7;
        }
        return LocalDateTime.of(currentTime.toLocalDate().plusDays(daysUntil), targetTime);
    }
    private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime currentTime) {
        String[] parts = splitFrequencyDetail(detail);
        int dayOfMonth = validateDayOfMonth(parts[0]);
        LocalTime targetTime = parseTime(parts[1]);
        YearMonth currentMonth = YearMonth.from(currentTime);
        for (int i = 0; i < 24; i++) {
            YearMonth targetMonth = currentMonth.plusMonths(i);
            if (dayOfMonth > targetMonth.lengthOfMonth()) {
                continue;
            }
            LocalDateTime candidate = LocalDateTime.of(
                    targetMonth.getYear(),
                    targetMonth.getMonthValue(),
                    dayOfMonth,
                    targetTime.getHour(),
                    targetTime.getMinute()
            );
            if (currentTime.isBefore(candidate)) {
                return candidate;
            }
        }
        throw new IllegalArgumentException("无法计算下次执行时间");
    }
    private String[] splitFrequencyDetail(String detail) {
        String[] parts = detail.split(",");
        if (parts.length != 2) {
            throw new IllegalArgumentException("频率详情格式错误");
        }
        return Arrays.stream(parts).map(String::trim).toArray(String[]::new);
    }
    private LocalTime parseTime(String timeStr) {
        try {
            return LocalTime.parse(timeStr, TIME_FORMATTER);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("时间格式必须为HH:mm", e);
        }
    }
    private int validateDayOfMonth(String dayStr) {
        try {
            int day = Integer.parseInt(dayStr);
            if (day < 1 || day > 31) {
                throw new IllegalArgumentException("日期必须在1-31之间");
            }
            return day;
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("日期必须在1-31之间", e);
        }
    }
    private Integer resolveEnabledValue(Integer requestEnabled, SafeLineInspectionTask oldTask) {
        if (requestEnabled != null) {
            return requestEnabled;
        }
        if (oldTask != null && oldTask.getIsEnabled() != null) {
            return oldTask.getIsEnabled();
        }
        return ENABLED;
    }
    private boolean isEnabled(Integer enabledValue) {
        return Objects.equals(enabledValue, ENABLED);
    }
    private void fillInspectorName(List<SafeLineInspectionTask> records) {
        if (records == null || records.isEmpty()) {
            return;
        }
        Set<Long> userIds = records.stream()
                .map(SafeLineInspectionTask::getInspectorId)
                .filter(StringUtils::isNotBlank)
                .flatMap(ids -> Arrays.stream(ids.split(",")))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .map(this::parseUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (userIds.isEmpty()) {
            return;
        }
        Map<Long, String> userNameMap = new HashMap<>();
        List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
        users.forEach(user -> userNameMap.put(user.getUserId(), user.getNickName()));
        for (SafeLineInspectionTask record : records) {
            if (StringUtils.isBlank(record.getInspectorId())) {
                continue;
            }
            List<String> names = Arrays.stream(record.getInspectorId().split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotBlank)
                    .map(this::parseUserId)
                    .filter(Objects::nonNull)
                    .map(id -> userNameMap.getOrDefault(id, "未知用户"))
                    .collect(Collectors.toList());
            record.setInspector(names);
            record.setInspectorName(String.join(",", names));
        }
    }
    private Long parseUserId(String idStr) {
        try {
            return Long.parseLong(idStr);
        } catch (NumberFormatException e) {
            return null;
        }
    }
}
src/main/resources/mapper/safe/SafeLineInspectionHazardMapper.xml
@@ -6,6 +6,7 @@
        <id property="id" column="id"/>
        <result property="inspectionId" column="inspection_id"/>
        <result property="recordId" column="record_id"/>
        <result property="safeHiddenId" column="safe_hidden_id"/>
        <result property="hazardCode" column="hazard_code"/>
        <result property="hazardDesc" column="hazard_desc"/>
        <result property="hazardLevel" column="hazard_level"/>
@@ -13,6 +14,7 @@
        <result property="hazardImage" column="hazard_image"/>
        <result property="status" column="status"/>
        <result property="rectifyUserId" column="rectify_user_id"/>
        <result property="rectifyDeadline" column="rectify_deadline"/>
        <result property="rectifyTime" column="rectify_time"/>
        <result property="rectifyDesc" column="rectify_desc"/>
        <result property="createTime" column="create_time"/>
src/main/resources/mapper/safe/SafeLineInspectionMapper.xml
@@ -4,14 +4,19 @@
    <resultMap type="com.ruoyi.safe.pojo.SafeLineInspection" id="SafeLineInspectionResult">
        <id property="id" column="id"/>
        <result property="scheduleTaskId" column="schedule_task_id"/>
        <result property="inspectionCode" column="inspection_code"/>
        <result property="inspectionName" column="inspection_name"/>
        <result property="lineName" column="line_name"/>
        <result property="inspectionType" column="inspection_type"/>
        <result property="inspectionProject" column="inspection_project"/>
        <result property="planTime" column="plan_time"/>
        <result property="assignUserId" column="assign_user_id"/>
        <result property="inspectorId" column="inspector_id"/>
        <result property="status" column="status"/>
        <result property="inspectionResult" column="inspection_result"/>
        <result property="actualInspectionTime" column="actual_inspection_time"/>
        <result property="hiddenId" column="hidden_id"/>
        <result property="remark" column="remark"/>
        <result property="createTime" column="create_time"/>
        <result property="createUser" column="create_user"/>
src/main/resources/mapper/safe/SafeLineInspectionTaskMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.safe.mapper.SafeLineInspectionTaskMapper">
    <resultMap type="com.ruoyi.safe.pojo.SafeLineInspectionTask" id="SafeLineInspectionTaskResult">
        <id property="id" column="id"/>
        <result property="inspectionName" column="inspection_name"/>
        <result property="lineName" column="line_name"/>
        <result property="inspectionProject" column="inspection_project"/>
        <result property="inspectorId" column="inspector_id"/>
        <result property="frequencyType" column="frequency_type"/>
        <result property="frequencyDetail" column="frequency_detail"/>
        <result property="nextExecutionTime" column="next_execution_time"/>
        <result property="lastExecutionTime" column="last_execution_time"/>
        <result property="isEnabled" column="is_enabled"/>
        <result property="remark" column="remark"/>
        <result property="createTime" column="create_time"/>
        <result property="createUser" column="create_user"/>
        <result property="updateTime" column="update_time"/>
        <result property="updateUser" column="update_user"/>
        <result property="tenantId" column="tenant_id"/>
        <result property="deptId" column="dept_id"/>
    </resultMap>
</mapper>