feat:清理过期会员

This commit is contained in:
dzc committed 2025-12-05 17:10:01 +08:00
1 parent 7d74e96a94
commit e1e3521d7f
22 files changed
+256 -16

No files matched your search

@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserCreateReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageCodeDO;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageCodeService;
import io.swagger.v3.oas.annotations.Operation;
@@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -18,12 +18,13 @@ public enum MemberRecentTagEnum {
TRUE_PERSON_AUTH("1", "真人认证"),
NEW_PERSON("2", "新人"),
HOME_RECOMMEND("3", "首页推荐"),
VIP("4", "VIP用户"),
;
private final String type;
private final String description;
public static MemberRecentTagEnum valueOfType(String type) {
return Arrays.asList(values()).stream().filter(v-> ObjectUtil.equals(v.type, type)).findFirst().orElse(null);
return Arrays.asList(values()).stream().filter(v -> ObjectUtil.equals(v.type, type)).findFirst().orElse(null);
}
}
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 会员配置 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -36,4 +37,7 @@ public class MemberConfigBaseVO {
@Schema(description = "普通用户每天可以和人发几次消息")
private Integer defaultChatUserMsgCout;
@Schema(description = "举报类型")
private List<String> reportTypeList;
}
@@ -58,6 +58,12 @@ public class OperationPageReqVO extends PageParam {
@Schema(description = "举报类型")
private String reportType;
@Schema(description = "举报问题描述")
private String reportDescription;
@Schema(description = "举报图片")
private String reportPic;
@Schema(description = "身材评分")
private Integer scoreSc;
@@ -56,6 +56,12 @@ public class OperationRespVO {
@ExcelProperty("举报类型")
private String reportType;
@Schema(description = "举报问题描述")
private String reportDescription;
@Schema(description = "举报图片")
private String reportPic;
@Schema(description = "身材评分")
@ExcelProperty("身材评分")
private Integer scoreSc;
@@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.member.controller.admin.recent.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 朋友圈操作新增/修改 Request VO")
@@ -35,6 +38,12 @@ public class OperationSaveReqVO {
@Schema(description = "举报类型", example = "2")
private String reportType;
@Schema(description = "举报问题描述")
private String reportDescription;
@Schema(description = "举报图片")
private String reportPic;
@Schema(description = "身材评分")
private Integer scoreSc;
@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.member.controller.app.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.member.controller.admin.config.vo.MemberConfigRespVO;
import cn.iocoder.yudao.module.member.convert.config.MemberConfigConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO;
import cn.iocoder.yudao.module.member.service.config.MemberConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 会员设置")
@RestController
@RequestMapping("/member/config")
@Validated
public class AppMemberConfigController {
@Resource
private MemberConfigService memberConfigService;
@GetMapping("/get")
@Operation(summary = "获得会员配置")
public CommonResult<MemberConfigRespVO> getConfig() {
MemberConfigDO config = memberConfigService.getConfig();
return success(MemberConfigConvert.INSTANCE.convert(config));
}
}
@@ -25,6 +25,12 @@ public class AppRecentOperateReqVo {
@Schema(description = "举报类型")
private String reportType;
@Schema(description = "举报问题描述")
private String reportDescription;
@Schema(description = "举报图片")
private String reportPic;
@Schema(description = "身材评分")
private Integer scoreSc;
@@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.member.controller.app.user;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.member.client.service.ChatApi;
import cn.iocoder.yudao.module.member.controller.admin.opentype.vo.OpenTypeExtReqVO;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
@@ -10,7 +9,6 @@ import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberRecentTagDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
import cn.iocoder.yudao.module.member.service.opentype.OpenTypeService;
import cn.iocoder.yudao.module.member.service.recent.RecentService;
import cn.iocoder.yudao.module.member.service.user.MemberRecentTagService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import io.swagger.v3.oas.annotations.Operation;
@@ -54,7 +52,7 @@ public class AppMemberUserController {
List<MemberRecentTagDO> memberRecentTagList = memberRecentTagService.getByMemberId(user.getId());
result.setMemberTagList(memberRecentTagList);
// 获取用户会员信息
OpenTypeExtReqVO vipExt = openTypeService.getExtByMemeberId(user.getId());
OpenTypeExtBO vipExt = openTypeService.getExtByMemeberId(user.getId());
result.setMemberVip(vipExt);
return success(result);
}
@@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.member.controller.app.user.vo;
import cn.iocoder.yudao.module.member.controller.admin.opentype.vo.OpenTypeExtReqVO;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberRecentTagDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
@@ -62,7 +62,7 @@ public class AppMemberUserInfoRespVO {
private List<MemberRecentTagDO> memberTagList;
@Schema(description = "用户会员信息")
private OpenTypeExtReqVO memberVip;
private OpenTypeExtBO memberVip;
@Schema(description = "用户 App - 会员等级")
@Data
@@ -2,10 +2,14 @@ package cn.iocoder.yudao.module.member.dal.dataobject.config;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import java.util.List;
/**
* 会员配置 DO
*
@@ -59,4 +63,10 @@ public class MemberConfigDO extends BaseDO {
*/
private Integer defaultChatUserMsgCout;
/**
* 举报类型
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> reportTypeList;
}
@@ -67,6 +67,16 @@ public class OperationDO extends BaseDO {
*/
private String reportType;
/**
* 举报问题描述
*/
private String reportDescription;
/**
* 举报图片
*/
private String reportPic;
/**
* 身材评分
*/
@@ -5,9 +5,12 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.opentype.OpenTypeUserDO;
import cn.iocoder.yudao.module.member.enums.opentype.OpenTypeStatusEnum;
import cn.iocoder.yudao.module.member.enums.opentype.OpenTypeUserStatusEnum;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
/**
* 会员开通类型与用户关联 Mapper
@@ -30,4 +33,5 @@ public interface OpenTypeUserMapper extends BaseMapperX<OpenTypeUserDO> {
);
}
List<OpenTypeExtBO> getExtByMemeberIdList(@Param("memberIdList") List<Long> memberIdList);
}
@@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.member.job.member;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.member.service.opentype.OpenTypeService;
import cn.iocoder.yudao.module.member.service.user.MemberRecentTagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 清理过期VIP
*/
@Component
@Slf4j
public class CheckVipJob implements JobHandler {
@Resource
private OpenTypeService openTypeService;
@Resource
private MemberRecentTagService memberRecentTagService;
@Override
@TenantJob
public String execute(String param) throws Exception {
// 清理了过期的vip
int vipCount = openTypeService.checkVip();
// 清理了过期的vip tag
int vipTagCount = memberRecentTagService.checkVipTag();
return String.format("清理了过期的 vip记录 %s 个\n清理过期的 vip tag记录 %s 个\n", vipCount, vipTagCount);
}
}
@@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.member.controller.admin.opentype.vo;
package cn.iocoder.yudao.module.member.service.opentype.BO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@@ -10,7 +9,10 @@ import java.time.LocalDateTime;
@Schema(description = "管理后台 - 会员类型分页 Request VO")
@Data
@ToString(callSuper = true)
public class OpenTypeExtReqVO {
public class OpenTypeExtBO {
@Schema(description = "会员编号")
private Long memberId;
@Schema(description = "是否是会员")
private boolean isVip;
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.member.controller.admin.opentype.vo.*;
import cn.iocoder.yudao.module.member.controller.app.opentype.vo.AppPayOpenReqType;
import cn.iocoder.yudao.module.member.dal.dataobject.opentype.OpenTypeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import java.util.List;
@@ -67,5 +68,12 @@ public interface OpenTypeService {
/**
* 查询会员信息
*/
OpenTypeExtReqVO getExtByMemeberId(Long memberId);
List<OpenTypeExtBO> getExtByMemeberId(List<Long> memberIdList);
OpenTypeExtBO getExtByMemeberId(Long memberId);
/**
* 检查过期的vip
*/
int checkVip();
}
@@ -3,17 +3,23 @@ package cn.iocoder.yudao.module.member.service.opentype;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.client.service.ChatApi;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotalMessageTotalReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotalMessageTotalResVO;
import cn.iocoder.yudao.module.member.controller.app.opentype.vo.AppPayOpenReqType;
import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.opentype.OpenTypeUserDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberRecentTagDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeUserMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberRecentTagMapper;
import cn.iocoder.yudao.module.member.enums.MemberErrorCode;
import cn.iocoder.yudao.module.member.enums.opentype.OpenTypeUserStatusEnum;
import cn.iocoder.yudao.module.member.enums.tag.MemberRecentTagEnum;
import cn.iocoder.yudao.module.member.service.config.MemberConfigService;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import cn.iocoder.yudao.module.member.service.user.MemberRecentTagService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -32,6 +38,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeMapper;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -51,6 +58,8 @@ public class OpenTypeServiceImpl implements OpenTypeService {
private OpenTypeMapper openTypeMapper;
@Resource
private OpenTypeUserMapper openTypeUserMapper;
@Resource
private MemberRecentTagMapper memberRecentTagMapper;
@Resource
private MemberConfigService memberConfigService;
@@ -143,9 +152,16 @@ public class OpenTypeServiceImpl implements OpenTypeService {
} else {
openTypeUserObj.setEndTime(now.plusDays(openType.getDuration()));
}
// 新增会员开通表
openTypeUserMapper.insert(openTypeUserObj);
// 新增用户tag
MemberRecentTagDO tagObj = new MemberRecentTagDO();
tagObj.setMemberId(dto.getMemberId());
tagObj.setTagBizType(MemberRecentTagEnum.VIP.getType());
tagObj.setTagBizId(openTypeUserObj.getId());
tagObj.setTagTitle(MemberRecentTagEnum.VIP.getDescription());
memberRecentTagMapper.insert(tagObj);
return openTypeUserObj.getId();
}
@@ -217,14 +233,39 @@ public class OpenTypeServiceImpl implements OpenTypeService {
* 查询会员信息
*/
@Override
public OpenTypeExtReqVO getExtByMemeberId(Long memberId) {
OpenTypeExtReqVO result = new OpenTypeExtReqVO();
public List<OpenTypeExtBO> getExtByMemeberId(List<Long> memberIdList) {
return openTypeUserMapper.getExtByMemeberIdList(memberIdList);
}
@Override
public OpenTypeExtBO getExtByMemeberId(Long memberId) {
OpenTypeExtBO result = new OpenTypeExtBO();
OpenTypeUserDO openTypeUserDO = openTypeUserMapper.selectEnableByUserId(memberId);
result.setVip(ObjectUtil.isNotEmpty(openTypeUserDO));
result.setExpirationTime(ObjectUtil.isNotEmpty(openTypeUserDO) ? openTypeUserDO.getEndTime() : null);
return result;
}
/**
* 检查过期的vip
*/
@Override
public int checkVip() {
List<OpenTypeUserDO> list = openTypeUserMapper.selectList(new LambdaQueryWrapperX<OpenTypeUserDO>()
.eq(OpenTypeUserDO::getStatus, OpenTypeUserStatusEnum.EFFICIENT.getType())
.lt(OpenTypeUserDO::getEndTime, LocalDateTime.now())
);
List<OpenTypeUserDO> updateList = new ArrayList<>();
for (OpenTypeUserDO v : list) {
OpenTypeUserDO entity = new OpenTypeUserDO();
entity.setId(v.getId());
entity.setStatus(OpenTypeUserStatusEnum.EXPIRED.getType());
updateList.add(entity);
}
openTypeUserMapper.updateById(updateList);
return updateList.size();
}
private void validateOpenTypeExists(Long id) {
if (openTypeMapper.selectById(id) == null) {
throw exception(MemberErrorCode.OPEN_TYPE_NOT_EXISTS);
@@ -239,6 +239,8 @@ public class RecentServiceImpl implements RecentService {
if (reportList.contains(dto.getAction())) {
if (ObjectUtil.isEmpty(dto.getReportType())) throw exception(MemberErrorCode.REPORT_TYPE_NOT_NULL);
operationDO.setReportType(dto.getReportType());
operationDO.setReportDescription(dto.getReportDescription());
operationDO.setReportPic(dto.getReportPic());
}
// 评价
List<MemberRecentOperateEnum> ratingList = new ArrayList<MemberRecentOperateEnum>() {{
@@ -26,4 +26,9 @@ public interface MemberRecentTagService {
List<MemberTagExtBO> getUserTagExtList(List<Long> memberIds);
List<MemberTagExtBO> getUserTagExtList(Long memberId);
/**
* 清理了过期的vip tag
*/
int checkVipTag();
}
@@ -4,14 +4,19 @@ package cn.iocoder.yudao.module.member.service.user;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberRecentTagDO;
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeMapper;
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeUserMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberRecentTagMapper;
import cn.iocoder.yudao.module.member.enums.tag.MemberRecentTagEnum;
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
import cn.iocoder.yudao.module.member.service.opentype.OpenTypeService;
import cn.iocoder.yudao.module.member.service.user.BO.MemberTagExtBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -25,6 +30,9 @@ public class MemberRecentTagServiceImp implements MemberRecentTagService {
@Resource
private MemberRecentTagMapper memberRecentTagMapper;
@Resource
private OpenTypeService openTypeService;
/**
* 设置用户真人认证tag
*/
@@ -81,4 +89,28 @@ public class MemberRecentTagServiceImp implements MemberRecentTagService {
return getUserTagExtList(Arrays.asList(memberId));
}
/**
* 清理了过期的vip tag
*/
@Override
public int checkVipTag() {
List<MemberRecentTagDO> vipTagList = memberRecentTagMapper.selectList(new LambdaQueryWrapperX<MemberRecentTagDO>()
.eq(MemberRecentTagDO::getTagBizType, MemberRecentTagEnum.VIP.getType())
);
if (ObjectUtil.isEmpty(vipTagList)) return 0;
List<Long> removeTagMemberIdList = new ArrayList<>();
for (MemberRecentTagDO item : vipTagList) {
boolean isVip = openTypeService.isUserOpenType(item.getMemberId());
if (!isVip) {
removeTagMemberIdList.add(item.getMemberId());
}
}
int deleteCount = memberRecentTagMapper.delete(new LambdaQueryWrapperX<MemberRecentTagDO>()
.eq(MemberRecentTagDO::getTagBizType, MemberRecentTagEnum.VIP.getType())
.in(MemberRecentTagDO::getMemberId, removeTagMemberIdList)
);
return deleteCount;
}
}
@@ -0,0 +1,24 @@
<?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.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeUserMapper">
<select id="getExtByMemeberIdList" resultType="cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO">
select a.member_id as memberId, TRUE as isVip, a.end_time as expirationTime
from member_open_type_user a
<where>
a.deleted = '0'
and a.status = 1
and a.end_time > now()
<if test="memberIdList != null and memberIdList.size() != 0">
and a.member_id in
<foreach collection="memberIdList" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
</where>
group by a.member_id
order by a.end_time desc
</select>
</mapper>
@@ -80,6 +80,7 @@
from member_operation a
<where>
a.deleted = '0'
and a.biz_type = '4'
<if test="operationUserId != null">
and a.operator_member_id = #{operationUserId}
</if>
@@ -100,6 +101,7 @@
from member_operation a
<where>
a.deleted = '0'
and a.biz_type = '1'
<if test="operationUserId != null">
and a.operator_member_id = #{operationUserId}
</if>