فهرست منبع

Merge branch 'dev/2024/0509/update-app-Y' of feifan/mall-backend-app into master

添加用户签到获取身价
Yangzw 11 ماه پیش
والد
کامیت
b78cb6a87a
26فایلهای تغییر یافته به همراه664 افزوده شده و 9 حذف شده
  1. 9 0
      feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/constant/DistriConstants.java
  2. 3 0
      feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/enums/ErrorCodeConstants.java
  3. 39 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/config/orderPercentageConfig.java
  4. 0 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/orderpercentage/OrderPercentageController.java
  5. 17 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/orderpercentage/vo/OrderPercentageRedisVO.java
  6. 90 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/UserSignInLogController.java
  7. 27 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogPageReqVO.java
  8. 29 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogRespVO.java
  9. 22 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogSaveReqVO.java
  10. 9 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/orderpercentage/OrderPercentageDO.java
  11. 36 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/usersigninlog/UserSignInLogDO.java
  12. 29 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/usersigninlog/UserSignInLogMapper.java
  13. 6 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/duser/DuserService.java
  14. 6 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusService.java
  15. 6 5
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusServiceImpl.java
  16. 55 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/usersigninlog/UserSignInLogService.java
  17. 189 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/usersigninlog/UserSignInLogServiceImpl.java
  18. 12 0
      feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/usersigninlog/UserSignInLogMapper.xml
  19. 3 0
      feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/DictTypeConstants.java
  20. 2 0
      feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/ErrorCodeConstants.java
  21. 6 0
      feifan-module-member/feifan-module-member-biz/pom.xml
  22. 17 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/admin/signin/vo/config/OrderPercentageRedisVO.java
  23. 5 1
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/signin/vo/record/AppMemberSignInConfigMoonRespVO.java
  24. 12 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java
  25. 18 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/convert/signin/MemberSignInRecordConvert.java
  26. 17 2
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/signin/MemberSignInRecordServiceImpl.java

+ 9 - 0
feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/constant/DistriConstants.java

@@ -19,4 +19,13 @@ public class DistriConstants {
 
     public static final Boolean IS_EFFECTIVE  = true;
 
+    //将身价参数存在redis中的前缀
+    public static final String DISTRI_ORDER_PERCENTAGE  = "distri:orderPercentage";
+
+    //默认的签到天数
+    public static final int DEFAULT_DAY = 0;
+
+    //每次签到加的天数
+    public static final int ONE_DAY = 1;
+
 }

+ 3 - 0
feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/enums/ErrorCodeConstants.java

@@ -30,4 +30,7 @@ public interface ErrorCodeConstants {
 
     // ========== 会员身价变化类别 T1_005_000_000 ==========
     ErrorCode SOCIAL_STATUS_CHANGE_CATEGORY_NOT_EXISTS = new ErrorCode(1_005_031_001, "会员身价变化类别不存在");
+    ErrorCode USER_SIGN_IN_LOG_NOT_EXISTS = new ErrorCode(1_005_031_002, "用户签到日志记录不存在");
+    ErrorCode REDIS_ORDER_PERCENTAGE_NOT_EXISTS = new ErrorCode(1_005_031_003, "缓存中没有找到存储的签到获取的身价值");
+
 }

+ 39 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/config/orderPercentageConfig.java

@@ -0,0 +1,39 @@
+package cn.newfeifan.mall.module.distri.config;
+
+import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
+import cn.newfeifan.mall.module.distri.controller.admin.orderpercentage.vo.OrderPercentageRedisVO;
+import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
+import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.DISTRI_ORDER_PERCENTAGE;
+
+/**
+ * 身价配置,服务器启动时,缓存到服务器的全局静态变量中
+ */
+@Slf4j
+@Component
+public class orderPercentageConfig {
+
+    @Resource
+    private OrderPercentageService orderPercentageService;
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @PostConstruct
+    public void init(){
+        OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
+        OrderPercentageRedisVO build = OrderPercentageRedisVO
+                .builder()
+                .signInSocialStatus(orderPercentageDO.getSignInSocialStatus())
+                .signInSocialStatusMax(orderPercentageDO.getSignInSocialStatusMax())
+                .build();
+        stringRedisTemplate.opsForValue().set(DISTRI_ORDER_PERCENTAGE, JsonUtils.toJsonString(build));
+        log.info("======初始化身价配置成功======");
+    }
+}

+ 0 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/orderpercentage/OrderPercentageController.java

@@ -72,7 +72,6 @@ public class OrderPercentageController {
 
     @GetMapping("/page")
     @Operation(summary = "获得积分相关计算浮动百分比设置分页")
-    @PreAuthorize("@ss.hasPermission('distri:order-percentage:query')")
     public CommonResult<PageResult<OrderPercentageRespVO>> getOrderPercentagePage(@Valid OrderPercentagePageReqVO pageReqVO) {
         PageResult<OrderPercentageDO> pageResult = orderPercentageService.getOrderPercentagePage(pageReqVO);
         return success(BeanUtils.toBean(pageResult, OrderPercentageRespVO.class));

+ 17 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/admin/orderpercentage/vo/OrderPercentageRedisVO.java

@@ -0,0 +1,17 @@
+package cn.newfeifan.mall.module.distri.controller.admin.orderpercentage.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "管理后台 - 服务启动时存放在redis中的数据 VO")
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class OrderPercentageRedisVO {
+    @Schema(description = "用户签到可获取的最大身价值")
+    private String signInSocialStatusMax;
+
+    @Schema(description = "签到获取身价")
+    private String signInSocialStatus;
+}

+ 90 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/UserSignInLogController.java

@@ -0,0 +1,90 @@
+package cn.newfeifan.mall.module.distri.controller.app.usersigninlog;
+
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogPageReqVO;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogRespVO;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogSaveReqVO;
+import cn.newfeifan.mall.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.CommonResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+
+import cn.newfeifan.mall.framework.excel.core.util.ExcelUtils;
+
+import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
+import static cn.newfeifan.mall.framework.operatelog.core.enums.OperateTypeEnum.*;
+
+import cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog.UserSignInLogDO;
+import cn.newfeifan.mall.module.distri.service.usersigninlog.UserSignInLogService;
+
+@Tag(name = "用户 APP - 用户签到日志")
+@RestController
+@RequestMapping("/distri/user-sign-in-log")
+@Validated
+public class UserSignInLogController {
+
+    @Resource
+    private UserSignInLogService userSignInLogService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建用户签到日志")
+    public CommonResult<AppMemberSignInRecordRespVO> createUserSignInLog() {
+        return success(userSignInLogService.createUserSignInLog());
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新用户签到日志")
+    public CommonResult<Boolean> updateUserSignInLog(@Valid @RequestBody UserSignInLogSaveReqVO updateReqVO) {
+        userSignInLogService.updateUserSignInLog(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除用户签到日志")
+    @Parameter(name = "id", description = "编号", required = true)
+    public CommonResult<Boolean> deleteUserSignInLog(@RequestParam("id") Long id) {
+        userSignInLogService.deleteUserSignInLog(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得用户签到日志")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    public CommonResult<UserSignInLogRespVO> getUserSignInLog(@RequestParam("id") Long id) {
+        UserSignInLogDO userSignInLog = userSignInLogService.getUserSignInLog(id);
+        return success(BeanUtils.toBean(userSignInLog, UserSignInLogRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得用户签到日志分页")
+    public CommonResult<PageResult<UserSignInLogRespVO>> getUserSignInLogPage(@Valid UserSignInLogPageReqVO pageReqVO) {
+        PageResult<UserSignInLogDO> pageResult = userSignInLogService.getUserSignInLogPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, UserSignInLogRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出用户签到日志 Excel")
+    @OperateLog(type = EXPORT)
+    public void exportUserSignInLogExcel(@Valid UserSignInLogPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<UserSignInLogDO> list = userSignInLogService.getUserSignInLogPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "用户签到日志.xls", "数据", UserSignInLogRespVO.class,
+                        BeanUtils.toBean(list, UserSignInLogRespVO.class));
+    }
+
+}

+ 27 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogPageReqVO.java

@@ -0,0 +1,27 @@
+package cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 用户签到日志分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class UserSignInLogPageReqVO extends PageParam {
+
+    @Schema(description = "签到的用户ID", example = "29837")
+    private Long userId;
+
+    @Schema(description = "连续签到天数")
+    private Integer runningDays;
+
+    @Schema(description = "操作时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 29 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogRespVO.java

@@ -0,0 +1,29 @@
+package cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 用户签到日志 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class UserSignInLogRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24258")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "签到的用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29837")
+    @ExcelProperty("签到的用户ID")
+    private Long userId;
+
+    @Schema(description = "连续签到天数", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("连续签到天数")
+    private Integer runningDays;
+
+    @Schema(description = "操作时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("操作时间")
+    private LocalDateTime createTime;
+
+}

+ 22 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/usersigninlog/vo/UserSignInLogSaveReqVO.java

@@ -0,0 +1,22 @@
+package cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.*;
+
+@Schema(description = "管理后台 - 用户签到日志新增/修改 Request VO")
+@Data
+public class UserSignInLogSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24258")
+    private Long id;
+
+    @Schema(description = "签到的用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29837")
+    @NotNull(message = "签到的用户ID不能为空")
+    private Long userId;
+
+    @Schema(description = "连续签到天数", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "连续签到天数不能为空")
+    private Integer runningDays;
+
+}

+ 9 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/orderpercentage/OrderPercentageDO.java

@@ -78,4 +78,13 @@ public class OrderPercentageDO extends BaseDO {
      */
     private String collectSocialStatus;
 
+    /**
+     * 用户签到可获取的最大身价值
+     */
+    private String signInSocialStatusMax;
+    /**
+     * 签到获取身价
+     */
+    private String signInSocialStatus;
+
 }

+ 36 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/usersigninlog/UserSignInLogDO.java

@@ -0,0 +1,36 @@
+package cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 用户签到日志 DO
+ *
+ * @author 非繁人
+ */
+@TableName("distri_user_sign_in_log")
+@KeySequence("distri_user_sign_in_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserSignInLogDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 签到的用户ID
+     */
+    private Long userId;
+    /**
+     * 连续签到天数
+     */
+    private Integer runningDays;
+
+}

+ 29 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/usersigninlog/UserSignInLogMapper.java

@@ -0,0 +1,29 @@
+package cn.newfeifan.mall.module.distri.dal.mysql.usersigninlog;
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogPageReqVO;
+import cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog.UserSignInLogDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户签到日志 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface UserSignInLogMapper extends BaseMapperX<UserSignInLogDO> {
+
+    default PageResult<UserSignInLogDO> selectPage(UserSignInLogPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<UserSignInLogDO>()
+                .eqIfPresent(UserSignInLogDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(UserSignInLogDO::getRunningDays, reqVO.getRunningDays())
+                .betweenIfPresent(UserSignInLogDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(UserSignInLogDO::getId));
+    }
+
+    default UserSignInLogDO selectByUserId(Long loginUserId){
+        return selectOne(UserSignInLogDO::getUserId, loginUserId);
+    }
+}

+ 6 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/duser/DuserService.java

@@ -57,6 +57,12 @@ public interface DuserService {
 
     DuserInfoVO getDuserInfo(Long userId);
 
+    /**
+     * 修改用户身价
+     * @param userId 用户编号
+     * @param social 身价值
+     * @param socialStatus 身价状态
+     */
     void updateDuserSocial(Long userId, Long social, Integer socialStatus);
 
     DuserDO getDuserByUser(Long userId);

+ 6 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusService.java

@@ -62,4 +62,10 @@ public interface SocialStatusService {
     SocialStatusBO calculateSocial(Long point);
 
 
+    /**
+     * 获取身价等级名称
+     * @param socialStatusId 身价编号
+     * @return 等级名称
+     */
+    String getSocialStatusName(Long socialStatusId);
 }

+ 6 - 5
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusServiceImpl.java

@@ -84,11 +84,7 @@ public class SocialStatusServiceImpl implements SocialStatusService {
         for (int i = 0; i < socialStatusDOS.size(); i++) {
             if (point < socialStatusDOS.get(i).getPoint()) {
                 socialStatusBO.setId(socialStatusDOS.get(i - 1).getId());
-                if (i + 1 >= socialStatusDOS.size()) {
-                    socialStatusBO.setSocialUpNeed(0L);
-                } else {
-                    socialStatusBO.setSocialUpNeed(socialStatusDOS.get(i).getPoint() - point);
-                }
+                socialStatusBO.setSocialUpNeed(socialStatusDOS.get(i).getPoint() - point);
                 break;
             }
         }
@@ -99,4 +95,9 @@ public class SocialStatusServiceImpl implements SocialStatusService {
         return socialStatusBO;
     }
 
+    @Override
+    public String getSocialStatusName(Long socialStatusId) {
+        return socialStatusMapper.selectById(socialStatusId).getName();
+    }
+
 }

+ 55 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/usersigninlog/UserSignInLogService.java

@@ -0,0 +1,55 @@
+package cn.newfeifan.mall.module.distri.service.usersigninlog;
+
+import javax.validation.*;
+
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogPageReqVO;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogSaveReqVO;
+import cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog.UserSignInLogDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
+
+/**
+ * 用户签到日志 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface UserSignInLogService {
+
+    /**
+     * 创建用户签到日志
+     *
+     * @return 日志
+     */
+    AppMemberSignInRecordRespVO createUserSignInLog();
+
+    /**
+     * 更新用户签到日志
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateUserSignInLog(@Valid UserSignInLogSaveReqVO updateReqVO);
+
+    /**
+     * 删除用户签到日志
+     *
+     * @param id 编号
+     */
+    void deleteUserSignInLog(Long id);
+
+    /**
+     * 获得用户签到日志
+     *
+     * @param id 编号
+     * @return 用户签到日志
+     */
+    UserSignInLogDO getUserSignInLog(Long id);
+
+    /**
+     * 获得用户签到日志分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 用户签到日志分页
+     */
+    PageResult<UserSignInLogDO> getUserSignInLogPage(UserSignInLogPageReqVO pageReqVO);
+
+}

+ 189 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/usersigninlog/UserSignInLogServiceImpl.java

@@ -0,0 +1,189 @@
+package cn.newfeifan.mall.module.distri.service.usersigninlog;
+
+import cn.newfeifan.mall.module.distri.controller.admin.orderpercentage.vo.OrderPercentageRedisVO;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogPageReqVO;
+import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogSaveReqVO;
+import cn.newfeifan.mall.module.distri.dal.dataobject.duser.DuserDO;
+import cn.newfeifan.mall.module.distri.enums.SocialStatusEnum;
+import cn.newfeifan.mall.module.distri.service.duser.DuserService;
+import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
+import cn.newfeifan.mall.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
+import cn.newfeifan.mall.module.member.convert.signin.MemberSignInRecordConvert;
+import cn.newfeifan.mall.module.member.dal.dataobject.signin.MemberSignInRecordDO;
+import cn.newfeifan.mall.module.member.service.signin.MemberSignInRecordService;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog.UserSignInLogDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.distri.dal.mysql.usersigninlog.UserSignInLogMapper;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.*;
+import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
+
+/**
+ * 用户签到日志 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class UserSignInLogServiceImpl implements UserSignInLogService {
+
+    @Resource
+    private UserSignInLogMapper userSignInLogMapper;
+
+    @Resource
+    private MemberSignInRecordService signInRecordService;
+
+    @Resource
+    private DuserService duserService;
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Resource
+    private SocialStatusService socialStatusService;
+
+    @Override
+    @Transactional
+    public AppMemberSignInRecordRespVO createUserSignInLog() {
+        //用户签到
+        Long loginUserId = getLoginUserId();
+        MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(loginUserId);
+
+        // 插入用户签到日志
+        UserSignInLogDO userSignInLogDO = userSignInLogMapper.selectByUserId(loginUserId);
+        if (userSignInLogDO == null) {
+            //代表还没有过签到记录
+            userSignInLogDO = UserSignInLogDO
+                    .builder()
+                    .userId(loginUserId)
+                    .runningDays(DEFAULT_DAY)
+                    .build();
+
+            userSignInLogMapper.insert(userSignInLogDO);
+        } else {
+            //如果是昨天签到过
+            if (isTargetYesterday(userSignInLogDO.getUpdateTime())) {
+                userSignInLogDO.setRunningDays(userSignInLogDO.getRunningDays() + ONE_DAY);
+            } else {
+                userSignInLogDO.setRunningDays(DEFAULT_DAY);
+            }
+
+            userSignInLogDO.setUpdateTime(LocalDateTime.now());
+            userSignInLogMapper.updateById(userSignInLogDO);
+        }
+
+        //计算用户签到获得身价
+        OrderPercentageRedisVO orderPercentageRedisVO = getOrderPercentageRedisVO();
+        long social = Long.parseLong(orderPercentageRedisVO.getSignInSocialStatus());
+
+        if(userSignInLogDO.getRunningDays() >= Integer.parseInt(orderPercentageRedisVO.getSignInSocialStatusMax())){
+            social = social + Long.parseLong(orderPercentageRedisVO.getSignInSocialStatusMax());
+        }else{
+            social = social + userSignInLogDO.getRunningDays();
+        }
+
+        //更新前用户身价等级
+        DuserDO duserByUserNow = duserService.getDuserByUser(loginUserId);
+        //更新用户身价
+        duserService.updateDuserSocial(loginUserId, social, SocialStatusEnum.SIGN_IN_SOCIAL.getStatus());
+
+        //更新后用户身价等级
+        DuserDO duserByUserAfter = duserService.getDuserByUser(loginUserId);
+
+        //判断是否升级
+        boolean upgradeOrNot = !duserByUserNow.getSocialStatusId().equals(duserByUserAfter.getSocialStatusId());
+        String socialStatusName = null;
+        if(upgradeOrNot){
+            socialStatusName = socialStatusService.getSocialStatusName(duserByUserAfter.getSocialStatusId());
+        }
+        // 返回
+        return MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO,upgradeOrNot,social,socialStatusName);
+    }
+
+    /**
+     * 获取身价固定值
+     * @return 签到身价固定值
+     */
+    private OrderPercentageRedisVO getOrderPercentageRedisVO() {
+        String s = stringRedisTemplate.opsForValue().get(DISTRI_ORDER_PERCENTAGE);
+        if (StringUtils.isEmpty(s)) {
+            throw exception(REDIS_ORDER_PERCENTAGE_NOT_EXISTS);
+        }
+        return JSONObject.parseObject(s, OrderPercentageRedisVO.class);
+    }
+
+    /**
+     * 判断给定的LocalDateTime是否为昨天
+     *
+     * @param targetTime 目标时间
+     * @return 如果目标时间是昨天,返回true;否则返回false
+     */
+    private boolean isTargetYesterday(LocalDateTime targetTime) {
+        // 获取当前系统时间的LocalDateTime
+        LocalDateTime now = LocalDateTime.now();
+
+        // 获取参考时间的ZonedDateTime,用于处理时区
+        ZonedDateTime referenceZonedDateTime = now.atZone(ZoneId.systemDefault());
+
+        // 获取目标时间的ZonedDateTime
+        ZonedDateTime targetZonedDateTime = targetTime.atZone(ZoneId.systemDefault());
+
+        // 计算两个时间之间的差值
+        long daysDiff = ChronoUnit.DAYS.between(referenceZonedDateTime.toLocalDate(), targetZonedDateTime.toLocalDate());
+
+        return daysDiff == -1; // 如果差值是-1,说明目标时间是昨天
+    }
+
+    @Override
+    public void updateUserSignInLog(UserSignInLogSaveReqVO updateReqVO) {
+        // 校验存在
+        validateUserSignInLogExists(updateReqVO.getId());
+        // 更新
+        UserSignInLogDO updateObj = BeanUtils.toBean(updateReqVO, UserSignInLogDO.class);
+        userSignInLogMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteUserSignInLog(Long id) {
+        // 校验存在
+        validateUserSignInLogExists(id);
+        // 删除
+        userSignInLogMapper.deleteById(id);
+    }
+
+    private void validateUserSignInLogExists(Long id) {
+        if (userSignInLogMapper.selectById(id) == null) {
+            throw exception(USER_SIGN_IN_LOG_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public UserSignInLogDO getUserSignInLog(Long id) {
+        return userSignInLogMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<UserSignInLogDO> getUserSignInLogPage(UserSignInLogPageReqVO pageReqVO) {
+        return userSignInLogMapper.selectPage(pageReqVO);
+    }
+
+}

+ 12 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/usersigninlog/UserSignInLogMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.distri.dal.mysql.usersigninlog.UserSignInLogMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>

+ 3 - 0
feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/DictTypeConstants.java

@@ -12,4 +12,7 @@ public interface DictTypeConstants {
      */
     String MEMBER_EXPERIENCE_BIZ_TYPE = "member_experience_biz_type";
 
+    //将身价参数存在redis中的前缀
+    String DISTRI_ORDER_PERCENTAGE  = "distri:orderPercentage";
+
 }

+ 2 - 0
feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/ErrorCodeConstants.java

@@ -55,4 +55,6 @@ public interface ErrorCodeConstants {
     ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_004_012_000, "用户分组不存在");
     ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除");
 
+    ErrorCode REDIS_ORDER_PERCENTAGE_NOT_EXISTS = new ErrorCode(1_004_012_002, "缓存中没有找到存储的签到获取的身价值");
+
 }

+ 6 - 0
feifan-module-member/feifan-module-member-biz/pom.xml

@@ -90,6 +90,12 @@
             <artifactId>feifan-spring-boot-starter-biz-ip</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.76</version> <!-- 或者使用更 recent 的版本 -->
+        </dependency>
+
     </dependencies>
 
 </project>

+ 17 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/admin/signin/vo/config/OrderPercentageRedisVO.java

@@ -0,0 +1,17 @@
+package cn.newfeifan.mall.module.member.controller.admin.signin.vo.config;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "管理后台 - 服务启动时存放在redis中的数据 VO")
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class OrderPercentageRedisVO {
+    @Schema(description = "用户签到可获取的最大身价值")
+    private String signInSocialStatusMax;
+
+    @Schema(description = "签到获取身价")
+    private String signInSocialStatus;
+}

+ 5 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/signin/vo/record/AppMemberSignInConfigMoonRespVO.java

@@ -1,6 +1,5 @@
 package cn.newfeifan.mall.module.member.controller.app.signin.vo.record;
 
-import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -25,4 +24,9 @@ public class AppMemberSignInConfigMoonRespVO {
 
     private Rules rules;
 
+    /**
+     * 签到获取的固定身价
+     */
+    private String signInSocialStatus;
+
 }

+ 12 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/signin/vo/record/AppMemberSignInRecordRespVO.java

@@ -21,4 +21,16 @@ public class AppMemberSignInRecordRespVO {
     @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    @Schema(description = "是否升级")
+    private boolean upgradeOrNot;
+
+    @Schema(description = "增加了多少身价")
+    private Long social;
+
+    @Schema(description = "身价等级名称")
+    private String socialStatusName;
+
+    @Schema(description = "连续签到天数")
+    private Integer continueDay;
+
 }

+ 18 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/convert/signin/MemberSignInRecordConvert.java

@@ -44,6 +44,24 @@ public interface MemberSignInRecordConvert {
     PageResult<AppMemberSignInRecordRespVO> convertPage02(PageResult<MemberSignInRecordDO> pageResult);
 
     AppMemberSignInRecordRespVO coverRecordToAppRecordVo(MemberSignInRecordDO memberSignInRecordDO);
+    default AppMemberSignInRecordRespVO coverRecordToAppRecordVo(MemberSignInRecordDO memberSignInRecordDO,boolean upgradeOrNot,Long social,String socialStatusName){
+        if ( memberSignInRecordDO == null ) {
+            return null;
+        }
+
+        AppMemberSignInRecordRespVO appMemberSignInRecordRespVO = new AppMemberSignInRecordRespVO();
+
+        appMemberSignInRecordRespVO.setDay( memberSignInRecordDO.getDay() );
+        appMemberSignInRecordRespVO.setPoint( memberSignInRecordDO.getPoint() );
+        appMemberSignInRecordRespVO.setExperience( memberSignInRecordDO.getExperience() );
+        appMemberSignInRecordRespVO.setCreateTime( memberSignInRecordDO.getCreateTime() );
+        appMemberSignInRecordRespVO.setContinueDay( memberSignInRecordDO.getContinueDay() );
+        appMemberSignInRecordRespVO.setUpgradeOrNot(upgradeOrNot);
+        appMemberSignInRecordRespVO.setSocial(social);
+        appMemberSignInRecordRespVO.setSocialStatusName(socialStatusName);
+
+        return appMemberSignInRecordRespVO;
+    }
 
     default MemberSignInRecordDO convert(Long userId, MemberSignInRecordDO lastRecord, List<MemberSignInConfigDO> configs) {
         // 1. 计算是第几天签到

+ 17 - 2
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/signin/MemberSignInRecordServiceImpl.java

@@ -2,6 +2,8 @@ package cn.newfeifan.mall.module.member.service.signin;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
+import cn.newfeifan.mall.module.member.controller.admin.signin.vo.config.OrderPercentageRedisVO;
+import com.alibaba.fastjson.JSONObject;
 import cn.newfeifan.mall.framework.common.enums.CommonStatusEnum;
 import cn.newfeifan.mall.framework.common.pojo.PageParam;
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
@@ -23,6 +25,7 @@ import cn.newfeifan.mall.module.member.service.level.MemberLevelService;
 import cn.newfeifan.mall.module.member.service.point.MemberPointRecordService;
 import cn.newfeifan.mall.module.member.service.user.MemberUserService;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -39,6 +42,8 @@ import java.util.Set;
 
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.newfeifan.mall.module.member.enums.DictTypeConstants.DISTRI_ORDER_PERCENTAGE;
+import static cn.newfeifan.mall.module.member.enums.ErrorCodeConstants.REDIS_ORDER_PERCENTAGE_NOT_EXISTS;
 import static cn.newfeifan.mall.module.member.enums.ErrorCodeConstants.SIGN_IN_RECORD_TODAY_EXISTS;
 
 /**
@@ -62,6 +67,9 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
     @Resource
     private MemberUserService memberUserService;
 
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
     @Override
     public AppMemberSignInRecordSummaryRespVO getSignInRecordSummary(Long userId) {
         // 1. 初始化默认返回信息
@@ -121,14 +129,21 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
 
         MemberSignInRecordDO lastRecord = signInRecordMapper.selectLastRecordByUserId(loginUserId);
         if (lastRecord!=null){
-            continueDays = lastRecord.getDay();
+            continueDays = lastRecord.getContinueDay();
+        }
+
+        String s = stringRedisTemplate.opsForValue().get(DISTRI_ORDER_PERCENTAGE);
+        if (StringUtils.isEmpty(s)) {
+            throw exception(REDIS_ORDER_PERCENTAGE_NOT_EXISTS);
         }
+        OrderPercentageRedisVO orderPercentageRedisVO = JSONObject.parseObject(s, OrderPercentageRedisVO.class);
 
         return AppMemberSignInConfigMoonRespVO.builder()
                 .days(days)
+                .signInSocialStatus(orderPercentageRedisVO.getSignInSocialStatus())
                 .continueDays(continueDays)
                 .rules(Rules.builder().build())
-                .continueDays(0).build();
+                .build();
     }