gongchunyi
3 天以前 bbe9fb61a7e3fbad1745bc09dc3e3c100eacc8b6
feat: 设备保养修改,新增保养人、详情
已添加1个文件
已修改11个文件
294 ■■■■■ 文件已修改
doc/maintenance_task_add_person_and_items.sql 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/DeviceMaintenanceFileService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceFileServiceImpl.java 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/maintenance_task_add_person_and_items.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
-- ============================================================================
-- å®šæ—¶ä¿å…»ä»»åŠ¡ maintenance_task:保养人、保养项目
-- è®¾å¤‡ä¿å…»è®°å½• device_maintenance:计划保养人
-- ============================================================================
ALTER TABLE `maintenance_task`
    ADD COLUMN `maintenance_person_id` bigint NULL DEFAULT NULL COMMENT '保养人id' AFTER `registrant`;
ALTER TABLE `maintenance_task`
    ADD COLUMN `maintenance_person` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '保养人' AFTER `maintenance_person_id`;
ALTER TABLE `maintenance_task`
    ADD COLUMN `maintenance_items` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '保养项目' AFTER `maintenance_person`;
ALTER TABLE `device_maintenance`
    ADD COLUMN `maintenance_person_id` bigint NULL DEFAULT NULL COMMENT '计划保养人id' AFTER `maintenance_actually_name`;
ALTER TABLE `device_maintenance`
    ADD COLUMN `maintenance_person` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '计划保养人' AFTER `maintenance_person_id`;
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java
@@ -8,6 +8,7 @@
import io.swagger.annotations.Api;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
@@ -31,22 +32,41 @@
    /**
     * æ–°å¢ž
     *
     * @param deviceMaintenanceFile
     * @return
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody DeviceMaintenanceFile deviceMaintenanceFile) {
        return AjaxResult.success(deviceMaintenanceFileService.save(deviceMaintenanceFile));
        try {
            return AjaxResult.success(deviceMaintenanceFileService.saveRecord(deviceMaintenanceFile));
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * ä¸Šä¼ é™„ä»¶
     */
    @PostMapping("/upload")
    public AjaxResult upload(@RequestParam("file") MultipartFile file,
                             @RequestParam("deviceMaintenanceId") Integer deviceMaintenanceId) {
        try {
            return AjaxResult.success(deviceMaintenanceFileService.uploadFile(file, deviceMaintenanceId));
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * åˆ é™¤
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/del")
    public AjaxResult delQualityUnqualified(@RequestBody List<Integer> ids) {
        if(CollectionUtils.isEmpty(ids)){
        if (CollectionUtils.isEmpty(ids)) {
            return AjaxResult.error("请选择至少一条数据");
        }
        //删除检验附件
@@ -54,14 +74,20 @@
    }
    /**
     *分页查询
     * åˆ†é¡µæŸ¥è¯¢
     *
     * @param page
     * @param deviceMaintenanceFile
     * @return
     */
    @GetMapping("/listPage")
    public AjaxResult qualityInspectFileListPage(Page page, DeviceMaintenanceFile deviceMaintenanceFile) {
        return AjaxResult.success(deviceMaintenanceFileService.page(page, Wrappers.<DeviceMaintenanceFile>lambdaQuery().eq(DeviceMaintenanceFile::getDeviceMaintenanceId,deviceMaintenanceFile.getDeviceMaintenanceId())));
        Page<DeviceMaintenanceFile> result = deviceMaintenanceFileService.page(page,
                Wrappers.<DeviceMaintenanceFile>lambdaQuery()
                        .eq(DeviceMaintenanceFile::getDeviceMaintenanceId, deviceMaintenanceFile.getDeviceMaintenanceId())
                        .orderByDesc(DeviceMaintenanceFile::getCreateTime));
        deviceMaintenanceFileService.enrichAccessUrl(result.getRecords());
        return AjaxResult.success(result);
    }
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -32,6 +32,9 @@
    @ApiModelProperty("计划保养日期")
    private String maintenancePlanTime;
    @ApiModelProperty("计划保养人")
    private String maintenancePerson;
    @ApiModelProperty("实际保养人")
    private String maintenanceActuallyName;
src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -50,6 +50,12 @@
    @ApiModelProperty("实际保养人")
    private String maintenanceActuallyName;
    @ApiModelProperty("计划保养人id")
    private Long maintenancePersonId;
    @ApiModelProperty("计划保养人")
    private String maintenancePerson;
    @ApiModelProperty("实际保养日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java
@@ -37,6 +37,10 @@
    @ApiModelProperty("文件路径")
    private String url;
    @ApiModelProperty("临时文件ID")
    @TableField(exist = false)
    private String tempId;
    @ApiModelProperty("文件大小")
    private Integer fileSize;
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -69,6 +69,17 @@
    @Excel(name = "录入人")
    private String registrant;
    @ApiModelProperty(value = "保养人id")
    private Long maintenancePersonId;
    @ApiModelProperty(value = "保养人")
    @Excel(name = "保养人")
    private String maintenancePerson;
    @ApiModelProperty(value = "保养项目")
    @Excel(name = "保养项目")
    private String maintenanceItems;
    @ApiModelProperty(value = "录入日期")
    @Excel(name = "录入日期", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd")
src/main/java/com/ruoyi/device/service/DeviceMaintenanceFileService.java
@@ -1,7 +1,11 @@
package com.ruoyi.device.service;
import com.ruoyi.device.pojo.DeviceMaintenanceFile;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.device.pojo.DeviceMaintenanceFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
 * <p>
@@ -13,4 +17,11 @@
 */
public interface DeviceMaintenanceFileService extends IService<DeviceMaintenanceFile> {
    DeviceMaintenanceFile uploadFile(MultipartFile file, Integer deviceMaintenanceId) throws IOException;
    DeviceMaintenanceFile bindFromTemp(String tempId, Integer deviceMaintenanceId, String name) throws IOException;
    DeviceMaintenanceFile saveRecord(DeviceMaintenanceFile deviceMaintenanceFile) throws IOException;
    void enrichAccessUrl(List<DeviceMaintenanceFile> files);
}
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceFileServiceImpl.java
@@ -1,10 +1,31 @@
package com.ruoyi.device.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.device.mapper.DeviceMaintenanceFileMapper;
import com.ruoyi.device.pojo.DeviceMaintenanceFile;
import com.ruoyi.device.service.DeviceMaintenanceFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
/**
 * <p>
@@ -15,6 +36,167 @@
 * @since 2026-01-27 09:48:09
 */
@Service
public class DeviceMaintenanceFileServiceImpl extends ServiceImpl<DeviceMaintenanceFileMapper, DeviceMaintenanceFile> implements DeviceMaintenanceFileService {
@Slf4j
public class DeviceMaintenanceFileServiceImpl extends ServiceImpl<DeviceMaintenanceFileMapper, DeviceMaintenanceFile>
        implements DeviceMaintenanceFileService {
    @Resource
    private TempFileMapper tempFileMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Value("${file.temp-dir}")
    private String tempDir;
    @Override
    public DeviceMaintenanceFile uploadFile(MultipartFile file, Integer deviceMaintenanceId) throws IOException {
        if (deviceMaintenanceId == null || deviceMaintenanceId <= 0) {
            throw new ServiceException("设备保养记录ID不能为空");
        }
        if (file == null || file.isEmpty()) {
            throw new ServiceException("上传失败,文件不能为空");
        }
        Path formalPath = storeMultipartFile(file, deviceMaintenanceId);
        return insertFileRecord(deviceMaintenanceId, file.getOriginalFilename(), formalPath, (int) file.getSize());
    }
    @Override
    public DeviceMaintenanceFile bindFromTemp(String tempId, Integer deviceMaintenanceId, String name) throws IOException {
        if (!StringUtils.hasText(tempId)) {
            throw new ServiceException("临时文件ID不能为空");
        }
        if (deviceMaintenanceId == null || deviceMaintenanceId <= 0) {
            throw new ServiceException("设备保养记录ID不能为空");
        }
        TempFile tempFile = tempFileMapper.selectById(tempId);
        if (tempFile == null) {
            throw new ServiceException("临时文件不存在或已过期");
        }
        Path source = Paths.get(tempFile.getTempPath());
        if (!Files.exists(source)) {
            tempFileMapper.deleteById(tempId);
            throw new ServiceException("临时文件已失效,请重新上传");
        }
        Path formalPath = copyToFormalDir(source, deviceMaintenanceId, tempFile.getOriginalName());
        Files.deleteIfExists(source);
        tempFileMapper.deleteById(tempId);
        String fileName = StringUtils.hasText(name) ? name : tempFile.getOriginalName();
        return insertFileRecord(deviceMaintenanceId, fileName, formalPath, null);
    }
    @Override
    public DeviceMaintenanceFile saveRecord(DeviceMaintenanceFile deviceMaintenanceFile) throws IOException {
        if (deviceMaintenanceFile == null) {
            throw new ServiceException("附件信息不能为空");
        }
        if (StringUtils.hasText(deviceMaintenanceFile.getTempId())) {
            return bindFromTemp(
                    deviceMaintenanceFile.getTempId(),
                    deviceMaintenanceFile.getDeviceMaintenanceId(),
                    deviceMaintenanceFile.getName());
        }
        String url = deviceMaintenanceFile.getUrl();
        if (isTempStoragePath(url)) {
            throw new ServiceException("请勿直接保存临时目录文件,请使用上传接口或传递 tempId");
        }
        if (StringUtils.hasText(url) && !url.startsWith(Constants.RESOURCE_PREFIX)) {
            deviceMaintenanceFile.setUrl(buildAccessLink(Paths.get(url)));
        }
        save(deviceMaintenanceFile);
        enrichAccessUrl(deviceMaintenanceFile);
        return deviceMaintenanceFile;
    }
    @Override
    public void enrichAccessUrl(List<DeviceMaintenanceFile> files) {
        if (files == null) {
            return;
        }
        files.forEach(this::enrichAccessUrl);
    }
    private void enrichAccessUrl(DeviceMaintenanceFile file) {
        if (file == null || !StringUtils.hasText(file.getUrl())) {
            return;
        }
        String url = file.getUrl().trim();
        if (url.startsWith(Constants.RESOURCE_PREFIX) || url.startsWith("http://") || url.startsWith("https://")) {
            return;
        }
        try {
            file.setUrl(buildAccessLink(Paths.get(url)));
        } catch (Exception e) {
            log.warn("附件URL转换失败 id={} url={}", file.getId(), url);
        }
    }
    private Path storeMultipartFile(MultipartFile file, Integer deviceMaintenanceId) throws IOException {
        Path formalDirPath = resolveFormalDirPath();
        Files.createDirectories(formalDirPath);
        String originalFilename = file.getOriginalFilename();
        if (!StringUtils.hasText(originalFilename)) {
            throw new ServiceException("文件名不能为空");
        }
        Path formalPath = formalDirPath.resolve(buildFormalFilename(deviceMaintenanceId, originalFilename));
        file.transferTo(formalPath.toFile());
        return formalPath;
    }
    private Path copyToFormalDir(Path source, Integer deviceMaintenanceId, String originalFilename) throws IOException {
        Path formalDirPath = resolveFormalDirPath();
        Files.createDirectories(formalDirPath);
        String name = StringUtils.hasText(originalFilename) ? originalFilename : source.getFileName().toString();
        Path formalPath = formalDirPath.resolve(buildFormalFilename(deviceMaintenanceId, name));
        Files.copy(source, formalPath, StandardCopyOption.REPLACE_EXISTING);
        return formalPath;
    }
    private Path resolveFormalDirPath() {
        String dir = uploadDir;
        if (!dir.endsWith("/") && !dir.endsWith("\\")) {
            dir = dir + "/";
        }
        return Paths.get(dir + "deviceMaintenance/" + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
    private String buildFormalFilename(Integer deviceMaintenanceId, String originalFilename) {
        String ext = FilenameUtils.getExtension(originalFilename);
        String base = deviceMaintenanceId + "_" + System.currentTimeMillis() + "_"
                + UUID.randomUUID().toString().substring(0, 8);
        return StringUtils.hasText(ext) ? base + "." + ext : base;
    }
    private DeviceMaintenanceFile insertFileRecord(Integer deviceMaintenanceId, String name, Path formalPath, Integer fileSize) {
        DeviceMaintenanceFile record = new DeviceMaintenanceFile();
        record.setName(name);
        record.setUrl(buildAccessLink(formalPath));
        record.setFileSize(fileSize);
        record.setDeviceMaintenanceId(deviceMaintenanceId);
        save(record);
        return record;
    }
    private boolean isTempStoragePath(String url) {
        if (!StringUtils.hasText(url)) {
            return false;
        }
        String normalized = url.replace("\\", "/").toLowerCase();
        return normalized.contains("/temp/") || normalized.contains("temp/uploads");
    }
    private String buildAccessLink(Path formalFilePath) {
        String normalizedPath = formalFilePath.toString().replace("\\", "/");
        String profile = RuoYiConfig.getProfile();
        String normalizedProfile = profile == null ? "" : profile.replace("\\", "/");
        String relativePath = normalizedPath;
        if (StringUtils.hasText(normalizedProfile) && normalizedPath.startsWith(normalizedProfile)) {
            relativePath = normalizedPath.substring(normalizedProfile.length());
        }
        if (!relativePath.startsWith("/")) {
            relativePath = "/" + relativePath;
        }
        return Constants.RESOURCE_PREFIX + relativePath;
    }
}
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -37,8 +37,8 @@
    @Override
    public AjaxResult saveDeviceRepair(DeviceMaintenance deviceMaintenance) {
        boolean save = this.save(deviceMaintenance);
        if (save){
            return AjaxResult.success();
        if (save) {
            return AjaxResult.success(deviceMaintenance);
        }
        return AjaxResult.error();
    }
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
@@ -97,6 +97,11 @@
        inspectionTask.setTenantId(timingTask.getTenantId());
        inspectionTask.setStatus(0);
        inspectionTask.setDeviceModel(timingTask.getDeviceModel());
        inspectionTask.setMaintenanceLocation(timingTask.getMaintenanceItems());
        if (timingTask.getMaintenancePersonId() != null) {
            inspectionTask.setMaintenancePersonId(timingTask.getMaintenancePersonId());
            inspectionTask.setMaintenancePerson(timingTask.getMaintenancePerson());
        }
        inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
        inspectionTask.setUpdateTime(LocalDateTime.now());
        inspectionTask.setCreateTime(LocalDateTime.now());
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -66,6 +66,9 @@
            if (task.getRegistrantId() != null) {
                userIds.add(task.getRegistrantId());
            }
            if (task.getMaintenancePersonId() != null) {
                userIds.add(task.getMaintenancePersonId());
            }
        });
        // 4. æ‰¹é‡æŸ¥è¯¢ç”¨æˆ·ä¿¡æ¯
@@ -75,10 +78,12 @@
            users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
        }
        taskPage.getRecords().forEach(task -> {
            // è®¾ç½®ç™»è®°äººæ˜µç§°
            if (task.getRegistrantId() != null) {
                task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "未知用户"));
            }
            if (task.getMaintenancePersonId() != null) {
                task.setMaintenancePerson(userNickNameMap.getOrDefault(task.getMaintenancePersonId(), "未知用户"));
            }
        });
        return AjaxResult.success(taskPage);
    }
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -18,6 +18,7 @@
        dm.update_user,
        dm.tenant_id,
        dm.maintenance_actually_name,
        dm.maintenance_person,
        dm.maintenance_location,
        dl.device_name,
        dl.device_model,
@@ -67,6 +68,7 @@
               dm.update_user,
               dm.tenant_id,
               dm.maintenance_actually_name,
               dm.maintenance_person,
               dm.maintenance_location,
               dl.device_name,
               dl.device_model,