Browse Source

试卷结构上传-增加短信日志管理,优化同步方法

xiaof 3 năm trước cách đây
mục cha
commit
59709b18a6
15 tập tin đã thay đổi với 580 bổ sung454 xóa
  1. 43 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicMessage.java
  2. 21 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/enums/MessageEnum.java
  3. 34 12
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/BasicMessageService.java
  4. 3 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamPrintPlanService.java
  5. 196 221
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicMessageServiceImpl.java
  6. 18 11
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/DataSyncServiceImpl.java
  7. 2 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamPaperStructureServiceImpl.java
  8. 16 4
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamPrintPlanServiceImpl.java
  9. 0 198
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/HttpKit.java
  10. 135 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/SmsUtils.java
  11. 96 0
      distributed-print/src/main/java/com/qmth/distributed/print/api/BasicMessageController.java
  12. 3 1
      distributed-print/src/main/resources/application-dev.properties
  13. 1 1
      distributed-print/src/test/java/com/qmth/distributed/print/ServiceTest.java
  14. 3 3
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/dto/SyncStructureData.java
  15. 9 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/domain/SmsDomain.java

+ 43 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicMessage.java

@@ -38,12 +38,31 @@ public class BasicMessage extends BaseEntity implements Serializable {
     @TableField("user_id")
     private Long userId;
 
+    /**
+     * 用户名称
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("user_name")
+    private String userName;
+
     /**
      * 手机号
      */
     @TableField("mobile_number")
     private String mobileNumber;
 
+    /**
+     * 试卷编号
+     */
+    @TableField("paper_number")
+    private String paperNumber;
+
+    /**
+     * 课程代码
+     */
+    @TableField("course_code")
+    private String courseCode;
+
     /**
      * 业务id
      */
@@ -133,6 +152,14 @@ public class BasicMessage extends BaseEntity implements Serializable {
         this.userId = userId;
     }
 
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
     public String getMobileNumber() {
         return mobileNumber;
     }
@@ -141,6 +168,22 @@ public class BasicMessage extends BaseEntity implements Serializable {
         this.mobileNumber = mobileNumber;
     }
 
+    public String getPaperNumber() {
+        return paperNumber;
+    }
+
+    public void setPaperNumber(String paperNumber) {
+        this.paperNumber = paperNumber;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
     public Long getBusinessId() {
         return businessId;
     }

+ 21 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/enums/MessageEnum.java

@@ -1,5 +1,10 @@
 package com.qmth.distributed.print.business.enums;
 
+import com.qmth.teachcloud.common.enums.EnumResult;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @Description: 发送消息枚举类
  * @Author: CaoZixuan
@@ -37,7 +42,8 @@ public enum MessageEnum {
     NOTICE_OF_AUDIT_WILL_EXPIRE("审核待办到期预警通知","${userName}您好,您还有${count}条审核待办即将逾期,请您尽快处理!"),
     NOTICE_OF_AUDIT_OVERDUE("审核待办逾期通知","${userName}您好,您有${count}条审核待办已逾期!"),
 
-    NOTICE_OF_AUDIT_REJECT("审核驳回生成通知","${userName}您好,${courseNameAndPaperNumber}试卷审核未通过,请您尽快处理!");
+    NOTICE_OF_AUDIT_REJECT("审核驳回生成通知","${userName}您好,${courseNameAndPaperNumber}试卷审核未通过,请您尽快处理!"),
+    NOTICE_OF_UPLOAD_STRUCTURE("试卷结构标答上传通知","${userName}您好,${courseNameAndPaperNumber}试卷印刷任务已经完成,请上传试卷结构及标答生成阅卷任务,请您尽快处理!");
 
 
     MessageEnum(String name, String template) {
@@ -48,6 +54,20 @@ public enum MessageEnum {
     private final String name;
     private final String template;
 
+
+    public static List<EnumResult> listTypes() {
+        List<EnumResult> list = new ArrayList<>();
+        for (MessageEnum value : MessageEnum.values()) {
+            EnumResult result = new EnumResult();
+            result.setName(value.name());
+            result.setOrdinal(value.ordinal());
+            result.setCode(null);
+            result.setDesc(value.getName());
+            list.add(result);
+        }
+        return list;
+    }
+
     public String getName() {
         return name;
     }

+ 34 - 12
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/BasicMessageService.java

@@ -1,14 +1,15 @@
 package com.qmth.distributed.print.business.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.distributed.print.business.entity.BasicMessage;
 import com.qmth.distributed.print.business.entity.ExamTask;
 import com.qmth.distributed.print.business.enums.MessageEnum;
 import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
 import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.EnumResult;
 
 import java.util.List;
-import java.util.Set;
 
 /**
  * @Description: 短信消息发送
@@ -17,17 +18,6 @@ import java.util.Set;
  */
 public interface BasicMessageService extends IService<BasicMessage> {
 
-    /**
-     * 保存消息发送日志(以下参数必传)
-     *
-     * @param userId         接收人id
-     * @param mobileNumber   接收人电话
-     * @param businessId     业务id
-     * @param variableParams 变量参数
-     * @param messageType    消息类型
-     */
-    void saveMessageSendLog(Long userId, String mobileNumber, Long businessId, String variableParams, Long createId, MessageEnum messageType, String remark);
-
     /**
      * 命题任务审核消息处理
      *
@@ -72,4 +62,36 @@ public interface BasicMessageService extends IService<BasicMessage> {
      * @param messageType
      */
     void sendNoticeTaskAuditFlow(ExamTask examTask, List<ApproveUserResult> users, MessageEnum messageType);
+
+    /**
+     * 发送给命题老师-试卷结构标答上传通知
+     * @param paperNumber 试卷编号
+     * @param courseCode 课程代码
+     * @param userId 命题老师ID
+     * @param messageType 短信类型
+     * @param sysUser
+     */
+    void sendNoticeUploadStructure(String paperNumber, String courseCode, Long userId, MessageEnum messageType, SysUser sysUser);
+
+    /**
+     * 查询
+     * @param messageType
+     * @param sendStatus
+     * @param pageNumber
+     * @param pageSize
+     * @return
+     */
+    IPage<BasicMessage> listByMessageType(MessageEnum messageType, Boolean sendStatus, Integer pageNumber, Integer pageSize);
+
+    /**
+     * 查询短信类型
+     * @return
+     */
+    List<EnumResult> listMessageTypes();
+
+    /**
+     * 短信失败重发
+     * @param id
+     */
+    void resendSmsTaskById(Long id);
 }

+ 3 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamPrintPlanService.java

@@ -11,6 +11,7 @@ import com.qmth.distributed.print.business.bean.result.PrintPlanBrief;
 import com.qmth.distributed.print.business.bean.result.PrintPlanResult;
 import com.qmth.distributed.print.business.entity.ExamPrintPlan;
 import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
+import com.qmth.teachcloud.common.entity.SysUser;
 
 import java.util.List;
 import java.util.Map;
@@ -101,4 +102,6 @@ public interface ExamPrintPlanService extends IService<ExamPrintPlan> {
      * @return 印刷计划
      */
     ExamPrintPlan findByExamDetailId(Long examDetailId);
+
+    void sendNoticeUploadStructure(Long id, SysUser sysUser);
 }

+ 196 - 221
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicMessageServiceImpl.java

@@ -1,15 +1,10 @@
 package com.qmth.distributed.print.business.service.impl;
 
 import com.alibaba.fastjson.JSON;
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.http.MethodType;
-import com.aliyuncs.profile.DefaultProfile;
-import com.aliyuncs.profile.IClientProfile;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+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.distributed.print.business.entity.BasicMessage;
 import com.qmth.distributed.print.business.entity.ExamTask;
@@ -17,19 +12,21 @@ import com.qmth.distributed.print.business.enums.MessageEnum;
 import com.qmth.distributed.print.business.mapper.BasicMessageMapper;
 import com.qmth.distributed.print.business.service.BasicMessageService;
 import com.qmth.distributed.print.business.service.ExamTaskService;
+import com.qmth.distributed.print.business.util.SmsUtils;
 import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
-import com.qmth.teachcloud.common.config.DictionaryConfig;
 import com.qmth.teachcloud.common.contant.SpringContextHolder;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.SysConfig;
 import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.EnumResult;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.service.CommonCacheService;
 import com.qmth.teachcloud.common.service.SysConfigService;
 import com.qmth.teachcloud.common.util.ServletUtil;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 import java.util.*;
@@ -44,128 +41,170 @@ import java.util.stream.Collectors;
 public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, BasicMessage> implements BasicMessageService {
     @Resource
     private SysConfigService sysConfigService;
-    @Resource
-    private DictionaryConfig dictionaryConfig;
+
     @Resource
     private CommonCacheService commonCacheService;
 
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public void saveMessageSendLog(Long userId, String mobileNumber, Long businessId, String variableParams, Long createId, MessageEnum messageType, String remark) {
-        String schoolId = ServletUtil.getRequestHeaderSchoolId().toString();
-        BasicMessage basicMessage = new BasicMessage();
-        // code和content
-        Map<String, String> enumInfo = this.getCodeAndContentByEnum(messageType);
-        String templateCode = enumInfo.get("templateCode");
-        String templateContent = enumInfo.get("templateContent");
+    @Autowired
+    private SmsUtils smsUtils;
 
-        String errorMessage = null;
-        if (SystemConstant.strNotNull(mobileNumber)){
-            try {
-                // 其他方法调用所传入的参数,必须校验有值
-                this.checkData(userId, variableParams, messageType);
+    @Override
+    public IPage<BasicMessage> listByMessageType(MessageEnum messageType, Boolean sendStatus, Integer pageNumber, Integer pageSize) {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
+        Page<BasicMessage> page = new Page<>(pageNumber, pageSize);
+        QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(BasicMessage::getSchoolId, schoolId);
+        if (!Objects.isNull(messageType)) {
+            queryWrapper.lambda().eq(BasicMessage::getMessageType, messageType);
+        }
+        if (Objects.nonNull(sendStatus)) {
+            if (sendStatus) {
+                queryWrapper.lambda().eq(BasicMessage::getSendStatus, "OK");
+            } else {
+                queryWrapper.lambda().ne(BasicMessage::getSendStatus, "OK");
+            }
+        }
+        queryWrapper.lambda().orderByDesc(BasicMessage::getCreateTime);
+        return this.page(page, queryWrapper);
+    }
 
-                // 短信提示系统是否启用配置验证
-                SysConfig sysConfig = sysConfigService.getByKey("sys.message.enable");
-                if (sysConfig == null) {
-                    throw ExceptionResultEnum.ERROR.exception("未找到短信配置");
-                }
-                if (sysConfig.getConfigValue() == null) {
-                    throw ExceptionResultEnum.ERROR.exception("短信消息提示启用开关未设置");
-                }
-                if (sysConfig.getConfigValue().equals("false")) {
-                    throw ExceptionResultEnum.ERROR.exception("短信消息提示已关闭");
-                }
+    @Override
+    public List<EnumResult> listMessageTypes() {
+        return MessageEnum.listTypes();
+    }
 
-                SendSmsResponse sendSmsResponse = sendSms(mobileNumber, templateCode, variableParams);
+    @Override
+    public void resendSmsTaskById(Long id) {
+        BasicMessage basicMessage = this.getById(id);
+        if (Objects.isNull(basicMessage)) {
+            return;
+        }
+        this.saveMessageResendLog(basicMessage);
+    }
 
-                if (sendSmsResponse.getCode() != null) {
+    /**
+     * 发送短信
+     *
+     * @param userId
+     * @param userName
+     * @param mobileNumber
+     * @param paperNumber
+     * @param courseCode
+     * @param variableParams
+     * @param messageType
+     * @param createId
+     * @param remark
+     */
+    public void saveMessageSendLog(Long schoolId, Long userId, String userName, String mobileNumber, String paperNumber, String courseCode, String variableParams, MessageEnum messageType, Long createId, String remark) {
+        BasicMessage basicMessage = new BasicMessage();
+        String templateCode = null;
+        try {
+            // code和content
+            Map<String, String> enumInfo = smsUtils.getCodeAndContentByEnum(messageType);
+            if (!enumInfo.containsKey("templateCode")) {
+                throw ExceptionResultEnum.ERROR.exception("未找到短信模板Code");
+            }
+            templateCode = enumInfo.get("templateCode");
+            if (StringUtils.isBlank(templateCode)) {
+                throw ExceptionResultEnum.ERROR.exception("阿里云短信模板Code必填");
+            }
 
-                    basicMessage.setSendStatus(sendSmsResponse.getCode());
-                    basicMessage.setSendResult(sendSmsResponse.getMessage());
+            // 发送短信参数配置验证
+            SysConfig sysConfig = sysConfigService.getByKey("sys.message.enable");
+            if (sysConfig == null) {
+                throw ExceptionResultEnum.ERROR.exception("未找到发送短信开关配置参数,默认不发送");
+            }
+            if (sysConfig.getConfigValue() == null) {
+                throw ExceptionResultEnum.ERROR.exception("未正确配置发送短信开关参数,默认不发送");
+            }
+            if (sysConfig.getConfigValue().equals("false")) {
+                throw ExceptionResultEnum.ERROR.exception("发送短信开关设置为已关闭");
+            }
 
-                } else {
-                    throw ExceptionResultEnum.ERROR.exception(sendSmsResponse.getMessage());
-                }
-            } catch (Exception e) {
-                errorMessage = e.getMessage();
-            } finally {
-                // 传入的必填字段
-                basicMessage.setSchoolId(Long.valueOf(schoolId));
-                basicMessage.setUserId(userId);
-                basicMessage.setMobileNumber(mobileNumber);
-                basicMessage.setBusinessId(businessId);
-                basicMessage.setVariableParams(variableParams);
-                basicMessage.setCreateId(createId);
-                basicMessage.setMessageType(messageType);
-                basicMessage.setRemark(remark);
-                basicMessage.setResendCount(0);
+            // 参数校验
+            if (StringUtils.isBlank(userName)) {
+                throw ExceptionResultEnum.ERROR.exception("用户名称必填");
+            }
+            if (StringUtils.isBlank(mobileNumber)) {
+                throw ExceptionResultEnum.ERROR.exception("用户手机号必填");
+            }
+            if (StringUtils.isBlank(variableParams)) {
+                throw ExceptionResultEnum.ERROR.exception("短信内容参数值必填");
+            }
 
-                // 经过处理的新字段
-                basicMessage.setId(SystemConstant.getDbUuid());
-                basicMessage.setBusinessOperate(messageType.getName());
-                basicMessage.setCreateTime(System.currentTimeMillis());
-                basicMessage.setTemplateCode(templateCode);
-                if (errorMessage != null && errorMessage.length() > 0) {
-                    basicMessage.setSendStatus("SYSTEM_ERROR");
-                    basicMessage.setSendResult(errorMessage);
-                }
-                this.save(basicMessage);
+            // 调用阿里云短信平台发送短信
+            SendSmsResponse sendSmsResponse = smsUtils.sendSms(mobileNumber, templateCode, variableParams);
+            if (sendSmsResponse == null) {
+                throw ExceptionResultEnum.ERROR.exception("阿里云短信发送接口调用失败");
             }
+            basicMessage.setSendStatus(sendSmsResponse.getCode());
+            basicMessage.setSendResult(sendSmsResponse.getMessage());
+
+        } catch (Exception e) {
+            basicMessage.setSendStatus("SYSTEM_ERROR");
+            basicMessage.setSendResult(e.getMessage());
+        } finally {
+            basicMessage.setId(SystemConstant.getDbUuid());
+            basicMessage.setSchoolId(schoolId);
+            basicMessage.setUserId(userId);
+            basicMessage.setUserName(userName);
+            basicMessage.setMobileNumber(mobileNumber);
+            basicMessage.setPaperNumber(paperNumber);
+            basicMessage.setCourseCode(courseCode);
+            basicMessage.setTemplateCode(templateCode);
+            basicMessage.setVariableParams(variableParams);
+            basicMessage.setMessageType(messageType);
+            basicMessage.setBusinessOperate(messageType.getName());
+            basicMessage.setRemark(remark);
+            basicMessage.setResendCount(0);
+            basicMessage.setCreateId(createId);
+            basicMessage.setCreateTime(System.currentTimeMillis());
+            this.save(basicMessage);
         }
     }
 
     /**
-     * 发送短信
-     * @param mobileNumber
-     * @param templateCode
-     * @param variableParams
-     * @return
-     * @throws ClientException
+     * 失败重发
+     *
+     * @param basicMessage
      */
-    private SendSmsResponse sendSms(String mobileNumber, String templateCode, String variableParams) throws ClientException {
-        System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
-        System.setProperty("sun.net.client.defaultReadTimeout", "18000");
-        // 初始化ascClient需要的几个参数
-        final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
-        final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
-        // 替换成你的AK
-        final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
-        final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
-        // 初始化ascClient,暂时不支持多region(请勿修改)
-        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
-        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-        IAcsClient acsClient = new DefaultAcsClient(profile);
-        // 组装请求对象
-        SendSmsRequest request = new SendSmsRequest();
-        // 使用post提交
-        request.setMethod(MethodType.POST);
-        // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
-        request.setPhoneNumbers(mobileNumber);
-        // 必填:短信签名-可在短信控制台中找到
-        request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
-        // 必填:短信模板-可在短信控制台中找到
-        request.setTemplateCode(templateCode);
-        // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
-        // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
-        request.setTemplateParam(variableParams);
-        // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
-        // request.setSmsUpExtendCode("90997");
-        // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-//             request.setOutId("yourOutId");
-        // 请求失败这里会抛ClientException异常
+    public void saveMessageResendLog(BasicMessage basicMessage) {
+        try {
+            if (basicMessage == null) {
+                return;
+            }
+            if ("OK".equals(basicMessage.getSendStatus())) {
+                return;
+            }
 
-        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
-        return sendSmsResponse;
+            if (!StringUtils.isBlank(basicMessage.getMobileNumber())) {
+                // 调用阿里云短信平台发送短信
+                SendSmsResponse sendSmsResponse = smsUtils.sendSms(basicMessage.getMobileNumber(), basicMessage.getTemplateCode(), basicMessage.getVariableParams());
+                if (sendSmsResponse == null) {
+                    throw ExceptionResultEnum.ERROR.exception("阿里云短信发送接口调用失败");
+                }
+                basicMessage.setSendStatus(sendSmsResponse.getCode());
+                basicMessage.setSendResult(sendSmsResponse.getMessage());
+            }
+        } catch (Exception e) {
+            basicMessage.setSendStatus("SYSTEM_ERROR");
+            basicMessage.setSendResult(e.getMessage());
+        } finally {
+            // 重试次数+1
+            basicMessage.setResendCount(basicMessage.getResendCount() + 1);
+            this.updateById(basicMessage);
+        }
     }
 
-    @Transactional(rollbackFor = Exception.class)
+
     @Override
     public void noticeOfExamTaskAudit(List<Long> examTaskIdList, MessageEnum messageType, SysUser sysUser) {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         ExamTaskService examTaskService = SpringContextHolder.getBean(ExamTaskService.class);
         for (Long examTaskId : examTaskIdList) {
             ExamTask examTask = examTaskService.getById(examTaskId);
             if (Objects.nonNull(examTask)) {
+                String courseCode = examTask.getCourseCode();
                 String courseName = examTask.getCourseName();
                 String paperNumber = examTask.getPaperNumber();
                 // 获取短信接收对象的信息
@@ -180,7 +219,11 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
                     jsonMap.put("courseName", courseName);
                     jsonMap.put("paperNumber", paperNumber);
                     String variableParams = JSON.toJSONString(jsonMap);
-                    this.saveMessageSendLog(userId, mobileNumber, examTaskId, variableParams, sysUser.getId(), messageType, null);
+                    String remark = String.format("命题任务ID:%s", examTaskId);
+                    this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
+                } else {
+                    String remark = String.format("命题任务ID:%s,用户不存在", examTaskId);
+                    this.saveMessageSendLog(schoolId, userId, null, null, paperNumber, courseCode, null, messageType, sysUser.getId(), remark);
                 }
             }
         }
@@ -195,6 +238,7 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
     @Override
     public void sendNoticeTaskCreate(ExamTask... examTasks) {
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         // 指派命题老师的命题任务
         Map<Long, List<String>> collects = Arrays.stream(examTasks).filter(m -> m.getUserId() != null).collect(Collectors.groupingBy(ExamTask::getUserId, Collectors.mapping(m -> String.valueOf(m.getId()), Collectors.toList())));
         for (Map.Entry<Long, List<String>> longListEntry : collects.entrySet()) {
@@ -210,13 +254,17 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
                 jsonMap.put("count", ids.size());
                 String variableParams = JSON.toJSONString(jsonMap);
                 String remark = String.format("命题任务ID:%s", String.join(",", ids));
-                this.saveMessageSendLog(userId, mobileNumber, null, variableParams, sysUser.getId(), MessageEnum.NOTICE_OF_EXAM_TASK_CREATED, remark);
+                this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, null, null, variableParams, MessageEnum.NOTICE_OF_EXAM_TASK_CREATED, sysUser.getId(), remark);
+            } else {
+                String remark = String.format("命题任务ID:%s,用户不存在", String.join(",", ids));
+                this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, MessageEnum.NOTICE_OF_EXAM_TASK_CREATED, sysUser.getId(), remark);
             }
         }
     }
 
     @Override
     public void sendNoticeTaskAuditCreateOrReview(ExamTask examTask, MessageEnum messageType) {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         // 考务老师(命题任务创建人)
         Long userId = examTask.getCreateId();
@@ -224,19 +272,25 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
         if (Objects.nonNull(user)) {
             String userName = user.getRealName();
             String mobileNumber = user.getMobileNumber();
+            String paperNumber = examTask.getPaperNumber();
+            String courseCode = examTask.getCourseCode();
 
             Map<String, Object> jsonMap = new HashMap<>();
             jsonMap.put("userName", userName);
-            StringJoiner sj = new StringJoiner("、").add(examTask.getCourseName()).add(examTask.getPaperNumber());
+            StringJoiner sj = new StringJoiner("、").add(courseCode).add(paperNumber);
             jsonMap.put("courseNameAndPaperNumber", sj.toString());
             String variableParams = JSON.toJSONString(jsonMap);
             String remark = String.format("命题任务ID:%s", examTask.getId().toString());
-            this.saveMessageSendLog(userId, mobileNumber, examTask.getId(), variableParams, sysUser.getId(), messageType, remark);
+            this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
+        } else {
+            String remark = String.format("命题任务ID:%s,用户不存在", examTask.getId().toString());
+            this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, messageType, sysUser.getId(), remark);
         }
     }
 
     @Override
     public void sendNoticeExpireOrOverdue(MessageEnum messageType, Long userId, List<String> ids) {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         // 考务老师(命题任务创建人)
         SysUser user = commonCacheService.userCache(userId);
         if (Objects.nonNull(user)) {
@@ -247,14 +301,17 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
             jsonMap.put("count", ids.size());
             String variableParams = JSON.toJSONString(jsonMap);
             String remark = String.format("命题任务ID:%s", String.join(",", ids));
-            this.saveMessageSendLog(userId, mobileNumber, null, variableParams, null, messageType, remark);
+            this.saveMessageSendLog(schoolId, userId, userName, mobileNumber, null, null, variableParams, messageType, null, remark);
+        } else {
+            String remark = String.format("命题任务ID:%s,用户不存在", String.join(",", ids));
+            this.saveMessageSendLog(schoolId, userId, null, null, null, null, null, messageType, null, remark);
         }
     }
 
     @Override
     public void resendSmsTask() {
         SysConfig sysConfig = sysConfigService.getByKey("sys.message.resendCount");
-        if(sysConfig != null){
+        if (sysConfig != null) {
             Integer resendCount = StringUtils.isBlank(sysConfig.getConfigValue()) ? 0 : Integer.valueOf(sysConfig.getConfigValue());
             QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
             queryWrapper.lambda().ne(BasicMessage::getSendStatus, "OK").lt(BasicMessage::getResendCount, resendCount);
@@ -269,125 +326,43 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
 
     @Override
     public void sendNoticeTaskAuditFlow(ExamTask examTask, List<ApproveUserResult> users, MessageEnum messageType) {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         // 考务老师(命题任务创建人)
         for (ApproveUserResult user : users) {
             String userName = user.getRealName();
             String mobileNumber = user.getMobileNumber();
-            if(StringUtils.isNotBlank(mobileNumber)) {
-                Map<String, Object> jsonMap = new HashMap<>();
-                jsonMap.put("userName", userName);
-                StringJoiner sj = new StringJoiner("、").add(examTask.getCourseName()).add(examTask.getPaperNumber());
-                jsonMap.put("courseNameAndPaperNumber", sj.toString());
-                String variableParams = JSON.toJSONString(jsonMap);
-                String remark = String.format("命题任务ID:%s", examTask.getId().toString());
-                this.saveMessageSendLog(user.getId(), mobileNumber, examTask.getId(), variableParams, sysUser.getId(), messageType, remark);
-            }
-        }
-    }
-
-    /**
-     * 自动重发
-     * @param basicMessage
-     */
-    private void saveMessageResendLog(BasicMessage basicMessage) {
-        String errorMessage = null;
-        try {
-            SendSmsResponse sendSmsResponse = sendSms(basicMessage.getMobileNumber(), basicMessage.getTemplateCode(), basicMessage.getVariableParams());
-            if (sendSmsResponse.getCode() != null) {
-                basicMessage.setSendStatus(sendSmsResponse.getCode());
-                basicMessage.setSendResult(sendSmsResponse.getMessage());
-            } else {
-                throw ExceptionResultEnum.ERROR.exception(sendSmsResponse.getMessage());
-            }
-        } catch (Exception e) {
-            errorMessage = e.getMessage();
-        } finally {
-            // 重试次数+1
-            basicMessage.setResendCount(basicMessage.getResendCount() + 1);
-            // 经过处理的新字段
-            if (errorMessage != null && errorMessage.length() > 0) {
-                basicMessage.setSendStatus("SYSTEM_ERROR");
-                basicMessage.setSendResult(errorMessage);
-            }
-            this.updateById(basicMessage);
+            String paperNumber = examTask.getPaperNumber();
+            String courseCode = examTask.getCourseCode();
+            Map<String, Object> jsonMap = new HashMap<>();
+            jsonMap.put("userName", userName);
+            StringJoiner sj = new StringJoiner("、").add(courseCode).add(paperNumber);
+            jsonMap.put("courseNameAndPaperNumber", sj.toString());
+            String variableParams = JSON.toJSONString(jsonMap);
+            String remark = String.format("命题任务ID:%s", examTask.getId().toString());
+            this.saveMessageSendLog(schoolId, user.getId(), userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), remark);
         }
     }
 
-    private void checkData(Object... objects) {
-        for (Object object : objects) {
-            if (Objects.isNull(object)) {
-                throw ExceptionResultEnum.ERROR.exception("调用发送短信方法时必传参数缺失");
-            } else if (object instanceof String) {
-                String param = String.valueOf(object);
-                if (param.length() == 0 || param.equals("null")) {
-                    throw ExceptionResultEnum.ERROR.exception("调用发送短信方法时必传参数缺失");
-                }
-            } else if (object instanceof Long) {
-                Long param = SystemConstant.convertIdToLong(String.valueOf(object));
-                if (param == null || param == 0) {
-                    throw ExceptionResultEnum.ERROR.exception("调用发送短信方法时必传参数缺失");
-                }
-            }
+    @Override
+    public void sendNoticeUploadStructure(String paperNumber, String courseCode, Long userId, MessageEnum messageType, SysUser sysUser) {
+        QueryWrapper<BasicMessage> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(BasicMessage::getPaperNumber, paperNumber).eq(BasicMessage::getCourseCode, courseCode).eq(BasicMessage::getUserId, userId).eq(BasicMessage::getMessageType, messageType);
+        List<BasicMessage> list = this.list(queryWrapper);
+        if (!CollectionUtils.isEmpty(list)) {
+            return;
         }
-    }
+        SysUser user = commonCacheService.userCache(userId);
+        if (Objects.nonNull(user)) {
+            String userName = user.getRealName();
+            String mobileNumber = user.getMobileNumber();
 
-    private Map<String, String> getCodeAndContentByEnum(MessageEnum messageEnum) {
-        Map<String, String> result = new HashMap<>();
-        String templateContent = null;
-        String templateCode = null;
-        switch (messageEnum) {
-            case NOTICE_OF_AUDIT_PASS:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditPassCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_NOT_PASS:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditNotPassCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_EXAM_TASK_CREATED:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskCreatedCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_EXAM_TASK_WILL_EXPIRE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskWillExpireCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_EXAM_TASK_OVERDUE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskOverdueCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_ALLOCATION_WILL_EXPIRE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAllocationWillExpireCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_ALLOCATION_OVERDUE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAllocationOverdueCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_CREATED:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditCreatedCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_REVIEW:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditReviewCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_WILL_EXPIRE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditWillExpireCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_OVERDUE:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditOverdueCode();
-                templateContent = messageEnum.getTemplate();
-                break;
-            case NOTICE_OF_AUDIT_REJECT:
-                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditRejectCode();
-                templateContent = messageEnum.getTemplate();
-                break;
+            Map<String, Object> jsonMap = new HashMap<>();
+            jsonMap.put("userName", userName);
+            StringJoiner sj = new StringJoiner("、").add(courseCode).add(paperNumber);
+            jsonMap.put("courseNameAndPaperNumber", sj.toString());
+            String variableParams = JSON.toJSONString(jsonMap);
+            this.saveMessageSendLog(sysUser.getSchoolId(), userId, userName, mobileNumber, paperNumber, courseCode, variableParams, messageType, sysUser.getId(), null);
         }
-        result.put("templateContent", templateContent);
-        result.put("templateCode", templateCode);
-        return result;
     }
 }

+ 18 - 11
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/DataSyncServiceImpl.java

@@ -19,6 +19,7 @@ import com.qmth.teachcloud.common.bean.dto.SyncStructureData;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.BasicAttachment;
 import com.qmth.teachcloud.common.entity.SysConfig;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.enums.SyncFileTypeEnum;
 import com.qmth.teachcloud.common.enums.TaskResultEnum;
@@ -28,6 +29,8 @@ import com.qmth.teachcloud.common.service.SysConfigService;
 import com.qmth.teachcloud.common.service.SysUserService;
 import com.qmth.teachcloud.common.service.TeachcloudCommonService;
 import com.qmth.teachcloud.common.sync.StmmsUtils;
+import com.qmth.teachcloud.common.util.ServletUtil;
+import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -77,9 +80,6 @@ public class DataSyncServiceImpl implements DataSyncService {
     @Autowired
     private BasicAttachmentService basicAttachmentService;
 
-    @Autowired
-    private SysUserService sysUserService;
-
     @Autowired
     StmmsUtils stmmsUtils;
 
@@ -93,13 +93,14 @@ public class DataSyncServiceImpl implements DataSyncService {
     @Override
     public void syncToCloudReview() {
         // 查询可同步计划(同步状态为空:未同步,false:同步失败)
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         QueryWrapper<ExamPrintPlan> queryWrapper = new QueryWrapper<>();
         queryWrapper.lambda().eq(ExamPrintPlan::getStatus, PrintPlanStatusEnum.END)
                 .and(q -> q.isNull(ExamPrintPlan::getSyncStatus).or().eq(ExamPrintPlan::getSyncStatus, false));
         List<ExamPrintPlan> examPrintPlans = examPrintPlanService.list(queryWrapper);
         if (!CollectionUtils.isEmpty(examPrintPlans)) {
             for (ExamPrintPlan examPrintPlan : examPrintPlans) {
-                executorService.execute(syncBaseData(examPrintPlan, null, examPrintPlan.getName()));
+                executorService.execute(syncBaseData(examPrintPlan, null, examPrintPlan.getName(), sysUser));
             }
         }
     }
@@ -112,6 +113,7 @@ public class DataSyncServiceImpl implements DataSyncService {
      */
     @Override
     public void syncDataCloud(Long printPlanId, Long thirdRelateId) {
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         ExamPrintPlan examPrintPlan = examPrintPlanService.getById(printPlanId);
         if (examPrintPlan == null) {
             throw ExceptionResultEnum.ERROR.exception("印刷计划数据异常");
@@ -121,12 +123,13 @@ public class DataSyncServiceImpl implements DataSyncService {
         }
         Long relateId = Objects.isNull(thirdRelateId) ? examPrintPlan.getThirdRelateId() : thirdRelateId;
         String thirdRelateName = Objects.isNull(examPrintPlan.getThirdRelateId()) ? examPrintPlan.getName() : examPrintPlan.getThirdRelateName();
-        executorService.execute(syncBaseData(examPrintPlan, relateId, thirdRelateName));
+        executorService.execute(syncBaseData(examPrintPlan, relateId, thirdRelateName, sysUser));
 
     }
 
     @Override
     public void syncDataMerge(SyncDataParam syncDataParam) {
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         List<Long> printPlans = syncDataParam.getList();
         if (CollectionUtils.isEmpty(printPlans)) {
             throw ExceptionResultEnum.ERROR.exception("请选择需要合并的印刷任务");
@@ -149,7 +152,7 @@ public class DataSyncServiceImpl implements DataSyncService {
 
         for (Long printPlanId : printPlans) {
             ExamPrintPlan printPlan = examPrintPlanService.getById(printPlanId);
-            executorService.execute(syncBaseData(printPlan, syncDataParam.getThirdRelateId(), syncDataParam.getThirdRelateName()));
+            executorService.execute(syncBaseData(printPlan, syncDataParam.getThirdRelateId(), syncDataParam.getThirdRelateName(), sysUser));
         }
     }
 
@@ -166,14 +169,14 @@ public class DataSyncServiceImpl implements DataSyncService {
      * @param thirdRelateName
      * @return
      */
-    private TimerTask syncBaseData(ExamPrintPlan examPrintPlan, Long thirdRelateId, String thirdRelateName) {
+    private TimerTask syncBaseData(ExamPrintPlan examPrintPlan, Long thirdRelateId, String thirdRelateName, SysUser sysUser) {
         return new TimerTask() {
             @Override
             public void run() {
                 SysConfig sysConfig = sysConfigService.getByKey("sys.sync.enable");
                 if (sysConfig != null && "true".equals(sysConfig.getConfigValue())) {
                     TBSyncTask syncTask = tbSyncTaskService.saveTask(examPrintPlan);
-                    doSyncBaseData(examPrintPlan, thirdRelateId, thirdRelateName, syncTask);
+                    doSyncBaseData(examPrintPlan, thirdRelateId, thirdRelateName, syncTask, sysUser);
                 }
             }
         };
@@ -299,7 +302,7 @@ public class DataSyncServiceImpl implements DataSyncService {
                 List<ExamPaperObjectiveStructureDto> objectiveStructureDtos = JSONObject.parseArray(objectiveContent, ExamPaperObjectiveStructureDto.class);
                 List<SyncStructureData> syncObjectiveStructureDatas = objectiveStructureDtos.stream().map(m -> {
                     SyncStructureData syncStructureData = new SyncStructureData();
-                    syncStructureData.setMainNumber(m.getMainNumber());
+                    syncStructureData.setMainNumber(Integer.valueOf(m.getMainNumber()));
                     syncStructureData.setSubNumber(m.getSubNumber());
                     syncStructureData.setMainTitle(m.getMainName());
                     syncStructureData.setTotalScore(Double.valueOf(m.getScore()));
@@ -334,7 +337,7 @@ public class DataSyncServiceImpl implements DataSyncService {
                 List<ExamPaperSubjectiveStructureDto> subjectiveStructureDtos = JSONObject.parseArray(subjectiveContent, ExamPaperSubjectiveStructureDto.class);
                 List<SyncStructureData> syncSubjectiveStructureDatas = subjectiveStructureDtos.stream().map(m -> {
                     SyncStructureData syncStructureData = new SyncStructureData();
-                    syncStructureData.setMainNumber(m.getMainNumber());
+                    syncStructureData.setMainNumber(Integer.valueOf(m.getMainNumber()));
                     syncStructureData.setSubNumber(m.getSubNumber());
                     syncStructureData.setMainTitle(m.getMainName());
                     syncStructureData.setTotalScore(Double.valueOf(m.getScore()));
@@ -363,7 +366,7 @@ public class DataSyncServiceImpl implements DataSyncService {
      * @param thirdRelateName
      * @param syncTask
      */
-    public void doSyncBaseData(ExamPrintPlan examPrintPlan, Long thirdRelateId, String thirdRelateName, TBSyncTask syncTask) {
+    public void doSyncBaseData(ExamPrintPlan examPrintPlan, Long thirdRelateId, String thirdRelateName, TBSyncTask syncTask, SysUser sysUser) {
         UpdateWrapper<ExamPrintPlan> updateWrapper = new UpdateWrapper<>();
         ExamPrintPlanSyncStatusEnum syncStatus = ExamPrintPlanSyncStatusEnum.INIT;
         try {
@@ -400,6 +403,10 @@ public class DataSyncServiceImpl implements DataSyncService {
             tbSyncTaskService.saveOrUpdate(syncTask);
             updateWrapper.lambda().set(ExamPrintPlan::getSyncStatus, syncStatus).eq(ExamPrintPlan::getId, examPrintPlan.getId());
             examPrintPlanService.update(updateWrapper);
+            // 同步成功,发送短信
+            if(ExamPrintPlanSyncStatusEnum.FINISH.equals(syncStatus)) {
+                examPrintPlanService.sendNoticeUploadStructure(examPrintPlan.getId(), sysUser);
+            }
         }
 
     }

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

@@ -251,7 +251,7 @@ public class ExamPaperStructureServiceImpl extends ServiceImpl<ExamPaperStructur
                     if (StringUtils.isBlank(subjectiveStructureDto.getMainName())) {
                         excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题名称]必填"));
                     }
-                    if (StringUtils.isBlank(subjectiveStructureDto.getMainNumber())) {
+                    if (subjectiveStructureDto.getMainNumber() == null) {
                         excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题号]必填"));
                     }
                     if (StringUtils.isBlank(subjectiveStructureDto.getSubNumber())) {
@@ -307,7 +307,7 @@ public class ExamPaperStructureServiceImpl extends ServiceImpl<ExamPaperStructur
                     if (StringUtils.isBlank(objectiveStructureDto.getMainName())) {
                         excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题名称]必填"));
                     }
-                    if (StringUtils.isBlank(objectiveStructureDto.getMainNumber())) {
+                    if (objectiveStructureDto.getMainNumber() == null) {
                         excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题号]必填"));
                     }
                     if (StringUtils.isBlank(objectiveStructureDto.getSubNumber())) {

+ 16 - 4
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamPrintPlanServiceImpl.java

@@ -12,10 +12,7 @@ import com.qmth.distributed.print.business.bean.params.SyncDataParam;
 import com.qmth.distributed.print.business.bean.result.PrintPlanBrief;
 import com.qmth.distributed.print.business.bean.result.PrintPlanResult;
 import com.qmth.distributed.print.business.bean.result.TemplatePrintInfoResult;
-import com.qmth.distributed.print.business.entity.BasicExamRule;
-import com.qmth.distributed.print.business.entity.ClientPrintData;
-import com.qmth.distributed.print.business.entity.ExamDetail;
-import com.qmth.distributed.print.business.entity.ExamPrintPlan;
+import com.qmth.distributed.print.business.entity.*;
 import com.qmth.distributed.print.business.enums.*;
 import com.qmth.distributed.print.business.mapper.ExamPrintPlanMapper;
 import com.qmth.distributed.print.business.service.*;
@@ -59,12 +56,18 @@ public class ExamPrintPlanServiceImpl extends ServiceImpl<ExamPrintPlanMapper, E
     @Resource
     private BasicSchoolService basicSchoolService;
 
+    @Autowired
+    private ExamTaskService examTaskService;
+
     @Autowired
     private BasicAttachmentService basicAttachmentService;
 
     @Resource
     private BasicExamRuleService basicExamRuleService;
 
+    @Autowired
+    private BasicMessageService basicMessageService;
+
     @Resource
     private TBTaskService tbTaskService;
 
@@ -464,6 +467,15 @@ public class ExamPrintPlanServiceImpl extends ServiceImpl<ExamPrintPlanMapper, E
         return examPrintPlan;
     }
 
+    @Override
+    public void sendNoticeUploadStructure(Long id, SysUser sysUser) {
+        List<ExamDetailCourse> examDetailCourses = examDetailService.listSyncPaperNumberByPrintPlanId(id);
+        for (ExamDetailCourse examDetailCours : examDetailCourses) {
+            ExamTask examTask = examTaskService.getByCourseCodeAndPaperNumber(examDetailCours.getSchoolId(), examDetailCours.getCourseCode(), examDetailCours.getPaperNumber());
+            basicMessageService.sendNoticeUploadStructure(examTask.getPaperNumber(), examTask.getCourseCode(), examTask.getUserId(), MessageEnum.NOTICE_OF_UPLOAD_STRUCTURE, sysUser);
+        }
+    }
+
 
     /**
      * 查找子机构

+ 0 - 198
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/HttpKit.java

@@ -1,198 +0,0 @@
-package com.qmth.distributed.print.business.util;
-
-import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
-
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Date;
-import java.util.Map;
-
-public class HttpKit {
-
-    /**
-     * 向指定 URL 发送POST方法的请求
-     *
-     * @param url    发送请求的 URL
-     * @param params 请求的参数集合
-     * @return 远程资源的响应结果
-     */
-    @SuppressWarnings("unused")
-    public static String sendPost(String url, Map<String, String> params, Map<String, String> requestHeader) {
-        OutputStreamWriter out = null;
-        BufferedReader in = null;
-        StringBuilder result = new StringBuilder();
-        try {
-            URL realUrl = new URL(url);
-            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
-            // 发送POST请求必须设置如下两行
-            conn.setDoOutput(true);
-            conn.setDoInput(true);
-            // POST方法
-            conn.setRequestMethod("POST");
-            // 设置通用的请求属性
-            conn.setRequestProperty("accept", "*/*");
-            conn.setRequestProperty("connection", "Keep-Alive");
-            conn.setRequestProperty("user-agent",
-                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
-            if (requestHeader != null && requestHeader.size() > 0) {
-                for (Map.Entry<String, String> entry : requestHeader.entrySet()) {
-                    conn.setRequestProperty(entry.getKey(), entry.getValue());
-                }
-            }
-//            conn.setRequestProperty("Authorization", authorization);
-            conn.connect();
-            // 获取URLConnection对象对应的输出流
-            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
-            // 发送请求参数
-            if (params != null) {
-                StringBuilder param = new StringBuilder();
-                for (Map.Entry<String, String> entry : params.entrySet()) {
-                    if (param.length() > 0) {
-                        param.append("&");
-                    }
-                    param.append(entry.getKey());
-                    param.append("=");
-                    param.append(entry.getValue());
-                }
-                out.write(param.toString());
-            }
-            // flush输出流的缓冲
-            out.flush();
-            // 定义BufferedReader输入流来读取URL的响应
-            in = new BufferedReader(
-                    new InputStreamReader(conn.getInputStream(), "UTF-8"));
-            String line;
-            while ((line = in.readLine()) != null) {
-                result.append(line);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        //使用finally块来关闭输出流、输入流
-        finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-                if (in != null) {
-                    in.close();
-                }
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
-        return result.toString();
-    }
-
-    /**
-     * 发送post请求
-     *
-     * @param requestUrl       请求url
-     * @param requestHeader    请求头
-     * @param formTexts        表单数据
-     * @param files            上传文件
-     * @param requestEncoding  请求编码
-     * @param responseEncoding 响应编码
-     * @return 页面响应html
-     */
-    public static String sendPost(String requestUrl, Map<String, String> requestHeader, Map<String, String> formTexts, Map<String, String> files, String requestEncoding, String responseEncoding) {
-        OutputStream out = null;
-        BufferedReader reader = null;
-        String result = "";
-        try {
-            if (requestUrl == null || requestUrl.isEmpty()) {
-                return result;
-            }
-            URL realUrl = new URL(requestUrl);
-            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
-            connection.setRequestProperty("accept", "text/html, application/xhtml+xml, image/jxr, */*");
-            connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0");
-            if (requestHeader != null && requestHeader.size() > 0) {
-                for (Map.Entry<String, String> entry : requestHeader.entrySet()) {
-                    connection.setRequestProperty(entry.getKey(), entry.getValue());
-                }
-            }
-            connection.setDoOutput(true);
-            connection.setDoInput(true);
-            connection.setRequestMethod("POST");
-            if (requestEncoding == null || requestEncoding.isEmpty()) {
-                requestEncoding = "UTF-8";
-            }
-            if (responseEncoding == null || responseEncoding.isEmpty()) {
-                responseEncoding = "UTF-8";
-            }
-            if (files == null || files.size() == 0) {
-                connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
-                out = new DataOutputStream(connection.getOutputStream());
-                if (formTexts != null && formTexts.size() > 0) {
-                    String formData = "";
-                    for (Map.Entry<String, String> entry : formTexts.entrySet()) {
-                        formData += entry.getKey() + "=" + entry.getValue() + "&";
-                    }
-                    formData = formData.substring(0, formData.length() - 1);
-                    out.write(formData.getBytes(requestEncoding));
-                }
-            } else {
-                String boundary = "-----------------------------" + new Date().getTime();
-                connection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);
-                out = new DataOutputStream(connection.getOutputStream());
-                if (formTexts != null && formTexts.size() > 0) {
-                    StringBuilder sbFormData = new StringBuilder();
-                    for (Map.Entry<String, String> entry : formTexts.entrySet()) {
-                        sbFormData.append("--" + boundary + "\r\n");
-                        sbFormData.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n");
-                        sbFormData.append(entry.getValue() + "\r\n");
-                    }
-                    out.write(sbFormData.toString().getBytes(requestEncoding));
-                }
-                for (Map.Entry<String, String> entry : files.entrySet()) {
-                    String fileName = entry.getKey();
-                    String filePath = entry.getValue();
-                    if (fileName == null || fileName.isEmpty() || filePath == null || filePath.isEmpty()) {
-                        continue;
-                    }
-                    File file = new File(filePath);
-                    if (!file.exists()) {
-                        continue;
-                    }
-                    out.write(("--" + boundary + "\r\n").getBytes(requestEncoding));
-                    out.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n").getBytes(requestEncoding));
-                    out.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes(requestEncoding));
-                    DataInputStream in = new DataInputStream(new FileInputStream(file));
-                    int bytes = 0;
-                    byte[] bufferOut = new byte[1024];
-                    while ((bytes = in.read(bufferOut)) != -1) {
-                        out.write(bufferOut, 0, bytes);
-                    }
-                    in.close();
-                    out.write(("\r\n").getBytes(requestEncoding));
-                }
-                out.write(("--" + boundary + "--").getBytes(requestEncoding));
-            }
-            out.flush();
-            out.close();
-//            out = null;
-            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), responseEncoding));
-            String line;
-            while ((line = reader.readLine()) != null) {
-                result += line;
-            }
-        } catch (Exception e) {
-            throw ExceptionResultEnum.ERROR.exception("发送POST请求出现异常:" + e.getMessage());
-        } finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-                if (reader != null) {
-                    reader.close();
-                }
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
-        return result;
-    }
-}

+ 135 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/SmsUtils.java

@@ -0,0 +1,135 @@
+package com.qmth.distributed.print.business.util;
+
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import com.qmth.distributed.print.business.enums.MessageEnum;
+import com.qmth.teachcloud.common.config.DictionaryConfig;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Date: 2021/11/5.
+ */
+@Component
+public class SmsUtils {
+
+    @Resource
+    private DictionaryConfig dictionaryConfig;
+
+    /**
+     * 发送短信
+     *
+     * @param mobileNumber
+     * @param templateCode
+     * @param variableParams
+     * @return
+     * @throws ClientException
+     */
+    public SendSmsResponse sendSms(String mobileNumber, String templateCode, String variableParams) throws ClientException {
+        System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "18000");
+        // 初始化ascClient需要的几个参数
+        final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
+        final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
+        // 替换成你的AK
+        final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
+        final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
+        // 初始化ascClient,暂时不支持多region(请勿修改)
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+        // 组装请求对象
+        SendSmsRequest request = new SendSmsRequest();
+        // 使用post提交
+        request.setMethod(MethodType.POST);
+        // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
+        request.setPhoneNumbers(mobileNumber);
+        // 必填:短信签名-可在短信控制台中找到
+        request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
+        // 必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode(templateCode);
+        // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+        // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
+        request.setTemplateParam(variableParams);
+        // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
+        // request.setSmsUpExtendCode("90997");
+        // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+//             request.setOutId("yourOutId");
+        // 请求失败这里会抛ClientException异常
+
+        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+        return sendSmsResponse;
+    }
+
+    public Map<String, String> getCodeAndContentByEnum(MessageEnum messageEnum) {
+        Map<String, String> result = new HashMap<>();
+        String templateContent = null;
+        String templateCode = null;
+        switch (messageEnum) {
+            case NOTICE_OF_AUDIT_PASS:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditPassCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_NOT_PASS:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditNotPassCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_EXAM_TASK_CREATED:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskCreatedCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_EXAM_TASK_WILL_EXPIRE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskWillExpireCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_EXAM_TASK_OVERDUE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSExamTaskOverdueCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_ALLOCATION_WILL_EXPIRE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAllocationWillExpireCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_ALLOCATION_OVERDUE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAllocationOverdueCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_CREATED:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditCreatedCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_REVIEW:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditReviewCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_WILL_EXPIRE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditWillExpireCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_OVERDUE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditOverdueCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_AUDIT_REJECT:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSAuditRejectCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+            case NOTICE_OF_UPLOAD_STRUCTURE:
+                templateCode = dictionaryConfig.smsDomain().getAliyunSMSUploadStructureCode();
+                templateContent = messageEnum.getTemplate();
+                break;
+        }
+        result.put("templateContent", templateContent);
+        result.put("templateCode", templateCode);
+        return result;
+    }
+}

+ 96 - 0
distributed-print/src/main/java/com/qmth/distributed/print/api/BasicMessageController.java

@@ -0,0 +1,96 @@
+package com.qmth.distributed.print.api;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.distributed.print.business.bean.result.EditResult;
+import com.qmth.distributed.print.business.entity.BasicMessage;
+import com.qmth.distributed.print.business.enums.MessageEnum;
+import com.qmth.distributed.print.business.service.BasicMessageService;
+import com.qmth.distributed.print.business.service.PrintCommonService;
+import com.qmth.distributed.print.business.templete.execute.AsyncCourseDataImportService;
+import com.qmth.teachcloud.common.bean.params.BasicCourseParams;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.BasicCourse;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.enums.EnumResult;
+import com.qmth.teachcloud.common.enums.TaskTypeEnum;
+import com.qmth.teachcloud.common.service.BasicCourseService;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import com.qmth.teachcloud.common.util.ServletUtil;
+import com.sun.org.apache.xpath.internal.operations.Bool;
+import io.swagger.annotations.*;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 短信发送日志 前端控制器
+ * </p>
+ *
+ * @author xf
+ */
+@Api(tags = "短信发送日志Controller")
+@RestController
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.basic}/message")
+@Validated
+public class BasicMessageController {
+
+    @Resource
+    private BasicMessageService basicMessageService;
+
+    /**
+     * 查询短信类型
+     * @return
+     */
+    @ApiOperation(value = "查询短信类型")
+    @RequestMapping(value = "/list_message_types", method = RequestMethod.POST)
+    public Result listType() {
+        List<EnumResult> list = basicMessageService.listMessageTypes();
+        return ResultUtil.ok(list);
+    }
+
+    /**
+     * 查询
+     * @param messageType
+     * @param pageNumber
+     * @param pageSize
+     * @return
+     */
+    @ApiOperation(value = "查询")
+    @RequestMapping(value = "/list", method = RequestMethod.POST)
+    public Result list(@RequestParam(value = "messageType", required = false) MessageEnum messageType,
+                        @RequestParam(value = "sendStatus", required = false) Boolean sendStatus,
+                        @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
+                        @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+        IPage<BasicMessage> messageIPage = basicMessageService.listByMessageType(messageType, sendStatus, pageNumber, pageSize);
+        return ResultUtil.ok(messageIPage);
+    }
+
+    /**
+     * 短信失败重发
+     * @param id
+     * @return
+     */
+    @ApiOperation(value = "短信失败重发")
+    @RequestMapping(value = "/resend", method = RequestMethod.POST)
+    public Result list(@RequestParam(value = "id", required = false) Long id) {
+        basicMessageService.resendSmsTaskById(id);
+        return ResultUtil.ok(true, null);
+    }
+}
+

+ 3 - 1
distributed-print/src/main/resources/application-dev.properties

@@ -177,4 +177,6 @@ sms.config.aliyunSMSAuditWillExpireCode=SMS_217436302
 #\uFFFD\uFFFD\u02F4\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0368\u05AA
 sms.config.aliyunSMSAuditOverdueCode=SMS_217416271
 #\uFFFD\uFFFD\uFFFD\uFFFD
-sms.config.aliyunSMSAuditRejectCode=SMS_225394754
+sms.config.aliyunSMSAuditRejectCode=SMS_225394754
+# ĘÔží˝áššąę´đÉĎ´ŤÍ¨ÖŞ
+sms.config.aliyunSMSUploadStructureCode=SMS_227253569

+ 1 - 1
distributed-print/src/test/java/com/qmth/distributed/print/ServiceTest.java

@@ -101,7 +101,7 @@ public class ServiceTest {
         Long createId = 1L;
         MessageEnum messageType = MessageEnum.NOTICE_OF_AUDIT_PASS;
 
-        basicMessageService.saveMessageSendLog(userId, mobileNumber, businessId, variableParams, createId, messageType, null);
+//        basicMessageService.saveMessageSendLog(userId, "李四", mobileNumber, businessId, variableParams, createId, messageType, null);
     }
 
     @Test

+ 3 - 3
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/dto/SyncStructureData.java

@@ -5,7 +5,7 @@ package com.qmth.teachcloud.common.bean.dto;
  */
 public class SyncStructureData {
 
-    private String mainNumber;
+    private Integer mainNumber;
 
     private String subNumber;
 
@@ -15,11 +15,11 @@ public class SyncStructureData {
 
     private String answer;
 
-    public String getMainNumber() {
+    public Integer getMainNumber() {
         return mainNumber;
     }
 
-    public void setMainNumber(String mainNumber) {
+    public void setMainNumber(Integer mainNumber) {
         this.mainNumber = mainNumber;
     }
 

+ 9 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/domain/SmsDomain.java

@@ -24,6 +24,7 @@ public class SmsDomain {
     String aliyunSMSAuditWillExpireCode;
     String aliyunSMSAuditOverdueCode;
     String aliyunSMSAuditRejectCode;
+    String aliyunSMSUploadStructureCode;
 
     public String getSmsNormalCode() {
         return smsNormalCode;
@@ -176,4 +177,12 @@ public class SmsDomain {
     public void setAliyunSMSAuditRejectCode(String aliyunSMSAuditRejectCode) {
         this.aliyunSMSAuditRejectCode = aliyunSMSAuditRejectCode;
     }
+
+    public String getAliyunSMSUploadStructureCode() {
+        return aliyunSMSUploadStructureCode;
+    }
+
+    public void setAliyunSMSUploadStructureCode(String aliyunSMSUploadStructureCode) {
+        this.aliyunSMSUploadStructureCode = aliyunSMSUploadStructureCode;
+    }
 }