已添加9个文件
已修改37个文件
1176 ■■■■■ 文件已修改
basic-server/src/main/java/com/ruoyi/basic/event/StandardMethodSavedEvent.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/resources/mapper/StandardMethodMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/controller/ClientSatisfactionController.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/mapper/ClientSatisfactionAttachmentMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/pojo/ClientSatisfaction.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/pojo/ClientSatisfactionAttachment.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/service/ClientSatisfactionService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ClientSatisfactionServiceImpl.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ManageRecordIntervalsServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ManageRecordVerifyServiceImpl.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewFileSeqMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/resources/mapper/ProcessMethodSearchNewFileSeqMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/controller/FeStandardSubstanceAcceptanceController.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/controller/FeStandardSubstanceRecordController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/controller/SupplierManagementController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/dto/AcceptanceDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/excel/FeStandardSubstanceExcel.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/excel/FeStandardSubstanceImport.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/mapper/SupplierManagementAttachmentMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstance.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstanceAcceptance.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstanceRecord.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/pojo/SupplierManagementAttachment.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/FeStandardSubstanceRecordService.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/SupplierManagementService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceAcceptanceServiceImpl.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceRecordServiceImpl.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/service/impl/SupplierManagementServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/vo/AcceptanceVo.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/java/com/ruoyi/require/vo/SubstanceRecordVo.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/resources/mapper/FeStandardSubstanceAcceptanceMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-require/src/main/resources/mapper/FeStandardSubstanceRecordMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-druid.yml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-xjxj.yml 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/event/StandardMethodSavedEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.basic.event;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
/** æ ‡å‡†ç»´æŠ¤ä¿å­˜äº‹ä»¶ã€‚ */
@Data
@AllArgsConstructor
@Schema(description = "标准维护保存事件")
public class StandardMethodSavedEvent {
    @Schema(description = "标准方法ID")
    private Integer standardMethodId;
    @Schema(description = "标准编号")
    private String code;
    @Schema(description = "标准描述")
    private String name;
    @Schema(description = "是否查新(0否,1是)")
    private Integer needSearchNew;
    @Schema(description = "是否为编辑操作")
    private boolean edit;
}
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java
@@ -15,27 +15,33 @@
 */
@TableName(value ="standard_method")
@Data
@Schema(description = "标准方法")
public class StandardMethod implements Serializable {
    /**
     *
     */
    @TableId(type = IdType.AUTO)
    @Schema(description = "标准方法ID")
    private Integer id;
    @Schema(description = "领域")
    private String field;
    @Schema(description = "检验对象")
    private String structureTestObjectId;
    /** æ ‡å‡†åº“一级行业ID(仅接口交互,不落standard_method表) */
    @Schema(description = "标准库一级行业ID")
    @TableField(exist = false)
    private List<Integer> industryIds;
    /** å·²ç»‘定行业名称(列表展示) */
    @Schema(description = "已绑定行业名称")
    @TableField(exist = false)
    private String industryNames;
    /** é™„件数量(列表展示) */
    @Schema(description = "附件数量")
    @TableField(exist = false)
    private Integer attachmentCount;
@@ -69,6 +75,9 @@
    @Schema(description = "是否启用")
    private Integer isUse;
    @Schema(description = "是否查新(0否,1是)")
    private Integer needSearchNew;
    @Schema(description = "创建人id")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
@@ -8,6 +8,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.pojo.StandardMethodList;
import com.ruoyi.basic.event.StandardMethodSavedEvent;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.basic.mapper.StandardMethodMapper;
import com.ruoyi.basic.mapper.StandardProductListMapper;
@@ -31,6 +32,7 @@
import com.ruoyi.basic.utils.StandardTreePath;
import com.ruoyi.basic.utils.StandardTreePathParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@@ -66,6 +68,7 @@
    private LaboratoryMapper laboratoryMapper;
    private StandardTreeMapper standardTreeMapper;
    private StandardTreeTemplateBindingMapper standardTreeTemplateBindingMapper;
    private final ApplicationEventPublisher eventPublisher;
    @Value("${file.path}")
    private String filePath;
@@ -86,7 +89,8 @@
                                     StandardMethodAttachmentMapper standardMethodAttachmentMapper,
                                     LaboratoryMapper laboratoryMapper,
                                     StandardTreeMapper standardTreeMapper,
                                     StandardTreeTemplateBindingMapper standardTreeTemplateBindingMapper) {
                                     StandardTreeTemplateBindingMapper standardTreeTemplateBindingMapper,
                                     ApplicationEventPublisher eventPublisher) {
        this.standardMethodMapper = standardMethodMapper;
        this.standardProductListMapper = standardProductListMapper;
        this.standardProductListService = standardProductListService;
@@ -97,6 +101,7 @@
        this.laboratoryMapper = laboratoryMapper;
        this.standardTreeMapper = standardTreeMapper;
        this.standardTreeTemplateBindingMapper = standardTreeTemplateBindingMapper;
        this.eventPublisher = eventPublisher;
    }
    @Override
@@ -117,8 +122,12 @@
    @Transactional(rollbackFor = Exception.class)
    public Integer addStandardMethod(StandardMethod standardMethod) {
        standardMethod.setStructureTestObjectId(null);
        if (standardMethod.getNeedSearchNew() == null) {
            standardMethod.setNeedSearchNew(0);
        }
        standardMethodMapper.insert(standardMethod);
        syncIndustries(standardMethod, Collections.<Integer>emptySet());
        publishSavedEvent(standardMethod, false);
        return standardMethod.getId();
    }
@@ -149,11 +158,22 @@
        if (!oldStandardMethod.getCode().equals(standardMethod.getCode())) {
            CompletableFuture.supplyAsync(() -> replaceMethod(oldStandardMethod.getCode(), standardMethod.getCode()));
        }
        if (standardMethod.getNeedSearchNew() == null) {
            standardMethod.setNeedSearchNew(oldStandardMethod.getNeedSearchNew() == null
                    ? 0 : oldStandardMethod.getNeedSearchNew());
        }
        int i = standardMethodMapper.updateById(standardMethod);
        syncIndustries(standardMethod, new LinkedHashSet<>(selectIndustryIds(oldStandardMethod.getId())));
        publishSavedEvent(standardMethodMapper.selectById(standardMethod.getId()), true);
        return i;
    }
    private void publishSavedEvent(StandardMethod standardMethod, boolean edit) {
        eventPublisher.publishEvent(new StandardMethodSavedEvent(
                standardMethod.getId(), standardMethod.getCode(), standardMethod.getName(),
                standardMethod.getNeedSearchNew(), edit));
    }
    private List<Integer> selectIndustryIds(Integer methodId) {
        List<StandardMethodIndustry> list = standardMethodIndustryMapper.selectList(
                Wrappers.<StandardMethodIndustry>lambdaQuery()
basic-server/src/main/resources/mapper/StandardMethodMapper.xml
@@ -13,6 +13,7 @@
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
        <result property="needSearchNew" column="need_search_new" jdbcType="INTEGER"/>
    </resultMap>
    <select id="selectStandardMethodList" resultType="com.ruoyi.basic.pojo.StandardMethod">
@@ -30,6 +31,7 @@
                sm.field,
                sm.name_en,
                sm.is_use,
                sm.need_search_new,
                sm.qualification_id,
                COALESCE((SELECT GROUP_CONCAT(l.laboratory_name ORDER BY COALESCE(l.sort, 0), l.id SEPARATOR '、')
                          FROM standard_method_industry smi JOIN laboratory l ON l.id = smi.industry_id
@@ -59,6 +61,7 @@
               sm.field,
               sm.name_en,
               sm.is_use,
               sm.need_search_new,
               sm.qualification_id
        from standard_method sm
                 left join user u1 on sm.create_user = u1.id
cnas-manage/src/main/java/com/ruoyi/manage/controller/ClientSatisfactionController.java
@@ -136,5 +136,33 @@
    public Result delAnalyseFile(Integer analyseFileId){
        return Result.success(clientSatisfactionAnalyseFileMapper.deleteById(analyseFileId));
    }
    /**
     * æŸ¥è¯¢æ»¡æ„åº¦é™„ä»¶
     */
    @Operation(summary = "查询满意度附件")
    @GetMapping("/selectAttachments")
    public Result selectAttachments(Integer clientSatisfactionId) {
        return Result.success(clientSatisfactionService.selectAttachments(clientSatisfactionId));
    }
    /**
     * ä¸Šä¼ æ»¡æ„åº¦é™„ä»¶
     */
    @Operation(summary = "上传满意度附件")
    @PostMapping("/uploadAttachment")
    public Result uploadAttachment(@RequestParam("clientSatisfactionId") Integer clientSatisfactionId,
                                   @RequestParam("file") MultipartFile file) {
        return Result.success(clientSatisfactionService.uploadAttachment(clientSatisfactionId, file));
    }
    /**
     * åˆ é™¤æ»¡æ„åº¦é™„ä»¶
     */
    @Operation(summary = "删除满意度附件")
    @DeleteMapping("/deleteAttachment")
    public Result deleteAttachment(Long id) {
        return Result.success(clientSatisfactionService.deleteAttachment(id));
    }
}
cnas-manage/src/main/java/com/ruoyi/manage/mapper/ClientSatisfactionAttachmentMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.ruoyi.manage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.manage.pojo.ClientSatisfactionAttachment;
import org.apache.ibatis.annotations.Mapper;
/**
 * å®¢æˆ·æ»¡æ„åº¦é™„ä»¶
 */
@Mapper
public interface ClientSatisfactionAttachmentMapper extends BaseMapper<ClientSatisfactionAttachment> {
}
cnas-manage/src/main/java/com/ruoyi/manage/pojo/ClientSatisfaction.java
@@ -73,6 +73,15 @@
    @Schema(description = "备注(对我们的希望)")
    private String remark;
    @Schema(description = "委托单id(ins_order.id)")
    private Integer orderId;
    @Schema(description = "委托单编号")
    private String entrustCode;
    @Schema(description = "样品名称")
    private String sampleName;
    @Schema(description = "创建人")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
cnas-manage/src/main/java/com/ruoyi/manage/pojo/ClientSatisfactionAttachment.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.ruoyi.manage.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * å®¢æˆ·æ»¡æ„åº¦é™„ä»¶
 */
@Data
@TableName("cnas_client_satisfaction_attachment")
public class ClientSatisfactionAttachment {
    @TableId(type = IdType.AUTO)
    private Long id;
    private Integer clientSatisfactionId;
    private String fileName;
    private String fileUrl;
    private Integer sort;
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
cnas-manage/src/main/java/com/ruoyi/manage/service/ClientSatisfactionService.java
@@ -5,9 +5,11 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.manage.pojo.ClientSatisfaction;
import com.ruoyi.manage.pojo.ClientSatisfactionAnalyseFile;
import com.ruoyi.manage.pojo.ClientSatisfactionAttachment;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
/**
 * å®¢æˆ·æ»¡æ„åº¦
@@ -55,5 +57,27 @@
     * @param userId             ä¿®æ”¹äººid
     */
    void confirmClientSatisfaction(ClientSatisfaction clientSatisfaction, Integer userId);
    /**
     * æŸ¥è¯¢æ»¡æ„åº¦é™„ä»¶
     * @param clientSatisfactionId æ»¡æ„åº¦è®°å½•id
     * @return
     */
    List<ClientSatisfactionAttachment> selectAttachments(Integer clientSatisfactionId);
    /**
     * ä¸Šä¼ æ»¡æ„åº¦é™„ä»¶
     * @param clientSatisfactionId æ»¡æ„åº¦è®°å½•id
     * @param file
     * @return
     */
    ClientSatisfactionAttachment uploadAttachment(Integer clientSatisfactionId, MultipartFile file);
    /**
     * åˆ é™¤æ»¡æ„åº¦é™„ä»¶
     * @param id é™„ä»¶id
     * @return
     */
    boolean deleteAttachment(Long id);
}
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ClientSatisfactionServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.manage.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,13 +10,16 @@
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.Pictures;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.framework.exception.ErrorException;
import com.ruoyi.manage.dto.ClientSatisfactionDto;
import com.ruoyi.manage.mapper.ClientSatisfactionAnalyseFileMapper;
import com.ruoyi.manage.mapper.ClientSatisfactionAttachmentMapper;
import com.ruoyi.manage.mapper.ClientSatisfactionMapper;
import com.ruoyi.manage.pojo.ClientSatisfaction;
import com.ruoyi.manage.pojo.ClientSatisfactionAnalyseFile;
import com.ruoyi.manage.pojo.ClientSatisfactionAttachment;
import com.ruoyi.manage.service.ClientSatisfactionService;
import com.ruoyi.system.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Value;
@@ -24,12 +28,14 @@
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
/**
@@ -43,6 +49,9 @@
    @Resource
    private ClientSatisfactionAnalyseFileMapper clientSatisfactionAnalyseFileMapper;
    @Resource
    private ClientSatisfactionAttachmentMapper clientSatisfactionAttachmentMapper;
    @Resource
    private UserMapper userMapper;
@@ -184,5 +193,75 @@
        clientSatisfaction.setConfirmStatus(1);
        baseMapper.updateById(clientSatisfaction);
    }
    /**
     * æŸ¥è¯¢æ»¡æ„åº¦é™„ä»¶
     *
     * @param clientSatisfactionId æ»¡æ„åº¦è®°å½•id
     * @return
     */
    @Override
    public List<ClientSatisfactionAttachment> selectAttachments(Integer clientSatisfactionId) {
        return clientSatisfactionAttachmentMapper.selectList(new QueryWrapper<ClientSatisfactionAttachment>().lambda()
                .eq(ClientSatisfactionAttachment::getClientSatisfactionId, clientSatisfactionId)
                .orderByAsc(ClientSatisfactionAttachment::getSort, ClientSatisfactionAttachment::getId));
    }
    /**
     * ä¸Šä¼ æ»¡æ„åº¦é™„ä»¶
     *
     * @param clientSatisfactionId æ»¡æ„åº¦è®°å½•id
     * @param file
     * @return
     */
    @Override
    public ClientSatisfactionAttachment uploadAttachment(Integer clientSatisfactionId, MultipartFile file) {
        if (baseMapper.selectById(clientSatisfactionId) == null) {
            throw new BaseException("客户满意度调查不存在");
        }
        if (file == null || file.isEmpty()) {
            throw new BaseException("附件不能为空");
        }
        // ç³»ç»Ÿå…¨å±€ä¸Šä¼ ä¸Šé™ä¸º200MB,这里提前给出友好提示
        if (file.getSize() > 200L * 1024 * 1024) {
            throw new BaseException("附件不能超过200MB");
        }
        String originalName = file.getOriginalFilename();
        if (originalName == null || originalName.trim().isEmpty()) {
            originalName = "未命名文件";
        }
        // ä¸ªåˆ«æµè§ˆå™¨å¯èƒ½å¸¦ä¸Šè·¯å¾„前缀,只保留文件名本身
        originalName = originalName.replaceAll(".*[/\\\\]", "");
        try {
            // å›¾ç‰‡æ”¾å›¾ç‰‡ç›®å½•(/img é™æ€è·¯å¾„),其余任意格式放 word ç›®å½•(/word é™æ€è·¯å¾„)
            boolean image = originalName.matches("(?i).+\\.(jpg|jpeg|png|gif)$");
            File directory = new File(image ? imgUrl : wordUrl);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            String fileUrl = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmssSSS")) + "-" + originalName;
            file.transferTo(new File(directory, fileUrl));
            ClientSatisfactionAttachment attachment = new ClientSatisfactionAttachment();
            attachment.setClientSatisfactionId(clientSatisfactionId);
            attachment.setFileName(originalName);
            attachment.setFileUrl(fileUrl);
            attachment.setSort(selectAttachments(clientSatisfactionId).size());
            clientSatisfactionAttachmentMapper.insert(attachment);
            return attachment;
        } catch (IOException e) {
            throw new BaseException("附件上传失败");
        }
    }
    /**
     * åˆ é™¤æ»¡æ„åº¦é™„ä»¶
     *
     * @param id é™„ä»¶id
     * @return
     */
    @Override
    public boolean deleteAttachment(Long id) {
        return clientSatisfactionAttachmentMapper.deleteById(id) > 0;
    }
}
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ManageRecordIntervalsServiceImpl.java
@@ -428,13 +428,7 @@
        List<ManageRecordIntervals> manageRecordIntervalsList = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //获取当前年份
        LocalDate currentDate = LocalDate.now();
        // å®šä¹‰æ—¥æœŸæ ¼å¼
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
        // æ ¼å¼åŒ–当前日期
        String currentMonth = currentDate.format(formatter);
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = manageRecordIntervalsTotalMapper.selectOne(Wrappers.<ManageRecordIntervalsTotal>lambdaQuery().eq(ManageRecordIntervalsTotal::getYear, currentMonth));
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = getOrCreateCurrentYearTotal();
        try {
            InputStream inputStream = file.getInputStream();
            XWPFDocument document = new XWPFDocument(inputStream);
@@ -482,13 +476,7 @@
    @Override
    public int addManageRecordIntervals(ManageRecordIntervals manageRecordIntervals) {
        //获取当前年份
        LocalDate currentDate = LocalDate.now();
        // å®šä¹‰æ—¥æœŸæ ¼å¼
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
        // æ ¼å¼åŒ–当前日期
        String currentMonth = currentDate.format(formatter);
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = manageRecordIntervalsTotalMapper.selectOne(Wrappers.<ManageRecordIntervalsTotal>lambdaQuery().eq(ManageRecordIntervalsTotal::getYear, currentMonth));
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = getOrCreateCurrentYearTotal();
        manageRecordIntervals.setRecordIntervalsTotalId(manageRecordIntervalsTotal.getId());
        manageRecordIntervalsMapper.insert(manageRecordIntervals);
        manageRecordIntervalsTotal.setTotalNum(1 + manageRecordIntervalsTotal.getTotalNum());
@@ -500,10 +488,28 @@
        ManageRecordIntervals manageRecordIntervals = manageRecordIntervalsMapper.selectById(id);
        manageRecordIntervalsMapper.deleteById(id);
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = manageRecordIntervalsTotalMapper.selectById(manageRecordIntervals.getRecordIntervalsTotalId());
        manageRecordIntervalsTotal.setTotalNum(manageRecordIntervalsTotal.getTotalNum() - 1);
        if (manageRecordIntervalsTotal == null) {
            return 0;
        }
        manageRecordIntervalsTotal.setTotalNum((manageRecordIntervalsTotal.getTotalNum() == null ? 0 : manageRecordIntervalsTotal.getTotalNum()) - 1);
        return manageRecordIntervalsTotalMapper.updateById(manageRecordIntervalsTotal);
    }
    // å¹´åº¦æ±‡æ€»è®°å½•原本由每年 1 æœˆ 1 æ—¥çš„定时任务创建,任务未启用时此处兜底自动补建,避免取 id æ—¶æŠ¥ç©ºæŒ‡é’ˆ
    private ManageRecordIntervalsTotal getOrCreateCurrentYearTotal() {
        String year = String.valueOf(LocalDate.now().getYear());
        ManageRecordIntervalsTotal manageRecordIntervalsTotal = manageRecordIntervalsTotalMapper.selectOne(Wrappers.<ManageRecordIntervalsTotal>lambdaQuery().eq(ManageRecordIntervalsTotal::getYear, year));
        if (manageRecordIntervalsTotal == null) {
            manageRecordIntervalsTotal = new ManageRecordIntervalsTotal();
            manageRecordIntervalsTotal.setYear(year);
            manageRecordIntervalsTotal.setTotalNum(0);
            manageRecordIntervalsTotalMapper.insert(manageRecordIntervalsTotal);
        } else if (manageRecordIntervalsTotal.getTotalNum() == null) {
            manageRecordIntervalsTotal.setTotalNum(0);
        }
        return manageRecordIntervalsTotal;
    }
    // æ°´å¹³åˆå¹¶å•元格
    private static void mergeCellsHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
        for (int i = fromCol; i <= toCol; i++) {
cnas-manage/src/main/java/com/ruoyi/manage/service/impl/ManageRecordVerifyServiceImpl.java
@@ -53,28 +53,14 @@
    @Override
    public IPage<ManageRecordVerify> pageManageRecordVerify(Page page, ManageRecordVerify manageRecordVerify) {
        if (ObjectUtils.isEmpty(manageRecordVerify.getManageRecordTotalId())) {
            //获取当前年份
            LocalDate currentDate = LocalDate.now();
            // å®šä¹‰æ—¥æœŸæ ¼å¼
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
            // æ ¼å¼åŒ–当前日期
            String currentMonth = currentDate.format(formatter);
            //查询历史
            ManageRecordTotal manageRecordTotal = manageRecordTotalMapper.selectOne(Wrappers.<ManageRecordTotal>lambdaQuery().eq(ManageRecordTotal::getYear, currentMonth));
            manageRecordVerify.setManageRecordTotalId(manageRecordTotal.getId());
            manageRecordVerify.setManageRecordTotalId(getOrCreateCurrentYearTotal().getId());
        }
        return manageRecordVerifyMapper.pageManageRecordVerify(page, QueryWrappers.queryWrappers(manageRecordVerify));
    }
    @Override
    public int addManageRecordVerify(ManageRecordVerify manageRecordVerify) {
        //获取当前年份
        LocalDate currentDate = LocalDate.now();
        // å®šä¹‰æ—¥æœŸæ ¼å¼
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
        // æ ¼å¼åŒ–当前日期
        String currentMonth = currentDate.format(formatter);
        ManageRecordTotal manageRecordTotal = manageRecordTotalMapper.selectOne(Wrappers.<ManageRecordTotal>lambdaQuery().eq(ManageRecordTotal::getYear, currentMonth));
        ManageRecordTotal manageRecordTotal = getOrCreateCurrentYearTotal();
        manageRecordVerify.setManageRecordTotalId(manageRecordTotal.getId());
        manageRecordVerifyMapper.insert(manageRecordVerify);
        manageRecordTotal.setTotalNum(1 + manageRecordTotal.getTotalNum());
@@ -86,7 +72,10 @@
        ManageRecordVerify manageRecordVerify = manageRecordVerifyMapper.selectById(id);
        manageRecordVerifyMapper.deleteById(id);
        ManageRecordTotal manageRecordTotal = manageRecordTotalMapper.selectById(manageRecordVerify.getManageRecordTotalId());
        manageRecordTotal.setTotalNum(manageRecordTotal.getTotalNum() - 1);
        if (manageRecordTotal == null) {
            return 0;
        }
        manageRecordTotal.setTotalNum((manageRecordTotal.getTotalNum() == null ? 0 : manageRecordTotal.getTotalNum()) - 1);
        return manageRecordTotalMapper.updateById(manageRecordTotal);
    }
@@ -94,13 +83,7 @@
    public int exportManageRecordVerify(MultipartFile file) {
        List<ManageRecordVerify> manageRecordVerifyList = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //获取当前年份
        LocalDate currentDate = LocalDate.now();
        // å®šä¹‰æ—¥æœŸæ ¼å¼
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
        // æ ¼å¼åŒ–当前日期
        String currentMonth = currentDate.format(formatter);
        ManageRecordTotal manageRecordTotal = manageRecordTotalMapper.selectOne(Wrappers.<ManageRecordTotal>lambdaQuery().eq(ManageRecordTotal::getYear, currentMonth));
        ManageRecordTotal manageRecordTotal = getOrCreateCurrentYearTotal();
        try {
            InputStream inputStream = file.getInputStream();
            XWPFDocument document = new XWPFDocument(inputStream);
@@ -154,4 +137,19 @@
        }
        return 0;
    }
    // å¹´åº¦æ±‡æ€»è®°å½•原本由每年 1 æœˆ 1 æ—¥çš„定时任务创建,任务未启用时此处兜底自动补建,避免取 id æ—¶æŠ¥ç©ºæŒ‡é’ˆ
    private ManageRecordTotal getOrCreateCurrentYearTotal() {
        String year = String.valueOf(LocalDate.now().getYear());
        ManageRecordTotal manageRecordTotal = manageRecordTotalMapper.selectOne(Wrappers.<ManageRecordTotal>lambdaQuery().eq(ManageRecordTotal::getYear, year));
        if (manageRecordTotal == null) {
            manageRecordTotal = new ManageRecordTotal();
            manageRecordTotal.setYear(year);
            manageRecordTotal.setTotalNum(0);
            manageRecordTotalMapper.insert(manageRecordTotal);
        } else if (manageRecordTotal.getTotalNum() == null) {
            manageRecordTotal.setTotalNum(0);
        }
        return manageRecordTotal;
    }
}
cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java
@@ -55,7 +55,7 @@
    @Operation(summary = "修改标准查新")
    @PostMapping("/updateMethodSearchNew")
    public Result updateMethodSearchNew(@RequestBody ProcessMethodSearchNew processMethodSearchNew ) {
        return Result.success(processMethodSearchNewService.updateById(processMethodSearchNew));
        return Result.success(processMethodSearchNewService.updateMethodSearchNew(processMethodSearchNew));
    }
    /**
@@ -67,6 +67,12 @@
        return Result.success(processMethodSearchNewService.pageMethodSearchNew(page, processMethodSearchNew));
    }
    @Operation(summary = "自动归档记录列表")
    @GetMapping("/pageAutoArchived")
    public Result<IPage<ProcessMethodSearchNew>> pageAutoArchived(ProcessMethodSearchNew processMethodSearchNew, Page page) {
        return Result.success(processMethodSearchNewService.pageAutoArchived(page, processMethodSearchNew));
    }
    @Operation(summary = "标准查新导出")
    @GetMapping("/exportMethodSearchNew")
    public void exportMethodSearchNew(Integer archivedId, HttpServletResponse response) throws Exception {
cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.ruoyi.process.listener;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.basic.event.StandardMethodSavedEvent;
import com.ruoyi.basic.mapper.StandardMethodMapper;
import com.ruoyi.basic.pojo.StandardMethod;
import com.ruoyi.process.mapper.ProcessMethodSearchNewFileSeqMapper;
import com.ruoyi.process.mapper.ProcessMethodSearchNewMapper;
import com.ruoyi.process.pojo.ProcessMethodSearchNew;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
/** æ ¹æ®æ ‡å‡†ç»´æŠ¤ä¿å­˜åŠ¨ä½œåŒæ­¥ç”Ÿæˆã€å½’æ¡£æ ‡å‡†æŸ¥æ–°è®°å½•ã€‚ */
@Component
@RequiredArgsConstructor
public class StandardMethodSearchNewListener {
    private static final ZoneId CHINA_ZONE = ZoneId.of("Asia/Shanghai");
    private static final DateTimeFormatter FILE_DATE = DateTimeFormatter.BASIC_ISO_DATE;
    private final StandardMethodMapper standardMethodMapper;
    private final ProcessMethodSearchNewMapper searchNewMapper;
    private final ProcessMethodSearchNewFileSeqMapper fileSeqMapper;
    @EventListener
    public void onStandardMethodSaved(StandardMethodSavedEvent event) {
        if (!Integer.valueOf(1).equals(event.getNeedSearchNew())) {
            return;
        }
        StandardMethod standard = standardMethodMapper.selectOne(Wrappers.<StandardMethod>lambdaQuery()
                .eq(StandardMethod::getId, event.getStandardMethodId())
                .last("FOR UPDATE"));
        if (standard == null) {
            return;
        }
        ProcessMethodSearchNew current = searchNewMapper.selectOne(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
                .eq(ProcessMethodSearchNew::getCurrentAutoStandardId, event.getStandardMethodId())
                .last("FOR UPDATE"));
        if (!event.isEdit() && current != null) {
            return;
        }
        LocalDateTime now = LocalDateTime.now(CHINA_ZONE);
        if (current != null) {
            searchNewMapper.update(null, Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                    .eq(ProcessMethodSearchNew::getMethodSearchNewId, current.getMethodSearchNewId())
                    .set(ProcessMethodSearchNew::getIsNewStandard, 0)
                    .set(ProcessMethodSearchNew::getIsAutoArchived, 1)
                    .set(ProcessMethodSearchNew::getCurrentAutoStandardId, null)
                    .set(ProcessMethodSearchNew::getAutoArchivedTime, now));
        }
        ProcessMethodSearchNew created = new ProcessMethodSearchNew();
        created.setMethodName(event.getName());
        created.setStandardNo(event.getCode());
        created.setFileNo(nextFileNo(now.toLocalDate()));
        created.setIsNewStandard(1);
        created.setSearchNewSource(null);
        created.setStandardMethodId(event.getStandardMethodId());
        created.setCurrentAutoStandardId(event.getStandardMethodId());
        created.setIsAutoArchived(0);
        searchNewMapper.insert(created);
    }
    private String nextFileNo(LocalDate date) {
        String prefix = date.format(FILE_DATE);
        fileSeqMapper.insertIfAbsent(date);
        Integer stored = fileSeqMapper.selectForUpdate(date);
        Integer existing = fileSeqMapper.selectMaxExisting(prefix);
        int next = Math.max(stored == null ? 0 : stored, existing == null ? 0 : existing) + 1;
        fileSeqMapper.updateValue(date, next);
        return prefix + String.format("%03d", next);
    }
}
cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewFileSeqMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.process.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDate;
@Mapper
public interface ProcessMethodSearchNewFileSeqMapper {
    int insertIfAbsent(@Param("seqDate") LocalDate seqDate);
    Integer selectForUpdate(@Param("seqDate") LocalDate seqDate);
    Integer selectMaxExisting(@Param("prefix") String prefix);
    int updateValue(@Param("seqDate") LocalDate seqDate, @Param("value") Integer value);
}
cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java
@@ -28,5 +28,8 @@
     */
    IPage<ProcessMethodSearchNew> pageMethodSearchNew(@Param("page") Page page, @Param("ew") QueryWrapper<ProcessMethodSearchNewBackupsDto> processMethodSearchNewDtoQueryWrapper, @Param("beginDate") String beginDate, @Param("endDate") String endDate);
    IPage<ProcessMethodSearchNew> pageAutoArchived(@Param("page") Page page,
                                                    @Param("ew") QueryWrapper<ProcessMethodSearchNew> queryWrapper);
}
cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java
@@ -19,6 +19,7 @@
public class ProcessMethodSearchNew {
    @TableId(type = IdType.AUTO)
    @Schema(description = "标准查新记录ID")
    private Integer methodSearchNewId;
    @Schema(description = "标准方法验证id")
@@ -48,6 +49,19 @@
    @Schema(description = "备注,0作废, 1替换")
    private Integer remark;
    @Schema(description = "来源标准维护ID,自动生成记录使用")
    private Integer standardMethodId;
    @Schema(description = "当前自动记录对应的标准维护ID;归档后为空")
    private Integer currentAutoStandardId;
    @Schema(description = "是否自动归档(0否,1是)")
    private Integer isAutoArchived;
    @Schema(description = "自动归档时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime autoArchivedTime;
    @Schema(description = "创建人")
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java
@@ -28,6 +28,8 @@
     */
    boolean addMethodSearchNew(List<ProcessMethodSearchNew> processMethodSearchNewList);
    boolean updateMethodSearchNew(ProcessMethodSearchNew processMethodSearchNew);
    /**
     * æ ‡å‡†æŸ¥æ–°åˆ—表
     * @param processMethodSearchNew
@@ -35,6 +37,8 @@
     */
    IPage<ProcessMethodSearchNew> pageMethodSearchNew(Page page, ProcessMethodSearchNewBackupsDto processMethodSearchNew);
    IPage<ProcessMethodSearchNew> pageAutoArchived(Page page, ProcessMethodSearchNew processMethodSearchNew);
    /**
     * æ ‡å‡†æŸ¥æ–°å¯¼å‡º
     * @param archivedId
cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java
@@ -73,10 +73,36 @@
    public boolean addMethodSearchNew(List<ProcessMethodSearchNew> processMethodSearchNewList) {
        for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNewList) {
            processMethodSearchNew.setIsNewStandard(1);
            processMethodSearchNew.setIsAutoArchived(0);
            processMethodSearchNew.setStandardMethodId(null);
            processMethodSearchNew.setCurrentAutoStandardId(null);
            processMethodSearchNew.setAutoArchivedTime(null);
        }
        // æ–°å¢ž
        this.saveBatch(processMethodSearchNewList);
        return true;
    }
    @Override
    public boolean updateMethodSearchNew(ProcessMethodSearchNew processMethodSearchNew) {
        ProcessMethodSearchNew old = getById(processMethodSearchNew.getMethodSearchNewId());
        if (old == null) {
            throw new ErrorException("标准查新记录不存在");
        }
        if (Integer.valueOf(1).equals(old.getIsAutoArchived())) {
            throw new ErrorException("自动归档记录不允许修改");
        }
        return update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                .eq(ProcessMethodSearchNew::getMethodSearchNewId, old.getMethodSearchNewId())
                .set(ProcessMethodSearchNew::getVerifyId, processMethodSearchNew.getVerifyId())
                .set(ProcessMethodSearchNew::getMethodName, processMethodSearchNew.getMethodName())
                .set(ProcessMethodSearchNew::getStandardNo, processMethodSearchNew.getStandardNo())
                .set(ProcessMethodSearchNew::getFileNo, processMethodSearchNew.getFileNo())
                .set(ProcessMethodSearchNew::getNewMethodName, processMethodSearchNew.getNewMethodName())
                .set(ProcessMethodSearchNew::getNewStandardNo, processMethodSearchNew.getNewStandardNo())
                .set(ProcessMethodSearchNew::getSearchNewSource, processMethodSearchNew.getSearchNewSource())
                .set(ProcessMethodSearchNew::getRemark, processMethodSearchNew.getRemark())
                .set(ProcessMethodSearchNew::getIsNewStandard, 1));
    }
    /**
@@ -92,6 +118,12 @@
        processMethodSearchNew.setBeginDate(null);
        processMethodSearchNew.setEndDate(null);
        return baseMapper.pageMethodSearchNew(page, QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate);
    }
    @Override
    public IPage<ProcessMethodSearchNew> pageAutoArchived(Page page, ProcessMethodSearchNew processMethodSearchNew) {
        processMethodSearchNew.setIsAutoArchived(null);
        return baseMapper.pageAutoArchived(page, QueryWrappers.queryWrappers(processMethodSearchNew));
    }
    /**
@@ -136,7 +168,7 @@
                    searchNewBackupsDto.setRemarkString("作废");
                }
            }
            switch (methodSearchNew.getSearchNewSource()) {
            if (methodSearchNew.getSearchNewSource() != null) switch (methodSearchNew.getSearchNewSource()) {
                case 0:
                    searchNewBackupsDto.setStandardNet("√");
                    break;
@@ -257,20 +289,14 @@
            List<ProcessMethodSearchNew> collect = searchNewDtoList.stream().map(searchNewDto -> {
                ProcessMethodSearchNew searchNew = new ProcessMethodSearchNew();
                BeanUtils.copyProperties(searchNewDto, searchNew);
                // æ˜¯å¦æ˜¯æ›´æ–°
                if (StringUtils.isNotBlank(searchNewDto.getIsNewStandardString())) {
                    if (searchNewDto.getIsNewStandardString().equals("是")) {
                        searchNew.setIsNewStandard(1);
                    } else {
                        searchNew.setIsNewStandard(0);
                    }
                }
                searchNew.setIsNewStandard(1);
                searchNew.setIsAutoArchived(0);
                // æŸ¥æ–°è®°å½•
                if (StringUtils.isNotBlank(searchNewDto.getStandardNet())) {
                    searchNew.setSearchNewSource(0);
                } else if (StringUtils.isNotBlank(searchNewDto.getInformationOffices())) {
                    searchNew.setSearchNewSource(1);
                } else if (StringUtils.isNotBlank(searchNewDto.getIsNewStandardString())) {
                } else if (StringUtils.isNotBlank(searchNewDto.getStandardBookstore())) {
                    searchNew.setSearchNewSource(2);
                } else if (StringUtils.isNotBlank(searchNewDto.getOther())) {
                    searchNew.setSearchNewSource(3);
@@ -309,12 +335,14 @@
        processMethodSearchNewArchivedMapper.insert(archived);
        // æŸ¥è¯¢æ‰€æœ‰çš„æ ‡å‡†æŸ¥æ–°
        List<ProcessMethodSearchNew> searchNewList = this.list();
        List<ProcessMethodSearchNew> searchNewList = this.list(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
                .eq(ProcessMethodSearchNew::getIsAutoArchived, 0));
        // æ–°å¢žå¤åˆ¶
        List<ProcessMethodSearchNewBackups> methodSearchNewBackups = searchNewList.stream().map(processMethodSearchNew -> {
            ProcessMethodSearchNewBackups backups = new ProcessMethodSearchNewBackups();
            BeanUtils.copyProperties(processMethodSearchNew, backups);
            backups.setIsNewStandard(0);
            backups.setArchivedId(archived.getArchivedId());
            return backups;
        }).collect(Collectors.toList());
cnas-process/src/main/resources/mapper/ProcessMethodSearchNewFileSeqMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.process.mapper.ProcessMethodSearchNewFileSeqMapper">
    <insert id="insertIfAbsent">
        INSERT IGNORE INTO cnas_process_method_search_new_file_seq
            (seq_date, sequence_value)
        VALUES
            (#{seqDate}, 0)
    </insert>
    <select id="selectForUpdate" resultType="java.lang.Integer">
        SELECT sequence_value
        FROM cnas_process_method_search_new_file_seq
        WHERE seq_date = #{seqDate}
        FOR UPDATE
    </select>
    <select id="selectMaxExisting" resultType="java.lang.Integer">
        SELECT COALESCE(MAX(seq_value), 0)
        FROM (
            SELECT CAST(SUBSTRING(file_no, 9) AS UNSIGNED) AS seq_value
            FROM cnas_process_method_search_new
            WHERE file_no REGEXP CONCAT('^', #{prefix}, '[0-9]+$')
            UNION ALL
            SELECT CAST(SUBSTRING(file_no, 9) AS UNSIGNED) AS seq_value
            FROM cnas_process_method_search_new_backups
            WHERE file_no REGEXP CONCAT('^', #{prefix}, '[0-9]+$')
        ) numbers
    </select>
    <update id="updateValue">
        UPDATE cnas_process_method_search_new_file_seq
        SET sequence_value = #{value}
        WHERE seq_date = #{seqDate}
    </update>
</mapper>
cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml
@@ -8,6 +8,7 @@
        from (select *
        from cnas_process_method_search_new
        <where>
            and is_auto_archived = 0
            <if test="beginDate != null and beginDate != '' and endDate != null and endDate != ''">
                and create_time between #{beginDate} and #{endDate}
            </if>
@@ -18,4 +19,16 @@
            ${ew.customSqlSegment}
        </if>
    </select>
    <select id="pageAutoArchived" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNew">
        select *
        from (
            select * from cnas_process_method_search_new
            where is_auto_archived = 1
            order by auto_archived_time desc, method_search_new_id desc
        ) a
        <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
            ${ew.customSqlSegment}
        </if>
    </select>
</mapper>
cnas-require/src/main/java/com/ruoyi/require/controller/FeStandardSubstanceAcceptanceController.java
@@ -4,9 +4,11 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.require.dto.AcceptanceDto;
import com.ruoyi.require.pojo.FeStandardSubstance;
import com.ruoyi.require.pojo.FeStandardSubstanceAcceptanceInspection;
import com.ruoyi.require.service.FeStandardSubstanceAcceptanceInspectionService;
import com.ruoyi.require.service.FeStandardSubstanceAcceptanceService;
import com.ruoyi.require.service.FeStandardSubstanceService;
import com.ruoyi.require.vo.AcceptanceVo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
@@ -34,6 +36,8 @@
    private FeStandardSubstanceAcceptanceInspectionService inspectionService;
    @Resource
    private FeStandardSubstanceAcceptanceService feStandardSubstanceAcceptanceService;
    @Resource
    private FeStandardSubstanceService feStandardSubstanceService;
    @Operation(summary = "新增")
    @PostMapping("/addAcceptance")
@@ -58,7 +62,20 @@
    @Operation(summary = "编辑")
    @PostMapping("/updateAcceptance")
    @Transactional
    public Result updateAcceptance(@RequestBody AcceptanceDto acceptanceDto) {
        FeStandardSubstance substance = acceptanceDto.getSubstance();
        if (substance != null) {
            if (substance.getId() == null) {
                substance.setState(0);
                feStandardSubstanceService.save(substance);
            } else {
                // é¢†ç”¨çŠ¶æ€ç”±é¢†ç”¨/归还操作维护,编辑验收单时不回写
                substance.setState(null);
                feStandardSubstanceService.updateById(substance);
            }
            acceptanceDto.getAcceptance().setSubstanceId(substance.getId());
        }
        feStandardSubstanceAcceptanceService.updateById(acceptanceDto.getAcceptance());
        for (FeStandardSubstanceAcceptanceInspection v : acceptanceDto.getList()) {
            if (v.getId()== null) {
cnas-require/src/main/java/com/ruoyi/require/controller/FeStandardSubstanceRecordController.java
@@ -37,12 +37,10 @@
        return Result.success();
    }
    @Operation(summary = "标准物质清单归还")
    @PostMapping("/returnSubstance")
    @Transactional
    public Result returnSubstance(@RequestBody FeStandardSubstanceRecord record) {
        feStandardSubstanceRecordService.returnSubstance(record);
        return Result.success();
    @Operation(summary = "查询标准物质剩余可领用数量")
    @GetMapping("/getRemainingQuantity/{substanceId}")
    public Result<Long> getRemainingQuantity(@PathVariable("substanceId") Integer substanceId) {
        return Result.success(feStandardSubstanceRecordService.getRemainingQuantity(substanceId));
    }
    @Operation(summary = "标准物质清单领用查询")
cnas-require/src/main/java/com/ruoyi/require/controller/SupplierManagementController.java
@@ -12,6 +12,7 @@
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@@ -88,4 +89,23 @@
        return Result.success(supplierManagementService.selectSupplierManagementAll());
    }
    @Operation(summary = "查询供应商附件")
    @GetMapping("/selectAttachments")
    public Result selectAttachments(Integer supplierManagementId) {
        return Result.success(supplierManagementService.selectAttachments(supplierManagementId));
    }
    @Operation(summary = "上传供应商附件")
    @PostMapping("/uploadAttachment")
    public Result uploadAttachment(@RequestParam("supplierManagementId") Integer supplierManagementId,
                                   @RequestParam("file") MultipartFile file) {
        return Result.success(supplierManagementService.uploadAttachment(supplierManagementId, file));
    }
    @Operation(summary = "删除供应商附件")
    @DeleteMapping("/deleteAttachment")
    public Result deleteAttachment(Long id) {
        return Result.success(supplierManagementService.deleteAttachment(id));
    }
}
cnas-require/src/main/java/com/ruoyi/require/dto/AcceptanceDto.java
@@ -1,5 +1,6 @@
package com.ruoyi.require.dto;
import com.ruoyi.require.pojo.FeStandardSubstance;
import com.ruoyi.require.pojo.FeStandardSubstanceAcceptance;
import com.ruoyi.require.pojo.FeStandardSubstanceAcceptanceInspection;
import lombok.Data;
@@ -11,5 +12,7 @@
    private FeStandardSubstanceAcceptance acceptance;
    private FeStandardSubstance substance;
    private List<FeStandardSubstanceAcceptanceInspection> list;
}
cnas-require/src/main/java/com/ruoyi/require/excel/FeStandardSubstanceExcel.java
@@ -16,7 +16,7 @@
    @ExcelProperty("生产厂家")
    private String factoryManufacturer;
    @ExcelProperty("出场编号")
    @ExcelProperty("出厂编号")
    private String factoryNum;
    @ExcelProperty("管理编号")
@@ -34,7 +34,7 @@
    @ExcelProperty("有效期")
    private LocalDateTime effectiveDate;
    @ExcelProperty("文档编号")
    @ExcelProperty("档案编号")
    private String fileNum;
    @ExcelProperty("存放位置")
cnas-require/src/main/java/com/ruoyi/require/excel/FeStandardSubstanceImport.java
@@ -14,7 +14,7 @@
    @ExcelProperty("规格型号*")
    private String model;
    @ExcelProperty("生产厂家*")
    @ExcelProperty("生产厂家")
    private String factoryManufacturer;
    @ExcelProperty("出厂编号*")
@@ -29,6 +29,9 @@
    @ExcelProperty("数量*")
    private String quantity;
    @ExcelProperty("单位")
    private String unit;
    @ExcelProperty("购置日期*(yyyy-MM-dd)")
    private String acquisitionDate;
cnas-require/src/main/java/com/ruoyi/require/mapper/SupplierManagementAttachmentMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.ruoyi.require.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.require.pojo.SupplierManagementAttachment;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SupplierManagementAttachmentMapper extends BaseMapper<SupplierManagementAttachment> {
}
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstance.java
@@ -1,6 +1,7 @@
package com.ruoyi.require.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -36,7 +37,10 @@
    @Schema(description = "生产厂家")
    private String factoryManufacturer;
    @Schema(description = "出场编号")
    @Schema(description = "供应商")
    private String supplier;
    @Schema(description = "出厂编号")
    private String factoryNum;
    @Schema(description = "管理编号")
@@ -48,13 +52,18 @@
    @Schema(description = "数量")
    private Long quantity;
    @Schema(description = "单位")
    private String unit;
    @Schema(description = "购置日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime acquisitionDate;
    @Schema(description = "有效期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime effectiveDate;
    @Schema(description = "文档编号")
    @Schema(description = "档案编号")
    private String fileNum;
    @Schema(description = "存放位置")
@@ -70,11 +79,13 @@
    private String createUser;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstanceAcceptance.java
@@ -3,6 +3,7 @@
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -78,6 +79,7 @@
    @ExcelIgnore
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ExcelIgnore
@@ -86,5 +88,6 @@
    @ExcelIgnore
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
cnas-require/src/main/java/com/ruoyi/require/pojo/FeStandardSubstanceRecord.java
@@ -1,6 +1,7 @@
package com.ruoyi.require.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -30,6 +31,15 @@
    @Schema(description = "物质id")
    private Integer substanceId;
    @Schema(description = "本次领用数量")
    private Long borrowQuantity;
    @Schema(description = "原始数量(领用时快照)")
    private Long originalQuantity;
    @Schema(description = "领用后剩余数量")
    private Long remainingQuantity;
    @Schema(description = "借用-完好性")
    private String integrity;
@@ -40,9 +50,11 @@
    private String phone;
    @Schema(description = "借用-借出日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime borrowDate;
    @Schema(description = "归还日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime borrowReturnDate;
    @Schema(description = "借出人")
@@ -58,6 +70,7 @@
    private String returnedPerson;
    @Schema(description = "归还-日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime returnDate;
    @Schema(description = "归还-完好性")
@@ -67,11 +80,13 @@
    private String createUser;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
cnas-require/src/main/java/com/ruoyi/require/pojo/SupplierManagementAttachment.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.require.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("cnas_supplier_management_attachment")
public class SupplierManagementAttachment {
    @TableId(type = IdType.AUTO)
    private Long id;
    private Integer supplierManagementId;
    private String fileName;
    private String fileUrl;
    private Integer sort;
    @TableField(fill = FieldFill.INSERT)
    private Integer createUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
}
cnas-require/src/main/java/com/ruoyi/require/service/FeStandardSubstanceRecordService.java
@@ -21,10 +21,10 @@
    void borrowSubstance(FeStandardSubstanceRecord feStandardSubstanceRecord);
    void returnSubstance(FeStandardSubstanceRecord feStandardSubstanceRecord);
    List<FeStandardSubstanceRecord> getSubstanceRecord(Integer id);
    IPage<SubstanceRecordVo> getPage(Page page, SubstanceRecordVo vo);
    Long getRemainingQuantity(Integer substanceId);
}
cnas-require/src/main/java/com/ruoyi/require/service/SupplierManagementService.java
@@ -4,6 +4,8 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.require.pojo.SupplierManagement;
import com.ruoyi.require.pojo.SupplierManagementAttachment;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@@ -29,4 +31,10 @@
    List<SupplierManagement> selectSupplierManagementByParentId(Integer parentId);
    List<SupplierManagement> selectSupplierManagementAll();
    List<SupplierManagementAttachment> selectAttachments(Integer supplierManagementId);
    SupplierManagementAttachment uploadAttachment(Integer supplierManagementId, MultipartFile file);
    boolean deleteAttachment(Long id);
}
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceAcceptanceServiceImpl.java
@@ -53,6 +53,14 @@
    @Override
    public void addAcceptance(AcceptanceDto dto) {
        FeStandardSubstanceAcceptance acceptance = dto.getAcceptance();
        FeStandardSubstance substance = dto.getSubstance();
        if (substance != null) {
            if (substance.getId() == null) {
                substance.setState(0);
                feStandardSubstanceMapper.insert(substance);
            }
            acceptance.setSubstanceId(substance.getId());
        }
        this.baseMapper.insert(acceptance);
        List<FeStandardSubstanceAcceptanceInspection> list = dto.getList();
        if (CollectionUtils.isNotEmpty(list)) {
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceRecordServiceImpl.java
@@ -36,31 +36,51 @@
    @Override
    public void borrowSubstance(FeStandardSubstanceRecord feStandardSubstanceRecord) {
        FeStandardSubstance standardSubstance = feStandardSubstanceMapper.selectOne(Wrappers.<FeStandardSubstance>lambdaQuery()
                .eq(FeStandardSubstance::getId, feStandardSubstanceRecord.getSubstanceId())
                .eq(FeStandardSubstance::getState, 0)
                .last("limit 1"));
        if (ObjectUtils.isEmpty(standardSubstance)){
            throw new ErrorException("该物质已被借出!");
        Long borrowQuantity = feStandardSubstanceRecord.getBorrowQuantity();
        if (borrowQuantity == null || borrowQuantity <= 0) {
            throw new ErrorException("请填写正确的领用数量!");
        }
        FeStandardSubstance standardSubstance = feStandardSubstanceMapper.selectById(feStandardSubstanceRecord.getSubstanceId());
        if (ObjectUtils.isEmpty(standardSubstance)){
            throw new ErrorException("该标准物质不存在!");
        }
        long remaining = calcRemaining(standardSubstance);
        if (remaining <= 0) {
            throw new ErrorException("该标准物质已全部领用,剩余数量为0!");
        }
        if (borrowQuantity > remaining) {
            throw new ErrorException("领用数量不能超过剩余数量(当前剩余" + remaining + ")!");
        }
        long remainingAfter = remaining - borrowQuantity;
        feStandardSubstanceRecord.setRemainingQuantity(remainingAfter);
        // è®°å½•领用当时的原始数量快照,之后清单里再改数量不影响历史领用记录
        feStandardSubstanceRecord.setOriginalQuantity(standardSubstance.getQuantity());
        this.baseMapper.insert(feStandardSubstanceRecord);
        standardSubstance.setState(1);
        standardSubstance.setState(remainingAfter == 0 ? 1 : 0);
        feStandardSubstanceMapper.updateById(standardSubstance);
    }
    @Override
    public void returnSubstance(FeStandardSubstanceRecord feStandardSubstanceRecord) {
        FeStandardSubstance standardSubstance = feStandardSubstanceMapper.selectOne(Wrappers.<FeStandardSubstance>lambdaQuery()
                .eq(FeStandardSubstance::getId, feStandardSubstanceRecord.getSubstanceId())
                .eq(FeStandardSubstance::getState, 1));
        if (ObjectUtils.isEmpty(standardSubstance)){
            throw new ErrorException("该物质未被领用,无需归还!");
    public Long getRemainingQuantity(Integer substanceId) {
        FeStandardSubstance standardSubstance = feStandardSubstanceMapper.selectById(substanceId);
        if (ObjectUtils.isEmpty(standardSubstance)) {
            return 0L;
        }
        standardSubstance.setState(0);
        feStandardSubstanceMapper.updateById(standardSubstance);
        baseMapper.update(feStandardSubstanceRecord, Wrappers.<FeStandardSubstanceRecord>lambdaUpdate()
                .eq(FeStandardSubstanceRecord::getSubstanceId, feStandardSubstanceRecord.getSubstanceId())
                .eq(FeStandardSubstanceRecord::getStatus, 0));
        return Math.max(calcRemaining(standardSubstance), 0L);
    }
    private long calcRemaining(FeStandardSubstance substance) {
        long total = substance.getQuantity() == null ? 0L : substance.getQuantity();
        long borrowed = 0L;
        List<FeStandardSubstanceRecord> records = this.baseMapper.selectList(Wrappers.<FeStandardSubstanceRecord>lambdaQuery()
                .eq(FeStandardSubstanceRecord::getSubstanceId, substance.getId()));
        for (FeStandardSubstanceRecord record : records) {
            if ("1".equals(record.getStatus())) { // åŽ†å²å½’è¿˜è®°å½•ä¸è®¡å…¥å·²é¢†ç”¨
                continue;
            }
            borrowed += record.getBorrowQuantity() == null ? total : record.getBorrowQuantity();
        }
        return total - borrowed;
    }
    @Override
cnas-require/src/main/java/com/ruoyi/require/service/impl/FeStandardSubstanceServiceImpl.java
@@ -90,11 +90,12 @@
            FeStandardSubstance substance = new FeStandardSubstance();
            substance.setName(required(row.getName(), rowNumber, "标准物质名称"));
            substance.setModel(required(row.getModel(), rowNumber, "规格型号"));
            substance.setFactoryManufacturer(required(row.getFactoryManufacturer(), rowNumber, "生产厂家"));
            substance.setFactoryManufacturer(trim(row.getFactoryManufacturer()));
            substance.setFactoryNum(required(row.getFactoryNum(), rowNumber, "出厂编号"));
            substance.setManageNum(manageNum);
            substance.setUncertainty(required(row.getUncertainty(), rowNumber, "不确定度"));
            substance.setQuantity(parseQuantity(row.getQuantity(), rowNumber));
            substance.setUnit(trim(row.getUnit()));
            substance.setAcquisitionDate(parseDate(row.getAcquisitionDate(), rowNumber, "购置日期"));
            substance.setEffectiveDate(parseDate(row.getEffectiveDate(), rowNumber, "有效期"));
            substance.setFileNum(required(row.getFileNum(), rowNumber, "档案编号"));
cnas-require/src/main/java/com/ruoyi/require/service/impl/SupplierManagementServiceImpl.java
@@ -8,18 +8,26 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.require.dto.SupplierManagementDto;
import com.ruoyi.require.mapper.SupplierManagementAttachmentMapper;
import com.ruoyi.require.mapper.SupplierManagementMapper;
import com.ruoyi.require.pojo.SupplierManagement;
import com.ruoyi.require.pojo.SupplierManagementAttachment;
import com.ruoyi.require.service.SupplierManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
@@ -35,6 +43,15 @@
    @Autowired
    private SupplierManagementMapper supplierManagementMapper;
    @Autowired
    private SupplierManagementAttachmentMapper supplierManagementAttachmentMapper;
    @Value("${file.path}")
    private String filePath;
    @Value("${wordUrl}")
    private String wordUrl;
    public SupplierManagementServiceImpl(SupplierManagementMapper supplierManagementMapper) {
        this.supplierManagementMapper = supplierManagementMapper;
@@ -88,4 +105,55 @@
    public List<SupplierManagement> selectSupplierManagementAll() {
        return supplierManagementMapper.selectList(null);
    }
    @Override
    public List<SupplierManagementAttachment> selectAttachments(Integer supplierManagementId) {
        return supplierManagementAttachmentMapper.selectList(new QueryWrapper<SupplierManagementAttachment>().lambda()
                .eq(SupplierManagementAttachment::getSupplierManagementId, supplierManagementId)
                .orderByAsc(SupplierManagementAttachment::getSort, SupplierManagementAttachment::getId));
    }
    @Override
    public SupplierManagementAttachment uploadAttachment(Integer supplierManagementId, MultipartFile file) {
        if (supplierManagementMapper.selectById(supplierManagementId) == null) {
            throw new BaseException("供应商不存在");
        }
        if (file == null || file.isEmpty()) {
            throw new BaseException("附件不能为空");
        }
        // ç³»ç»Ÿå…¨å±€ä¸Šä¼ ä¸Šé™ä¸º200MB,这里提前给出友好提示
        if (file.getSize() > 200L * 1024 * 1024) {
            throw new BaseException("附件不能超过200MB");
        }
        String originalName = file.getOriginalFilename();
        if (originalName == null || originalName.trim().isEmpty()) {
            originalName = "未命名文件";
        }
        // ä¸ªåˆ«æµè§ˆå™¨å¯èƒ½å¸¦ä¸Šè·¯å¾„前缀,只保留文件名本身
        originalName = originalName.replaceAll(".*[/\\\\]", "");
        try {
            // å›¾ç‰‡æ”¾å›¾ç‰‡ç›®å½•(/img é™æ€è·¯å¾„),其余任意格式放 word ç›®å½•(/word é™æ€è·¯å¾„)
            boolean image = originalName.matches("(?i).+\\.(jpg|jpeg|png|gif)$");
            File directory = new File(image ? filePath : wordUrl);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            String fileUrl = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmssSSS")) + "-" + originalName;
            file.transferTo(new File(directory, fileUrl));
            SupplierManagementAttachment attachment = new SupplierManagementAttachment();
            attachment.setSupplierManagementId(supplierManagementId);
            attachment.setFileName(originalName);
            attachment.setFileUrl(fileUrl);
            attachment.setSort(selectAttachments(supplierManagementId).size());
            supplierManagementAttachmentMapper.insert(attachment);
            return attachment;
        } catch (IOException e) {
            throw new BaseException("附件上传失败");
        }
    }
    @Override
    public boolean deleteAttachment(Long id) {
        return supplierManagementAttachmentMapper.deleteById(id) > 0;
    }
}
cnas-require/src/main/java/com/ruoyi/require/vo/AcceptanceVo.java
@@ -1,5 +1,6 @@
package com.ruoyi.require.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -20,7 +21,7 @@
    @Schema(description = "生产厂家")
    private String factoryManufacturer;
    @Schema(description = "出场编号")
    @Schema(description = "出厂编号")
    private String factoryNum;
    @Schema(description = "管理编号")
@@ -32,15 +33,24 @@
    @Schema(description = "数量")
    private Long quantity;
    @Schema(description = "单位")
    private String unit;
    @Schema(description = "购置日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime acquisitionDate;
    @Schema(description = "有效期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime effectiveDate;
    @Schema(description = "文档编号")
    @Schema(description = "档案编号")
    private String fileNum;
    @Schema(description = "存放位置")
    private String position;
    @Schema(description = "提交时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
}
cnas-require/src/main/java/com/ruoyi/require/vo/SubstanceRecordVo.java
@@ -1,5 +1,6 @@
package com.ruoyi.require.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -17,29 +18,27 @@
    @Schema(description = "规格型号")
    private String model;
    @Schema(description = "出场编号")
    @Schema(description = "出厂编号")
    private String factoryNum;
    @Schema(description = "数量")
    private Long quantity;
    @Schema(description = "单位")
    private String unit;
    @Schema(description = "本次领用数量")
    private Long borrowQuantity;
    @Schema(description = "领用后剩余数量")
    private Long remainingQuantity;
    @Schema(description = "领用人")
    private String borrowUser;
    @Schema(description = "借出日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime borrowDate;
    @Schema(description = "归还日期")
    private LocalDateTime returnDate;
    @Schema(description = "归还人")
    private String returnedPerson;
    @Schema(description = "完好性")
    private String returnIntegrity;
    @Schema(description = "0:借用 1:归还")
    private String status;
    @Schema(description = "备注")
    private String remark;
cnas-require/src/main/resources/mapper/FeStandardSubstanceAcceptanceMapper.xml
@@ -30,10 +30,12 @@
            ss.manage_num,
            ss.uncertainty,
            ss.quantity,
            ss.unit,
            ss.acquisition_date,
            ss.effective_date,
            ss.file_num,
            ss.position
            ss.position,
            sa.create_time
        FROM cnas_fe_standard_substance_acceptance sa
                 LEFT JOIN cnas_fe_standard_substance ss on ss.id = sa.substance_id
        <where>
cnas-require/src/main/resources/mapper/FeStandardSubstanceRecordMapper.xml
@@ -25,13 +25,13 @@
        ss.name,
        ss.model,
        ss.factory_num,
        ss.quantity,
        COALESCE(ssr.original_quantity, ss.quantity) AS quantity,
        ss.unit,
        COALESCE(ssr.borrow_quantity, ss.quantity) AS borrowQuantity,
        COALESCE(ssr.remaining_quantity, 0) AS remainingQuantity,
        ssr.borrow_user,
        ssr.borrow_date,
        ssr.return_date,
        ssr.integrity,
        ssr.return_integrity,
        ssr.returned_person,
        ss.remark
        FROM cnas_fe_standard_substance_record ssr
        LEFT JOIN cnas_fe_standard_substance ss on ss.id = ssr.substance_id
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderController.java
@@ -1,5 +1,6 @@
package com.ruoyi.inspect.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.dto.InventoryDetailDTO;
@@ -287,4 +288,16 @@
        return insOrderService.judgeNotSpotCheckOrder(insPlaceOrderDto.getSampleList(), insPlaceOrderDto.getInsOrder());
    }
    @Operation(summary = "查询已完成委托单(客户满意度下拉用, ä»…已检验state=4)")
    @GetMapping("/selectCompletedOrders")
    public Result selectCompletedOrders() {
        LambdaQueryWrapper<InsOrder> qw = new LambdaQueryWrapper<>();
        qw.select(InsOrder::getId, InsOrder::getEntrustCode, InsOrder::getCompany,
                        InsOrder::getCompanyId, InsOrder::getSampleView)
                .eq(InsOrder::getState, 4)
                .isNotNull(InsOrder::getCompany)
                .orderByDesc(InsOrder::getCreateTime);
        return Result.success(insOrderService.page(new Page<>(1, 500), qw).getRecords());
    }
}
ruoyi-admin/src/main/resources/application-druid.yml
@@ -6,7 +6,7 @@
        druid:
            # ä¸»åº“数据源
            master:
                url: jdbc:mysql://192.168.0.24:3307/lims-xjxj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                url: jdbc:mysql://127.0.0.1:3307/lims-xjxj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: 123456
            # ä»Žåº“数据源
@@ -60,6 +60,56 @@
                    config:
                        multi-statement-allow: true
    # Redis è¿žæŽ¥é…ç½®
    data:
        redis:
            host: 127.0.0.1
            port: 6379
            database: 0
            password:
            timeout: 10s
            lettuce:
              pool:
                # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
                min-idle: 0
                # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
                max-idle: 8
                # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
                max-active: 8
                # #连接池最大阻塞等待时间(使用负值表示没有限制)
                max-wait: -1ms
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  name: RuoYi
  version: 3.9.2
  copyrightYear: 2026
  profile: D:/ruoyi/uploadPath
  addressEnabled: false
# ç”¨æˆ·å¯†ç é…ç½®
user:
  password:
    maxRetryCount: 5
    lockTime: 10
# ä»¤ç‰Œé…ç½®
token:
  header: Authorization
  secret: awertgbadrtawetfgfbsdfawerghbfdsftreagd
  expireTime: 450
# é˜²ç›—链配置
referer:
  enabled: false
  allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
# XSS è¿‡æ»¤é…ç½®
xss:
  enabled: true
  excludes: /system/notice
  urlPatterns: /system/*,/monitor/*,/tool/*
# ç…§ç‰‡å­˜å‚¨è·¯å¾„+++++++++++++++++++++++++++运维需要配置+++++++++++++++++++++++++++
file:
  path: D:\项目文件存储\image
@@ -67,4 +117,4 @@
  allowed: png,jpg,jpeg,gif
# æŠ¥å‘Š word å­˜å‚¨è·¯å¾„
wordUrl: D:\项目文件存储\word
wordUrl: D:\项目文件存储\word
ruoyi-admin/src/main/resources/application-xjxj.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
# è£…备测试库配置
# æ•°æ®æºé…ç½®
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # ä¸»åº“数据源
      master:
        url: jdbc:mysql://172.17.0.1:11101/lims-xjxj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: xd@123456..
      # ä»Žåº“数据源
      slave:
        # ä»Žæ•°æ®æºå¼€å…³/默认关闭
        enabled: false
        url:
        username:
        password:
      # åˆå§‹è¿žæŽ¥æ•°
      initialSize: 5
      # æœ€å°è¿žæŽ¥æ± æ•°é‡
      minIdle: 10
      # æœ€å¤§è¿žæŽ¥æ± æ•°é‡
      maxActive: 20
      # é…ç½®èŽ·å–è¿žæŽ¥ç­‰å¾…è¶…æ—¶çš„æ—¶é—´
      maxWait: 60000
      # é…ç½®è¿žæŽ¥è¶…æ—¶æ—¶é—´
      connectTimeout: 30000
      # é…ç½®ç½‘络超时时间
      socketTimeout: 60000
      # é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      minEvictableIdleTimeMillis: 300000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å¤§ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # è®¾ç½®ç™½åå•,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # æŽ§åˆ¶å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç 
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # æ…¢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
  # redis é…ç½®
  data:
    # redis é…ç½®
    redis:
      # åœ°å€
      host: 172.17.0.1
      # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
      port: 11102
      # æ•°æ®åº“索引
      database: 6
      # å¯†ç 
      password:
      # è¿žæŽ¥è¶…æ—¶æ—¶é—´
      timeout: 10s
      lettuce:
        pool:
          # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
          min-idle: 0
          # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
          max-idle: 8
          # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
          max-active: 8
          # #连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
# mybatis-plus配置
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# æ—¥å¿—配置
logging:
  file-location: /center-lims/Java
  level:
    root: info
    com.ruoyi: debug
    org.springframework.web: debug
    org.springframework.security: info
    org.mybatis: debug
    com.baomidou.mybatisplus: debug
# Swagger配置
swagger:
  # æ˜¯å¦å¼€å¯swagger
  enabled: true
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  name: RuoYi
  version: 3.9.2
  copyrightYear: 2026
  profile: D:/ruoyi/uploadPath
  addressEnabled: false
# ç”¨æˆ·å¯†ç é…ç½®
user:
  password:
    maxRetryCount: 5
    lockTime: 10
# ä»¤ç‰Œé…ç½®
token:
  header: Authorization
  secret: awertgbadrtawetfgfbsdfawerghbfdsftreagd
  expireTime: 450
# é˜²ç›—链配置
referer:
  enabled: false
  allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
# XSS è¿‡æ»¤é…ç½®
xss:
  enabled: true
  excludes: /system/notice
  urlPatterns: /system/*,/monitor/*,/tool/*
# ç…§ç‰‡å­˜å‚¨è·¯å¾„+++++++++++++++++++++++++++运维需要配置+++++++++++++++++++++++++++
file:
  path: /center-lims/Work/img
  # ä¸Šä¼ æ–‡ä»¶å…è®¸çš„æ‰©å±•名
  allowed: png,jpg,jpeg,gif
# æŠ¥å‘Šåœ°å€
wordUrl: /center-lims/Work/word
ruoyi-admin/src/main/resources/application.yml
@@ -1,20 +1,7 @@
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  # åç§°
  name: RuoYi
  # ç‰ˆæœ¬
  version: 3.9.2
  # ç‰ˆæƒå¹´ä»½
  copyrightYear: 2026
  # æ–‡ä»¶è·¯å¾„ ç¤ºä¾‹ï¼ˆ Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # èŽ·å–ip地址开关
  addressEnabled: false
# å¼€å‘环境配置
server:
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080
  port: 8002
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080,服务器新聚后端为9509
  port: 9509
  servlet:
    # åº”用的访问路径
    context-path: /
@@ -34,14 +21,6 @@
  level:
    com.ruoyi: debug
    org.springframework: warn
# ç”¨æˆ·é…ç½®
user:
  password:
    # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•°
    maxRetryCount: 5
    # å¯†ç é”å®šæ—¶é—´ï¼ˆé»˜è®¤10分钟)
    lockTime: 10
# Spring配置
spring:
@@ -70,39 +49,6 @@
    restart:
      # çƒ­éƒ¨ç½²å¼€å…³
      enabled: true
  data:
    # redis é…ç½®
    redis:
      # åœ°å€
      host: 192.168.0.24
      # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
      port: 6379
      # æ•°æ®åº“索引
      database: 0
      # å¯†ç 
      password:
      # è¿žæŽ¥è¶…æ—¶æ—¶é—´
      timeout: 10s
      lettuce:
        pool:
          # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
          min-idle: 0
          # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
          max-idle: 8
          # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
          max-active: 8
          # #连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
# token配置
token:
  # ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
  header: Authorization
  # ä»¤ç‰Œå¯†é’¥
  secret: abcdefghijklmnopqrstuvwxyz
  # ä»¤ç‰Œæœ‰æ•ˆæœŸï¼ˆé»˜è®¤30分钟)
  expireTime: 30
# MyBatis-Plus配置
mybatis-plus:
  # æœç´¢æŒ‡å®šåŒ…别名
@@ -136,19 +82,3 @@
      display-name: '测试模块'
      paths-to-match: '/**'
      packages-to-scan: com.ruoyi
# é˜²ç›—链配置
referer:
  # é˜²ç›—链开关
  enabled: false
  # å…è®¸çš„域名列表
  allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
# é˜²æ­¢XSS攻击
xss:
  # è¿‡æ»¤å¼€å…³
  enabled: true
  # æŽ’除链接(多个用逗号分隔)
  excludes: /system/notice
  # åŒ¹é…é“¾æŽ¥
  urlPatterns: /system/*,/monitor/*,/tool/*