liding
9 小时以前 315ef5820062ba31eb821cc3c347e38a313b1976
设备管理(1.设备台账 2.备件管理 3.巡检)
已添加7个文件
已修改44个文件
已删除3个文件
1351 ■■■■ 文件已修改
src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceRepairController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceAssetInfoDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/MaintenanceTaskMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceLedger.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceRepair.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/SpringContextHolder.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerPageDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerRecordDTO.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceRepairMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml 62 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java
@@ -2,10 +2,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.device.dto.DeviceDefectRecordDto;
import com.ruoyi.device.dto.DeviceRepairDto;
import com.ruoyi.device.pojo.DeviceDefectRecord;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.device.service.DeviceDefectRecordService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
@@ -2,7 +2,6 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.device.dto.DeviceLedgerDto;
import com.ruoyi.device.mapper.DeviceLedgerMapper;
@@ -10,14 +9,11 @@
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.device.pojo.DeviceMaintenance;
import com.ruoyi.device.service.IDeviceLedgerService;
import com.ruoyi.device.service.IDeviceMaintenanceService;
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ArrayUtils;
import org.ehcache.spi.service.MaintainableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -25,7 +21,6 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Api(tags = "设备台账管理")
@@ -84,14 +79,7 @@
    public void export(HttpServletResponse response, Long[] ids) {
         deviceLedgerService.export(response, ids);
    }
    /**
     *
     */
    @GetMapping("/report/forms")
    @ApiOperation("查询设备台账图表数据")
    public AjaxResult report() {
        return AjaxResult.success(deviceLedgerService.report());
    }
    @PostMapping("import")
    @ApiModelProperty("导入设备台账")
    public AjaxResult importData(MultipartFile file) throws IOException {
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
@@ -3,13 +3,10 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.device.dto.DeviceMaintenanceDto;
import com.ruoyi.device.dto.DeviceRepairDto;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.device.pojo.DeviceMaintenance;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.device.service.IDeviceLedgerService;
import com.ruoyi.device.service.IDeviceMaintenanceService;
import com.ruoyi.device.service.IDeviceRepairService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
@@ -17,7 +14,6 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
@Api(tags = "设备保养")
src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
@@ -1,10 +1,7 @@
package com.ruoyi.device.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.approve.service.IApproveProcessService;
import com.ruoyi.device.dto.DeviceRepairDto;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.device.service.IDeviceLedgerService;
@@ -13,12 +10,10 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Api(tags = "设备报修管理")
@RequestMapping("/device/repair")
@@ -30,8 +25,6 @@
    @Autowired
    private IDeviceLedgerService deviceLedgerService;
    @Autowired
    private IApproveProcessService approveProcessService;
    @ApiModelProperty("设备报修列表")
    @GetMapping("/page")
@@ -40,30 +33,9 @@
    }
    @PostMapping()
    @Transactional(rollbackFor = Exception.class)
    @ApiModelProperty("添加设备报修")
    public AjaxResult add( @RequestBody DeviceRepair deviceRepair) throws Exception {
        deviceRepairService.saveDeviceRepair(deviceRepair);
        // todo å‰ç«¯ä»£ç ä¸åŒ¹é…ï¼Œå¾…处理
//        ApproveProcessVO approveProcessVO = new ApproveProcessVO();
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        // èŽ·å–å½“å‰ç™»å½•å…¬å¸
//        Long tenantId = loginUser.getTenantId();
//        if(null != tenantId){
//            //获取当前登录部门id
//            approveProcessVO.setApproveDeptId(tenantId);
//            //获取当前登录用户id
//            approveProcessVO.setApproveUser(loginUser.getUserId());
//            //获取当前时间
//            approveProcessVO.setApproveTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//            approveProcessVO.setApproveType(4);
//            approveProcessVO.setApproveUserIds(deviceRepair.getApproverId().toString());
//            approveProcessVO.setApproveReason(deviceRepair.getRemark());
//            approveProcessVO.setDeviceRepairId(deviceRepair.getId());
//            approveProcessVO.setMaintenancePrice(deviceRepair.getMaintenancePrice());
//            approveProcessService.addApprove(approveProcessVO);
//        }
        return AjaxResult.success();
    public AjaxResult add( @RequestBody DeviceRepair deviceRepair) {
        return deviceRepairService.saveDeviceRepair(deviceRepair);
    }
    @ApiModelProperty("根据id查询设备报修")
@@ -88,17 +60,6 @@
    @DeleteMapping("/{ids}")
    @ApiModelProperty("删除设备报修")
    public AjaxResult delete(@PathVariable("ids") Long[] ids) {
        LambdaQueryWrapper<ApproveProcess> QueryWrapper = new LambdaQueryWrapper<>();
        QueryWrapper.in(ApproveProcess::getDeviceRepairId,ids);
        List<ApproveProcess> approveProcessList = approveProcessService.list(QueryWrapper);
        if(!approveProcessList.isEmpty()){
            approveProcessList.forEach(approveProcess -> {
                if (approveProcess.getApproveStatus() != 0){
                    //抛出异常
                    throw new RuntimeException("有正在处理中的审批流程,不能删除");
                }
            });
        }
        boolean b = deviceRepairService.removeBatchByIds(Arrays.asList(ids));
        if (!b) {
            return AjaxResult.error("删除失败");
src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.ruoyi.device.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.device.pojo.MaintenanceTask;
import com.ruoyi.device.service.MaintenanceTaskService;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author :yys
 * @date : 2025/12/22 14:58
 */
@Api(tags = "设备保养定时任务管理")
@RestController
@RequestMapping("/deviceMaintenanceTask")
public class MaintenanceTaskController extends BaseController {
    @Autowired
    private MaintenanceTaskService maintenanceTaskService;
    @GetMapping("/listPage")
    @ApiOperation(value = "设备保养定时任务列表")
    public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
        return maintenanceTaskService.listPage(page,maintenanceTask);
    }
    @PostMapping("/add")
    @ApiOperation(value = "添加设备保养定时任务")
    @Log(title = "设备保养定时任务", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody MaintenanceTask maintenanceTask) {
        return maintenanceTaskService.add(maintenanceTask);
    }
    @PostMapping("/update")
    @ApiOperation(value = "修改设备保养定时任务")
    @Log(title = "设备保养定时任务", businessType = BusinessType.UPDATE)
    public AjaxResult update(@RequestBody MaintenanceTask maintenanceTask) {
        return maintenanceTaskService.updateByMaintenanceTaskId(maintenanceTask);
    }
    @DeleteMapping("/delete")
    @ApiOperation(value = "删除设备保养定时任务")
    @Log(title = "设备保养定时任务", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        return maintenanceTaskService.delete(ids);
    }
}
src/main/java/com/ruoyi/device/dto/DeviceAssetInfoDto.java
ÎļþÒÑɾ³ý
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -6,7 +6,6 @@
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
@Data
public class DeviceMaintenanceDto {
src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -69,7 +68,7 @@
    @ApiModelProperty("租户id")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("维修价格")
    private String maintenancePrice;
}
src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
@@ -1,13 +1,9 @@
package com.ruoyi.device.execl;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class DeviceLedgerExeclDto {
src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java
@@ -1,8 +1,6 @@
package com.ruoyi.device.execl;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java
@@ -6,7 +6,6 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.device.dto.DeviceMaintenanceDto;
import com.ruoyi.device.dto.DeviceRepairDto;
import com.ruoyi.device.pojo.DeviceMaintenance;
import org.apache.ibatis.annotations.Mapper;
src/main/java/com/ruoyi/device/mapper/MaintenanceTaskMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.ruoyi.device.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.device.pojo.MaintenanceTask;
/**
 * @author :yys
 * @date : 2025/12/22 14:56
 */
public interface MaintenanceTaskMapper extends BaseMapper<MaintenanceTask> {
}
src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
@@ -12,7 +12,6 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
/**
 * è®¾å¤‡å°è´¦å®žä½“ç±»
src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -1,15 +1,15 @@
package com.ruoyi.device.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.models.auth.In;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@TableName("device_maintenance")
@@ -22,6 +22,21 @@
    @ApiModelProperty("设备台账id")
    private Long deviceLedgerId;
    @ApiModelProperty("保养任务id")
    private Long maintenanceTaskId;
    @ApiModelProperty(value = "频次")
    private String frequencyType;
    @ApiModelProperty(value = "频次详情")
    private String frequencyDetail;
    @ApiModelProperty(value = "下次执行时间")
    private LocalDateTime nextExecutionTime;
    @ApiModelProperty(value = "最后执行时间")
    private LocalDateTime lastExecutionTime;
    private String deviceName;
src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
@@ -4,13 +4,10 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@@ -23,9 +20,9 @@
    @ApiModelProperty("设备台账id")
    private Long deviceLedgerId;
    @ApiModelProperty("设备名称")
    private String deviceName;
    @ApiModelProperty("设备型号")
    private String deviceModel;
    @ApiModelProperty("报修时间")
@@ -48,7 +45,7 @@
    @ApiModelProperty("维修结果")
    private String maintenanceResult;
    @ApiModelProperty("状态:0审核中,1审核通过,2审核失败,3维修中,4维修通过,5维修失败")
    @ApiModelProperty("状态 0 å¾…ç»´ä¿® 1完结 2 å¤±è´¥")
    private Integer status;
    @ApiModelProperty("创建时间")
@@ -74,8 +71,6 @@
    @ApiModelProperty("租户id")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("维修价格")
    private BigDecimal maintenancePrice;
    @ApiModelProperty("审批人id")
    private Integer approverId;
}
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package com.ruoyi.device.pojo;
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 com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
 * @author :yys
 * @date : 2025/9/19 10:27
 */
@Data
@ApiModel
@TableName("maintenance_task")
public class MaintenanceTask {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "规格型号")
    private String deviceModel;
    /**
     * ä¸»é”®ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "设备名称")
    @Excel(name = "保养任务名称")
    private String taskName;
    @ApiModelProperty(value = "设备id")
    private Long taskId;
    @ApiModelProperty(value = "频次")
    @Excel(name = "频次")
    private String frequencyType;
    @ApiModelProperty(value = "频次详情")
    @Excel(name = "开始日期与时间")
    private String frequencyDetail;
    @ApiModelProperty(value = "下次执行时间")
    private LocalDateTime nextExecutionTime;
    @ApiModelProperty(value = "最后执行时间")
    private LocalDateTime lastExecutionTime;
    @ApiModelProperty(value = "是否激活")
    private boolean isActive;
    @ApiModelProperty(value = "备注")
    @Excel(name = "备注")
    private String remarks;
    @ApiModelProperty(value = "录入人id")
    private Long registrantId;
    @ApiModelProperty(value = "录入人")
    @Excel(name = "录入人")
    private String registrant;
    @ApiModelProperty(value = "录入日期")
    @Excel(name = "录入日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate registrationDate;
    @ApiModelProperty(value = "状态")
    private String status;
    @ApiModelProperty(value = "软删除标志,0=未删除,1=已删除")
    private Integer deleted;
    @TableField(exist = false)
    private String dateStr;
    @ApiModelProperty(value = "创建该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    private Integer createUser;
    @ApiModelProperty(value = "记录创建时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
//    @JsonFormat(pattern = "yyyy-MM-dd")
//    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "最后修改该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty(value = "记录最后更新时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    private Long tenantId;
}
src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
@@ -3,7 +3,6 @@
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.device.dto.DeviceAssetInfoDto;
import com.ruoyi.device.dto.DeviceLedgerDto;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.framework.web.domain.AjaxResult;
@@ -11,7 +10,6 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
public interface IDeviceLedgerService  extends IService<DeviceLedger> {
    IPage<DeviceLedgerDto> queryPage(Page page, DeviceLedgerDto deviceLedger);
@@ -23,5 +21,4 @@
    void export(HttpServletResponse response, Long[] ids);
    Boolean importData(MultipartFile file) throws IOException;
    DeviceAssetInfoDto report();
}
src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.ruoyi.device.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.device.pojo.MaintenanceTask;
import com.ruoyi.framework.web.domain.AjaxResult;
import java.util.List;
/**
 * @author :yys
 * @date : 2025/12/22 14:56
 */
public interface MaintenanceTaskService extends IService<MaintenanceTask> {
    AjaxResult listPage(Page page, MaintenanceTask maintenanceTask);
    AjaxResult add(MaintenanceTask maintenanceTask);
    AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask);
    AjaxResult delete(List<Long> ids);
}
src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java
@@ -10,7 +10,6 @@
import com.ruoyi.device.pojo.DeviceDefectRecord;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.device.service.DeviceDefectRecordService;
import com.ruoyi.device.service.IDeviceRepairService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
@@ -2,13 +2,11 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.device.dto.DeviceAssetInfoDto;
import com.ruoyi.device.dto.DeviceLedgerDto;
import com.ruoyi.device.execl.DeviceLedgerExeclDto;
import com.ruoyi.device.mapper.DeviceLedgerMapper;
@@ -25,8 +23,6 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -120,15 +116,5 @@
        });
        return true;
    }
    @Override
    public DeviceAssetInfoDto report() {
        List<DeviceLedger> list = deviceLedgerMapper.selectList(null);
        DeviceAssetInfoDto deviceAssetInfoDto = new DeviceAssetInfoDto();
        deviceAssetInfoDto.setTotalEquipment(list.stream().map(DeviceLedger::getNumber).reduce(BigDecimal.ZERO, BigDecimal::add).intValue());
        deviceAssetInfoDto.setTotalOriginalValue(list.stream().map(DeviceLedger::getTaxIncludingPriceTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
        deviceAssetInfoDto.setTotalNetValue(list.stream().map(DeviceLedger::getUnTaxIncludingPriceTotal).reduce(BigDecimal.ZERO, BigDecimal::add));
        deviceAssetInfoDto.setTotalDepreciation(deviceAssetInfoDto.getTotalOriginalValue().subtract(deviceAssetInfoDto.getTotalNetValue()));
        return deviceAssetInfoDto;
    }
}
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -17,7 +17,6 @@
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
@@ -8,9 +8,7 @@
import com.ruoyi.device.dto.DeviceDefectRecordDto;
import com.ruoyi.device.dto.DeviceRepairDto;
import com.ruoyi.device.execl.DeviceRepairExeclDto;
import com.ruoyi.device.mapper.DeviceDefectRecordMapper;
import com.ruoyi.device.mapper.DeviceRepairMapper;
import com.ruoyi.device.pojo.DeviceDefectRecord;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.device.service.DeviceDefectRecordService;
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,243 @@
package com.ruoyi.device.service.impl;
import com.ruoyi.device.pojo.DeviceMaintenance;
import com.ruoyi.device.pojo.MaintenanceTask;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
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.util.HashSet;
import java.util.List;
import java.util.Set;
@Component
@DisallowConcurrentExecution // ç¦æ­¢å¹¶å‘执行同一个Job
public class MaintenanceTaskJob implements Job, Serializable {
    private static final long serialVersionUID = 1L; // å¿…须定义序列化ID
    @Autowired
    private DeviceMaintenanceServiceImpl deviceMaintenanceService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        // ä¿®å¤ç±»åž‹è½¬æ¢é”™è¯¯ï¼Œæ­£ç¡®èŽ·å–taskId
        Long taskId = jobDataMap.getLong("maintenanceTaskId");
        try {
            // 3. å°è¯•查询你的业务数据
            // é€šè¿‡JDBC模板查询定时任务信息,使用参数化查询防止SQL注入
            String yourSql = "SELECT * FROM maintenance_task where id = ?";
            List<MaintenanceTask> tasks = jdbcTemplate.query(
                    yourSql,
                    new BeanPropertyRowMapper<>(MaintenanceTask.class),
                    taskId
            );
            MaintenanceTask timingTask = tasks.isEmpty() ? null : tasks.get(0);
            if (timingTask == null) {
                throw new JobExecutionException("MaintenanceTaskJob找不到定时任务: " + taskId);
            }
            // 2. åˆ›å»ºå¹¶ä¿å­˜å·¡æ£€ä»»åŠ¡è®°å½• - è¿™å°±æ˜¯æ‚¨æä¾›çš„代码应该放的位置
            DeviceMaintenance deviceMaintenance = createInspectionTask(timingTask);
            deviceMaintenanceService.save(deviceMaintenance);
            // 3. æ›´æ–°å®šæ—¶ä»»åŠ¡çš„æ‰§è¡Œæ—¶é—´
            if (!tasks.isEmpty()) {
                MaintenanceTask task = tasks.get(0);
                // æ›´æ–°æœ€åŽæ‰§è¡Œæ—¶é—´ä¸ºå½“前时间
                LocalDateTime lastExecutionTime = LocalDateTime.now();
                // è®¡ç®—下次执行时间
                LocalDateTime nextExecutionTime = calculateNextExecutionTime(
                        task.getFrequencyType(),
                        task.getFrequencyDetail(),
                        lastExecutionTime
                );
                // æ‰§è¡Œæ›´æ–°æ“ä½œ
                String updateSql = "UPDATE maintenance_task " +
                        "SET last_execution_time = ?, next_execution_time = ? " +
                        "WHERE id = ?";
                jdbcTemplate.update(
                        updateSql,
                        lastExecutionTime,
                        nextExecutionTime,
                        taskId
                );
            }
        } catch (Exception e) {
            throw new JobExecutionException(e);
        }
    }
    // è¿™å°±æ˜¯æ‚¨æä¾›çš„代码封装成的方法
    private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask) {
        DeviceMaintenance inspectionTask = new DeviceMaintenance();
        // å¤åˆ¶åŸºæœ¬å±žæ€§
        inspectionTask.setDeviceName(timingTask.getTaskName());
        inspectionTask.setMaintenanceTaskId(timingTask.getId());
        inspectionTask.setDeviceLedgerId(timingTask.getTaskId());
        inspectionTask.setMaintenancePlanTime(LocalDateTime.now());
        inspectionTask.setFrequencyType(timingTask.getFrequencyType());
        inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
        inspectionTask.setTenantId(timingTask.getTenantId());
        inspectionTask.setStatus(0);
        inspectionTask.setDeviceModel(timingTask.getDeviceModel());
        inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
        inspectionTask.setUpdateTime(LocalDateTime.now());
        inspectionTask.setCreateTime(LocalDateTime.now());
        inspectionTask.setUpdateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
        return inspectionTask;
    }
    /**
     * è®¡ç®—下次执行时间
     */
    private LocalDateTime calculateNextExecutionTime(String frequencyType,
                                                     String frequencyDetail,
                                                     LocalDateTime currentTime) {
        try {
            switch (frequencyType) {
                case "DAILY":
                    return calculateDailyNextTime(frequencyDetail, currentTime);
                case "WEEKLY":
                    return calculateWeeklyNextTime(frequencyDetail, currentTime);
                case "MONTHLY":
                    return calculateMonthlyNextTime(frequencyDetail, currentTime);
                case "QUARTERLY":
                    return calculateQuarterlyNextTime(frequencyDetail, currentTime);
                default:
                    throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
            }
        } catch (Exception e) {
            throw new RuntimeException("计算下次执行时间失败: " + e.getMessage(), e);
        }
    }
    /**
     * è®¡ç®—每日任务的下次执行时间
     */
    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
        LocalTime executionTime = LocalTime.parse(timeStr); // è§£æžæ ¼å¼ "HH:mm"
        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(",");
        String dayOfWeekStr = parts[0];  // å¦‚ "MON" æˆ– "MON|WED|FRI"
        LocalTime time = LocalTime.parse(parts[1]); // æ—¶é—´éƒ¨åˆ†
        // è§£æžæ˜ŸæœŸå‡ (支持多个星期)
        Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr);
        // ä»Žå½“前时间开始找下一个符合条件的星期几
        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]);
        LocalTime time = LocalTime.parse(parts[1]);
        // ä»Žä¸‹ä¸ªæœˆå¼€å§‹è®¡ç®—
        LocalDateTime nextTime = current.plusMonths(1)
                .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth()))
                .with(time);
        return nextTime;
    }
    /**
     * è®¡ç®—每季度任务的下次执行时间
     */
    private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int quarterMonth = Integer.parseInt(parts[0]); // 1=第1个月,2=第2个月,3=第3个月
        int dayOfMonth = Integer.parseInt(parts[1]);
        LocalTime time = LocalTime.parse(parts[2]);
        // è®¡ç®—当前季度
        int currentQuarter = (current.getMonthValue() - 1) / 3 + 1;
        int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1;
        YearMonth targetYearMonth;
        if (currentMonthInQuarter < quarterMonth) {
            // æœ¬å­£åº¦å†…还有执行机会
            targetYearMonth = YearMonth.from(current)
                    .plusMonths(quarterMonth - currentMonthInQuarter);
        } else {
            // éœ€è¦åˆ°ä¸‹ä¸ªå­£åº¦
            targetYearMonth = YearMonth.from(current)
                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
        }
        // å¤„理月末日期
        int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
        return LocalDateTime.of(
                targetYearMonth.getYear(),
                targetYearMonth.getMonthValue(),
                adjustedDay,
                time.getHour(),
                time.getMinute()
        );
    }
    /**
     * è§£æžæ˜ŸæœŸå‡ å­—符串
     */
    private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
        Set<DayOfWeek> days = new HashSet<>();
        String[] dayStrs = dayOfWeekStr.split("\\|");
        for (String dayStr : dayStrs) {
            switch (dayStr) {
                case "MON": days.add(DayOfWeek.MONDAY); break;
                case "TUE": days.add(DayOfWeek.TUESDAY); break;
                case "WED": days.add(DayOfWeek.WEDNESDAY); break;
                case "THU": days.add(DayOfWeek.THURSDAY); break;
                case "FRI": days.add(DayOfWeek.FRIDAY); break;
                case "SAT": days.add(DayOfWeek.SATURDAY); break;
                case "SUN": days.add(DayOfWeek.SUNDAY); break;
                default: throw new IllegalArgumentException("无效的星期几: " + dayStr);
            }
        }
        return days;
    }
}
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,278 @@
package com.ruoyi.device.service.impl;
import com.ruoyi.device.pojo.MaintenanceTask;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
 * @author :yys
 * @date : 2025/12/22 15:16
 */
@Service
@Slf4j
public class MaintenanceTaskScheduler {
    @Autowired
    private Scheduler scheduler;
    /**
     * æ·»åŠ æ–°ä»»åŠ¡åˆ°è°ƒåº¦å™¨
     */
    public void scheduleMaintenanceTask(MaintenanceTask task){
        try {
            JobDetail jobDetail = buildJobDetail(task);
            Trigger trigger = buildJobTrigger(task, jobDetail);
            scheduler.scheduleJob(jobDetail, trigger);
        }catch (SchedulerException e){
            log.error("SchedulerException scheduleMaintenanceTask ERROR",e);
            throw new RuntimeException(e);
        }
    }
    /**
     * æ›´æ–°å·²æœ‰ä»»åŠ¡
     */
    public void rescheduleMaintenanceTask(MaintenanceTask task){
       try{
           TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId());
           // èŽ·å–çŽ°æœ‰è§¦å‘å™¨å¹¶è½¬æ¢ä¸º CronTrigger
           Trigger oldTrigger = scheduler.getTrigger(triggerKey);
           if (!(oldTrigger instanceof CronTrigger)) {
               throw new SchedulerException("Existing trigger is not a CronTrigger");
           }
           // 3. æž„建CronTrigger,确保持久化配置
           CronTrigger newTrigger = TriggerBuilder.newTrigger()
                   .withIdentity(triggerKey)                // å”¯ä¸€æ ‡è¯†ï¼Œç”¨äºŽæŒä¹…化存储
                   .withDescription(task.getTaskName() + "_TRIGGER") // è§¦å‘器描述
                   .forJob(oldTrigger.getJobKey())                       // å…³è”对应的Job
                   .withSchedule(CronScheduleBuilder
                           .cronSchedule(convertToCronExpression(task)) // é”™è¿‡æ‰§è¡Œæ—¶çš„策略(根据业务调整)
                   )
                   // 4. è®¾ç½®å¼€å§‹æ—¶é—´ï¼ˆè‹¥ä¸ºnull则立即生效)
                   .startAt(task.getNextExecutionTime() != null
                           ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())
                           : new Date())
                   .build();
           scheduler.rescheduleJob(triggerKey, newTrigger);
       }catch (SchedulerException e){
           log.error("SchedulerException rescheduleMaintenanceTask ERROR",e);
           throw new RuntimeException(e);
       }
    }
    /**
     * æš‚停任务
     */
    public void pauseMaintenanceTask(Long taskId) throws SchedulerException {
        JobKey jobKey = new JobKey("MaintenanceTask_" + taskId);
        scheduler.pauseJob(jobKey);
    }
    /**
     * æ¢å¤ä»»åŠ¡
     */
    public void resumeMaintenanceTask(Long taskId) throws SchedulerException {
        JobKey jobKey = new JobKey("MaintenanceTask_" + taskId);
        scheduler.resumeJob(jobKey);
    }
    /**
     * åˆ é™¤ä»»åŠ¡
     */
    public void unscheduleMaintenanceTask(Long taskId){
        try {
            JobKey jobKey = new JobKey("MaintenanceTask_" + taskId);
            scheduler.deleteJob(jobKey);
        }catch (SchedulerException e){
            log.error("SchedulerException unscheduleMaintenanceTask ERROR",e);
            throw new RuntimeException(e);
        }
    }
    private JobDetail buildJobDetail(MaintenanceTask task) {
        // 1. æž„建唯一JobKey(基于任务ID,确保重启后能识别)
        JobKey jobKey = new JobKey("MaintenanceTask_" + task.getId());
        // 2. å°è£…任务数据(仅使用基本类型,确保可序列化)
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("maintenanceTaskId", task.getId());           // ä»»åŠ¡ID(Long,可序列化)
        jobDataMap.put("taskName", task.getTaskName());   // ä»»åŠ¡åç§°ï¼ˆString,可序列化)
        jobDataMap.put("taskType", task.getFrequencyType()); // ä»»åŠ¡ç±»åž‹ï¼ˆString)
        // æŒ‰éœ€æ·»åŠ å…¶ä»–å¿…è¦çš„åŸºæœ¬ç±»åž‹å‚æ•°
        // 3. æž„建JobDetail,设置持久化相关属性
        return JobBuilder.newJob(MaintenanceTaskJob.class)
                .withIdentity(jobKey)                    // å”¯ä¸€æ ‡è¯†ï¼Œç”¨äºŽæŒä¹…化存储
                .withDescription(task.getTaskName())     // ä»»åŠ¡æè¿°ï¼Œå­˜å…¥æ•°æ®åº“
                .usingJobData(jobDataMap)                // ç»‘定任务数据
                .storeDurably(true)                          // å³ä½¿æ²¡æœ‰è§¦å‘器关联也持久化保存
                .requestRecovery(true)                   // å½“调度器崩溃后恢复时,重新执行未完成的任务
                .build();
    }
    private Trigger buildJobTrigger(MaintenanceTask task, JobDetail jobDetail) {
        // 1. æž„建唯一TriggerKey(基于任务ID)
        TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId());
        // 2. ç”ŸæˆCron表达式(原逻辑不变)
        String cronExpression = convertToCronExpression(task);
        // 3. æž„建CronTrigger,确保持久化配置
        return TriggerBuilder.newTrigger()
                .withIdentity(triggerKey)                // å”¯ä¸€æ ‡è¯†ï¼Œç”¨äºŽæŒä¹…化存储
                .withDescription(task.getTaskName() + "_TRIGGER") // è§¦å‘器描述
                .forJob(jobDetail)                       // å…³è”对应的Job
                .withSchedule(CronScheduleBuilder
                        .cronSchedule(cronExpression)
                        .withMisfireHandlingInstructionDoNothing() // é”™è¿‡æ‰§è¡Œæ—¶çš„策略(根据业务调整)
                )
                // 4. è®¾ç½®å¼€å§‹æ—¶é—´ï¼ˆè‹¥ä¸ºnull则立即生效)
                .startAt(task.getNextExecutionTime() != null
                        ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())
                        : new Date())
                .build();
    }
    private String convertToCronExpression(MaintenanceTask task) {
        // å‚数校验
        if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) {
            throw new IllegalArgumentException("任务参数不能为空");
        }
        // ä½¿ç”¨switch确保条件互斥
        String frequencyType = task.getFrequencyType().toUpperCase(); // ç»Ÿä¸€è½¬ä¸ºå¤§å†™æ¯”较
        switch (frequencyType) {
            case "DAILY":
                return convertDailyToCron(task.getFrequencyDetail());
            case "WEEKLY":
                return convertWeeklyToCron(task.getFrequencyDetail());
            case "MONTHLY":
                return convertMonthlyToCron(task.getFrequencyDetail());
            case "QUARTERLY":
                return convertQuarterlyToCron(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 = convertDayNamesToCron(parts[0]);
        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 convertQuarterlyToCron(String frequencyDetail) {
        String[] parts = validateAndSplit(frequencyDetail, ",", 3);
        int month = validateMonth(parts[0]);  // éªŒè¯æœˆä»½(1-12)
        int day = validateDayOfMonth(parts[1]);  // éªŒè¯æ—¥æœŸ
        LocalTime time = parseTime(parts[2]);  // è§£æžæ—¶é—´
        // è®¡ç®—季度起始月份(1月=1, 4月=4, 7月=7, 10月=10)
        int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
        return String.format("0 %d %d %d %d/3 ?",
                time.getMinute(),
                time.getHour(),
                day,
                quarterStartMonth);
    }
    // æ–°å¢žéªŒè¯æœˆä»½çš„æ–¹æ³•(1-12)
    private int validateMonth(String monthStr) {
        try {
            int month = Integer.parseInt(monthStr);
            if (month < 1 || month > 12) {
                throw new IllegalArgumentException("月份必须在1-12之间");
            }
            return month;
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无效的月份格式");
        }
    }
    // è¾…助方法:解析时间
    private LocalTime parseTime(String timeStr) {
        try {
            return LocalTime.parse(timeStr);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("时间格式必须为HH:mm", e);
        }
    }
    // è¾…助方法:验证并分割字符串
    private String[] validateAndSplit(String input, String delimiter, int expectedParts) {
        String[] parts = input.split(delimiter);
        if (parts.length != expectedParts) {
            throw new IllegalArgumentException(
                    String.format("格式错误,应为%d部分用'%s'分隔", expectedParts, delimiter));
        }
        return parts;
    }
    // è¾…助方法:验证月份中的日
    private int validateDayOfMonth(String dayStr) {
        int day = Integer.parseInt(dayStr);
        if (day < 1 || day > 31) {
            throw new IllegalArgumentException("日期必须在1-31之间");
        }
        return day;
    }
    // è¾…助方法:验证季度中的月
    private int validateMonthInQuarter(String monthStr) {
        int month = Integer.parseInt(monthStr);
        if (month < 1 || month > 3) {
            throw new IllegalArgumentException("季度月份必须是1、2或3");
        }
        return month;
    }
    // è½¬æ¢æ˜ŸæœŸå‡ åç§°
    private String convertDayNamesToCron(String dayNames) {
        return Arrays.stream(dayNames.split("\\|"))
                .map(this::convertSingleDayName)
                .collect(Collectors.joining(","));
    }
    // è½¬æ¢å•个星期几名称
    private String convertSingleDayName(String dayName) {
        switch (dayName.toUpperCase()) {
            case "MON": return "MON";
            case "TUE": return "TUE";
            case "WED": return "WED";
            case "THU": return "THU";
            case "FRI": return "FRI";
            case "SAT": return "SAT";
            case "SUN": return "SUN";
            default: throw new IllegalArgumentException("无效的星期几: " + dayName);
        }
    }
}
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
package com.ruoyi.device.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.device.mapper.MaintenanceTaskMapper;
import com.ruoyi.device.pojo.MaintenanceTask;
import com.ruoyi.device.service.MaintenanceTaskService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.inspectiontask.pojo.TimingTask;
import com.ruoyi.inspectiontask.service.impl.TimingTaskServiceImpl;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
/**
 * @author :yys
 * @date : 2025/12/22 14:57
 */
@Service
@Slf4j
public class MaintenanceTaskServiceImpl extends ServiceImpl<MaintenanceTaskMapper, MaintenanceTask> implements MaintenanceTaskService {
    @Autowired
    private MaintenanceTaskMapper maintenanceTaskMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private TimingTaskServiceImpl timingTaskService;
    @Autowired
    private MaintenanceTaskScheduler maintenanceTaskScheduler;
    @Override
    public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
        Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, null);
        // 2. å¦‚果没有数据,直接返回空分页
        if (taskPage.getRecords().isEmpty()) {
            return AjaxResult.success(taskPage);
        }
        // 3. æ”¶é›†æ‰€æœ‰éœ€è¦æŸ¥è¯¢çš„用户ID
        Set<Long> userIds = new HashSet<>();
        // æ”¶é›†ç™»è®°äººID
        taskPage.getRecords().forEach(task -> {
            if (task.getRegistrantId() != null) {
                userIds.add(task.getRegistrantId());
            }
        });
        // 4. æ‰¹é‡æŸ¥è¯¢ç”¨æˆ·ä¿¡æ¯
        Map<Long, String> userNickNameMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds)));
            users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
        }
        taskPage.getRecords().forEach(task -> {
            // è®¾ç½®ç™»è®°äººæ˜µç§°
            if (task.getRegistrantId() != null) {
                task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "未知用户"));
            }
        });
        return AjaxResult.success(taskPage);
    }
    @Override
    public AjaxResult add(MaintenanceTask maintenanceTask) {
        maintenanceTask.setActive(true);
        // è®¡ç®—首次执行时间
        TimingTask task = new TimingTask();
        task.setFrequencyType(maintenanceTask.getFrequencyType());
        task.setFrequencyDetail(maintenanceTask.getFrequencyDetail());
        LocalDateTime firstExecutionTime = timingTaskService.calculateFirstExecutionTime(task);
        maintenanceTask.setNextExecutionTime(firstExecutionTime);
        int insert = maintenanceTaskMapper.insert(maintenanceTask);
        if (insert > 0) {
            maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask);
        }
        return AjaxResult.success("添加成功");
    }
    @Override
    public AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask) {
        MaintenanceTask maintenanceTask1 = maintenanceTaskMapper.selectById(maintenanceTask.getId());
        if (maintenanceTask1 == null) {
            return AjaxResult.warn("没有此数据");
        }
        BeanUtils.copyProperties(maintenanceTask, maintenanceTask1);
        int update = maintenanceTaskMapper.updateById(maintenanceTask1);
        if (update > 0) {
            maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1);
        }
        return AjaxResult.success("更新成功");
    }
    @Override
    public AjaxResult delete(List<Long> ids) {
        int delete = maintenanceTaskMapper.deleteBatchIds(ids);
        if (delete > 0) {
            ids.forEach(id -> {
                maintenanceTaskScheduler.unscheduleMaintenanceTask(id);
            });
        }
        return AjaxResult.success("删除成功");
    }
}
src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
@@ -6,12 +6,10 @@
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
import com.ruoyi.inspectiontask.dto.TimingTaskDto;
import com.ruoyi.inspectiontask.pojo.InspectionTask;
import com.ruoyi.inspectiontask.service.InspectionTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
@@ -9,7 +9,6 @@
import com.ruoyi.inspectiontask.service.QrCodeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
@@ -9,7 +9,6 @@
import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
@@ -3,6 +3,8 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.inspectiontask.dto.TimingTaskDto;
@@ -10,7 +12,6 @@
import com.ruoyi.inspectiontask.service.TimingTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -58,6 +59,7 @@
     */
    @PostMapping("/addOrEditTimingTask")
    @ApiOperation(value = "新增修改定时任务")
    @Log(title = "定时任务", businessType = BusinessType.INSERT)
    public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException {
        return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto));
    }
@@ -67,6 +69,7 @@
     */
    @DeleteMapping("/delTimingTask")
    @ApiOperation(value = "删除定时任务")
    @Log(title = "定时任务", businessType = BusinessType.DELETE)
    public R remove(@RequestBody Long[] ids) {
        return R.ok(timingTaskService.delByIds(ids));
    }
src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
@@ -67,22 +67,22 @@
    private Integer deleted;
    @ApiModelProperty(value = "创建该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @ApiModelProperty(value = "记录创建时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "登记日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "最后修改该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty(value = "记录最后更新时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "租户")
src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
@@ -53,21 +53,21 @@
    private Integer deleted;
    @ApiModelProperty(value = "创建该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @ApiModelProperty(value = "记录创建时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "最后修改该记录的用户")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty(value = "记录最后更新时间")
    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}
src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
@@ -4,12 +4,10 @@
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 com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
@@ -77,7 +77,7 @@
        // æ‰¹é‡æŸ¥è¯¢ç™»è®°äºº
        Map<Long, SysUser> sysUserMap;
        if (!registrantIds.isEmpty()) {
            List<SysUser> sysUsers = sysUserMapper.selectRegistrantIds(registrantIds);
            List<SysUser> sysUsers = sysUserMapper.selectList(registrantIds);
            sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));
        } else {
            sysUserMap = new HashMap<>();
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
@@ -11,7 +11,6 @@
import com.ruoyi.basic.pojo.StorageAttachment;
import com.ruoyi.basic.pojo.StorageBlob;
import com.ruoyi.basic.service.StorageAttachmentService;
import com.ruoyi.common.constant.StorageAttachmentConstants;
import com.ruoyi.common.utils.MinioUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
@@ -22,8 +21,6 @@
import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java
@@ -1,6 +1,6 @@
package com.ruoyi.inspectiontask.service.impl;
import org.quartz.*;
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
@@ -8,8 +8,6 @@
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
src/main/java/com/ruoyi/inspectiontask/service/impl/SpringContextHolder.java
@@ -1,6 +1,5 @@
package com.ruoyi.inspectiontask.service.impl;
import org.quartz.JobExecutionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -11,8 +11,6 @@
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.Serializable;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -84,9 +84,13 @@
    /**
     * åˆ é™¤ä»»åŠ¡
     */
    public void unscheduleTimingTask(Long taskId) throws SchedulerException {
        JobKey jobKey = new JobKey("timingTask_" + taskId);
        scheduler.deleteJob(jobKey);
    public void unscheduleTimingTask(Long taskId){
        try {
            JobKey jobKey = new JobKey("timingTask_" + taskId);
            scheduler.deleteJob(jobKey);
        }catch (SchedulerException e){
            throw new RuntimeException(e);
        }
    }
    private JobDetail buildJobDetail(TimingTask task) {
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -155,7 +155,7 @@
        }
    }
    private LocalDateTime calculateFirstExecutionTime(TimingTask task) {
    public LocalDateTime calculateFirstExecutionTime(TimingTask task) {
        // æ ¹æ®é¢‘率类型和详情计算首次执行时间
        String frequencyType = task.getFrequencyType();
        if ("DAILY".equals(frequencyType)) {
@@ -455,7 +455,13 @@
    @Override
    public int delByIds(Long[] ids) {
        return timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
        int i = timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
        if(i > 0){
            for (Long id : ids) {
                timingTaskScheduler.unscheduleTimingTask(id);
            }
        }
        return i;
    }
}
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java
@@ -7,7 +7,7 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerRecordDTO;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
@@ -107,8 +107,8 @@
    @ApiOperation("计量器具台账-检定")
    @Log(title = "计量器具台账-检定", businessType = BusinessType.UPDATE)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult verifying(@RequestBody MeasuringInstrumentLedgerRecordDTO measuringInstrumentLedgerRecordDTO) throws IOException {
        boolean update = measuringInstrumentLedgerService.verifying(measuringInstrumentLedgerRecordDTO);
    public AjaxResult verifying(@RequestBody MeasuringInstrumentLedgerDto measuringInstrumentLedger) throws IOException {
        boolean update = measuringInstrumentLedgerService.verifying(measuringInstrumentLedger);
        return update ? AjaxResult.success("检定成功") : AjaxResult.error("检定失败");
    }
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java
@@ -8,7 +8,6 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerRecordService;
import io.jsonwebtoken.lang.Collections;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -17,7 +16,6 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
 * @author :yys
@@ -52,14 +50,6 @@
        return AjaxResult.error();
    }
    @DeleteMapping("/delete")
    @ApiOperation("计量器具台账记录-删除")
    @Log(title = "计量器具台账记录-删除", businessType = BusinessType.DELETE)
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if(Collections.isEmpty(ids)) return AjaxResult.error("请选择要删除的数据");
        return AjaxResult.success(measuringInstrumentLedgerRecordService.removeBatchByIds(ids));
    }
    /**
     * å¯¼å‡ºè®¡é‡å™¨å…·å°è´¦
     */
@@ -68,11 +58,6 @@
    @PostMapping("/export")
    public void export(HttpServletResponse response) {
        measuringInstrumentLedgerRecordService.export( response);
    }
    @GetMapping("/detail/{id}")
    public AjaxResult getById(@PathVariable("id") Long id) {
        return AjaxResult.success(measuringInstrumentLedgerRecordService.getById(id));
    }
}
src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java
@@ -7,7 +7,6 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.measuringinstrumentledger.dto.SparePartsDto;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
import com.ruoyi.measuringinstrumentledger.service.SparePartsService;
import io.swagger.annotations.Api;
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java
@@ -1,8 +1,6 @@
package com.ruoyi.measuringinstrumentledger.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerPageDto.java
ÎļþÒÑɾ³ý
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerRecordDTO.java
ÎļþÒÑɾ³ý
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java
@@ -104,7 +104,7 @@
     * çŠ¶æ€ï¼ˆ1-有效 2-逾期)
     */
    @ApiModelProperty("状态(1-有效 2-逾期)")
    @Excel(name = "状态", readConverterExp = "1=有效,2=逾期,3=即将到期")
    @Excel(name = "状态", readConverterExp = "1=有效,2=逾期")
    private Integer status;
    /**
@@ -136,17 +136,5 @@
     */
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("部门id")
    private Long deptId;
    @ApiModelProperty("安装位置")
    private String installationLocation;
    @ApiModelProperty("检定单位")
    private String unit;
    @ApiModelProperty("检定周期(天)")
    private Long cycle;
}
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java
@@ -6,6 +6,7 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@@ -22,6 +23,21 @@
     */
    private String sparePartsNo;
    /**
     * å¤‡ä»¶ä»·æ ¼
     */
    private BigDecimal price;
    /**
     * è®¾å¤‡id集合(字符串,隔开)
     */
    private String deviceIds;
    /**
     * è®¾å¤‡åç§°é›†åˆï¼ˆå­—符串,隔开)
     */
    @TableField(exist = false)
    private String deviceNameStr;
    /**
     * å¤‡ä»¶çˆ¶id
     */
    private Long parentId;
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java
@@ -3,7 +3,6 @@
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.measuringinstrumentledger.dto.MeasuringInstrumentLedgerRecordDTO;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
import javax.servlet.http.HttpServletResponse;
@@ -27,6 +26,4 @@
    void export(HttpServletResponse response);
    boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException;
    MeasuringInstrumentLedgerRecordDTO getById(Long id);
}
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java
@@ -3,7 +3,7 @@
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.measuringinstrumentledger.dto.MeasuringInstrumentLedgerRecordDTO;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
import javax.servlet.http.HttpServletResponse;
@@ -30,8 +30,7 @@
     * @param measuringInstrumentLedger
     * @return
     */
    boolean verifying(MeasuringInstrumentLedgerRecordDTO measuringInstrumentLedger) throws IOException;
    boolean verifying(MeasuringInstrumentLedgerDto measuringInstrumentLedger) throws IOException;
    void export(HttpServletResponse response);
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java
@@ -4,14 +4,9 @@
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.StorageBlobDTO;
import com.ruoyi.basic.pojo.StorageAttachment;
import com.ruoyi.basic.service.StorageAttachmentService;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.enums.StorageAttachmentRecordType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerRecordDTO;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
@@ -23,7 +18,6 @@
import com.ruoyi.sales.pojo.CommonFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -39,11 +33,7 @@
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile;
/**
 * @author :yys
@@ -64,9 +54,6 @@
    @Autowired
    private TempFileMapper tempFileMapper;
    @Autowired
    private StorageAttachmentService storageAttachmentService;
    @Value("${file.upload-dir}")
    private String uploadDir;
@@ -185,20 +172,5 @@
                throw new IOException("文件迁移异常", e);
            }
        }
    }
    @Override
    public MeasuringInstrumentLedgerRecordDTO getById(Long id) {
        MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord = measuringInstrumentLedgerRecordMapper.selectById(id);
        List<StorageAttachment> storageAttachments = storageAttachmentService.selectStorageAttachments(measuringInstrumentLedgerRecord.getId(), StorageAttachmentRecordType.MeasuringInstrumentLedgerRecord, StorageAttachmentFile);
        List<StorageBlobDTO> storageBlobDTOList =
                storageAttachments.stream()
                        .map(StorageAttachment::getStorageBlobDTO)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
        MeasuringInstrumentLedgerRecordDTO measuringInstrumentLedgerRecordDTO = new MeasuringInstrumentLedgerRecordDTO();
        BeanUtils.copyProperties(measuringInstrumentLedgerRecord, measuringInstrumentLedgerRecordDTO);
        measuringInstrumentLedgerRecordDTO.setBlobs(storageBlobDTOList);
        return measuringInstrumentLedgerRecordDTO;
    }
}
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java
@@ -5,14 +5,10 @@
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.dto.StorageBlobDTO;
import com.ruoyi.basic.pojo.StorageAttachment;
import com.ruoyi.basic.service.StorageAttachmentService;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.enums.StorageAttachmentRecordType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerRecordDTO;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
@@ -40,12 +36,10 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile;
/**
 * @author :yys
@@ -70,54 +64,64 @@
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private StorageAttachmentService attachmentService;
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Override
    public IPage<MeasuringInstrumentLedger> listPage(Page page, MeasuringInstrumentLedger measuringInstrumentLedger) {
        IPage<MeasuringInstrumentLedger> iPage = measuringInstrumentLedgerMapper.listPage(page, measuringInstrumentLedger);
        List<MeasuringInstrumentLedger> records = iPage.getRecords();
        List<Long> ids = records.stream().map(MeasuringInstrumentLedger::getId).collect(Collectors.toList());
        List<MeasuringInstrumentLedgerRecord> measuringInstrumentLedgerRecords = measuringInstrumentLedgerRecordMapper.selectList(new LambdaQueryWrapper<MeasuringInstrumentLedgerRecord>()
                .in(MeasuringInstrumentLedgerRecord::getMeasuringInstrumentLedgerId, ids)
                .orderByDesc(MeasuringInstrumentLedgerRecord::getCreateTime));
        if (!CollectionUtils.isEmpty(measuringInstrumentLedgerRecords)) {
            Map<Long, List<MeasuringInstrumentLedgerRecord>> collect = measuringInstrumentLedgerRecords.stream().collect(Collectors.groupingBy(MeasuringInstrumentLedgerRecord::getMeasuringInstrumentLedgerId));
            for (MeasuringInstrumentLedger ledger : records) {
                if (collect.containsKey(ledger.getId())) {
                    ledger.setMostDate(collect.get(ledger.getId()).get(0).getRecordDate());
                }
        IPage<MeasuringInstrumentLedger> measuringInstrumentLedgerIPage = measuringInstrumentLedgerMapper.listPage(page, measuringInstrumentLedger);
        List<Integer>  types = new ArrayList<>();
        types.add(FileNameType.MEASURING.getValue());
        types.add(FileNameType.MEASURINGRecord.getValue());
        measuringInstrumentLedgerIPage.getRecords().forEach(item -> {
            LambdaQueryWrapper<MeasuringInstrumentLedgerRecord> measuringInstrumentLedgerRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            measuringInstrumentLedgerRecordLambdaQueryWrapper.eq(MeasuringInstrumentLedgerRecord::getMeasuringInstrumentLedgerId, item.getId());
            List<MeasuringInstrumentLedgerRecord> measuringInstrumentLedgerRecords = measuringInstrumentLedgerRecordMapper.selectList(measuringInstrumentLedgerRecordLambdaQueryWrapper);
            List<Long> collect = new ArrayList<>();
            if(!CollectionUtils.isEmpty(measuringInstrumentLedgerRecords)){
                collect = measuringInstrumentLedgerRecords.stream().map(MeasuringInstrumentLedgerRecord::getId).collect(Collectors.toList());
            }
        }
        return iPage;
            collect.add(item.getId());
            LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
            salesLedgerFileWrapper.in(CommonFile::getCommonId, collect)
                    .in(CommonFile::getType,types);
            List<CommonFile> commonFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
            item.setCommonFiles(commonFiles);
        });
        return measuringInstrumentLedgerIPage;
    }
    @Override
    public boolean verifying(MeasuringInstrumentLedgerRecordDTO req) throws IOException {
        MeasuringInstrumentLedger measuringInstrumentLedger = measuringInstrumentLedgerMapper.selectById(req.getMeasuringInstrumentLedgerId());
        if (measuringInstrumentLedger == null) {
            throw new RuntimeException("计量器具台账不存在");
    public boolean verifying(MeasuringInstrumentLedgerDto req) throws IOException {
        MeasuringInstrumentLedger measuringInstrumentLedger = measuringInstrumentLedgerMapper.selectById(req.getId());
        if(measuringInstrumentLedger == null) {
            return false;
        }
        measuringInstrumentLedgerRecordMapper.insert(req);
        if (req.getBlobs() != null && !req.getBlobs().isEmpty()) {
            List<StorageAttachment> attachments = new ArrayList<>();
            for (StorageBlobDTO storageBlobDTO : req.getBlobs()) {
                StorageAttachment storageAttachment = new StorageAttachment(
                        StorageAttachmentFile,
                        (long) StorageAttachmentRecordType.MeasuringInstrumentLedgerRecord.ordinal(),
                        req.getId()
                );
                storageAttachment.setStorageBlobDTO(storageBlobDTO);
                attachments.add(storageAttachment);
        SysUser sysUser = sysUserMapper.selectUserById(measuringInstrumentLedger.getUserId());
        measuringInstrumentLedger.setValid(req.getValid());
        measuringInstrumentLedger.setMostDate(req.getRecordDate());
        measuringInstrumentLedger.setNextDate(new Date(req.getRecordDate().getTime() + 1000L * 60 * 60 * 24 * req.getValid()));
        MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord = new MeasuringInstrumentLedgerRecord();
        if(measuringInstrumentLedgerMapper.updateById(measuringInstrumentLedger) > 0) {
            measuringInstrumentLedgerRecord.setMeasuringInstrumentLedgerId(req.getId());
            measuringInstrumentLedgerRecord.setRecordDate(req.getRecordDate());
            measuringInstrumentLedgerRecord.setEntryDate(req.getEntryDate());
            measuringInstrumentLedgerRecord.setValid(req.getValid());
            measuringInstrumentLedgerRecord.setUserId(req.getUserId());
            measuringInstrumentLedgerRecord.setUserName(sysUser.getUserName());
            measuringInstrumentLedgerRecordMapper.insert(measuringInstrumentLedgerRecord);
            // å°è´¦ç»‘定一次
//            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
//                migrateTempFilesToFormal(measuringInstrumentLedger.getId(), req.getTempFileIds(), FileNameType.MEASURING.getValue());
//            }
            // å°è´¦è®°å½•绑定一次
            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
                migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), req.getTempFileIds(), FileNameType.MEASURINGRecord.getValue());
            }
            attachmentService.saveStorageAttachment(attachments, req.getId(), StorageAttachmentRecordType.MeasuringInstrumentLedgerRecord, StorageAttachmentFile);
            return true;
        }
        return true;
        return false;
    }
    @Override
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java
@@ -2,8 +2,12 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
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.device.mapper.DeviceLedgerMapper;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.measuringinstrumentledger.dto.SparePartsDto;
import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
@@ -15,14 +19,29 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class SparePartsServiceImpl extends ServiceImpl<SparePartsMapper, SpareParts> implements SparePartsService {
    @Autowired
    private SparePartsMapper sparePartsMapper;
    @Autowired
    private DeviceLedgerMapper deviceLedgerMapper;
    @Override
    public IPage<SparePartsDto> listPage(Page page, SpareParts spareParts) {
        return sparePartsMapper.listPage(page,spareParts);
        IPage<SparePartsDto> sparePartsDtoIPage = sparePartsMapper.listPage(page, spareParts);
        for (SparePartsDto record : sparePartsDtoIPage.getRecords()) {
            if(StringUtils.isNotEmpty(record.getDeviceIds())){
                List<String> deviceIds = StringUtils.str2List(record.getDeviceIds(), ",", true, true);
                List<DeviceLedger> deviceLedgers = deviceLedgerMapper.selectBatchIds(deviceIds);
                if(CollectionUtils.isNotEmpty(deviceLedgers)){
                    record.setDeviceNameStr(deviceLedgers.stream().map(DeviceLedger::getDeviceName).collect(Collectors.joining( ",")));
                }
            }
        }
        return sparePartsDtoIPage;
    }
    @Override
src/main/resources/mapper/device/DeviceRepairMapper.xml
@@ -14,7 +14,6 @@
                dr.maintenance_name,
                dr.maintenance_time,
                dr.maintenance_result,
                dr.maintenance_price,
                dr.status,
                dr.create_time,
                dr.update_time,
@@ -60,7 +59,6 @@
               dr.maintenance_name,
               dr.maintenance_time,
               dr.maintenance_result,
               dr.maintenance_price,
               dr.status,
               dr.create_time,
               dr.update_time,
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
@@ -2,48 +2,54 @@
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper">
    <select id="listPage" resultType="com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerPageDto">
    <select id="listPage" resultType="com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger">
        SELECT
        mil.id,
        mil.user_id,
        mil.user_name,
        mil.code,
        sd.dept_name,
        mil.installation_location,
        mil.unit,
        mil.cycle,
        mil.name,
        mil.model,
        mil.most_date,
        mil.valid,
        mil.next_date,
        mil.record_date,
        mil.create_user,
        mil.create_time,
        mil.update_user,
        mil.update_time,
        mil.tenant_id
        id,
        user_id,
        user_name,
        code,
        name,
        model,
        most_date,
        valid,
        next_date,
        record_date,
        CASE
        WHEN next_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d') THEN 1
        ELSE 2
        END AS status,
        create_user,
        create_time,
        update_user,
        update_time,
        tenant_id
        FROM
        measuring_instrument_ledger mil
        left join sys_dept sd on sd.id = mil.dept_id
        measuring_instrument_ledger
        <where>
            <!-- æŸ¥è¯¢æ¡ä»¶åŒä¸Š -->
            <if test="req.code != null and req.code != ''">
                AND mil.code LIKE CONCAT('%', #{req.code}, '%')
                AND code LIKE CONCAT('%', #{req.code}, '%')
            </if>
            <if test="req.name != null and req.name != ''">
                AND mil.name LIKE CONCAT('%', #{req.name}, '%')
                AND name LIKE CONCAT('%', #{req.name}, '%')
            </if>
            <if test="req.status != null">
                AND mil.status = #{req.status}
                <choose>
                    <when test="req.status == 1">
                        AND next_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d')
                    </when>
                    <when test="req.status == 2">
                        AND next_date &lt;  DATE_FORMAT(now(),'%Y-%m-%d')
                    </when>
                </choose>
            </if>
            <if test="req.tenantId != null">
                AND mil.tenant_id = #{req.tenantId}
                AND tenant_id = #{req.tenantId}
            </if>
            <if test="req.recordDate != null">
                AND mil.record_date = DATE_FORMAT(#{req.recordDate},'%Y-%m-%d')
                AND record_date = DATE_FORMAT(#{req.recordDate},'%Y-%m-%d')
            </if>
        </where>
        ORDER BY mil.update_time DESC
        ORDER BY update_time DESC
    </select>
</mapper>