Commit f363c598d8100ff2db1114551e3af18902451e4a
1 parent
1bb2010d
Banner:完善 review 提到的问题
Showing
10 changed files
with
149 additions
and
31 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/banner/BannerPositionEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.enums.banner; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||
| 4 | +import cn.iocoder.yudao.module.promotion.enums.bargain.BargainRecordStatusEnum; | ||
| 5 | +import lombok.AllArgsConstructor; | ||
| 6 | +import lombok.Getter; | ||
| 7 | + | ||
| 8 | +import java.util.Arrays; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Banner Position 枚举 | ||
| 12 | + * | ||
| 13 | + * @author HUIHUI | ||
| 14 | + */ | ||
| 15 | +@AllArgsConstructor | ||
| 16 | +@Getter | ||
| 17 | +public enum BannerPositionEnum implements IntArrayValuable { | ||
| 18 | + | ||
| 19 | + HOME_POSITION(1, "首页"), | ||
| 20 | + SECKILL_POSITION(2, "秒杀活动页"), | ||
| 21 | + COMBINATION_POSITION(3, "砍价活动页"), | ||
| 22 | + DISCOUNT_POSITION(4, "限时折扣页"), | ||
| 23 | + REWARD_POSITION(5, "满减送页"); | ||
| 24 | + | ||
| 25 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BargainRecordStatusEnum::getStatus).toArray(); | ||
| 26 | + /** | ||
| 27 | + * 值 | ||
| 28 | + */ | ||
| 29 | + private final Integer position; | ||
| 30 | + /** | ||
| 31 | + * 名字 | ||
| 32 | + */ | ||
| 33 | + private final String name; | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public int[] array() { | ||
| 37 | + return ARRAYS; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/banner/vo/BannerBaseVO.java
| @@ -27,6 +27,10 @@ public class BannerBaseVO { | @@ -27,6 +27,10 @@ public class BannerBaseVO { | ||
| 27 | @NotNull(message = "图片地址不能为空") | 27 | @NotNull(message = "图片地址不能为空") |
| 28 | private String picUrl; | 28 | private String picUrl; |
| 29 | 29 | ||
| 30 | + @Schema(description = "position", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 31 | + @NotNull(message = "position 不能为空") | ||
| 32 | + private Integer position; | ||
| 33 | + | ||
| 30 | @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED) | 34 | @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED) |
| 31 | @NotNull(message = "排序不能为空") | 35 | @NotNull(message = "排序不能为空") |
| 32 | private Integer sort; | 36 | private Integer sort; |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/banner/vo/BannerPageReqVO.java
| @@ -25,7 +25,6 @@ public class BannerPageReqVO extends PageParam { | @@ -25,7 +25,6 @@ public class BannerPageReqVO extends PageParam { | ||
| 25 | @Schema(description = "标题") | 25 | @Schema(description = "标题") |
| 26 | private String title; | 26 | private String title; |
| 27 | 27 | ||
| 28 | - | ||
| 29 | @Schema(description = "状态") | 28 | @Schema(description = "状态") |
| 30 | @InEnum(CommonStatusEnum.class) | 29 | @InEnum(CommonStatusEnum.class) |
| 31 | private Integer status; | 30 | private Integer status; |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/banner/AppBannerController.java
| @@ -2,18 +2,23 @@ package cn.iocoder.yudao.module.promotion.controller.app.banner; | @@ -2,18 +2,23 @@ package cn.iocoder.yudao.module.promotion.controller.app.banner; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.module.promotion.controller.app.banner.vo.AppBannerRespVO; | 4 | import cn.iocoder.yudao.module.promotion.controller.app.banner.vo.AppBannerRespVO; |
| 5 | +import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert; | ||
| 6 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO; | ||
| 7 | +import cn.iocoder.yudao.module.promotion.service.banner.BannerService; | ||
| 8 | +import com.google.common.cache.CacheLoader; | ||
| 9 | +import com.google.common.cache.LoadingCache; | ||
| 5 | import io.swagger.v3.oas.annotations.Operation; | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 11 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 6 | import io.swagger.v3.oas.annotations.tags.Tag; | 12 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 7 | import org.springframework.validation.annotation.Validated; | 13 | import org.springframework.validation.annotation.Validated; |
| 8 | -import org.springframework.web.bind.annotation.GetMapping; | ||
| 9 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
| 10 | -import org.springframework.web.bind.annotation.RequestParam; | ||
| 11 | -import org.springframework.web.bind.annotation.RestController; | 14 | +import org.springframework.web.bind.annotation.*; |
| 12 | 15 | ||
| 13 | -import java.util.ArrayList; | 16 | +import javax.annotation.Resource; |
| 17 | +import java.time.Duration; | ||
| 14 | import java.util.List; | 18 | import java.util.List; |
| 15 | 19 | ||
| 16 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 20 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 21 | +import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | ||
| 17 | 22 | ||
| 18 | @RestController | 23 | @RestController |
| 19 | @RequestMapping("/promotion/banner") | 24 | @RequestMapping("/promotion/banner") |
| @@ -21,22 +26,39 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | @@ -21,22 +26,39 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 21 | @Validated | 26 | @Validated |
| 22 | public class AppBannerController { | 27 | public class AppBannerController { |
| 23 | 28 | ||
| 29 | + @Resource | ||
| 30 | + private BannerService bannerService; | ||
| 31 | + /** | ||
| 32 | + * {@link AppBannerRespVO} 缓存,通过它异步刷新 {@link #getBannerList0(Integer)} 所要的首页数据 | ||
| 33 | + */ | ||
| 34 | + private final LoadingCache<Integer, List<AppBannerRespVO>> bannerListCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), | ||
| 35 | + new CacheLoader<Integer, List<AppBannerRespVO>>() { | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public List<AppBannerRespVO> load(Integer position) { | ||
| 39 | + return getBannerList0(position); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + }); | ||
| 43 | + | ||
| 24 | @GetMapping("/list") | 44 | @GetMapping("/list") |
| 25 | @Operation(summary = "获得 banner 列表") | 45 | @Operation(summary = "获得 banner 列表") |
| 26 | - // todo @芋艿:swagger 注解,待补全 | ||
| 27 | - // TODO @芋艿:可以增加缓存,提升性能 | ||
| 28 | - // TODO @芋艿:position = 1 时,首页;position = 10 时,拼团活动页 | 46 | + @Parameter(name = "position", description = "Banner position", example = "1") |
| 29 | public CommonResult<List<AppBannerRespVO>> getBannerList(@RequestParam("position") Integer position) { | 47 | public CommonResult<List<AppBannerRespVO>> getBannerList(@RequestParam("position") Integer position) { |
| 30 | - List<AppBannerRespVO> bannerList = new ArrayList<>(); | ||
| 31 | - AppBannerRespVO banner1 = new AppBannerRespVO(); | ||
| 32 | - banner1.setUrl("https://www.example.com/link1"); | ||
| 33 | - banner1.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2022/08/04/0f78716213f64bfa83f191d51a832cbf73f6axavoy.jpg"); | ||
| 34 | - bannerList.add(banner1); | ||
| 35 | - AppBannerRespVO banner2 = new AppBannerRespVO(); | ||
| 36 | - banner2.setUrl("https://www.example.com/link2"); | ||
| 37 | - banner2.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2023/01/11/be09e755268b43ee90b0db3a3e1b7132r7a6t2wvsm.jpg"); | ||
| 38 | - bannerList.add(banner2); | ||
| 39 | - return success(bannerList); | 48 | + return success(bannerListCache.getUnchecked(position)); |
| 49 | + } | ||
| 50 | + | ||
| 51 | + private List<AppBannerRespVO> getBannerList0(Integer position) { | ||
| 52 | + List<BannerDO> bannerList = bannerService.getBannerListByPosition(position); | ||
| 53 | + return BannerConvert.INSTANCE.convertList01(bannerList); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @PutMapping("/add-browse-count") | ||
| 57 | + @Operation(summary = "增加 Banner 点击量") | ||
| 58 | + @Parameter(name = "id", description = "Banner 编号", example = "1024") | ||
| 59 | + public CommonResult<Boolean> addBrowseCount(@RequestParam("id") Long id) { | ||
| 60 | + bannerService.addBannerBrowseCount(id); | ||
| 61 | + return success(true); | ||
| 40 | } | 62 | } |
| 41 | 63 | ||
| 42 | } | 64 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/banner/vo/AppBannerRespVO.java
| @@ -9,6 +9,13 @@ import javax.validation.constraints.NotNull; | @@ -9,6 +9,13 @@ import javax.validation.constraints.NotNull; | ||
| 9 | @Data | 9 | @Data |
| 10 | public class AppBannerRespVO { | 10 | public class AppBannerRespVO { |
| 11 | 11 | ||
| 12 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 16 | + @NotNull(message = "标题不能为空") | ||
| 17 | + private String title; | ||
| 18 | + | ||
| 12 | @Schema(description = "跳转链接", requiredMode = Schema.RequiredMode.REQUIRED) | 19 | @Schema(description = "跳转链接", requiredMode = Schema.RequiredMode.REQUIRED) |
| 13 | @NotNull(message = "跳转链接不能为空") | 20 | @NotNull(message = "跳转链接不能为空") |
| 14 | private String url; | 21 | private String url; |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/banner/BannerConvert.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO; | 4 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerUpdateReqVO; |
| 7 | +import cn.iocoder.yudao.module.promotion.controller.app.banner.vo.AppBannerRespVO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO; |
| 8 | import org.mapstruct.Mapper; | 9 | import org.mapstruct.Mapper; |
| 9 | import org.mapstruct.factory.Mappers; | 10 | import org.mapstruct.factory.Mappers; |
| @@ -25,4 +26,6 @@ public interface BannerConvert { | @@ -25,4 +26,6 @@ public interface BannerConvert { | ||
| 25 | 26 | ||
| 26 | BannerDO convert(BannerUpdateReqVO updateReqVO); | 27 | BannerDO convert(BannerUpdateReqVO updateReqVO); |
| 27 | 28 | ||
| 29 | + List<AppBannerRespVO> convertList01(List<BannerDO> bannerList); | ||
| 30 | + | ||
| 28 | } | 31 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/banner/BannerDO.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.dataobject.banner; | 1 | package cn.iocoder.yudao.module.promotion.dal.dataobject.banner; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | +import cn.iocoder.yudao.module.promotion.enums.banner.BannerPositionEnum; | ||
| 4 | import com.baomidou.mybatisplus.annotation.TableName; | 6 | import com.baomidou.mybatisplus.annotation.TableName; |
| 5 | import lombok.*; | 7 | import lombok.*; |
| 6 | 8 | ||
| @@ -40,14 +42,25 @@ public class BannerDO extends BaseDO { | @@ -40,14 +42,25 @@ public class BannerDO extends BaseDO { | ||
| 40 | private Integer sort; | 42 | private Integer sort; |
| 41 | 43 | ||
| 42 | /** | 44 | /** |
| 43 | - * 状态 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} | 45 | + * 状态 {@link CommonStatusEnum} |
| 44 | */ | 46 | */ |
| 45 | private Integer status; | 47 | private Integer status; |
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 定位 {@link BannerPositionEnum} | ||
| 51 | + */ | ||
| 52 | + private Integer position; | ||
| 53 | + | ||
| 46 | /** | 54 | /** |
| 47 | * 备注 | 55 | * 备注 |
| 48 | */ | 56 | */ |
| 49 | private String memo; | 57 | private String memo; |
| 50 | 58 | ||
| 51 | - // TODO 芋艿 点击次数。&& 其他数据相关 | 59 | + /** |
| 60 | + * 点击次数 | ||
| 61 | + */ | ||
| 62 | + private Integer browseCount; | ||
| 63 | + | ||
| 64 | + // TODO 芋艿 其他数据相关 | ||
| 52 | 65 | ||
| 53 | } | 66 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/banner/BannerMapper.java
| @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerPageReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO; |
| 8 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||
| 8 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 10 | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 10 | /** | 13 | /** |
| 11 | * Banner Mapper | 14 | * Banner Mapper |
| 12 | * | 15 | * |
| @@ -23,4 +26,14 @@ public interface BannerMapper extends BaseMapperX<BannerDO> { | @@ -23,4 +26,14 @@ public interface BannerMapper extends BaseMapperX<BannerDO> { | ||
| 23 | .orderByDesc(BannerDO::getSort)); | 26 | .orderByDesc(BannerDO::getSort)); |
| 24 | } | 27 | } |
| 25 | 28 | ||
| 29 | + default void updateBrowseCount(Long id) { | ||
| 30 | + update(null, new LambdaUpdateWrapper<BannerDO>() | ||
| 31 | + .eq(BannerDO::getId, id) | ||
| 32 | + .setSql("browse_count = browse_count + 1")); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + default List<BannerDO> selectBannerListByPosition(Integer position) { | ||
| 36 | + return selectList(new LambdaQueryWrapperX<BannerDO>().eq(BannerDO::getPosition, position)); | ||
| 37 | + } | ||
| 38 | + | ||
| 26 | } | 39 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/banner/BannerService.java
| @@ -47,12 +47,6 @@ public interface BannerService { | @@ -47,12 +47,6 @@ public interface BannerService { | ||
| 47 | BannerDO getBanner(Long id); | 47 | BannerDO getBanner(Long id); |
| 48 | 48 | ||
| 49 | /** | 49 | /** |
| 50 | - * 获得所有 Banner列表 | ||
| 51 | - * @return Banner列表 | ||
| 52 | - */ | ||
| 53 | - List<BannerDO> getBannerList(); | ||
| 54 | - | ||
| 55 | - /** | ||
| 56 | * 获得 Banner 分页 | 50 | * 获得 Banner 分页 |
| 57 | * | 51 | * |
| 58 | * @param pageReqVO 分页查询 | 52 | * @param pageReqVO 分页查询 |
| @@ -60,4 +54,19 @@ public interface BannerService { | @@ -60,4 +54,19 @@ public interface BannerService { | ||
| 60 | */ | 54 | */ |
| 61 | PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO); | 55 | PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO); |
| 62 | 56 | ||
| 57 | + /** | ||
| 58 | + * 增加 Banner 点击量 | ||
| 59 | + * | ||
| 60 | + * @param id Banner编号 | ||
| 61 | + */ | ||
| 62 | + void addBannerBrowseCount(Long id); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 获得 Banner 列表 | ||
| 66 | + * | ||
| 67 | + * @param position 定位 | ||
| 68 | + * @return Banner 列表 | ||
| 69 | + */ | ||
| 70 | + List<BannerDO> getBannerListByPosition(Integer position); | ||
| 71 | + | ||
| 63 | } | 72 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/banner/BannerServiceImpl.java
| @@ -66,13 +66,21 @@ public class BannerServiceImpl implements BannerService { | @@ -66,13 +66,21 @@ public class BannerServiceImpl implements BannerService { | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | @Override | 68 | @Override |
| 69 | - public List<BannerDO> getBannerList() { | ||
| 70 | - return bannerMapper.selectList(); | 69 | + public PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO) { |
| 70 | + return bannerMapper.selectPage(pageReqVO); | ||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | @Override | 73 | @Override |
| 74 | - public PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO) { | ||
| 75 | - return bannerMapper.selectPage(pageReqVO); | 74 | + public void addBannerBrowseCount(Long id) { |
| 75 | + // 校验 Banner 是否存在 | ||
| 76 | + validateBannerExists(id); | ||
| 77 | + // 增加点击次数 | ||
| 78 | + bannerMapper.updateBrowseCount(id); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public List<BannerDO> getBannerListByPosition(Integer position) { | ||
| 83 | + return bannerMapper.selectBannerListByPosition(position); | ||
| 76 | } | 84 | } |
| 77 | 85 | ||
| 78 | } | 86 | } |