抽奖功能实现

1. 需求分析

抽奖可以获得积分,礼券,小样,正品等

若库存为0,则用户不能在抽中此奖

每个奖项的中奖概率

每天抽奖次数的限制

每次抽奖是否需要消耗积分的限制

有没有批量抽奖功能

 

2.表结构设计

会员表,积分表,是以前就有的,本次新增抽奖功能,需要新增一下的表:

首先要有库存表,暂且定义为BPRIZE

其次要记录用户抽中的奖项,暂且定义为HPRIZE

      

 

3. 后台代码实现

Controller 

@RestController
@RequestMapping(value = "draw")
public class DrawController extends BaseController {

    @Autowired
    DrawService drawService;

    @Autowired
    CouponService couponService;

    @Autowired
    SocialProviderService socialProviderService;

    @ApiOperation(value = "抽奖历史记录", notes = "抽奖历史记录")
    @GetMapping(value = "history", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    private ResponseBean prizeHistory(@RequestParam("userId") String userId,
                                      @RequestParam("social") String social, @RequestParam("page") int page, @RequestParam("size") int size) {

        ResponseBean responseBean = new ResponseBean();
        List<HPrizerecord> hPrizerecords = drawService.getPrizeHistory(userId, social, page, size);
        responseBean.setData(hPrizerecords);
        return responseBean;
    }

    @ApiOperation(value = "抽奖榜单", notes = "抽奖榜单")
    @GetMapping(value = "billboard", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    private ResponseBean billboard(@RequestParam("topN") int topN, @RequestParam("levelList") String levelList, @RequestParam("social") String social) {
        ResponseBean responseBean = new ResponseBean();

        // 查找SopId
        SSocialProvider socialProvider = socialProviderService.findSocialProvider(social);

        // 格式化等级 (str-> list(int))
        List<Integer> level = Arrays.stream(levelList.split(",")).map(a -> {
            return Integer.parseInt(a);
        }).collect(Collectors.toList());

        // 查询
        JSONArray billboard = drawService.getBillboard(topN, level, socialProvider.getSopId());
        responseBean.setData(billboard);
        return responseBean;
    }


    @ApiOperation(value = "抽奖", notes = "抽奖")
    @PostMapping(produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    private ResponseBean<BPrize> draw(@RequestParam("userId") String userId,
                                      @RequestParam("social") String social) throws Exception {

        ResponseBean responseBean = new ResponseBean();
        BPrize bPrize = drawService.draw(userId, social, super.getSid());
        responseBean.setData(bPrize);

        return responseBean;
    }
}

 

 

具体实现

@Service
public class DrawServiceImpl implements DrawService {


    @Autowired
    HPrizerecordMapper hPrizerecordMapper;

    @Autowired
    SaveDrawRecord saveDrawRecord;


    @Autowired
    SocialService socialService;

    @Autowired
    SocialProviderService socialProviderService;

    @Autowired
    BCustomerService bCustomerService;

    @Autowired
    BPrizeService bPrizeService;

    @Autowired
    PEService peService;


    @Autowired
    CustomerService customerService;

    @Autowired
    SendMemberInfoToEcrmMqTask sendMemberInfoToEcrmMqTask;

    @Value("${sys.name}")
    private String sysName;

    int freeCount=2;

    int dalyMaxDrawCount=5;


    @Value("${cc.draw.pe.code}")
    String luckyDrawPeEventCode;

    @Value("${cc.draw.max.probability}")
    int maxProbability;
    static  Random rand = new Random();

    @Value("#{'${cc.draw.actual.prizeLevel}'.split(',')}")
    private  List<Integer>  actualPrizeLevel;


    @Override
    public List<HPrizerecord> getPrizeHistory(String userId, String social, int page, int size) {
        int cstId = socialService.findCstIdBySocialAndSocialId(userId, social);

        if (size == 0 ){
            size = 10;
        }
        if (page<=0){
            page = 1;
        }

        return  hPrizerecordMapper.getPrizeHistory(cstId, page, size);
    }


    @Override
    public BPrize draw(String userId, String social, String sid) throws Exception {
        int cstId = socialService.findCstIdBySocialAndSocialId(userId, social);


        // 今天一共抽了几次奖
        int todayCount = getDrawCountToday(cstId);

        // 如果超过最大次数,直接返回, 不进行抽奖
        if (todayCount >= dalyMaxDrawCount){
            throw new DrawCountLimitException();
        }

        // 超过规定的一个次数就要开始扣积分
        if (todayCount >= freeCount) {
            // 扣减积分, 如果扣减失败, 会抛出异常,这边不用管
            peService.sendEvent(cstId, sysName, luckyDrawPeEventCode);
            sendMemberInfoToEcrmMqTask.syncMemberInfoToECRM(cstId, luckyDrawPeEventCode);
        }

        boolean drawEnd = false;
        BPrize bPrize = null;

        while (!drawEnd) {
            int x = rand.nextInt(maxProbability);
            bPrize = bPrizeService.getPrize(x);

            // 如果抽中的是实物奖品
            if (bPrize!=null && actualPrizeLevel.indexOf(bPrize.getPrizeLevel())>=0){
                // 判断当日是否有中过实物奖品
                boolean isWinningTheActualPrizeFlag =  isWinningTheActualPrize(cstId);
                // 如果isWinningTheActualPrizeFlag 为false , 抽奖成功
                if (!isWinningTheActualPrizeFlag) {
                    drawEnd = true;
                }
            }

            if (bPrize != null) {
                drawEnd = true;
            }
        }

        // 如果礼品里面配置了PEcode 调用PE积分调整
        String peCode = bPrize.getPointCode();
        if (StringUtils.isNotBlank(peCode)) {
            peService.sendEvent(cstId, sysName, peCode);
            sendMemberInfoToEcrmMqTask.syncMemberInfoToECRM(cstId, luckyDrawPeEventCode);
        }

        // 记录到抽奖历史
        saveDrawRecord.savePrizerecordHistory(cstId, bPrize, sid);
        return bPrize;
    }

    private boolean isWinningTheActualPrize(int cstId) {

        // 查询今天是否中过实物奖项
        List<HPrizerecord> hPrizerecords = hPrizerecordMapper.getWinningTheActualPrizeToday(cstId,actualPrizeLevel);
        if (null != hPrizerecords ||!hPrizerecords.isEmpty() || hPrizerecords.size()>0) {
            return true;
        }

        return false;
    }

    @Override
    public JSONArray getBillboard(int topN, List<Integer> levelList, Integer sopId) {


        List<Map> records = hPrizerecordMapper.selectBillboard(topN, levelList, sopId);

        return (JSONArray) JSONArray.toJSON(records);
    }

    private int getDrawCountToday(int cstId) {
        return hPrizerecordMapper.getDrawCountToday(cstId);
    }


}

  

 

 

4. 前端UI实现

posted @ 2019-08-28 14:26  巴黎爱工作  阅读(1208)  评论(0编辑  收藏  举报