抽獎功能實現


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實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM