Parcourir la source

Merge remote-tracking branch 'origin/企微聊天' into 企微聊天

yh il y a 1 semaine
Parent
commit
aecff6f26c
28 fichiers modifiés avec 255 ajouts et 25 suppressions
  1. 44 0
      fs-admin/src/main/java/com/fs/course/task/VideoTask.java
  2. 3 2
      fs-admin/src/main/java/com/fs/his/controller/FsStorePaymentController.java
  3. 1 1
      fs-admin/src/main/java/com/fs/his/task/Task.java
  4. 1 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyProfileController.java
  5. 7 1
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  6. 1 0
      fs-service/src/main/java/com/fs/company/param/CompanyUserEditParam.java
  7. 9 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  8. 1 0
      fs-service/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java
  9. 7 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  10. 2 0
      fs-service/src/main/java/com/fs/his/config/IntegralConfig.java
  11. 1 0
      fs-service/src/main/java/com/fs/his/enums/FsUserIntegralLogTypeEnum.java
  12. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java
  13. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserIntegralLogsMapper.java
  14. 6 0
      fs-service/src/main/java/com/fs/his/service/IFsArticleService.java
  15. 1 1
      fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java
  16. 58 1
      fs-service/src/main/java/com/fs/his/service/impl/FsArticleServiceImpl.java
  17. 6 4
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  18. 9 3
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  19. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java
  20. 2 2
      fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java
  21. 5 1
      fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml
  22. 6 0
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  23. 14 0
      fs-service/src/main/resources/mapper/his/FsUserIntegralLogsMapper.xml
  24. 31 1
      fs-user-app/src/main/java/com/fs/app/controller/ArticleController.java
  25. 9 1
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java
  26. 7 1
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java
  27. 7 1
      fs-user-app/src/main/java/com/fs/app/controller/store/CourseH5ScrmController.java
  28. 7 1
      fs-user-app/src/main/java/com/fs/app/controller/store/CourseScrmController.java

+ 44 - 0
fs-admin/src/main/java/com/fs/course/task/VideoTask.java

@@ -5,9 +5,14 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.*;
 import com.fs.course.mapper.*;
+import com.fs.course.param.FsCourseSendRewardUParam;
 import com.fs.course.service.IFsCourseTrafficLogService;
+import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.service.IFsUserVideoCommentService;
 import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserIntegralLogs;
+import com.fs.his.enums.FsUserIntegralLogTypeEnum;
+import com.fs.his.mapper.FsUserIntegralLogsMapper;
 import com.fs.his.mapper.FsUserMapper;
 import com.qcloud.cos.COSClient;
 import com.qcloud.cos.ClientConfig;
@@ -15,6 +20,7 @@ import com.qcloud.cos.auth.BasicCOSCredentials;
 import com.qcloud.cos.auth.COSCredentials;
 import com.qcloud.cos.model.ObjectMetadata;
 import com.qcloud.cos.region.Region;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,6 +33,7 @@ import java.time.ZoneId;
 import java.util.*;
 
 @Component("videoTask")
+@Slf4j
 public class VideoTask {
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
     private static final String YL_SECRET_ID = "AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT";
@@ -59,6 +66,10 @@ public class VideoTask {
 
     @Autowired
     private IFsCourseTrafficLogService iFsCourseTrafficLogService;
+    @Autowired
+    private FsUserIntegralLogsMapper fsUserIntegralLogsMapper;
+    @Autowired
+    private IFsUserCourseVideoService courseVideoService;
 
     public void autoNotShowVideo() {
         List<Long> list = videoMapper.selectNotAuditVideo();
@@ -254,4 +265,37 @@ public class VideoTask {
         iFsCourseTrafficLogService.saveCourseTrafficLog();
     }
 
+    /**
+     * 补发完课积分
+     */
+    public void reissueFinishVideoIntegral() {
+        List<FsCourseWatchLog> watchingLogs = courseWatchLogMapper.findWatchLogsIdExitAndFinish();
+        //查询积分记录 是否存在
+        for (FsCourseWatchLog watchingLog : watchingLogs) {
+            FsUserIntegralLogs queryParam = new FsUserIntegralLogs();
+            queryParam.setUserId(watchingLog.getUserId());
+            queryParam.setBusinessId(watchingLog.getLogId().toString());
+            queryParam.setLogType(FsUserIntegralLogTypeEnum.TYPE_17.getValue());
+            //查询积分记录 是否存在
+            Long num = fsUserIntegralLogsMapper.selectFsUserIntegralLogsListCOUNT(queryParam);
+            if (num == null || num == 0){
+                FsCourseSendRewardUParam param = new FsCourseSendRewardUParam();
+                param.setIsAuto(1);
+                param.setVideoId(watchingLog.getVideoId());
+                param.setQwUserId(watchingLog.getQwUserId().toString());
+                param.setCompanyUserId(watchingLog.getCompanyUserId());
+                param.setCompanyId(watchingLog.getCompanyId());
+                param.setCourseId(watchingLog.getCourseId());
+                param.setQwExternalId(watchingLog.getQwExternalContactId());
+                param.setSource(watchingLog.getWatchType() == 2?2:1);
+                param.setSendType(watchingLog.getSendType());
+                param.setPeriodId(watchingLog.getPeriodId());
+                param.setUserId(watchingLog.getUserId());
+                param.setAppId("");
+                courseVideoService.sendRewardByFsUser(param);
+                log.info("补发积分 userId:{},watchLogsId:{}",watchingLog.getUserId(),watchingLog.getLogId());
+            }
+        }
+    }
+
 }

+ 3 - 2
fs-admin/src/main/java/com/fs/his/controller/FsStorePaymentController.java

@@ -122,10 +122,11 @@ public class FsStorePaymentController extends BaseController
 
     @GetMapping(value = "getStatus/{paymentId}")
     public AjaxResult getStatus(@PathVariable("paymentId") Long paymentId,
-                                @RequestParam(value = "refundDate",required = false ) Date refundDate)
+                                @RequestParam(value = "refundDate",required = false ) Date refundDate,
+                                @RequestParam(value = "orgHfSeqId",required = false ) String orgHfSeqId)
     {
 
-        return AjaxResult.success( fsStorePaymentService.updateFsStorePaymentByDecryptForm(paymentId,refundDate));
+        return AjaxResult.success( fsStorePaymentService.updateFsStorePaymentByDecryptForm(paymentId,refundDate,orgHfSeqId));
     }
     @PreAuthorize("@ss.hasPermi('his:storePayment:refund')")
     @GetMapping(value = "refund/{paymentId}")

+ 1 - 1
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -599,7 +599,7 @@ public class Task {
         List<FsStorePayment> fsStorePayments = fsStorePaymentService.selectAllPayment();
         for (FsStorePayment fsStorePayment : fsStorePayments) {
             try{
-                fsStorePaymentService.updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId(),null);
+                fsStorePaymentService.updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId(),null,null);
             }catch (Exception e){
                 logger.error("同步支付失败:"+fsStorePayment.getPaymentId());
             }

+ 1 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyProfileController.java

@@ -85,6 +85,7 @@ public class CompanyProfileController extends BaseController
             loginUser.getUser().setPhonenumber(user.getPhonenumber());
             loginUser.getUser().setEmail(user.getEmail());
             loginUser.getUser().setSex(user.getSex());
+            loginUser.getUser().setImNickName(user.getImNickName());
             tokenService.setLoginUser(loginUser);
             return AjaxResult.success();
         }

+ 7 - 1
fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java

@@ -770,7 +770,13 @@ public class CompanyUserController extends BaseController {
                     ArrayList<Object> users = new ArrayList<>();
                     HashMap<String, String> map = new HashMap<>();
                     map.put("userID",userId);
-                    map.put("nickname",companyUser.getNickName());
+                    String imNickName = companyUser.getImNickName();
+                    if (StringUtils.isNotBlank(imNickName)) {
+                        map.put("nickname", imNickName);
+                    } else {
+                        map.put("nickname",companyUser.getNickName());
+                    }
+
                     map.put("faceURL",companyUser.getAvatar());
                     users.add(map);
                     requestBody = new JSONObject();

+ 1 - 0
fs-service/src/main/java/com/fs/company/param/CompanyUserEditParam.java

@@ -16,4 +16,5 @@ public class CompanyUserEditParam implements Serializable
     private String phonenumber;
     @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
     private String sex;
+    private String imNickName;
 }

+ 9 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -730,4 +730,13 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     List<Long> getExContactIdsIdsByWatchLogIds(@Param("watchLogIds")List<Long> watchLogIds);
 
     List<FsSopMyCourseH5LinkVO> getSopCourseH5StudyList(@Param("userId") Long userId);
+
+
+    List<FsCourseWatchLog> findWatchLogsIdExitAndFinish();
+
+    @Select("select * from fs_course_watch_log " +
+            "where video_id = #{videoId} " +
+            "and company_user_id = #{companyUserId} " +
+            "and user_id = #{userId} order by create_time desc limit 1")
+    FsCourseWatchLog getWatchCourseVideoByFsUser2(@Param("userId") Long userId, @Param("videoId") Long videoId, @Param("companyUserId") Long companyUserId);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java

@@ -38,5 +38,6 @@ public class FsCourseSendRewardUParam implements Serializable
     private String appId; //前端传来的小程序的appid
 
     private String code;
+    private Integer isAuto;
 
 }

+ 7 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -1520,7 +1520,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
 
             //服务号授权的,缺mpOpenId的重新登录
-            if (config.getMiniAppAuthType() == 2 && StringUtil.strIsNullOrEmpty(user.getMpOpenId())) {
+            if (param.getSource() != 3 && config.getMiniAppAuthType() == 2 && StringUtil.strIsNullOrEmpty(user.getMpOpenId())) {
                 return R.error(401, "授权后可继续!");
             }
 
@@ -1623,8 +1623,12 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         if (user == null) {
             return R.error("未识别到用户信息");
         }
-
-        FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByFsUser(param.getUserId(), param.getVideoId(), param.getCompanyUserId());
+        FsCourseWatchLog log = null;
+        if (param.getIsAuto() != null && param.getIsAuto() == 1) {
+            log = courseWatchLogMapper.getWatchCourseVideoByFsUser2(param.getUserId(), param.getVideoId(), param.getCompanyUserId());
+        } else {
+            log = courseWatchLogMapper.getWatchCourseVideoByFsUser(param.getUserId(), param.getVideoId(), param.getCompanyUserId());
+        }
         if (log == null) {
             return R.error("无记录");
         }

+ 2 - 0
fs-service/src/main/java/com/fs/his/config/IntegralConfig.java

@@ -28,4 +28,6 @@ public class IntegralConfig implements Serializable {
     private Integer integralSubscriptCourse;//付费课程订阅积分比例
     private Integer downloadAppIntegral; // 首次下载app获取积分
     private Integer integralPlayGame; // 首次下载app获取积分
+    private Integer integralArticle; // 观看文章(图文)一篇
+    private Integer integralArticleTime; // 观看文章(图文)一篇  多少秒算已看完
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/enums/FsUserIntegralLogTypeEnum.java

@@ -39,6 +39,7 @@ public enum FsUserIntegralLogTypeEnum {
 //    TYPE_27(27, "积分订单取消退回积分"),
     TYPE_28(28, "首次下载APP获取积分"),
     TYPE_29(29,"玩游戏获取积分"),
+    TYPE_30(30,"阅读文章获取积分")
     ;
 
 

+ 1 - 1
fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java

@@ -85,7 +85,7 @@ public interface FsIntegralGoodsMapper
             "<if test = 'maps.goodsType != null and maps.goodsType != 0     '> " +
             "and g.goods_type = #{maps.goodsType}  " +
             "</if>" +
-            " order by g.goods_id desc "+
+            " order by sort asc ,g.goods_id desc "+
             "</script>"})
     List<FsIntegralGoodsListUVO> selectFsIntegralGoodsListUVO(@Param("maps")FsIntegralGoodsListUParam param);
 

+ 4 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserIntegralLogsMapper.java

@@ -37,6 +37,9 @@ public interface FsUserIntegralLogsMapper
      */
     public List<FsUserIntegralLogs> selectFsUserIntegralLogsList(FsUserIntegralLogs fsUserIntegralLogs);
 
+
+    Long selectFsUserIntegralLogsListCOUNT(FsUserIntegralLogs fsUserIntegralLogs);
+
     /**
      * 新增积分记录
      *
@@ -139,4 +142,5 @@ public interface FsUserIntegralLogsMapper
     Long selectH5VideoIntegralCount(@Param("userId") Long userId,@Param("videoId") Long videoId);
 
     List<FsUserIntegralLogs> selectFsUserIntegralLogsByUserIdAndLogType(@Param("userId") Long userId, @Param("logType") Integer logType, @Param("date") LocalDate date);
+
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/IFsArticleService.java

@@ -1,6 +1,8 @@
 package com.fs.his.service;
 
 import java.util.List;
+
+import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.param.FsArticleListUParam;
 import com.fs.his.vo.FsArticleListUVO;
@@ -68,4 +70,8 @@ public interface IFsArticleService
     int updateFsArticleViews(Long articleId);
 
     List<FsArticleListVO> selectFsArticleListVO(FsArticle fsArticle);
+
+    R finishView(Long userId, Long articleId);
+
+    R queryFinishViewStatus(Long userId, Long articleId);
 }

+ 1 - 1
fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java

@@ -89,7 +89,7 @@ public interface IFsStorePaymentService
 
     List<FsStorePaymentExcelVO> selectFsStorePaymentExcelVO(FsStorePaymentParam fsStorePayment);
 
-    String updateFsStorePaymentByDecryptForm(Long paymentId, Date refundDate);
+    String updateFsStorePaymentByDecryptForm(Long paymentId, Date refundDate,String orgHfSeqId);
 
     R refundFsStorePayment(Long paymentId, String appId);
 

+ 58 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsArticleServiceImpl.java

@@ -1,16 +1,25 @@
 package com.fs.his.service.impl;
 
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
+import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.param.FsArticleListUParam;
+import com.fs.his.param.FsUserAddIntegralTemplateParam;
+import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.vo.FsArticleListUVO;
 import com.fs.his.vo.FsArticleListVO;
-import com.fs.his.vo.FsArticleVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsArticleMapper;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.service.IFsArticleService;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 文章Service业务层处理
@@ -23,6 +32,10 @@ public class FsArticleServiceImpl implements IFsArticleService
 {
     @Autowired
     private FsArticleMapper fsArticleMapper;
+    @Autowired
+    private  RedisCache redisCache;
+    @Autowired
+    private IFsUserIntegralLogsService userIntegralLogsService;
 
     /**
      * 查询文章
@@ -112,4 +125,48 @@ public class FsArticleServiceImpl implements IFsArticleService
     public List<FsArticleListVO> selectFsArticleListVO(FsArticle fsArticle) {
         return fsArticleMapper.selectFsArticleListVO(fsArticle);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R finishView(Long userId, Long articleId) {
+        //1.添加积分
+        // 先检查今天是否已领取
+        String today = DateUtils.getDate(); // 格式:2026-03-02
+        String finishViewKey = String.format("article:integral:%s:%s:%s", userId, articleId, today);
+        boolean success = redisCache.setIfAbsent(finishViewKey, "1", getSecondsUntilMidnight(), TimeUnit.SECONDS);
+        // 检查今天是否已领取
+        if (!success) {
+            return R.error("今日已领取该文章积分,明天再来吧");
+        }
+        FsUserAddIntegralTemplateParam param = new FsUserAddIntegralTemplateParam();
+        param.setUserId(userId);
+        param.setLogType(FsUserIntegralLogTypeEnum.TYPE_30.getValue());
+        param.setBusinessId(articleId.toString());
+        try {
+            R r = userIntegralLogsService.addIntegralTemplate(param);
+            if (!"200".equals(r.get("code").toString())) {
+                redisCache.deleteObject(finishViewKey);
+                return R.error("阅读文章领取积分失败:" + r.get("msg"));
+            }
+        } catch (Exception e) {
+            // 异常时删除缓存,允许用户重试
+            redisCache.deleteObject(finishViewKey);
+            return R.error("阅读文章领取积分失败");
+        }
+        return R.ok("今日已领取奖励!");
+    }
+
+    @Override
+    public R queryFinishViewStatus(Long userId, Long articleId) {
+        String today = DateUtils.getDate(); // 格式:2026-03-02
+        String finishViewKey = String.format("article:integral:%s:%s:%s", userId, articleId, today);
+        boolean isView = redisCache.hasKey(finishViewKey);
+        return R.ok().put("isView", isView ? 1 : 0);
+    }
+
+    private long getSecondsUntilMidnight() {
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay();
+        return ChronoUnit.SECONDS.between(now, midnight);
+    }
 }

+ 6 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -388,13 +388,15 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
                     fsStorePayment.setBusinessCode(newOrderSn);
                     fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
                 }
+                if (order.getStatus() != 2){
+                    try {
+                        fsStoreOrderService.createOmsOrder(order.getOrderId());
+                    } catch (ParseException e) {
 
-                try {
-                    fsStoreOrderService.createOmsOrder(order.getOrderId());
-                } catch (ParseException e) {
-
+                    }
                 }
 
+
             }
         }
 

+ 9 - 3
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -374,7 +374,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
     @Override
     @Transactional
-    public String updateFsStorePaymentByDecryptForm(Long paymentId,Date refundDate) {
+    public String updateFsStorePaymentByDecryptForm(Long paymentId,Date refundDate,String orgHfSeqId) {
         FsStorePayment fsStorePayment = fsStorePaymentMapper.selectFsStorePaymentByPaymentId(paymentId);
         if (fsStorePayment != null && fsStorePayment.getStatus() == 1) {
             //退款同步
@@ -384,7 +384,13 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                 refundQueryRequest.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(refundDate));
 //                refundQueryRequest.setOrgReqDate("20260128");
                 //自己传的
-                refundQueryRequest.setOrgReqSeqId("refund-"+fsStorePayment.getPayCode());
+                if (StringUtils.isNotBlank(orgHfSeqId)) {
+                    refundQueryRequest.setOrgHfSeqId(orgHfSeqId);
+                } else {
+                    refundQueryRequest.setOrgReqSeqId("refund-"+fsStorePayment.getPayCode());
+                }
+
+
                 refundQueryRequest.setAppId(fsStorePayment.getAppId());
                 try {
                     HuiFuRefundResult huiFuRefundResult = huiFuService.queryRefundOrder(refundQueryRequest);
@@ -1889,7 +1895,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                         if (fsStorePayment.getCreateTime().before(DateUtils.addDateDay(-20))) {
                             logger.info("定时任务:同步支付状态在20天前,取消同步,payment_id:{}",fsStorePayment.getPaymentId());
                         } else {
-                            updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId(),null);
+                            updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId(),null,null);
                             //查询是否改为已支付
                             FsStorePayment finalPayment = fsStorePaymentMapper.selectFsStorePaymentByPaymentId(fsStorePayment.getPaymentId());
                             try {

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java

@@ -394,6 +394,11 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
                     integralNum = param.getPoints() * config.getIntegralSubscriptCourse();
                     logsType = FsUserIntegralLogTypeEnum.TYPE_24;
                     break;
+                case 30: //阅读文章获取积分
+                    integralNum = config.getIntegralArticle();
+                    logsType = FsUserIntegralLogTypeEnum.TYPE_30;
+                    param.setRemark(DateUtils.getTime() + FsUserIntegralLogTypeEnum.TYPE_30.getDesc() + " " +integralNum);
+                    break;
                 default:
                     return R.error("积分类型错误,联系管理员");
             }

+ 2 - 2
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -455,7 +455,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         }
         for (UserInfo user : users) {
             updateUserInfo.setUserID(user.getUserID());
-            updateUserInfo.setNickname(companyUser.getNickName());
+            updateUserInfo.setNickname(StringUtils.isNotEmpty(companyUser.getImNickName())?companyUser.getImNickName():companyUser.getNickName());
             //updateUserInfo.setFaceURL(Optional.ofNullable(user.getFaceURL()).orElse("http://company.muyi88.com/profile/avatar/2025/09/10/35ed3564-aad9-4580-a746-5da01e24d2ab.jpeg"));
             updateUserInfo.setFaceURL("http://company.muyi88.com/prod-api/profile/avatar/2025/04/08/aa418999-6738-492d-9856-491916f714d9.jpeg");
             updateUserInfo.setEx(Optional.ofNullable(user.getEx()).orElse(""));
@@ -539,7 +539,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
         offlinePushInfo.setDesc(title);
         CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
-        offlinePushInfo.setTitle(companyUser.getNickName());
+        offlinePushInfo.setTitle(StringUtils.isNotEmpty(companyUser.getImNickName())?companyUser.getImNickName():companyUser.getNickName());
         offlinePushInfo.setIOSBadgeCount(true);
         offlinePushInfo.setIOSPushSound("");
 

+ 5 - 1
fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -45,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="doctorId"    column="doctor_id"    />
         <result property="bindCompanyUserId"    column="bind_company_user_id"    />
         <result property="unionId"    column="union_id"    />
+        <result property="imNickName"    column="im_nick_name"    />
         <association property="dept"    column="dept_id" javaType="CompanyDept" resultMap="deptResult" />
         <collection  property="roles"   javaType="java.util.List"        resultMap="RoleResult" />
     </resultMap>
@@ -238,6 +239,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="addressId != null">address_id,</if>
             <if test="domain != null">domain,</if>
             <if test="isAudit != null">`is_audit`,</if>
+            <if test="imNickName != null">im_nick_name,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyId != null">#{companyId},</if>
@@ -271,6 +273,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="addressId != null">#{addressId},</if>
             <if test="domain != null">#{domain},</if>
             <if test="isAudit != null">#{isAudit},</if>
+            <if test="imNickName != null">#{imNickName},</if>
         </trim>
     </insert>
     <insert id="insertQwIpadTotal">
@@ -317,6 +320,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isAudit != null">`is_audit` = #{isAudit},</if>
             <if test="doctorId != null">`doctor_id` = #{doctorId},</if>
             <if test="unionId != null">`union_id` = #{unionId},</if>
+            <if test="imNickName != null">im_nick_name = #{imNickName},</if>
         </trim>
         where user_id = #{userId}
     </update>
@@ -445,7 +449,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                u.create_time,u.id_card, u.remark,u.user_type,u.open_id,u.qr_code_weixin,u.qr_code_wecom,u.jpush_id,u.domain,u.is_audit,u.address_id,
                d.dept_id, d.parent_id, d.dept_name, d.order_num, d.leader, d.status as dept_status,
                r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,
-               u.is_need_register_member, u.is_allowed_all_register,u.doctor_id,u.union_id
+               u.is_need_register_member, u.is_allowed_all_register,u.doctor_id,u.union_id,u.im_nick_name
         from company_user u
                  left join company_dept d on u.dept_id = d.dept_id
                  left join company_user_role ur on u.user_id = ur.user_id

+ 6 - 0
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -1202,4 +1202,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
           AND l.create_time &lt; CURDATE() + INTERVAL 1 DAY
         order by l.create_time desc
     </select>
+    <select id="findWatchLogsIdExitAndFinish" resultType="com.fs.course.domain.FsCourseWatchLog">
+        SELECT log_id,user_id,video_id,qw_user_id,company_user_id,company_id,course_id,qw_external_contact_id,send_type,period_id,watch_type
+        FROM fs_course_watch_log
+        WHERE log_type = 2
+          AND finish_time >= NOW() - INTERVAL 10 MINUTE
+    </select>
 </mapper>

+ 14 - 0
fs-service/src/main/resources/mapper/his/FsUserIntegralLogsMapper.xml

@@ -33,6 +33,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
 
+    <select id="selectFsUserIntegralLogsListCOUNT" resultType="java.lang.Long">
+        select count(*) from fs_user_integral_logs
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="logType != null  and logType != ''"> and log_type = #{logType}</if>
+            <if test="integral != null "> and integral = #{integral}</if>
+            <if test="balance != null "> and balance = #{balance}</if>
+            <if test="businessId != null  and businessId != ''"> and business_id = #{businessId}</if>
+            <if test="createTime != null "> and create_time = #{createTime}</if>
+            <if test="businessType != null "> and business_type = #{businessType}</if>
+        </where>
+    </select>
+
     <select id="selectFsUserIntegralLogsById" parameterType="Long" resultMap="FsUserIntegralLogsResult">
         <include refid="selectFsUserIntegralLogsVo"/>
         where id = #{id}
@@ -47,6 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
     </select>
 
+
     <insert id="insertFsUserIntegralLogs" parameterType="FsUserIntegralLogs" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_integral_logs
         <trim prefix="(" suffix=")" suffixOverrides=",">

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

@@ -1,7 +1,9 @@
 package com.fs.app.controller;
 
 
+import com.fs.app.annotation.Login;
 import com.fs.app.utils.JwtUtils;
+import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.domain.FsArticleCate;
@@ -34,7 +36,7 @@ import java.util.Map;
 @Api("文章接口")
 @RestController
 @RequestMapping(value="/app/article")
-public class ArticleController {
+public class ArticleController extends AppBaseController{
 	@Autowired
     JwtUtils jwtUtils;
 	@Autowired
@@ -76,4 +78,32 @@ public class ArticleController {
 		return R.ok().put("data",article);
 	}
 
+	@Login
+	@ApiOperation("文章阅读完成")
+	@GetMapping("/finishView")
+	@RepeatSubmit
+	public R finishView(@RequestParam("articleId")Long articleId){
+		String userId;
+        try {
+            userId = getUserId();
+        } catch (Exception e) {
+            return R.error("获取用户信息错误,请重新登录!");
+        }
+		return articleService.finishView(Long.valueOf(userId),articleId);
+	}
+
+	@Login
+	@ApiOperation("查询今日文章阅读是否完成")
+	@GetMapping("/queryFinishViewStatus")
+	public R queryFinishViewStatus(@RequestParam("articleId")Long articleId){
+		String userId;
+		try {
+			userId = getUserId();
+		} catch (Exception e) {
+			return R.error("获取用户信息错误,请重新登录!");
+		}
+
+		return articleService.queryFinishViewStatus(Long.valueOf(userId),articleId);
+	}
+
 }

+ 9 - 1
fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java

@@ -16,6 +16,7 @@ import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.SecurityUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.course.dto.BatchSendCourseDTO;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
@@ -39,6 +40,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
 import java.util.HashMap;
 import java.util.Map;
@@ -158,12 +160,18 @@ public class CourseFsUserController extends AppBaseController {
     @PostMapping("/sendReward")
     @UserOperationLog(operationType = FsUserOperationEnum.SENDREWARD)
     @RepeatSubmit
-    public R sendReward(@RequestBody FsCourseSendRewardUParam param)
+    public R sendReward(@RequestBody FsCourseSendRewardUParam param, HttpServletRequest request)
     {
         if (ObjectUtil.isEmpty(param.getUserId())){
             Long userId = Long.parseLong(getUserId());
             param.setUserId(userId);
         }
+        String sourceType = request.getHeader("sourcetype");
+        if(StringUtils.isNotBlank(sourceType)){
+            if ("APP".equals(sourceType)) {
+                param.setSource(3);
+            }
+        }
         logger.info("zyp \n【发放奖励】2:{}",param);
         return courseVideoService.sendRewardByFsUser(param);
     }

+ 7 - 1
fs-user-app/src/main/java/com/fs/app/controller/course/CourseQwController.java

@@ -326,8 +326,14 @@ public class CourseQwController extends AppBaseController {
     @PostMapping("/sendReward")
     @RepeatSubmit
     @UserOperationLog(operationType = FsUserOperationEnum.SENDREWARD)
-    public R sendReward(@RequestBody @Valid FsCourseSendRewardUParam param)
+    public R sendReward(@RequestBody @Valid FsCourseSendRewardUParam param,HttpServletRequest request)
     {
+        String sourceType = request.getHeader("sourcetype");
+        if(StringUtils.isNotBlank(sourceType)){
+            if ("APP".equals(sourceType)) {
+                param.setSource(3);
+            }
+        }
         param.setUserId(Long.parseLong(getUserId()));
         logger.info("【发放奖励】3:{}",param);
         return courseVideoService.sendReward(param);

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

@@ -156,8 +156,14 @@ public class CourseH5ScrmController extends AppBaseController {
     @ApiOperation("发放奖励")
     @PostMapping("/sendReward")
     @RepeatSubmit
-    public R sendReward(@RequestBody FsCourseSendRewardUParam param)
+    public R sendReward(@RequestBody FsCourseSendRewardUParam param,HttpServletRequest request)
     {
+        String sourceType = request.getHeader("sourcetype");
+        if(StringUtils.isNotBlank(sourceType)){
+            if ("APP".equals(sourceType)) {
+                param.setSource(3);
+            }
+        }
         param.setUserId(Long.parseLong(getUserId()));
         logger.info("【发放奖励】4:{}",param);
         return courseVideoService.sendReward(param);

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

@@ -435,8 +435,14 @@ public class CourseScrmController extends AppBaseController {
     @ApiOperation("发放奖励")
     @PostMapping("/sendReward")
     @RepeatSubmit
-    public R sendReward(@RequestBody FsCourseSendRewardUParam param)
+    public R sendReward(@RequestBody FsCourseSendRewardUParam param,HttpServletRequest request)
     {
+        String sourceType = request.getHeader("sourcetype");
+        if(StringUtils.isNotBlank(sourceType)){
+            if ("APP".equals(sourceType)) {
+                param.setSource(3);
+            }
+        }
         param.setUserId(Long.parseLong(getUserId()));
         logger.info("zyp \n【发放奖励】5:{}",param);
         return courseVideoService.sendReward(param);