提交 10455d27 authored 作者: 吕本才's avatar 吕本才

feat(mp): 实现抽奖参与功能并优化用户查询逻辑

上级 ccb5977a
package com.link.hub.controller.mp.core;
import com.link.hub.domain.weChatMiniProgram.entity.LotteryParticipate;
import com.link.hub.pojo.mp.vo.LotteryVo;
import com.link.hub.service.weChatMiniProgram.LotteryParticipateService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author : lvbencai
* @date : 2025-12-10
* @describe : 抽奖查询接口
*/
@RestController
@RequestMapping("/miniProgram/core/lottery")
public class LotteryCoreController {
@Resource
private LotteryParticipateService lotteryParticipateService;
// 查询抽奖列表信息
@PostMapping
public LotteryParticipate participateLotteryx(@RequestBody LotteryVo lotteryVo) {
return lotteryParticipateService.participateLottery(lotteryVo);
}
}
......@@ -2,6 +2,7 @@ package com.link.hub.domain.weChatMiniProgram.dao;
import com.link.hub.domain.weChatMiniProgram.entity.LotteryParticipate;
import com.link.hub.domain.weChatMiniProgram.wq.LotteryParticipateWq;
import com.link.hub.pojo.mp.dto.LotteryParticipateDto;
import java.util.List;
......@@ -36,10 +37,11 @@ public interface LotteryParticipateDao {
/**
* 保存参与记录(含防重校验)
*
* @param participatePO 参与记录实体
* @return 是否成功
*/
boolean saveParticipate(LotteryParticipate participatePO);
LotteryParticipate saveParticipate(LotteryParticipateDto participateDto);
/**
* 查询用户在某活动的参与记录
......
......@@ -4,7 +4,6 @@ import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq;
public interface WechatMiniProgramUserDao {
WechatMiniProgramUser queryMiniProgramUserWq(WechatMiniProgramUserWq wechatMiniProgramUserWq);
WechatMiniProgramUser queryMiniProgramUserOne(WechatMiniProgramUserWq wechatMiniProgramUserWq);
void insert(WechatMiniProgramUser wechatMiniProgramUser);
}
package com.link.hub.domain.weChatMiniProgram.dao.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.link.hub.domain.weChatMiniProgram.dao.LotteryParticipateDao;
import com.link.hub.domain.weChatMiniProgram.entity.LotteryParticipate;
import com.link.hub.domain.weChatMiniProgram.mapper.LotteryParticipateMapper;
import com.link.hub.domain.weChatMiniProgram.wq.LotteryParticipateWq;
import com.link.hub.pojo.mp.dto.LotteryParticipateDto;
import com.sfa.common.core.exception.ServiceException;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
......@@ -50,7 +53,11 @@ public class LotteryParticipateDaoImpl implements LotteryParticipateDao {
@Override
public boolean checkUserParticipated(Long activityId, Long userId) {
return false;
LambdaQueryWrapper<LotteryParticipate> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(LotteryParticipate::getActivityId, activityId)
.eq(LotteryParticipate::getUserId, userId)
.eq(LotteryParticipate::getDeleteFlag, 0);
return lotteryParticipateMapper.selectCount(wrapper) > 0;
}
@Override
......@@ -67,7 +74,8 @@ public class LotteryParticipateDaoImpl implements LotteryParticipateDao {
queryWrapper.lambda()
.eq(LotteryParticipate::getActivityId, activityId)
.eq(LotteryParticipate::getUserId, userId)
.eq(LotteryParticipate::getDeleteFlag, 0); // 仅查询未删除记录
// 仅查询未删除记录
.eq(LotteryParticipate::getDeleteFlag, 0);
return lotteryParticipateMapper.selectCount(queryWrapper) > 0;
}
......@@ -75,9 +83,15 @@ public class LotteryParticipateDaoImpl implements LotteryParticipateDao {
* 保存参与记录(插入前自动校验唯一性)
*/
@Override
public boolean saveParticipate(LotteryParticipate participatePO) {
public LotteryParticipate saveParticipate(LotteryParticipateDto participateDto) {
// MyBatis Plus 的 insert 方法会自动处理唯一索引冲突
return lotteryParticipateMapper.insert(participatePO) > 0;
LotteryParticipate participatePO = LotteryParticipate.create(participateDto);
int flag = lotteryParticipateMapper.insert(participatePO);
if (flag == 0) {
throw new ServiceException("保存参与记录失败");
}
return participatePO;
}
/**
......
......@@ -21,10 +21,11 @@ public class WechatMiniProgramUserDaoImpl implements WechatMiniProgramUserDao {
@Override
public WechatMiniProgramUser queryMiniProgramUserWq(WechatMiniProgramUserWq wechatMiniProgramUserWq) {
public WechatMiniProgramUser queryMiniProgramUserOne(WechatMiniProgramUserWq wechatMiniProgramUserWq) {
LambdaQueryWrapper<WechatMiniProgramUser> queryWrapper = new LambdaQueryWrapper<WechatMiniProgramUser>();
queryWrapper.eq(ObjectUtil.isNotEmpty(wechatMiniProgramUserWq.getOpenid()),WechatMiniProgramUser::getOpenid, wechatMiniProgramUserWq.getOpenid());
queryWrapper.eq(ObjectUtil.isNotEmpty(wechatMiniProgramUserWq.getUserId()),WechatMiniProgramUser::getId, wechatMiniProgramUserWq.getUserId());
WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserMapper.selectOne(queryWrapper);
return wechatMiniProgramUser;
}
......
package com.link.hub.domain.weChatMiniProgram.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.link.hub.pojo.mp.dto.LotteryParticipateDto;
import lombok.Data;
import java.time.LocalDateTime;
......@@ -77,4 +81,20 @@ public class LotteryParticipate {
*/
@TableLogic
private Integer deleteFlag;
// 核心业务规则:创建订单(封装状态初始化、金额计算)
public static LotteryParticipate create(LotteryParticipateDto dto) {
LotteryParticipate lotteryParticipate = new LotteryParticipate();
lotteryParticipate.setActivityId(dto.getActivityId());
lotteryParticipate.setUserId(dto.getUserId());
// 默认状态为1 已参与待开奖
lotteryParticipate.setLotteryStatus(1);
lotteryParticipate.setParticipateTime(LocalDateTime.now());
lotteryParticipate.setIpAddress(dto.getIpAddress());
lotteryParticipate.setDeviceInfo(dto.getDeviceInfo());
lotteryParticipate.setSource(dto.getSource());
return lotteryParticipate;
}
}
......@@ -5,4 +5,5 @@ import lombok.Data;
@Data
public class WechatMiniProgramUserWq {
private String openid;
private Long userId;
}
package com.link.hub.pojo.mp.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 用户参与抽奖记录DTO类
*/
@Data
public class LotteryParticipateBo {
/**
* 关联活动ID
*/
@NotNull(message = "活动ID不能为空")
private Long activityId;
/**
* 关联用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 参与IP
*/
private String ipAddress;
/**
* 设备标识
*/
private String deviceInfo;
/**
* 参与来源:1微信小程序2抖音小程序
*/
private String source;
}
package com.link.hub.pojo.mp.dto;
import cn.hutool.core.util.ObjectUtil;
import com.link.hub.domain.weChatMiniProgram.enums.SourceEnum;
import com.link.hub.pojo.mp.vo.LotteryVo;
import com.sfa.common.core.utils.ip.IpUtils;
import com.sfa.common.security.utils.SecurityUtils;
import lombok.Data;
import javax.validation.constraints.NotNull;
......@@ -34,5 +39,17 @@ public class LotteryParticipateDto {
/**
* 参与来源:1微信小程序2抖音小程序
*/
private String source;
private Integer source;
// 核心业务规则:创建订单(封装状态初始化、金额计算)
public static LotteryParticipateDto create(LotteryVo lotteryVo ) {
LotteryParticipateDto dto = new LotteryParticipateDto();
dto.setActivityId(lotteryVo.getActivityId());
dto.setUserId(SecurityUtils.getUserId());
dto.setSource(ObjectUtil.defaultIfNull(lotteryVo.getSource(), SourceEnum.WECHAT_MINI_PROGRAM.getCode()));
dto.setIpAddress(IpUtils.getIpAddr());
return dto;
}
}
......@@ -3,7 +3,7 @@ package com.link.hub.pojo.mp.dto;
import lombok.Data;
@Data
public class MiniProgramOpenIdDTO {
public class MpOpenIdDTO {
private String openid;
private String unionid;
}
package com.link.hub.pojo.mp.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class LotteryVo {
/**
* 抽奖id
*/
private Long id;
/**
* 抽奖名称
*/
private String title;
/**
* 抽奖描述
*/
private String description;
/**
* 抽奖图片
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private String coverImg;
/**
* 抽奖开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
/**
* 抽奖结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
/**
* 抽奖活动的状态
*/
private Integer status;
/**
* 抽奖类型
*/
// @JsonInclude(JsonInclude.Include.NON_NULL)
// private String type;
private Long activityId;
/**
* 抽奖参与人数
* 抽奖来源:1微信小程序2抖音小程序
*
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer participantCount;
/**
* 抽奖中奖人数
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer winningCount;
/**
* 抽奖中奖率
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Double winningRate;
private Integer source;
}
......@@ -3,6 +3,7 @@ package com.link.hub.service.weChatMiniProgram;
import com.baomidou.mybatisplus.extension.service.IService;
import com.link.hub.domain.weChatMiniProgram.entity.LotteryParticipate;
import com.link.hub.pojo.mp.vo.LotteryParticipateVo;
import com.link.hub.pojo.mp.vo.LotteryVo;
import java.util.List;
......@@ -12,10 +13,11 @@ import java.util.List;
public interface LotteryParticipateService extends IService<LotteryParticipate> {
/**
* 参与抽奖活动
*
* @param participate 参与信息
* @return 是否成功
*/
boolean participateLottery(LotteryParticipate participate);
LotteryParticipate participateLottery(LotteryVo lotteryVo);
/**
* 检查用户是否已参与活动
......@@ -40,5 +42,6 @@ public interface LotteryParticipateService extends IService<LotteryParticipate>
*/
int getUserParticipateCount(Long userId);
boolean participateActivity(Long activityId, Long userId);
}
}
package com.link.hub.service.weChatMiniProgram;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.pojo.mp.dto.MiniProgramOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto;
public interface WechatMiniProgramUserService {
WechatMiniProgramUser queryMiniProgramUserByOpenId(String openid);
WechatMiniProgramUser queryMiniProgramUserOne(MpUserDto openid);
Long saveMiniProgramUser(MiniProgramOpenIdDTO miniProgramOpenIdDTO);
Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO);
}
......@@ -3,11 +3,18 @@ package com.link.hub.service.weChatMiniProgram.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.link.hub.domain.weChatMiniProgram.dao.LotteryParticipateDao;
import com.link.hub.domain.weChatMiniProgram.entity.LotteryParticipate;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatMiniProgram.enums.SourceEnum;
import com.link.hub.domain.weChatMiniProgram.mapper.LotteryParticipateMapper;
import com.link.hub.pojo.mp.dto.LotteryParticipateDto;
import com.link.hub.pojo.mp.dto.MpUserDto;
import com.link.hub.pojo.mp.vo.LotteryParticipateVo;
import com.link.hub.pojo.mp.vo.LotteryVo;
import com.link.hub.service.officeAccount.WechatOfficeAccountService;
import com.link.hub.service.weChatMiniProgram.LotteryParticipateService;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
import com.sfa.common.core.utils.bean.BeanUtils;
import com.sfa.common.security.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
......@@ -23,14 +30,38 @@ public class LotteryParticipateServiceImpl extends ServiceImpl<LotteryParticipat
@Resource
private LotteryParticipateDao lotteryParticipateDao;
@Resource
private WechatMiniProgramUserService wechatMiniProgramUserService;
@Resource
private WechatOfficeAccountService wechatOfficeAccountService;
@Override
public boolean participateLottery(LotteryParticipate participate) {
// 检查用户是否已参与
if (checkUserParticipated(participate.getActivityId(), participate.getUserId())) {
return false;
public LotteryParticipate participateLottery(LotteryVo lotteryVo) {
// 检验是否关注公众号
MpUserDto mpUserDto = new MpUserDto();
mpUserDto.setId(SecurityUtils.getUserId());
WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserService.queryMiniProgramUserOne(mpUserDto);
String openid = wechatMiniProgramUser.getOpenid();
if (!checkIsSubscribe(openid)) {
throw new IllegalArgumentException("用户未关注公众号");
}
// 1. 校验是否已参与抽奖(防重)
Long activityId = lotteryVo.getActivityId();
Long userId = SecurityUtils.getUserId();
if (lotteryParticipateDao.hasParticipated(activityId, userId)) {
throw new IllegalArgumentException("用户已参与抽奖");
}
return save(participate);
// 2. 创建参与记录
LotteryParticipateDto dto =LotteryParticipateDto.create(lotteryVo);
// 3. 保存记录(插入数据库)
LotteryParticipate lotteryParticipate = lotteryParticipateDao.saveParticipate(dto);
return lotteryParticipate;
}
@Override
......@@ -59,22 +90,13 @@ public class LotteryParticipateServiceImpl extends ServiceImpl<LotteryParticipat
/**
* 用户参与活动(核心业务逻辑)
*/
@Override
public boolean participateActivity(Long activityId, Long userId) {
// 1. 校验是否已参与(防重)
if (lotteryParticipateDao.hasParticipated(activityId, userId)) {
return false; // 已参与过
}
// 2. 创建参与记录
LotteryParticipate participatePO = new LotteryParticipate();
participatePO.setActivityId(activityId);
participatePO.setUserId(userId);
participatePO.setIpAddress("192.168.1.1"); // 示例IP
participatePO.setDeviceInfo("iPhone14"); // 示例设备
participatePO.setSource(1); // 微信小程序
// 3. 保存记录(插入数据库)
return lotteryParticipateDao.saveParticipate(participatePO);
private boolean checkIsSubscribe(String openid) {
// 实现逻辑,检查用户是否已关注公众号
wechatOfficeAccountService.isSubscribe(openid);
return true;
}
}
......@@ -4,7 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.link.hub.config.WeChatMiniProgramConfig;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.pojo.mp.dto.MiniProgramOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto;
import com.link.hub.pojo.mp.vo.MiniProgramOpenIdVO;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramService;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
......@@ -50,7 +51,10 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
if (ObjectUtil.isEmpty(openid)) {
throw new ServiceException("获取openid失败");
}
WechatMiniProgramUser wechatMiniProgramUser = miniProgramUserService.queryMiniProgramUserByOpenId(openid);
MpUserDto mpUserDto = new MpUserDto();
mpUserDto.setOpenid(openid);
mpUserDto.setUnionid(unionid);
WechatMiniProgramUser wechatMiniProgramUser = miniProgramUserService.queryMiniProgramUserOne(mpUserDto);
Long userId = null;
if (ObjectUtil.isNotEmpty(wechatMiniProgramUser)) {
......@@ -58,10 +62,10 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
userId = wechatMiniProgramUser.getId();
} else {
// 保存小程序用户信息 新增小程序用户信息
MiniProgramOpenIdDTO miniProgramOpenIdDTO = new MiniProgramOpenIdDTO();
miniProgramOpenIdDTO.setOpenid(openid);
miniProgramOpenIdDTO.setUnionid(unionid);
userId = miniProgramUserService.saveMiniProgramUser(miniProgramOpenIdDTO);
MpOpenIdDTO mpOpenIdDTO = new MpOpenIdDTO();
mpOpenIdDTO.setOpenid(openid);
mpOpenIdDTO.setUnionid(unionid);
userId = miniProgramUserService.saveMiniProgramUser(mpOpenIdDTO);
}
LoginUser loginUser = new LoginUser();
String token = IdUtils.fastUUID();
......
......@@ -4,8 +4,11 @@ import cn.hutool.core.date.DateUtil;
import com.link.hub.domain.weChatMiniProgram.dao.WechatMiniProgramUserDao;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq;
import com.link.hub.pojo.mp.dto.MiniProgramOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
import com.sfa.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
......@@ -14,24 +17,35 @@ import javax.annotation.Resource;
/**
* 小程序用户服务实现
*/
@Slf4j
@Service
public class WechatMiniProgramUserServiceServiceImpl implements WechatMiniProgramUserService {
@Resource
private WechatMiniProgramUserDao wechatMiniProgramUserDao;
/**
* 查询小程序用户
* @param mpUserDto
* @return
*/
@Override
public WechatMiniProgramUser queryMiniProgramUserByOpenId(String openid) {
public WechatMiniProgramUser queryMiniProgramUserOne(MpUserDto mpUserDto) {
WechatMiniProgramUserWq wechatMiniProgramUserWq = new WechatMiniProgramUserWq();
wechatMiniProgramUserWq.setOpenid(openid);
WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserDao.queryMiniProgramUserWq(wechatMiniProgramUserWq);
wechatMiniProgramUserWq.setOpenid(mpUserDto.getOpenid());
wechatMiniProgramUserWq.setUserId(mpUserDto.getId());
WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserDao.queryMiniProgramUserOne(wechatMiniProgramUserWq);
if (wechatMiniProgramUser == null) {
log.error("用户不存在,openid:{},userId:{}", mpUserDto.getOpenid(), mpUserDto.getId());
throw new ServiceException("用户不存在");
}
return wechatMiniProgramUser;
}
@Override
public Long saveMiniProgramUser(MiniProgramOpenIdDTO miniProgramOpenIdDTO) {
public Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO) {
WechatMiniProgramUser wechatMiniProgramUser = new WechatMiniProgramUser();
wechatMiniProgramUser.setOpenid(miniProgramOpenIdDTO.getOpenid());
wechatMiniProgramUser.setOpenid(mpOpenIdDTO.getOpenid());
wechatMiniProgramUser.setCreateTime(DateUtil.date());
wechatMiniProgramUser.setUpdateTime(DateUtil.date());
wechatMiniProgramUserDao.insert(wechatMiniProgramUser);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论