From 9344f3750c465fde163cf948ecc205d036cc7e22 Mon Sep 17 00:00:00 2001 From: "1350250847@qq.com" Date: Thu, 23 Apr 2026 15:59:10 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E9=85=8D=E7=BD=AE=202.=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=BC=82=E5=B8=B8=E7=A0=81=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E6=B1=A0=203.=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E4=BA=A7=E4=B8=9A=E5=8A=A1=204.=E5=A2=9E=E5=8A=A0=E7=A7=92?= =?UTF-8?q?=E6=9D=80=E6=B4=BB=E5=8A=A8=E4=B8=9A=E5=8A=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/constants/BaseConstants.java | 3 + .../common/core/enums/UserTypeEnum.java | 43 +++++ .../common/core/exception/ErrorCode.java | 27 +++ .../enums/GlobalErrorCodeConstants.java | 40 +++++ .../common/core/utils/LoginUserUtil.java | 29 ++++ .../ShopFlashSaleActivityController.java | 156 +++++++++++++++++ .../shop/entity/ShopFlashSaleActivity.java | 98 +++++++++++ .../mapper/ShopFlashSaleActivityMapper.java | 38 +++++ .../xml/ShopFlashSaleActivityMapper.xml | 75 ++++++++ .../param/ShopFlashSaleActivityParam.java | 79 +++++++++ .../service/ShopFlashSaleActivityService.java | 65 +++++++ .../ShopFlashSaleActivityServiceImpl.java | 160 ++++++++++++++++++ .../shop/vo/ShopFlashSaleActivityVO.java | 87 ++++++++++ src/main/resources/application-dev.yml | 4 +- .../gxwebsoft/generator/ShopGenerator.java | 9 +- .../generator/templates/controller.java.btl | 4 +- .../generator/templates/entity.java.btl | 2 + .../generator/templates/service.java.btl | 2 +- .../generator/templates/serviceImpl.java.btl | 3 +- 19 files changed, 913 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/gxwebsoft/common/core/enums/UserTypeEnum.java create mode 100644 src/main/java/com/gxwebsoft/common/core/exception/ErrorCode.java create mode 100644 src/main/java/com/gxwebsoft/common/core/exception/enums/GlobalErrorCodeConstants.java create mode 100644 src/main/java/com/gxwebsoft/common/core/utils/LoginUserUtil.java create mode 100644 src/main/java/com/gxwebsoft/shop/controller/ShopFlashSaleActivityController.java create mode 100644 src/main/java/com/gxwebsoft/shop/entity/ShopFlashSaleActivity.java create mode 100644 src/main/java/com/gxwebsoft/shop/mapper/ShopFlashSaleActivityMapper.java create mode 100644 src/main/java/com/gxwebsoft/shop/mapper/xml/ShopFlashSaleActivityMapper.xml create mode 100644 src/main/java/com/gxwebsoft/shop/param/ShopFlashSaleActivityParam.java create mode 100644 src/main/java/com/gxwebsoft/shop/service/ShopFlashSaleActivityService.java create mode 100644 src/main/java/com/gxwebsoft/shop/service/impl/ShopFlashSaleActivityServiceImpl.java create mode 100644 src/main/java/com/gxwebsoft/shop/vo/ShopFlashSaleActivityVO.java diff --git a/src/main/java/com/gxwebsoft/common/core/constants/BaseConstants.java b/src/main/java/com/gxwebsoft/common/core/constants/BaseConstants.java index 66cf4c0..e389908 100644 --- a/src/main/java/com/gxwebsoft/common/core/constants/BaseConstants.java +++ b/src/main/java/com/gxwebsoft/common/core/constants/BaseConstants.java @@ -2,4 +2,7 @@ package com.gxwebsoft.common.core.constants; public class BaseConstants { public static final String[] STATUS = {"未定义","显示","隐藏"}; + + public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; + } diff --git a/src/main/java/com/gxwebsoft/common/core/enums/UserTypeEnum.java b/src/main/java/com/gxwebsoft/common/core/enums/UserTypeEnum.java new file mode 100644 index 0000000..824b7dc --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/enums/UserTypeEnum.java @@ -0,0 +1,43 @@ +package com.gxwebsoft.common.core.enums; + +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 全局用户类型枚举 + */ +@AllArgsConstructor +@Getter +public enum UserTypeEnum { + + // 面向 a 端,管理后台 + RIDER(0, "骑手"), + // 面向 c 端,普通用户 + MEMBER(1, "会员"), + + STORE(3, "门店"), + // 面向 b 端,管理后台 + ADMIN(2, "管理员"), + + CHAT(4, "群聊"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray(); + + /** + * 类型 + */ + private final Integer value; + /** + * 类型名 + */ + private final String name; + + public static UserTypeEnum valueOf(Integer value) { + return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values()); + } + + +} diff --git a/src/main/java/com/gxwebsoft/common/core/exception/ErrorCode.java b/src/main/java/com/gxwebsoft/common/core/exception/ErrorCode.java new file mode 100644 index 0000000..7ce2521 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/exception/ErrorCode.java @@ -0,0 +1,27 @@ +package com.gxwebsoft.common.core.exception; +import lombok.Data; + +/** + * 错误码对象 + * + * 全局错误码,占用 [0, 999], 参见 {@link com.gxwebsoft.common.core.exception.enums.GlobalErrorCodeConstants} + * + */ +@Data +public class ErrorCode { + + /** + * 错误码 + */ + private final Integer code; + /** + * 错误提示 + */ + private final String msg; + + public ErrorCode(Integer code, String message) { + this.code = code; + this.msg = message; + } + +} diff --git a/src/main/java/com/gxwebsoft/common/core/exception/enums/GlobalErrorCodeConstants.java b/src/main/java/com/gxwebsoft/common/core/exception/enums/GlobalErrorCodeConstants.java new file mode 100644 index 0000000..6f7e49f --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/exception/enums/GlobalErrorCodeConstants.java @@ -0,0 +1,40 @@ +package com.gxwebsoft.common.core.exception.enums; + +import com.gxwebsoft.common.core.exception.ErrorCode; + +/** + * 全局错误码枚举 + * 0-999 系统异常编码保留 + * + * 一般情况下,使用 HTTP 响应状态码 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status + * 虽然说,HTTP 响应状态码作为业务使用表达能力偏弱,但是使用在系统层面还是非常不错的 + * 比较特殊的是,因为之前一直使用 0 作为成功,就不使用 200 啦。 + * + * @author xm + */ +public interface GlobalErrorCodeConstants { + + ErrorCode SUCCESS = new ErrorCode(0, "成功"); + + // ========== 客户端错误段 ========== + + ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确"); + ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录"); + ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限"); + ErrorCode NOT_FOUND = new ErrorCode(404, "查询无此数据"); + ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确"); + ErrorCode LOCKED = new ErrorCode(423, "请求失败,请稍后重试"); // 并发请求,不允许 + ErrorCode TOO_MANY_REQUESTS = new ErrorCode(429, "请求过于频繁,请稍后重试"); + + // ========== 服务端错误段 ========== + + ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常"); + ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启"); + + // ========== 自定义错误段 ========== + ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求 + ErrorCode DEMO_DENY = new ErrorCode(901, "演示模式,禁止写操作"); + + ErrorCode UNKNOWN = new ErrorCode(999, "未知错误"); + ErrorCode FINANCE_BILL_NOT_EXISTS = new ErrorCode(600, "门店财务账单不存在"); +} diff --git a/src/main/java/com/gxwebsoft/common/core/utils/LoginUserUtil.java b/src/main/java/com/gxwebsoft/common/core/utils/LoginUserUtil.java new file mode 100644 index 0000000..1f5fe8d --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/utils/LoginUserUtil.java @@ -0,0 +1,29 @@ +package com.gxwebsoft.common.core.utils; + +import com.gxwebsoft.common.system.entity.User; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +public class LoginUserUtil { + + /** + * 获取当前登录的user + * + * @return User + */ + public static User getLoginUser() { + try { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + Object object = authentication.getPrincipal(); + if (object instanceof User) { + return (User) object; + } + } + } catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + return null; + } +} diff --git a/src/main/java/com/gxwebsoft/shop/controller/ShopFlashSaleActivityController.java b/src/main/java/com/gxwebsoft/shop/controller/ShopFlashSaleActivityController.java new file mode 100644 index 0000000..47fdde5 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/controller/ShopFlashSaleActivityController.java @@ -0,0 +1,156 @@ +package com.gxwebsoft.shop.controller; + +import com.gxwebsoft.common.core.annotation.OperationLog; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.core.web.BatchParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.shop.entity.ShopFlashSaleActivity; +import com.gxwebsoft.shop.param.ShopFlashSaleActivityParam; +import com.gxwebsoft.shop.service.ShopFlashSaleActivityService; +import com.gxwebsoft.shop.vo.ShopFlashSaleActivityVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 秒杀活动控制器 + * + * @author xm + * @since 2026-04-22 17:18:18 + */ +@Tag(name = "秒杀活动管理") +@RestController +@RequestMapping("/api/shop/shop-flash-sale-activity") +public class ShopFlashSaleActivityController extends BaseController { + @Resource + private ShopFlashSaleActivityService shopFlashSaleActivityService; + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:list')") + @Operation(summary = "后台分页查询秒杀活动") + @GetMapping("/page") + public ApiResult> page(ShopFlashSaleActivityParam param) { + // 使用关联查询 + return success(shopFlashSaleActivityService.pageRel(param)); + } + + @Operation(summary = "个人获取秒杀活动数据") + @GetMapping("/getMyActive") + public ApiResult> getMyActive(@RequestParam("tenantId") Integer tenantId) { + // 使用关联查询 + return success(shopFlashSaleActivityService.getMyActive(tenantId)); + } + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:list')") + @Operation(summary = "查询全部秒杀活动") + @GetMapping() + public ApiResult> list(ShopFlashSaleActivityParam param) { + // 使用关联查询 + return success(shopFlashSaleActivityService.listRel(param)); + } + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:list')") + @Operation(summary = "根据id查询秒杀活动") + @GetMapping("/{id}") + public ApiResult get(@PathVariable("id") Long id) { + // 使用关联查询 + return success(shopFlashSaleActivityService.getByIdRel(id)); + } + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:save')") + @OperationLog + @Operation(summary = "添加秒杀活动") + @PostMapping() + public ApiResult save(@RequestBody ShopFlashSaleActivity shopFlashSaleActivity) { + // 记录当前登录用户id + User loginUser = getLoginUser(); + if (loginUser != null) { + shopFlashSaleActivity.setCreator(loginUser.getUserId().toString()); + } + if (shopFlashSaleActivityService.save(shopFlashSaleActivity)) { + return success("添加成功"); + } + return fail("添加失败"); + } + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:update')") + @OperationLog + @Operation(summary = "修改秒杀活动") + @PutMapping() + public ApiResult update(@RequestBody ShopFlashSaleActivity shopFlashSaleActivity) { + shopFlashSaleActivity.setUpdater(String.valueOf(getLoginUserId())); + if (shopFlashSaleActivityService.updateById(shopFlashSaleActivity)) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @OperationLog + @Operation(summary = "开启/关闭秒杀活动状态") + @PutMapping("/updateStatus") + public ApiResult updateStatus(@RequestParam("id") Long id) { + return success(shopFlashSaleActivityService.updateStatus(id)); + } + + @Operation(summary = "修改秒杀活动排序") + @PutMapping("/updateSortNumber") + @Parameters({ + @Parameter(name = "id", description = "活动ID", required = true, example = "1"), + @Parameter(name = "sortNumber", description = "排序", required = true, example = "2") + }) + public ApiResult updateSortNumber(@RequestParam("id") Long id, @RequestParam("sortNumber") Integer sortNumber) { + return success(shopFlashSaleActivityService.updateSortNumber(id, sortNumber)); + } + +// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:remove')") + @OperationLog + @Operation(summary = "删除秒杀活动") + @DeleteMapping("/{id}") + public ApiResult remove(@PathVariable("id") Integer id) { + if (shopFlashSaleActivityService.removeById(id)) { + return success("删除成功"); + } + return fail("删除失败"); + } + + @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:save')") + @OperationLog + @Operation(summary = "批量添加秒杀活动") + @PostMapping("/batch") + public ApiResult saveBatch(@RequestBody List list) { + if (shopFlashSaleActivityService.saveBatch(list)) { + return success("添加成功"); + } + return fail("添加失败"); + } + + @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:update')") + @OperationLog + @Operation(summary = "批量修改秒杀活动") + @PutMapping("/batch") + public ApiResult removeBatch(@RequestBody BatchParam batchParam) { + if (batchParam.update(shopFlashSaleActivityService, "id")) { + return success("修改成功"); + } + return fail("修改失败"); + } + + @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:remove')") + @OperationLog + @Operation(summary = "批量删除秒杀活动") + @DeleteMapping("/batch") + public ApiResult removeBatch(@RequestBody List ids) { + if (shopFlashSaleActivityService.removeByIds(ids)) { + return success("删除成功"); + } + return fail("删除失败"); + } + +} diff --git a/src/main/java/com/gxwebsoft/shop/entity/ShopFlashSaleActivity.java b/src/main/java/com/gxwebsoft/shop/entity/ShopFlashSaleActivity.java new file mode 100644 index 0000000..5e05533 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/entity/ShopFlashSaleActivity.java @@ -0,0 +1,98 @@ +package com.gxwebsoft.shop.entity; + +import com.baomidou.mybatisplus.annotation.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.gxwebsoft.common.core.constants.BaseConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 秒杀活动 + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(name = "ShopFlashSaleActivity对象", description = "秒杀活动") +@TableName("shop_flash_sale_activity") +public class ShopFlashSaleActivity implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "秒杀活动编号") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @Schema(description = "秒杀活动名称") + private String name; + + @Schema(description = "秒杀活动商品") + private Integer goodsId; + + @Schema(description = "商品skuId") + private Integer skuId; + + @Schema(description = "商品数量") + private Integer num; + + @Schema(description = "秒杀活动商品价格") + private BigDecimal price; + + @Schema(description = "活动状态 0-开启 1-关闭") + private Integer status; + + @Schema( + description = "活动开始时间", + type = "string", + pattern = BaseConstants.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, + example = "2026-04-01 12:00:00" + ) + private LocalDateTime startTime; + + @Schema( + description = "活动结束时间", + type = "string", + pattern = BaseConstants.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, + example = "2027-01-01 12:00:00" + ) + private LocalDateTime endTime; + + @Schema(description = "库存") + private Integer stock; + + @Schema(description = "展示类型,0:普通用户,1:新用户") + private Integer displayType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private Integer sortNumber; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "创建时间", pattern = BaseConstants.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime createTime; + + @Schema(description = "更新者") + private String updater; + + @Schema(description = "更新时间") + @DateTimeFormat(pattern = BaseConstants.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime updateTime; + + @Schema(description = "是否删除") + @TableLogic + private Integer deleted; + +} diff --git a/src/main/java/com/gxwebsoft/shop/mapper/ShopFlashSaleActivityMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/ShopFlashSaleActivityMapper.java new file mode 100644 index 0000000..d58b0b6 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/mapper/ShopFlashSaleActivityMapper.java @@ -0,0 +1,38 @@ +package com.gxwebsoft.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gxwebsoft.shop.entity.ShopFlashSaleActivity; +import com.gxwebsoft.shop.param.ShopFlashSaleActivityParam; +import com.gxwebsoft.shop.vo.ShopFlashSaleActivityVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 秒杀活动Mapper + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +public interface ShopFlashSaleActivityMapper extends BaseMapper { + + /** + * 分页查询 + * + * @param page 分页对象 + * @param param 查询参数 + * @return List + */ + List selectPageRel(@Param("page") IPage page, + @Param("param") ShopFlashSaleActivityParam param); + + /** + * 查询全部 + * + * @param param 查询参数 + * @return List + */ + List selectListRel(@Param("param") ShopFlashSaleActivityParam param); + +} diff --git a/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopFlashSaleActivityMapper.xml b/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopFlashSaleActivityMapper.xml new file mode 100644 index 0000000..60a78a9 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopFlashSaleActivityMapper.xml @@ -0,0 +1,75 @@ + + + + + + + SELECT a.* + FROM shop_flash_sale_activity a + + + AND a.id = #{param.id} + + + AND a.name LIKE CONCAT('%', #{param.name}, '%') + + + AND a.goods_id LIKE CONCAT('%', #{param.goodsId}, '%') + + + AND a.status = #{param.status} + + + AND a.start_time LIKE CONCAT('%', #{param.startTime}, '%') + + + AND a.end_time LIKE CONCAT('%', #{param.endTime}, '%') + + + AND a.stock = #{param.stock} + + + AND a.display_type = #{param.displayType} + + + AND a.remark LIKE CONCAT('%', #{param.remark}, '%') + + + AND a.sort_number = #{param.sortNumber} + + + AND a.creator LIKE CONCAT('%', #{param.creator}, '%') + + + AND a.create_time >= #{param.createTimeStart} + + + AND a.create_time <= #{param.createTimeEnd} + + + AND a.updater LIKE CONCAT('%', #{param.updater}, '%') + + + AND a.deleted = #{param.deleted} + + + AND a.deleted = 0 + + + AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') + ) + + + + + + + + + + + diff --git a/src/main/java/com/gxwebsoft/shop/param/ShopFlashSaleActivityParam.java b/src/main/java/com/gxwebsoft/shop/param/ShopFlashSaleActivityParam.java new file mode 100644 index 0000000..bd96c32 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/param/ShopFlashSaleActivityParam.java @@ -0,0 +1,79 @@ +package com.gxwebsoft.shop.param; + +import java.math.BigDecimal; +import com.gxwebsoft.common.core.annotation.QueryField; +import com.gxwebsoft.common.core.annotation.QueryType; +import com.gxwebsoft.common.core.web.BaseParam; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 秒杀活动查询参数 + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@JsonInclude(JsonInclude.Include.NON_NULL) +@Schema(name = "ShopFlashSaleActivityParam对象", description = "秒杀活动查询参数") +public class ShopFlashSaleActivityParam extends BaseParam { + private static final long serialVersionUID = 1L; + + @Schema(description = "秒杀活动编号") + @QueryField(type = QueryType.EQ) + private Long id; + + @Schema(description = "秒杀活动名称") + private String name; + + @Schema(description = "秒杀活动商品") + private Integer goodsId; + + @Schema(description = "商品skuId") + private Integer skuId; + + @Schema(description = "商品数量") + private Integer num; + + @Schema(description = "秒杀活动商品价格") + private BigDecimal price; + + @Schema(description = "活动状态 0-开启 1-关闭") + @QueryField(type = QueryType.EQ) + private Integer status; + + @Schema(description = "活动开始时间") + private String startTime; + + @Schema(description = "活动结束时间") + private String endTime; + + @Schema(description = "库存") + @QueryField(type = QueryType.EQ) + private Integer stock; + + @Schema(description = "展示类型,0:普通用户,1:新用户") + @QueryField(type = QueryType.EQ) + private Integer displayType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + @QueryField(type = QueryType.EQ) + private Integer sortNumber; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "更新者") + private String updater; + + @Schema(description = "是否删除") + @QueryField(type = QueryType.EQ) + private Integer deleted; + +} diff --git a/src/main/java/com/gxwebsoft/shop/service/ShopFlashSaleActivityService.java b/src/main/java/com/gxwebsoft/shop/service/ShopFlashSaleActivityService.java new file mode 100644 index 0000000..b3e17af --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/service/ShopFlashSaleActivityService.java @@ -0,0 +1,65 @@ +package com.gxwebsoft.shop.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.shop.entity.ShopFlashSaleActivity; +import com.gxwebsoft.shop.param.ShopFlashSaleActivityParam; +import com.gxwebsoft.shop.vo.ShopFlashSaleActivityVO; + +import java.util.List; + +/** + * 秒杀活动Service + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +public interface ShopFlashSaleActivityService extends IService { + + /** + * 分页关联查询 + * + * @param param 查询参数 + * @return PageResult + */ + PageResult pageRel(ShopFlashSaleActivityParam param); + + /** + * 关联查询全部 + * + * @param param 查询参数 + * @return List + */ + List listRel(ShopFlashSaleActivityParam param); + + /** + * 根据id查询 + * + * @param id 秒杀活动编号 + * @return ShopFlashSaleActivity + */ + ShopFlashSaleActivity getByIdRel(Long id); + + /** + * 查询个人可参与的活动数据 + * @param tenantId 租户ID + * @return + */ + List getMyActive(Integer tenantId); + + /** + * 修改秒杀活动状态 + * @param id + * @return + */ + Boolean updateStatus(Long id); + + /** + * 修改秒杀活动排序 + * @param id + * @param sortNumber + * @return + */ + Boolean updateSortNumber(Long id, Integer sortNumber); + +} diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/ShopFlashSaleActivityServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/ShopFlashSaleActivityServiceImpl.java new file mode 100644 index 0000000..ac09f3a --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/service/impl/ShopFlashSaleActivityServiceImpl.java @@ -0,0 +1,160 @@ +package com.gxwebsoft.shop.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gxwebsoft.common.core.exception.BusinessException; +import com.gxwebsoft.common.core.exception.enums.GlobalErrorCodeConstants; +import com.gxwebsoft.common.core.utils.LoginUserUtil; +import com.gxwebsoft.common.core.web.PageParam; +import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.shop.entity.ShopFlashSaleActivity; +import com.gxwebsoft.shop.entity.ShopGoods; +import com.gxwebsoft.shop.entity.ShopOrder; +import com.gxwebsoft.shop.mapper.ShopFlashSaleActivityMapper; +import com.gxwebsoft.shop.mapper.ShopGoodsMapper; +import com.gxwebsoft.shop.mapper.ShopOrderMapper; +import com.gxwebsoft.shop.param.ShopFlashSaleActivityParam; +import com.gxwebsoft.shop.service.ShopFlashSaleActivityService; +import com.gxwebsoft.shop.vo.ShopFlashSaleActivityVO; +import lombok.AllArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 秒杀活动Service实现 + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +@Service +@AllArgsConstructor +public class ShopFlashSaleActivityServiceImpl extends ServiceImpl implements ShopFlashSaleActivityService { + + private ShopGoodsMapper shopGoodsMapper; + + private ShopOrderMapper shopOrderMapper; + + @Override + public PageResult pageRel(ShopFlashSaleActivityParam param) { + PageParam page = new PageParam<>(param); + page.setDefaultOrder("sort_number asc, create_time desc"); + List list = baseMapper.selectPageRel(page, param); + if(CollectionUtils.isNotEmpty(list)){ + List goodsIdList = list.stream().map(ShopFlashSaleActivityVO::getGoodsId).distinct().collect(Collectors.toList()); + List shopGoods = shopGoodsMapper.selectBatchIds(goodsIdList); + list.forEach(shopFlashSaleActivityVO -> { + ShopGoods shopGood = shopGoods.stream().filter(goods -> shopFlashSaleActivityVO.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null); + if(shopGood != null){ + shopFlashSaleActivityVO.setGoodsPrice(shopGood.getPrice()); + shopFlashSaleActivityVO.setGoodsTotalPrice(shopGood.getPrice().multiply(new BigDecimal(shopFlashSaleActivityVO.getNum()))); + shopFlashSaleActivityVO.setGoodsName(shopGood.getName()); + } + }); + } + return new PageResult<>(list, page.getTotal()); + } + + @Override + public List listRel(ShopFlashSaleActivityParam param) { + List list = baseMapper.selectListRel(param); + // 排序 + PageParam page = new PageParam<>(); + page.setDefaultOrder("sort_number asc, create_time desc"); + return page.sortRecords(list); + } + + @Override + public ShopFlashSaleActivity getByIdRel(Long id) { + ShopFlashSaleActivityParam param = new ShopFlashSaleActivityParam(); + param.setId(id); + return param.getOne(baseMapper.selectListRel(param)); + } + + @Override + public List getMyActive(Integer tenantId) { + List resultVOList = new ArrayList<>(); + User loginUser = LoginUserUtil.getLoginUser(); + if(loginUser == null){ + throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg()); + } + + + Boolean newUser = true; + //判断是否为新用户【只要未成功下单都判定为新用户】 + LambdaQueryWrapper shopOrderLambdaQueryWrapper = new LambdaQueryWrapper().eq(ShopOrder::getUserId, loginUser.getUserId()).eq(ShopOrder::getPayStatus, 1) + .in(ShopOrder::getOrderStatus, Arrays.asList(0, 1)); + List shopOrderList = shopOrderMapper.selectList(shopOrderLambdaQueryWrapper); + if(CollectionUtils.isNotEmpty(shopOrderList)){ + newUser = false; + } + + //查询满足条件的活动数据 + LambdaQueryChainWrapper activityWrapper = lambdaQuery().eq(ShopFlashSaleActivity::getStatus, 0).gt(ShopFlashSaleActivity::getStock, 0).eq(ShopFlashSaleActivity::getTenantId, tenantId) + .apply("NOW() BETWEEN start_time AND end_time"); + if(!newUser){ + activityWrapper.eq(ShopFlashSaleActivity::getDisplayType, 0); + } + activityWrapper.orderByAsc(ShopFlashSaleActivity::getSortNumber); + List activityList = activityWrapper.list(); + + if(CollectionUtils.isNotEmpty(activityList)){ + resultVOList = BeanUtil.copyToList(activityList, ShopFlashSaleActivityVO.class); + List goodsIdList = resultVOList.stream().map(ShopFlashSaleActivityVO::getGoodsId).distinct().collect(Collectors.toList()); + List shopGoods = shopGoodsMapper.selectBatchIds(goodsIdList); + resultVOList.forEach(activity -> { + ShopGoods shopGood = shopGoods.stream().filter(goods -> activity.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null); + if(shopGood != null){ + activity.setGoodsPrice(shopGood.getPrice()); + activity.setGoodsTotalPrice(shopGood.getPrice().multiply(new BigDecimal(activity.getNum()))); + activity.setGoodsName(shopGood.getName()); + } + }); + } + return resultVOList; + } + + @Override + public Boolean updateStatus(Long id) { + ShopFlashSaleActivity saleActivity = baseMapper.selectById(id); + if(saleActivity != null){ + if (saleActivity.getStatus() == 0){ + saleActivity.setStatus(1); + }else { + saleActivity.setStatus(0); + } + User loginUser = LoginUserUtil.getLoginUser(); + if(loginUser != null){ + saleActivity.setUpdater(loginUser.getUserId().toString()); + } + saleActivity.setUpdateTime(LocalDateTime.now()); + baseMapper.updateById(saleActivity); + return Boolean.TRUE; + }else { + throw new BusinessException(GlobalErrorCodeConstants.NOT_FOUND.getMsg()); + } + } + + @Override + public Boolean updateSortNumber(Long id, Integer sortNumber) { + ShopFlashSaleActivity saleActivity = baseMapper.selectById(id); + if(saleActivity != null){ + saleActivity.setSortNumber(sortNumber); + saleActivity.setUpdateTime(LocalDateTime.now()); + baseMapper.updateById(saleActivity); + return Boolean.TRUE; + }else { + throw new BusinessException(GlobalErrorCodeConstants.NOT_FOUND.getMsg()); + } + } + +} diff --git a/src/main/java/com/gxwebsoft/shop/vo/ShopFlashSaleActivityVO.java b/src/main/java/com/gxwebsoft/shop/vo/ShopFlashSaleActivityVO.java new file mode 100644 index 0000000..07b5f10 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/vo/ShopFlashSaleActivityVO.java @@ -0,0 +1,87 @@ +package com.gxwebsoft.shop.vo; + +import com.baomidou.mybatisplus.annotation.TableLogic; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 秒杀活动 + * + * @author xm + * @since 2026-04-22 17:18:17 + */ +@Data +public class ShopFlashSaleActivityVO implements Serializable { + + @Schema(description = "秒杀活动编号") + private Long id; + + @Schema(description = "秒杀活动名称") + private String name; + + @Schema(description = "秒杀活动商品") + private Integer goodsId; + + @Schema(description = "秒杀活动商品名称") + private String goodsName; + + @Schema(description = "商品skuId") + private Integer skuId; + + @Schema(description = "商品数量") + private Integer num; + + @Schema(description = "秒杀价") + private BigDecimal price; + + @Schema(description = "商品单价") + private BigDecimal goodsPrice; + + @Schema(description = "商品总价") + private BigDecimal goodsTotalPrice; + + @Schema(description = "活动状态 0-开启 1-关闭") + private Integer status; + + @Schema(description = "活动开始时间") + private LocalDateTime startTime; + + @Schema(description = "活动结束时间") + private LocalDateTime endTime; + + @Schema(description = "库存") + private Integer stock; + + @Schema(description = "展示类型,0:普通用户,1:新用户") + private Integer displayType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private Integer sortNumber; + + @Schema(description = "租户id") + private Integer tenantId; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新者") + private String updater; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "是否删除") + @TableLogic + private Integer deleted; + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 8a221d2..34972e5 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -7,9 +7,9 @@ server: # 数据源配置 spring: datasource: - url: jdbc:mysql://8.134.55.105:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 + url: jdbc:mysql://47.107.249.41:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 username: modules - password: tYmmMGh5wpwXR3ae + password: tYmmMGh5wpwXR3ae2 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource diff --git a/src/test/java/com/gxwebsoft/generator/ShopGenerator.java b/src/test/java/com/gxwebsoft/generator/ShopGenerator.java index 9d1224c..5fdf7cf 100644 --- a/src/test/java/com/gxwebsoft/generator/ShopGenerator.java +++ b/src/test/java/com/gxwebsoft/generator/ShopGenerator.java @@ -38,14 +38,14 @@ public class ShopGenerator { // Vue文件输出目录 private static final String OUTPUT_DIR_VUE = "/src"; // 作者名称 - private static final String AUTHOR = "科技小王子"; + private static final String AUTHOR = "xm"; // 是否在xml中添加二级缓存配置 private static final boolean ENABLE_CACHE = false; // 数据库连接配置 - private static final String DB_URL = "jdbc:mysql://8.134.169.209:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"; + private static final String DB_URL = "jdbc:mysql://47.107.249.41:13306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8"; private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String DB_USERNAME = "modules"; - private static final String DB_PASSWORD = "8YdLnk7KsPAyDXGA"; + private static final String DB_PASSWORD = "tYmmMGh5wpwXR3ae2"; // 包名 private static final String PACKAGE_NAME = "com.gxwebsoft"; // 模块名 @@ -105,7 +105,8 @@ public class ShopGenerator { // "shop_express_template", // "shop_express_template_detail", // "shop_gift" - "shop_article" +// "shop_flash_sale_activity" +// "shop_flash_sale_product" }; // 需要去除的表前缀 private static final String[] TABLE_PREFIX = new String[]{ diff --git a/src/test/java/com/gxwebsoft/generator/templates/controller.java.btl b/src/test/java/com/gxwebsoft/generator/templates/controller.java.btl index e278dc1..24e6cdf 100644 --- a/src/test/java/com/gxwebsoft/generator/templates/controller.java.btl +++ b/src/test/java/com/gxwebsoft/generator/templates/controller.java.btl @@ -19,10 +19,8 @@ import ${cfg.packageName!}.${package.ModuleName}.entity.${entity}; import ${cfg.packageName!}.${package.ModuleName}.param.${entity}Param; import ${cfg.packageName!}.common.core.web.ApiResult; import ${cfg.packageName!}.common.core.web.PageResult; -import ${cfg.packageName!}.common.core.web.PageParam; import ${cfg.packageName!}.common.core.web.BatchParam; import ${cfg.packageName!}.common.core.annotation.OperationLog; -import ${cfg.packageName!}.common.system.entity.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; @@ -107,7 +105,7 @@ public class ${table.controllerName} { @PreAuthorize("hasAuthority('${authPre}:list')") @Operation(summary = "根据id查询${table.comment!}") @GetMapping("/{id}") - public ApiResult<${entity}> get(@PathVariable("id") Integer id) { + public ApiResult<${entity}> get(@PathVariable("id") Long id) { // 使用关联查询 return success(${serviceIns}.getByIdRel(id)); } diff --git a/src/test/java/com/gxwebsoft/generator/templates/entity.java.btl b/src/test/java/com/gxwebsoft/generator/templates/entity.java.btl index e98a1d3..88f6b79 100644 --- a/src/test/java/com/gxwebsoft/generator/templates/entity.java.btl +++ b/src/test/java/com/gxwebsoft/generator/templates/entity.java.btl @@ -3,6 +3,7 @@ package ${package.Entity}; <% for(pkg in table.importPackages) { %> import ${pkg}; <% } %> +import com.baomidou.mybatisplus.annotation.TableName; <% if(swagger2) { %> import io.swagger.v3.oas.annotations.media.Schema; <% } %> @@ -34,6 +35,7 @@ import lombok.experimental.Accessors; <% if(swagger2) { %> @Schema(name = "${entity}对象", description = "${table.comment!''}") <% } %> +@TableName("${table.name}") <% if(table.convert) { %> @TableName("${table.name}") <% } %> diff --git a/src/test/java/com/gxwebsoft/generator/templates/service.java.btl b/src/test/java/com/gxwebsoft/generator/templates/service.java.btl index 67efe6a..3a6c3ae 100644 --- a/src/test/java/com/gxwebsoft/generator/templates/service.java.btl +++ b/src/test/java/com/gxwebsoft/generator/templates/service.java.btl @@ -49,7 +49,7 @@ public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { * @param ${idPropertyName!} ${idComment!} * @return ${entity} */ - ${entity} getByIdRel(Integer ${idPropertyName!}); + ${entity} getByIdRel(Long ${idPropertyName!}); } <% } %> diff --git a/src/test/java/com/gxwebsoft/generator/templates/serviceImpl.java.btl b/src/test/java/com/gxwebsoft/generator/templates/serviceImpl.java.btl index 20b998d..072e052 100644 --- a/src/test/java/com/gxwebsoft/generator/templates/serviceImpl.java.btl +++ b/src/test/java/com/gxwebsoft/generator/templates/serviceImpl.java.btl @@ -27,6 +27,7 @@ import java.util.List; * @since ${date(), 'yyyy-MM-dd HH:mm:ss'} */ @Service +@AllArgsConstructor <% if(kotlin){ %> open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { @@ -52,7 +53,7 @@ public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.m } @Override - public ${entity} getByIdRel(Integer ${idPropertyName!}) { + public ${entity} getByIdRel(Long ${idPropertyName!}) { ${entity}Param param = new ${entity}Param(); param.set${idCapitalName!}(${idPropertyName!}); return param.getOne(baseMapper.selectListRel(param));