caozixuan 3 rokov pred
rodič
commit
8ab2c88c4c
29 zmenil súbory, kde vykonal 1085 pridanie a 50 odobranie
  1. 1 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamPaperStructureServiceImpl.java
  2. 18 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncSysUserDataImportService.java
  3. 68 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncUserPushService.java
  4. 153 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/push/AsyncPushTaskTemplate.java
  5. 7 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/TaskLogicService.java
  6. 34 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java
  7. 19 2
      distributed-print/src/main/java/com/qmth/distributed/print/api/SysUserController.java
  8. 51 0
      distributed-print/src/test/java/com/qmth/distributed/print/SyncHelpTest.java
  9. 18 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/annotation/DBVerify.java
  10. 43 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/PushBeforeRoleParam.java
  11. 98 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/UserPushParam.java
  12. 35 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/result/DBVerifyResult.java
  13. 1 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/config/DictionaryConfig.java
  14. 38 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java
  15. 20 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/domain/SyncDataDomain.java
  16. 26 4
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/PushUserError.java
  17. 3 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/TaskTypeEnum.java
  18. 27 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/userPush/BeforeJudgeEnum.java
  19. 1 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/userPush/SpecialPrivilegeEnum.java
  20. 2 2
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/mapper/PushUserErrorMapper.java
  21. 12 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/CallApiOrgCenterService.java
  22. 2 2
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/PushUserErrorService.java
  23. 40 2
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/SysUserService.java
  24. 43 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/CallApiOrgCenterServiceImpl.java
  25. 0 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/OrgCenterDataDisposeServiceImpl.java
  26. 4 4
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/PushUserErrorServiceImpl.java
  27. 43 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysRoleServiceImpl.java
  28. 277 27
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysUserServiceImpl.java
  29. 1 1
      teachcloud-common/src/main/resources/mapper/PushUserErrorMapper.xml

+ 1 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamPaperStructureServiceImpl.java

@@ -61,7 +61,7 @@ public class ExamPaperStructureServiceImpl extends ServiceImpl<ExamPaperStructur
     @Lazy
     PrintCommonService printCommonService;
 
-    @Autowired
+    @Resource
     BasicAttachmentService basicAttachmentService;
 
     @Override

+ 18 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncSysUserDataImportService.java

@@ -4,24 +4,33 @@ import cn.hutool.core.date.DateUtil;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.distributed.print.business.templete.importData.AsyncImportTaskTemplete;
 import com.qmth.distributed.print.business.templete.service.TaskLogicService;
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
+import com.qmth.teachcloud.common.bean.params.UserSaveParams;
 import com.qmth.teachcloud.common.contant.SpringContextHolder;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.entity.TBTask;
 import com.qmth.teachcloud.common.enums.TaskResultEnum;
 import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import com.qmth.teachcloud.common.service.CallApiOrgCenterService;
+import com.qmth.teachcloud.common.service.SysUserService;
 import com.qmth.teachcloud.common.service.TBTaskService;
 import com.qmth.teachcloud.common.util.Result;
 import com.qmth.teachcloud.common.util.ResultUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.io.IOException;
 import java.io.InputStream;
 import java.text.MessageFormat;
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
 import java.util.StringJoiner;
+import java.util.stream.Collectors;
 
 /**
  * @Description: 系统用户批量导入
@@ -34,6 +43,9 @@ public class AsyncSysUserDataImportService extends AsyncImportTaskTemplete {
 
     public static final String OBJ_TITLE = "用户基本信息";
 
+    @Resource
+    private SysUserService sysUserService;
+
     @Override
     public Result importTask(Map<String, Object> map) throws IOException, Exception {
         TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
@@ -48,9 +60,13 @@ public class AsyncSysUserDataImportService extends AsyncImportTaskTemplete {
         try {
             TaskLogicService taskLogicService = SpringContextHolder.getBean(TaskLogicService.class);
 
-            // 执行导入基础学生数据
+            // 执行导入基础用户数据
             Map<String, Object> result = taskLogicService.executeImportSysUserLogic(map);
-
+            // 执行用户同步数据
+            SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
+            Long schoolId = sysUser.getSchoolId();
+            List<UserPushParam> userPushParamList = (List<UserPushParam>) result.get("userPushParamList");
+            sysUserService.userPushService(userPushParamList,sysUser);
 
             stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), FINISH_TITLE, Long.valueOf(String.valueOf(result.get("dataCount"))), FINISH_SIZE));
             tbTask.setResult(TaskResultEnum.SUCCESS);

+ 68 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncUserPushService.java

@@ -0,0 +1,68 @@
+package com.qmth.distributed.print.business.templete.execute;
+
+import cn.hutool.core.date.DateUtil;
+import com.qmth.boot.api.exception.ApiException;
+import com.qmth.distributed.print.business.templete.push.AsyncPushTaskTemplate;
+import com.qmth.distributed.print.business.templete.service.TaskLogicService;
+import com.qmth.teachcloud.common.contant.SpringContextHolder;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.enums.TaskResultEnum;
+import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import com.qmth.teachcloud.common.service.TBTaskService;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.StringJoiner;
+
+/**
+ * @Description: 用户推送模板(异步任务)
+ * @Author: CaoZixuan
+ * @Date: 2021-10-31
+ */
+@Service
+public class AsyncUserPushService extends AsyncPushTaskTemplate {
+
+    private final static Logger log = LoggerFactory.getLogger(AsyncSysUserDataImportService.class);
+
+    public static final String OBJ_TITLE = "用户信息";
+
+    @Override
+    public Result pushTask(Map<String, Object> map) throws Exception {
+        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
+
+
+        StringJoiner stringJoinerSummary = new StringJoiner("\n")
+                .add(MessageFormat.format("{0}{1}{2}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), BEGIN_TITLE, OBJ_TITLE));
+        tbTask.setStatus(TaskStatusEnum.RUNNING);
+        TBTaskService tbTaskService = SpringContextHolder.getBean(TBTaskService.class);
+        tbTaskService.updateById(tbTask);
+        try {
+            TaskLogicService taskLogicService = SpringContextHolder.getBean(TaskLogicService.class);
+
+            // 执行需要重新同步的用户同步数据
+            Map<String, Object> result = taskLogicService.executeUserPushLogic(map);
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), FINISH_TITLE, Long.valueOf(String.valueOf(result.get("count"))),SUCCESS_TITLE,Long.valueOf(String.valueOf(result.get("correct"))), FINISH_SIZE));
+            tbTask.setResult(TaskResultEnum.SUCCESS);
+        }catch (Exception e){
+            log.error("请求出错", e);
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_TITLE, EXCEPTION_DATA, e.getMessage()));
+            tbTask.setResult(TaskResultEnum.ERROR);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        } finally {//生成txt文件
+            tbTask.setSummary(stringJoinerSummary.toString());
+            super.createTxt(tbTask);
+        }
+        return ResultUtil.ok(map);
+    }
+}

+ 153 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/push/AsyncPushTaskTemplate.java

@@ -0,0 +1,153 @@
+package com.qmth.distributed.print.business.templete.push;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.qmth.boot.api.exception.ApiException;
+import com.qmth.distributed.print.business.templete.importData.AsyncImportTaskTemplete;
+import com.qmth.teachcloud.common.contant.SpringContextHolder;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.enums.TaskResultEnum;
+import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import com.qmth.teachcloud.common.enums.TaskTypeEnum;
+import com.qmth.teachcloud.common.enums.UploadFileEnum;
+import com.qmth.teachcloud.common.service.TBTaskService;
+import com.qmth.teachcloud.common.util.FileStoreUtil;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+/**
+ * @Description: 异步推送模板
+ * @Author: CaoZixuan
+ * @Date: 2021-10-31
+ */
+public abstract class AsyncPushTaskTemplate {
+    private final static Logger log = LoggerFactory.getLogger(AsyncPushTaskTemplate.class);
+
+    public static final String BEGIN_TITLE = "->开始准备处理同步的";
+    public static final String EXCEPTION_TITLE = "->数据处理发生异常!";
+    public static final String EXCEPTION_DATA = "错误信息:";
+    public static final String FINISH_TITLE = "->数据处理结束,共处理了";
+    public static final String SUCCESS_TITLE = "->其中成功处理了";
+    public static final String FINISH_SIZE = "条数据";
+    public static final String TXT_PREFIX = ".txt";
+    public static final String EXCEPTION_CREATE_TXT_TITLE = "->创建导出日志时发生异常!";
+
+    /**
+     * 异步导入任务
+     *
+     * @param map
+     * @return
+     * @throws IOException
+     */
+    @Async
+    public abstract Result pushTask(Map<String, Object> map) throws IOException, Exception;
+
+    /**
+     * 创建txt文件
+     *
+     * @param tbTask
+     */
+    public void createTxt(TBTask tbTask) {
+//        OssUtil ossUtil = SpringContextHolder.getBean(OssUtil.class);
+        TBTaskService tbTaskService = SpringContextHolder.getBean(TBTaskService.class);
+        ByteArrayOutputStream out = null;
+        InputStream inputStream = null;
+        try {
+            JSONObject jsonObject = JSONObject.parseObject(tbTask.getImportFilePath());
+            if (Objects.isNull(jsonObject)) {
+                jsonObject = new JSONObject();
+                LocalDateTime nowTime = LocalDateTime.now();
+                StringJoiner stringJoiner = new StringJoiner("");
+                stringJoiner.add(UploadFileEnum.FILE.getTitle()).add(File.separator);
+                stringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
+                        .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
+                        .add(String.format("%02d", nowTime.getDayOfMonth()))
+                        .add(File.separator).add(SystemConstant.getUuid()).add(TXT_PREFIX);
+                jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
+                jsonObject.put(SystemConstant.PATH, stringJoiner.toString());
+            }
+            String path = (String) jsonObject.get(SystemConstant.PATH);
+            path = path.replaceAll("\\\\","/");
+            String type = (String) jsonObject.get(SystemConstant.TYPE);
+
+            out = new ByteArrayOutputStream();
+            out.write(tbTask.getSummary().getBytes(StandardCharsets.UTF_8));
+            byte[] bookByteAry = out.toByteArray();
+            inputStream = new ByteArrayInputStream(bookByteAry);
+            StringJoiner stringJoiner = new StringJoiner("");
+            if (tbTask.getType() == TaskTypeEnum.CREATE_PDF) {
+                path = path.replaceAll(UploadFileEnum.PDF.getTitle(), UploadFileEnum.FILE.getTitle());
+            }
+
+            if (Objects.equals(type, SystemConstant.OSS)) {//上传至oss
+                path = path.substring(0, path.lastIndexOf("/") + 1);
+                stringJoiner.add(path).add(SystemConstant.getUuid()).add(TXT_PREFIX).toString();
+                FileStoreUtil fileStoreUtil = SpringContextHolder.getBean(FileStoreUtil.class);
+                fileStoreUtil.ossUpload(stringJoiner.toString(), inputStream, DigestUtils.md5Hex(new ByteArrayInputStream(bookByteAry)), fileStoreUtil.getUploadEnumByPath(stringJoiner.toString()).getFssType());
+            } else {//上传至服务器
+                File finalFile = new File(stringJoiner.toString());
+                if (!finalFile.exists()) {
+                    finalFile.getParentFile().mkdirs();
+                    finalFile.createNewFile();
+                }
+                FileUtils.copyInputStreamToFile(inputStream, finalFile);
+            }
+            JSONObject json = new JSONObject();
+            json.put(SystemConstant.PATH, stringJoiner.toString());
+            json.put(SystemConstant.TYPE, type);
+            json.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
+
+            tbTask.setReportFilePath(json.toJSONString());
+        } catch (Exception e) {
+            log.error("请求出错", e);
+            StringJoiner stringJoinerSummary = new StringJoiner("").add(tbTask.getSummary()).add("\n");
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_CREATE_TXT_TITLE, EXCEPTION_DATA, e.getMessage()));
+            tbTask.setSummary(stringJoinerSummary.toString());
+            tbTask.setResult(TaskResultEnum.ERROR);
+//            TBTask dbTask = tbTaskService.getById(tbTask.getId());
+//            if (tbTask.getVersion() == dbTask.getVersion()) {
+//                tbTask.setResetCount(new AtomicInteger(tbTask.getResetCount()).incrementAndGet());
+//            }
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        } finally {
+            try {
+                if (Objects.nonNull(inputStream)) {
+                    inputStream.close();
+                }
+                if (Objects.nonNull(out)) {
+                    out.flush();
+                    out.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            tbTask.setStatus(TaskStatusEnum.FINISH);
+            if (tbTask.getType() == TaskTypeEnum.CREATE_PDF) {
+                tbTask.setResultFilePath(tbTask.getImportFilePath());
+                tbTask.setImportFileName(null);
+                tbTask.setImportFilePath(null);
+                tbTask.setErrorMessage(null);
+            }
+            tbTaskService.updateById(tbTask);
+        }
+    }
+}

+ 7 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/TaskLogicService.java

@@ -107,4 +107,11 @@ public interface TaskLogicService {
      * @throws Exception 异常
      */
     Map<String, Object> executeImportStatisticsLogic(Map<String, Object> map) throws Exception;
+
+    /**
+     * 用户推送异步任务处理方法
+     * @param map 任务源
+     * @return 结果
+     */
+    Map<String,Object> executeUserPushLogic(Map<String, Object> map) throws IllegalAccessException;
 }

+ 34 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java

@@ -23,11 +23,16 @@ import com.qmth.distributed.print.business.templete.service.TaskLogicService;
 import com.qmth.distributed.print.business.util.CreatePdfUtil;
 import com.qmth.distributed.print.business.util.HtmlToPdfUtil;
 import com.qmth.teachcloud.common.annotation.ExcelDBFieldDesc;
+import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.bean.dto.excel.*;
 import com.qmth.teachcloud.common.bean.params.ArraysParams;
+import com.qmth.teachcloud.common.bean.params.PushBeforeRoleParam;
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.*;
 import com.qmth.teachcloud.common.enums.*;
+import com.qmth.teachcloud.common.enums.userPush.BeforeJudgeEnum;
+import com.qmth.teachcloud.common.enums.userPush.SyncStatusEnum;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.*;
 import com.qmth.teachcloud.common.util.excel.ExcelError;
@@ -159,6 +164,9 @@ public class TaskLogicServiceImpl implements TaskLogicService {
     @Resource
     TCStatisticsTempService tcStatisticsTempService;
 
+    @Resource
+    SysUserRoleService sysUserRoleService;
+
     /**
      * 创建pdf前置条件
      *
@@ -1394,6 +1402,32 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         return map;
     }
 
+    @Transactional
+    @Override
+    public Map<String, Object> executeUserPushLogic(Map<String, Object> map) throws IllegalAccessException {
+        int correct = 0;
+        int count = 0;
+        SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
+        Long schoolId = sysUser.getSchoolId();
+        // 需要同步的用户
+        List<SysUser> sysUserList = sysUserService.list(new QueryWrapper<SysUser>().lambda()
+                .eq(SysUser::getSchoolId,schoolId)
+                .eq(SysUser::getSyncStatus, SyncStatusEnum.NEED_PUSH_AGAIN));
+        count = sysUserList.size();
+        for (SysUser user : sysUserList) {
+            Set<Long> roleIdSet = sysUserRoleService.listRoleByUserId(user.getId()).stream().map(BaseEntity::getId).collect(Collectors.toSet());
+            PushBeforeRoleParam pushBeforeRoleParam = new PushBeforeRoleParam(null, BeforeJudgeEnum.FORBIDDEN_NECESSARY);
+            List<UserPushParam> userPushParamList = sysUserService.analyzeUserPushSpecialPrivilege(user.getId(),user.getSchoolId(),user.getCode(), user.getRealName(),user.getPassword(),roleIdSet,pushBeforeRoleParam,user.getEnable());
+            boolean syncResult = sysUserService.userPushService(userPushParamList,sysUser);
+            if (syncResult){
+                correct ++;
+            }
+        }
+        map.put("correct",correct);
+        map.put("count",count);
+        return map;
+    }
+
 
     public String createTempNumber(SerialNumberParams serialNumberParams) {
         return convertUtil.getIncre(serialNumberParams.getPrefix(), serialNumberParams.getModel(), serialNumberParams.getDigit());

+ 19 - 2
distributed-print/src/main/java/com/qmth/distributed/print/api/SysUserController.java

@@ -6,6 +6,7 @@ import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.bean.result.EditResult;
 import com.qmth.distributed.print.business.service.PrintCommonService;
 import com.qmth.distributed.print.business.templete.execute.AsyncSysUserDataImportService;
+import com.qmth.distributed.print.business.templete.execute.AsyncUserPushService;
 import com.qmth.teachcloud.common.bean.params.UserSaveParams;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.SysUser;
@@ -54,6 +55,8 @@ public class SysUserController {
     private PrintCommonService printCommonService;
     @Resource
     private AsyncSysUserDataImportService asyncSysUserDataImportService;
+    @Resource
+    private AsyncUserPushService asyncUserPushService;
 
     /**
      * 查询
@@ -112,7 +115,7 @@ public class SysUserController {
      */
     @ApiOperation(value = "新增/修改")
     @RequestMapping(value = "/save", method = RequestMethod.POST)
-    public Result save(@ApiParam(value = "用户信息", required = true) @Valid @RequestBody UserSaveParams userSaveParams, BindingResult bindingResult) {
+    public Result save(@ApiParam(value = "用户信息", required = true) @Valid @RequestBody UserSaveParams userSaveParams, BindingResult bindingResult) throws IllegalAccessException {
         if (bindingResult.hasErrors()) {
             return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
         }
@@ -142,7 +145,7 @@ public class SysUserController {
      */
     @ApiOperation(value = "启用/禁用")
     @RequestMapping(value = "/enable", method = RequestMethod.POST)
-    public Result enable(@RequestBody SysUser user) throws NoSuchAlgorithmException {
+    public Result enable(@RequestBody SysUser user) throws NoSuchAlgorithmException, IllegalAccessException {
         return ResultUtil.ok(sysUserService.enable(user));
     }
 
@@ -194,5 +197,19 @@ public class SysUserController {
         TBTask tbTask = Objects.nonNull(map.get(SystemConstant.TASK)) ? (TBTask) map.get(SystemConstant.TASK) : null;
         return Objects.nonNull(tbTask) ? ResultUtil.ok(tbTask.getId()) : ResultUtil.error("创建任务失败");
     }
+
+    @ApiOperation(value = "用户管理-用户推送(异步)")
+    @RequestMapping(value = "/push", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)})
+    @Aac(strict = BOOL.FALSE, auth = BOOL.FALSE)
+    public Result sysUserPush() throws Exception {
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+        Map<String, Object> map = printCommonService.saveTask(TaskTypeEnum.USER_PUSH);
+        map.put(SystemConstant.SYS_USER, sysUser);
+
+        asyncUserPushService.pushTask(map);
+        TBTask tbTask = Objects.nonNull(map.get(SystemConstant.TASK)) ? (TBTask) map.get(SystemConstant.TASK) : null;
+        return Objects.nonNull(tbTask) ? ResultUtil.ok(tbTask.getId()) : ResultUtil.error("创建任务失败");
+    }
 }
 

+ 51 - 0
distributed-print/src/test/java/com/qmth/distributed/print/SyncHelpTest.java

@@ -0,0 +1,51 @@
+package com.qmth.distributed.print;
+
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
+import com.qmth.distributed.print.business.service.DataSyncService;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
+import com.qmth.teachcloud.common.service.CallApiOrgCenterService;
+import com.qmth.teachcloud.common.service.SysUserService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description: 推送云阅卷帮助类
+ * @Author: CaoZixuan
+ * @Date: 2021-10-27
+ */
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class SyncHelpTest {
+
+    @Resource
+    private CallApiOrgCenterService callApiOrgCenterService;
+    @Resource
+    private SysUserService sysUserService;
+
+    @Test
+    public void testSyncUser() throws IllegalAccessException {
+        int x = 0;
+        while (x < 10){
+            x ++;
+            UserPushParam userPushParam = new UserPushParam();
+            if (x < 7){
+                userPushParam.setAccount(String.valueOf(x));
+            }
+            if (x % 2 == 1){
+                userPushParam.setRole(SpecialPrivilegeEnum.MARKER);
+            }else {
+                userPushParam.setRole(SpecialPrivilegeEnum.SUBJECT_HEADER);
+            }
+            callApiOrgCenterService.basicSyncUser(userPushParam,2L);
+        }
+    }
+
+    @Test
+    public void testAutoPushUserErrorData() throws IllegalAccessException {
+        sysUserService.autoPushUserErrorData();
+    }
+}

+ 18 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/annotation/DBVerify.java

@@ -0,0 +1,18 @@
+package com.qmth.teachcloud.common.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @Description: 数据库映射类字段校验注解
+ * @Author: CaoZixuan
+ * @Date: 2021-05-11
+ */
+@Retention(RetentionPolicy.RUNTIME) //定义注解运行策略
+public @interface DBVerify {
+    String value();
+
+    boolean required() default false;
+
+    int length() default 0; //属性接收长度限制默认0,为0的不校验长度
+}

+ 43 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/PushBeforeRoleParam.java

@@ -0,0 +1,43 @@
+package com.qmth.teachcloud.common.bean.params;
+
+import com.qmth.teachcloud.common.enums.userPush.BeforeJudgeEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Set;
+
+/**
+ * @Description: 推送前用户角色权限判断参数
+ * @Author: CaoZixuan
+ * @Date: 2021-10-30
+ */
+public class PushBeforeRoleParam {
+    @ApiModelProperty(value = "更新前用户角色idSet")
+    private Set<Long> roleIdSet;
+
+    @ApiModelProperty(value = "更新前后对比策略枚举")
+    private BeforeJudgeEnum beforeJudgeEnum;
+
+    public PushBeforeRoleParam(Set<Long> roleIdSet, BeforeJudgeEnum beforeJudgeEnum) {
+        this.roleIdSet = roleIdSet;
+        this.beforeJudgeEnum = beforeJudgeEnum;
+    }
+
+    public PushBeforeRoleParam() {
+    }
+
+    public Set<Long> getRoleIdSet() {
+        return roleIdSet;
+    }
+
+    public void setRoleIdSet(Set<Long> roleIdSet) {
+        this.roleIdSet = roleIdSet;
+    }
+
+    public BeforeJudgeEnum getBeforeJudgeEnum() {
+        return beforeJudgeEnum;
+    }
+
+    public void setBeforeJudgeEnum(BeforeJudgeEnum beforeJudgeEnum) {
+        this.beforeJudgeEnum = beforeJudgeEnum;
+    }
+}

+ 98 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/UserPushParam.java

@@ -0,0 +1,98 @@
+package com.qmth.teachcloud.common.bean.params;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.common.annotation.DBVerify;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description: 用户同步参数对象
+ * @Author: CaoZixuan
+ * @Date: 2021-10-27
+ */
+public class UserPushParam {
+    @ApiModelProperty(value = "系统用户id")
+    @DBVerify(value = "系统用户id",required = true)
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long userId;
+
+    @ApiModelProperty(value = "关联名称(唯一标识)")
+    @DBVerify(value = "关联名称(唯一标识)",required = true)
+    private String account;
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    @ApiModelProperty(value = "密码")
+    private String password;
+
+    @ApiModelProperty(value = "特殊角色权限")
+    @DBVerify(value = "特殊角色权限",required = true)
+    private SpecialPrivilegeEnum role;
+
+    @ApiModelProperty(value = "是否启用")
+    private Boolean enable;
+
+    @ApiModelProperty(value = "科组长关联科目,科目代码用,分割,例如ASC,WED")
+    private String subjectCodes;
+
+    public UserPushParam() {
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public SpecialPrivilegeEnum getRole() {
+        return role;
+    }
+
+    public void setRole(SpecialPrivilegeEnum role) {
+        this.role = role;
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public String getSubjectCodes() {
+        return subjectCodes;
+    }
+
+    public void setSubjectCodes(String subjectCodes) {
+        this.subjectCodes = subjectCodes;
+    }
+}

+ 35 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/result/DBVerifyResult.java

@@ -0,0 +1,35 @@
+package com.qmth.teachcloud.common.bean.result;
+
+/**
+ * @Description: 验证返回参数
+ * @Author: CaoZixuan
+ * @Date: 2021-05-11
+ */
+public class DBVerifyResult {
+    private Boolean status;
+    private String message;
+
+    public DBVerifyResult(Boolean status, String message) {
+        this.status = status;
+        this.message = message;
+    }
+
+    public DBVerifyResult() {
+    }
+
+    public Boolean getStatus() {
+        return status;
+    }
+
+    public void setStatus(Boolean status) {
+        this.status = status;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 1 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/config/DictionaryConfig.java

@@ -72,7 +72,7 @@ public class DictionaryConfig {
 
 
     /**
-     * 机构用户中心配置
+     * 云阅卷同步推送
      *
      * @return
      */

+ 38 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java

@@ -1,11 +1,14 @@
 package com.qmth.teachcloud.common.contant;
 
 import com.qmth.boot.core.uid.service.UidService;
+import com.qmth.teachcloud.common.annotation.DBVerify;
+import com.qmth.teachcloud.common.bean.result.DBVerifyResult;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.util.ServletUtil;
 
 import java.io.File;
+import java.lang.reflect.Field;
 import java.nio.charset.Charset;
 import java.util.*;
 
@@ -333,4 +336,39 @@ public class SystemConstant {
         }
         return schoolId;
     }
+
+    /**
+     * 检验数据库字段
+     *
+     * @param obj   被检验的映射类对象
+     * @param clazz 该对象的类
+     * @return 检验结果(状态 、 信息)
+     * @throws IllegalAccessException 异常
+     */
+    public static DBVerifyResult verifyDBFields(Object obj, Class<?> clazz) throws IllegalAccessException {
+        Field[] fields = clazz.getDeclaredFields();
+        for (Field field : fields) {
+            field.setAccessible(true); // 解除封装
+            String fieldValue = String.valueOf(field.get(obj));
+            DBVerify dbVerify = field.getAnnotation(DBVerify.class);
+            if (Objects.isNull(dbVerify)){
+                continue;
+            }
+            String value = dbVerify.value();
+            boolean required = dbVerify.required();
+            int length = dbVerify.length();
+
+            if (required) {
+                if (fieldValue == null || fieldValue.length() == 0 || fieldValue.equals("null")) {
+                    return new DBVerifyResult(false, "[" + value + "]为必须字段,不能为空");
+                }
+            }
+            if (fieldValue != null && length > 0) {
+                if (fieldValue.length() > length) {
+                    return new DBVerifyResult(false, "[" + value + "]超出最大长度限制,最大限制[" + length + "]");
+                }
+            }
+        }
+        return new DBVerifyResult(true, "成功");
+    }
 }

+ 20 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/domain/SyncDataDomain.java

@@ -21,6 +21,10 @@ public class SyncDataDomain {
 
     String structureUrl;
 
+    String userSaveUrl;
+
+    String carduploadurl;
+
     public String getHostUrl() {
         return hostUrl;
     }
@@ -84,4 +88,20 @@ public class SyncDataDomain {
     public void setStructureUrl(String structureUrl) {
         this.structureUrl = structureUrl;
     }
+
+    public String getUserSaveUrl() {
+        return userSaveUrl;
+    }
+
+    public void setUserSaveUrl(String userSaveUrl) {
+        this.userSaveUrl = userSaveUrl;
+    }
+
+    public String getCarduploadurl() {
+        return carduploadurl;
+    }
+
+    public void setCarduploadurl(String carduploadurl) {
+        this.carduploadurl = carduploadurl;
+    }
 }

+ 26 - 4
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/PushUserError.java → teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/PushUserError.java

@@ -1,8 +1,10 @@
-package com.qmth.distributed.print.business.entity;
+package com.qmth.teachcloud.common.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.teachcloud.common.base.BaseEntity;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -23,24 +25,36 @@ public class PushUserError extends BaseEntity implements Serializable {
 
     @ApiModelProperty(value = "逸教云系统用户id")
     @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("school_id")
+    private Long schoolId;
+
+    @ApiModelProperty(value = "逸教云系统用户id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("user_id")
     private Long userId;
 
     @ApiModelProperty(value = "关联名称(唯一标识)")
+    @TableField("account")
     private String account;
 
     @ApiModelProperty(value = "名称")
+    @TableField("name")
     private String name;
 
     @ApiModelProperty(value = "密码")
+    @TableField("password")
     private String password;
 
     @ApiModelProperty(value = "特殊角色权限 MARKER('评卷员权限','Marker','M_'),SUBJECT_HEADER('科组长权限','SubjectHeader','S_')")
-    private String role;
+    @TableField("role")
+    private SpecialPrivilegeEnum role;
 
     @ApiModelProperty(value = "是否启用")
+    @TableField("enable")
     private Boolean enable;
 
     @ApiModelProperty(value = "科组长关联科目,科目代码用,分割,例如ASC,WED")
+    @TableField("subject_codes")
     private String subjectCodes;
 
 
@@ -48,6 +62,14 @@ public class PushUserError extends BaseEntity implements Serializable {
         return serialVersionUID;
     }
 
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
     public Long getUserId() {
         return userId;
     }
@@ -80,11 +102,11 @@ public class PushUserError extends BaseEntity implements Serializable {
         this.password = password;
     }
 
-    public String getRole() {
+    public SpecialPrivilegeEnum getRole() {
         return role;
     }
 
-    public void setRole(String role) {
+    public void setRole(SpecialPrivilegeEnum role) {
         this.role = role;
     }
 

+ 3 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/TaskTypeEnum.java

@@ -37,7 +37,9 @@ public enum TaskTypeEnum {
 
     CREATE_TASK_PRINT("发布印刷任务"),
 
-    STATISTICS_IMPORT("命题统计导入");
+    STATISTICS_IMPORT("命题统计导入"),
+
+    USER_PUSH("用户推送");
 
     private String title;
 

+ 27 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/userPush/BeforeJudgeEnum.java

@@ -0,0 +1,27 @@
+package com.qmth.teachcloud.common.enums.userPush;
+
+/**
+ * @Description: 是否要根据同步之前用户状态判断是否发送禁用推送枚举类
+ * @Author: CaoZixuan
+ * @Date: 2021-10-30
+ */
+public enum BeforeJudgeEnum {
+    FORBIDDEN_NO_NEED("只根据更新后角色权限判断,更新后即使没有特殊权限,也不发送禁用推送"),
+    FORBIDDEN_BY_BEFORE_ROLE("根据用户更新前的角色权限和更新后的对比(更新前如果特殊权限,更新后没有特殊权限则发送两条禁用推送)"),
+    FORBIDDEN_NECESSARY("不根据更新前的角色权限判断,只要更新后没有特殊权限,直接发送两条禁用推送"),
+    ;
+
+    BeforeJudgeEnum(String desc) {
+        this.desc = desc;
+    }
+
+    private String desc;
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+}

+ 1 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/userPush/SpecialPrivilegeEnum.java

@@ -9,6 +9,7 @@ public enum SpecialPrivilegeEnum {
     MARKER("评卷员权限","Marker","M_"),
     SUBJECT_HEADER("科组长权限","SubjectHeader","S_"),
     COMPOSITE("复合权限","Composite",null),
+    UNIDENTIFIED("无特殊权限","Unidentified",null),
     ;
 
     SpecialPrivilegeEnum(String title, String id, String prefix) {

+ 2 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/PushUserErrorMapper.java → teachcloud-common/src/main/java/com/qmth/teachcloud/common/mapper/PushUserErrorMapper.java

@@ -1,7 +1,7 @@
-package com.qmth.distributed.print.business.mapper;
+package com.qmth.teachcloud.common.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.qmth.distributed.print.business.entity.PushUserError;
+import com.qmth.teachcloud.common.entity.PushUserError;
 
 /**
  * <p>

+ 12 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/CallApiOrgCenterService.java

@@ -1,5 +1,7 @@
 package com.qmth.teachcloud.common.service;
 
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
+
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -17,4 +19,14 @@ public interface CallApiOrgCenterService {
      * @throws IOException 异常
      */
     List<Map> callOrgInfo() throws IOException;
+
+
+    /**
+     * 基础用户同步(推送)云阅卷接口
+     *
+     * @param userPushParam 用户推送参数
+     * @param schoolId 学校主键
+     * @return 是否成功
+     */
+    boolean basicSyncUser(UserPushParam userPushParam, Long schoolId) throws IllegalAccessException;
 }

+ 2 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PushUserErrorService.java → teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/PushUserErrorService.java

@@ -1,7 +1,7 @@
-package com.qmth.distributed.print.business.service;
+package com.qmth.teachcloud.common.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.qmth.distributed.print.business.entity.PushUserError;
+import com.qmth.teachcloud.common.entity.PushUserError;
 
 /**
  * <p>

+ 40 - 2
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/SysUserService.java

@@ -6,10 +6,13 @@ import com.qmth.teachcloud.common.bean.dto.BlurryUserDto;
 import com.qmth.teachcloud.common.bean.dto.LoginDto;
 import com.qmth.teachcloud.common.bean.dto.UserDto;
 import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
+import com.qmth.teachcloud.common.bean.params.PushBeforeRoleParam;
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
 import com.qmth.teachcloud.common.bean.params.UserSaveParams;
 import com.qmth.teachcloud.common.bean.result.LoginResult;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.FlowApproveNameEnum;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
 import org.springframework.util.LinkedMultiValueMap;
 
 import java.security.NoSuchAlgorithmException;
@@ -29,9 +32,9 @@ public interface SysUserService extends IService<SysUser> {
 
     IPage<UserDto> list(String loginName, String roleId, Boolean enable, String realName, Integer pageNumber, Integer pageSize);
 
-    boolean saveUser(UserSaveParams userSaveParams);
+    boolean saveUser(UserSaveParams userSaveParams) throws IllegalAccessException;
 
-    boolean enable(SysUser user) throws NoSuchAlgorithmException;
+    boolean enable(SysUser user) throws NoSuchAlgorithmException, IllegalAccessException;
 
     boolean resetPassword(Long id) throws NoSuchAlgorithmException;
 
@@ -171,4 +174,39 @@ public interface SysUserService extends IService<SysUser> {
      * @return
      */
     public int countByTeachingRoomId(Long orgId);
+
+    /**
+     * 用户推送云阅卷服务
+     * @param userPushParamList 推送参数
+     * @param requestUser 请求的用户信息
+     * @throws IllegalAccessException
+     */
+    boolean userPushService(List<UserPushParam> userPushParamList,SysUser requestUser) throws IllegalAccessException;
+
+    /**
+     * 自动推送用户推送失败表用户到云阅卷
+     */
+    void autoPushUserErrorData() throws IllegalAccessException;
+
+    /**
+     * 查询用户角色id查询用户特殊权限
+     * @param roleIdSet 用户角色id
+     * @return 用户特殊权限身份
+     */
+    SpecialPrivilegeEnum findUserSpecialPrivilegeByRoleIdSet(Set<Long> roleIdSet);
+
+    /**
+     * 解析用户推送状态
+     *
+     * @param userId              用户id
+     * @param schoolId            学校id
+     * @param userCode            用户工号
+     * @param realName            用户真实姓名
+     * @param password            用户密码
+     * @param currentRoleIdSet    当前用户角色id集合
+     * @param pushBeforeRoleParam 用户推送策略参数
+     * @param enable              用户启用禁用状态
+     * @return 组装好的用户推送参数集合
+     */
+    List<UserPushParam> analyzeUserPushSpecialPrivilege(Long userId, Long schoolId, String userCode, String realName, String password, Set<Long> currentRoleIdSet, PushBeforeRoleParam pushBeforeRoleParam, boolean enable);
 }

+ 43 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/CallApiOrgCenterServiceImpl.java

@@ -1,13 +1,18 @@
 package com.qmth.teachcloud.common.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.qmth.boot.tools.signature.SignatureEntity;
 import com.qmth.boot.tools.signature.SignatureType;
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
+import com.qmth.teachcloud.common.bean.result.DBVerifyResult;
 import com.qmth.teachcloud.common.config.DictionaryConfig;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.service.CallApiOrgCenterService;
 import com.qmth.teachcloud.common.util.HttpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -25,6 +30,8 @@ public class CallApiOrgCenterServiceImpl implements CallApiOrgCenterService {
     @Resource
     private DictionaryConfig dictionaryConfig;
 
+    private final static Logger log = LoggerFactory.getLogger(CallApiOrgCenterServiceImpl.class);
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public List<Map> callOrgInfo() throws IOException {
@@ -65,4 +72,40 @@ public class CallApiOrgCenterServiceImpl implements CallApiOrgCenterService {
         }
         return orgList;
     }
+
+
+    @Override
+    public boolean basicSyncUser(UserPushParam userPushParam, Long schoolId) throws IllegalAccessException {
+        DBVerifyResult dbVerifyResult = SystemConstant.verifyDBFields(userPushParam, userPushParam.getClass());
+        boolean result = dbVerifyResult.getStatus();
+        if (!result) {
+            log.warn(dbVerifyResult.getMessage());
+            return false;
+        }
+//        String hostUrl = dictionaryConfig.syncDataDomain().getHostUrl();
+//        String userSaveUrl = dictionaryConfig.syncDataDomain().getUserSaveUrl();
+//        String postUrl = hostUrl.concat(userSaveUrl);
+//        // 参数
+//        Map paramMap = JSON.parseObject(JSON.toJSONString(userPushParam), Map.class);
+//
+//        String httpResult = HttpKit.sendPost(postUrl, getHeaders(schoolId, userSaveUrl), paramMap, null, null, null);
+//        JSONObject jsonObject = JSONObject.parseObject(httpResult);
+//        if (jsonObject.containsKey("updateTime")) {
+//            return true;
+//        } else {
+//            log.warn("用户推送(同步)失败");
+//            return false;
+//        }
+        {
+            // 模拟云阅卷返回结果 3/5的成功率
+            int x = (int) (Math.random() * 10);
+            if (x > 0) {
+                // 失败
+                log.warn("x = " + x + ",云阅卷用户同步失败 \n" + JSON.toJSONString(userPushParam));
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
 }

+ 0 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/OrgCenterDataDisposeServiceImpl.java

@@ -1,6 +1,5 @@
 package com.qmth.teachcloud.common.service.impl;
 
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.contant.SystemConstant;

+ 4 - 4
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PushUserErrorServiceImpl.java → teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/PushUserErrorServiceImpl.java

@@ -1,9 +1,9 @@
-package com.qmth.distributed.print.business.service.impl;
+package com.qmth.teachcloud.common.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.distributed.print.business.entity.PushUserError;
-import com.qmth.distributed.print.business.mapper.PushUserErrorMapper;
-import com.qmth.distributed.print.business.service.PushUserErrorService;
+import com.qmth.teachcloud.common.entity.PushUserError;
+import com.qmth.teachcloud.common.mapper.PushUserErrorMapper;
+import com.qmth.teachcloud.common.service.PushUserErrorService;
 import org.springframework.stereotype.Service;
 
 /**

+ 43 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysRoleServiceImpl.java

@@ -6,10 +6,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.api.exception.ApiException;
+import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.*;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.enums.FieldUniqueEnum;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
+import com.qmth.teachcloud.common.enums.userPush.SyncStatusEnum;
 import com.qmth.teachcloud.common.mapper.SysRoleMapper;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.ResultUtil;
@@ -53,6 +56,9 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
     @Resource
     SysPrivilegeService sysPrivilegeService;
 
+    @Resource
+    SysUserService sysUserService;
+
     @Override
     public IPage<SysRole> list(String name, Boolean enable, Integer pageNumber, Integer pageSize) {
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
@@ -153,6 +159,11 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
                 sysRoleService.updateById(role);
                 commonCacheService.updateRoleCache(role.getId());
                 if (count != sysRolePrivilegeList.size() || count != finalRelatedSet.size()) {
+                    // 删除权限前先更新涉及特殊权限用户 -> 需要重新同步
+                    this.updateUserPushStats(sysPrivilegeList.stream().map(SysPrivilege::getId).distinct().collect(Collectors.toList()),
+                            Arrays.asList(role.getPrivilegeIds()),
+                            role.getId(),
+                            schoolId);
                     sysRolePrivilegeService.removeByRoleId(role.getId());
                     sysRolePrivilegeService.saveBatch(role);//角色权限
                     commonCacheService.updateRolePrivilegeCache(role.getId());
@@ -251,4 +262,36 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
         }
         return this.list(queryWrapper);
     }
+
+    /**
+     * 更新用户状态为重新推送
+     *
+     * @param dbPrivilege 角色旧权限
+     * @param upPrivilege 角色新权限
+     * @param roleId      角色id
+     * @param schoolId    学校id
+     */
+    @Transactional
+    public void updateUserPushStats(List<Long> dbPrivilege, List<Long> upPrivilege, Long roleId, Long schoolId) {
+        // 评卷员权限
+        SysPrivilege marker = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.MARKER.getId())).get(0);
+        Long markerId = marker.getId();
+
+        // 科组长权限
+        SysPrivilege subjectHeader = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.SUBJECT_HEADER.getId())).get(0);
+        Long subjectHeaderId = subjectHeader.getId();
+        if ((dbPrivilege.contains(markerId) || upPrivilege.contains(markerId)) || (dbPrivilege.contains(subjectHeaderId) || upPrivilege.contains(subjectHeaderId))) {
+            List<SysUserRole> sysUserRoleList = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getRoleId, roleId));
+            Set<Long> userIdSet = sysUserRoleList.stream().map(SysUserRole::getUserId).collect(Collectors.toSet());
+            if (userIdSet.size() > 0) {
+                List<SysUser> sysUserList = sysUserService.listByIds(userIdSet);
+                for (SysUser sysUser : sysUserList) {
+                    sysUser.setSyncStatus(SyncStatusEnum.NEED_PUSH_AGAIN);
+                }
+                sysUserService.updateBatchById(sysUserList);
+            }
+        }
+    }
 }

+ 277 - 27
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysUserServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qmth.teachcloud.common.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -7,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.gson.Gson;
 import com.qmth.boot.api.exception.ApiException;
+import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.bean.auth.AuthBean;
 import com.qmth.teachcloud.common.bean.dto.BlurryUserDto;
 import com.qmth.teachcloud.common.bean.dto.LoginDto;
@@ -15,6 +17,8 @@ import com.qmth.teachcloud.common.bean.dto.VerifyCodeCheckDto;
 import com.qmth.teachcloud.common.bean.dto.excel.DescribeImportDto;
 import com.qmth.teachcloud.common.bean.dto.excel.SysUserImportDto;
 import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
+import com.qmth.teachcloud.common.bean.params.PushBeforeRoleParam;
+import com.qmth.teachcloud.common.bean.params.UserPushParam;
 import com.qmth.teachcloud.common.bean.params.UserSaveParams;
 import com.qmth.teachcloud.common.bean.result.LoginResult;
 import com.qmth.teachcloud.common.bean.result.UserBatchDisposeResult;
@@ -23,12 +27,18 @@ import com.qmth.teachcloud.common.contant.SpringContextHolder;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.*;
 import com.qmth.teachcloud.common.enums.*;
+import com.qmth.teachcloud.common.enums.userPush.BeforeJudgeEnum;
+import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
+import com.qmth.teachcloud.common.enums.userPush.SyncStatusEnum;
 import com.qmth.teachcloud.common.mapper.SysUserMapper;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.Base64Util;
 import com.qmth.teachcloud.common.util.ResultUtil;
 import com.qmth.teachcloud.common.util.ServletUtil;
+import javassist.bytecode.stackmap.BasicBlock;
 import org.apache.commons.lang3.StringUtils;
+import org.redisson.api.ExpiredObjectListener;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
@@ -90,6 +100,15 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     @Resource
     TeachcloudCommonService teachcloudCommonService;
 
+    @Resource
+    SysPrivilegeService sysPrivilegeService;
+
+    @Resource
+    CallApiOrgCenterService callApiOrgCenterService;
+
+    @Resource
+    PushUserErrorService pushUserErrorService;
+
 
     @Override
     public IPage<UserDto> list(String loginName, String roleId, Boolean enable, String realName, Integer pageNumber, Integer pageSize) {
@@ -113,12 +132,28 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 
     @Transactional
     @Override
-    public boolean saveUser(UserSaveParams userSaveParams) {
-        return saveUserCommon(userSaveParams,null);
+    public boolean saveUser(UserSaveParams userSaveParams) throws IllegalAccessException {
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+        Long oldId = userSaveParams.getId();
+        Set<Long> roleIdSet = new HashSet<>();
+        if (SystemConstant.longNotNull(oldId)) {
+            // 编辑
+            roleIdSet = new HashSet<>(sysRoleService.getUserRoles(oldId));
+        }
+        boolean result = false;
+        Long upUserId = saveUserCommon(userSaveParams, null);
+        if (SystemConstant.longNotNull(upUserId)) {
+            result = true;
+            PushBeforeRoleParam pushBeforeRoleParam = new PushBeforeRoleParam(roleIdSet, BeforeJudgeEnum.FORBIDDEN_BY_BEFORE_ROLE);
+            List<UserPushParam> userPushParamList = this.analyzeUserPushSpecialPrivilege(upUserId, requestUser.getSchoolId(), userSaveParams.getCode(), userSaveParams.getRealName(), userSaveParams.getPassword(), new HashSet<>(Arrays.asList(userSaveParams.getRoleIds())), pushBeforeRoleParam, userSaveParams.getEnable());
+            this.userPushService(userPushParamList, requestUser);
+        }
+        return result;
     }
 
     @Override
-    public boolean enable(SysUser user) throws NoSuchAlgorithmException {
+    public boolean enable(SysUser user) throws NoSuchAlgorithmException, IllegalAccessException {
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
         updateWrapper.lambda().set(SysUser::getEnable, user.getEnable()).eq(SysUser::getId, user.getId());
         commonCacheService.updateUserCache(user.getId());
@@ -127,6 +162,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         if (!user.getEnable()) {
             commonService.removeUserInfo(user.getId(), true);
         }
+        List<UserPushParam> userPushParamList = this.analyzeUserEnableSpecialPrivilege(requestUser.getSchoolId(), user.getId(), user.getEnable());
+        if (success) {
+            this.userPushService(userPushParamList, requestUser);
+        }
         return success;
     }
 
@@ -162,7 +201,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         String oldPassword = user.getOldPassword();
         if (SystemConstant.strNotNull(newPwd)) {
             // 参数中存在密码 -》 更新密码
-            if (SystemConstant.strNotNull(oldPassword) && oldPassword.equals(newPwd)){
+            if (SystemConstant.strNotNull(oldPassword) && oldPassword.equals(newPwd)) {
                 throw ExceptionResultEnum.ERROR.exception("新密码和旧密码一致请重新输入");
             }
             sysUser.setPwdCount(sysUser.getPwdCount() == null ? 1 : sysUser.getPwdCount() + 1);
@@ -187,7 +226,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             sysUser.setMobileNumber(mobileNumber);
         }
         boolean success = this.updateById(sysUser);
-        if (!success){
+        if (!success) {
             throw ExceptionResultEnum.ERROR.exception("用户更新失败");
         }
 
@@ -213,14 +252,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         BasicSchool basicSchool = null;
         String schoolCode = null;
         basicSchool = basicSchoolService.getById(sysUser.getSchoolId());
-        if (Objects.isNull(basicSchool)){
+        if (Objects.isNull(basicSchool)) {
             List<Long> userRoles = sysRoleService.getUserRoles(sysUser.getId());
-            List<SysRole> sysRoleList = sysRoleService.list(new QueryWrapper<SysRole>().lambda().in(SysRole::getId,userRoles));
+            List<SysRole> sysRoleList = sysRoleService.list(new QueryWrapper<SysRole>().lambda().in(SysRole::getId, userRoles));
             Set<RoleTypeEnum> roleType = sysRoleList.stream().map(SysRole::getType).collect(Collectors.toSet());
-            if (roleType.contains(RoleTypeEnum.ADMIN) || roleType.contains(RoleTypeEnum.CUSTOMER)){
+            if (roleType.contains(RoleTypeEnum.ADMIN) || roleType.contains(RoleTypeEnum.CUSTOMER)) {
                 schoolCode = SystemConstant.ADMIN_CODE;
             }
-        }else {
+        } else {
             schoolCode = basicSchool.getCode();
         }
         if (!schoolCode.equalsIgnoreCase(SystemConstant.ADMIN_CODE)) {
@@ -361,7 +400,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     @Transactional
     @Override
     public boolean saveCustomer(UserSaveParams userSaveParams) {
-        return saveUserCommon(userSaveParams,null);
+        Long upUserId = saveUserCommon(userSaveParams, null);
+        return SystemConstant.longNotNull(upUserId);
     }
 
     @Override
@@ -399,17 +439,18 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
      * 保存用户公用
      *
      * @param userSaveParams
-     * @return
+     * @return 新增或更新的用户id
      */
-    public boolean saveUserCommon(UserSaveParams userSaveParams,Long requestUserId) {
+    public Long saveUserCommon(UserSaveParams userSaveParams, Long requestUserId) {
         SysUserService sysUserService = SpringContextHolder.getBean(SysUserService.class);
         boolean isSuccess = true;
+        Long resultUserId = null;
         try {
             Long schoolId = userSaveParams.getSchoolId();
             if (schoolId == null) {
                 schoolId = Objects.nonNull(ServletUtil.getRequestHeaderSchoolIdByNotVaild()) ? Long.valueOf(ServletUtil.getRequestHeaderSchoolIdByNotVaild().toString()) : null;
             }
-            if (!SystemConstant.longNotNull(requestUserId)){
+            if (!SystemConstant.longNotNull(requestUserId)) {
                 SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
                 requestUserId = requestUser.getId();
             }
@@ -439,24 +480,26 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             if (Objects.isNull(sysUser.getId())) {//新增用户
                 sysUser.insertInfo(requestUserId);
                 sysUserService.save(sysUser);
+                resultUserId = sysUser.getId();
                 commonService.addUserRolePrivilege(sysUser, userSaveParams.getRoleIds());
             } else {//修改用户
+                resultUserId = sysUser.getId();
                 List<SysUserRole> sysUserRoleList = commonCacheService.userRolePrivilegeCache(sysUser.getId());
                 List<Long> userRolesList = Arrays.asList(userSaveParams.getRoleIds());
                 Set<Long> dbUserRolesList = sysUserRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());
                 int count = (int) dbUserRolesList.stream().filter(userRolesList::contains).count();
                 SysUser dbUser = sysUserService.getById(sysUser.getId());
                 sysUserService.update(new UpdateWrapper<SysUser>().lambda()
-                        .eq(SysUser::getId,sysUser.getId())
-                        .set(SysUser::getSchoolId,userSaveParams.getSchoolId())
-                        .set(SysUser::getLoginName,sysUser.getLoginName())
-                        .set(SysUser::getRealName,sysUser.getRealName())
-                        .set(SysUser::getCode,sysUser.getCode())
-                        .set(SysUser::getMobileNumber,sysUser.getMobileNumber())
-                        .set(SysUser::getOrgId,sysUser.getOrgId())
-                        .set(SysUser::getEnable,sysUser.getEnable())
-                        .set(SysUser::getUpdateId,requestUserId)
-                        .set(SysUser::getUpdateTime,System.currentTimeMillis())
+                        .eq(SysUser::getId, sysUser.getId())
+                        .set(SysUser::getSchoolId, userSaveParams.getSchoolId())
+                        .set(SysUser::getLoginName, sysUser.getLoginName())
+                        .set(SysUser::getRealName, sysUser.getRealName())
+                        .set(SysUser::getCode, sysUser.getCode())
+                        .set(SysUser::getMobileNumber, sysUser.getMobileNumber())
+                        .set(SysUser::getOrgId, sysUser.getOrgId())
+                        .set(SysUser::getEnable, sysUser.getEnable())
+                        .set(SysUser::getUpdateId, requestUserId)
+                        .set(SysUser::getUpdateTime, System.currentTimeMillis())
                 );
                 //如果修改了角色,需要重新登录
                 if (count == 0 || dbUserRolesList.size() != userRolesList.size()) {
@@ -478,6 +521,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
                         commonCacheService.updateUserAuthCache(sysUser.getId());
                     }
                 }
+
             }
 //            //用户科目全量删除全量增加
 //            QueryWrapper<BasicUserCourse> basicUserCourseQueryWrapper = new QueryWrapper<>();
@@ -505,7 +549,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
                 ResultUtil.error(e.getMessage());
             }
         }
-        return isSuccess;
+        if (!isSuccess) {
+            resultUserId = null;
+        }
+        return resultUserId;
     }
 
 
@@ -632,7 +679,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     public Map<String, Object> executeSysUserImportLogic(List<LinkedMultiValueMap<Integer, Object>> finalList, Map<String, Object> map) throws NoSuchAlgorithmException {
         SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
         Long schoolId = sysUser.getSchoolId();
-//        List<UserSaveParams> userSaveParamsList = new ArrayList<>();
+        List<UserPushParam> userPushParamList = new ArrayList<>();
         for (int i = 0; i < finalList.size(); i++) {
             LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
             List<Object> sysUserImportDtoList = excelMap.get(i);
@@ -655,8 +702,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 
                 SysUser oldUser = this.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getCode, code).eq(SysUser::getSchoolId, schoolId));
                 Long oldUserId = null;
+                Set<Long> oldRoleSet = new HashSet<>();
                 if (Objects.nonNull(oldUser)) {
                     oldUserId = oldUser.getId();
+                    oldRoleSet = new HashSet<>(sysRoleService.getUserRoles(oldUserId));
                 }
                 String loginName = code;
                 if (SystemConstant.longNotNull(oldUserId)) {
@@ -673,10 +722,15 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
                 }
                 userSaveParams.setCode(code);
                 userSaveParams.setSchoolId(schoolId);
-                this.saveUserCommon(userSaveParams,sysUser.getId());
-//                userSaveParamsList.add(userSaveParams);
+                Long upUserId = this.saveUserCommon(userSaveParams, sysUser.getId());
+                if (SystemConstant.longNotNull(upUserId)) {
+                    PushBeforeRoleParam pushBeforeRoleParam = new PushBeforeRoleParam(oldRoleSet, BeforeJudgeEnum.FORBIDDEN_BY_BEFORE_ROLE);
+                    List<UserPushParam> pushCellList = this.analyzeUserPushSpecialPrivilege(upUserId, schoolId, userSaveParams.getCode(), userSaveParams.getRealName(), userSaveParams.getPassword(), new HashSet<>(Arrays.asList(userSaveParams.getRoleIds())), pushBeforeRoleParam, true);
+                    userPushParamList.addAll(pushCellList);
+                }
             }
         }
+        map.put("userPushParamList", userPushParamList);
 //        UserBatchDisposeResult userBatchDisposeResult = this.disposeUserInfoHelp(userSaveParamsList, sysUser);
 //        List<SysUser> sysUserList = userBatchDisposeResult.getUserList();
 //        List<SysUserRole> sysUserRoleList = userBatchDisposeResult.getUserRoleList();
@@ -878,6 +932,189 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         return sysUserService.count(sysUserQueryWrapper);
     }
 
+    @Transactional
+    @Override
+    public boolean userPushService(List<UserPushParam> userPushParamList, SysUser requestUser) throws IllegalAccessException {
+        boolean result = true;
+        for (UserPushParam userPushParam : userPushParamList) {
+            boolean syncResult = callApiOrgCenterService.basicSyncUser(userPushParam, requestUser.getSchoolId());
+            if (!syncResult) {
+                log.warn("-----------------------------用户同步推送失败----------------------------");
+                result = false;
+                PushUserError pushUserError = new PushUserError();
+                pushUserError.setId(SystemConstant.getDbUuid());
+                pushUserError.setSchoolId(requestUser.getSchoolId());
+                pushUserError.setUserId(userPushParam.getUserId());
+                pushUserError.setAccount(userPushParam.getAccount());
+                pushUserError.setName(userPushParam.getName());
+                pushUserError.setPassword(userPushParam.getPassword());
+                pushUserError.setEnable(userPushParam.getEnable());
+                pushUserError.setSubjectCodes(userPushParam.getSubjectCodes());
+                pushUserError.setRole(userPushParam.getRole());
+                pushUserError.setCreateId(requestUser.getId());
+                log.warn(JSON.toJSONString(pushUserError));
+                pushUserErrorService.save(pushUserError);
+            }
+        }
+        return result;
+    }
+
+    @Transactional
+    @Override
+    public void autoPushUserErrorData() throws IllegalAccessException {
+        List<PushUserError> pushUserErrorList = pushUserErrorService.list();
+        Set<Long> userIdSet = pushUserErrorList.stream().map(PushUserError::getUserId).collect(Collectors.toSet());
+        List<SysUser> sysUserList = this.listByIds(userIdSet);
+        // 清空push-user-error表
+        pushUserErrorService.remove(new QueryWrapper<PushUserError>().lambda().in(PushUserError::getUserId, userIdSet));
+        for (SysUser sysUser : sysUserList) {
+            if (!SyncStatusEnum.NEED_PUSH_AGAIN.equals(sysUser.getSyncStatus())) {
+                // 用户同步状态不为需要重新同步的错误数据再同步(防止和需要重新同步类型的数据冲突或因为权限改动导致的反复同步!)
+                Long userId = sysUser.getId();
+                Long schoolId = sysUser.getSchoolId();
+                Set<Long> roleIdSet = sysUserRoleService.listRoleByUserId(userId).stream().map(BaseEntity::getId).collect(Collectors.toSet());
+                PushBeforeRoleParam pushBeforeRoleParam = new PushBeforeRoleParam(null, BeforeJudgeEnum.FORBIDDEN_NECESSARY);
+                List<UserPushParam> userPushParamList = this.analyzeUserPushSpecialPrivilege(userId, schoolId, sysUser.getCode(), sysUser.getRealName(), sysUser.getPassword(), roleIdSet, pushBeforeRoleParam, sysUser.getEnable());
+                SysUser requestUser = new SysUser();
+                requestUser.setSchoolId(schoolId);
+                requestUser.setId(1L);
+                this.userPushService(userPushParamList, requestUser);
+            }
+        }
+    }
+
+    @Override
+    public SpecialPrivilegeEnum findUserSpecialPrivilegeByRoleIdSet(Set<Long> roleIdSet) {
+        SpecialPrivilegeEnum result = SpecialPrivilegeEnum.UNIDENTIFIED;
+        // 查询该学校特殊权限id
+        // 评卷员权限
+        SysPrivilege marker = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.MARKER.getId())).get(0);
+        Long markerId = marker.getId();
+
+        // 科组长权限
+        SysPrivilege subjectHeader = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.SUBJECT_HEADER.getId())).get(0);
+        Long subjectHeaderId = subjectHeader.getId();
+        if (roleIdSet.size() > 0) {
+            List<SysRolePrivilege> sysRolePrivilegeList = sysRolePrivilegeService.list(new QueryWrapper<SysRolePrivilege>().lambda().in(SysRolePrivilege::getRoleId, roleIdSet));
+            Set<Long> priIds = sysRolePrivilegeList.stream().map(SysRolePrivilege::getPrivilegeId).collect(Collectors.toSet());
+            if (priIds.size() > 0) {
+                if (priIds.contains(markerId) && !priIds.contains(subjectHeaderId)) {
+                    // 评卷员权限
+                    result = SpecialPrivilegeEnum.MARKER;
+                } else if (!priIds.contains(markerId) && priIds.contains(subjectHeaderId)) {
+                    // 科组长权限
+                    result = SpecialPrivilegeEnum.SUBJECT_HEADER;
+                } else if (priIds.contains(markerId) && priIds.contains(subjectHeaderId)) {
+                    // 复合权限
+                    result = SpecialPrivilegeEnum.COMPOSITE;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 解析用户推送状态
+     *
+     * @param userId              用户id
+     * @param schoolId            学校id
+     * @param userCode            用户工号
+     * @param realName            用户真实姓名
+     * @param password            用户密码
+     * @param currentRoleIdSet    当前用户角色id集合
+     * @param pushBeforeRoleParam 用户推送策略参数
+     * @param enable              用户启用禁用状态
+     * @return 组装好的用户推送参数集合
+     */
+    @Transactional
+    @Override
+    public List<UserPushParam> analyzeUserPushSpecialPrivilege(Long userId, Long schoolId, String userCode, String realName, String password, Set<Long> currentRoleIdSet, PushBeforeRoleParam pushBeforeRoleParam, boolean enable) {
+        List<UserPushParam> userPushParamList = new ArrayList<>();
+        // 查询该学校特殊权限id
+        // 评卷员权限
+        SysPrivilege marker = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.MARKER.getId())).get(0);
+        Long markerId = marker.getId();
+
+        // 科组长权限
+        SysPrivilege subjectHeader = sysPrivilegeService.list(new QueryWrapper<SysPrivilege>().lambda()
+                .eq(SysPrivilege::getUrl, SpecialPrivilegeEnum.SUBJECT_HEADER.getId())).get(0);
+        Long subjectHeaderId = subjectHeader.getId();
+
+        if (currentRoleIdSet.size() > 0) {
+            List<SysRolePrivilege> sysRolePrivilegeList = sysRolePrivilegeService.list(new QueryWrapper<SysRolePrivilege>().lambda().in(SysRolePrivilege::getRoleId, currentRoleIdSet));
+            Set<Long> priIds = sysRolePrivilegeList.stream().map(SysRolePrivilege::getPrivilegeId).collect(Collectors.toSet());
+            if (priIds.size() > 0) {
+                UserPushParam markerCell = new UserPushParam();
+                markerCell.setUserId(userId);
+                markerCell.setName(realName);
+                markerCell.setPassword(password);
+                markerCell.setRole(SpecialPrivilegeEnum.MARKER);
+                markerCell.setAccount(SpecialPrivilegeEnum.MARKER.getPrefix() + userCode);
+
+                UserPushParam headerCell = new UserPushParam();
+                headerCell.setUserId(userId);
+                headerCell.setName(realName);
+                headerCell.setPassword(password);
+                headerCell.setRole(SpecialPrivilegeEnum.SUBJECT_HEADER);
+                headerCell.setAccount(SpecialPrivilegeEnum.SUBJECT_HEADER.getPrefix() + userCode);
+
+                if (priIds.contains(markerId) && !priIds.contains(subjectHeaderId)) {
+                    // 评卷员权限
+                    markerCell.setEnable(enable);
+                    headerCell.setEnable(false);
+                } else if (!priIds.contains(markerId) && priIds.contains(subjectHeaderId)) {
+                    // 科组长权限
+                    headerCell.setEnable(enable);
+                    markerCell.setEnable(false);
+                } else if (priIds.contains(markerId) && priIds.contains(subjectHeaderId)) {
+                    // 复合权限
+                    headerCell.setEnable(enable);
+                    markerCell.setEnable(enable);
+                } else {
+                    // 无特殊权限
+                    switch (pushBeforeRoleParam.getBeforeJudgeEnum()) {
+                        case FORBIDDEN_NO_NEED:
+                            // 当前用户无特殊权限,且策略为不需要禁用则不推送
+                            markerCell = null;
+                            headerCell = null;
+                            break;
+                        case FORBIDDEN_BY_BEFORE_ROLE:
+                            Set<Long> beforeRoleIdSet = pushBeforeRoleParam.getRoleIdSet();
+                            if (beforeRoleIdSet != null && beforeRoleIdSet.size() > 0) {
+                                List<SysRolePrivilege> beforeSysRolePrivilegeList = sysRolePrivilegeService.list(new QueryWrapper<SysRolePrivilege>().lambda().in(SysRolePrivilege::getRoleId, beforeRoleIdSet));
+                                Set<Long> beforePris = beforeSysRolePrivilegeList.stream().map(SysRolePrivilege::getPrivilegeId).collect(Collectors.toSet());
+                                if (beforePris.contains(markerId) || beforePris.contains(subjectHeaderId)) {
+                                    // 如果启用了判断该用户原先的角色且原先用户含有特殊角色,但新用户新角色一个都不含,要发送两个禁用
+                                    markerCell.setEnable(false);
+                                    headerCell.setEnable(false);
+                                }
+                            } else {
+                                // 不发送同步
+                                markerCell = null;
+                                headerCell = null;
+                            }
+                            break;
+                        case FORBIDDEN_NECESSARY:
+                            markerCell.setEnable(false);
+                            headerCell.setEnable(false);
+                            break;
+                    }
+                }
+                if (Objects.nonNull(markerCell)) {
+                    userPushParamList.add(markerCell);
+                }
+                if (Objects.nonNull(headerCell)) {
+                    userPushParamList.add(headerCell);
+                }
+            }
+        }
+
+        return userPushParamList;
+    }
+
     /**
      * 批量处理用户信息帮助类
      *
@@ -995,4 +1232,17 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         }
         return roleIdList;
     }
+
+
+
+    private List<UserPushParam> analyzeUserEnableSpecialPrivilege(Long schoolId, Long userId, boolean enable) {
+        SysUser dbUser = sysUserService.getById(userId);
+        if (Objects.isNull(dbUser)) {
+            throw ExceptionResultEnum.ERROR.exception("未找到系统用户");
+        }
+        String code = dbUser.getCode();
+        Set<Long> roleIdList = new HashSet<>(sysRoleService.getUserRoles(userId));
+        PushBeforeRoleParam pushBeforeRoleParam = new PushBeforeRoleParam(null, BeforeJudgeEnum.FORBIDDEN_NECESSARY);
+        return this.analyzeUserPushSpecialPrivilege(userId, schoolId, code, null, null, roleIdList, pushBeforeRoleParam, enable);
+    }
 }

+ 1 - 1
distributed-print-business/src/main/resources/mapper/PushUserErrorMapper.xml → teachcloud-common/src/main/resources/mapper/PushUserErrorMapper.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.qmth.distributed.print.business.mapper.PushUserErrorMapper">
+<mapper namespace="com.qmth.teachcloud.common.mapper.PushUserErrorMapper">
 
 </mapper>