Bladeren bron

Merge remote-tracking branch 'origin/master'

yfh 5 dagen geleden
bovenliggende
commit
dd39b3f126

+ 3 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -157,4 +157,7 @@ public interface FsCourseRedPacketLogMapper
     @Select("SELECT company_id, SUM(amount) as money FROM fs_course_red_packet_log    WHERE status = 0 and create_time >= DATE_SUB(CURDATE(), INTERVAL 2 DAY)  AND create_time < DATE_SUB(CURDATE(), INTERVAL 1 DAY) GROUP BY company_id  ")
     List<RedPacketMoneyVO> selectFsCourseAddRedPacketLogByCompany();
 
+    @Select("select * from fs_course_red_packet_log where video_id = #{videoId} and user_id = #{userId} and period_id = #{periodId} limit 1")
+    FsCourseRedPacketLog selectUserFsCourseRedPacketLog(@Param("videoId") Long videoId, @Param("userId")Long userId, @Param("periodId")Long periodId);
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java

@@ -88,4 +88,6 @@ public interface IFsCourseQuestionBankService
      * @return  list
      */
     List<FsCourseQuestionBankImportDTO> exportData(FsCourseQuestionBank fsCourseQuestionBank);
+
+    R courseAnswerByFsUser(FsCourseQuestionAnswerUParam param);
 }

+ 109 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -9,14 +9,12 @@ import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.course.config.CourseConfig;
-import com.fs.course.domain.FsCourseAnswerLogs;
-import com.fs.course.domain.FsCourseQuestionBank;
-import com.fs.course.domain.FsCourseWatchLog;
-import com.fs.course.domain.FsUserCourseCategory;
+import com.fs.course.domain.*;
 import com.fs.course.dto.FsCourseQuestionBankImportDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.FsCourseQuestionAnswerUParam;
 import com.fs.course.service.IFsCourseQuestionBankService;
+import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.system.service.ISysConfigService;
@@ -134,6 +132,113 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         return fsCourseQuestionBankMapper.deleteFsCourseQuestionBankById(id);
     }
 
+    @Override
+    public R courseAnswerByFsUser(FsCourseQuestionAnswerUParam param) {
+        FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
+        if (user==null){
+            return R.error("未识别到领取信息");
+        }
+        //获取配置参数
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+
+        //本次答题正确个数
+        int thisRightCount = 0;
+        //用户答错次数
+        int errorCount = 0;
+        List<FsCourseQuestionBank> incorrectQuestions = new ArrayList<>();
+        //日志id
+        Long logId = null;
+
+        new FsCourseAnswerLogs();
+        FsCourseAnswerLogs rightLog;
+        //判断短链类型
+
+        FsCourseWatchLog log = courseWatchLogMapper.getWatchLogByFsUser(param.getVideoId(), param.getUserId(), param.getCompanyUserId());
+        if (log==null){
+            return R.error("无记录");
+        }
+        if (log.getLogType()!=2){
+            return R.error("未完课");
+        }
+        logId = log.getLogId();
+
+        rightLog = courseAnswerLogsMapper.selectRightLogByCourseVideo(param.getVideoId(), param.getUserId(), param.getQwUserId());
+        if (rightLog != null) {
+            if (log.getRewardType() != null) {
+                // 增加判断,去查询红包记录是否已发送成功,如果成功,则返回当前提示,否则返回答题成功(让其可以继续答题,直到红包领取完成)
+                FsCourseRedPacketLog fsCourseRedPacketLog = redPacketLogMapper.selectUserFsCourseRedPacketLog(param.getVideoId(), param.getUserId(),param.getPeriodId());
+                if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 1) {
+                    return R.error("该课程已答题完成,不可重复答题");
+                } else {
+                    return R.ok("答题成功");
+                }
+            } else {
+                return R.ok("答题成功");
+            }
+        }
+        errorCount = courseAnswerLogsMapper.selectErrorCountByCourseVideo(param.getVideoId(), param.getUserId(),param.getQwUserId());
+
+
+
+        if (errorCount >= config.getAnswerErrorCount()) {
+            return R.error("该课题到达答错次数限制");
+        }
+        int remainCount = config.getAnswerErrorCount()-errorCount-1;
+
+        // 一次性获取所有问题的正确答案
+        Map<Long, FsCourseQuestionBank> correctAnswersMap = fsCourseQuestionBankMapper.selectFsCourseQuestionBankByIds(
+                param.getQuestions().stream().map(FsCourseQuestionBank::getId).collect(Collectors.toList())
+        ).stream().collect(Collectors.toMap(FsCourseQuestionBank::getId, question -> question));
+
+        for (FsCourseQuestionBank questionBank : param.getQuestions()) {
+            FsCourseQuestionBank correctAnswer = correctAnswersMap.get(questionBank.getId());
+            if (correctAnswer.getType() == 1) {
+                if (questionBank.getAnswer().equals(correctAnswer.getAnswer())) {
+                    thisRightCount++;
+                } else {
+                    correctAnswer.setAnswer(null);
+                    incorrectQuestions.add(correctAnswer);
+                }
+            } else if (correctAnswer.getType() == 2) {
+                String[] userAnswers = convertStringToArray(questionBank.getAnswer());
+                String[] correctAnswers = convertStringToArray(correctAnswer.getAnswer());
+
+                Arrays.sort(userAnswers);
+                Arrays.sort(correctAnswers);
+
+                if (Arrays.equals(userAnswers, correctAnswers)) {
+                    thisRightCount++;
+                } else {
+                    correctAnswer.setAnswer(null);
+                    incorrectQuestions.add(correctAnswer);
+                }
+            }
+        }
+
+        FsCourseAnswerLogs logs = new FsCourseAnswerLogs();
+        logs.setWatchLogId(logId);
+        logs.setUserId(param.getUserId());
+        logs.setVideoId(param.getVideoId());
+        logs.setCourseId(param.getCourseId());
+        logs.setCompanyId(param.getCompanyId());
+        logs.setCompanyUserId(param.getCompanyUserId());
+        logs.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null );
+        logs.setQuestionJson(JSONObject.toJSONString(param.getQuestions()));
+        logs.setCreateTime(new Date());
+        logs.setPeriodId(param.getPeriodId());
+
+        if (thisRightCount == param.getQuestions().size()) {
+            logs.setIsRight(1);
+            courseAnswerLogsMapper.insertFsCourseAnswerLogs(logs);
+            return R.ok("答题成功");
+        } else {
+            logs.setIsRight(0);
+            courseAnswerLogsMapper.insertFsCourseAnswerLogs(logs);
+            return R.ok("答题失败").put("incorrectQuestions", incorrectQuestions).put("remain",remainCount);
+        }
+    }
+
     @Override
     @Transactional
     public R courseAnswer(FsCourseQuestionAnswerUParam param,Boolean isH5User) {

+ 0 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -506,7 +506,6 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         String courseJson = JSON.toJSONString(courseMap);
         link.setRealLink(realLink + courseJson);
 
-        link.setLink(random);
         link.setCreateTime(new Date());
 
         //获取过期时间

+ 12 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -879,7 +879,18 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             return R.error("无记录");
         }
         if (log.getRewardType() != null) {
-            return R.error("奖励已发放");
+            FsCourseRedPacketLog fsCourseRedPacketLog = redPacketLogMapper.selectUserFsCourseRedPacketLog(param.getVideoId(), param.getUserId(),param.getPeriodId());
+            if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 1) {
+                return R.error("奖励已发放");
+            }
+            if(fsCourseRedPacketLog != null && fsCourseRedPacketLog.getStatus() == 0) {
+                if(StringUtils.isNotEmpty(fsCourseRedPacketLog.getResult())){
+                    R r = JSON.parseObject(fsCourseRedPacketLog.getResult(), R.class);
+                    return r;
+                } else {
+                    return R.error();
+                }
+            }
         }
 
 

+ 56 - 32
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -191,9 +191,6 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
     @Autowired
     private QwTagMapper qwTagMapper;
 
-    @Autowired
-    private QwExternalContactServiceImpl qwExternalContactService;
-
 
     org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -417,7 +414,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
             // 获取组公共信息(每组只需查一次)
             QwExternalContact sample = group.get(0);
-            QwUser qwUser = qwExternalContactService.getQwUserByRedis(sample.getCorpId(), sample.getUserId());
+            QwUser qwUser = this.getQwUserByRedis(sample.getCorpId(), sample.getUserId());
             if (qwUser == null) {
                 logger.error("无企微员工信息: {}|{}", sample.getUserId(), sample.getCorpId());
                 return;
@@ -3248,8 +3245,18 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             if (i == 1) {
                 return;
             }
-            // 判断 SOP 任务的开始时间
-            qwSopRuleTimeToolsCheck(sopStartLocalDate,currentDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate,qwAutoSopTimeParam,timeFormatter,localTime);
+
+            if (Integer.valueOf(1).equals(ruleTimeVO.getIsFixed())){
+
+                qwSopRuleTimeToolsCheckByIsFixed(sopStartLocalDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate);
+
+            }else {
+                // 判断 SOP 任务的开始时间
+                qwSopRuleTimeToolsCheck(sopStartLocalDate,currentDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate,qwAutoSopTimeParam,timeFormatter,localTime);
+
+            }
+
+
         });
     }
 
@@ -3859,8 +3866,17 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                             logsInfo.setExternalUserName(qwExternalContact.getName());
                             logsInfo.setSopId(ruleTimeVO.getId());
 
-                            //检查营期
-                            qwSopRuleTimeToolsCheck(sopStartLocalDate,currentDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate,qwAutoSopTimeParam,timeFormatter,localTime);
+
+                            //如果是固定营期
+                            if (Integer.valueOf(1).equals(ruleTimeVO.getIsFixed())){
+
+                                qwSopRuleTimeToolsCheckByIsFixed(sopStartLocalDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate);
+
+                            }else {
+                                //检查营期
+                                qwSopRuleTimeToolsCheck(sopStartLocalDate,currentDate,dateFormatter,userLogs,logsInfo,userLogsParamByDate,qwAutoSopTimeParam,timeFormatter,localTime);
+                            }
+
 
                         }
 
@@ -3875,30 +3891,6 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                         });
                     }
 
-//                    if (!runRuleTime.isEmpty() && !qwSopRuleTimeVOS.isEmpty()){
-//
-//                        //剔除掉 销售的其他任务里的,这个人的信息ps:可能没有
-//                        Set<String> qwSopRuleTimeVOIds = qwSopRuleTimeVOS.stream()
-//                                .map(QwSopRuleTimeVO::getId)
-//                                .filter(Objects::nonNull)       // 过滤掉 null
-//                                .map(String::trim)              // 去除前后空格
-//                                .collect(Collectors.toSet());
-//
-//                        if (!qwSopRuleTimeVOIds.isEmpty()){
-//
-//                            //在 qwSopRuleTimeVOS 中过滤掉包含在 runRuleTimeIds 中的 id
-//                            List<QwSopRuleTimeVO> notOverlapList = runRuleTime.stream()
-//                                    .filter(item -> item.getId() != null &&!qwSopRuleTimeVOIds.contains(item.getId().trim()))
-//                                    .collect(Collectors.toList());
-//
-//                            notOverlapList.forEach(notSop->{
-//                                logger.info("删除这个客户在这个销售的其他不符合的sop"+notSop.getId()+"标签:"+tagArr+"id:"+qwExternalContact.getQwUserId()+"排除的标签:"+qwSopRuleTimeVOIds);
-//
-//                                deleteBySopIdToContactIdTools(notSop.getId(),qwExternalContact.getUserId(),qwExternalContact.getCorpId(),qwExternalContact.getId());
-//
-//                            });
-//                        }
-//                    }
                 }else {
                     //没匹配上任意一个(即这个剩下的标签匹配不上任意的sop),但是销售有任务-以防万一-删除这个客户在这个销售的sop
                     if (!runRuleTime.isEmpty()){
@@ -3918,6 +3910,38 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
     };
 
+
+    //固定营期  以 SOP 任务的开始时间为营期
+    private void qwSopRuleTimeToolsCheckByIsFixed(LocalDate sopStartLocalDate,DateTimeFormatter dateFormatter,
+                                                  SopUserLogs userLogs,SopUserLogsInfo logsInfo,
+                                                  SopUserLogsParamByDate userLogsParamByDate){
+
+        String sopStartLocalDateStr = sopStartLocalDate.format(dateFormatter);
+
+        userLogs.setStartTime(sopStartLocalDateStr);
+        // 查询开始时间营期表
+        String unionSopStartId = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);
+
+        // 如果营期表里有,则加入;否则创建新营期
+        if (!StringUtil.strIsNullOrEmpty(unionSopStartId)) {
+            logsInfo.setUserLogsId(unionSopStartId);
+            // 查询这个人是否已在该营期里
+            handleInsertSopUserLogsInfo(logsInfo);
+        }
+        else {
+            // 没有营期记录就先插入
+            userLogsParamByDate.setStartTime(sopStartLocalDateStr);
+
+            sopUserLogsService.insertSopUserLogsByDate(userLogsParamByDate);
+
+            // 再次查询 拿营期主键
+            String unionSopStartIdNew = sopUserLogsService.selectSopUserLogsByUnionSopId(userLogs);
+            logsInfo.setUserLogsId(unionSopStartIdNew);
+
+            // 查询是否在营期里,如果没有再插入
+            handleInsertSopUserLogsInfo(logsInfo);
+        }
+    }
     /**
      * 新客对话
      */

+ 2 - 1
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -30,6 +30,7 @@ import com.fs.sop.vo.QwSopTempRedPackageVo;
 import com.fs.sop.vo.VoiceVo;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
+import io.netty.util.internal.StringUtil;
 import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
@@ -412,7 +413,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService
                 content.setIsBindUrl(1);
                 List<QwSopTempContent> qwSopTempContents = new ArrayList<>() ;
                 qwSopTempContents.add(content);
-                if (sorts.get() == 0 && temp.getModeContent()!=null&&!temp.getModeContent().isEmpty()) {
+                if (sorts.get() == 0 && !StringUtil.isNullOrEmpty(temp.getModeContent())) {
                     QwSopTempContent content2 = new QwSopTempContent();
                     content2.setTempId(temp.getId());
                     content2.setContentType(3);

+ 151 - 0
fs-service/src/main/resources/application-druid-jzzx-test.yml

@@ -0,0 +1,151 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-jzzx,common
+    # redis 配置
+    redis:
+        # 地址
+        host: 127.0.0.1
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password:
+#        password: Ylrztek250218!3@.
+        # 连接超时时间
+        timeout: 20s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+        #        clickhouse:
+        #            type: com.alibaba.druid.pool.DruidDataSource
+        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+        #            username: rt_2024
+        #            password: Yzx_19860213
+        #            initialSize: 10
+        #            maxActive: 100
+        #            minIdle: 10
+        #            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://1.95.34.221:2345/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://1.95.34.221:2345/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 1 - 0
fs-service/src/main/resources/mapper/sop/QwSopMapper.xml

@@ -31,6 +31,7 @@
         <result property="stopTime"    column="stop_time"    />
         <result property="isRating"    column="is_rating"    />
         <result property="courseDay"    column="course_day"    />
+        <result property="isFixed"    column="is_fixed"    />
         <result property="chatId"    column="chat_id"    />
         <result property="openCommentStatus"    column="open_comment_status"    />
         <result property="isSampSend"    column="is_samp_send"    />

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/CourseWxH5Controller.java

@@ -109,7 +109,7 @@ public class CourseWxH5Controller extends AppBaseController {
         if (param.getDuration()==null){
             logger.info("zyp \n【未识别到时长】:{}",param.getUserId());
         }
-        return questionBankService.courseAnswer(param, true);
+        return questionBankService.courseAnswerByFsUser(param);
     }
 
     @ApiOperation("发放奖励")