lxp
2025-03-12 10d6587ec3f5c4779f40bcc1afe54d441db68711
报告编制修改
已修改5个文件
已添加12个文件
1756 ■■■■■ 文件已修改
inspect-server/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsReportApproveConfigController.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsReportController.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/InsReportApproveConfigService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/InsReportService.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportApproveConfigServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java 876 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/controller/AttachmentTypeController.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/AttachmentType.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/mapper/AttachmentTableMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/pojo/AttachmentTable.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/service/AttachmentTableService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/service/impl/AttachmentTableServiceImpl.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/UserMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/pom.xml
@@ -45,6 +45,11 @@
            <groupId>com.ruoyi</groupId>
            <artifactId>performance-server</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>cnas-process</artifactId>
        </dependency>
        <!-- poi-tl包生成报告 -->
        <dependency>
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsReportApproveConfigController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.inspect.controller;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.inspect.dto.ApproveConfigDTO;
import com.ruoyi.inspect.service.InsReportApproveConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/approveConfig")
@Api(tags = "报告审批签名配置")
public class InsReportApproveConfigController {
    @Autowired
    private InsReportApproveConfigService insReportApproveConfigService;
    @ApiOperation("审批签名配置按钮")
    @GetMapping("/getApproveConfigList")
    public Result getApproveConfigList(){
        return Result.success(insReportApproveConfigService.getApproveConfigList());
    }
    @ApiOperation("查询人员")
    @GetMapping("/getUserList")
    public Result getUserList(){
        return Result.success(insReportApproveConfigService.getUserList());
    }
    @ApiOperation("更新审批签名配置")
    @PostMapping("/updateApproveConfig")
    public Result updateApproveConfig(@RequestBody ApproveConfigDTO approveConfigDTO){
        return Result.success(insReportApproveConfigService.updateApproveConfig(approveConfigDTO));
    }
}
inspect-server/src/main/java/com/ruoyi/inspect/controller/InsReportController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,217 @@
package com.ruoyi.inspect.controller;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.JackSonUtil;
import com.ruoyi.framework.exception.ErrorException;
import com.ruoyi.inspect.dto.BatchApprovalReportDTO;
import com.ruoyi.inspect.dto.ReportPageDto;
import com.ruoyi.inspect.pojo.InsReport;
import com.ruoyi.inspect.service.InsReportService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.util.Strings;
import org.apache.poi.hssf.record.SSTRecord;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Objects;
import java.util.Scanner;
@RestController
@RequestMapping("/insReport")
@Api(tags = "检验报告")
public class InsReportController {
    @Resource
    private InsReportService insReportService;
    @Value("${wordUrl}")
    private String wordUrl;
    @ApiOperation(value = "查看检验报告列表")
    @GetMapping("/pageInsReport")
    public Result pageInsReport(Page page , ReportPageDto reportPageDto) throws Exception {
        return Result.success(insReportService.pageInsReport(page, reportPageDto));
    }
    @ApiOperation(value = "一键审批按钮")
    @PostMapping("/batchApprovalReport")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result batchApprovalReport(@RequestBody BatchApprovalReportDTO batchApprovalReportDTO){
        try {
            insReportService.batchApprovalReport(batchApprovalReportDTO.getIds());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return Result.success();
    }
    @ApiOperation(value = "获取审批进度")
    @GetMapping("/getBatchApprovalProgress")
    public Result getBatchApprovalProgress(){
        return Result.success(insReportService.getBatchApprovalProgress());
    }
    @ApiOperation(value = "查看检验报告数量信息")
    @GetMapping("/getReportCountInfo")
    public Result getReportCountInfo(@RequestParam Map<String, Object> params) throws Exception {
        ReportPageDto reportPageDto = JackSonUtil.unmarshal(JackSonUtil.marshal(params), ReportPageDto.class);
        return Result.success(insReportService.getReportCountInfo(reportPageDto));
    }
    @ApiOperation(value = "上传按钮")
    @PostMapping("/inReport")
    @Log(title = "检验报告", businessType = BusinessType.IMPORT)
    public Result inReport(MultipartFile file, Integer id) {
        String urlString;
        String pathName;
        try {
            String path = wordUrl;
            File realpath = new File(path);
            if (!realpath.exists()) {
                realpath.mkdirs();
            }
            InsReport insReport = insReportService.getById(id);
            // å¦‚æžœURLS有值 å…ˆå°†è¯¥æ–‡ä»¶åˆ é™¤
            if(Strings.isNotEmpty(insReport.getUrlS())){
                String url = wordUrl + File.separator + insReport.getUrlS().replace("/word/", "");
                File file1 = new File(url);
                if(file1.exists()) {
                    file1.delete();
                }
            }
            String code = insReport.getCode().replace("/", "") + ".docx";
            pathName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss")) + "_" + code;
            urlString = realpath + "/" + pathName;
            file.transferTo(new File(urlString));
            return Result.success(insReportService.inReport("/word/" + pathName, id));
        } catch (Exception e) {
            throw new ErrorException("文件上传失败");
        }
    }
    //下载
    @GetMapping("/downReport")
    @Log(title = "检验报告", businessType = BusinessType.EXPORT)
    public void downReport(@RequestParam("id") Integer id,@RequestParam("type") Integer type,  HttpServletResponse response) {
        insReportService.downReport(id,type, response);
    }
    @ApiOperation(value = "还原按钮")
    @PostMapping("/upReportUrl")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result upReportUrl(Integer id,Integer type) {
        insReportService.upReportUrl(id,type);
        return Result.success();
    }
    @ApiOperation(value = "编制按钮")
    @GetMapping("/upReportFile")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result upReportFile() {
        return Result.success();
    }
    @ApiOperation(value = "提交按钮")
    @PostMapping("/writeReport")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result writeReport(Integer id) {
        return Result.success(insReportService.writeReport(id));
    }
    @ApiOperation(value = "审核按钮")
    @PostMapping("/examineReport")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result examineReport(Integer id, Integer isExamine, String examineTell) {
        return Result.success(insReportService.examineReport(id, isExamine, examineTell));
    }
    @ApiOperation(value = "批准按钮")
    @PostMapping("/ratifyReport")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result ratifyReport(Integer id, Integer isRatify, String ratifyTell) {
        return Result.success(insReportService.ratifyReport(id, isRatify, ratifyTell));
    }
    @RequestMapping("/onlyOffice/save")
    @Log(title = "检验报告", businessType = BusinessType.OTHER)
    public void saveFile(@RequestParam String fileName, HttpServletRequest request, HttpServletResponse response) {
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            // èŽ·å–ä¼ è¾“çš„json数据
            Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
            String body = scanner.hasNext() ? scanner.next() : "";
            JSONObject jsonObject = JSONObject.parseObject(body);
            if (jsonObject.containsKey("url")) {
                String jsonArray = jsonObject.get("lastsave").toString(); // æ›´æ–°æ—¶é—´
                String fileUrl = jsonObject.get("url").toString(); // æ›´æ–°æ–‡ä»¶url
                HttpUtil.downloadFile(fileUrl, FileUtil.file(wordUrl + "/" + fileName));
            }
        } catch (Exception e) {
            e.printStackTrace();
            writer.write("{\"error\":-1}");
            return;
        }
        /*
         * status = 1,我们给onlyOffice的服务返回{"error":"0"}的信息。
         * è¿™æ ·onlyOffice会认为回调接口是没问题的,这样就可以在线编辑文档了,否则的话会弹出窗口说明
         */
        if (Objects.nonNull(writer)) {
            writer.write("{\"error\":0}");
        }
    }
    @ApiOperation(value = "批量下载按钮")
    @GetMapping("/downAll")
    @Log(title = "检验报告", businessType = BusinessType.EXPORT)
    public Result downAll(String ids) {
        return Result.success(insReportService.downAll(ids));
    }
    @ApiOperation(value = "批量上传按钮")
    @PostMapping("/upAll")
    @Log(title = "检验报告", businessType = BusinessType.IMPORT)
    public Result upAll(MultipartFile file) throws IOException {
        return Result.success(insReportService.upAll(file));
    }
    @ApiOperation(value = "撤回按钮")
    @PostMapping("/withdraw")
    @Log(title = "检验报告", businessType = BusinessType.UPDATE)
    public Result withdraw(@RequestBody Map<String,Object> map) {
        insReportService.withdraw(map);
        return  Result.success();
    }
    @GetMapping("/getLaboratoryByReportId")
    public Result getLaboratoryByReportId(Integer id) {
        return Result.success(insReportService.getLaboratoryByReportId(id));
    }
}
inspect-server/src/main/java/com/ruoyi/inspect/service/InsReportApproveConfigService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.inspect.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.inspect.dto.ApproveConfigDTO;
import com.ruoyi.inspect.pojo.InsReportApproveConfig;
import java.util.List;
import java.util.Map;
/**
 * @author 27233
 * @description é’ˆå¯¹è¡¨ã€ins_report_approve_config(报告审批签名配置)】的数据库操作Service
 * @createDate 2024-12-10 09:36:10
 */
public interface InsReportApproveConfigService extends IService<InsReportApproveConfig> {
    List<InsReportApproveConfig> getApproveConfigList();
    InsReportApproveConfig getApproveConfigByLaboratory(String laboratory);
    Map<String, List<Map<String,Object>>> getUserList();
    boolean updateApproveConfig(ApproveConfigDTO approveConfigDTO);
}
inspect-server/src/main/java/com/ruoyi/inspect/service/InsReportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
package com.ruoyi.inspect.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.inspect.dto.ReportPageDto;
import com.ruoyi.inspect.pojo.InsReport;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
 * @author Administrator
 * @description é’ˆå¯¹è¡¨ã€ins_report(检验报告)】的数据库操作Service
 * @createDate 2024-03-17 22:10:02
 */
public interface InsReportService extends IService<InsReport> {
    IPage<ReportPageDto> pageInsReport(Page page, ReportPageDto reportPageDto);
    int inReport(String url, Integer id);
    void upReportUrl(Integer id,Integer type);
    // ä¸‹è½½
    void downReport(Integer id, Integer type , HttpServletResponse response);
    //提交
    int writeReport(Integer id);
    //审核
    int examineReport(Integer id, Integer isExamine, String examineTell);
    //批准
    int ratifyReport(Integer id, Integer isRatify, String ratifyTell);
    int wordInsertUrl(Map<String, Object> map, String url);
    String downAll(String ids);
    int upAll(MultipartFile file) throws IOException;
    void withdraw(Map<String,Object> map);
    List<Map<String,Object>> getLaboratoryByReportId(Integer id);
    Map<String,Object> getReportCountInfo(ReportPageDto reportPageDto);
    void batchApprovalReport(List<Integer> ids);
    Map<String,Object> getBatchApprovalProgress();
}
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportApproveConfigServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
package com.ruoyi.inspect.service.impl;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.inspect.dto.ApproveConfigDTO;
import com.ruoyi.inspect.mapper.InsOrderMapper;
import com.ruoyi.inspect.mapper.InsReportApproveConfigMapper;
import com.ruoyi.inspect.pojo.InsReportApproveConfig;
import com.ruoyi.inspect.service.InsReportApproveConfigService;
import com.ruoyi.system.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @author 27233
 * @description é’ˆå¯¹è¡¨ã€ins_report_approve_config(报告审批签名配置)】的数据库操作Service实现
 * @createDate 2024-12-10 09:36:10
 */
@Service
public class InsReportApproveConfigServiceImpl extends ServiceImpl<InsReportApproveConfigMapper, InsReportApproveConfig>
        implements InsReportApproveConfigService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private InsOrderMapper insOrderMapper;
    @Override
    public List<InsReportApproveConfig> getApproveConfigList() {
        Integer userId = Integer.parseInt(SecurityUtils.getUserId()+"");
        User user = userMapper.selectById(userId);//当前登录的人
        //获取当前人所属实验室id
        String departLimsId = user.getDepartLimsId();
        String laboratory = null;
        if (ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.isEmpty()) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = insOrderMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
        }
        return baseMapper.selectList(Wrappers.<InsReportApproveConfig>lambdaQuery()
                .eq(StringUtils.isNotBlank(laboratory),InsReportApproveConfig::getLaboratory,laboratory));
    }
    @Override
    public InsReportApproveConfig getApproveConfigByLaboratory(String laboratory) {
        return baseMapper.selectOne(Wrappers.<InsReportApproveConfig>lambdaQuery()
                .eq(StringUtils.isNotBlank(laboratory),InsReportApproveConfig::getLaboratory,laboratory));
    }
    @Override
    public Map<String, List<Map<String,Object>>> getUserList() {
        //查询通信和电力下的人员信息
        //查询当前登录人员的架构
        Integer userId = Integer.parseInt(SecurityUtils.getUserId()+"");
        //判断全部,个人,组织的权限
        User user = userMapper.selectById(userId);//当前登录的人
        //获取当前人所属实验室id
        String laboratory = "";
        String departLimsId = user.getDepartLimsId();
        if (org.apache.commons.lang3.ObjectUtils.isNotEmpty(departLimsId)) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = userMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
        }
        return userMapper.getPersonList(laboratory).stream().collect(Collectors.groupingBy(m->m.get("depName").toString()));
    }
    @Override
    public boolean updateApproveConfig(ApproveConfigDTO approveConfigDTO) {
        if(!approveConfigDTO.getConfigList().isEmpty()){
            approveConfigDTO.getConfigList().forEach(config->baseMapper.updateById(config));
            return true;
        }
        throw new RuntimeException("更新失败");
    }
}
inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,876 @@
package com.ruoyi.inspect.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.FilePictureRenderData;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.ruoyi.common.config.MinioConfig;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.enums.AttachmentType;
import com.ruoyi.common.mapper.AttachmentTableMapper;
import com.ruoyi.common.pojo.AttachmentTable;
import com.ruoyi.common.service.AttachmentTableService;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.exception.ErrorException;
import com.ruoyi.inspect.dto.ReportPageDto;
import com.ruoyi.inspect.mapper.*;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.inspect.pojo.InsOrderState;
import com.ruoyi.inspect.pojo.InsReport;
import com.ruoyi.process.pojo.ProcessReport;
import com.ruoyi.inspect.service.InsReportService;
import com.ruoyi.process.mapper.ProcessReportMapper;
import com.ruoyi.system.mapper.UserMapper;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
 * @author Administrator
 * @description é’ˆå¯¹è¡¨ã€ins_report(检验报告)】的数据库操作Service实现
 * @createDate 2024-03-17 22:10:02
 */
@Service
@Slf4j
public class InsReportServiceImpl extends ServiceImpl<InsReportMapper, InsReport>
        implements InsReportService {
    @Resource
    private AttachmentTableMapper attachmentTableMapper;
    @Resource
    private AttachmentTableService attachmentTableService;
    @Resource
    private MinioConfig minioConfig;
    @Resource
    private UserMapper userMapper;
    @Resource
    private InsReportMapper insReportMapper;
    @Resource
    ProcessReportMapper processReportMapper;
    @Value("${wordUrl}")
    private String wordUrl;
    @Value("${file.licenseUrl}")
    private String licenseUrl;
    @Value("${file.path}")
    private String imgUrl;
    @Resource
    private InsOrderMapper insOrderMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private InsOrderStateMapper insOrderStateMapper;
    private static final String SYNC_REPORT_KEY_PREFIX = "syncApprovalReport_lock_";
    @Resource
    private InsReportApproveConfigMapper insReportApproveConfigMapper;
    @Override
    public IPage<ReportPageDto> pageInsReport(Page page, ReportPageDto reportPageDto) {
        User user = userMapper.selectById(SecurityUtils.getUserId());//当前登录的人
        //获取当前人所属实验室id
        String departLimsId = user.getDepartLimsId();
        String laboratory = null;
        if (ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.isEmpty()) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = insOrderMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
        }
        QueryWrapper<ReportPageDto> wrapper = QueryWrappers.queryWrappers(reportPageDto);
        if(Objects.nonNull(reportPageDto) && Objects.nonNull(reportPageDto.getCreateTimeRange())){
            wrapper.gt(reportPageDto.getCreateTimeRange().size()>1,"create_time",reportPageDto.getCreateTimeRange().get(0))
                    .lt(reportPageDto.getCreateTimeRange().size()>1,"create_time",reportPageDto.getCreateTimeRange().get(1));
        }
        IPage<ReportPageDto> iPage = insReportMapper.pageInsReport(page, wrapper, laboratory);
        return iPage;
    }
    @Override
    public int inReport(String url, Integer id) {
        InsReport insReport = new InsReport();
        insReport.setId(id);
        insReport.setUrlS(url);
        return insReportMapper.updateById(insReport);
    }
    // è¿˜åŽŸ
    @Override
    public void upReportUrl(Integer id,Integer type) {
        List<AttachmentTable> attachmentTables = attachmentTableMapper.selectList(new LambdaQueryWrapper<AttachmentTable>()
                .eq(AttachmentTable::getSubclassId, id)
                .eq(AttachmentTable::getOtherTableName, AttachmentType.getAttachmentValue(type))
                .orderByAsc(AttachmentTable::getId));
        if(CollectionUtils.isNotEmpty(attachmentTables)) {
           // èŽ·å–æ‰€æœ‰çš„id
            List<Integer> collect = attachmentTables.stream().map(AttachmentTable::getId).collect(Collectors.toList());
            // é™¤äº†ç¬¬ä¸€ä¸ªå…¨éƒ¨åˆ é™¤ åˆ é™¤æ‰€æœ‰çš„附件
            collect.remove(0);
            if(collect.size() > 0) {
                attachmentTableMapper.deleteBatchIds(collect);
            }
        }
    }
    @Override
    public void downReport(Integer id,Integer type, HttpServletResponse response) {
        InsReport insReport = insReportMapper.selectById(id);
        String url = "";
        // 0 ä¸‹è½½docx 1 ä¸‹è½½pdf
        if(type == 0) {
            url  = Strings.isNotEmpty(insReport.getUrlS()) ? insReport.getUrlS() : insReport.getUrl();
        }else {
            url = insReport.getTempUrlPdf();
        }
        if(Strings.isEmpty(url)){
            throw new ErrorException("报告地址为空");
        }
        File file = new File(wordUrl + File.separator + url.replace("/word/", ""));
        try {
            String fileName = file.getName();
            if(fileName.indexOf("_") != -1) {
                fileName = fileName.split("_")[1];
            }
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-disposition","attachment;filename=" + fileName);
            ServletOutputStream stream = response.getOutputStream();
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[1024];
            int byteRead;
            while((byteRead = fileInputStream.read(bytes)) != -1){
                stream.write(bytes, 0, byteRead);
                stream.flush();
            }
            fileInputStream.close();
            stream.close();
        }catch (Exception e){
            throw new ErrorException("下载失败");
        }
    }
    //提交
    @Override
    public int writeReport(Integer id) {
        int userId = Integer.parseInt(SecurityUtils.getUserId() + "");
        InsReport insReport = insReportMapper.selectById(id);
        insReport.setId(id);
        insReport.setState(1);
        insReport.setWriteTime(LocalDateTime.now());//提交时间
        insReport.setWriteUserId(userId);//提交人
        return insReportMapper.updateById(insReport);
    }
    /**
     * åˆ›å»ºä¸´æ—¶æ–‡ä»¶
     * @param inputStream è¾“入流
     * @param suffix åŽç¼€
     * @return
     */
    public String temporaryFile(InputStream inputStream,String suffix) {
        String tempFilePath = "";
        try {
            File tempFile = File.createTempFile(UUID.randomUUID().toString(), suffix);
            tempFile.deleteOnExit();
            // å°†è¾“入流内容赋值的临时文件
            try(FileOutputStream fileInputStream = new FileOutputStream(tempFile)) {
                byte[] bytes = new byte[1024];
                int len;
                while((len = inputStream.read(bytes)) != -1) {
                    fileInputStream.write(bytes,0,len);
                }
                // èŽ·å–ä¸´æ—¶æ–‡ä»¶çš„è·¯å¾„
                tempFilePath = tempFile.getAbsolutePath();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tempFilePath;
    }
    /**
     * å°†æ–‡ä»¶ä¸Šä¼ åˆ°Minio
     * @return
     */
    public void  uploadMinio(String url,Integer id) {
        String suffix = url.substring(url.lastIndexOf("."));
        // é‡æ–°ä¸Šä¼ åˆ°MinIo
        File file = new File(url);
        String fileName = UUID.randomUUID().toString() + suffix;
        FileInputStream stream = null;
        try {
            MinioClient build = MinioClient.builder().endpoint(minioConfig.getEndpoint(), minioConfig.getPort(), minioConfig.getSecure())
                    .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                    .build();
            stream = new FileInputStream(file);
            build.putObject(
                    PutObjectArgs.builder()
                            .bucket(minioConfig.getBucketName())
                            .object(fileName)
                            .stream(stream, file.length(), -1)
                            .contentType("application/octet-stream")
                            .userMetadata(Collections.singletonMap("Content-Disposition", "attachment; filename=\"" + fileName + "\""))
                            .build()
            );
            // ä¿å­˜åˆ°æ•°æ®åº“
            AttachmentTable attachmentTable = new AttachmentTable();
            attachmentTable.setBucketName(minioConfig.getBucketName());
            attachmentTable.setFileName(fileName);
            attachmentTable.setSubclassId(id);
            attachmentTable.setOtherTableName(AttachmentType.getAttachmentValue(1));
            attachmentTableMapper.insert(attachmentTable);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    //审核
    @Override
    public int examineReport(Integer id, Integer isExamine, String examineTell) {
        int userId = Integer.parseInt(SecurityUtils.getUserId() + "");
        InsReport insReport = insReportMapper.selectById(id);
        insReport.setIsExamine(isExamine);
        if (ObjectUtils.isNotEmpty(examineTell)) {
            insReport.setExamineTell(examineTell);
        }
        insReport.setExamineUserId(userId);//审核人
        insReport.setExamineTime(LocalDateTime.now());//审核时间
        if (isExamine == 0) {
            //如果审核不通过
            insReport.setState(0);//提交状态改为待提交
            return insReportMapper.updateById(insReport);
        }
        //获取审核人的签名地址
        String signatureUrl;
        try {
            signatureUrl = userMapper.selectById(insReport.getExamineUserId()).getSignatureUrl();
        } catch (Exception e) {
            throw new ErrorException("找不到审核人的签名");
        }
        //系统生成报告地址
        String url = insReport.getUrl();
        //手动上传报告地址
        String urlS = insReport.getUrlS();
        wordInsertUrl(new HashMap<String, Object>() {{
            put("examineUrl", new FilePictureRenderData(100,50,imgUrl + "/" + signatureUrl));
        }}, (urlS == null ? url : urlS).replace("/word", wordUrl));
        // ä¿®æ”¹ä¸´æ—¶pdf
        String tempUrlPdf = wordToPdfTemp((StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
        insReport.setTempUrlPdf("/word/" + tempUrlPdf);
        return insReportMapper.updateById(insReport);
    }
    //批准
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int ratifyReport(Integer id, Integer isRatify, String ratifyTell) {
        int userId = Integer.parseInt(SecurityUtils.getUserId() + "");
        InsReport insReport = insReportMapper.selectById(id);
        insReport.setIsRatify(isRatify);
        if (ObjectUtils.isNotEmpty(ratifyTell)) {
            insReport.setRatifyTell(ratifyTell);
        }
        insReport.setRatifyUserId(userId);//批准人
        insReport.setRatifyTime(LocalDateTime.now());//批准时间
        if (isRatify == 0) {
            //如果批准不通过
            insReport.setState(0);//提交状态改为待提交
            return insReportMapper.updateById(insReport);
        }
        //获取批准人的签名地址
        String signatureUrl;
        try {
            signatureUrl = userMapper.selectById(insReport.getRatifyUserId()).getSignatureUrl();
        } catch (Exception e) {
            throw new ErrorException("找不到批准人的签名");
        }
        //获取场所的报告专用章
        String sealUrl;
        try {
            String laboratory = insOrderMapper.selectById(insReport.getInsOrderId()).getLaboratory();
            sealUrl = insReportMapper.getLaboratoryByName(laboratory);
        } catch (Exception e) {
            throw new ErrorException("找不到报告专用章");
        }
        if (sealUrl == null) throw new ErrorException("找不到报告专用章");
        //系统生成报告地址
        String url = insReport.getUrl();
        //手动上传报告地址
        String urlS = insReport.getUrlS();
        String finalUrl = (urlS == null ? url : urlS).replace("/word", wordUrl);
        wordInsertUrl(new HashMap<String, Object>() {{
            put("ratifyUrl", new FilePictureRenderData(100,50,imgUrl + "/" + signatureUrl));
            put("seal1", new FilePictureRenderData(600,600,imgUrl + "/" + sealUrl));
            put("seal2", new FilePictureRenderData(600,600,imgUrl + "/" + sealUrl));
        }}, finalUrl);
        wordToPdf(finalUrl, sealUrl);
        InsOrder insOrder = new InsOrder();
        insOrder.setId(insReportMapper.selectById(id).getInsOrderId());
        insOrder.setState(4);
        insOrderMapper.updateById(insOrder);
        // ä¿®æ”¹ä¸´æ—¶pdf
        String tempUrlPdf = wordToPdfTemp((StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
        insReport.setTempUrlPdf("/word/" + tempUrlPdf);
        /*新增cnas7.8报告结果*/
        ProcessReport processReport = new ProcessReport();
        processReport.setInsReportCode(insReport.getCode());
        processReportMapper.insert(processReport);
        return insReportMapper.updateById(insReport);
    }
    @Override
    public int wordInsertUrl(Map<String, Object> map, String url) {
        XWPFTemplate template = XWPFTemplate.compile(url).render(map);
        try {
            template.writeAndClose(Files.newOutputStream(Paths.get(url)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return 1;
    }
    //报告批量下载
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String downAll(String ids) {
        List<Long> list = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<InsReport> insReports = insReportMapper.selectBatchIds(list);
        String zipFilePath = null;
        // ä¸´æ—¶æ–‡ä»¶å¤¹è·¯å¾„
        try {
            String tempFolderPath = wordUrl + "/tempFolder";
            File tempFolder = new File(tempFolderPath);
            if (tempFolder.exists()) {
                deleteDirectory(tempFolder); // åˆ é™¤æ—§çš„临时文件夹
            }
            tempFolder.mkdirs(); // åˆ›å»ºæ–°çš„临时文件夹
            for (InsReport insReport : insReports) {
                File sourceFile = new File((ObjectUtils.isNotEmpty(insReport.getUrlS()) ? insReport.getUrlS() : insReport.getUrl()).replace("/word", wordUrl));
                // ä¸‹è½½æ–‡ä»¶åç§°åŽ»é™¤æ—¶é—´
                String destinationFileName = sourceFile.getName();
                if(destinationFileName.indexOf("_") != -1) {
                    destinationFileName = destinationFileName.split("_")[1];
                }
                File destinationFile = new File(tempFolder, destinationFileName);
                Files.copy(sourceFile.toPath(), destinationFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
            // åŽ‹ç¼©ä¸´æ—¶æ–‡ä»¶å¤¹
            zipFilePath = wordUrl + "/zip/output.zip";
            zipDirectory(tempFolderPath, zipFilePath);
            // æ¸…理临时文件夹
            deleteDirectory(tempFolder);
            System.out.println("ZIP文件创建完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "/word/zip/output.zip";
    }
    //批量上传
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int upAll(MultipartFile file) {
        if (file != null) {
            // æ ¹æ®æ–‡ä»¶åæŸ¥è¯¢id
            String fileName = file.getOriginalFilename();
            String code = fileName.replace(".docx", "").replace("JCZX", "JCZX/");
            if(fileName.lastIndexOf("_") != -1) {
                code = code.substring(file.getOriginalFilename().lastIndexOf("_") + 1);
            }
            //查询未审核的报告数据
            InsReport insReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery().eq(InsReport::getCode, code).eq(InsReport::getIsExamine,-9));
            if (ObjectUtils.isEmpty(insReport)) {
                throw new ErrorException("没有编号为" + code + "的报告或该报告已审核通过");
            }
            // å¦‚æžœUrlS有值 å…ˆå°†è¯¥æ–‡ä»¶åˆ é™¤
            if(Strings.isNotEmpty(insReport.getUrlS())) {
                String url = wordUrl + File.separator + insReport.getUrlS().replace("/word/", "");
                File file1 = new File(url);
                if(file1.exists()) {
                    file1.delete();
                }
            }
            String urlString;
            String pathName;
            String path = wordUrl;
            File realpath = new File(path);
            if (!realpath.exists()) {
                realpath.mkdirs();
            }
            pathName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss")) + "_" + insReport.getCode().replace("/", "") + ".docx";
            urlString = realpath + "/" + pathName;
            // å¤åˆ¶æ–‡ä»¶åˆ°æŒ‡å®šè·¯å¾„
            try {
                Files.copy(file.getInputStream(), new File(urlString).toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            inReport("/word/" + pathName, insReport.getId());
        }
        return 0;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdraw(Map<String,Object> map) {
        Integer id = Integer.parseInt(map.get("id").toString());
        List<String> list = JSONArray.parseArray(map.get("laboratory").toString(), String.class);
        Integer insOrderId = insReportMapper.selectById(id).getInsOrderId();
        List<InsOrderState> insOrderStateS = insOrderStateMapper.selectList(new LambdaQueryWrapper<InsOrderState>()
                .eq(InsOrderState::getInsOrderId, insOrderId)
                .in(CollectionUtils.isNotEmpty(list),InsOrderState::getLaboratory, list));
        if(CollectionUtils.isNotEmpty(insOrderStateS)) {
            List<Integer> collect = insOrderStateS.stream().map(InsOrderState::getId).collect(Collectors.toList());
            // ä¿®æ”¹è¯¥å•子试验室的状态为待复核,删除报告信息
            insOrderStateMapper.update(null,new LambdaUpdateWrapper<InsOrderState>()
                    .set(InsOrderState::getInsState,3) // å¾…复核
                    .in(InsOrderState::getId,collect));
            insReportMapper.delete(new LambdaQueryWrapper<InsReport>().eq(InsReport::getId,id));
        }
    }
    @Override
    public List<Map<String, Object>> getLaboratoryByReportId(Integer id) {
        List<Map<String, Object>> list = new ArrayList<>();
        Integer insOrderId = insReportMapper.selectById(id).getInsOrderId();
        insOrderStateMapper.selectList(new LambdaQueryWrapper<InsOrderState>()
                        .eq(InsOrderState::getInsOrderId,insOrderId))
                .forEach(insOrderState -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("label",insOrderState.getLaboratory());
                    map.put("value",insOrderState.getLaboratory());
                    list.add(map);
                });
        return list;
    }
    @Override
    public Map<String, Object> getReportCountInfo(ReportPageDto reportPageDto) {
        int userId = Integer.parseInt(SecurityUtils.getUserId() + "");
        HashMap<String, Object> map = new HashMap<>();
        User user = userMapper.selectById(userId);//当前登录的人
        //获取当前人所属实验室id
        String departLimsId = user.getDepartLimsId();
        String laboratory = null;
        if (ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.isEmpty()) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = insOrderMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
        }
        QueryWrapper<ReportPageDto> wrapper = QueryWrappers.queryWrappers(reportPageDto);
        if(Objects.nonNull(reportPageDto) && Objects.nonNull(reportPageDto.getCreateTimeRange())){
            wrapper.gt(reportPageDto.getCreateTimeRange().size()>1,"create_time",reportPageDto.getCreateTimeRange().get(0))
                    .lt(reportPageDto.getCreateTimeRange().size()>1,"create_time",reportPageDto.getCreateTimeRange().get(1));
        }
        map.put("unSubmitCount",insReportMapper.findReportCountInfo(wrapper,laboratory,"ir.write_user_id").size());
        map.put("unExamineCount",insReportMapper.findReportCountInfo(wrapper,laboratory,"ir.is_examine").size());
        map.put("unRatifyCount",insReportMapper.findReportCountInfo(wrapper,laboratory,"ir.is_ratify").size());
        return map;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchApprovalReport(List<Integer> ids) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        Integer userId = Integer.parseInt(SecurityUtils.getUserId() + "");
        String key = SYNC_REPORT_KEY_PREFIX+userId;
        //执行前删除之前的keys
        deleteRedisKeys(key);
        synchronized (key) {
            redisTemplate.opsForValue().set(key,1);
            RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(),true);
            //异步执行审批操作
            CompletableFuture.runAsync(() -> {
                try {
                    runBatchApproval(ids,key);
                }catch (Exception e){
                    //删除key
                    deleteRedisKeys(key);
                    redisTemplate.opsForValue().set(key+"_exception",e.getMessage());
                }
            },threadPoolTaskExecutor);
        }
    }
    /**
     * åˆ é™¤redis key
     * @param key
     */
    private void deleteRedisKeys(String key){
        redisTemplate.delete(key);
        redisTemplate.delete(key+"_num");
        redisTemplate.delete(key+"_count");
        redisTemplate.delete(key+"_surplus");
        redisTemplate.delete(key+"_exception");
    }
    /**
     * æ‰§è¡Œå®¡æ‰¹æ“ä½œ
     * @param ids æŠ¥å‘Šid列表
     */
    private void runBatchApproval(List<Integer> ids,String keyPrefix) {
        if(ids.isEmpty()){
            return;
        }
        long start = System.currentTimeMillis();
        String surplusKey = keyPrefix + "_surplus";//剩余条数
        String numKey = keyPrefix + "_num";//总进度
        String countKey = keyPrefix + "_count";//总条数
        redisTemplate.opsForValue().set(countKey, ids.size());
        redisTemplate.opsForValue().set(surplusKey, ids.size());
        Object countObj = redisTemplate.opsForValue().get(countKey);
        long parsed2 = Long.parseLong(String.valueOf(countObj));
        AtomicLong count = new AtomicLong(parsed2);
        for (Integer id : ids) {
            //业务代码
            InsReport insReport = insReportMapper.selectById(id);
            String laboratory = insOrderMapper.selectById(insReport.getInsOrderId()).getLaboratory();
            //获取签名和印章
            String sealUrl;
            String writeUrl;
            String examineUrl;
            String ratifyUrl;
            int writeId;
            int examineId;
            int ratifyId;
            try {
                sealUrl = insReportMapper.getLaboratoryByName(laboratory);//印章
                Map<String,Object> urlMap = insReportApproveConfigMapper.selectApprovalConfigByLaboratory(laboratory);//签名
                writeUrl = imgUrl + "/" + (Objects.isNull(urlMap.get("writeUrl"))?"":urlMap.get("writeUrl").toString());//编制人签名url
                examineUrl = imgUrl + "/" +  (Objects.isNull(urlMap.get("examineUrl"))?"":urlMap.get("examineUrl").toString());//审核人签名url
                ratifyUrl = imgUrl + "/" +  (Objects.isNull(urlMap.get("ratifyUrl"))?"":urlMap.get("ratifyUrl").toString());//批准人签名url
                writeId = Integer.parseInt(urlMap.get("writeId").toString());//编制人
                examineId = Integer.parseInt(urlMap.get("examineId").toString());//审核人签
                ratifyId =Integer.parseInt(urlMap.get("ratifyId").toString());//批准人
            } catch (Exception e) {
                throw new ErrorException("找不到签名和印章");
            }
            //设置报告信息
            insReport.setIsExamine(1);
            insReport.setIsRatify(1);
            insReport.setState(1);
            insReport.setWriteUserId(writeId);
            insReport.setExamineUserId(examineId);
            insReport.setRatifyUserId(ratifyId);
            if(Objects.isNull(insReport.getWriteTime())){
                insReport.setWriteTime(LocalDateTime.now());
            }
            if(Objects.isNull(insReport.getExamineTime())){
                insReport.setExamineTime(LocalDateTime.now());
            }
            if(Objects.isNull(insReport.getRatifyTime())){
                insReport.setRatifyTime(LocalDateTime.now());
            }
            //更新订单状态
            InsOrder insOrder = new InsOrder();
            insOrder.setId(insReport.getInsOrderId());
            insOrder.setState(4);
            insOrderMapper.updateById(insOrder);
            //系统生成报告地址
            String url = insReport.getUrl();
            //手动上传报告地址
            String urlS = insReport.getUrlS();
            String finalUrl = (StringUtils.isBlank(urlS) ? url : urlS).replace("/word", wordUrl);
            wordInsertUrl(new HashMap<String, Object>() {{
                put("writeUrl", new FilePictureRenderData(100,50,writeUrl));
                put("examineUrl", new FilePictureRenderData(100,50,examineUrl));
                put("ratifyUrl", new FilePictureRenderData(100,50,ratifyUrl));
                put("seal1", new FilePictureRenderData(600,600,imgUrl + "/" +sealUrl));
                put("seal2", new FilePictureRenderData(600,600,imgUrl + "/" +sealUrl));
            }}, finalUrl);
            wordToPdf(finalUrl, sealUrl);
            // ä¿®æ”¹ä¸´æ—¶pdf
            String tempUrlPdf = wordToPdfTemp((StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
            insReport.setTempUrlPdf("/word/" + tempUrlPdf);
            //更新报告状态
            insReportMapper.updateById(insReport);
            //更新redis的key
            Object o = redisTemplate.opsForValue().get(numKey);
            if (Objects.isNull(o)) {
                redisTemplate.opsForValue().set(numKey, 1);
            } else {
                long parsed = Long.parseLong(String.valueOf(o));
                redisTemplate.opsForValue().set(numKey, parsed + 1);
            }
            redisTemplate.opsForValue().set(surplusKey, count.decrementAndGet());
        }
        long end = System.currentTimeMillis();
        long useTime = (end-start)/1000;
        log.info("线程{}报告审批结束,耗时:{}s",keyPrefix,useTime);
    }
    @Override
    public Map<String, Object> getBatchApprovalProgress() {
        Integer userId =  Integer.parseInt(SecurityUtils.getUserId() + "");
        String key = SYNC_REPORT_KEY_PREFIX + userId;
        Map<String, Object> map = new HashMap<>();
        map.put("hasProgress",false);
        map.put("hasNum",0);
        map.put("hasCount",0);
        map.put("surplus",0);
        Object o = redisTemplate.opsForValue().get(key);
        if(Objects.nonNull(o)){
            map.put("hasProgress",true);
        }
        Object o1 = redisTemplate.opsForValue().get(key+"_num");
        Object o2 = redisTemplate.opsForValue().get(key+"_count");
        Object surplus = redisTemplate.opsForValue().get(key+"_surplus");
        Object exception = redisTemplate.opsForValue().get(key+"_exception");
        if(Objects.nonNull(surplus)){
            map.put("surplus",surplus);
        }
        if (Objects.nonNull(o1)&&Objects.nonNull(o2)){
            //得到进度
            BigDecimal multiply = new BigDecimal(String.valueOf(o1)).divide(new BigDecimal(String.valueOf(o2)), 2,BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(100));
            map.put("hasNum",multiply);
            map.put("hasCount",Long.parseLong(String.valueOf(o2)));
        }
        map.put("hasException",exception);
        return map;
    }
    //解压文件夹
    private void unzip(File zipFile, File destDir) throws IOException {
        try (ZipFile zip = new ZipFile(zipFile)) {
            Enumeration<? extends ZipEntry> entries = zip.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                File file = new File(destDir, entry.getName());
                if (entry.isDirectory()) {
                    file.mkdirs();
                } else {
                    file.getParentFile().mkdirs();
                    try (InputStream in = zip.getInputStream(entry);
                         OutputStream out = new FileOutputStream(file)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = in.read(buffer)) > 0) {
                            out.write(buffer, 0, len);
                        }
                    }
                }
            }
        }
    }
    // åŽ‹ç¼©æ–‡ä»¶å¤¹
    public static void zipDirectory(String sourceDirPath, String zipFilePath) throws IOException {
        try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
            Path sourceDir = Paths.get(sourceDirPath);
            Files.walk(sourceDir)
                    .filter(path -> !Files.isDirectory(path))
                    .forEach(path -> {
                        ZipEntry zipEntry = new ZipEntry(sourceDir.relativize(path).toString());
                        try {
                            zipOut.putNextEntry(zipEntry);
                            Files.copy(path, zipOut);
                            zipOut.closeEntry();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        }
    }
    // åˆ é™¤æ–‡ä»¶å¤¹åŠå…¶å†…容
    public static void deleteDirectory(File directory) throws IOException {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        Files.delete(directory.toPath());
    }
    /**
     * word转换pdf
     * @param path
     * @return
     */
    public String wordToPdfTemp(String path) {
        try {
            return wordToPdf(path, path.replace(".docx", ""));
        } catch (Exception e) {
            throw new ErrorException("转换失败");
        }
    }
    public String wordToPdf(String wordPath, String pdfPath) {
        FileOutputStream os = null;
        try {
            //凭证 ä¸ç„¶åˆ‡æ¢åŽæœ‰æ°´å°
            InputStream is = Files.newInputStream(new File(licenseUrl).toPath());
            License license = new License();
            license.setLicense(is);
            if (!license.getIsLicensed()) {
                System.out.println("License验证不通过...");
                return null;
            }
            //生成一个空的PDF文件
            File file;
            //判断是否是进厂报告
            file = File.createTempFile(pdfPath, ".pdf");
            file.deleteOnExit();
            os = new FileOutputStream(file);
            //要转换的word文件
            com.aspose.words.Document doc = new com.aspose.words.Document(wordPath);
            doc.save(os, SaveFormat.PDF);
            String name = file.getName();
            return file.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    /**
     * åˆ‡å‰²å›¾ç‰‡
     *
     * @param Path å›¾ç‰‡è·¯å¾„
     * @param n    åˆ‡å‰²ä»½æ•°
     */
    public static com.itextpdf.text.Image[] slicingImages(String Path, int n) throws IOException, BadElementException {
        com.itextpdf.text.Image[] nImage = new com.itextpdf.text.Image[n];
        BufferedImage img = ImageIO.read(new File(Path));
        int h = img.getHeight();
        int w = img.getWidth();
        int sw = w / n;
        for (int i = 0; i < n; i++) {
            BufferedImage subImg;
            if (i == n - 1) {//最后剩余部分
                subImg = img.getSubimage(i * sw, 0, w - i * sw, h);
            } else {//前n-1块均匀切
                subImg = img.getSubimage(i * sw, 0, sw, h);
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(subImg, Path.substring(Path.lastIndexOf('.') + 1), out);
            nImage[i] = com.itextpdf.text.Image.getInstance(out.toByteArray());
        }
        return nImage;
    }
    /**
     * ç›–骑缝章
     *
     * @param infilePath  åŽŸPDF路径
     * @param outFilePath è¾“出PDF路径
     */
    public static void stamperCheckMarkPDF(String infilePath, String outFilePath, String picPath) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(infilePath);//选择需要印章的pdf
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf
        com.itextpdf.text.Rectangle pageSize = reader.getPageSize(1);//获得第一页
        float height = pageSize.getHeight();
        float width = pageSize.getWidth();
        int nums = reader.getNumberOfPages();
        com.itextpdf.text.Image[] nImage = slicingImages(picPath, nums);//生成骑缝章切割图片
        for (int n = 1; n <= nums; n++) {
            PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章
            com.itextpdf.text.Image img = nImage[n - 1];//选择图片
            float newHeight = 100f;
            float newWidth = img.getWidth() / (img.getHeight() / 100);
            img.scaleAbsolute(newWidth, newHeight);//控制图片大小
            img.setAbsolutePosition(width - newWidth, height / 2 - newHeight / 2);//控制图片位置
            over.addImage(img);
        }
        stamp.close();
    }
}
performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml
@@ -110,8 +110,9 @@
    <select id="performanceShiftList" resultMap="performanceShiftPageMap">
        SELECT
        if(u.department is not null and u.department != '', CONCAT(u.name, '(', u.department, ')'), u.name) name,
        GROUP_CONCAT(s.work_time, ':', s.shift, ':', s.id order by s.work_time SEPARATOR ';') AS shift_time, u.id user_id, u.department
        <!--if(u.department is not null and u.department != '', CONCAT(u.name, '(', u.department, ')'), u.name) name,-->
            u.name name,
        GROUP_CONCAT(s.work_time, ':', s.shift, ':', s.id order by s.work_time SEPARATOR ';') AS shift_time, u.id user_id, u.dept_id
        FROM performance_shift s
        LEFT JOIN user u on u.id = s.user_id
        <where>
@@ -124,8 +125,8 @@
            <if test="laboratory != null and laboratory != ''">
            </if>
        </where>
        order by s.create_time
        GROUP BY u.id
        order by s.create_time
    </select>
    <select id="seldepLimsId" resultType="java.lang.String">
ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java
@@ -17,6 +17,7 @@
    private String accessKey;
    private String secretKey;
    private Boolean secure;
    private String bucketName;
    @Bean
    public MinioClient getMinioClient() {
ruoyi-common/src/main/java/com/ruoyi/common/controller/AttachmentTypeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package com.ruoyi.common.controller;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.service.AttachmentTableService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/file/attachmentType")
@AllArgsConstructor
public class AttachmentTypeController {
    private AttachmentTableService attachmentTableService;
    /**
     * ä¸Šä¼ æ–‡ä»¶
     * @param file æ–‡ä»¶
     * @param type æžšä¸¾ç±»åž‹
     * @param id ä¸šåŠ¡id
     * @return
     */
    @PostMapping("/upload")
    public Result upload(@RequestParam("file")MultipartFile file,@RequestParam("type")Integer type,@RequestParam("id")Integer id) {
        attachmentTableService.upload(file,type,id);
        return Result.success();
    }
    /**
     * ä¸‹è½½æ–‡ä»¶
     * @param id ä¸šåŠ¡id
     * @param type æžšä¸¾ç±»åž‹
     * @param code æ–‡ä»¶åç§°
     * @param suffix æ–‡ä»¶åŽç¼€ å¯èƒ½æ˜¯word æˆ–者 pdf
     * @return
     */
    @GetMapping("/downLoad")
    public void downLoad(Integer id, Integer type , String code,String suffix, HttpServletResponse response)   {
        attachmentTableService.downLoad(id, type,code, suffix,response);
    }
    /**
     * èŽ·å–æ–‡ä»¶çš„MIME
     * @param id
     * @param type
     * @return
     */
    @GetMapping("/getMIME")
    public Result getMIME(Integer id, Integer type,String suffix) {
        return Result.success(attachmentTableService.getAttachmentList(id, type,suffix));
    }
    /**
     * èŽ·å–æ–‡ä»¶URL
     * @param id
     * @param type
     * @param suffix æ–‡ä»¶åŽç¼€  å¯èƒ½æ˜¯word å’Œ pdf
     */
    @GetMapping("/getURL")
    public Result getURL(Integer id, Integer type  , String suffix) {
        return Result.success(attachmentTableService.getURL(id, type , suffix));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/AttachmentType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package com.ruoyi.common.enums;
public enum AttachmentType {
    /*
    * æŠ¥å‘Šç¼–制
     */
    INS_REPORT(1, "ins_report"),
    USER(2, "user"),
    ;
    private Integer type;
    private String value;
    private AttachmentType(Integer type, String value) {
        this.type = type;
        this.value = value;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public static String getAttachmentValue(Integer type) {
        for (AttachmentType attachmentType : AttachmentType.values()) {
            if (attachmentType.getType().equals(type)) {
                return attachmentType.getValue();
            }
        }
        return null;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/mapper/AttachmentTableMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
package com.ruoyi.common.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.pojo.AttachmentTable;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AttachmentTableMapper  extends BaseMapper<AttachmentTable> {
}
ruoyi-common/src/main/java/com/ruoyi/common/pojo/AttachmentTable.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package com.ruoyi.common.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@TableName("attachment_table")
public class AttachmentTable {
    @TableId(type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty("其他表绑定id")
    private Integer subclassId;
    @ApiModelProperty("文件名称")
    private String fileName;
    @ApiModelProperty("文件类型")
    private String fileType;
    @ApiModelProperty("文件原名称")
    private String originalFileName;
    @ApiModelProperty("桶名")
    private String bucketName;
    @ApiModelProperty("所在模块名称")
    private String moduleName;
    @ApiModelProperty("其他表名")
    private String otherTableName;
}
ruoyi-common/src/main/java/com/ruoyi/common/service/AttachmentTableService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.ruoyi.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.pojo.AttachmentTable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Map;
public interface AttachmentTableService extends IService<AttachmentTable> {
    void upload(MultipartFile file, Integer type, Integer id);
   void downLoad(Integer id, Integer type,String code,String suffix,HttpServletResponse response)  ;
   Map<String, Object> getAttachmentList(Integer id, Integer type,String suffix);
   String getURL(Integer id, Integer type  , String suffix);
    InputStream getInputStream(Integer id, Integer type  , String suffix);
}
ruoyi-common/src/main/java/com/ruoyi/common/service/impl/AttachmentTableServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,218 @@
package com.ruoyi.common.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.MinioConfig;
import com.ruoyi.common.enums.AttachmentType;
import com.ruoyi.common.mapper.AttachmentTableMapper;
import com.ruoyi.common.pojo.AttachmentTable;
import com.ruoyi.common.service.AttachmentTableService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import io.minio.*;
import io.minio.http.Method;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@AllArgsConstructor
public class AttachmentTableServiceImpl  extends ServiceImpl<AttachmentTableMapper, AttachmentTable> implements AttachmentTableService {
    private MinioConfig minioConfig;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void upload(MultipartFile file, Integer type, Integer id) {
        MinioClient build = MinioClient.builder()
                .endpoint(minioConfig.getEndpoint(), minioConfig.getPort(), minioConfig.getSecure())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                .build();
        String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        try(InputStream inputStream = file.getInputStream()) {
            build.putObject(
                    PutObjectArgs.builder()
                            .bucket(minioConfig.getBucketName())
                            .object(fileName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType("application/octet-stream")
                            .userMetadata(Collections.singletonMap("Content-Disposition", "attachment; filename=\"" + fileName + "\""))
                            .build()
            );
            // ä¿å­˜åˆ°æ•°æ®åº“
            AttachmentTable attachmentTable = new AttachmentTable();
            attachmentTable.setSubclassId(id);
            attachmentTable.setFileName(fileName);
            attachmentTable.setOriginalFileName(file.getOriginalFilename());
            attachmentTable.setFileType(file.getContentType());
            attachmentTable.setBucketName(minioConfig.getBucketName());
            attachmentTable.setOtherTableName(AttachmentType.getAttachmentValue(type));
            baseMapper.insert(attachmentTable);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void downLoad(Integer id, Integer type,String code,String suffix, HttpServletResponse response)   {
        // æŸ¥è¯¢æ•°æ®åº“
        List<AttachmentTable> list = baseMapper.selectList(new LambdaQueryWrapper<AttachmentTable>()
                .eq(AttachmentTable::getSubclassId, id)
                .eq(AttachmentTable::getOtherTableName, AttachmentType.getAttachmentValue(type))
                .like(AttachmentTable::getFileName, suffix)
                .orderByDesc(AttachmentTable::getId));
        if(CollectionUtils.isNotEmpty(list)) {
            AttachmentTable attachmentTable = list.get(0);
            String fileName = attachmentTable.getFileName(); // æ–‡ä»¶å
            MinioClient build = MinioClient.builder()
                    .endpoint(minioConfig.getEndpoint(), minioConfig.getPort(), minioConfig.getSecure())
                    .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                    .build();
            try( InputStream inputStream = build.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build());
                 ServletOutputStream stream = response.getOutputStream()) {
                String finalName = "";
                String fileNameMinIo = attachmentTable.getFileName();
                String suffix1 = fileNameMinIo.substring(fileNameMinIo.lastIndexOf(".")+1);
                String contentType = getContentType(suffix1);
                if(StringUtils.isNotEmpty(code)) {
                    finalName = code + "." + suffix1;
                }else {
                    finalName = fileNameMinIo;
                }
                // è®¾ç½®å“åº”头
                response.setContentType(contentType);
                response.setHeader("Content-disposition", "attachment;filename=" + finalName);
                byte[] bytes = new byte[1024];
                int len;
                while ((len = inputStream.read(bytes)) != -1) {
                    stream.write(bytes, 0, len);
                    stream.flush();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public Map<String, Object> getAttachmentList(Integer id, Integer type,String suffix) {
        HashMap<String, Object> map = new HashMap<>();
        // æŸ¥è¯¢æ•°æ®åº“
        List<AttachmentTable> list = baseMapper.selectList(new LambdaQueryWrapper<AttachmentTable>()
                .eq(AttachmentTable::getSubclassId, id)
                .eq(AttachmentTable::getOtherTableName, AttachmentType.getAttachmentValue(type))
                .like(StringUtils.isNotEmpty(suffix),AttachmentTable::getFileName, suffix)
                .orderByDesc(AttachmentTable::getId));
        if(CollectionUtils.isNotEmpty(list)) {
            String contentType = getContentType(suffix.replace(".",""));
            map.put("contentType", contentType);
            map.put("suffix", suffix);
        }
        return map;
    }
    @Override
    public String getURL(Integer id, Integer type , String suffix) {
        String url = "";
        // æŸ¥è¯¢æ•°æ®åº“ èŽ·å–æœ€æ–°æ–‡ä»¶å
        List<AttachmentTable> attachmentTables = baseMapper.selectList(new LambdaQueryWrapper<AttachmentTable>()
                .eq(AttachmentTable::getSubclassId, id)
                .eq(AttachmentTable::getOtherTableName, AttachmentType.getAttachmentValue(type))
                .like(AttachmentTable::getFileName, suffix)
                .orderByDesc(AttachmentTable::getId));
        if(CollectionUtils.isNotEmpty(attachmentTables)) {
            AttachmentTable attachmentTable = attachmentTables.get(0);
            MinioClient build = MinioClient.builder()
                    .endpoint(minioConfig.getEndpoint(), minioConfig.getPort(), minioConfig.getSecure())
                    .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                    .build();
            try {
                 url = build.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(minioConfig.getBucketName())
                        .object(attachmentTable.getFileName())
                        .expiry(60 * 60 * 24)
                        .build());
            }  catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return url;
    }
    public InputStream  getInputStream(Integer id, Integer type , String suffix) {
        InputStream inputStream = null;
        // æŸ¥è¯¢æ•°æ®åº“ èŽ·å–æœ€æ–°æ–‡ä»¶å
        List<AttachmentTable> attachmentTables = baseMapper.selectList(new LambdaQueryWrapper<AttachmentTable>()
                .eq(AttachmentTable::getSubclassId, id)
                .eq(AttachmentTable::getOtherTableName, AttachmentType.getAttachmentValue(type))
                .like(StringUtils.isNotEmpty(suffix),AttachmentTable::getFileName, suffix)
                .orderByDesc(AttachmentTable::getId));
        if(CollectionUtils.isNotEmpty(attachmentTables)) {
            AttachmentTable attachmentTable = attachmentTables.get(0);
            MinioClient build = MinioClient.builder()
                    .endpoint(minioConfig.getEndpoint(), minioConfig.getPort(), minioConfig.getSecure())
                    .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                    .build();
            try {
                inputStream  = build.getObject(
                        GetObjectArgs.builder()
                                .bucket(minioConfig.getBucketName())
                                .object(attachmentTable.getFileName())
                                .build());
            }  catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return inputStream;
    }
    // æ ¹æ®æ–‡ä»¶æ‰©å±•名获取 MIME ç±»åž‹
    private String getContentType(String fileExtension) {
        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "pdf":
                return "application/pdf";
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt":
            case "pptx":
                return "application/vnd.ms-powerpoint";
            default:
                return "application/octet-stream"; // é»˜è®¤äºŒè¿›åˆ¶æµ
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java
@@ -47,5 +47,8 @@
    User getUserNow(@Param("userId") int userId);
    SysUserVO selectUserInfo(Long userId);
    String seldepLimsId(int depLimsId);
    List<Map<String, Object>> getPersonList(String laboratory);
}
ruoyi-system/src/main/resources/mapper/system/UserMapper.xml
@@ -63,4 +63,28 @@
    <select id="selectUserInfo" resultType="com.ruoyi.common.core.vo.SysUserVO">
        select * from user
    </select>
    <select id="seldepLimsId" resultType="java.lang.String">
        select name
        from department_lims
        where id = #{depLimsId}
    </select>
    <select id="getPersonList" resultType="java.util.Map">
        select
        u.id,
        u.name,
        dl.name as depName
        from
        user u
        left join
        department_lims dl
        on
        FIND_IN_SET(dl.id,u.depart_lims_id)
        where
        dl.name in('通信产品实验室','电力产品实验室','检测办')
        and u.status = 1
        and u.is_custom = 0
        <if test="laboratory!='' and laboratory!=null">
            and (dl.name = #{laboratory} or dl.name='检测办')
        </if>
    </select>
</mapper>