Browse Source

Merge branch 'course_link' into pre

zoujiajian 3 năm trước cách đây
mục cha
commit
5312cb9e7f

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/mapper/EmailConfigMapper.java

@@ -0,0 +1,7 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EmailConfig;
+
+public interface EmailConfigMapper extends BaseMapper<EmailConfig> {
+}

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpTagGroupMapper.java

@@ -7,6 +7,8 @@ import com.cyksj.model.views.CorpTagBackView;
 import com.cyksj.model.views.CorpTagGroupView;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Map;
+
 /*
  *项目名: netflix
  *文件名: CorpTagGroupMapper
@@ -19,4 +21,6 @@ public interface CorpTagGroupMapper extends BaseMapper<CorpTagGroup> {
 	Page<CorpTagGroupView> getCorpTagList(@Param("groupName") String groupName, @Param("page") Page<CorpTagGroupView> page);
 
 	Page<CorpTagBackView> getCorpTagBackView(@Param("page") Page<CorpTagBackView> page, @Param("groupIds") String[] groupIds, @Param("sort") String sort, @Param("order") String order, @Param("wxCorpId") Long wxCorpId);
+
+	CorpTagBackView fillCorpGroupTagInfo(@Param("groupId") String groupId, @Param("wxCorpId") Long wxCorpI);
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpTagMapper.java

@@ -23,4 +23,6 @@ public interface CorpTagMapper extends BaseMapper<CorpTag> {
 	CorpTag getCorpTagById(Long corpTagId);
 
 	CorpTagHeadDataView getCorpTagHeadDataView();
+
+	Integer selectCountOfCustomer(@Param("tagId") String tagId, @Param("wxCorpId") Long wxCorpId);
 }

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EmailConfig.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class EmailConfig extends BaseEntity{
+	private String host;
+
+	private Integer port;
+
+	private String protocol;
+
+	private String username;
+
+	private String password;
+
+	private String defaultEncoding;
+
+	private String source;
+
+	private Integer type;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsCoursewareFile.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.entity;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -11,6 +12,7 @@ import lombok.Setter;
  */
 @Getter
 @Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsCoursewareFile extends BaseEntity{
 	private Long goodsId;
 
@@ -25,5 +27,9 @@ public class GoodsCoursewareFile extends BaseEntity{
 
 	private String img;
 
+	private String link;
+
+	private String code;
+
 	private Boolean status;
 }

+ 12 - 17
netflix-dao/src/main/resources/mapper/CorpTagGroupMapper.xml

@@ -41,26 +41,21 @@
         select * from (select cg.id as group_id,
         cg.group_id as groupIdStr,
         cg.group_name,
-        count(distinct ct.id) as tagSize,
-        count(cut.id) as numOfCustomer,
-        any_value(cg.update_time) as updateTime
+        cg.update_time
         from corp_tag_group cg
-        left join corp_tag ct on ct.group_id = cg.group_id
-        left join corp_user_tag cut on cut.tag_id = ct.tag_id
-        left join corp_user_follow_relation cufr on cufr.id = cut.relation_id and cufr.wx_corp_id = #{wxCorpId}
-        left join corp_user_auth cua on cua.external_userid = cufr.corp_user_id and cua.wx_corp_id = #{wxCorpId}
-        left join corp_user cu on cu.id = cua.corp_user_id and cu.unionid != ''
-        <where>
-            <if test="groupIds != null and groupIds.length >0">
-                cg.group_id in
-                <foreach collection="groupIds" item="item" open="(" separator="," close=")">
-                    #{item}
-                </foreach>
-            </if>
-        </where>
-        group by cg.id,cg.group_id,cg.group_name order by cg.id desc)s
+        )s
         <if test="sort != null">
             order by ${sort} ${order}
         </if>
     </select>
+
+    <select id="fillCorpGroupTagInfo" resultType="com.cyksj.model.views.CorpTagBackView">
+        select count(distinct ct.id)        as tagSize,
+               count(distinct corp_user_id) as numOfCustomer
+        from corp_tag ct
+                 left join corp_user_tag cut on cut.tag_id = ct.tag_id
+                 left join corp_user_follow_relation cufr on cufr.id = cut.relation_id
+        where ct.group_id = #{groupId}
+          and cufr.wx_corp_id = #{wxCorpId}
+    </select>
 </mapper>

+ 7 - 15
netflix-dao/src/main/resources/mapper/CorpTagMapper.xml

@@ -17,23 +17,10 @@
         ct.type,
         ct.group_name,
         ct.name as tagName,
-        count(distinct cu.user_id) as numOfCustomer,
-        any_value(ct.update_time) as updateTime,
+        ct.update_time,
         ct.rule_name_list_str
         from `corp_tag` ct
-        left join corp_user_tag cut on cut.tag_id = ct.tag_id
-        left join corp_user_follow_relation cufr on cufr.id = cut.relation_id and cufr.wx_corp_id = #{wxCorpId}
-        left join corp_user_auth cua on cua.external_userid = cufr.corp_user_id and cua.wx_corp_id = #{wxCorpId}
-        left join corp_user cu on cu.id = cua.corp_user_id and cu.unionid != ''
-        <where>
-            <if test="tagIds != null and tagIds.length > 0">
-                ct.id in
-                <foreach collection="tagIds" item="item" open="(" separator="," close=")">
-                    #{item}
-                </foreach>
-            </if>
-        </where>
-        group by ct.id, ct.group_name, ct.name, ct.tag_id,ct.group_id,ct.rule_name_list_str order by ct.id desc) s
+        ) s
         <if test="sort != null">
             order by ${sort} ${order}
         </if>
@@ -57,4 +44,9 @@
         from `corp_tag_group` cg
                  left join corp_tag ct on ct.group_id = ct.group_id
     </select>
+
+    <select id="selectCountOfCustomer" resultType="java.lang.Integer">
+        select count(distinct cufr.corp_user_id) from corp_user_tag cut left join corp_user_follow_relation cufr on cufr.id = cut.relation_id
+        where cufr.wx_corp_id = #{wxCorpId} and cut.tag_id = #{tagId}
+    </select>
 </mapper>

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpMsgBulkTaskServiceImpl.java

@@ -397,6 +397,7 @@ public class CorpMsgBulkTaskServiceImpl extends ServiceImpl<CorpMsgBulkTaskMappe
 			List<List<String>> split = CollectionUtil.split(corpUserIdList, LIMIT / 4);
 			for (List<String> strings : split) {
 				List<CorpUserSendRecord> corpUserSendRecords = corpMsgBulkTaskMapper.getsSuccessCorpUser(strings);
+				log.info("保存群发记录大小:{}", corpUserSendRecords.size());
 				corpUserSendRecords.forEach(corpUserSendRecord -> {
 					corpUserSendRecord.setCorpMsgRecordId(corpMsgBulkTaskRecord.getId());
 				});
@@ -408,6 +409,7 @@ public class CorpMsgBulkTaskServiceImpl extends ServiceImpl<CorpMsgBulkTaskMappe
 			List<CorpUserSendRecord> corpUserSendRecords = corpMsgBulkTaskMapper.getsSuccessCorpUser(failList);
 			if (CollectionUtil.isNotEmpty(corpUserSendRecords)) {
 				corpUserSendRecords.forEach(corpUserSendRecord -> {
+					log.info("失败群发记录大小:{}", corpUserSendRecords.size());
 					corpUserSendRecord.setCorpMsgRecordId(corpMsgBulkTaskRecord.getId());
 					corpMsgBulkTaskRecord.setTaskId(corpMsgBulkTaskRecord.getTaskId());
 					corpUserSendRecordService.saveBatch(corpUserSendRecords);

+ 8 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpTagServiceImpl.java

@@ -295,10 +295,17 @@ public class CorpTagServiceImpl implements CorpTagService {
 					} catch (Exception e) {
 					}
 				}
+				view.setNumOfCustomer(corpTagMapper.selectCountOfCustomer(view.getTagIdStr(), wxCorpId));
 			});
 			return corpTagBackViewPage;
 		}
-		return corpTagGroupMapper.getCorpTagBackView(new Page<>(start, limit), groupIds, sort, order, wxCorpId);
+		Page<CorpTagBackView> corpTagBackView = corpTagGroupMapper.getCorpTagBackView(new Page<>(start, limit), groupIds, sort, order, wxCorpId);
+		corpTagBackView.getRecords().forEach(data->{
+			CorpTagBackView info = corpTagGroupMapper.fillCorpGroupTagInfo(data.getGroupIdStr(), wxCorpId);
+			data.setTagSize(info.getTagSize());
+			data.setNumOfCustomer(info.getNumOfCustomer());
+		});
+		return corpTagBackView;
 	}
 
 	@Override

+ 92 - 3
netflix-service/src/main/java/com/cyksj/service/mail/impl/MailServiceImpl.java

@@ -5,9 +5,11 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.EmailConfigMapper;
 import com.cyksj.mapper.GoodsCoursewareFileMapper;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.model.entity.EmailConfig;
 import com.cyksj.model.entity.GoodsCoursewareFile;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.entity.OrderDon;
@@ -19,13 +21,18 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.mail.MailException;
 import org.springframework.mail.SimpleMailMessage;
 import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
 import org.springframework.mail.javamail.MimeMessageHelper;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.PostConstruct;
 import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeUtility;
 import java.io.File;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ThreadLocalRandom;
 
 /*
  *项目名: netflix
@@ -52,8 +59,46 @@ public class MailServiceImpl implements MailService {
 
 	private final OrderDonMapper orderDonMapper;
 
+	private final EmailConfigMapper emailConfigMapper;
+
+	private static List<JavaMailSenderImpl> senders;
+
 	private static String IMG_HTML = "<p><img src='%s' width=200></p>";
 
+	/**
+	 * 获取邮箱客户端
+	 */
+	@PostConstruct
+	public void init() throws Exception {
+		List<EmailConfig> emailConfigs = emailConfigMapper.selectList(null);
+		senders = new ArrayList<>(emailConfigs.size());
+		emailConfigs.forEach(emailConfig->{
+			//过滤163邮箱
+			if (emailConfig.getType() == 1) {
+				return;
+			}
+			JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
+			javaMailSender.setHost(emailConfig.getHost());
+			javaMailSender.setProtocol(emailConfig.getProtocol());
+			javaMailSender.setUsername(emailConfig.getUsername());
+			javaMailSender.setPassword(emailConfig.getPassword());
+			javaMailSender.setDefaultEncoding(emailConfig.getDefaultEncoding());
+			Properties properties = new Properties();
+			properties.setProperty("mail.smtp.auth", "true");
+			properties.setProperty("mail.smtp.port", emailConfig.getPort().toString());
+			properties.setProperty("mail.smtp.starttls.enable", "true");
+			properties.setProperty("mail.smtp.starttls.required", "true");
+			properties.setProperty("mail.smtp.ssl.enable", "true");
+
+			properties.setProperty("mail.smtp.socketFactory.port", "465");
+			properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+			properties.setProperty("mail.smtp.socketFactory.fallback", "false");
+			javaMailSender.setJavaMailProperties(properties);
+			senders.add(javaMailSender);
+		});
+		log.info("初始化邮箱大小:{}", senders.size());
+	}
+
 	@Override
 	public String sendLoginCodeEmailToPeople(Integer digit, String toAddress) {
 		// 生成验证码
@@ -122,12 +167,13 @@ public class MailServiceImpl implements MailService {
 		}
 		helper.setSubject(subject.toString());
 		helper.setText(sb.toString(), true);
-		helper.setFrom(from);
 		helper.setTo(email);
 		TASK_EXECUTOR.execute(() -> {
 			try {
-				log.info("开始给用户userId:{},relationId:{} 发送课程:{}专属课件", userId, relationId, goodsTitle);
-				mailSender.send(msg);
+				JavaMailSenderImpl sender = getJavaEmailServer();
+				helper.setFrom(sender.getUsername());
+				log.info("使用邮箱:{},开始给用户userId:{},relationId:{} 发送课程:{}专属课件", sender.getUsername(), userId, relationId, goodsTitle);
+				sendMsgIfFailRetry(sender, msg);
 			} catch (Exception e) {
 				log.info("发送课件失败,error:{}", StringUtil.getErrorText(e));
 				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
@@ -144,6 +190,49 @@ public class MailServiceImpl implements MailService {
 		});
 	}
 
+	private void sendMsgIfFailRetry(JavaMailSenderImpl sender, MimeMessage msg) {
+		try {
+			sender.send(msg);
+			log.info("发送课件成功");
+		} catch (Exception e) {
+			log.error("发送课件失败失败,error:{}", StringUtil.getErrorText(e));
+			if (!retry(msg)) {
+				throw BusinessRuntimeException.getInstance("暂无可用邮件服务器");
+			}
+		}
+	}
+
+	public Boolean retry(MimeMessage msg) {
+		for (JavaMailSenderImpl retry : senders) {
+			try {
+				msg.setFrom(retry.getUsername());
+				retry.send(msg);
+				log.info("重试发送课件成功");
+				return true;
+			} catch (Exception e2) {
+				log.error("重试发送课件失败失败,error:{}", StringUtil.getErrorText(e2));
+			}
+		}
+		return false;
+	}
+
+	public JavaMailSenderImpl getJavaEmailServer() throws Exception {
+		if (senders.isEmpty()) {
+			String key = "reEmailSenders";
+			if (redisService.setNx(key, "reEmailSenders", 30l)) {
+				if (senders.isEmpty()) {
+					init();
+					redisService.del(key);
+				}
+			} else {
+				if (senders.isEmpty()) {
+					throw BusinessRuntimeException.getInstance("系统超时,请重新获取邮箱验证码..");
+				}
+			}
+		}
+		int i = ThreadLocalRandom.current().nextInt(senders.size());
+		return senders.get(i);
+	}
 
 	public boolean sendMail(String toAddress, String subject, String text) {
 		SimpleMailMessage msg = new SimpleMailMessage();

+ 24 - 0
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -103,6 +103,8 @@ public class GroupRelationController {
 
     private final ChatGptAuthService chatGptAuthService;
 
+    private final GoodsCoursewareFileMapper goodsCoursewareFileMapper;
+
     private final static Sequence SEQUENCE = new Sequence(0);
 
     @RequestMapping("/get/renewal")
@@ -542,4 +544,26 @@ public class GroupRelationController {
         groupRelationFrontService.sendCourseWare(request);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
+
+    //获取课程云盘链接
+    @GetMapping("/get/courseware")
+    public Result<GoodsCoursewareFile> getGoodsCourseware(Long relationId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        GroupsRelationView relationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
+                .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
+                .field(GroupsRelationView::getId, relationId).build());
+        if (relationView == null) {
+            throw BusinessRuntimeException.getInstance("您的车票不存在");
+        }
+        GoodsCoursewareFile goodsCoursewareFile = goodsCoursewareFileMapper.selectOne(Wrappers.lambdaQuery(GoodsCoursewareFile.class)
+                .eq(GoodsCoursewareFile::getGoodsId, relationView.getGoodsId())
+                .eq(GoodsCoursewareFile::getStatus, true)
+                .select(GoodsCoursewareFile::getLink, GoodsCoursewareFile::getCode)
+                .last("limit 1"));
+        if (goodsCoursewareFile == null) {
+            throw BusinessRuntimeException.getInstance("暂未配置课件链接地址,请联系客服");
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCoursewareFile);
+    }
 }