Commit be1ecf96d424bef5ffece08a60c5e11afa24540c
1 parent
477342d3
code review:会员签到逻辑
Showing
4 changed files
with
55 additions
and
57 deletions
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
| @@ -39,8 +39,7 @@ public interface ErrorCodeConstants { | @@ -39,8 +39,7 @@ public interface ErrorCodeConstants { | ||
| 39 | ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1004009001, "签到天数规则已存在"); | 39 | ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1004009001, "签到天数规则已存在"); |
| 40 | 40 | ||
| 41 | //========== 签到配置 1004010000 ========== | 41 | //========== 签到配置 1004010000 ========== |
| 42 | - ErrorCode SIGN_IN_RECORD_EXISTS = new ErrorCode(1004010000,"用户重复签到"); | ||
| 43 | - | 42 | + ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1004010000,"今日已签到,请勿重复签到"); |
| 44 | 43 | ||
| 45 | //========== 用户等级 1004011000 ========== | 44 | //========== 用户等级 1004011000 ========== |
| 46 | ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1004011000, "用户等级不存在"); | 45 | ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1004011000, "用户等级不存在"); |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInController.java
| 1 | package cn.iocoder.yudao.module.member.controller.app.signin; | 1 | package cn.iocoder.yudao.module.member.controller.app.signin; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 5 | import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; | 4 | import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; |
| 6 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; | 5 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; |
| 7 | import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; | 6 | import cn.iocoder.yudao.module.member.service.signin.MemberSignInRecordService; |
| @@ -14,42 +13,33 @@ import org.springframework.web.bind.annotation.RestController; | @@ -14,42 +13,33 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 14 | 13 | ||
| 15 | import javax.annotation.Resource; | 14 | import javax.annotation.Resource; |
| 16 | 15 | ||
| 17 | -/** | ||
| 18 | - * 描述 :用户签到相关信息接口 | ||
| 19 | - * Author :xiaqing | ||
| 20 | - * Date :2023-09-15 09:02 | ||
| 21 | - */ | 16 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 17 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 18 | + | ||
| 19 | +// TODO @xiaqing:sign-in | ||
| 22 | @Tag(name = "签到APP - 签到") | 20 | @Tag(name = "签到APP - 签到") |
| 23 | @RestController | 21 | @RestController |
| 24 | @RequestMapping("/member/signin") | 22 | @RequestMapping("/member/signin") |
| 25 | public class AppMemberSignInController { | 23 | public class AppMemberSignInController { |
| 26 | 24 | ||
| 27 | @Resource | 25 | @Resource |
| 28 | - MemberSignInRecordService signInRecordService; | ||
| 29 | - | ||
| 30 | - /** | ||
| 31 | - * 描述 :获取个人签到信息 | ||
| 32 | - * Author :xiaqing | ||
| 33 | - * Date :2023-09-15 12:56:47 | ||
| 34 | - */ | 26 | + private MemberSignInRecordService signInRecordService; |
| 35 | 27 | ||
| 28 | + // TODO @xiaqing:泛型: | ||
| 29 | + // TODO @xiaqing:合并到 AppMemberSignInRecordController 的 getSignInRecordSummary 里哈。 | ||
| 36 | @Operation(summary = "个人签到信息") | 30 | @Operation(summary = "个人签到信息") |
| 37 | @GetMapping("/get-summary") | 31 | @GetMapping("/get-summary") |
| 38 | public CommonResult getUserSummary(){ | 32 | public CommonResult getUserSummary(){ |
| 39 | - return CommonResult.success(signInRecordService.getUserSummary(SecurityFrameworkUtils.getLoginUserId())); | 33 | + return success(signInRecordService.getSignInRecordSummary(getLoginUserId())); |
| 40 | } | 34 | } |
| 41 | 35 | ||
| 42 | - | ||
| 43 | - /** | ||
| 44 | - * 描述 :用户签到 | ||
| 45 | - * Author :xiaqing | ||
| 46 | - * Date :2023-09-15 09:20:58 | ||
| 47 | - */ | 36 | + // TODO @xiaqing:泛型: |
| 37 | + // TODO @xiaqing:合并到 AppMemberSignInRecordController 的 createSignInRecord 里哈。 | ||
| 48 | @Operation(summary = "会员签到") | 38 | @Operation(summary = "会员签到") |
| 49 | @PostMapping("/create") | 39 | @PostMapping("/create") |
| 50 | public CommonResult create(){ | 40 | public CommonResult create(){ |
| 51 | - MemberSignInRecordDO recordDO = signInRecordService.create(SecurityFrameworkUtils.getLoginUserId()); | ||
| 52 | - return CommonResult.success(MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO)); | 41 | + MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(getLoginUserId()); |
| 42 | + return success(MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO)); | ||
| 53 | } | 43 | } |
| 54 | 44 | ||
| 55 | } | 45 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordService.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.member.service.signin; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.member.service.signin; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; | 5 | import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordPageReqVO; |
| 6 | -import cn.iocoder.yudao.module.member.controller.app.signin.vo.AppMemberSignInRecordRespVO; | ||
| 7 | import cn.iocoder.yudao.module.member.controller.app.signin.vo.AppMemberSignInSummaryRespVO; | 6 | import cn.iocoder.yudao.module.member.controller.app.signin.vo.AppMemberSignInSummaryRespVO; |
| 8 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; | 7 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO; |
| 9 | 8 | ||
| @@ -31,18 +30,21 @@ public interface MemberSignInRecordService { | @@ -31,18 +30,21 @@ public interface MemberSignInRecordService { | ||
| 31 | */ | 30 | */ |
| 32 | PageResult<MemberSignInRecordDO> getSignRecordPage(Long userId, PageParam pageParam); | 31 | PageResult<MemberSignInRecordDO> getSignRecordPage(Long userId, PageParam pageParam); |
| 33 | 32 | ||
| 34 | - | ||
| 35 | - MemberSignInRecordDO create(Long userId); | 33 | + /** |
| 34 | + * 创建签到记录 | ||
| 35 | + * | ||
| 36 | + * @param userId 用户编号 | ||
| 37 | + * @return 签到记录 | ||
| 38 | + */ | ||
| 39 | + MemberSignInRecordDO createSignRecord(Long userId); | ||
| 36 | 40 | ||
| 37 | /** | 41 | /** |
| 42 | + * 根据用户编号,获得个人签到统计信息 | ||
| 38 | * | 43 | * |
| 39 | - *功能描述: 根据用户id获取个人签到信息 | ||
| 40 | - * @param userId | ||
| 41 | - * @return | ||
| 42 | - * @author xiaqing | ||
| 43 | - * @date 2023-09-15 14:21:01 | 44 | + * @param userId 用户编号 |
| 45 | + * @return 个人签到统计信息 | ||
| 44 | */ | 46 | */ |
| 45 | - AppMemberSignInSummaryRespVO getUserSummary(Long userId); | 47 | + AppMemberSignInSummaryRespVO getSignInRecordSummary(Long userId); |
| 46 | 48 | ||
| 47 | 49 | ||
| 48 | } | 50 | } |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java
| @@ -37,27 +37,27 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -37,27 +37,27 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 37 | public class MemberSignInRecordServiceImpl implements MemberSignInRecordService { | 37 | public class MemberSignInRecordServiceImpl implements MemberSignInRecordService { |
| 38 | 38 | ||
| 39 | @Resource | 39 | @Resource |
| 40 | - private MemberSignInRecordMapper memberSignInRecordMapper; | ||
| 41 | - @Resource | ||
| 42 | private MemberSignInRecordMapper signInRecordMapper; | 40 | private MemberSignInRecordMapper signInRecordMapper; |
| 43 | @Resource | 41 | @Resource |
| 44 | private MemberSignInConfigMapper signInConfigMapper; | 42 | private MemberSignInConfigMapper signInConfigMapper; |
| 43 | + | ||
| 45 | @Resource | 44 | @Resource |
| 46 | private MemberUserApi memberUserApi; | 45 | private MemberUserApi memberUserApi; |
| 47 | 46 | ||
| 48 | - | ||
| 49 | @Override | 47 | @Override |
| 50 | - public AppMemberSignInSummaryRespVO getUserSummary(Long userId) { | 48 | + public AppMemberSignInSummaryRespVO getSignInRecordSummary(Long userId) { |
| 51 | AppMemberSignInSummaryRespVO vo = new AppMemberSignInSummaryRespVO(); | 49 | AppMemberSignInSummaryRespVO vo = new AppMemberSignInSummaryRespVO(); |
| 52 | vo.setTotalDay(0); | 50 | vo.setTotalDay(0); |
| 53 | vo.setContinuousDay(0); | 51 | vo.setContinuousDay(0); |
| 54 | vo.setTodaySignIn(false); | 52 | vo.setTodaySignIn(false); |
| 55 | //获取用户签到的记录,按照天数倒序获取 | 53 | //获取用户签到的记录,按照天数倒序获取 |
| 56 | List <MemberSignInRecordDO> signInRecordDOList = signInRecordMapper.selectListByUserId(userId); | 54 | List <MemberSignInRecordDO> signInRecordDOList = signInRecordMapper.selectListByUserId(userId); |
| 55 | + // TODO @xiaqing:if 空的时候,直接 return;这样括号少,逻辑更简洁; | ||
| 57 | if(!CollectionUtils.isEmpty(signInRecordDOList)){ | 56 | if(!CollectionUtils.isEmpty(signInRecordDOList)){ |
| 58 | //设置总签到天数 | 57 | //设置总签到天数 |
| 59 | - vo.setTotalDay(signInRecordDOList.size()); | 58 | + vo.setTotalDay(signInRecordDOList.size()); // TODO @xiaqing:是不是不用读取 signInRecordDOList 所有的,而是 count下,然后另外再读取一条最后一条; |
| 60 | //判断当天是否有签到复用校验方法 | 59 | //判断当天是否有签到复用校验方法 |
| 60 | + // TODO @xiaqing:不要用异常实现逻辑;还是判断哈; | ||
| 61 | try { | 61 | try { |
| 62 | validSignDay(signInRecordDOList.get(0)); | 62 | validSignDay(signInRecordDOList.get(0)); |
| 63 | vo.setTodaySignIn(false); | 63 | vo.setTodaySignIn(false); |
| @@ -69,6 +69,7 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -69,6 +69,7 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 69 | //下方计算连续签到从2天开始,此处直接设置一天连续签到 | 69 | //下方计算连续签到从2天开始,此处直接设置一天连续签到 |
| 70 | vo.setContinuousDay(1); | 70 | vo.setContinuousDay(1); |
| 71 | //判断连续签到天数 | 71 | //判断连续签到天数 |
| 72 | + // TODO @xiaqing:这里逻辑,想想怎么在简化下,可读性可以在提升下哈; | ||
| 72 | for (int i = 1; i < signInRecordDOList.size(); i++) { | 73 | for (int i = 1; i < signInRecordDOList.size(); i++) { |
| 73 | //前一天减1等于当前天数则说明连续,继续循环 | 74 | //前一天减1等于当前天数则说明连续,继续循环 |
| 74 | LocalDate cur = signInRecordDOList.get(i).getCreateTime().toLocalDate(); | 75 | LocalDate cur = signInRecordDOList.get(i).getCreateTime().toLocalDate(); |
| @@ -103,47 +104,50 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -103,47 +104,50 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 103 | userIds = convertSet(users, MemberUserRespDTO::getId); | 104 | userIds = convertSet(users, MemberUserRespDTO::getId); |
| 104 | } | 105 | } |
| 105 | // 分页查询 | 106 | // 分页查询 |
| 106 | - return memberSignInRecordMapper.selectPage(pageReqVO, userIds); | 107 | + return signInRecordMapper.selectPage(pageReqVO, userIds); |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | @Override | 110 | @Override |
| 110 | public PageResult<MemberSignInRecordDO> getSignRecordPage(Long userId, PageParam pageParam) { | 111 | public PageResult<MemberSignInRecordDO> getSignRecordPage(Long userId, PageParam pageParam) { |
| 111 | - return memberSignInRecordMapper.selectPage(userId, pageParam); | 112 | + return signInRecordMapper.selectPage(userId, pageParam); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | @Override | 115 | @Override |
| 115 | - public MemberSignInRecordDO create(Long userId) { | ||
| 116 | - //获取当前用户签到的最大天数 | 116 | + public MemberSignInRecordDO createSignRecord(Long userId) { |
| 117 | + // 获取当前用户签到的最大天数 | ||
| 118 | + // TODO @xiaqing:db 操作,dou封装到 mapper 中; | ||
| 119 | + // TODO @xiaqing:maxSignDay,是不是变量叫 lastRecord 会更容易理解哈; | ||
| 117 | MemberSignInRecordDO maxSignDay = signInRecordMapper.selectOne(new LambdaQueryWrapperX <MemberSignInRecordDO>() | 120 | MemberSignInRecordDO maxSignDay = signInRecordMapper.selectOne(new LambdaQueryWrapperX <MemberSignInRecordDO>() |
| 118 | .eq(MemberSignInRecordDO::getUserId, userId) | 121 | .eq(MemberSignInRecordDO::getUserId, userId) |
| 119 | .orderByDesc(MemberSignInRecordDO::getDay) | 122 | .orderByDesc(MemberSignInRecordDO::getDay) |
| 120 | .last("limit 1")); | 123 | .last("limit 1")); |
| 121 | - //判断是否重复签到 | 124 | + // 判断是否重复签到 |
| 122 | validSignDay(maxSignDay); | 125 | validSignDay(maxSignDay); |
| 123 | 126 | ||
| 127 | + // TODO @xiaqing:可以使用 // 进行注释 | ||
| 124 | /**1.查询出当前签到的天数**/ | 128 | /**1.查询出当前签到的天数**/ |
| 125 | - MemberSignInRecordDO sign = new MemberSignInRecordDO(); | ||
| 126 | - sign.setUserId(userId); | ||
| 127 | - //设置签到初始化天数 | ||
| 128 | - sign.setDay(1); | ||
| 129 | - //设置签到分数默认为0 | ||
| 130 | - sign.setPoint(0); | ||
| 131 | - //如果不为空则修改当前签到对应的天数 | 129 | + MemberSignInRecordDO sign = new MemberSignInRecordDO().setUserId(userId); // TODO @xiaqing:应该使用 record 变量,会更合适 |
| 130 | + sign.setDay(1); // 设置签到初始化天数 | ||
| 131 | + sign.setPoint(0); // 设置签到分数默认为 0 | ||
| 132 | + // 如果不为空则修改当前签到对应的天数 | ||
| 133 | + // TODO @xiaqing:应该是要判断连续哈,就是昨天; | ||
| 132 | if (maxSignDay != null) { | 134 | if (maxSignDay != null) { |
| 133 | sign.setDay(maxSignDay.getDay() + 1); | 135 | sign.setDay(maxSignDay.getDay() + 1); |
| 134 | } | 136 | } |
| 135 | /**2.获取签到对应的分数**/ | 137 | /**2.获取签到对应的分数**/ |
| 136 | - //获取所有的签到规则,按照天数排序,只获取启用的 | 138 | + // 获取所有的签到规则,按照天数排序,只获取启用的 TODO @xiaqing:不要使用 signInConfigMapper 直接查询,而是要通过 SigninConfigService; |
| 137 | List <MemberSignInConfigDO> configDOList = signInConfigMapper.selectList(new LambdaQueryWrapperX <MemberSignInConfigDO>() | 139 | List <MemberSignInConfigDO> configDOList = signInConfigMapper.selectList(new LambdaQueryWrapperX <MemberSignInConfigDO>() |
| 138 | .eq(MemberSignInConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | 140 | .eq(MemberSignInConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) |
| 139 | .orderByAsc(MemberSignInConfigDO::getDay)); | 141 | .orderByAsc(MemberSignInConfigDO::getDay)); |
| 140 | - //如果签到的天数大于最大启用的规则天数,直接给最大签到的分数 | 142 | + // 如果签到的天数大于最大启用的规则天数,直接给最大签到的分数 |
| 143 | + // TODO @xiaqing:超过最大配置的天数,应该直接重置到第一天哈; | ||
| 141 | MemberSignInConfigDO lastConfig = configDOList.get(configDOList.size() - 1); | 144 | MemberSignInConfigDO lastConfig = configDOList.get(configDOList.size() - 1); |
| 142 | if (sign.getDay() > lastConfig.getDay()) { | 145 | if (sign.getDay() > lastConfig.getDay()) { |
| 143 | sign.setPoint(lastConfig.getPoint()); | 146 | sign.setPoint(lastConfig.getPoint()); |
| 144 | } else { | 147 | } else { |
| 145 | configDOList.forEach(el -> { | 148 | configDOList.forEach(el -> { |
| 146 | - //循环匹配对应天数,设置对应分数 | 149 | + // 循环匹配对应天数,设置对应分数 |
| 150 | + // TODO @xiaqing:使用 equals;另外,这种不应该去遍历比较,从可读性来说,应该 CollUtil.findOne() | ||
| 147 | if (el.getDay() == sign.getDay()) { | 151 | if (el.getDay() == sign.getDay()) { |
| 148 | sign.setPoint(el.getPoint()); | 152 | sign.setPoint(el.getPoint()); |
| 149 | } | 153 | } |
| @@ -151,18 +155,21 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -151,18 +155,21 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 151 | }); | 155 | }); |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | - //3.插入当前签到获取的分数 | 158 | + // 3. 插入当前签到获取的分数 |
| 155 | signInRecordMapper.insert(sign); | 159 | signInRecordMapper.insert(sign); |
| 156 | - //4.返回给用户 | ||
| 157 | return sign; | 160 | return sign; |
| 158 | } | 161 | } |
| 159 | 162 | ||
| 160 | - void validSignDay(MemberSignInRecordDO signInRecordDO) { | 163 | + // TODO @xiaqing:校验使用 validate 动词哈;可以改成 validateSigned |
| 164 | + private void validSignDay(MemberSignInRecordDO signInRecordDO) { | ||
| 165 | + // TODO @xiaqing:代码格式:if () {} 要有括号哈 | ||
| 161 | if (signInRecordDO == null) | 166 | if (signInRecordDO == null) |
| 162 | return; | 167 | return; |
| 168 | + // TODO @xiaqing:可以直接使用 DateUtils.isToday() | ||
| 163 | LocalDate today = LocalDate.now(); | 169 | LocalDate today = LocalDate.now(); |
| 164 | if (today.equals(signInRecordDO.getCreateTime().toLocalDate())) { | 170 | if (today.equals(signInRecordDO.getCreateTime().toLocalDate())) { |
| 165 | - throw exception(ErrorCodeConstants.SIGN_IN_RECORD_EXISTS); | 171 | + throw exception(ErrorCodeConstants.SIGN_IN_RECORD_TODAY_EXISTS); |
| 166 | } | 172 | } |
| 167 | } | 173 | } |
| 174 | + | ||
| 168 | } | 175 | } |