commit
aee5f39a77
|
@ -25,6 +25,8 @@ public class DateUtils {
|
||||||
|
|
||||||
public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
|
public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 LocalDateTime 转换成 Date
|
* 将 LocalDateTime 转换成 Date
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package cn.iocoder.yudao.framework.jackson.config;
|
package cn.iocoder.yudao.framework.jackson.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
|
||||||
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.jackson.core.databind.LocalTimeJson;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -12,6 +13,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -30,12 +32,15 @@ public class YudaoJacksonAutoConfiguration {
|
||||||
/*
|
/*
|
||||||
* 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型
|
* 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型
|
||||||
* 2. 新增LocalDateTime序列化、反序列化规则
|
* 2. 新增LocalDateTime序列化、反序列化规则
|
||||||
|
* 3. 新增LocalTime序列化、反序列化规则
|
||||||
*/
|
*/
|
||||||
simpleModule
|
simpleModule
|
||||||
// .addSerializer(Long.class, ToStringSerializer.instance)
|
// .addSerializer(Long.class, ToStringSerializer.instance)
|
||||||
// .addSerializer(Long.TYPE, ToStringSerializer.instance)
|
// .addSerializer(Long.TYPE, ToStringSerializer.instance)
|
||||||
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
|
.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
|
||||||
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
|
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE)
|
||||||
|
.addSerializer(LocalTime.class, LocalTimeJson.SERIALIZER)
|
||||||
|
.addDeserializer(LocalTime.class, LocalTimeJson.DESERIALIZABLE);
|
||||||
|
|
||||||
objectMapper.registerModules(simpleModule);
|
objectMapper.registerModules(simpleModule);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.framework.jackson.core.databind;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
public class LocalTimeJson {
|
||||||
|
|
||||||
|
public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
|
||||||
|
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
|
||||||
|
.withZone(ZoneId.systemDefault()));
|
||||||
|
|
||||||
|
public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
|
||||||
|
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
|
||||||
|
.withZone(ZoneId.systemDefault()));
|
||||||
|
|
||||||
|
}
|
|
@ -45,4 +45,16 @@ public interface ErrorCodeConstants {
|
||||||
// ========== Price 相关 1003007000 ============
|
// ========== Price 相关 1003007000 ============
|
||||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1003007000, "支付价格计算异常,原因:价格小于等于 0");
|
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1003007000, "支付价格计算异常,原因:价格小于等于 0");
|
||||||
|
|
||||||
|
// ========== 秒杀活动 1003008000 ==========
|
||||||
|
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1003008000, "秒杀活动不存在");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003008002, "存在商品参加了其它秒杀活动");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003008003, "秒杀活动已关闭,不能修改");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1003008004, "秒杀活动未关闭或未结束,不能删除");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003008005, "秒杀活动已关闭,不能重复关闭");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1003008006, "秒杀活动已结束,不能关闭");
|
||||||
|
|
||||||
|
// ========== 秒杀时段 1003009000 ==========
|
||||||
|
ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1003009000, "秒杀时段不存在");
|
||||||
|
ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1003009001, "秒杀时段冲突");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Api(tags = "管理后台 - 秒杀活动")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/promotion/seckill-activity")
|
||||||
|
@Validated
|
||||||
|
public class SeckillActivityController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillActivityService seckillActivityService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@ApiOperation("创建秒杀活动")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:create')")
|
||||||
|
public CommonResult<Long> createSeckillActivity(@Valid @RequestBody SeckillActivityCreateReqVO createReqVO) {
|
||||||
|
return success(seckillActivityService.createSeckillActivity(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@ApiOperation("更新秒杀活动")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:update')")
|
||||||
|
public CommonResult<Boolean> updateSeckillActivity(@Valid @RequestBody SeckillActivityUpdateReqVO updateReqVO) {
|
||||||
|
seckillActivityService.updateSeckillActivity(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/close")
|
||||||
|
@ApiOperation("关闭秒杀活动")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:close')")
|
||||||
|
public CommonResult<Boolean> closeSeckillActivity(@RequestParam("id") Long id) {
|
||||||
|
seckillActivityService.closeSeckillActivity(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@ApiOperation("删除秒杀活动")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:delete')")
|
||||||
|
public CommonResult<Boolean> deleteSeckillActivity(@RequestParam("id") Long id) {
|
||||||
|
seckillActivityService.deleteSeckillActivity(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@ApiOperation("获得秒杀活动")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
|
||||||
|
public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
|
||||||
|
SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);
|
||||||
|
if (seckillActivity == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);
|
||||||
|
return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@ApiOperation("获得秒杀活动列表")
|
||||||
|
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
|
||||||
|
public CommonResult<List<SeckillActivityRespVO>> getSeckillActivityList(@RequestParam("ids") Collection<Long> ids) {
|
||||||
|
List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(ids);
|
||||||
|
return success(SeckillActivityConvert.INSTANCE.convertList(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@ApiOperation("获得秒杀活动分页")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
|
||||||
|
public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
|
||||||
|
PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
|
||||||
|
return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||||
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SeckillActivityBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
|
||||||
|
@NotNull(message = "秒杀活动名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "活动开始时间", required = true)
|
||||||
|
@NotNull(message = "活动开始时间不能为空")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "活动结束时间", required = true)
|
||||||
|
@NotNull(message = "活动结束时间不能为空")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModel("商品")
|
||||||
|
@Data
|
||||||
|
public static class Product {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "商品 SPU 编号不能为空")
|
||||||
|
private Long spuId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "商品 SKU 编号不能为空")
|
||||||
|
private Long skuId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀金额", required = true, example = "12.00")
|
||||||
|
@NotNull(message = "秒杀金额不能为空")
|
||||||
|
private Integer seckillPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀库存", example = "80")
|
||||||
|
@Min(value = 0, message = "秒杀库存需要大于等于 0")
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "每人限购", example = "10", notes = "如果为0则不限购")
|
||||||
|
@Min(value = 0, message = "每人限购需要大于等于 0")
|
||||||
|
private Integer limitBuyCount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀活动创建 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序", required = true)
|
||||||
|
@NotNull(message = "排序不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段id", required = true)
|
||||||
|
@NotBlank(message = "参与场次不能为空")
|
||||||
|
private String timeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品列表
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "商品列表不能为空")
|
||||||
|
@Valid
|
||||||
|
private List<Product> products;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀活动的详细 Response VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillActivityDetailRespVO extends SeckillActivityRespVO{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品列表
|
||||||
|
*/
|
||||||
|
private List<Product> products;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀活动分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillActivityPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀活动名称", example = "晚九点限时秒杀")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "活动状态", example = "进行中")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段id")
|
||||||
|
private String timeId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "创建时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||||
|
private LocalDateTime[] createTime;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀活动 Response VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillActivityRespVO extends SeckillActivityBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀活动id", required = true, example = "1")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "付款订单数", required = true)
|
||||||
|
private Integer orderCount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "付款人数", required = true)
|
||||||
|
private Integer userCount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "创建时间", required = true)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段id", required = true)
|
||||||
|
private String timeId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序", required = true)
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "活动状态", example = "进行中")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀活动更新 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀活动编号", required = true, example = "224")
|
||||||
|
@NotNull(message = "秒杀活动编号不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "备注", example = "限时秒杀活动")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序", required = true)
|
||||||
|
@NotNull(message = "排序不能为空")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段id", required = true)
|
||||||
|
@NotNull(message = "秒杀时段id不能为空")
|
||||||
|
private String timeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品列表
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "商品列表不能为空")
|
||||||
|
@Valid
|
||||||
|
private List<Product> products;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@Api(tags = "管理后台 - 秒杀时段")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/promotion/seckill-time")
|
||||||
|
@Validated
|
||||||
|
public class SeckillTimeController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillTimeService seckillTimeService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@ApiOperation("创建秒杀时段")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:create')")
|
||||||
|
public CommonResult<Long> createSeckillTime(@Valid @RequestBody SeckillTimeCreateReqVO createReqVO) {
|
||||||
|
return success(seckillTimeService.createSeckillTime(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@ApiOperation("更新秒杀时段")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:update')")
|
||||||
|
public CommonResult<Boolean> updateSeckillTime(@Valid @RequestBody SeckillTimeUpdateReqVO updateReqVO) {
|
||||||
|
seckillTimeService.updateSeckillTime(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@ApiOperation("删除秒杀时段")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:delete')")
|
||||||
|
public CommonResult<Boolean> deleteSeckillTime(@RequestParam("id") Long id) {
|
||||||
|
seckillTimeService.deleteSeckillTime(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@ApiOperation("获得秒杀时段")
|
||||||
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
|
||||||
|
public CommonResult<SeckillTimeRespVO> getSeckillTime(@RequestParam("id") Long id) {
|
||||||
|
SeckillTimeDO seckillTime = seckillTimeService.getSeckillTime(id);
|
||||||
|
return success(SeckillTimeConvert.INSTANCE.convert(seckillTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@ApiOperation("获得所有秒杀时段列表")
|
||||||
|
// @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
|
||||||
|
public CommonResult<List<SeckillTimeRespVO>> getSeckillTimeList() {
|
||||||
|
List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList();
|
||||||
|
return success(SeckillTimeConvert.INSTANCE.convertList(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
// @GetMapping("/page")
|
||||||
|
// @ApiOperation("获得秒杀时段分页")
|
||||||
|
// @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')")
|
||||||
|
// public CommonResult<PageResult<SeckillTimeRespVO>> getSeckillTimePage(@Valid SeckillTimePageReqVO pageVO) {
|
||||||
|
// PageResult<SeckillTimeDO> pageResult = seckillTimeService.getSeckillTimePage(pageVO);
|
||||||
|
// return success(SeckillTimeConvert.INSTANCE.convertPage(pageResult));
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.*;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||||
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SeckillTimeBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段名称", required = true)
|
||||||
|
@NotNull(message = "秒杀时段名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "开始时间点", required = true)
|
||||||
|
@NotNull(message = "开始时间点不能为空")
|
||||||
|
private LocalTime startTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "结束时间点", required = true)
|
||||||
|
@NotNull(message = "结束时间点不能为空")
|
||||||
|
private LocalTime endTime;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀时段创建 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillTimeCreateReqVO extends SeckillTimeBaseVO {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀时段分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillTimePageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀时段名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "开始时间点")
|
||||||
|
@DateTimeFormat(pattern = "HH:mm:ss")
|
||||||
|
private LocalTime startTime;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "结束时间点")
|
||||||
|
@DateTimeFormat(pattern = "HH:mm:ss")
|
||||||
|
private LocalTime endTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @ApiModelProperty(value = "创建时间")
|
||||||
|
// @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
// private Date[] createTime;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import java.util.*;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀时段 Response VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillTimeRespVO extends SeckillTimeBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "编号", required = true)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "秒杀活动数量", required = true)
|
||||||
|
private Integer seckillActivityCount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "创建时间", required = true)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
public class SeckillTimeSimpleRespVO {
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 秒杀时段更新 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "编号", required = true)
|
||||||
|
@NotNull(message = "编号不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 Convert
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface SeckillActivityConvert {
|
||||||
|
|
||||||
|
SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
|
||||||
|
|
||||||
|
SeckillProductDO convert(SeckillActivityBaseVO.Product product);
|
||||||
|
|
||||||
|
|
||||||
|
SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
|
||||||
|
|
||||||
|
default String map(Long[] value){
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
|
||||||
|
|
||||||
|
SeckillActivityRespVO convert(SeckillActivityDO bean);
|
||||||
|
|
||||||
|
List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list);
|
||||||
|
|
||||||
|
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
|
||||||
|
|
||||||
|
@Mappings({@Mapping(target = "products",source = "seckillProducts")})
|
||||||
|
SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较两个秒杀商品对象是否相等
|
||||||
|
*
|
||||||
|
* @param productDO 数据库中的商品
|
||||||
|
* @param productVO 前端传入的商品
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
default boolean isEquals(SeckillProductDO productDO, SeckillActivityBaseVO.Product productVO) {
|
||||||
|
return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
|
||||||
|
&& ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
|
||||||
|
&& ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
|
||||||
|
&& ObjectUtil.equals(productDO.getStock(), productVO.getStock())
|
||||||
|
&& ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较两个秒杀商品对象是否相等
|
||||||
|
*
|
||||||
|
* @param productDO 商品1
|
||||||
|
* @param productVO 商品2
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
|
||||||
|
return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId())
|
||||||
|
&& ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId())
|
||||||
|
&& ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice())
|
||||||
|
&& ObjectUtil.equals(productDO.getStock(), productVO.getStock())
|
||||||
|
&& ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeUpdateReqVO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 Convert
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface SeckillTimeConvert {
|
||||||
|
|
||||||
|
SeckillTimeConvert INSTANCE = Mappers.getMapper(SeckillTimeConvert.class);
|
||||||
|
|
||||||
|
SeckillTimeDO convert(SeckillTimeCreateReqVO bean);
|
||||||
|
|
||||||
|
SeckillTimeDO convert(SeckillTimeUpdateReqVO bean);
|
||||||
|
|
||||||
|
SeckillTimeRespVO convert(SeckillTimeDO bean);
|
||||||
|
|
||||||
|
List<SeckillTimeRespVO> convertList(List<SeckillTimeDO> list);
|
||||||
|
|
||||||
|
PageResult<SeckillTimeRespVO> convertPage(PageResult<SeckillTimeDO> page);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 DO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@TableName("promotion_seckill_activity")
|
||||||
|
@KeySequence("promotion_seckill_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class SeckillActivityDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动编号
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 秒杀活动名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 活动状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link PromotionActivityStatusEnum 对应的类}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
/**
|
||||||
|
* 活动开始时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
/**
|
||||||
|
* 活动结束时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
/**
|
||||||
|
* 秒杀时段id
|
||||||
|
*/
|
||||||
|
private String timeId;
|
||||||
|
/**
|
||||||
|
* 付款订单数
|
||||||
|
*/
|
||||||
|
private Integer orderCount;
|
||||||
|
/**
|
||||||
|
* 付款人数
|
||||||
|
*/
|
||||||
|
private Integer userCount;
|
||||||
|
/**
|
||||||
|
* 订单实付金额,单位:分
|
||||||
|
*/
|
||||||
|
private BigDecimal totalPrice;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀参与商品
|
||||||
|
* @TableName promotion_seckill_product
|
||||||
|
*/
|
||||||
|
@TableName(value ="promotion_seckill_product")
|
||||||
|
@Data
|
||||||
|
public class SeckillProductDO extends BaseDO {
|
||||||
|
/**
|
||||||
|
* 秒杀参与商品编号
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动id
|
||||||
|
*/
|
||||||
|
private Long activityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段id
|
||||||
|
*/
|
||||||
|
private Long timeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品id
|
||||||
|
*/
|
||||||
|
private Long spuId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品sku_id
|
||||||
|
*/
|
||||||
|
private Long skuId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀金额
|
||||||
|
*/
|
||||||
|
private Integer seckillPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀库存
|
||||||
|
*/
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每人限购
|
||||||
|
*/
|
||||||
|
private Integer limitBuyCount;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 DO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@TableName("promotion_seckill_time")
|
||||||
|
@KeySequence("promotion_seckill_time_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class SeckillTimeDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 秒杀时段名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 开始时间点
|
||||||
|
*/
|
||||||
|
private LocalTime startTime;
|
||||||
|
/**
|
||||||
|
* 结束时间点
|
||||||
|
*/
|
||||||
|
private LocalTime endTime;
|
||||||
|
/**
|
||||||
|
* 秒杀活动数量
|
||||||
|
*/
|
||||||
|
private Integer seckillActivityCount;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 Mapper
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
|
||||||
|
// TODO: 2022/11/28 halfninety 秒杀活动通过场次查询使用like会出现问题,查询活动场次编号为1,则活动场次编号为 1,11,......的都会被查出来
|
||||||
|
default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
|
||||||
|
.likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
|
||||||
|
.eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
|
||||||
|
.likeIfPresent(SeckillActivityDO::getTimeId, reqVO.getTimeId())
|
||||||
|
// .like(StringUtils.hasText(reqVO.getTimeId()),SeckillActivityDO::getTimeId, reqVO.getTimeId() + ",")
|
||||||
|
.betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
|
||||||
|
.orderByDesc(SeckillActivityDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
|
||||||
|
|
||||||
|
default List<SeckillProductDO> selectListByActivityId(Long id){
|
||||||
|
return selectList(SeckillProductDO::getActivityId,id);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds){
|
||||||
|
return selectList(SeckillProductDO::getSkuId,skuIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 Mapper
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface SeckillTimeMapper extends BaseMapperX<SeckillTimeDO> {
|
||||||
|
default List<SeckillTimeDO> selectListWithTime(LocalTime time){
|
||||||
|
if (time == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return selectList(new LambdaQueryWrapper<SeckillTimeDO>()
|
||||||
|
.le(SeckillTimeDO::getStartTime,time)
|
||||||
|
.ge(SeckillTimeDO::getEndTime,time));
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<SeckillTimeDO> selectListWithTime(LocalTime startTime, LocalTime endTime){
|
||||||
|
if (startTime == null && endTime == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return selectList(new LambdaQueryWrapper<SeckillTimeDO>()
|
||||||
|
.ge(SeckillTimeDO::getStartTime,startTime)
|
||||||
|
.le(SeckillTimeDO::getEndTime,endTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
default void sekillActivityCountAdd(List<Long> ids){
|
||||||
|
if (CollUtil.isEmpty(ids)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new LambdaUpdateChainWrapper<SeckillTimeDO>(this)
|
||||||
|
.in(SeckillTimeDO::getId,ids)
|
||||||
|
.setSql("`seckill_activity_count` = `seckill_activity_count` + 1 ")
|
||||||
|
.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
default void sekillActivityCountReduce(List<Long> ids){
|
||||||
|
if (CollUtil.isEmpty(ids)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new LambdaUpdateChainWrapper<SeckillTimeDO>(this)
|
||||||
|
.in(SeckillTimeDO::getId,ids)
|
||||||
|
.setSql("`seckill_activity_count` = `seckill_activity_count` - 1 ")
|
||||||
|
.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import javax.validation.*;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface SeckillActivityService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建秒杀活动
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createSeckillActivity(@Valid SeckillActivityCreateReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新秒杀活动
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭秒杀活动
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void closeSeckillActivity(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除秒杀活动
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteSeckillActivity(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得秒杀活动
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 秒杀活动
|
||||||
|
*/
|
||||||
|
SeckillActivityDO getSeckillActivity(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得秒杀活动列表
|
||||||
|
*
|
||||||
|
* @param ids 编号
|
||||||
|
* @return 秒杀活动列表
|
||||||
|
*/
|
||||||
|
List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得秒杀活动分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 秒杀活动分页
|
||||||
|
*/
|
||||||
|
PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过活动编号获取活动商品
|
||||||
|
* @param id 活动编号
|
||||||
|
* @return 活动商品列表
|
||||||
|
*/
|
||||||
|
List<SeckillProductDO> getSeckillProductListByActivityId(Long id);
|
||||||
|
}
|
|
@ -0,0 +1,221 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityBaseVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService;
|
||||||
|
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀活动 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class SeckillActivityServiceImpl implements SeckillActivityService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillActivityMapper seckillActivityMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillProductMapper seckillProductMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillTimeService seckillTimeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
|
||||||
|
List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
|
||||||
|
// 校验商品是否冲突
|
||||||
|
validateSeckillActivityProductConflicts(null, createReqVO.getProducts());
|
||||||
|
// 更新秒杀时段的秒杀活动数量
|
||||||
|
seckillTimeService.sekillActivityCountAdd(StrUtils.splitToLong(createReqVO.getTimeId(),","));
|
||||||
|
// 插入秒杀活动
|
||||||
|
SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
|
||||||
|
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime()));
|
||||||
|
seckillActivityMapper.insert(seckillActivity);
|
||||||
|
// 插入商品
|
||||||
|
List<SeckillProductDO> productDOS = CollectionUtils.convertList(createReqVO.getProducts(),
|
||||||
|
product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(seckillActivity.getId()));
|
||||||
|
seckillProductMapper.insertBatch(productDOS);
|
||||||
|
return seckillActivity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
|
||||||
|
// 校验存在
|
||||||
|
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(updateReqVO.getId());
|
||||||
|
if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
// 校验商品是否冲突
|
||||||
|
validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
|
||||||
|
// 更新秒杀时段的秒杀活动数量
|
||||||
|
updateSeckillTimeActivityCount(updateReqVO.getId(), updateReqVO.getTimeId());
|
||||||
|
// 更新活动
|
||||||
|
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
|
||||||
|
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime()));
|
||||||
|
seckillActivityMapper.updateById(updateObj);
|
||||||
|
// 更新商品
|
||||||
|
updateSeckillProduct(updateReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新秒杀时段的秒杀活动数量
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @param timeId
|
||||||
|
*/
|
||||||
|
private void updateSeckillTimeActivityCount(Long id, String timeId) {
|
||||||
|
List<Long> updateTimeIds = StrUtils.splitToLong(timeId, ",");
|
||||||
|
// 查出自己的timeIds
|
||||||
|
SeckillActivityDO seckillActivityDO = seckillActivityMapper.selectById(id);
|
||||||
|
List<Long> existsTimeIds = StrUtils.splitToLong(seckillActivityDO.getTimeId(), ",");
|
||||||
|
//需要减少的时间段
|
||||||
|
List<Long> reduceIds = existsTimeIds.stream()
|
||||||
|
.filter(existsTimeId -> !updateTimeIds.contains(existsTimeId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
//需要添加的时间段
|
||||||
|
updateTimeIds.removeIf(updateTimeId -> existsTimeIds.contains(updateTimeId));
|
||||||
|
//更新减少时间段和增加时间段
|
||||||
|
seckillTimeService.sekillActivityCountAdd(updateTimeIds);
|
||||||
|
seckillTimeService.sekillActivityCountReduce(reduceIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新秒杀商品
|
||||||
|
*/
|
||||||
|
private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
|
||||||
|
List<SeckillProductDO> seckillProductDOS = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
|
||||||
|
List<SeckillActivityBaseVO.Product> products = updateReqVO.getProducts();
|
||||||
|
//对后台查出的数据和前台查出的数据进行遍历,
|
||||||
|
//1.对前台数据进行遍历:如果不存在于后台的sku中需要新增
|
||||||
|
//2.对后台数据进行遍历:如果不存在于前台的sku中需要删除
|
||||||
|
//计算需要删除的数据
|
||||||
|
List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOS, SeckillProductDO::getId,
|
||||||
|
seckillProductDO -> products.stream()
|
||||||
|
.noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
|
||||||
|
if (CollUtil.isNotEmpty(deleteIds)) {
|
||||||
|
seckillProductMapper.deleteBatchIds(deleteIds);
|
||||||
|
}
|
||||||
|
//计算需要新增的数据
|
||||||
|
List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
|
||||||
|
product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
|
||||||
|
newSeckillProductDOs.removeIf(product -> seckillProductDOS.stream()
|
||||||
|
.anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
|
||||||
|
if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
|
||||||
|
seckillProductMapper.insertBatch(newSeckillProductDOs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验商品是否冲突
|
||||||
|
*
|
||||||
|
* @param id 秒杀活动编号
|
||||||
|
* @param products 商品列表
|
||||||
|
*/
|
||||||
|
private void validateSeckillActivityProductConflicts(Long id, List<SeckillActivityBaseVO.Product> products) {
|
||||||
|
if (CollUtil.isEmpty(products)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<SeckillProductDO> seckillProductDOS = seckillProductMapper
|
||||||
|
.selectListBySkuIds(CollectionUtils.convertSet(products, SeckillActivityBaseVO.Product::getSkuId));
|
||||||
|
if (CollUtil.isEmpty(seckillProductDOS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<SeckillActivityDO> seckillActivityDOS = seckillActivityMapper
|
||||||
|
.selectBatchIds(CollectionUtils.convertSet(seckillProductDOS, SeckillProductDO::getActivityId));
|
||||||
|
if (id != null) {// 排除自己这个活动
|
||||||
|
seckillActivityDOS.removeIf(item -> id.equals(item.getId()));
|
||||||
|
}
|
||||||
|
// 排除不满足status的活动
|
||||||
|
List<Integer> statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus());
|
||||||
|
seckillActivityDOS.removeIf(item -> !statuses.contains(item.getStatus()));
|
||||||
|
//如果非空,则说明冲突
|
||||||
|
if (CollUtil.isNotEmpty(seckillActivityDOS)) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeSeckillActivity(Long id) {
|
||||||
|
// 校验存在
|
||||||
|
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
|
||||||
|
if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END);
|
||||||
|
}
|
||||||
|
// 更新
|
||||||
|
SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
|
||||||
|
seckillActivityMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteSeckillActivity(Long id) {
|
||||||
|
// 校验存在
|
||||||
|
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
|
||||||
|
List<Integer> statuses = asList(PromotionActivityStatusEnum.CLOSE.getStatus(), PromotionActivityStatusEnum.END.getStatus());
|
||||||
|
if (!statuses.contains(seckillActivity.getStatus())) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
|
||||||
|
}
|
||||||
|
// 更新秒杀时段的秒杀活动数量
|
||||||
|
seckillTimeService.sekillActivityCountReduce(StrUtils.splitToLong(seckillActivity.getTimeId(),","));
|
||||||
|
// 删除
|
||||||
|
seckillActivityMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SeckillActivityDO validateSeckillActivityExists(Long id) {
|
||||||
|
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(id);
|
||||||
|
if (seckillActivity == null) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return seckillActivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SeckillActivityDO getSeckillActivity(Long id) {
|
||||||
|
return seckillActivityMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids) {
|
||||||
|
return seckillActivityMapper.selectBatchIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) {
|
||||||
|
return seckillActivityMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SeckillProductDO> getSeckillProductListByActivityId(Long id) {
|
||||||
|
return seckillProductMapper.selectListByActivityId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface SeckillTimeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建秒杀时段
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createSeckillTime(@Valid SeckillTimeCreateReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新秒杀时段
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateSeckillTime(@Valid SeckillTimeUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除秒杀时段
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteSeckillTime(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得秒杀时段
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 秒杀时段
|
||||||
|
*/
|
||||||
|
SeckillTimeDO getSeckillTime(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得所有秒杀时段列表
|
||||||
|
*
|
||||||
|
* @return 所有秒杀时段列表
|
||||||
|
*/
|
||||||
|
List<SeckillTimeDO> getSeckillTimeList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段列表的秒杀活动数量加 1
|
||||||
|
*
|
||||||
|
* @param ids 秒杀时段id列表
|
||||||
|
*/
|
||||||
|
void sekillActivityCountAdd(List<Long> ids);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段列表的秒杀活动数量减 1
|
||||||
|
*
|
||||||
|
* @param ids 秒杀时段id列表
|
||||||
|
*/
|
||||||
|
void sekillActivityCountReduce(List<Long> ids);
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeUpdateReqVO;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒杀时段 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class SeckillTimeServiceImpl implements SeckillTimeService {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillTimeMapper seckillTimeMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createSeckillTime(SeckillTimeCreateReqVO createReqVO) {
|
||||||
|
// 校验时间段是否冲突
|
||||||
|
validateSeckillTimeConflict(null,createReqVO.getStartTime(), createReqVO.getEndTime());
|
||||||
|
// 插入
|
||||||
|
SeckillTimeDO seckillTime = SeckillTimeConvert.INSTANCE.convert(createReqVO);
|
||||||
|
seckillTimeMapper.insert(seckillTime);
|
||||||
|
// 返回
|
||||||
|
return seckillTime.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSeckillTime(SeckillTimeUpdateReqVO updateReqVO) {
|
||||||
|
// 校验存在
|
||||||
|
this.validateSeckillTimeExists(updateReqVO.getId());
|
||||||
|
// 校验时间段是否冲突
|
||||||
|
validateSeckillTimeConflict(updateReqVO.getId(), updateReqVO.getStartTime(), updateReqVO.getEndTime());
|
||||||
|
// 更新
|
||||||
|
SeckillTimeDO updateObj = SeckillTimeConvert.INSTANCE.convert(updateReqVO);
|
||||||
|
seckillTimeMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteSeckillTime(Long id) {
|
||||||
|
// 校验存在
|
||||||
|
this.validateSeckillTimeExists(id);
|
||||||
|
// 删除
|
||||||
|
seckillTimeMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSeckillTimeExists(Long id) {
|
||||||
|
if (seckillTimeMapper.selectById(id) == null) {
|
||||||
|
throw exception(SECKILL_TIME_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验时间是否存在冲突
|
||||||
|
*
|
||||||
|
* @param startTime 开始时间
|
||||||
|
* @param endTime 结束时间
|
||||||
|
*/
|
||||||
|
private void validateSeckillTimeConflict(Long id, LocalTime startTime, LocalTime endTime) {
|
||||||
|
//查询开始时间,结束时间,是否在别人的时间段内
|
||||||
|
List<SeckillTimeDO> startTimeList = seckillTimeMapper.selectListWithTime(startTime);
|
||||||
|
List<SeckillTimeDO> endTimeList = seckillTimeMapper.selectListWithTime(endTime);
|
||||||
|
//查询自己时间段内是否有时间段
|
||||||
|
List<SeckillTimeDO> startEndTimeList = seckillTimeMapper.selectListWithTime(startTime, endTime);
|
||||||
|
if (id != null) {
|
||||||
|
//移除自己
|
||||||
|
startTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
|
||||||
|
endTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
|
||||||
|
startEndTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id));
|
||||||
|
}
|
||||||
|
if (CollUtil.isNotEmpty(startTimeList) || CollUtil.isNotEmpty(endTimeList)
|
||||||
|
|| CollUtil.isNotEmpty(startEndTimeList)) {
|
||||||
|
throw exception(SECKILL_TIME_CONFLICTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SeckillTimeDO getSeckillTime(Long id) {
|
||||||
|
return seckillTimeMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SeckillTimeDO> getSeckillTimeList() {
|
||||||
|
return seckillTimeMapper.selectList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sekillActivityCountAdd(List<Long> ids) {
|
||||||
|
seckillTimeMapper.sekillActivityCountAdd(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sekillActivityCountReduce(List<Long> ids) {
|
||||||
|
seckillTimeMapper.sekillActivityCountReduce(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||||
|
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||||
|
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||||
|
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||||
|
-->
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||||
|
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||||
|
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||||
|
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||||
|
-->
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -0,0 +1,170 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckillactivity;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckillactivity.vo.SeckillActivityUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_NOT_EXISTS;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link SeckillActivityServiceImpl} 的单元测试类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Import(SeckillActivityServiceImpl.class)
|
||||||
|
public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillActivityServiceImpl seckillActivityService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillActivityMapper seckillActivityMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSeckillActivity_success() {
|
||||||
|
// 准备参数
|
||||||
|
SeckillActivityCreateReqVO reqVO = randomPojo(SeckillActivityCreateReqVO.class);
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
Long seckillActivityId = seckillActivityService.createSeckillActivity(reqVO);
|
||||||
|
// 断言
|
||||||
|
assertNotNull(seckillActivityId);
|
||||||
|
// 校验记录的属性是否正确
|
||||||
|
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(seckillActivityId);
|
||||||
|
assertPojoEquals(reqVO, seckillActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSeckillActivity_success() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class);
|
||||||
|
seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据
|
||||||
|
// 准备参数
|
||||||
|
SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class, o -> {
|
||||||
|
o.setId(dbSeckillActivity.getId()); // 设置更新的 ID
|
||||||
|
});
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
seckillActivityService.updateSeckillActivity(reqVO);
|
||||||
|
// 校验是否更新正确
|
||||||
|
SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(reqVO.getId()); // 获取最新的
|
||||||
|
assertPojoEquals(reqVO, seckillActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSeckillActivity_notExists() {
|
||||||
|
// 准备参数
|
||||||
|
SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class);
|
||||||
|
|
||||||
|
// 调用, 并断言异常
|
||||||
|
assertServiceException(() -> seckillActivityService.updateSeckillActivity(reqVO), SECKILL_ACTIVITY_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSeckillActivity_success() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class);
|
||||||
|
seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据
|
||||||
|
// 准备参数
|
||||||
|
Long id = dbSeckillActivity.getId();
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
seckillActivityService.deleteSeckillActivity(id);
|
||||||
|
// 校验数据不存在了
|
||||||
|
assertNull(seckillActivityMapper.selectById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSeckillActivity_notExists() {
|
||||||
|
// 准备参数
|
||||||
|
Long id = randomLongId();
|
||||||
|
|
||||||
|
// 调用, 并断言异常
|
||||||
|
assertServiceException(() -> seckillActivityService.deleteSeckillActivity(id), SECKILL_ACTIVITY_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||||
|
public void testGetSeckillActivityPage() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
|
||||||
|
o.setName(null);
|
||||||
|
o.setStatus(null);
|
||||||
|
o.setTimeId(null);
|
||||||
|
o.setCreateTime(null);
|
||||||
|
});
|
||||||
|
seckillActivityMapper.insert(dbSeckillActivity);
|
||||||
|
// 测试 name 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
|
||||||
|
// 测试 status 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
|
||||||
|
// 测试 timeId 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeId(null)));
|
||||||
|
// 测试 createTime 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
|
||||||
|
// 准备参数
|
||||||
|
SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
|
||||||
|
reqVO.setName(null);
|
||||||
|
reqVO.setStatus(null);
|
||||||
|
reqVO.setTimeId(null);
|
||||||
|
reqVO.setCreateTime((new LocalDateTime[]{}));
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
|
||||||
|
// 断言
|
||||||
|
assertEquals(1, pageResult.getTotal());
|
||||||
|
assertEquals(1, pageResult.getList().size());
|
||||||
|
assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||||
|
public void testGetSeckillActivityList() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到
|
||||||
|
o.setName(null);
|
||||||
|
o.setStatus(null);
|
||||||
|
o.setTimeId(null);
|
||||||
|
o.setCreateTime(null);
|
||||||
|
});
|
||||||
|
seckillActivityMapper.insert(dbSeckillActivity);
|
||||||
|
// 测试 name 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
|
||||||
|
// 测试 status 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
|
||||||
|
// 测试 timeId 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeId(null)));
|
||||||
|
// 测试 createTime 不匹配
|
||||||
|
seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
|
||||||
|
// 准备参数
|
||||||
|
// SeckillActivityExportReqVO reqVO = new SeckillActivityExportReqVO();
|
||||||
|
// reqVO.setName(null);
|
||||||
|
// reqVO.setStatus(null);
|
||||||
|
// reqVO.setTimeId(null);
|
||||||
|
// reqVO.setCreateTime((new Date[]{}));
|
||||||
|
//
|
||||||
|
// // 调用
|
||||||
|
// List<SeckillActivityDO> list = seckillActivityService.getSeckillActivityList(reqVO);
|
||||||
|
// // 断言
|
||||||
|
// assertEquals(1, list.size());
|
||||||
|
// assertPojoEquals(dbSeckillActivity, list.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.service.seckilltime;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.seckilltime.vo.SeckillTimeUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeServiceImpl;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link SeckillTimeServiceImpl} 的单元测试类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Import(SeckillTimeServiceImpl.class)
|
||||||
|
public class SeckillTimeServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillTimeServiceImpl seckillTimeService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SeckillTimeMapper seckillTimeMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJacksonSerializ(){
|
||||||
|
|
||||||
|
// 准备参数
|
||||||
|
SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
|
||||||
|
// ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
String string = objectMapper.writeValueAsString(reqVO);
|
||||||
|
System.out.println(string);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSeckillTime_success() {
|
||||||
|
// 准备参数
|
||||||
|
SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class);
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
Long seckillTimeId = seckillTimeService.createSeckillTime(reqVO);
|
||||||
|
// 断言
|
||||||
|
assertNotNull(seckillTimeId);
|
||||||
|
// 校验记录的属性是否正确
|
||||||
|
SeckillTimeDO seckillTime = seckillTimeMapper.selectById(seckillTimeId);
|
||||||
|
assertPojoEquals(reqVO, seckillTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSeckillTime_success() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
|
||||||
|
seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
|
||||||
|
// 准备参数
|
||||||
|
SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class, o -> {
|
||||||
|
o.setId(dbSeckillTime.getId()); // 设置更新的 ID
|
||||||
|
});
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
seckillTimeService.updateSeckillTime(reqVO);
|
||||||
|
// 校验是否更新正确
|
||||||
|
SeckillTimeDO seckillTime = seckillTimeMapper.selectById(reqVO.getId()); // 获取最新的
|
||||||
|
assertPojoEquals(reqVO, seckillTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSeckillTime_notExists() {
|
||||||
|
// 准备参数
|
||||||
|
SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class);
|
||||||
|
|
||||||
|
// 调用, 并断言异常
|
||||||
|
assertServiceException(() -> seckillTimeService.updateSeckillTime(reqVO), SECKILL_TIME_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSeckillTime_success() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class);
|
||||||
|
seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据
|
||||||
|
// 准备参数
|
||||||
|
Long id = dbSeckillTime.getId();
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
seckillTimeService.deleteSeckillTime(id);
|
||||||
|
// 校验数据不存在了
|
||||||
|
assertNull(seckillTimeMapper.selectById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSeckillTime_notExists() {
|
||||||
|
// 准备参数
|
||||||
|
Long id = randomLongId();
|
||||||
|
|
||||||
|
// 调用, 并断言异常
|
||||||
|
assertServiceException(() -> seckillTimeService.deleteSeckillTime(id), SECKILL_TIME_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||||
|
public void testGetSeckillTimePage() {
|
||||||
|
// mock 数据
|
||||||
|
// SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
|
||||||
|
// o.setName(null);
|
||||||
|
// o.setStartTime(null);
|
||||||
|
// o.setEndTime(null);
|
||||||
|
// o.setCreateTime(null);
|
||||||
|
// });
|
||||||
|
// seckillTimeMapper.insert(dbSeckillTime);
|
||||||
|
// // 测试 name 不匹配
|
||||||
|
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
|
||||||
|
// // 测试 startTime 不匹配
|
||||||
|
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
|
||||||
|
// // 测试 endTime 不匹配
|
||||||
|
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
|
||||||
|
// // 测试 createTime 不匹配
|
||||||
|
// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
|
||||||
|
// // 准备参数
|
||||||
|
// SeckillTimePageReqVO reqVO = new SeckillTimePageReqVO();
|
||||||
|
// reqVO.setName(null);
|
||||||
|
//// reqVO.setStartTime((new LocalTime()));
|
||||||
|
//// reqVO.setEndTime((new LocalTime[]{}));
|
||||||
|
//// reqVO.setCreateTime((new Date[]{}));
|
||||||
|
//
|
||||||
|
// // 调用
|
||||||
|
// PageResult<SeckillTimeDO> pageResult = seckillTimeService.getSeckillTimePage(reqVO);
|
||||||
|
// // 断言
|
||||||
|
// assertEquals(1, pageResult.getTotal());
|
||||||
|
// assertEquals(1, pageResult.getList().size());
|
||||||
|
// assertPojoEquals(dbSeckillTime, pageResult.getList().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||||
|
public void testGetSeckillTimeList() {
|
||||||
|
// mock 数据
|
||||||
|
SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到
|
||||||
|
o.setName(null);
|
||||||
|
o.setStartTime(null);
|
||||||
|
o.setEndTime(null);
|
||||||
|
o.setCreateTime(null);
|
||||||
|
});
|
||||||
|
seckillTimeMapper.insert(dbSeckillTime);
|
||||||
|
// 测试 name 不匹配
|
||||||
|
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null)));
|
||||||
|
// 测试 startTime 不匹配
|
||||||
|
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null)));
|
||||||
|
// 测试 endTime 不匹配
|
||||||
|
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null)));
|
||||||
|
// 测试 createTime 不匹配
|
||||||
|
seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null)));
|
||||||
|
// 准备参数
|
||||||
|
// SeckillTimeExportReqVO reqVO = new SeckillTimeExportReqVO();
|
||||||
|
// reqVO.setName(null);
|
||||||
|
// reqVO.setStartTime((new LocalTime[]{}));
|
||||||
|
// reqVO.setEndTime((new LocalTime[]{}));
|
||||||
|
// reqVO.setCreateTime((new Date[]{}));
|
||||||
|
//
|
||||||
|
// // 调用
|
||||||
|
// List<SeckillTimeDO> list = seckillTimeService.getSeckillTimeList(reqVO);
|
||||||
|
// // 断言
|
||||||
|
// assertEquals(1, list.size());
|
||||||
|
// assertPojoEquals(dbSeckillTime, list.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 创建秒杀活动
|
||||||
|
export function createSeckillActivity(data) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/create',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新秒杀活动
|
||||||
|
export function updateSeckillActivity(data) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/update',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭限时折扣活动
|
||||||
|
export function closeSeckillActivity(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/close?id=' + id,
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除秒杀活动
|
||||||
|
export function deleteSeckillActivity(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/delete?id=' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得秒杀活动
|
||||||
|
export function getSeckillActivity(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/get?id=' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得秒杀活动分页
|
||||||
|
export function getSeckillActivityPage(query) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-activity/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 创建秒杀时段
|
||||||
|
export function createSeckillTime(data) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/create',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新秒杀时段
|
||||||
|
export function updateSeckillTime(data) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/update',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除秒杀时段
|
||||||
|
export function deleteSeckillTime(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/delete?id=' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得秒杀时段
|
||||||
|
export function getSeckillTime(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/get?id=' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得秒杀时段分页
|
||||||
|
export function getSeckillTimePage(query) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有的秒杀时段
|
||||||
|
export function getSeckillTimeList() {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/list',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出秒杀时段 Excel
|
||||||
|
export function exportSeckillTimeExcel(query) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion/seckill-time/export-excel',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,490 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
|
||||||
|
label-width="68px">
|
||||||
|
<el-form-item label="活动名称" prop="name">
|
||||||
|
<el-input v-model="queryParams.name" placeholder="请输入秒杀活动名称" clearable
|
||||||
|
@keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
|
||||||
|
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)" :key="dict.value"
|
||||||
|
:label="dict.label" :value="dict.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="参与场次" prop="timeId">
|
||||||
|
<el-select v-model="queryParams.timeId" placeholder="请选择参与场次" clearable size="small">
|
||||||
|
<el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间" prop="createTime">
|
||||||
|
<el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
:default-time="['00:00:00', '23:59:59']" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 操作工具栏 -->
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||||
|
v-hasPermi="['promotion:seckill-activity:create']">新增秒杀活动</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="el-icon-menu" size="mini" @click="openSeckillTime"
|
||||||
|
v-hasPermi="['promotion:seckill-activity:create']">管理参与场次</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="活动名称" align="center" prop="name" />
|
||||||
|
<el-table-column label="活动状态" align="center" prop="status">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="参与场次" prop="timeId" width="250">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-for="item in seckillTimeList" :key="item.id"
|
||||||
|
v-if="scope.row.timeId.indexOf(item.id) !== -1">
|
||||||
|
<el-tag style="margin:4px;" size="small">{{ item.name }}</el-tag>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="活动开始时间" align="center" prop="startTime" width="190">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ "开始: " + parseTime(scope.row.startTime) }}</span>
|
||||||
|
<span>{{ "结束: " + parseTime(scope.row.endTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="付款订单数" align="center" prop="orderCount" />
|
||||||
|
<el-table-column label="付款人数" align="center" prop="userCount" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['promotion:seckill-activity:update']">修改</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-close" @click="handleClose(scope.row)"
|
||||||
|
v-hasPermi="['promotion:seckill-activity:delete']">关闭</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['promotion:seckill-activity:delete']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
|
||||||
|
<!-- 对话框(添加 / 修改) -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="1200px" v-dialogDrag append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="活动名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入秒杀活动名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="活动时间" prop="startAndEndTime">
|
||||||
|
<el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange"
|
||||||
|
value-format="timestamp" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||||
|
style="width: 1080px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="sort">
|
||||||
|
<el-input-number v-model="form.sort" controls-position="right" :min="0" :max="10000">
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="场次选择">
|
||||||
|
<el-select v-model="form.timeId" placeholder="请选择参与场次" clearable size="small" multiple filterable
|
||||||
|
style="width: 880px">
|
||||||
|
<el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id">
|
||||||
|
<span style="float: left">{{ item.name + ': { ' }} {{ item.startTime }} -- {{ item.endTime +
|
||||||
|
' }'
|
||||||
|
}}</span>
|
||||||
|
<span style="float: right; color: #8492a6; font-size: 13px"></span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品选择">
|
||||||
|
<el-select v-model="form.skuIds" placeholder="请选择活动商品" clearable size="small" multiple filterable
|
||||||
|
style="width: 880px" @change="changeFormSku">
|
||||||
|
<el-option v-for="item in productSkus" :key="item.id" :label="item.spuName + ' ' + item.name"
|
||||||
|
:value="item.id">
|
||||||
|
<span style="float: left">{{ item.spuName }} {{ item.name }}</span>
|
||||||
|
<span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price /
|
||||||
|
100.0).toFixed(2)
|
||||||
|
}}</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-row>
|
||||||
|
<el-button type="primary" size="mini" @click="batchEditProduct('limitBuyCount')">限购</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="batchEditProduct('seckillPrice')">秒杀价</el-button>
|
||||||
|
<el-button type="primary" size="mini" @click="batchEditProduct('seckillStock')">秒杀库存</el-button>
|
||||||
|
</el-row>
|
||||||
|
<el-table v-loading="loading" ref="productsTable" :data="form.products">
|
||||||
|
<el-table-column type="selection" width="55">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="商品名称" align="center" width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.spuName }} {{ scope.row.name }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="商品价格" align="center" prop="price">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
¥{{ (scope.row.price / 100.0).toFixed(2) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="库存" align="center" prop="productStock" />
|
||||||
|
<el-table-column label="限购(0为不限购)" align="center" width="150">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.limitBuyCount" size="mini" :min="0" :max="10000">
|
||||||
|
</el-input-number>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="秒杀价(元)" align="center" width="150">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.seckillPrice" size="mini" :precision="2" :min="0"
|
||||||
|
:max="10000">
|
||||||
|
</el-input-number>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="秒杀库存" align="center" width="150" prop="seckillStock">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.seckillStock" size="mini" :min="0" :max="10000">
|
||||||
|
</el-input-number>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-delete"
|
||||||
|
@click="removeFormSku(scope.row.skuId)">删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getSkuOptionList } from "@/api/mall/product/sku";
|
||||||
|
import { createSeckillActivity, updateSeckillActivity, closeSeckillActivity,deleteSeckillActivity, getSeckillActivity, getSeckillActivityPage, exportSeckillActivityExcel } from "@/api/mall/promotion/seckillActivity";
|
||||||
|
import { getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
|
||||||
|
import { deepClone } from "@/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SeckillActivity",
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 秒杀活动列表
|
||||||
|
list: [],
|
||||||
|
// 秒杀场次列表
|
||||||
|
seckillTimeList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
name: null,
|
||||||
|
status: null,
|
||||||
|
timeId: null,
|
||||||
|
createTime: [],
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {
|
||||||
|
skuIds: [], // 选中的 SKU
|
||||||
|
products: [], // 商品信息
|
||||||
|
timeId: [], //选中的秒杀场次id
|
||||||
|
},
|
||||||
|
// 商品 SKU 列表
|
||||||
|
productSkus: [],
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
name: [{ required: true, message: "秒杀活动名称不能为空", trigger: "blur" }],
|
||||||
|
status: [{ required: true, message: "活动状态不能为空", trigger: "blur" }],
|
||||||
|
startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
|
||||||
|
sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
|
||||||
|
timeId: [{ required: true, message: "秒杀场次不能为空", trigger: "blur" }],
|
||||||
|
totalPrice: [{ required: true, message: "订单实付金额,单位:分不能为空", trigger: "blur" }],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
$route: 'getList'
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
const timeId = this.$route.params && this.$route.params.timeId;
|
||||||
|
if (timeId) {
|
||||||
|
this.queryParams.timeId = timeId
|
||||||
|
}
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getSeckillActivityPage(this.queryParams).then(response => {
|
||||||
|
this.list = response.data.list;
|
||||||
|
this.total = response.data.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
if (timeId) {
|
||||||
|
this.$route.params.timeId = undefined
|
||||||
|
}
|
||||||
|
// 获得 SKU 商品列表
|
||||||
|
getSkuOptionList().then(response => {
|
||||||
|
this.productSkus = response.data;
|
||||||
|
});
|
||||||
|
// 获取参与场次列表
|
||||||
|
getSeckillTimeList().then(response => {
|
||||||
|
this.seckillTimeList = response.data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 取消按钮 */
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
/** 表单重置 */
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
status: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
sort: undefined,
|
||||||
|
timeId: [],
|
||||||
|
totalPrice: undefined,
|
||||||
|
skuIds: [],
|
||||||
|
products: [],
|
||||||
|
};
|
||||||
|
this.resetForm("form");
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNo = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
/**打开秒杀场次管理页面 */
|
||||||
|
openSeckillTime() {
|
||||||
|
this.$tab.openPage("秒杀场次管理", "/promotion/seckill-time");
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset();
|
||||||
|
this.open = true;
|
||||||
|
this.title = "添加秒杀活动";
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset();
|
||||||
|
const id = row.id;
|
||||||
|
getSeckillActivity(id).then(response => {
|
||||||
|
var timeIdList = response.data.timeId.split(',')
|
||||||
|
this.form = response.data;
|
||||||
|
// 修改数据
|
||||||
|
this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
|
||||||
|
this.form.timeId = timeIdList.map(item => parseInt(item))
|
||||||
|
this.form.skuIds = response.data.products.map(item => item.skuId);
|
||||||
|
this.form.products.forEach(product => {
|
||||||
|
// 获得对应的 SKU 信息
|
||||||
|
const sku = this.productSkus.find(item => item.id === product.skuId);
|
||||||
|
if (!sku) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置商品信息
|
||||||
|
product.name = sku.name;
|
||||||
|
product.spuName = sku.spuName;
|
||||||
|
product.price = sku.price;
|
||||||
|
product.productStock = sku.stock;
|
||||||
|
this.$set(product,'seckillStock',product.stock);
|
||||||
|
product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice / 100 : undefined;
|
||||||
|
|
||||||
|
});
|
||||||
|
// 打开弹窗
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改限时折扣活动";
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 处理数据
|
||||||
|
const data = deepClone(this.form);
|
||||||
|
data.startTime = this.form.startAndEndTime[0];
|
||||||
|
data.endTime = this.form.startAndEndTime[1];
|
||||||
|
data.timeId = data.timeId.toString();
|
||||||
|
data.products.forEach(product => {
|
||||||
|
product.stock = product.seckillStock;
|
||||||
|
product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice * 100 : undefined;
|
||||||
|
});
|
||||||
|
// 修改的提交
|
||||||
|
if (this.form.id != null) {
|
||||||
|
updateSeckillActivity(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 添加的提交
|
||||||
|
createSeckillActivity(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 关闭按钮操作 */
|
||||||
|
handleClose(row) {
|
||||||
|
const id = row.id;
|
||||||
|
this.$modal.confirm('是否确认关闭秒杀活动编号为"' + id + '"的数据项?').then(function () {
|
||||||
|
return closeSeckillActivity(id);
|
||||||
|
}).then(() => {
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("关闭成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const id = row.id;
|
||||||
|
this.$modal.confirm('是否确认删除秒杀活动编号为"' + id + '"的数据项?').then(function () {
|
||||||
|
return deleteSeckillActivity(id);
|
||||||
|
}).then(() => {
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("删除成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
},
|
||||||
|
/** 批量修改商品秒杀价,秒杀库存,每人限购数量 */
|
||||||
|
batchEditProduct(editType) {
|
||||||
|
const selectProducts = this.$refs.productsTable.selection;
|
||||||
|
if (selectProducts.length === 0) {
|
||||||
|
this.$modal.msgError("请选择需要修改的商品");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let promptTitle = '请输入';
|
||||||
|
let regularPattern = /^[\s\S]*.*[^\s][\s\S]*$/; // 判断非空,且非空格
|
||||||
|
//限购数
|
||||||
|
if (editType === 'limitBuyCount') {
|
||||||
|
promptTitle = '限购数';
|
||||||
|
regularPattern = /^[0-9]*$/; //数字
|
||||||
|
}
|
||||||
|
//秒杀价
|
||||||
|
if (editType === 'seckillPrice') {
|
||||||
|
promptTitle = '秒杀价(元)';
|
||||||
|
regularPattern = /^[0-9]+(\.[0-9]{1,2})?$/; // 有一位或两位小数的正数
|
||||||
|
}
|
||||||
|
//秒杀库存
|
||||||
|
if (editType === 'seckillStock') {
|
||||||
|
promptTitle = '秒杀库存';
|
||||||
|
regularPattern = /^[0-9]*$/; //数字
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$prompt(promptTitle, '提示', {
|
||||||
|
confirmButtonText: '保存',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
inputPattern: regularPattern,
|
||||||
|
inputErrorMessage: promptTitle + '格式不正确'
|
||||||
|
}).then(({ value }) => {
|
||||||
|
if (editType === 'limitBuyCount') {
|
||||||
|
selectProducts.forEach((item) => {
|
||||||
|
item.limitBuyCount = value;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (editType === 'seckillPrice') {
|
||||||
|
selectProducts.forEach((item) => {
|
||||||
|
item.seckillPrice = value;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (editType === 'seckillStock') {
|
||||||
|
selectProducts.forEach((item) => {
|
||||||
|
item.seckillStock = value;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch();
|
||||||
|
},
|
||||||
|
/** 当 Form 的 SKU 发生变化时 */
|
||||||
|
changeFormSku(skuIds) {
|
||||||
|
// 处理【新增】
|
||||||
|
skuIds.forEach(skuId => {
|
||||||
|
// 获得对应的 SKU 信息
|
||||||
|
const sku = this.productSkus.find(item => item.id === skuId);
|
||||||
|
if (!sku) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 判断已存在,直接跳过
|
||||||
|
const product = this.form.products.find(item => item.skuId === skuId);
|
||||||
|
if (product) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.form.products.push({
|
||||||
|
skuId: sku.id,
|
||||||
|
name: sku.name,
|
||||||
|
price: sku.price,
|
||||||
|
productStock: sku.stock,
|
||||||
|
spuId: sku.spuId,
|
||||||
|
spuName: sku.spuName,
|
||||||
|
limitBuyCount: 1,
|
||||||
|
seckillStock: sku.stock,
|
||||||
|
seckillPrice: sku.price,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 处理【移除】
|
||||||
|
this.form.products.map((product, index) => {
|
||||||
|
if (!skuIds.includes(product.skuId)) {
|
||||||
|
this.form.products.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 移除 Form 的 SKU */
|
||||||
|
removeFormSku(skuId) {
|
||||||
|
this.form.skuIds.map((id, index) => {
|
||||||
|
if (skuId === id) {
|
||||||
|
this.form.skuIds.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.changeFormSku(this.form.skuIds);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,197 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
|
||||||
|
<!-- 操作工具栏 -->
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||||
|
v-hasPermi="['promotion:seckill-time:create']">新增秒杀时段</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<el-table v-loading="loading" :data="list">
|
||||||
|
<el-table-column label="秒杀时段名称" align="center" prop="name" />
|
||||||
|
<el-table-column label="开始时间点" align="center" prop="startTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.startTime }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="结束时间点" align="center" prop="endTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.endTime }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="秒杀活动数量" align="center" prop="seckillActivityCount" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleOpenSeckillActivity(scope.row)">
|
||||||
|
查看秒杀活动</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['promotion:seckill-time:update']">修改</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['promotion:seckill-time:delete']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 对话框(添加 / 修改) -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
|
||||||
|
<el-form-item label="秒杀场次名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入秒杀时段名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="秒杀时间段" prop="startAndEndTime">
|
||||||
|
<el-time-picker is-range v-model="form.startAndEndTime" range-separator="至" start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间" placeholder="选择时间范围" value-format="HH:mm:ss">
|
||||||
|
</el-time-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { createSeckillTime, updateSeckillTime, deleteSeckillTime, getSeckillTime, getSeckillTimePage, exportSeckillTimeExcel, getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
|
||||||
|
import router from "@/router";
|
||||||
|
import { deepClone } from "@/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SeckillTime",
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 导出遮罩层
|
||||||
|
exportLoading: false,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
// total: 0,
|
||||||
|
// 秒杀时段列表
|
||||||
|
list: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
name: [{ required: true, message: "秒杀时段名称不能为空", trigger: "blur" }],
|
||||||
|
startAndEndTime: [{ required: true, message: "秒杀时间段不能为空", trigger: "blur" }],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getSeckillTimeList().then(response => {
|
||||||
|
this.list = response.data;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 取消按钮 */
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
/** 表单重置 */
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
startAndEndTime: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
};
|
||||||
|
this.resetForm("form");
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
/**查看当前秒杀时段的秒杀活动 */
|
||||||
|
handleOpenSeckillActivity(row) {
|
||||||
|
router.push({ name: 'SeckillActivity', params: { timeId: row.id } })
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset();
|
||||||
|
this.open = true;
|
||||||
|
this.title = "添加秒杀时段";
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset();
|
||||||
|
const id = row.id;
|
||||||
|
getSeckillTime(id).then(response => {
|
||||||
|
response.data.startAndEndTime = [response.data.startTime, response.data.endTime]
|
||||||
|
this.form = response.data;
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改秒杀时段";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
console.log(valid, "是否通过");
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 处理数据
|
||||||
|
const data = deepClone(this.form);
|
||||||
|
data.startTime = this.form.startAndEndTime[0];
|
||||||
|
data.endTime = this.form.startAndEndTime[1];
|
||||||
|
// 修改的提交
|
||||||
|
if (this.form.id != null) {
|
||||||
|
updateSeckillTime(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 添加的提交
|
||||||
|
createSeckillTime(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const id = row.id;
|
||||||
|
this.$modal.confirm('是否确认删除秒杀时段编号为"' + id + '"的数据项?').then(function () {
|
||||||
|
return deleteSeckillTime(id);
|
||||||
|
}).then(() => {
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("删除成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
Loading…
Reference in New Issue