Explorar el Código

Merge remote-tracking branch 'origin/Payment-Configuration' into Payment-Configuration

xgb hace 3 semanas
padre
commit
a9c04c5ca0

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

@@ -7,6 +7,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.ImTypeEnum;
+import com.fs.common.exception.file.OssException;
 import com.fs.common.utils.PatternUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.file.FileUploadUtils;
@@ -18,6 +19,8 @@ import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
 import com.fs.im.config.ImTypeConfig;
 import com.fs.im.service.OpenIMService;
+import com.fs.system.oss.CloudStorageService;
+import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -140,7 +143,12 @@ public class CompanyProfileController extends BaseController
         if (!file.isEmpty())
         {
             LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-            String avatar = FileUploadUtils.upload(FSConfig.getAvatarPath(), file);
+            if (file.isEmpty())
+            {
+                throw new OssException("上传文件不能为空");
+            }
+            CloudStorageService storage = OSSFactory.build();
+            String avatar = storage.uploadSuffix(file.getBytes(), ".jpg");
             if (userService.updateUserAvatar(loginUser.getUsername(), avatar)>0)
             {
                 AjaxResult ajax = AjaxResult.success();

+ 22 - 0
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -13,6 +13,7 @@ import com.fs.company.service.ICompanyMiniappService;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.domain.LuckyBagCollectRecord;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
@@ -26,6 +27,7 @@ import com.fs.live.mapper.LiveWatchLogMapper;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.domain.QwUserVideo;
+import com.fs.qw.mapper.LuckyBagCollectRecordMapper;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.service.IQwUserService;
@@ -38,6 +40,7 @@ import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.wxwork.dto.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -62,6 +65,7 @@ public class IpadSendServer {
     private final IFsCoursePlaySourceConfigService playSourceConfigService;
     private final FsUserMapper fsUserMapper;
     private final FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    private final LuckyBagCollectRecordMapper luckyBagCollectRecordMapper;
 
 
     private static final List<String> PROJECT_NAMES = Arrays.asList("济南联志健康", "北京存在文化","宽益堂");
@@ -607,6 +611,12 @@ public class IpadSendServer {
                     // 语音
                     sendWxVideo(vo, content);
                     break;
+                case "14":
+                    // 记录福袋发送记录
+                    addLuckyBagCollectRecord(vo, content,qwSopLogs);
+                    // 福袋
+                    sendMiniProgram(vo, content, miniMap,qwUser.getCompanyId());
+                    break;
                 case "99":
                     // 群发
                     sendTxtAtMsg(vo);
@@ -621,6 +631,18 @@ public class IpadSendServer {
             content.setSendRemarks("发送失败:" + e.getMessage());
         }
     }
+    private void addLuckyBagCollectRecord(BaseVo vo,QwSopCourseFinishTempSetting.Setting content,QwSopLogs qwSopLogs) {
+        try {
+            // 写入福袋发放记录
+            LuckyBagCollectRecord luckyBagCollectRecord = luckyBagCollectRecordMapper.selectLuckyBagCollectRecordById(Long.valueOf(content.getBusinessId()));
+            luckyBagCollectRecord.setSendTime(new Date());
+            luckyBagCollectRecord.setCollectType("0");
+            luckyBagCollectRecordMapper.updateLuckyBagCollectRecord(luckyBagCollectRecord);
+
+        }catch (Exception e){
+            log.error("ID:" + qwSopLogs.getId() + "-添加福袋记录失败", e);
+        }
+    }
 
     public void loginOut(QwUser user) {
         ipadSendUtils.loginOut(user.getUid(), user.getServerId());

+ 6 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseLinkMiniParam.java

@@ -30,4 +30,10 @@ public class FsCourseLinkMiniParam {
      */
     private String chatId;
 
+
+    /**
+     * 福袋选择id
+     */
+    private Long luckyBagId;
+
 }

+ 11 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.domain.LuckyBagCollectRecord;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
 import com.fs.course.param.newfs.FsUserCourseVideoLinkParam;
@@ -273,4 +274,14 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
      * @return list
      */
     List<OptionsVO> selectVideoOptionsByCourseId(Long courseId);
+
+    /**
+     * 创建app福袋
+     * @param param
+     * @return
+     */
+    R createAppFd(LuckyBagCollectRecord param);
+
+    R registerQwFsUserFinish(FsUserCourseVideoAddKfUParam param);
+
 }

+ 297 - 27
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
@@ -9,6 +10,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.constant.FsConstants;
 import com.fs.common.core.domain.R;
@@ -52,6 +56,7 @@ import com.fs.his.config.AppConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserIntegralLogs;
 import com.fs.his.domain.FsUserWx;
+import com.fs.his.mapper.FsPackageMapper;
 import com.fs.his.mapper.FsUserIntegralLogsMapper;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.WxSendRedPacketParam;
@@ -60,22 +65,22 @@ import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.vo.FsPackageListVO;
 import com.fs.his.vo.OptionsVO;
 import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.*;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
-import com.fs.qw.mapper.QwExternalContactMapper;
-import com.fs.qw.mapper.QwGroupChatMapper;
-import com.fs.qw.mapper.QwGroupChatUserMapper;
-import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.mapper.*;
 import com.fs.qw.param.FsUserCourseRedPageParam;
 import com.fs.qw.service.IQwCompanyService;
 import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qwApi.Result.QwAddContactWayResult;
 import com.fs.qwApi.param.QwAddContactWayParam;
 import com.fs.qwApi.service.QwApiService;
+import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.domain.SopUserLogsInfo;
 import com.fs.sop.mapper.SopUserLogsInfoMapper;
 import com.fs.sop.service.ISopUserLogsInfoService;
@@ -130,6 +135,10 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     @Autowired
     private OpenIMService openIMService;
     @Autowired
+    private LuckyBagMapper luckyBagMapper;
+    @Autowired
+    private LuckyBagCollectRecordMapper luckyBagCollectRecordMapper;
+    @Autowired
     private CompanyCompanyFsuserMapper companyCompanyFsuserMapper;
     private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
 
@@ -254,6 +263,9 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     @Autowired
     private IFsCourseLinkService linkService;
 
+    @Autowired
+    private FsPackageMapper fsPackageMapper;
+
 
     /**
      * 查询课堂视频
@@ -4447,6 +4459,146 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         }
     }
 
+    @Override
+    public R registerQwFsUserFinish(FsUserCourseVideoAddKfUParam param) {// 查询用户
+        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
+
+        // 不能反401 前端会絮乱
+        // 用户不存在唤起重新授权
+        if (fsUser == null) {
+            return R.error("用户不存在");
+        }
+//        if (StringUtils.isNotEmpty(fsUser.getNickName())
+//                &&fsUser.getNickName().equals("微信用户")) {
+//            return R.error(409, "请重新登录用户!");
+//        }
+        if (fsUser.getStatus() != null && fsUser.getStatus() == 0) {
+            return R.error("会员被停用,无权限,请联系客服!");
+        }
+
+        // 处理群聊逻辑
+        if (param.getChatId() != null && StringUtils.isNotEmpty(param.getChatId())) {
+            QwGroupChat qwGroupChat = qwGroupChatMapper.selectQwGroupChatByChatId(param.getChatId());
+            if (qwGroupChat == null) {
+                logger.error("群聊不存在,chatId: {}", param.getChatId());
+                return R.error("群聊不存在!");
+            }
+
+            SopUserLogsInfo sopUserLogsInfo = new SopUserLogsInfo();
+            sopUserLogsInfo.setChatId(param.getChatId());
+            List<QwGroupChatUser> qwGroupChatUsers = qwGroupChatUserMapper.selectByChatId(sopUserLogsInfo);
+
+            if (qwGroupChatUsers == null || qwGroupChatUsers.isEmpty()) {
+                logger.error("群聊用户为空,chatId: {}", param.getChatId());
+                return R.error("群聊用户为空!");
+            }
+
+            QwExternalContact qwExternalContact =
+                    qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+                            .eq("user_id", qwGroupChat.getOwner())
+                            .eq("fs_user_id", param.getUserId())
+                            .eq("corp_id", param.getCorpId())
+                            .eq("status",0));
+            if(null == qwExternalContact){
+                try{
+                    //修改成通过昵称匹配
+                    qwExternalContact =
+                            qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+                                    .eq("user_id", qwGroupChat.getOwner())
+                                    .eq("name", fsUser.getNickName())
+                                    .eq("corp_id", param.getCorpId())
+                                    .eq("status",0));
+                } catch(Exception e){
+                    log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),fsUser.getNickName(),param.getCorpId(),e);
+                }
+
+            }
+
+            if (qwExternalContact == null) {
+                return R.error("未查询到客户!");
+            }
+
+            QwExternalContact finalQwExternalContact = qwExternalContact;
+            if(qwGroupChatUsers.stream().noneMatch(e -> e.getUserId().equals(finalQwExternalContact.getExternalUserId()))){
+                log.error("客户不在群:{},里面:{}", qwGroupChat.getChatId(), qwExternalContact.getExternalUserId());
+                return R.error("客户不在群!");
+            }
+
+            logger.info("外部联系人数据:{}", qwExternalContact);
+
+            // 如果群在里面
+            if (qwExternalContact.getFsUserId() != null) {
+                // 有客户有小程序id,但登录的小程序id和根据外部联系人id查出来的小程序id不一致
+//                if (!qwExternalContact.getFsUserId().equals(param.getUserId())) {
+//                    logger.error("已注册,但绑定的userId,不一致param.getUserId{},qwExternalContact.getFsUserId(){}",param.getUserId(),qwExternalContact.getFsUserId());
+//                    return R.error("已注册!");
+//                }
+            }else {
+                // 未绑定
+                return R.error( "客户未绑定用户");
+            }
+
+
+        }else {
+            Long qwExternalId = param.getQwExternalId();
+
+            if (qwExternalId == null) {
+                return R.error("外部联系人ID不能为空");
+            }
+
+            // 查询外部联系人
+            QwExternalContact externalContact = qwExternalContactMapper.selectQwExternalContactById(qwExternalId);
+
+            // 如果查不出来客户信息,加好友
+            if (externalContact == null) {
+                return R.error("未查询到企微客户信息!");
+            }
+
+            if (externalContact.getFsUserId() != null) {
+                // 有客户有小程序id,但登录的小程序id和根据外部联系人id查出来的小程序id不一致
+//                if (!externalContact.getFsUserId().equals(param.getUserId())) {
+//                    logger.error("已注册,但绑定的userId,不一致param.getUserId{},qwExternalContact.getFsUserId(){}",param.getUserId(),externalContact.getFsUserId());
+//                    return R.error("已注册!");
+//                }
+            }else {
+                // 未绑定
+                return R.error( "客户未绑定用户");
+            }
+        }
+
+        return R.ok();
+    }
+
+    @Override
+    public R registerQwFsUser(FsUserCourseVideoAddKfUParam param) {
+        logger.info("zyp \n【判断添加客服】:{}", param);
+
+        // 参数校验
+        if (param == null) {
+            return R.error("参数不能为空");
+        }
+
+        // 查询用户
+        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
+
+        // 用户不存在唤起重新授权
+        if (fsUser == null) {
+            return R.error(401, "用户不存在");
+        }
+
+        if (fsUser.getStatus() != null && fsUser.getStatus() == 0) {
+            return R.error("会员被停用,无权限,请联系客服!");
+        }
+
+        // 处理群聊逻辑
+        if (param.getChatId() != null) {
+            return handleGroupChatLogic(param,fsUser);
+        }
+
+        // 处理普通外部联系人逻辑
+        return handleExternalContactLogic(param, fsUser);
+    }
+
 
     public void uploadSingleTaskWithRetry(FsVideoResource videoResource,Integer type) {
         int maxRetry = 3;
@@ -4556,38 +4708,156 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
 
         return link;
     }
+
     @Override
-    public R registerQwFsUser(FsUserCourseVideoAddKfUParam param) {
-        logger.info("zyp \n【判断添加客服】:{}", param);
+    public List<OptionsVO> selectVideoOptionsByCourseId(Long courseId) {
+        return fsUserCourseVideoMapper.selectVideoOptionsByCourseId(courseId);
+    }
 
-        // 参数校验
-        if (param == null) {
-            return R.error("参数不能为空");
-        }
+    @Override
+    public R createAppFd(LuckyBagCollectRecord param) {
 
-        // 查询用户
-        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
+        try {
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(param.getCompanyUserId());
+            if (companyUser==null||companyUser.getCompanyId()==null||companyUser.getUserId()==null){
+                return R.error("员工不存在!");
+            }
 
-        // 用户不存在唤起重新授权
-        if (fsUser == null) {
-            return R.error(401, "用户不存在");
+            Company company = companyMapper.selectCompanyById(param.getCompanyId());
+            if (company == null ) {
+                return  R.error().put("msg","企业不存在,请联系管理员");
+            }
+            String course = configService.selectConfigByKey("course.config");
+            CourseConfig config = JSON.parseObject(course, CourseConfig.class);
+            LocalDateTime sendDateTime = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+            LocalDateTime expireDateTime = sendDateTime.plusDays(config.getVideoLinkExpireDate() - 1);
+            expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
+            Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
+
+            Map<String,Object> business = addLuckyBagCollectRecord(param.getLuckyBagId(),param.getUserId(),updateTime,String.valueOf(param.getCompanyUserId()),String.valueOf(param.getCompanyId()));
+            String json = configService.selectConfigByKey("luckyBag.config");
+            Map<String, Object> luckyBagConfig = JSON.parseObject(json, Map.class);
+            business.put("img",luckyBagConfig.get("miniprogramPicUrl"));
+            return R.ok().put("data",business);
+        }catch (Exception e){
+            e.printStackTrace();
+            return R.error("发放福袋失败!");
         }
+    }
 
-        if (fsUser.getStatus() != null && fsUser.getStatus() == 0) {
-            return R.error("会员被停用,无权限,请联系客服!");
-        }
 
-        // 处理群聊逻辑
-        if (param.getChatId() != null) {
-            return handleGroupChatLogic(param,fsUser);
-        }
+    /**
+     * 增加福袋发放记录、领取记录
+     *
+     * @param luckyBagId
+     * @param userId
+     * @param sendTime
+     * @param companyUserId
+     * @param companyId
+     * @return
+     */
+    private Map<String,Object> addLuckyBagCollectRecord(Long luckyBagId,
+                                          Long userId,
+                                          Date sendTime,
+                                          String companyUserId,
+                                          String companyId) {
+        try {
 
-        // 处理普通外部联系人逻辑
-        return handleExternalContactLogic(param, fsUser);
+            if (StringUtils.isEmpty(companyId) || StringUtils.isEmpty(companyUserId)) {
+                log.warn("公司ID或用户ID为空 [companyId:{}, companyUserId:{}]", companyId, companyUserId);
+                return null;
+            }
+
+            // 验证福袋ID
+            if (luckyBagId == null) {
+                log.warn("福袋ID为空");
+                return null;
+            }
+
+            // 查询福袋信息
+            LuckyBag luckyBag = luckyBagMapper.selectLuckyBagById(luckyBagId);
+            if (luckyBag == null) {
+                log.warn("未找到对应的福袋信息 [luckyBagId:{}]", luckyBagId);
+                return null;
+            }
+
+            // 检查福袋状态
+            if (luckyBag.getDataStatus() != null && luckyBag.getDataStatus().equals(0)) {
+                log.warn("福袋被禁用 [luckyBagId:{}]", luckyBagId);
+                return null;
+            }
+
+            // 查询公司信息
+            Company company = companyMapper.selectCompanyById(Long.valueOf(companyId));
+            if (company == null) {
+                log.warn("未找到对应的公司信息 [companyId:{}]", companyId);
+                return null;
+            }
+
+            LuckyBagCollectRecord luckyBagCollectRecord = buildLuckyBagRecord(luckyBagId,userId,sendTime,
+                    companyUserId, companyId, company, luckyBag);
+
+            // 插入记录并返回ID
+            int result = luckyBagCollectRecordMapper.insertLuckyBagCollectRecord(luckyBagCollectRecord);
+            if (result <= 0) {
+                log.warn("福袋记录插入失败 [luckyBagId:{}]", luckyBagId);
+                return null;
+            }
+
+            // 返回新增记录的ID
+            Long recordId = luckyBagCollectRecord.getId();
+            if (recordId == null) {
+                log.warn("福袋记录插入成功但未返回ID [luckyBagId:{}]", luckyBagId);
+                return null;
+            }
+
+            log.info("福袋记录添加成功 [recordId:{}, luckyBagId:{}]", recordId, luckyBagId);
+            Map<String,Object> map = new HashMap<>();
+            map.put("recordId",recordId);
+            map.put("luckyBag",luckyBag);
+            return map;
+
+        } catch (NumberFormatException e) {
+            log.error("ID转换失败 [companyId:{}, companyUserId:{}]", companyId, companyUserId, e);
+            return null;
+        } catch (Exception e) {
+            log.error("ID:" + (luckyBagId != null ? luckyBagId : "unknown") + "-添加福袋记录失败", e);
+            return null;
+        }
     }
-    @Override
-    public List<OptionsVO> selectVideoOptionsByCourseId(Long courseId) {
-        return fsUserCourseVideoMapper.selectVideoOptionsByCourseId(courseId);
+
+    /**
+     * 构建福袋记录对象
+     */
+    private LuckyBagCollectRecord buildLuckyBagRecord(Long luckyBagId,
+                                                      Long userId,
+                                                      Date sendTime,
+                                                      String companyUserId,
+                                                      String companyId,
+                                                      Company company,
+                                                      LuckyBag luckyBag) {
+        LuckyBagCollectRecord record = new LuckyBagCollectRecord();
+        record.setLuckyBagId(luckyBagId);
+        record.setExpiryTime(sendTime);
+        record.setCollectType("0");
+        record.setSendTime(new Date());
+        record.setCompanyId(Long.valueOf(companyId));
+        record.setUserId(userId);
+        if (ObjectUtil.isNotEmpty(userId)){
+            FsUser fsUser = fsUserMapper.selectFsUserByUserId(userId);
+            record.setUserName(ObjectUtil.isNotEmpty(fsUser)?fsUser.getNickName():null);
+        }
+        record.setCompanyName(company.getCompanyName());
+        record.setCompanyUserId(Long.valueOf(companyUserId));
+
+        record.setRewardType(2L);
+
+        // 设置币种金额
+        if (luckyBag.getRewardType() != null && luckyBag.getRewardType().equals("1")) {
+            record.setCoinAmount(luckyBag.getAmount());
+        }
+
+        return record;
     }
 }
 

+ 11 - 0
fs-service/src/main/java/com/fs/course/vo/newfs/FsUserCourseVideoDetailsVO.java

@@ -1,5 +1,6 @@
 package com.fs.course.vo.newfs;
 
+import com.fs.his.vo.FsPackageListVO;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -44,4 +45,14 @@ public class FsUserCourseVideoDetailsVO {
     @ApiModelProperty(value = "题库内容")
     private List<FsUserVideoQuestionVO> questionBankList;
 
+    /**
+     * 疗法包套餐
+     */
+    private List<FsPackageListVO> treatmentPackage;
+
+    /**
+     * 疗法包展示
+     */
+    private String showTreatment;
+
 }

+ 48 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -3,18 +3,26 @@ package com.fs.app.controller;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.app.annotation.Login;
 import com.fs.app.param.*;
 import com.fs.app.utils.WxUtil;
 import com.fs.common.VerifyCodeUtil;
+import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.service.ISmsService;
 import com.fs.common.utils.sign.Md5Utils;
 import com.fs.core.config.WxOpenProperties;
+import com.fs.course.domain.LuckyBag;
+import com.fs.course.domain.LuckyBagCollectRecord;
+import com.fs.course.param.FsCourseLinkMiniParam;
+import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.his.config.FsSysConfig;
@@ -26,6 +34,9 @@ import com.fs.his.service.IFsUserNewTaskService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.FsUserRegisterParam;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.service.ILuckyBagService;
+import com.fs.voice.utils.StringUtil;
 import com.fs.watch.domain.WatchDeviceSetup;
 import com.fs.watch.domain.WatchUser;
 import com.fs.watch.service.WatchUserService;
@@ -63,7 +74,11 @@ public class AppLoginController extends AppBaseController{
     private IFsUserNewTaskService userNewTaskService;
     @Autowired
     private WxOpenProperties openProperties;
+    @Autowired
+    private ILuckyBagService luckyBagService;
 
+    @Autowired
+    private IFsUserCourseVideoService fsUserCourseVideoService;
     @Autowired
     private RedisCache redisCache;
 
@@ -951,4 +966,37 @@ public class AppLoginController extends AppBaseController{
         // 不存在,追加到末尾
         return currentAppIds + "," + newAppId;
     }
+
+
+
+    /**
+     * 创建 福袋
+     */
+
+    @RepeatSubmit
+    @PostMapping("/createFdMiniLink")
+    @Log(title = "createFdMiniLink", businessType = BusinessType.INSERT)
+    public R createAppFd(@RequestBody LuckyBagCollectRecord param) {
+
+        if (ObjectUtil.isEmpty(param.getLuckyBagId())){
+            return R.error("福袋id不能为空");
+        }
+        return fsUserCourseVideoService.createAppFd(param);
+    }
+    /**
+     * 查询福袋配置信息
+     *
+     * @param reward
+     * @return
+     */
+    @GetMapping("/luckyBagList")
+    public TableDataInfo list(LuckyBag reward)
+    {
+        reward.setDataStatus("1");
+
+        reward.setCompanyId(String.valueOf(reward.getCompanyId()));
+        startPage();
+        List<LuckyBag> list = luckyBagService.selectLuckyBagList(reward);
+        return getDataTable(list);
+    }
 }

+ 10 - 0
fs-user-app/src/main/java/com/fs/app/controller/CourseController.java

@@ -388,4 +388,14 @@ public class CourseController extends  AppBaseController{
 
 
 
+
+    @Login
+    @ApiOperation("判断是否注册")
+    @PostMapping("/registerQwFsUserFinish")
+    public R registerQwFsUserFinish(@RequestBody FsUserCourseVideoAddKfUParam param) {
+        Long userId = Long.parseLong(getUserId());
+        param.setUserId(userId);
+        return courseVideoService.registerQwFsUserFinish(param);
+    }
+
 }

+ 55 - 0
fs-user-app/src/main/java/com/fs/app/controller/LuckyBagController.java

@@ -0,0 +1,55 @@
+package com.fs.app.controller;
+
+import com.fs.app.annotation.Login;
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsUser;
+import com.fs.his.param.FsReceiveLuckyBagParam;
+import com.fs.his.service.IFsUserService;
+import com.fs.qw.service.ILuckyBagService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @description: 福袋控制器 福袋信息 领取福袋
+ * @author: Xgb
+ * @createDate: 2025/11/20
+ * @version: 1.0
+ */
+@Api("福袋接口")
+@RestController
+@RequestMapping(value="/app/luckyBag")
+public class LuckyBagController extends  AppBaseController {
+
+
+    @Autowired
+    private ILuckyBagService luckyBagService;
+
+    @Autowired
+    private IFsUserService userService;
+
+    @ApiOperation("获取福袋详情信息")
+    @GetMapping("/getLuckyBagInfo")
+    public R getLuckyBagInfo(@RequestParam("recordId")Long recordId, HttpServletRequest request){
+        return luckyBagService.getLuckyBagInfoByRecordId(recordId);
+    }
+
+    @Login
+    @ApiOperation("领取福袋")
+    @PostMapping("/receiveLuckyBag")
+    public R receiveLuckyBag(@RequestBody FsReceiveLuckyBagParam param, HttpServletRequest request){
+
+        Long userId = Long.parseLong(getUserId());
+//        Long userId = param.getUserId();
+        FsUser user=userService.selectFsUserByUserId(userId);
+        param.setUserId(user.getUserId());
+        param.setUserName(user.getNickName());
+        return luckyBagService.receiveLuckyBag(param,user);
+
+    }
+
+
+}

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

@@ -46,7 +46,7 @@ import java.util.concurrent.TimeUnit;
 
 @RestController
 @RequestMapping("/app/wx/mp")
-public class WxMpController {
+public class WxMpController extends AppBaseController{
   Logger logger= LoggerFactory.getLogger(getClass());
   @Autowired
   private WxMpService wxMpService;
@@ -197,6 +197,68 @@ public class WxMpController {
 
     }
 
+  @ApiOperation("课程短链公众号登录")
+  @PostMapping("/mpByLogin")
+  @Transactional
+  public R mpByLogin( @RequestBody FsUserLoginByMpParam param) {
+
+    if (StringUtils.isBlank(param.getCode())) {
+      return R.error("code不存在");
+    }
+    try{
+      wxMpService.switchoverTo("wxd59797042932c49a");
+      WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
+      WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
+      WxMpUserService wxMpUserService = wxMpService.getUserService();
+      WxMpUser userInfo = wxMpUserService.userInfo(wxMpUser.getOpenid());
+//      if (!userInfo.getSubscribe()){
+//        return R.error("请关注公众号进行登录");
+//      }
+      FsUser user=userService.selectFsUserByUnionid(wxMpUser.getUnionId());
+      if(user!=null){
+        FsUser userMap=new FsUser();
+        userMap.setUserId(user.getUserId());
+        userMap.setNickName(wxMpUser.getNickname());
+        userMap.setAvatar(wxMpUser.getHeadImgUrl());
+        userMap.setMpOpenId(wxMpUser.getOpenid());
+        userMap.setUpdateTime(new DateTime());
+        userService.updateFsUser(userMap);
+      }
+      else{
+        //写入
+//        String code=genCode();
+        user=new FsUser();
+//        user.setPhone(code);
+        user.setNickName(wxMpUser.getNickname());
+        user.setAvatar(wxMpUser.getHeadImgUrl());
+        user.setStatus(1);
+        user.setSex(wxMpUser.getSex());
+        user.setMpOpenId(wxMpUser.getOpenid());
+        user.setUnionId(wxMpUser.getUnionId());
+        user.setCreateTime(new Date());
+        userService.insertFsUser(user);
+      }
+      String token = jwtUtils.generateToken(user.getUserId());
+      redisCache.setCacheObject("token:"+user.getUserId(),token,604800, TimeUnit.SECONDS);
+      Map<String,Object> map=new HashMap<>();
+      map.put("token",token);
+      map.put("user",user);
+      logger.info("zyp \n 【点播公众号登录】:{}",user.getUserId());
+      return R.ok(map);
+
+    }
+    catch (WxErrorException e){
+      if(e.getError().getErrorCode()==40163){
+        return R.error(40163,e.getError().getErrorMsg());
+      }
+      else{
+        return R.error("授权失败,"+e.getMessage());
+      }
+    }
+
+  }
+
+
 
 
 

+ 83 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxUserController.java

@@ -8,6 +8,7 @@ import cn.hutool.core.date.DateTime;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
 import com.fs.app.annotation.UserOperationLog;
+import com.fs.app.param.FsUserLoginByMpParam;
 import com.fs.app.utils.JwtUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
@@ -460,4 +461,86 @@ public class WxUserController extends AppBaseController{
         return currentAppIds + "," + newAppId;
     }
 
+
+    @ApiOperation("处理用户与小程序的绑定")
+    @PostMapping("/handleFsUserWx")
+    public R handleFsUserWx(@RequestBody FsUserLoginByMpParam param) {
+
+        SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
+        List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
+        if (courseMaConfigs.isEmpty()){
+            return R.error("小程序配置为空");
+        }
+        // 根据appId匹配配置
+        CourseMaConfig matchedConfig = courseMaConfigs.stream()
+                .filter(config -> param.getAppId().equals(config.getAppid()))
+                .findFirst()
+                .orElse(null);
+
+        if (matchedConfig == null) {
+            return R.error("未找到匹配的小程序配置");
+        }
+        return handleCourseLogin1(param,
+                () -> WxMaConfiguration.getMaService(matchedConfig.getAppid()),
+                matchedConfig.getName());
+
+//    final WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
+//    try {
+//      //获取微信用户信息
+//      WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
+//
+//      FsUser user = userService.selectFsUserByUserId(param.getUserId());
+//      handleFsUserWx(user, param, session);
+//      return R.ok();
+//    } catch (WxErrorException e) {
+//      if (e.getError().getErrorCode() == 40163) {
+//        return R.error(40163, e.getError().getErrorMsg());
+//      } else {
+//        return R.error("获取用户信息失败," + e.getMessage());
+//      }
+//    }
+    }
+
+    private R handleCourseLogin1(FsUserLoginByMpParam param, Supplier<WxMaService> wxServiceSupplier, String logName) {
+        if (StringUtils.isBlank(param.getCode())) {
+            return R.error("code不存在");
+        }
+
+        try {
+            // 通过函数式接口获取不同的微信服务实例
+            final WxMaService wxService = wxServiceSupplier.get();
+            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
+            this.logger.info("获取{} Session:{}", logName, session);
+
+            FsUser user = userService.selectFsUserByUserId(param.getUserId());
+
+            handleFsUserWx(user, param,session);
+            return R.ok();
+        } catch (WxErrorException e) {
+            if (e.getError().getErrorCode() == 40163) {
+                return R.error(40163, e.getError().getErrorMsg());
+            } else {
+                return R.error("获取用户信息失败," + e.getMessage());
+            }
+        }
+    }
+
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+    /**
+     * 处理用户与小程序的绑定
+     */
+    private void handleFsUserWx(FsUser user, FsUserLoginByMpParam param, WxMaJscode2SessionResult session) {
+        if (user == null) return;
+        FsUserWx fsUserWx = new FsUserWx();
+        fsUserWx.setType(1);
+        fsUserWx.setFsUserId(user.getUserId());
+        fsUserWx.setAppId(param.getAppId());
+        fsUserWx.setOpenId(session.getOpenid());
+        fsUserWx.setUnionId(session.getUnionid() != null ? session.getUnionid() : null);
+        fsUserWx.setCreateTime(new Date());
+        fsUserWx.setUpdateTime(new Date());
+        fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
+    }
+
 }