Ver Fonte

Merge remote-tracking branch 'origin/master'

ct há 3 dias atrás
pai
commit
41263cd077

+ 230 - 1
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -76,6 +76,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
     private static final String miniappRealLink = "/pages_course/video.html?course=";
     private static final String appRealLink = "/pages/courseAnswer/index?link=";
     private static final String appLink = "https://jump.ylrztop.com/jumpapp/pages/index/index?link=";
+
 //    private static final String miniappRealLink = "/pages/index/index?course=";
 
     private static final String QWSOP_KEY_PREFIX = "qwsop:";
@@ -1968,7 +1969,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         if (settings == null) {
             return null;
         }
-
+        //完课后若是小程序发送另外一堂课
+        saveWacthLogOfCourseLink(settings,sopLogs,newTimeString,finishLog,finishTemp);
         // 处理音频内容
 //        for (QwSopCourseFinishTempSetting.Setting st : settings) {
 //            if (st.getContentType().equals("7")) {
@@ -1987,6 +1989,233 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         return sopLogs;
     }
 
+    /**
+     * 判定小程序的话新增创建看课记录,以及fsCourseLink
+     *
+     * @param settings
+     */
+    public void saveWacthLogOfCourseLink(List<QwSopCourseFinishTempSetting.Setting> settings, QwSopLogs sopLogs,  String newTimeString, FsCourseWatchLog finishLog, FsCourseFinishTemp finishTemp){
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+        Date dataTime = new Date();
+        List<CompanyMiniapp> miniList = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().orderByAsc("sort_num"));
+        Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap = miniList.stream().collect(Collectors.groupingBy(CompanyMiniapp::getCompanyId, Collectors.groupingBy(CompanyMiniapp::getType)));
+
+        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(sopLogs.getCorpId());
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(sopLogs.getCorpId(), sopLogs.getQwUserid());
+        if (qwUser == null){
+            return;
+        }
+        for (QwSopCourseFinishTempSetting.Setting st : settings) {
+            switch (st.getContentType()) {
+                //小程序单独
+                case "4":
+                    addWatchLogIfNeeded(sopLogs.getSopId(), st.getVideoId().intValue(), st.getCourseId().intValue(), sopLogs.getFsUserId(),  String.valueOf(qwUser.getId()),qwUser.getCompanyUserId().toString(), qwUser.getCompanyId().toString(),
+                            sopLogs.getExternalId(), newTimeString.substring(0, 10), dataTime);
+
+                    String linkByMiniApp = createLinkByMiniApp(st, sopLogs.getCorpId(), dataTime, finishTemp.getCourseId().intValue(), Integer.valueOf(st.getVideoId().toString()),
+                            String.valueOf(qwUser.getId()), qwUser.getCompanyUserId().toString(), qwUser.getCompanyId().toString(), sopLogs.getExternalId(), config);
+
+
+                    String miniAppId = null;
+                    if (!miniMap.isEmpty() && qwUser.getSendMsgType() == 1) {
+                        Map<Integer, List<CompanyMiniapp>> integerListMap = miniMap.get(Long.valueOf(qwUser.getCompanyId()));
+                        if (integerListMap != null) {
+                            int listIndex = 0;
+                            List<CompanyMiniapp> miniapps = integerListMap.get(listIndex);
+
+                            if (miniapps != null && !miniapps.isEmpty()) {
+                                CompanyMiniapp companyMiniapp = miniapps.get(0);
+                                if (companyMiniapp != null && !StringUtil.strIsNullOrEmpty(companyMiniapp.getAppId())) {
+                                    miniAppId = companyMiniapp.getAppId();
+                                }
+                            }
+                        }
+                    }
+
+                    if (StringUtil.strIsNullOrEmpty(miniAppId) && !StringUtil.strIsNullOrEmpty(qwCompany.getMiniAppId())) {
+                        miniAppId = qwCompany.getMiniAppId();
+                    }
+
+                    if (!StringUtil.strIsNullOrEmpty(miniAppId)) {
+                        st.setMiniprogramAppid(miniAppId);
+                    } else {
+                        log.error("企业未配置小程序-" + sopLogs.getCorpId());
+                    }
+
+                    String miniprogramTitle = st.getMiniprogramTitle();
+                    int maxLength = 17;
+                    st.setMiniprogramTitle(miniprogramTitle.length() > maxLength ? miniprogramTitle.substring(0, maxLength)+"..." : miniprogramTitle);
+                    st.setMiniprogramPage(linkByMiniApp);
+                    break;
+                default:
+                    break;
+
+            }
+        }
+    }
+    private Date processDate(String sendTimeParam) {
+        // 1. 获取当前日期(年月日)
+        LocalDate currentDate = LocalDate.now();
+
+        // 2. 解析传入的时分(支持 "HH:mm" 或 "H:mm")
+        LocalTime sendTime = LocalTime.parse(sendTimeParam);
+
+        // 3. 合并为 LocalDateTime
+        LocalDateTime dateTime = LocalDateTime.of(currentDate, sendTime);
+
+        // 4. 转换为 Date(需通过 Instant 和系统默认时区)
+        Date date = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
+
+        return date;
+    }
+
+    /**
+     * 新增courseLink
+     *
+     * @param setting
+     * @param corpId
+     * @param sendTime
+     * @param courseId
+     * @param videoId
+     * @param qwUserId
+     * @param companyUserId
+     * @param companyId
+     * @param externalId
+     * @param config
+     * @return
+     */
+    private String createLinkByMiniApp(QwSopCourseFinishTempSetting.Setting setting, String corpId, Date sendTime,
+                                       Integer courseId, Integer videoId, String qwUserId,
+                                       String companyUserId, String companyId, Long externalId, CourseConfig config) {
+
+        FsCourseLink link = createFsCourseLink(corpId, sendTime, courseId, videoId, qwUserId,
+                companyUserId, companyId, externalId, 3, null);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link, courseMap);
+
+        String courseJson = JSON.toJSONString(courseMap);
+        String realLinkFull = miniappRealLink + courseJson;
+        link.setRealLink(realLinkFull);
+
+        Date updateTime = createUpdateTime(setting, sendTime, config);
+
+        link.setUpdateTime(updateTime);
+        //存短链-
+        fsCourseLinkMapper.insertFsCourseLink(link);
+        return link.getRealLink();
+    }
+
+    /**
+     * 创建courselink
+     * @param corpId
+     * @param sendTime
+     * @param courseId
+     * @param videoId
+     * @param qwUserId
+     * @param companyUserId
+     * @param companyId
+     * @param externalId
+     * @param type
+     * @param chatId
+     * @return
+     */
+    public FsCourseLink createFsCourseLink(String corpId, Date sendTime, Integer courseId, Integer videoId, String qwUserId,
+                                           String companyUserId, String companyId, Long externalId, Integer type, String chatId) {
+        // 手动创建 FsCourseLink 对象,避免使用 BeanUtils.copyProperties
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(Long.parseLong(companyId));
+        link.setQwUserId(Long.valueOf(qwUserId));
+        link.setCompanyUserId(Long.parseLong(companyUserId));
+        link.setVideoId(videoId.longValue());
+        link.setCorpId(corpId);
+        link.setCourseId(courseId.longValue());
+        link.setChatId(chatId);
+        link.setQwExternalId(externalId);
+        link.setLinkType(type); //小程序
+        link.setUNo(UUID.randomUUID().toString());
+        String randomString = generateRandomStringWithLock();
+        if (StringUtil.strIsNullOrEmpty(randomString)) {
+            link.setLink(UUID.randomUUID().toString().replace("-", ""));
+        } else {
+            link.setLink(randomString);
+        }
+
+        link.setCreateTime(sendTime);
+
+        return link;
+    }
+
+
+    /**
+     * 计算过期时间
+     * @param setting
+     * @param sendTime
+     * @param config
+     * @return
+     */
+    private Date createUpdateTime(QwSopCourseFinishTempSetting.Setting setting, Date sendTime, CourseConfig config) {
+
+        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
+                ? config.getVideoLinkExpireDate()
+                : setting.getExpiresDays();
+
+//         使用 Java 8 时间 API 计算过期时间
+        LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        LocalDateTime expireDateTime = sendDateTime.plusDays(expireDays - 1);
+        expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
+        Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
+
+        return updateTime;
+    }
+
+    /**
+     * 增加看课记录
+     *
+     * @param sopId
+     * @param videoId
+     * @param courseId
+     * @param fsUserId
+     * @param qwUserId
+     * @param companyUserId
+     * @param companyId
+     * @param externalId
+     * @param startTime
+     * @param createTime
+     * @return
+     */
+    private Long addWatchLogIfNeeded(String sopId, Integer videoId, Integer courseId,
+                                     Long fsUserId, String qwUserId, String companyUserId,
+                                     String companyId, Long externalId, String startTime, Date createTime) {
+
+        try {
+            FsCourseWatchLog watchLog = new FsCourseWatchLog();
+            watchLog.setVideoId(videoId != null ? videoId.longValue() : null);
+            watchLog.setQwExternalContactId(externalId);
+            watchLog.setSendType(2);
+            watchLog.setQwUserId(Long.valueOf(qwUserId));
+            watchLog.setSopId(sopId);
+            watchLog.setDuration(0L);
+            watchLog.setCourseId(courseId != null ? courseId.longValue() : null);
+            watchLog.setCompanyUserId(companyUserId != null ? Long.valueOf(companyUserId) : null);
+            watchLog.setCompanyId(companyId != null ? Long.valueOf(companyId) : null);
+            watchLog.setCreateTime(createTime);
+            watchLog.setUpdateTime(createTime);
+            watchLog.setLogType(3);
+            watchLog.setUserId(fsUserId);
+            watchLog.setCampPeriodTime(convertStringToDate(startTime, "yyyy-MM-dd"));
+
+            //存看课记录
+            int i = fsCourseWatchLogMapper.insertOrUpdateFsCourseWatchLog(watchLog);
+            return watchLog.getLogId();
+        } catch (Exception e) {
+            log.error("插入观看记录失败:" + e.getMessage());
+            return null;
+        }
+    }
+
+
     /**
      * 解析模板设置
      */

+ 42 - 5
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -16,13 +16,11 @@ import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.course.config.CourseConfig;
-import com.fs.course.domain.FsCourseFinishTemp;
-import com.fs.course.domain.FsCourseWatchLog;
-import com.fs.course.domain.FsUserCourse;
-import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.domain.*;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
 import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.service.cache.IFsUserCourseVideoCacheService;
 import com.fs.course.vo.*;
 import com.fs.his.config.FsSysConfig;
@@ -127,6 +125,9 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     @Autowired
     private HyWatchLogMapper hyWatchLogMapper;
 
+    @Autowired
+    private IFsUserCoursePeriodService userCoursePeriodService;
+
     /**
      * 查询短链课程看课记录
      *
@@ -616,7 +617,26 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
 
     @Override
     public List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVO(FsCourseWatchLogListParam param) {
-        return fsCourseWatchLogMapper.selectFsCourseWatchLogListVO(param);
+        List<FsCourseWatchLogListVO> fsCourseWatchLogListVOS = fsCourseWatchLogMapper.selectFsCourseWatchLogListVO(param);
+        List<FsUserCoursePeriod> fsUserCoursePeriods = userCoursePeriodService.selectFsUserCoursePeriodList(new FsUserCoursePeriod());
+
+        // 将 fsUserCoursePeriods 转换为 Map,便于快速查找
+        Map<Long, String> periodIdToNameMap = fsUserCoursePeriods.stream()
+                .collect(Collectors.toMap(
+                        FsUserCoursePeriod::getPeriodId,
+                        FsUserCoursePeriod::getPeriodName,
+                        (existing, replacement) -> existing // 如果有重复key,保留现有的
+                ));
+
+        // 遍历并赋值
+        fsCourseWatchLogListVOS.forEach(vo -> {
+            String periodName = periodIdToNameMap.get(vo.getPeriodId());
+            if (periodName != null) {
+                vo.setPeriodIdName(periodName);
+            }
+        });
+
+        return fsCourseWatchLogListVOS;
     }
 
     @Override
@@ -1096,7 +1116,24 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     public List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVOexport(FsCourseWatchLogListParam param) {
 
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogMapper.selectFsCourseWatchLogListVOexport(param);
+
+        //查询所有营期
+        List<FsUserCoursePeriod> fsUserCoursePeriods = userCoursePeriodService.selectFsUserCoursePeriodList(new FsUserCoursePeriod());
+
         for (FsCourseWatchLogListVO item : list) {
+            //营期名称
+            if (ObjectUtils.isNotNull(item.getPeriodId())) {
+                // 获取匹配的periodName
+                String periodName = fsUserCoursePeriods.stream()
+                        .filter(period -> item.getPeriodId().equals(period.getPeriodId()))
+                        .map(FsUserCoursePeriod::getPeriodName)
+                        .findFirst()
+                        .orElse("无营期名称");
+                item.setPeriodIdName(periodName);
+            }else {
+                item.setPeriodIdName("自动发课无营期名称");
+            }
+
             // 项目
             if(ObjectUtils.isNotNull(item.getProject())) {
                 String sysCourseProject = DictUtils.getDictLabel("sys_course_project", String.valueOf(item.getProject()));

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

@@ -119,6 +119,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private static final String miniappRealLink = "/pages_course/video.html?course=";
     private static final String REAL_LINK_PREFIX = "/courseH5/pages/course/learning?course=";
     private static final String SHORT_LINK_PREFIX = "/courseH5/pages/course/learning?s=";
+    // 排除看课数量限制的公司集合
+    private static final Set<String> EXCLUDE_PROJECTS = new HashSet<>(Arrays.asList(
+           "福本源","宽益堂","叮当国医"
+    ));
     @Autowired
     ICompanyService companyService;
     @Autowired
@@ -1879,7 +1883,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             return ResponseResult.fail(504, "请观看最新的课程项目");
         }
         // 项目看课数限制
-        if(!"福本源".equals(signProjectName) && !"宽益堂".equals(signProjectName) && !CloudHostUtils.hasCloudHostName("弘德堂")) {
+        if(!EXCLUDE_PROJECTS.contains(signProjectName) && !CloudHostUtils.hasCloudHostName("弘德堂")) {
             Integer logCount = fsUserCourseMapper.selectTodayCourseWatchLogCountByUserIdAndProjectId(param.getUserId(), courseProject);
             if (Objects.isNull(watchCourseVideo) && logCount > 0) {
                 return ResponseResult.fail(504, "超过项目看课数量限制");

+ 7 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java

@@ -44,9 +44,16 @@ public class FsCourseWatchLogListVO extends BaseEntity
      * 项目
      */
     private Integer project;
+
+    /** 营期id */
+    private Long periodId;
+
     @Excel(name = "项目名称")
     private String projectName;
 
+    @Excel(name = "营期名称")
+    private String periodIdName;
+
     @Excel(name = "课程名称")
     private String courseName;
 

+ 9 - 0
fs-service/src/main/java/com/fs/qw/vo/QwSopCourseFinishTempSetting.java

@@ -107,6 +107,15 @@ public class QwSopCourseFinishTempSetting implements Serializable,Cloneable{
         // 原因
         private String sendRemarks;
 
+        // 封面标题
+        private String nickname;
+        //头像
+        private String avatar;
+        //封面图片地址
+        private String coverUrl;
+
+        //课程id
+        private Long courseId;
         @Override
         public Setting clone() {
             try {

+ 4 - 2
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -25,10 +25,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="campPeriodTime"    column="camp_period_time"    />
         <result property="lastHeartbeatTime"    column="last_heartbeat_time"    />
         <result property="project"    column="project"    />
+        <result property="periodId"    column="period_id"    />
     </resultMap>
 
     <sql id="selectFsCourseWatchLogVo">
-        select log_id, user_id,finish_time,send_finish_msg,sop_id,video_id,reward_type, log_type, create_time, update_time, qw_external_contact_id, duration, qw_user_id, company_user_id, company_id, course_id,camp_period_time,project from fs_course_watch_log
+        select log_id, user_id,finish_time,send_finish_msg,sop_id,video_id,reward_type, log_type, create_time, update_time, qw_external_contact_id, duration, qw_user_id, company_user_id, company_id, course_id,camp_period_time,project,period_id  from fs_course_watch_log
     </sql>
 
     <select id="selectFsCourseWatchLogList" parameterType="FsCourseWatchLog" resultMap="FsCourseWatchLogResult">
@@ -55,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
 
     <select id="selectFsCourseWatchLogListVO" resultType="com.fs.course.vo.FsCourseWatchLogListVO">
-        select l.log_id,l.project,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,
+        select l.log_id,l.project,l.period_id,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,
         l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
         cu.nick_name as company_user_name ,l.send_type,l.create_time,l.update_time,l.last_heartbeat_time,
         qu.qw_user_name,qec.name as external_user_name,c.company_id,u.avatar as fsAvatar,u.nick_name as fsNickName,qec.create_time as qec_create_time,
@@ -741,6 +742,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         SELECT
         l.log_id,
         l.project AS project,
+        l.period_id,
         l.user_id,
         l.log_type,
         SEC_TO_TIME(l.duration) AS duration,

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

@@ -53,7 +53,7 @@ public class StoreAfterSalesScrmController extends AppBaseController {
     private IFsStoreOrderScrmService orderService;
     @Login
     @ApiOperation("获取订单项列表")
-    @GetMapping("/getStoreOrderItems")
+    @GetMapping({"/getStoreOrderItems", "/getMyStoreOrderItemByOrderId"})
     public R getMyStoreOrderById(@RequestParam("orderId") Long orderId, HttpServletRequest request){
         List<FsStoreOrderItemVO> list=itemService.selectFsStoreOrderItemListByOrderId(orderId);
         FsStoreOrderScrm order=orderService.selectFsStoreOrderById(orderId);

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

@@ -90,7 +90,7 @@ public class UserScrmController extends AppBaseController {
             }
             return R.ok().put("user",user);
         } catch (Exception e){
-
+            log.error("【获取用户信息】:{}",e);
             return R.error("操作异常");
         }
     }