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