后台-系统设置-扩展变量-手机广告位-内容正文顶部 |
代码设计
1、接口调用流程图
平台发布促销活动
商家选择商品参与限时抢购活动
平台审核商家参与活动的商品
2、相关代码展示
新增和修改限时抢购活动
@RestController
@RequestMapping("/admin/promotion/seckills")
@Api(description = "限时抢购活动相关API")
@Validated
public class SeckillManagerController {
@ApiOperation(value = "添加限时抢购入库", response = SeckillVO.class)
@PostMapping
public SeckillVO add(@Valid @RequestBody SeckillVO seckill) {
this.verifyParam(seckill);
seckill.setSeckillStatus(SeckillStatusEnum.EDITING.name());
this.seckillManager.add(seckill);
return seckill;
}
@PutMapping(value = "/{id}")
@ApiOperation(value = "修改限时抢购入库", response = SeckillDO.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "主键",
required = true, dataType = "int", paramType = "path")
})
public SeckillVO edit(@Valid @RequestBody SeckillVO seckill,
@PathVariable @NotNull(message = "限时抢购ID参数错误") Long id) {
this.verifyParam(seckill);
this.seckillManager.edit(seckill, id);
return seckill;
}
}
@Service
public class SeckillManagerImpl extends AbstractPromotionRuleManagerImpl implements SeckillManager {
@Override
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = {ServiceException.class, RuntimeException.class})
public SeckillVO add(SeckillVO seckill) {
//验证活动名称是否为空
this.checkName(seckill.getSeckillName(), null);
String date = DateUtil.toString(seckill.getStartDay(), "yyyy-MM-dd");
long startTime = DateUtil.getDateline(date + " 00:00:00",
"yyyy-MM-dd HH:mm:ss");
long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
this.verifyTime(startTime, endTime, PromotionTypeEnum.SECKILL, null);
SeckillDO seckillDO = new SeckillDO();
seckillDO.setDeleteStatus(DeleteStatusEnum.NORMAL.value());
BeanUtils.copyProperties(seckill, seckillDO);
seckillMapper.insert(seckillDO);
Long id = seckillDO.getSeckillId();
this.seckillRangeManager.addList(seckill.getRangeList(), id);
//开启延时任务执行器
openTimeExecuter(seckill, endTime, id);
return seckill;
}
@Override
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = {ServiceException.class})
public SeckillVO edit(SeckillVO seckill, Long id) {
//验证活动名称是否为空
this.checkName(seckill.getSeckillName(), id);
String date = DateUtil.toString(seckill.getStartDay(), "yyyy-MM-dd");
long startTime = DateUtil.getDateline(date + " 00:00:00",
"yyyy-MM-dd HH:mm:ss");
long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
PromotionValid.paramValid(startTime, endTime, 1, null);
this.verifyTime(startTime, endTime, PromotionTypeEnum.SECKILL, id);
SeckillDO seckillDO = new SeckillDO();
BeanUtils.copyProperties(seckill, seckillDO);
seckillDO.setSeckillId(id);
seckillMapper.updateById(seckillDO);
this.seckillRangeManager.addList(seckill.getRangeList(), id);
//开启延时任务执行器
openTimeExecuter(seckill, endTime, id);
return seckill;
}
}
发布限时抢购活动
@RestController
@RequestMapping("/admin/promotion/seckills")
@Api(description = "限时抢购活动相关API")
@Validated
public class SeckillManagerController {
@ApiOperation(value = "发布限时抢购活动")
@PostMapping("/{seckill_id}/release")
@ApiImplicitParams({
@ApiImplicitParam(name = "seckill_id", value = "要查询的限时抢购入库主键",
required = true, dataType = "int", paramType = "path")
})
public SeckillVO publish(@Valid @RequestBody SeckillVO seckill,
@ApiIgnore @PathVariable("seckill_id") Long seckillId) {
this.verifyParam(seckill);
//发布状态
seckill.setSeckillStatus(SeckillStatusEnum.RELEASE.name());
if (seckillId == null || seckillId == 0) {
seckillManager.add(seckill);
} else {
seckillManager.edit(seckill, seckillId);
}
return seckill;
}
}
平台审核商家参与限时抢购活动的商品
@RestController
@RequestMapping("/admin/promotion/seckills")
@Api(description = "限时抢购活动相关API")
@Validated
public class SeckillManagerController {
@ApiOperation(value = "批量审核商品")
@PostMapping(value = "/batch/audit")
public String batchAudit(@Valid @RequestBody SeckillAuditParam param) {
this.seckillManager.batchAuditGoods(param);
return "";
}
}
@Service
public class SeckillManagerImpl extends AbstractPromotionRuleManagerImpl implements SeckillManager {
@Override
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = {ServiceException.class, RuntimeException.class})
public void batchAuditGoods(SeckillAuditParam param) {
if (param.getApplyIds() == null || param.getApplyIds().length == 0) {
throw new ServiceException(GoodsErrorCode.E301.code(), "请选择要审核的商品");
}
if (StringUtil.isEmpty(param.getStatus())) {
throw new ServiceException(PromotionErrorCode.E400.code(), "审核状态值不正确");
}
//状态值不正确
SeckillGoodsApplyStatusEnum applyStatusEnum =
SeckillGoodsApplyStatusEnum.valueOf(param.getStatus());
//驳回,原因必填
if (applyStatusEnum.equals(SeckillGoodsApplyStatusEnum.FAIL)) {
if (StringUtil.isEmpty(param.getFailReason())) {
throw new ServiceException(PromotionErrorCode.E400.code(),
"驳回原因必填");
}
if (param.getFailReason().length() > 500) {
throw new ServiceException(PromotionErrorCode.E400.code(),
"驳回原因长度不能超过500个字符");
}
}
//审核状态 true:审核通过,false:审核未通过
boolean auditStatus = SeckillGoodsApplyStatusEnum.PASS.equals(applyStatusEnum);
//参与限时抢购促销活动并且已被平台审核通过的商品集合
List
//审核通过的限时抢购商品集合
List
Long actId = 0L;
//批量审核
for (Long applyId : param.getApplyIds()) {
SeckillApplyDO apply = new QueryChainWrapper<>(seckillApplyMapper)
//拼接活动id查询条件
.eq("apply_id", applyId)
//拼接秒杀活动商品的申请状态查询条件
.eq("status", SeckillGoodsApplyStatusEnum.APPLY.name())
//查询单个对象
.one();
//申请不存在
if (apply == null) {
throw new ServiceException(PromotionErrorCode.E400.code(),
"商品不是可以审核的状态");
}
if (actId == 0) {
actId = apply.getSeckillId();
}
apply.setStatus(applyStatusEnum.name());
apply.setFailReason(param.getFailReason());
new UpdateChainWrapper<>(seckillApplyMapper)
//按活动id修改
.eq("apply_id", applyId)
//提交修改
.update(apply);
//查询商品
CacheGoods goods = goodsClient.getFromCache(apply.getGoodsId());
//将审核通过的商品,存储到活动商品表和缓存中
if (auditStatus) {
//将审核通过的商品放入集合中
goodsList.add(apply);
//促销商品表
PromotionGoodsDO promotion = new PromotionGoodsDO();
promotion.setTitle("限时抢购");
promotion.setGoodsId(apply.getGoodsId());
promotion.setSkuId(apply.getSkuId());
promotion.setPromotionType(PromotionTypeEnum.SECKILL.name());
promotion.setActivityId(apply.getSeckillId());
promotion.setNum(apply.getSoldQuantity());
promotion.setPrice(apply.getPrice());
promotion.setSellerId(goods.getSellerId());
//商品活动的开始时间为当前商品的参加时间段
int timeLine = apply.getTimeLine();
String date = DateUtil.toString(apply.getStartDay(), "yyyy-MM-dd");
long startTime = DateUtil.getDateline(
date + " " + timeLine + ":00:00", "yyyy-MM-dd HH:mm:ss");
long endTime = DateUtil.getDateline(
date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
promotion.setStartTime(startTime);
promotion.setEndTime(endTime);
promotionGoodsDOS.add(promotion);
//从缓存读取限时抢购的活动的商品
String redisKey = getRedisKey(apply.getStartDay());
Map
//如果redis中有当前审核商品参与的限时抢购活动商品信息,就删除掉
if (map != null && !map.isEmpty()) {
this.cache.remove(redisKey);
}
//设置延迟加载任务,到活动开始时间后将搜索引擎中的优惠价格设置为0
PromotionPriceDTO promotionPriceDTO = new PromotionPriceDTO();
promotionPriceDTO.setGoodsId(apply.getGoodsId());
promotionPriceDTO.setPrice(apply.getPrice());
timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,
promotionPriceDTO, startTime, null);
//此活动结束后将索引的优惠价格重置为0
promotionPriceDTO.setPrice(0.0);
timeTrigger.add(TimeExecute.PROMOTION_EXECUTER,
promotionPriceDTO, endTime, null);
}
}
//如果当前是商品审核通过的操作
if (auditStatus) {
SeckillVO seckillVO = this.getModel(actId);
if (seckillVO != null) {
String date = DateUtil.toString(seckillVO.getStartDay(), "yyyy-MM-dd");
long startTime = DateUtil.getDateline(
date + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
long endTime = DateUtil.getDateline(
date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
//活动信息DTO
PromotionDetailDTO detailDTO = new PromotionDetailDTO();
detailDTO.setActivityId(seckillVO.getSeckillId());
detailDTO.setStartTime(startTime);
detailDTO.setEndTime(endTime);
detailDTO.setPromotionType(PromotionTypeEnum.SECKILL.name());
detailDTO.setTitle("限时抢购");
this.promotionGoodsManager.addAndCheck(promotionGoodsDOS, detailDTO);
}
//创建审核通过的商品限时抢购促销活动脚本信息
this.seckillScriptManager.createCacheScript(
goodsList.get(0).getSeckillId(), goodsList);
}
}
- 创建限时抢购促销活动脚本引擎
```java
@Service
public class SeckillScriptManagerImpl implements SeckillScriptManager {
@Override
public void createCacheScript(Long promotionId, List
//如果参与促销活动的商品集合不为空并且集合长度不等于0
if (goodsList != null && goodsList.size() != 0) {
//批量放入缓存的数据集合
Map
//循环skuID集合,将脚本放入缓存中
for (SeckillApplyDO goods : goodsList) {
//缓存key
String cacheKey = CachePrefix.SKU_PROMOTION.getPrefix()
+ goods.getSkuId();
//获取商品开始的时刻
String[] time = this.getTime(goods.getTimeLine(), goods.getStartDay());
//获取拼团活动脚本信息
PromotionScriptVO scriptVO = new PromotionScriptVO();
//渲染并读取限时抢购促销活动脚本信息
String script = renderScript(time[0], time[1], goods.getPrice());
scriptVO.setPromotionScript(script);
scriptVO.setPromotionId(promotionId);
scriptVO.setPromotionType(PromotionTypeEnum.SECKILL.name());
scriptVO.setIsGrouped(false);
scriptVO.setPromotionName("限时抢购");
scriptVO.setSkuId(goods.getSkuId());
//从缓存中读取脚本信息
List
cache.get(cacheKey);
if (scriptList == null) {
scriptList = new ArrayList<>();
}
scriptList.add(scriptVO);
cacheMap.put(cacheKey, scriptList);
}
//将sku促销脚本数据批量放入缓存中
cache.multiSet(cacheMap);
}
}
/**
* 获取限时抢购开始和结束时间
* @param timeLine 开始时刻
* @param startDay 活动开始当天的起始时间
* @return
*/
private String[] getTime(Integer timeLine, Long startDay) {
String date = DateUtil.toString(startDay, "yyyy-MM-dd");
Long startTime = DateUtil.getDateline(date + " " + timeLine + ":00:00",
"yyyy-MM-dd HH:mm:ss");
Long endTime = DateUtil.getDateline(date + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
String[] time = new String[2];
time[0] = startTime.toString();
time[1] = endTime.toString();
return time;
}
/**
* 渲染并读取限时抢购促销活动脚本信息
* @param startTime 活动开始时间
* @param endTime 活动结束时间
* @param price 限时抢购商品价格
* @return
*/
private String renderScript(String startTime, String endTime, Double price) {
Map
Map
params.put("startTime", startTime);
params.put("endTime", endTime);
params.put("price", price);
model.put("promotionActive", params);
String path = "single_promotion.ftl";
String script = ScriptUtil.renderScript(path, model);
logger.debug("生成限时抢购促销活动脚本:" + script);
return script;
}
}
删除限时抢购促销活动脚本引擎
@Component("seckillScriptTimeTriggerExecuter")
public class SeckillScriptTimeTriggerExecuter implements TimeTriggerExecuter {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private PromotionScriptClient promotionScriptClient;
@Autowired
private PromotionGoodsClient promotionGoodsClient;
@Override
public void execute(Object object) {
PromotionScriptMsg promotionScriptMsg = (PromotionScriptMsg) object;
//如果是限时抢购促销活动结束
if (ScriptOperationTypeEnum.DELETE.equals(
promotionScriptMsg.getOperationType())) {
//获取促销活动ID
Long promotionId = promotionScriptMsg.getPromotionId();
//获取所有参与活动审核通过的商品集合
List
this.promotionGoodsClient.getSeckillGoodsList(
promotionId, SeckillGoodsApplyStatusEnum.PASS.value());
//清除促销活动脚本信息
this.promotionScriptClient.deleteCacheScript(promotionId, goodsList);
this.logger.debug("促销活动[" + promotionScriptMsg.getPromotionName()
+ "]结束,id=[" + promotionId + "]");
}
}
}
@Service
public class SeckillScriptManagerImpl implements SeckillScriptManager {
@Override
public void deleteCacheScript(Long promotionId, List
//如果参与促销活动的商品集合不为空并且集合长度不等于0
if (goodsList != null && goodsList.size() != 0) {
//需要批量更新的缓存数据集合
Map
//需要批量删除的缓存key集合
List
for (SeckillApplyDO goods : goodsList) {
//缓存key
String cacheKey = CachePrefix.SKU_PROMOTION.getPrefix()
+ goods.getSkuId();
//从缓存中读取促销脚本缓存
List
(List
if (scriptCacheList != null && scriptCacheList.size() != 0) {
//循环促销脚本缓存数据集合
for (PromotionScriptVO script : scriptCacheList) {
//如果脚本数据的促销活动信息与当前修改的促销活动信息一致,那么就将此信息删除
if (PromotionTypeEnum.SECKILL.name().
equals(script.getPromotionType())
&& script.getPromotionId().intValue()
== promotionId.intValue()) {
scriptCacheList.remove(script);
break;
}
}
if (scriptCacheList.size() == 0) {
delKeyList.add(cacheKey);
} else {
updateCacheMap.put(cacheKey, scriptCacheList);
}
}
}
cache.multiDel(delKeyList);
cache.multiSet(updateCacheMap);
}
}
}
限时抢购促销活动脚本引擎模板文件—single_promotion.ftl
<#--
验证促销活动是否在有效期内
@param promotionActive 活动信息对象(内置常量)
.startTime 获取开始时间
.endTime 活动结束时间
@param $currentTime 当前时间(变量)
@returns {boolean}
-->
function validTime(){
if (${promotionActive.startTime} <= $currentTime && $currentTime <= ${promotionActive.endTime}) {
return true;
}
return false;
}
<#--活动金额计算@param promotionActive 活动信息对象(内置常量)
.price 商品促销活动价格@param $sku 商品SKU信息对象(变量)
.$num 商品数量@returns {*}-->
function countPrice() {
var resultPrice = $sku.$num * ${promotionActive.price};
return resultPrice < 0 ? 0 : resultPrice.toString();
}
上述就是所有关于限时抢购促销活动的代码设计的内容,有任何问题,欢迎咨询在线客户或给我们留言。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。