Browse Source

Merge branch 'refs/heads/feature-lihb-20250725' into test-merge

# Conflicts:
#	blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java
#	blade-service/blade-user/src/main/java/org/springblade/system/user/util/RsaUtils.java
LHB 2 weeks ago
parent
commit
9e040e5717

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/InformationQuery.java

@@ -137,4 +137,10 @@ public class InformationQuery extends BaseEntity {
 
     @ApiModelProperty("节点pdf")
     private String nodePdfUrl;
+
+    @ApiModelProperty("重刷状态 0-待重刷,1-正在重刷,2-重刷成功,3-重刷失败")
+    private Integer saveAgain;
+
+    @ApiModelProperty("重刷次数:如果次数大于5次 每次都是3,就停止重刷")
+    private Integer saveAgainCount;
 }

+ 2 - 1
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java

@@ -185,5 +185,6 @@ public interface IUserClient {
     @GetMapping(API_PREFIX + "/clearContractLocalCacheAndRedisCache")
     void clearContractLocalCacheAndRedisCache();
 
-
+    @GetMapping(API_PREFIX + "/getTokenByUser")
+    String getTokenByUser(@RequestParam String account);
 }

+ 5 - 35
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -139,12 +139,6 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
 
     @Autowired
     StringRedisTemplate RedisTemplate;
-    @Autowired
-    private BladeRedis bladeRedis;
-    //异步类
-    @Autowired
-    private TaskSync taskSync;
-
 
 
     private final ITrialSelfInspectionRecordService iTrialSelfInspectionRecordService;
@@ -1988,37 +1982,13 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
     }*/
         @Override
         public R reSigningEVisaStatus0(List<reSigningEVisaStatus> dtos, String header) throws Exception {
-         R result= new R();
          if(dtos.size()>0){
-
-             //添加缓存
              Set<Long> newIds = dtos.stream().map(reSigningEVisaStatus::getId).collect(Collectors.toSet());
-
-             //随机id
-             String s = "sign-reSigningEVisaStatus0:" + SnowFlakeUtil.getId();
-
-             //数据效验
-             Set<Long> oldIds = new HashSet<>();
-             Set<String> keys = bladeRedis.keys("sign-reSigningEVisaStatus0*");
-             for (String key : keys) {
-                 Set<Long> ids = bladeRedis.get(key);
-                 if(ids !=null ){
-                     oldIds.addAll(ids);
-                 }
-             }
-
-             if(CollectionUtils.isNotEmpty(oldIds)){
-                 //如果旧的id中存在新的id,则不允许添加
-                 long count = oldIds.stream().filter(f -> newIds.contains(f)).count();
-                 if(count > 0){
-                     return R.fail("当前提交数据中存在正在保存的数据,请勿重复提交");
-                 }
-             }
-             //10分钟过期
-             bladeRedis.setEx(s,newIds, 600L);
-
-             //执行异步
-             taskSync.reSigningEVisaStatusSync(dtos,header,s);
+             //正在重刷的不允许再次重刷
+             informationQueryService.update(Wrappers.<InformationQuery>update().lambda()
+                     .set(InformationQuery::getSaveAgain, 0)
+                     .ne(InformationQuery::getSaveAgain, 1)
+                     .in(InformationQuery::getId, newIds));
         }
          return R.success("操作成功");
     }

+ 128 - 32
blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java

@@ -1,7 +1,13 @@
 package org.springblade.business.sync;
 
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springblade.business.dto.reSigningEVisaStatus;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.service.IInformationQueryFileService;
@@ -9,60 +15,150 @@ import org.springblade.business.service.IInformationQueryService;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsTreeSynchronousRecord;
 import org.springblade.manager.feign.ExcelTabClient;
+import org.springblade.system.user.feign.IUserClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.stream.Collectors;
 
 /**
  * @author LHB
  */
 @Component
 @AllArgsConstructor
+@Slf4j
 public class TaskSync {
 
     private final IInformationQueryService informationQueryService;
-
     private final ExcelTabClient excelTabClient;
-    @Autowired
-    private BladeRedis bladeRedis;
-    @Async("taskExecutor1")
-    public void reSigningEVisaStatusSync(List<reSigningEVisaStatus> dtos, String header,String s) {
-        R result= null;
-        try {
-            for (reSigningEVisaStatus dto : dtos) {
-                InformationQuery iq = informationQueryService.getById(dto.getId());
-                if(iq!=null){
-                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                            .eq(InformationQuery::getId, dto.getId())
-                            .set(InformationQuery::getEVisaPdfUrl, null)
-                            .set(InformationQuery::getPdfUrl, null));
+    // 线程池
+    @Resource(name = "taskExecutor1")
+    private ThreadPoolExecutor executor;
+
+    //用户
+    @Resource
+    private IUserClient userClient;
+
+
+    public void reSigningEVisaStatusSync(List<InformationQuery> dtos, String header) {
+        log.info("数据正在重刷,线程名称:{}", Thread.currentThread().getName());
+
+        for (InformationQuery dto : dtos) {
+            informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                    .eq(InformationQuery::getId, dto.getId())
+                    .set(InformationQuery::getEVisaPdfUrl, null)
+                    .set(InformationQuery::getUpdateTime, DateTime.now())
+
+                    .set(InformationQuery::getPdfUrl, null));
+            R result = this.saveNodePdf(dto.getClassify() + "", dto.getWbsId() + "", dto.getContractId() + "", dto.getProjectId() + "", header);
+
+            LambdaUpdateWrapper<InformationQuery> lambda = Wrappers.<InformationQuery>update().lambda();
+            if (result == null || result.getCode() != 200) {
+                //重签失败
+                lambda.set(InformationQuery::getSaveAgain, 3)
+                        .set(InformationQuery::getEVisaPdfUrl, dto.getEVisaPdfUrl())
+                        .setSql("save_again_count = save_again_count + 1")
+                        .set(InformationQuery::getPdfUrl, dto.getPdfUrl());
+            } else {
+                //成功重签
+                lambda.set(InformationQuery::getSaveAgain, 2);
+            }
+            lambda.set(InformationQuery::getUpdateTime, DateTime.now());
+            lambda.eq(InformationQuery::getId, dto.getId());
+
+            informationQueryService.update(lambda);
+        }
+        log.info("数据重刷完毕,线程名称:{}", Thread.currentThread().getName());
+    }
+
+
+    /**
+     * 定时检查save-again = 1 的数据 查看更新时间与当前时间是否超过30分钟,如果超过 30分钟,则修改状态为0
+     * 一个小时检查一次
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void updateStuckTask(){
+        List<InformationQuery> list = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery()
+                .eq(InformationQuery::getSaveAgain, 1)
+                .eq(InformationQuery::getIsDeleted, 0));
+
+        List<Long> ids = new ArrayList<>();
+        for (InformationQuery informationQuery : list) {
+            //更新时间 + 半个小时 < 当前时间
+            if (informationQuery.getUpdateTime().getTime() + 1800000 < System.currentTimeMillis()) {
+                ids.add(informationQuery.getId());
+            }
+        }
+        informationQueryService.update(null, Wrappers.<InformationQuery>lambdaUpdate()
+                .set(InformationQuery::getSaveAgain, 0)
+                .in(InformationQuery::getId, ids));
+    }
+
+
+    /**
+     * 重刷定时任务 使用多线程的方式去跑
+     */
+    @Scheduled(fixedDelay = 60000)
+    public void saveAgainTask() {
+        //获取token
+        String header = userClient.getTokenByUser("admin");
+
+        List<InformationQuery> list = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery()
+                .in(InformationQuery::getSaveAgain, 0, 3)
+                .eq(InformationQuery::getIsDeleted, 0)
+                //失败重刷次数小于5次
+                .lt(InformationQuery::getSaveAgainCount, 5)
+                .last("limit 50"));
+        if(CollectionUtils.isEmpty(list)){
+            return;
+        }
+
+        List<List<InformationQuery>> partition = Lists.partition(list, 10);
+
+        for (List<InformationQuery> informationQueries : partition) {
+            List<Long> collect = informationQueries.stream().map(InformationQuery::getId).collect(Collectors.toList());
+            //修改状态之后开始重刷
+            boolean update = informationQueryService.update(Wrappers.<InformationQuery>update().lambda()
+                    .set(InformationQuery::getSaveAgain, 1)
+                    .set(InformationQuery::getUpdateTime, DateTime.now())
+                    .in(InformationQuery::getId, collect));
+            if (update) {
+                CompletableFuture.runAsync(() -> {
                     try {
-                        result = this.saveNodePdf(iq.getClassify() + "", iq.getWbsId() + "", dto.getContractId() + "", dto.getProjectId() + "", header);
-                        if (result == null || (result != null && result.getCode() != 200)) {
-                           throw new ServiceException(iq.getName() + "重新保存PDF信息失败");
-                        }
+                        /*===============执行批量任务===============*/
+                        this.reSigningEVisaStatusSync(informationQueries, header);
                     } catch (Exception e) {
-                        e.printStackTrace();
-                        //如果失败 修改pdf和e_visa_pdf_url 路径
-                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                                .eq(InformationQuery::getId, dto.getId())
-                                .set(InformationQuery::getEVisaPdfUrl, iq.getEVisaPdfUrl())
-                                .set(InformationQuery::getPdfUrl, iq.getPdfUrl()));
+                        log.error("执行重刷任务失败,任务ID列表:{}", collect, e);
+                        // 可选:回滚状态或标记为失败
                     }
-                }
+                }, executor).exceptionally(throwable -> {
+                    log.error("异步任务执行异常,任务ID列表:{}", collect, throwable);
+                    return null;
+                });
             }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }finally {
-            //删除缓f存
-            bladeRedis.del(s);
         }
+        log.info("队列数量{}", executor.getQueue().size());
+        log.info("活跃数量{}", executor.getActiveCount());
+        log.info("总共数量{}", executor.getTaskCount());
+        log.info("完成数量{}", executor.getCompletedTaskCount());
     }
 
-    R saveNodePdf(String classify, String nodePKeyIds, String contractId, String projectId, String header) throws Exception {
-        return excelTabClient.synPDFInfo(contractId, nodePKeyIds, classify, projectId, header);
+
+    R saveNodePdf(String classify, String nodePKeyIds, String contractId, String projectId, String header) {
+        try {
+            return excelTabClient.synPDFInfo(contractId, nodePKeyIds, classify, projectId, header);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
     }
 }

+ 64 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@@ -751,4 +751,68 @@ public class UserController {
         }
         return this.getLoginInfo(Authorization, userInfo);
     }
+
+
+    /**
+     * 项目内部获取用户接口
+     * @param account
+     * @param type
+     * @param tenantId
+     * @param request
+     * @return
+     */
+    @PostMapping("/loginByToken4")
+    @ApiOperationSupport(order = 20)
+    @ApiOperation(value = "token验证加密", notes = "token验证登录")
+    public R loginByToken4(String account,Integer type, String tenantId, HttpServletRequest request) {
+        if(account==null || Func.isNull(account) || Func.isEmpty(account)){
+            return R.fail("account值不能为空");
+        }
+        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("account", account);
+        queryWrapper.eq("sys_type", type == null ? 2 : type);
+        if(StringUtil.isNotBlank(tenantId)){
+            queryWrapper.eq("tenant_id", tenantId);
+        }
+        queryWrapper.last("limit 1");
+        User userInfo = userService.getOne(queryWrapper);
+        if (userInfo == null) {
+            return R.fail("用户名或密码错误");
+        }
+
+        String Authorization = request == null ? null : request.getHeader("Authorization");
+
+        if (Authorization == null || StringUtil.isEmpty(Authorization)) {
+            String useType = userInfo.getUserType();
+            List<String> strList = Func.toStrList(useType);
+            for(String sys_id:strList){
+                String dataInfo = "";
+                if(sys_id.equals("1")){ //质量/试验平台
+                    dataInfo ="client:client_secret";
+                }else if(sys_id.equals("2")){ //APP端
+                    dataInfo ="uni-app:app_secret";
+                }else if(sys_id.equals("3")){ //档案平台"
+                    dataInfo ="archives:archives_secret";
+                }else if(sys_id.equals("4")){ //后台管理端"
+                    dataInfo ="saber:saber_secret";
+                }else if(sys_id.equals("5")){ //成本管控系统"
+                    dataInfo ="hac:hac_secret";
+                }else if(sys_id.equals("6")){ //征拆系统"
+                    dataInfo ="lar:lar_secret";
+                }else if(sys_id.equals("7")){ //计量系统"
+                    dataInfo ="measure:measure_secret";
+                }else if(sys_id.equals("8")){ //安全系统"
+                    dataInfo ="measure:measure_secret";
+                }
+                Authorization = "Basic "+Func.encodeBase64(dataInfo);
+                //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+                //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+                R loginInfo = this.getLoginInfo(Authorization, userInfo);
+                if(loginInfo.getCode()==200){
+                    return loginInfo;
+                }
+            }
+        }
+        return this.getLoginInfo(Authorization,userInfo);
+    }
 }

+ 14 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java

@@ -16,12 +16,15 @@
  */
 package org.springblade.system.user.feign;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
+import org.springblade.system.user.bean.ResultCYData;
+import org.springblade.system.user.controller.UserController;
 import org.springblade.system.user.dto.UserDTO;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.entity.UserInfo;
@@ -46,6 +49,7 @@ import java.util.List;
 public class UserClient implements IUserClient {
 
     private final IUserService service;
+    private final UserController userController;
 
     @Override
     public List<User> findUserInfoList() {
@@ -149,5 +153,15 @@ public class UserClient implements IUserClient {
         service.clearContractLocalCacheAndRedisCache();
     }
 
+    @Override
+    public String getTokenByUser(String account) {
+        R r = userController.loginByToken4(account, 1,"000000",null);
+        if(r.isSuccess()){
+            JSONObject data = (JSONObject) r.getData();
+            return (String) data.get("access_token");
+        } else {
 
+            return null;
+        }
+    }
 }