Selaa lähdekoodia

档案批量审批、批量认证接口

liuyc 1 vuosi sitten
vanhempi
commit
5a0c105755

+ 43 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskArchiveDTO.java

@@ -0,0 +1,43 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 档案审批DTO
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TaskArchiveDTO implements Serializable {
+
+    @ApiModelProperty("所选taskId")
+    private String taskId;
+
+    @ApiModelProperty("同意传OK(大写),废除可传非OK外任意字符或传空")
+    private String flag;
+
+    @ApiModelProperty("审批意见")
+    private String comment;
+
+    @ApiModelProperty("签章定位集合")
+    private List<Sign> sealStrategy;
+
+    @Data
+    public static class Sign {
+        @ApiModelProperty("签章地址url")
+        private String url;
+        @ApiModelProperty("page页码")
+        private String page;
+        @ApiModelProperty("lx")
+        private String lx;
+        @ApiModelProperty("ly")
+        private String ly;
+    }
+
+}

+ 15 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskArchiveOuterLayerDTO.java

@@ -0,0 +1,15 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class TaskArchiveOuterLayerDTO implements Serializable {
+
+    @ApiModelProperty("档案批量审批入参集合")
+    private List<TaskArchiveDTO> taskArchiveDtoList;
+
+}

+ 7 - 0
blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/feign/EVisaClient.java

@@ -4,6 +4,7 @@ import org.springblade.common.constant.EVisaConstant;
 import org.springblade.evisa.vo.CertBeanVO;
 import org.springblade.evisa.vo.EVisaMakeSealVO;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
+import org.springblade.evisa.vo.TaskArchiveDTO;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -31,6 +32,12 @@ public interface EVisaClient {
     @PostMapping(API_PREFIX + "/eVisa")
     String eVisa(@RequestBody EVisaTaskApprovalVO task);
 
+    /**
+     * 电签(自定义签章)
+     */
+    @PostMapping(API_PREFIX + "/eVisa/custom")
+    void eVisaCustom(@RequestBody org.springblade.evisa.vo.TaskArchiveDTO eVisaObj);
+
     /**
      * 创建印模
      */

+ 46 - 0
blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/vo/TaskArchiveDTO.java

@@ -0,0 +1,46 @@
+package org.springblade.evisa.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 档案审批DTO
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TaskArchiveDTO implements Serializable {
+
+    @ApiModelProperty("所选taskId")
+    private String taskId;
+
+    @ApiModelProperty("同意传OK(大写),废除可传非OK外任意字符或传空")
+    private String flag;
+
+    @ApiModelProperty("审批意见")
+    private String comment;
+
+    //1=审批任务,2=认证
+    private Integer type;
+
+    @ApiModelProperty("签章定位集合")
+    private List<Sign> sealStrategy;
+
+    @Data
+    public static class Sign {
+        @ApiModelProperty("签章地址url")
+        private String url;
+        @ApiModelProperty("page页码")
+        private String page;
+        @ApiModelProperty("lx")
+        private String lx;
+        @ApiModelProperty("ly")
+        private String ly;
+    }
+
+}

+ 4 - 0
blade-service/blade-archive/pom.xml

@@ -132,6 +132,10 @@
             <version>2.9.1.RELEASE</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 1 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java

@@ -4,7 +4,6 @@ import com.alibaba.excel.util.DateUtils;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.*;
@@ -25,7 +24,6 @@ import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.evisa.feign.EVisaClient;
-import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.feign.ArchiveTreeContractClient;
@@ -367,7 +365,7 @@ public class ArchiveFileController extends BladeController {
     public R getDutyUser(Long contractId, Long projectId) {
         ContractInfo contractById = null;
         if (contractId == null || contractId == -1) {
-            if(projectId == null || projectId == -1){
+            if (projectId == null || projectId == -1) {
                 return R.data(null);
             }
             List<Long> longs = new ArrayList<>();

+ 110 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java

@@ -0,0 +1,110 @@
+package org.springblade.archive.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.itextpdf.text.Image;
+import com.itextpdf.text.Rectangle;
+import com.itextpdf.text.pdf.PdfReader;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.poi.util.IOUtils;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.vo.ArchiveFileVO;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.secure.utils.SecureUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.evisa.feign.EVisaClient;
+import org.springblade.evisa.vo.TaskArchiveDTO;
+import org.springblade.resource.feign.IOSSClient;
+import org.springframework.beans.BeanUtils;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/archiveTask")
+@Api(value = "档案涉及任务相关接口", tags = "档案涉及任务相关接口")
+public class ArchiveFileTaskController extends BladeController {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final IOSSClient iossClient;
+    private final EVisaClient eVisaClient;
+
+    /**
+     * 批量认证(水印图片签章默认认证电签)
+     */
+    @PostMapping("/batchCertification")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "批量认证(水印图片签章默认认证电签)")
+    public R<Boolean> batchCertification(@RequestParam String ids) throws Exception {
+        if (ObjectUtil.isEmpty(SecureUtil.getUser()) || ObjectUtil.isEmpty(SecureUtil.getUserId()) || SecureUtil.getUserId().equals(-1L)) {
+            throw new ServiceException("未获取到当前登陆的用户信息,操作失败");
+        }
+        if (StringUtils.isNotEmpty(ids)) {
+            //获取档案文件
+            List<ArchiveFile> archiveFileList = jdbcTemplate.query("select * from u_archive_file where id in(" + ids + ")", new BeanPropertyRowMapper<>(ArchiveFile.class));
+            if (archiveFileList.size() > 0) {
+                //固定水印图片章
+                String pngQzUrl = "https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230911/5b42583d931664b785ebf481c37d17bc.png";
+                for (ArchiveFile archiveFile : archiveFileList) {
+                    String pdfUrl = StringUtils.isNotEmpty(archiveFile.getEVisaFile()) ? archiveFile.getEVisaFile() : archiveFile.getPdfFileUrl();
+                    if (StringUtils.isEmpty(pdfUrl)) {
+                        continue;
+                    }
+                    InputStream ossInputStreamPNG = CommonUtil.getOSSInputStream(pngQzUrl);
+                    InputStream ossInputStreamPDF = CommonUtil.getOSSInputStream(pdfUrl);
+                    PdfReader reader = null;
+                    Image img = null;
+                    if (ossInputStreamPDF != null && ossInputStreamPNG != null) {
+                        reader = new PdfReader(ossInputStreamPDF);
+                        img = Image.getInstance(IOUtils.toByteArray(ossInputStreamPNG));
+                    }
+                    if (reader != null) {
+                        //封装签章定位入参dto
+                        org.springblade.evisa.vo.TaskArchiveDTO eVISATaskArchiveDTO = new TaskArchiveDTO();
+                        //每条档案业务数据对应的pdf签章集合
+                        List<TaskArchiveDTO.Sign> signList = new ArrayList<>();
+
+                        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
+                            //计算当前页居中的位置坐标 TODO(有问题,坐标点不对,后续再算)
+                            Rectangle pageSize = reader.getPageSize(i);
+                            float x = (pageSize.getLeft() + pageSize.getRight()) / 2 - (img.getScaledWidth() / 2);
+                            float y = (pageSize.getTop() + pageSize.getBottom()) / 2 - (img.getScaledHeight() / 2);
+
+                            //构造签章对象
+                            TaskArchiveDTO.Sign sign = new TaskArchiveDTO.Sign();
+                            sign.setLx(String.valueOf(x)); //x轴
+                            sign.setLy(String.valueOf(y)); //y轴
+                            sign.setPage(String.valueOf(i)); //页码
+                            sign.setUrl(pngQzUrl); //签章图片url
+                            signList.add(sign);
+                        }
+                        eVISATaskArchiveDTO.setSealStrategy(signList);
+
+                        //TODO ============= 电签认证 =============
+                        eVISATaskArchiveDTO.setTaskId(archiveFile.getId().toString());
+                        eVISATaskArchiveDTO.setType(2); //认证
+                        this.eVisaClient.eVisaCustom(eVISATaskArchiveDTO);
+                    }
+                }
+                return R.data(true);
+            }
+        }
+        return R.data(300, false, "没有找到证书文件或PDF文件");
+    }
+
+
+}

+ 127 - 29
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -5,22 +5,29 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
-import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.jetbrains.annotations.NotNull;
-import org.springblade.business.entity.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.business.dto.TaskArchiveDTO;
+import org.springblade.business.dto.TaskArchiveOuterLayerDTO;
+import org.springblade.business.entity.DefaultConfig;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.business.entity.Task;
+import org.springblade.business.entity.TaskParallel;
 import org.springblade.business.service.*;
 import org.springblade.business.socket.WebSocket;
-import org.springblade.business.vo.BatchTaskVO;
-import org.springblade.business.vo.TaskApprovalVO;
-import org.springblade.business.vo.TaskQueryVO;
-import org.springblade.common.utils.CommonUtil;
+import org.springblade.business.vo.*;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.utils.AuthUtil;
@@ -31,11 +38,11 @@ import org.springblade.core.tool.jackson.JsonUtil;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.evisa.feign.EVisaClient;
 import org.springblade.flow.core.entity.BladeFlow;
 import org.springblade.flow.core.feign.NewFlowClient;
 import org.springblade.flow.core.vo.SendPageVO;
 import org.springblade.manager.entity.ContractInfo;
-import org.springblade.manager.entity.ContractRelationJlyz;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.resource.feign.CommonFileClient;
 import org.springblade.resource.feign.NewISmsClient;
@@ -46,17 +53,11 @@ import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.web.bind.annotation.*;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import org.springblade.business.vo.TaskVO;
-import org.springblade.core.boot.ctrl.BladeController;
 
-import javax.annotation.Resource;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.time.Duration;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ThreadPoolExecutor;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -72,31 +73,21 @@ import java.util.stream.Collectors;
 @Api(value = "任务审核主表", tags = "任务审核主表接口")
 public class TaskController extends BladeController {
 
+    private static final Logger log = LoggerFactory.getLogger(TaskController.class);
     private final JdbcTemplate jdbcTemplate;
-
     private final ITaskService taskService;
-
     private final ITaskParallelService taskParallelService;
-
     private final NewFlowClient newFlowClient;
-
     private final IDictBizClient dictBizClient;
-
     private final NewISmsClient newSmsClient;
-
     private final IDefaultConfigService defaultConfigService;
-
     private final ITaskBatchService taskBatchService;
-
     private final ITaskService iTaskService;
-
     private final WebSocket webSocket;
-
     private final CommonFileClient commonFileClient;
-
     private final ContractClient contractClient;
-
     private final IInformationQueryService informationQueryService;
+    private final EVisaClient eVisaClient;
 
     /**
      * 记录短信验证码超时时间
@@ -301,7 +292,7 @@ public class TaskController extends BladeController {
     }
 
     /**
-     * 批量审批
+     * 批量审批(质检、试验 平行审批)
      */
     @PostMapping("/batch-complete-approval-task")
     @ApiOperationSupport(order = 8)
@@ -364,6 +355,113 @@ public class TaskController extends BladeController {
         return R.data(false);
     }
 
+    /**
+     * 批量审批(档案 垂直审批)
+     */
+    @PostMapping("/batch-complete-approval-task-archive")
+    @ApiOperationSupport(order = 8)
+    @ApiOperation(value = "批量审批(档案 垂直审批)")
+    public R<Boolean> batchCompleteApprovalTaskArchive(@RequestBody TaskArchiveOuterLayerDTO taskArchiveOuterLayerDTO) throws IOException {
+        if (ObjectUtil.isEmpty(SecureUtil.getUser()) || ObjectUtil.isEmpty(SecureUtil.getUserId()) || SecureUtil.getUserId().equals(-1L)) {
+            throw new ServiceException("未获取到当前登陆的用户信息,操作失败");
+        }
+        //检查审批人是否符合顺序
+        this.checkArchiveTaskUserByCurrent(taskArchiveOuterLayerDTO.getTaskArchiveDtoList());
+
+        //构造业务数据,修改业务数据
+        for (TaskArchiveDTO taskArchiveDTO : taskArchiveOuterLayerDTO.getTaskArchiveDtoList()) {
+            if (StringUtils.isNotEmpty(taskArchiveDTO.getTaskId())) {
+                //通过checkArchiveTaskUserByCurrent检查,说明当前登陆用户是该条任务的审批人,修改审批任务状态
+                Task task = jdbcTemplate.queryForObject("select process_instance_id,form_data_id from u_task where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(Task.class));
+                if (task != null) {
+                    //获取审批任务关联用户的详情
+                    List<TaskParallel> taskParallels = jdbcTemplate.query("select id,process_instance_id,task_user,task_user_name from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
+                    if (taskParallels.size() > 0) {
+                        //当前用户任务
+                        TaskParallel taskParallelCurrentUser = taskParallels.stream().filter(f -> f.getTaskUser().equals(SecureUtil.getUserId().toString())).findAny().orElse(null);
+                        if (taskParallelCurrentUser != null) {
+                            //修改当前用户任务为已审批
+                            jdbcTemplate.execute("update u_task_parallel set status = 2 where id = " + taskParallelCurrentUser.getId());
+                        }
+                    }
+
+                    //TODO ============ 档案电签推送(每个人都要电签,按照顺序) ============
+                    org.springblade.evisa.vo.TaskArchiveDTO eVisaObj = new org.springblade.evisa.vo.TaskArchiveDTO();
+                    BeanUtils.copyProperties(taskArchiveDTO, eVisaObj);
+                    eVisaObj.setType(1); //审批
+                    this.eVisaClient.eVisaCustom(eVisaObj);
+
+                    /*//获取最新任务状态,判断是否存在未完成的审批任务(最后一个人审批完成);如果没有就闭环,修改审批任务状态、业务数据状态
+                    List<TaskParallel> taskParallelsNow = jdbcTemplate.query("select status from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
+                    List<TaskParallel> pendingApprovalTask = taskParallelsNow.stream().filter(f -> f.getStatus() != 2).collect(Collectors.toList());
+                    if (pendingApprovalTask.size() == 0) {
+                        //修改审批任务状态
+                        jdbcTemplate.execute("update u_task set status = 2 where id = " + taskArchiveDTO.getTaskId());
+                        //修改业务数据状态
+                        jdbcTemplate.execute("update u_archive_file set status = 2 where id = " + task.getFormDataId());
+                    }*/
+                }
+            }
+        }
+
+        //WebSocket推送
+        if (ObjectUtil.isNotEmpty(AuthUtil.getUserId())) {
+            Map<String, String> webSocketMessageMap = WebSocket.getWebSocketMessageMap();
+            Set<Map.Entry<String, String>> message = webSocketMessageMap.entrySet();
+            for (Map.Entry<String, String> entry : message) {
+                String userId = entry.getKey();
+                if (userId.equals(AuthUtil.getUserId().toString())) { //只推送当前用户
+                    String projectAndContractId = entry.getValue();
+                    if (StringUtils.isNotEmpty(projectAndContractId) && StringUtils.isNotEmpty(userId)) {
+                        String projectId = projectAndContractId.split(",")[0];
+                        String contractId = projectAndContractId.split(",")[1];
+                        Map<String, String> stringMap = iTaskService.getTaskCount(projectId, contractId, userId);
+                        webSocket.sendMessageByUserId(AuthUtil.getUserId().toString(), JSON.toJSONString(stringMap));
+                    }
+                }
+            }
+        }
+
+        return R.data(true);
+    }
+
+
+    /**
+     * 检查档案审批是否按照顺序审批
+     *
+     * @param taskArchiveDTOList
+     */
+    private void checkArchiveTaskUserByCurrent(List<TaskArchiveDTO> taskArchiveDTOList) {
+        for (TaskArchiveDTO taskArchiveDTO : taskArchiveDTOList) {
+            if (ObjectUtil.isNotEmpty(taskArchiveDTO.getTaskId())) {
+                Task task = jdbcTemplate.queryForObject("select process_instance_id,task_name from u_task where id = '" + taskArchiveDTO.getTaskId() + "'", new BeanPropertyRowMapper<>(Task.class));
+                if (ObjectUtil.isNotEmpty(task)) {
+                    List<TaskParallel> taskParallelList = jdbcTemplate.query("select id,process_instance_id,task_user,task_user_name,status from u_task_parallel where process_instance_id ='" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
+                    taskParallelList.sort(Comparator.comparing(TaskParallel::getId)); //根据id排序
+                    Map<String, List<TaskParallel>> taskParallelGroup = taskParallelList.stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
+                    for (Map.Entry<String, List<TaskParallel>> taskObj : taskParallelGroup.entrySet()) {
+                        //获取当前审批人前面的审批人信息
+                        List<TaskParallel> frontTaskUser = new LinkedList<>();
+                        for (TaskParallel taskParallel : taskObj.getValue()) {
+                            Long userId = SecureUtil.getUserId();
+                            if (!userId.toString().equals(taskParallel.getTaskUser())) {
+                                frontTaskUser.add(taskParallel);
+                            } else {
+                                //如果是当前的审批人,那么直接跳过
+                                break;
+                            }
+                        }
+                        List<TaskParallel> resultTaskStatus = frontTaskUser.stream().filter(f -> !f.getStatus().equals(2)).collect(Collectors.toList());
+                        if (resultTaskStatus.size() > 0) {
+                            String names = resultTaskStatus.stream().map(TaskParallel::getTaskUserName).collect(Collectors.joining("、"));
+                            throw new ServiceException("当前任务【" + task.getTaskName() + "】还有【" + names + "】未完成审批,请您稍后再试");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * 获取当前合同段的上报批次
      *
@@ -482,7 +580,7 @@ public class TaskController extends BladeController {
         this.integrationMethod(queryVO, masterTaskMap, parallelMap, parallelProcessInstanceIds, "1");
 
         //如果为空直接返回
-        if (masterTaskMap.size() == 0 && parallelMap.size() == 0) {
+        if (masterTaskMap.size() == 0 && parallelMap.size() == 0 && ObjectUtil.isNotEmpty(queryVO.getContractId()) && ObjectUtil.isNotEmpty(queryVO.getProjectId())) {
             this.sendsWebSocketCount(null, 2, queryVO);
             return R.data(null);
         }
@@ -494,9 +592,9 @@ public class TaskController extends BladeController {
         R<IPage<TaskVO>> iPageR = this.integrationMethod(queryVO, rObject, masterTaskMap, parallelMap, true);
 
         //推送
-        if (ObjectUtil.isNotEmpty(iPageR.getData()) && ObjectUtil.isNotEmpty(iPageR.getData().getRecords())) {
+        if (ObjectUtil.isNotEmpty(iPageR.getData()) && ObjectUtil.isNotEmpty(iPageR.getData().getRecords()) && ObjectUtil.isNotEmpty(queryVO.getContractId()) && ObjectUtil.isNotEmpty(queryVO.getProjectId())) {
             this.sendsWebSocketCount(iPageR, 1, queryVO);
-        } else {
+        } else if (ObjectUtil.isNotEmpty(queryVO.getContractId()) && ObjectUtil.isNotEmpty(queryVO.getProjectId())) {
             this.sendsWebSocketCount(null, 2, queryVO);
         }
         return iPageR;

+ 4 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java

@@ -65,6 +65,10 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
         pageVoList.forEach(vos -> {
             vos.setIsApprovalValue(new Integer("0").equals(vos.getStatus()) ? "未上报" : new Integer("1").equals(vos.getStatus()) ? "待审批" : new Integer("2").equals(vos.getStatus()) ? "已审批" : "已废除");
             vos.setIsCertificationValue(new Integer("1").equals(vos.getIsCertification()) ? "已认证" : "未认证");
+            if (vos.getIsCertificationValue().equals("已认证") && StringUtils.isNotEmpty(vos.getEVisaFile())){
+                vos.setPdfFileUrl(vos.getEVisaFile());
+                vos.setFileUrl(vos.getEVisaFile());
+            }
             if (StringUtils.isNotEmpty(vos.getSheetSource())) {
                 sheetSourceList.forEach(source -> {
                     if (source.getDictKey().equals(vos.getSheetSource())) {

+ 6 - 0
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/feign/EVisaClientImpl.java

@@ -8,6 +8,7 @@ import org.springblade.evisa.service.EVisaService;
 import org.springblade.evisa.vo.CertBeanVO;
 import org.springblade.evisa.vo.EVisaMakeSealVO;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
+import org.springblade.evisa.vo.TaskArchiveDTO;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
@@ -46,6 +47,11 @@ public class EVisaClientImpl implements EVisaClient {
         return this.eVisaService.eVisa(task);
     }
 
+    @Override
+    public void eVisaCustom(org.springblade.evisa.vo.TaskArchiveDTO eVisaObj) {
+        this.eVisaService.eVisaCustom(eVisaObj);
+    }
+
     @Override
     public String createSeal(EVisaMakeSealVO vo) {
         return this.eVisaService.createSeal(vo);

+ 5 - 0
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/EVisaService.java

@@ -23,6 +23,11 @@ public interface EVisaService {
      */
     String eVisa(EVisaTaskApprovalVO task);
 
+    /**
+     * 电签(档案-批量自定义)
+     */
+    void eVisaCustom(org.springblade.evisa.vo.TaskArchiveDTO eVisaObj);
+
     /**
      * 创建印模
      */

+ 180 - 20
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -23,29 +23,34 @@ import cfca.paperless.dto.response.responsebody.tx40.VerifyPdfSealResponseBody;
 import cfca.paperless.dto.response.tx20.MakeSealResponse;
 import cfca.paperless.dto.response.tx40.CompoundSealPdfListDetachedResponse;
 import cfca.paperless.dto.response.tx40.VerifyPdfSealResponse;
+import cfca.sadk.com.itextpdf.styledxmlparser.jsoup.helper.DataUtil;
 import cn.hutool.core.io.file.FileReader;
 import com.alibaba.fastjson.JSONObject;
 import lombok.AllArgsConstructor;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.entity.Task;
 import org.springblade.business.feign.TaskClient;
 import org.springblade.business.vo.TaskApprovalVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.constant.EVisaConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.secure.utils.SecureUtil;
+import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.evisa.redissionUtil.DistributedRedisLock;
 import org.springblade.evisa.service.EVisaService;
-import org.springblade.evisa.vo.EVisaMakeSealVO;
-import org.springblade.evisa.vo.EVisaTaskApprovalVO;
-import org.springblade.evisa.vo.SealPdfVO;
-import org.springblade.evisa.vo.SealStrategyVO;
+import org.springblade.evisa.vo.*;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.SignPfxFile;
 import org.springblade.manager.feign.ContractClient;
@@ -57,6 +62,8 @@ import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
@@ -70,10 +77,8 @@ import javax.imageio.stream.ImageOutputStream;
 import java.awt.image.BufferedImage;
 import java.io.*;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -103,6 +108,8 @@ public class EVisaServiceImpl implements EVisaService {
 
     private final ContractClient contractClient;
 
+    private final JdbcTemplate jdbcTemplate;
+
     @Autowired
     StringRedisTemplate RedisTemplate;
 
@@ -376,14 +383,14 @@ public class EVisaServiceImpl implements EVisaService {
                 if (result != null) {
                     if (result[0] != null) {
 
-                      //MultipartFile newFiles = new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "text/plain", IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0])));
+                        //MultipartFile newFiles = new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "text/plain", IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0])));
 
                         byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
-                        String dataUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/pdf/"+SnowFlakeUtil.getId() + ".pdf";
-                        File file1 =new File(dataUrl);
-                        FileUtil.copy(byteArray,file1);
+                        String dataUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/pdf/" + SnowFlakeUtil.getId() + ".pdf";
+                        File file1 = new File(dataUrl);
+                        FileUtil.copy(byteArray, file1);
                         //重新上传
-                        BladeFile bladeFile = this.newIOSSClient.uploadFile(SnowFlakeUtil.getId() + ".pdf",dataUrl);
+                        BladeFile bladeFile = this.newIOSSClient.uploadFile(SnowFlakeUtil.getId() + ".pdf", dataUrl);
                         if (bladeFile != null) {
                             resultMessage = SUCCESS + "@@@@" + bladeFile.getLink();
                         } else {
@@ -407,6 +414,156 @@ public class EVisaServiceImpl implements EVisaService {
         return resultMessage;
     }
 
+    /**
+     * 自定义签章-电签信息
+     *
+     * @param taskArchiveDTO
+     */
+    public void eVisaCustom(org.springblade.evisa.vo.TaskArchiveDTO taskArchiveDTO) {
+        //type=1表示任务审批自定义签章,type=2表示认证电签签章(不涉及审批任务)
+        if (taskArchiveDTO.getSealStrategy().size() > 0 && taskArchiveDTO.getType() == 1) {
+            //获取档案任务
+            Task task = jdbcTemplate.queryForObject("select form_data_id from u_task where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(Task.class));
+            if (task != null) {
+                //获取档案任务的文件信息
+                ArchiveFile archiveFile = jdbcTemplate.queryForObject("select pdf_file_url,e_visa_file from u_archive_file where id = " + task.getFormDataId(), new BeanPropertyRowMapper<>(ArchiveFile.class));
+                if (archiveFile != null && archiveFile.getPdfFileUrl() != null) {
+                    String signPdfUrl;
+                    if (ObjectUtil.isNotEmpty(archiveFile.getEVisaFile())) {
+                        //如果e_visa_file有值,那么证明之前有过其他人进行电签,那么获取e_visa_file进行追加电签
+                        signPdfUrl = archiveFile.getEVisaFile();
+                    } else {
+                        //否则使用原始pdf_file_url电签
+                        signPdfUrl = archiveFile.getPdfFileUrl();
+                    }
+
+                    try {
+                        //准备签章策略
+                        SealPdfVO pdfVO = new SealPdfVO();
+                        //获取当前用户的CA签字体证书信息、封装签章位置信息
+                        List<TaskArchiveDTO.Sign> signList = taskArchiveDTO.getSealStrategy();
+                        List<SealStrategyVO> sealStrategyVOS = new ArrayList<>();
+                        for (TaskArchiveDTO.Sign index : signList) {
+                            if (ObjectUtil.isNotEmpty(index.getUrl())) { //CA签字体证书不为空才签章
+                                SealStrategyVO signVO = new SealStrategyVO();
+                                signVO.setIsCenterCoordinate("1"); //左上角为原点
+                                signVO.setSealCode(EVisaConstant.SIGN_SEAL_CODE + SecureUtil.getUserId());
+                                signVO.setSealPassword(SecureUtil.getUserId().toString().substring(0, EVisaConstant.USER_ID_SUB));
+                                signVO.setSealPerson(SecureUtil.getNickName());
+
+                                //位置信息
+                                signVO.setImageUrl(index.getUrl()); //CA签字体
+                                signVO.setSealType("2");//坐标签章
+                                signVO.setLx(index.getLx()); //x轴
+                                signVO.setLy(index.getLy()); //y轴
+                                signVO.setPage(index.getPage()); //page页码
+                                sealStrategyVOS.add(signVO);
+                            }
+                        }
+                        pdfVO.setStrategyVoList(sealStrategyVOS);
+
+                        //获取档案pdfUrl
+                        byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(signPdfUrl));
+
+                        //TODO ========== 执行电签 ==========
+                        Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
+
+                        //返回结果集
+                        if (result != null) {
+                            if (result[0] != null) {
+                                byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
+
+                                /*String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
+                                File file1 = new File(dataUrl);
+                                FileUtils.writeByteArrayToFile(file1, byteArray);*/
+
+                                BladeFile bladeFile = this.newIOSSClient.updateFile(byteArray, SnowFlakeUtil.getId() + ".pdf");
+                                if (bladeFile != null) {
+                                    //更新最新的电签pdfUrl
+                                    jdbcTemplate.execute("update u_archive_file set e_visa_file = '" + bladeFile.getLink() + "' where id = " + task.getFormDataId());
+                                    String successMsg = SUCCESS + "@@@@" + bladeFile.getLink();
+                                    logger.info(successMsg);
+                                }
+                            }
+                        }
+                    } catch (Exception e) {
+                        logger.error(e.getMessage());
+                        e.printStackTrace();
+                    }
+                }
+            }
+        } else if (taskArchiveDTO.getSealStrategy().size() > 0 && taskArchiveDTO.getType() == 2) {
+            //此时的taskArchiveDTO.taskId=档案数据业务id(档案认证不涉及审批流任务)
+            //获取档案任务的文件信息(这里根据id再查询一次,入参的时候不想重新构造入参的dto了)
+            ArchiveFile archiveFile = jdbcTemplate.queryForObject("select pdf_file_url,e_visa_file from u_archive_file where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(ArchiveFile.class));
+            if (archiveFile != null && archiveFile.getPdfFileUrl() != null) {
+                String signPdfUrl;
+                if (ObjectUtil.isNotEmpty(archiveFile.getEVisaFile())) {
+                    //如果e_visa_file有值,那么证明之前有过其他人进行电签,那么获取e_visa_file进行追加电签
+                    signPdfUrl = archiveFile.getEVisaFile();
+                } else {
+                    //否则使用原始pdf_file_url电签
+                    signPdfUrl = archiveFile.getPdfFileUrl();
+                }
+
+                try {
+                    //准备签章策略
+                    SealPdfVO pdfVO = new SealPdfVO();
+                    //获取当前用户的CA签字体证书信息、封装签章位置信息
+                    List<TaskArchiveDTO.Sign> signList = taskArchiveDTO.getSealStrategy();
+                    List<SealStrategyVO> sealStrategyVOS = new ArrayList<>();
+                    for (TaskArchiveDTO.Sign index : signList) {
+                        if (ObjectUtil.isNotEmpty(index.getUrl())) { //CA签字体证书不为空才签章
+                            SealStrategyVO signVO = new SealStrategyVO();
+                            signVO.setIsCenterCoordinate("1"); //左上角为原点
+                            signVO.setSealCode(EVisaConstant.SIGN_SEAL_CODE + SecureUtil.getUserId());
+                            signVO.setSealPassword(SecureUtil.getUserId().toString().substring(0, EVisaConstant.USER_ID_SUB));
+                            signVO.setSealPerson(SecureUtil.getNickName());
+
+                            //位置信息
+                            signVO.setImageUrl(index.getUrl()); //CA签字体
+                            signVO.setSealType("2");//坐标签章
+                            signVO.setLx(index.getLx()); //x轴
+                            signVO.setLy(index.getLy()); //y轴
+                            signVO.setPage(index.getPage()); //page页码
+                            sealStrategyVOS.add(signVO);
+                        }
+                    }
+                    pdfVO.setStrategyVoList(sealStrategyVOS);
+
+                    //获取档案pdfUrl
+                    byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(signPdfUrl));
+
+                    //TODO ========== 执行电签 ==========
+                    Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
+
+                    //返回结果集
+                    if (result != null) {
+                        if (result[0] != null) {
+                            byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
+
+                            /*String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
+                            File file1 = new File(dataUrl);
+                            FileUtils.writeByteArrayToFile(file1, byteArray);*/
+
+                            BladeFile bladeFile = this.newIOSSClient.updateFile(byteArray, SnowFlakeUtil.getId() + ".pdf");
+                            if (bladeFile != null) {
+                                //更新最新的认证电签pdfUrl
+                                jdbcTemplate.execute("update u_archive_file set is_certification = 1,e_visa_file = '" + bladeFile.getLink() + "',certification_time = '" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss") + "' where id = " + taskArchiveDTO.getTaskId());
+                                String successMsg = SUCCESS + "@@@@" + bladeFile.getLink();
+                                logger.info(successMsg);
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    logger.error(e.getMessage());
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+
     /**
      * 东方 中讯
      *
@@ -605,12 +762,15 @@ public class EVisaServiceImpl implements EVisaService {
                     //对图片进行扣白底
                     imageData = ImageUtil.transferAlpha(imageData);
 
-                    //设置大小
-                    if (vo.isCompanySeal()) {
-                        imageData = ImageUtil.resizeImage(imageData, 540, 540);
-                    } else {
-                        imageData = ImageUtil.resizeImage(imageData, 480, 132);
-//                        imageData = ImageUtil.resizeImage(imageData,540,540);
+                    //设置大小(首先排查档案水印章,因为水印章要保持原样)
+                    if (!vo.getImageUrl().equals("https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230911/5b42583d931664b785ebf481c37d17bc.png")) {
+                        if (vo.isCompanySeal()) {
+                            //合同章
+                            imageData = ImageUtil.resizeImage(imageData, 540, 540);
+                        } else {
+                            //非合同章
+                            imageData = ImageUtil.resizeImage(imageData, 480, 132);
+                        }
                     }
 
                     //图片dpi设置
@@ -635,7 +795,7 @@ public class EVisaServiceImpl implements EVisaService {
                     sealStrategy.setOffsetX(vo.getOffSetX());
                     sealStrategy.setOffsetY(vo.getOffSetY());
                 } else if (vo.getSealType().equals("2")) {
-                    //设置PDF坐标原点,签章图片定位点   默认为PDF左下角,签章图片定位为左下角
+                    //设置PDF坐标原点,签章图片定位点默认为PDF左下角,签章图片定位为左下角
                     if (StringUtils.isNotEmpty(vo.getIsCenterCoordinate())) {
                         sealStrategy.setIsCenterCoordinate(vo.getIsCenterCoordinate());
                     }