Browse Source

益寿缘app-新增查询奖品列表接口

cgp 1 week ago
parent
commit
9a15fba7f0

+ 3 - 0
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -154,6 +154,9 @@ public class FsUser extends BaseEntity
      * **/
     private Long qwUserId;
 
+    /** 首次登录注册App时间 */
+    private Date firstLoginTime;
+
     /** app登录后不为null(表示是否下载app) */
     private String historyApp;
     public void setNickName(String nickname)

+ 7 - 6
fs-service/src/main/java/com/fs/his/domain/FsUserRewards.java

@@ -11,13 +11,14 @@ import java.util.Date;
 public class FsUserRewards {
     private Long id;
     private Long fsUserId;
-    private String activityType;
-    private Integer rewardType;  // 1-红包 2-积分 3-商品
-    private Integer status;      // 0-待领取 1-已领取 2-已失效
+    private String activityType; //活动类型:FIRST_LOGIN-首次登录,WATCH_COURSE-看课
+    private Integer rewardType;  //奖品类型: 1-红包 2-积分 3-商品
+    private Integer status;      //奖品状态: 0-待领取 1-已领取 2-已失效
     private String orderCode;
-    private Long goodsId;        //商品/套餐包id
-    private Integer productType; //1-商品 2-套餐包
-    private Date grantTime;
+    private Integer productType; //产品类型: 1-药品 2-套餐包
+    private Long goodsId;        //产品id: 药品/套餐包id
+    private Date grantTime;      //奖品实际领取时间
     private Date createTime;
     private Date updateTime;
+    private Integer isFirstLogin; //是否是首次注册奖励:0-否 1-是
 }

+ 0 - 10
fs-service/src/main/java/com/fs/his/enums/ActivityTypeEnum.java

@@ -17,16 +17,6 @@ public enum ActivityTypeEnum {
      * 看课奖励
      */
     WATCH_COURSE("WATCH_COURSE", "看课奖励"),
-
-//    /**
-//     * 邀请好友奖励(预留)
-//     */
-//    INVITE_FRIEND("INVITE_FRIEND", "邀请好友奖励"),
-//
-//    /**
-//     * 签到奖励(预留)
-//     */
-//    SIGN_IN("SIGN_IN", "签到奖励")
     ;
 
     /**

+ 56 - 0
fs-service/src/main/java/com/fs/his/enums/RewardTypeEnum.java

@@ -0,0 +1,56 @@
+package com.fs.his.enums;
+/**
+ * App用户奖品类型枚举
+ *
+ * @author
+ * @date 2026-02-25
+ */
+public enum RewardTypeEnum {
+    /**
+     * 红包
+     */
+    RED_PACKET(1, "红包"),
+    /**
+     * 积分
+     */
+    POINT(2, "积分"),
+    /**
+     * 商品
+     */
+    GOODS(3, "商品");
+    /**
+     * 类型编码(对应数据库 reward_type 字段)
+     */
+    private final Integer code;
+
+    /**
+     * 类型描述
+     */
+    private final String desc;
+    /**
+     * 构造函数
+     *
+     * @param code 编码
+     * @param desc 描述
+     */
+    RewardTypeEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+    /**
+     * 获取编码
+     *
+     * @return 编码
+     */
+    public Integer getCode() {
+        return code;
+    }
+    /**
+     * 获取描述
+     *
+     * @return 描述
+     */
+    public String getDesc() {
+        return desc;
+    }
+}

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

@@ -93,7 +93,7 @@ public interface FsUserRewardsMapper {
      * @param id 主键ID
      * @param status 新状态
      * @param orderCode 订单号(可选)
-     * @param grantTime 发放时间
+     * @param grantTime 领取时间
      * @return 结果
      */
     public int updateStatus(@Param("id") Long id, 

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

@@ -1,10 +1,34 @@
 package com.fs.his.service;
 
+import com.fs.his.domain.FsUserRewards;
+
+import java.util.List;
+
 public interface IAppUserRewardService {
+
+    /**
+     * 判断指定用户是否满足首次注册登录的条件
+     * @param fsUserId 用户ID
+     * @return {@code true} 如果用户是首次登录;否则返回 {@code false}。
+     * */
+    public boolean checkFirstLoginRewardStatus(Long fsUserId);
+
+    /**
+     * 为当前用户增加首次注册登录待领取的奖励
+     * @param fsUserId 用户ID
+     * */
+    public void addUserFirstLoginRewards(Long fsUserId);
+
+    /**
+     * 获取当前用户所有的奖励
+     * @param fsUserRewards 查询条件
+     * @return 奖励列表
+     * */
+    public List<FsUserRewards> getMyRewardList(FsUserRewards fsUserRewards);
     /**
      * 用户领取奖励
      * @param fsUserId 用户ID
      * @param rewardsId 奖品ID
      * */
-    void claimRewards(Long fsUserId,Long rewardsId);
+    public void claimRewards(Long fsUserId,Long rewardsId);
 }

+ 110 - 8
fs-service/src/main/java/com/fs/his/service/impl/AppUserRewardServiceImpl.java

@@ -1,18 +1,27 @@
 package com.fs.his.service.impl;
 
+import cn.hutool.core.util.RandomUtil;
 import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserRewards;
 import com.fs.his.enums.ActivityTypeEnum;
+import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.mapper.FsUserRewardsMapper;
 import com.fs.his.service.IAppUserRewardService;
 import com.fs.his.strategy.RewardResult;
 import com.fs.his.strategy.RewardStrategy;
 import com.fs.his.strategy.RewardStrategyFactory;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 
 @Slf4j
 @Service
@@ -20,10 +29,103 @@ public class AppUserRewardServiceImpl implements IAppUserRewardService {
 
     @Autowired
     private FsUserRewardsMapper rewardsMapper;
+    
+    @Autowired
+    private FsUserMapper fsUserMapper;
 
     @Autowired
     private RewardStrategyFactory strategyFactory;
 
+    @Override
+    public boolean checkFirstLoginRewardStatus(Long fsUserId) {
+        // 1. 查用户表判断是否首次登录注册App
+        FsUser fsUser = fsUserMapper.selectFsUserById(fsUserId);
+        if (fsUser != null && fsUser.getFirstLoginTime() != null) {
+            log.info("用户:{}已注册登录过,非首次登录", fsUserId);
+            return false;
+        }
+
+        // 2. 查奖品表判断是否已发放奖励
+        String activityType = ActivityTypeEnum.FIRST_LOGIN.getCode();
+        FsUserRewards queryReward = rewardsMapper.selectByUserIdAndActivityType(fsUserId, activityType);
+        if (queryReward != null) {
+            log.info("用户:{}已下发过首次注册奖励, status={}", fsUserId, queryReward.getStatus());
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addUserFirstLoginRewards(Long fsUserId) {
+        String activityType = ActivityTypeEnum.FIRST_LOGIN.getCode();
+
+        // TODO 根据配置获取奖品类型
+        Integer rewardType = RandomUtil.randomInt(1, 4);
+
+        // 构建奖品记录
+        FsUserRewards reward = buildFirstLoginReward(fsUserId, activityType, rewardType);
+
+        try {
+            // 插入奖品表
+            int insertResult = rewardsMapper.insertFsUserRewards(reward);
+            if (insertResult > 0) {
+                // 更新用户表的首次登录时间
+                FsUser updateFsUser = new FsUser();
+                updateFsUser.setUserId(fsUserId);
+                updateFsUser.setFirstLoginTime(DateUtils.getNowDate());
+
+                int updateResult = fsUserMapper.updateFsUser(updateFsUser);
+
+                if (updateResult > 0) {
+                    log.info("用户首次注册奖励发放成功: userId={}, rewardType={}, rewardsId={}",
+                            fsUserId, rewardType, reward.getId());
+                } else {
+                    log.error("用户首次登录时间更新失败: userId={}, 但奖品已发放, rewardsId={}",
+                            fsUserId, reward.getId());
+                }
+            }
+        } catch (DuplicateKeyException e) {
+            log.info("用户首次注册奖励已存在: userId={}", fsUserId);
+        } catch (Exception e) {
+            log.error("用户首次注册奖励发放异常: userId={}, error={}", fsUserId, e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public List<FsUserRewards> getMyRewardList(FsUserRewards fsUserRewards) {
+        List<FsUserRewards> fsUserRewardsList = rewardsMapper.selectFsUserRewardsList(fsUserRewards);
+        if (CollectionUtils.isEmpty(fsUserRewardsList)){
+            return Collections.emptyList();
+        }
+        return fsUserRewardsList;
+    }
+
+    private FsUserRewards buildFirstLoginReward(Long fsUserId, String activityType, Integer rewardType) {
+        FsUserRewards reward = new FsUserRewards();
+        reward.setFsUserId(fsUserId);
+        reward.setActivityType(activityType);
+        reward.setRewardType(rewardType);
+        reward.setStatus(0); // 待领取
+        reward.setCreateTime(DateUtils.getNowDate());
+        reward.setIsFirstLogin(1); // 标记为首次注册奖励(用于虚拟列索引)
+
+        if (rewardType == 3) {
+            // TODO 根据配置设置具体的商品
+            reward.setProductType(1); // 1-药品
+            reward.setGoodsId(1L);    // 默认商品ID
+        }
+
+        return reward;
+    }
+
+    //为当前用户新增看课奖励
+    public void addUserWatchCourseRewards(Long fsUserId) {
+        //看课奖励可以有多个
+
+        //TODO 根据用户id从配置获取用户领取奖品类型、产品类型是
+    }
+
     @Override
     public void claimRewards(Long fsUserId,Long rewardsId) {
         FsUserRewards reward = rewardsMapper.selectByUserIdAndRewardsId(fsUserId, rewardsId);
@@ -31,29 +133,29 @@ public class AppUserRewardServiceImpl implements IAppUserRewardService {
             log.info("用户:{}没有奖品:{}", fsUserId, rewardsId);
             return;
         }
-        // 校验是否过期(目前只有看课奖需要校验过期)
+        // 校验是否过期(目前只有看课奖需要校验过期)
         if (ActivityTypeEnum.WATCH_COURSE.getCode().equals(reward.getActivityType())) {
             if (isExpired(reward.getCreateTime())) {
-                log.info("奖品已过期: rewardId={}", rewardsId);
+                log.info("奖品已过期: rewardsId={}", rewardsId);
                 // 更新奖品状态为已过期
-                rewardsMapper.updateStatus(reward.getId(), 2, null, new Date());
+                rewardsMapper.updateStatus(reward.getId(), 2, null, null);
                 return;
             }
         }
-        //执行奖品发放逻辑
+        //执行奖品领取逻辑
         RewardStrategy strategy = strategyFactory.getStrategy(reward.getActivityType(), reward.getRewardType());
         RewardResult result = strategy.process(reward);
         if (result.isSuccess()) {
             // 更新奖品状态
-            rewardsMapper.updateStatus(rewardsId, 1, result.getOrderCode(), new Date());
-            log.info("奖品发放成功: rewardId={}, orderCode={}", rewardsId, result.getOrderCode());
+            rewardsMapper.updateStatus(rewardsId, 1, result.getOrderCode(), DateUtils.getNowDate());
+            log.info("奖品领取成功: rewardsId={}, orderCode={}", rewardsId, result.getOrderCode());
         } else {
-            log.error("奖品发放失败: rewardId={}, reason={}", rewardsId, result.getMessage());
+            log.error("奖品领取失败: rewardsId={}, reason={}", rewardsId, result.getMessage());
             throw new CustomException(result.getMessage());
         }
     }
 
-    //奖品过期的判断方法
+    //奖品是否过期的判断方法
     private boolean isExpired(Date createTime) {
         // TODO 实现过期判断逻辑
         return false;

+ 5 - 1
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -48,10 +48,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="courseMaOpenId"    column="course_ma_open_id"    />
         <result property="qwExtId"    column="qw_ext_id"    />
         <result property="qwUserId"    column="qw_user_id"    />
+        <result property="firstLoginTime"    column="first_login_time"    />
     </resultMap>
 
     <sql id="selectFsUserVo">
-        select user_id,qw_ext_id,sex,is_buy,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id from fs_user
+        select user_id,qw_ext_id,sex,is_buy,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id,first_login_time from fs_user
     </sql>
 
     <select id="selectFsUserList" parameterType="FsUser" resultMap="FsUserResult">
@@ -606,6 +607,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id,</if>
             <if test="orderCount != null">order_count,</if>
             <if test="companyUserId != null">company_user_id,</if>
+            <if test="firstLoginTime != null">first_login_time,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="nickName != null">#{nickName},</if>
@@ -649,6 +651,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">#{companyId},</if>
             <if test="orderCount != null">#{orderCount},</if>
             <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="firstLoginTime != null">#{firstLoginTime},</if>
          </trim>
     </insert>
 
@@ -698,6 +701,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderCount != null">order_count = #{orderCount},</if>
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="firstLoginTime != null">first_login_time = #{firstLoginTime},</if>
         </trim>
         where user_id = #{userId}
     </update>

+ 4 - 4
fs-service/src/main/resources/mapper/his/FsUserRewardsMapper.xml

@@ -63,7 +63,7 @@
         order by create_time asc
     </select>
 
-    <!-- 更新条件查询列表 -->
+    <!-- 条件查询列表 -->
     <select id="selectFsUserRewardsList" parameterType="com.fs.his.domain.FsUserRewards" resultMap="FsUserRewardsResult">
         <include refid="selectFsUserRewardsVo"/>
         <where>
@@ -81,7 +81,7 @@
         order by create_time desc
     </select>
 
-    <!-- 更新新增记录 -->
+    <!-- 新增记录 -->
     <insert id="insertFsUserRewards" parameterType="com.fs.his.domain.FsUserRewards" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_rewards
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -108,7 +108,7 @@
         </trim>
     </insert>
 
-    <!-- 更新修改记录 -->
+    <!-- 修改记录 -->
     <update id="updateFsUserRewards" parameterType="com.fs.his.domain.FsUserRewards">
         update fs_user_rewards
         <trim prefix="SET" suffixOverrides=",">
@@ -129,7 +129,7 @@
     <update id="updateStatus">
         update fs_user_rewards
         set status = #{status},
-            order_code = #{orderCode},
+        <if test="orderCode != null">order_code = #{orderCode},</if>
             grant_time = #{grantTime},
             update_time = sysdate()
         where id = #{id}

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

@@ -19,6 +19,7 @@ import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserNewTask;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.service.IAppUserRewardService;
 import com.fs.his.service.IFsUserNewTaskService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
@@ -64,6 +65,9 @@ public class AppLoginController extends AppBaseController{
     @Autowired
     private ISmsService smsService;
 
+    @Autowired
+    private IAppUserRewardService appUserRewardService;
+
     @Autowired
     private RedisCache redisCache;
     @ApiOperation("注册app用户")
@@ -267,6 +271,8 @@ public class AppLoginController extends AppBaseController{
                 userService.insertFsUser(user);
                 map.put("isNew", true);
                 map.put("unionid",unionid);
+                // 尝试添加首次登录奖励
+                tryAddFirstLoginReward(user.getUserId());
                 return R.ok(map);
             } else {
                 if (StringUtils.isNotEmpty(param.getJpushId())) {
@@ -275,6 +281,8 @@ public class AppLoginController extends AppBaseController{
                 if (StringUtils.isEmpty(user.getPhone())) {
                     map.put("isNew", true);
                     map.put("unionid",user.getUnionId());
+                    // 尝试添加首次登录奖励
+                    tryAddFirstLoginReward(user.getUserId());
                     return R.ok(map);
                 }
             }
@@ -284,6 +292,8 @@ public class AppLoginController extends AppBaseController{
             map.put("token", token);
             map.put("user", user);
             map.put("isFirst",isFirstLogin);
+            // 尝试添加首次登录奖励
+            tryAddFirstLoginReward(user.getUserId());
             return R.ok(map);
         }catch (Exception e){
             logger.error("zyp 登录失败:{}", e.getMessage());
@@ -292,6 +302,15 @@ public class AppLoginController extends AppBaseController{
 
     }
 
+    // 尝试添加首次登录奖励
+    public void tryAddFirstLoginReward(Long fsUserId){
+        boolean rewardAdded = appUserRewardService.checkFirstLoginRewardStatus(fsUserId);
+        if (rewardAdded) {
+            appUserRewardService.addUserFirstLoginRewards(fsUserId);
+            log.info("用户首次登录奖励添加成功: userId={}", fsUserId);
+        }
+    }
+
     @PostMapping("/loginByPhone")
     public R loginByPhone(@RequestBody Map<String,String> map){
         logger.info("短信登录参数:{}",map.toString());

+ 66 - 4
fs-user-app/src/main/java/com/fs/app/controller/AppUserRewardController.java

@@ -2,15 +2,20 @@ package com.fs.app.controller;
 
 import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.StringUtils;
+import com.fs.his.domain.FsUserRewards;
+import com.fs.his.enums.ActivityTypeEnum;
+import com.fs.his.enums.RewardTypeEnum;
 import com.fs.his.service.IAppUserRewardService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Api("App用户奖励")
 @RestController
@@ -20,6 +25,39 @@ public class AppUserRewardController  extends AppBaseController{
     @Autowired
     private IAppUserRewardService appUserRewardService;
 
+    /**
+     * 判断是否有首次登录注册奖励
+     */
+    @Login
+    @ApiOperation("判断用户是否有首次登录注册奖励")
+    @GetMapping("/checkFirstLoginRewardStatus")
+    public R checkFirstLoginRewardStatus() {
+        String loginUserId = getUserId();
+        if (StringUtils.isEmpty(loginUserId)){
+            return R.error("请登录");
+        }
+        boolean result = appUserRewardService.checkFirstLoginRewardStatus(Long.valueOf(loginUserId));
+        return result ? R.ok() : R.error();
+    }
+    /**
+     * 查询我的奖品列表
+     */
+    @Login
+    @ApiOperation("查询用户的奖品列表")
+    @GetMapping("/getMyRewardList")
+    public TableDataInfo getMyRewardList(@RequestBody FsUserRewards queryRewards) {
+        String loginUserId = getUserId();
+        if (StringUtils.isEmpty(loginUserId)){
+            return getDataTable(Collections.emptyList());
+        }
+        queryRewards.setFsUserId(Long.valueOf(loginUserId));
+        startPage();
+        List<FsUserRewards> list = appUserRewardService.getMyRewardList(queryRewards);
+        if (CollectionUtils.isEmpty(list)){
+            return getDataTable(Collections.emptyList());
+        }
+        return getDataTable(list);
+    }
     /**
      * 领取奖励
      */
@@ -34,4 +72,28 @@ public class AppUserRewardController  extends AppBaseController{
         appUserRewardService.claimRewards(Long.valueOf(loginUserId),rewardsId);
         return R.ok();
     }
+    /**
+     * 查询奖品类型
+     */
+    @Login
+    @ApiOperation("查询奖品类型")
+    @GetMapping("/getRewardType")
+    public R getRewardType() {
+        RewardTypeEnum[] values = RewardTypeEnum.values();
+        R response = R.ok();
+        response.put("data", values);
+        return response;
+    }
+    /**
+     * 查询活动类型
+     */
+    @Login
+    @ApiOperation("查询活动类型")
+    @GetMapping("/activityType")
+    public R getActivityType() {
+        ActivityTypeEnum[] values = ActivityTypeEnum.values();
+        R response = R.ok();
+        response.put("data", values);
+        return response;
+    }
 }