Commit e2a6530acb94de6a36be483162bc3b66804c4a2c
1 parent
f3c83488
feature(uniapp分类): 分类列表以及商品加载
Showing
16 changed files
with
585 additions
and
139 deletions
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.category; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.product.convert.category.CategoryConvert; | ||
| 6 | +import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; | ||
| 7 | +import cn.iocoder.yudao.module.product.service.category.CategoryService; | ||
| 8 | +import io.swagger.annotations.Api; | ||
| 9 | +import io.swagger.annotations.ApiOperation; | ||
| 10 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 12 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 13 | +import org.springframework.web.bind.annotation.RestController; | ||
| 14 | + | ||
| 15 | +import javax.annotation.Resource; | ||
| 16 | +import java.util.Comparator; | ||
| 17 | +import java.util.List; | ||
| 18 | + | ||
| 19 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 20 | + | ||
| 21 | +@Api(tags = "用户 APP - 商品分类") | ||
| 22 | +@RestController | ||
| 23 | +@RequestMapping("/product/category") | ||
| 24 | +@Validated | ||
| 25 | +public class AppCategoryController { | ||
| 26 | + | ||
| 27 | + @Resource | ||
| 28 | + private CategoryService categoryService; | ||
| 29 | + | ||
| 30 | + @GetMapping("/list") | ||
| 31 | + @ApiOperation("获得商品分类列表") | ||
| 32 | + public CommonResult<List<AppCategoryListRespVO>> listByQuery() { | ||
| 33 | + List<CategoryDO> list = categoryService.getCategoryList(); | ||
| 34 | + list.sort(Comparator.comparing(CategoryDO::getSort)); | ||
| 35 | + return success(CategoryConvert.INSTANCE.convertList03(list)); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/vo/AppCategoryListRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.category.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotBlank; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | + | ||
| 10 | +@Data | ||
| 11 | +@ApiModel(value = "App - 商品分类 列表 Request VO", description = "参数和 CategoryBaseVO 是一致的") | ||
| 12 | +public class AppCategoryListRespVO { | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "分类编号", required = true, example = "2") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "父分类编号", required = true, example = "1") | ||
| 18 | + @NotNull(message = "父分类编号不能为空") | ||
| 19 | + private Long parentId; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "分类名称", required = true, example = "办公文具") | ||
| 22 | + @NotBlank(message = "分类名称不能为空") | ||
| 23 | + private String name; | ||
| 24 | + | ||
| 25 | + @ApiModelProperty(value = "分类图标") | ||
| 26 | + @NotBlank(message = "分类图标不能为空") | ||
| 27 | + private String icon; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty(value = "分类图片", required = true) | ||
| 30 | + @NotBlank(message = "分类图片不能为空") | ||
| 31 | + private String bannerUrl; | ||
| 32 | + | ||
| 33 | + @ApiModelProperty(value = "分类排序", required = true, example = "1") | ||
| 34 | + private Integer sort; | ||
| 35 | + | ||
| 36 | + @ApiModelProperty(value = "分类描述", required = true, example = "描述") | ||
| 37 | + private String description; | ||
| 38 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.spu; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.SpuPageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.SpuRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | ||
| 10 | +import io.swagger.annotations.Api; | ||
| 11 | +import io.swagger.annotations.ApiOperation; | ||
| 12 | +import org.springframework.validation.annotation.Validated; | ||
| 13 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 14 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 15 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 16 | +import org.springframework.web.bind.annotation.RestController; | ||
| 17 | + | ||
| 18 | +import javax.annotation.Resource; | ||
| 19 | +import javax.validation.Valid; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 22 | + | ||
| 23 | +@Api(tags = "用户 APP - 商品spu") | ||
| 24 | +@RestController | ||
| 25 | +@RequestMapping("/product/spu") | ||
| 26 | +@Validated | ||
| 27 | +public class AppProductSpuController { | ||
| 28 | + | ||
| 29 | + @Resource | ||
| 30 | + private ProductSpuService spuService; | ||
| 31 | + | ||
| 32 | + @GetMapping("/page") | ||
| 33 | + @ApiOperation("获得商品spu分页") | ||
| 34 | + public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) { | ||
| 35 | + return success(spuService.getSpuPage(pageVO)); | ||
| 36 | + } | ||
| 37 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.spu.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | + | ||
| 10 | +@ApiModel("App - 商品spu分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +@ToString(callSuper = true) | ||
| 14 | +public class AppSpuPageReqVO extends PageParam { | ||
| 15 | + | ||
| 16 | + @ApiModelProperty(value = "分类id") | ||
| 17 | + private Long categoryId; | ||
| 18 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.spu.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | +import java.util.List; | ||
| 9 | + | ||
| 10 | +@ApiModel("App - 商品spu分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +public class AppSpuPageRespVO { | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "主键", required = true, example = "1") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "商品名称") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | + @ApiModelProperty(value = "卖点", required = true) | ||
| 21 | + @NotNull(message = "卖点不能为空") | ||
| 22 | + private String sellPoint; | ||
| 23 | + | ||
| 24 | + @ApiModelProperty(value = "描述", required = true) | ||
| 25 | + @NotNull(message = "描述不能为空") | ||
| 26 | + private String description; | ||
| 27 | + | ||
| 28 | + @ApiModelProperty(value = "分类id", required = true) | ||
| 29 | + @NotNull(message = "分类id不能为空") | ||
| 30 | + private Long categoryId; | ||
| 31 | + | ||
| 32 | + @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true) | ||
| 33 | + @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空") | ||
| 34 | + private List<String> picUrls; | ||
| 35 | + | ||
| 36 | + @ApiModelProperty(value = "排序字段", required = true) | ||
| 37 | + @NotNull(message = "排序字段不能为空") | ||
| 38 | + private Integer sort; | ||
| 39 | + | ||
| 40 | + @ApiModelProperty(value = "点赞初始人数") | ||
| 41 | + private Integer likeCount; | ||
| 42 | + | ||
| 43 | + @ApiModelProperty(value = "价格 单位使用:分") | ||
| 44 | + private Integer price; | ||
| 45 | + | ||
| 46 | + @ApiModelProperty(value = "库存数量") | ||
| 47 | + private Integer quantity; | ||
| 48 | + | ||
| 49 | + @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)") | ||
| 50 | + private Boolean status; | ||
| 51 | + | ||
| 52 | +} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java
| @@ -4,6 +4,7 @@ import java.util.*; | @@ -4,6 +4,7 @@ import java.util.*; | ||
| 4 | 4 | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | ||
| 7 | +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO; | ||
| 7 | import org.mapstruct.Mapper; | 8 | import org.mapstruct.Mapper; |
| 8 | import org.mapstruct.factory.Mappers; | 9 | import org.mapstruct.factory.Mappers; |
| 9 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; | 10 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; |
| @@ -31,4 +32,5 @@ public interface CategoryConvert { | @@ -31,4 +32,5 @@ public interface CategoryConvert { | ||
| 31 | 32 | ||
| 32 | List<CategoryExcelVO> convertList02(List<CategoryDO> list); | 33 | List<CategoryExcelVO> convertList02(List<CategoryDO> list); |
| 33 | 34 | ||
| 35 | + List<AppCategoryListRespVO> convertList03(List<CategoryDO> list); | ||
| 34 | } | 36 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
| @@ -4,6 +4,8 @@ import java.util.*; | @@ -4,6 +4,8 @@ import java.util.*; | ||
| 4 | 4 | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | ||
| 7 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||
| 7 | import org.mapstruct.Mapper; | 9 | import org.mapstruct.Mapper; |
| 8 | import org.mapstruct.Mapping; | 10 | import org.mapstruct.Mapping; |
| 9 | import org.mapstruct.Named; | 11 | import org.mapstruct.Named; |
| @@ -40,6 +42,11 @@ public interface ProductSpuConvert { | @@ -40,6 +42,11 @@ public interface ProductSpuConvert { | ||
| 40 | 42 | ||
| 41 | List<SpuExcelVO> convertList02(List<ProductSpuDO> list); | 43 | List<SpuExcelVO> convertList02(List<ProductSpuDO> list); |
| 42 | 44 | ||
| 45 | + SpuPageReqVO convert(AppSpuPageReqVO bean); | ||
| 46 | + | ||
| 47 | + @Mapping(source = "picUrls", target = "picUrls", qualifiedByName = "tokenizeToStringArray") | ||
| 48 | + AppSpuPageRespVO convertAppResp(ProductSpuDO list); | ||
| 49 | + | ||
| 43 | @Named("tokenizeToStringArray") | 50 | @Named("tokenizeToStringArray") |
| 44 | default List<String> translatePicUrlsArrayFromString(String picUrls) { | 51 | default List<String> translatePicUrlsArrayFromString(String picUrls) { |
| 45 | return Arrays.asList(StringUtils.tokenizeToStringArray(picUrls, ",")); | 52 | return Arrays.asList(StringUtils.tokenizeToStringArray(picUrls, ",")); |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.service.category; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.service.category; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; | 4 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.*; |
| 5 | +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO; | ||
| 5 | import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; | 6 | import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; |
| 6 | 7 | ||
| 7 | import javax.validation.Valid; | 8 | import javax.validation.Valid; |
| @@ -83,4 +84,11 @@ public interface CategoryService { | @@ -83,4 +84,11 @@ public interface CategoryService { | ||
| 83 | * @param categoryId 分类id | 84 | * @param categoryId 分类id |
| 84 | */ | 85 | */ |
| 85 | void validatedCategoryById(Long categoryId); | 86 | void validatedCategoryById(Long categoryId); |
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * app端获得商品分类列表 | ||
| 90 | + * | ||
| 91 | + * @return 商品分类列表 | ||
| 92 | + */ | ||
| 93 | + List<CategoryDO> getCategoryList(); | ||
| 86 | } | 94 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java
| 1 | package cn.iocoder.yudao.module.product.service.category; | 1 | package cn.iocoder.yudao.module.product.service.category; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.exception.ErrorCode; | 4 | import cn.iocoder.yudao.framework.common.exception.ErrorCode; |
| 4 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | 5 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -13,6 +14,7 @@ import org.springframework.validation.annotation.Validated; | @@ -13,6 +14,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 13 | import javax.annotation.Resource; | 14 | import javax.annotation.Resource; |
| 14 | import java.util.Collection; | 15 | import java.util.Collection; |
| 15 | import java.util.List; | 16 | import java.util.List; |
| 17 | +import java.util.stream.Collectors; | ||
| 16 | 18 | ||
| 17 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 18 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; | 20 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; |
| @@ -106,4 +108,13 @@ public class CategoryServiceImpl implements CategoryService { | @@ -106,4 +108,13 @@ public class CategoryServiceImpl implements CategoryService { | ||
| 106 | return categoryMapper.selectList(treeListReqVO); | 108 | return categoryMapper.selectList(treeListReqVO); |
| 107 | } | 109 | } |
| 108 | 110 | ||
| 111 | + @Override | ||
| 112 | + public List<CategoryDO> getCategoryList() { | ||
| 113 | + return categoryMapper.selectList() | ||
| 114 | + .stream() | ||
| 115 | + .filter(v->v.getStatus().equals(CommonStatusEnum.ENABLE.getStatus())) | ||
| 116 | + .collect(Collectors.toList()); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + | ||
| 109 | } | 120 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
| @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.product.service.spu; | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.product.service.spu; | ||
| 3 | import java.util.*; | 3 | import java.util.*; |
| 4 | import javax.validation.*; | 4 | import javax.validation.*; |
| 5 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | 5 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 6 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||
| 6 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 8 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 9 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | 10 | ||
| @@ -67,4 +69,13 @@ public interface ProductSpuService { | @@ -67,4 +69,13 @@ public interface ProductSpuService { | ||
| 67 | */ | 69 | */ |
| 68 | List<ProductSpuDO> getSpuList(SpuExportReqVO exportReqVO); | 70 | List<ProductSpuDO> getSpuList(SpuExportReqVO exportReqVO); |
| 69 | 71 | ||
| 72 | + /** | ||
| 73 | + * 获得商品spu分页 | ||
| 74 | + * | ||
| 75 | + * @param pageReqVO 分页查询 | ||
| 76 | + * @return 商品spu分页 | ||
| 77 | + */ | ||
| 78 | + PageResult<AppSpuPageRespVO> getSpuPage(AppSpuPageReqVO pageReqVO); | ||
| 79 | + | ||
| 80 | + | ||
| 70 | } | 81 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| @@ -8,9 +8,10 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | @@ -8,9 +8,10 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | ||
| 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; |
| 9 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; | 9 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; |
| 10 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | 10 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 11 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||
| 11 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | 13 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; |
| 12 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | 14 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; |
| 13 | -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO; | ||
| 14 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 15 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 15 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 16 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 16 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | 17 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; |
| @@ -175,4 +176,17 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -175,4 +176,17 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 175 | return ProductSpuMapper.selectList(exportReqVO); | 176 | return ProductSpuMapper.selectList(exportReqVO); |
| 176 | } | 177 | } |
| 177 | 178 | ||
| 179 | + @Override | ||
| 180 | + public PageResult<AppSpuPageRespVO> getSpuPage(AppSpuPageReqVO pageReqVO) { | ||
| 181 | + PageResult<ProductSpuDO> productSpuDOPageResult = ProductSpuMapper.selectPage(ProductSpuConvert.INSTANCE.convert(pageReqVO)); | ||
| 182 | + PageResult<AppSpuPageRespVO> pageResult = new PageResult<>(); | ||
| 183 | + List<AppSpuPageRespVO> collect = productSpuDOPageResult.getList() | ||
| 184 | + .stream() | ||
| 185 | + .map(ProductSpuConvert.INSTANCE::convertAppResp) | ||
| 186 | + .collect(Collectors.toList()); | ||
| 187 | + pageResult.setList(collect); | ||
| 188 | + pageResult.setTotal(productSpuDOPageResult.getTotal()); | ||
| 189 | + return pageResult; | ||
| 190 | + } | ||
| 191 | + | ||
| 178 | } | 192 | } |
yudao-ui-app/api/category.js
0 → 100644
yudao-ui-app/api/product.js
0 → 100644
yudao-ui-app/pages.json
| @@ -12,6 +12,14 @@ | @@ -12,6 +12,14 @@ | ||
| 12 | "navigationBarTitleText": "分类" | 12 | "navigationBarTitleText": "分类" |
| 13 | } | 13 | } |
| 14 | }, | 14 | }, |
| 15 | + { | ||
| 16 | + "path": "pages/category/product-list", | ||
| 17 | + "style": { | ||
| 18 | + "navigationBarTitleText": "", | ||
| 19 | + "navigationStyle": "custom", | ||
| 20 | + "navigationBarTextStyle": "white" | ||
| 21 | + } | ||
| 22 | + }, | ||
| 15 | { | 23 | { |
| 16 | "path": "pages/cart/cart", | 24 | "path": "pages/cart/cart", |
| 17 | "style": { | 25 | "style": { |
| @@ -112,7 +120,7 @@ | @@ -112,7 +120,7 @@ | ||
| 112 | "globalStyle": { | 120 | "globalStyle": { |
| 113 | "navigationBarTextStyle": "black", | 121 | "navigationBarTextStyle": "black", |
| 114 | "navigationBarTitleText": "yudao-ui-app", | 122 | "navigationBarTitleText": "yudao-ui-app", |
| 115 | - "navigationBarBackgroundColor": "#F8F8F8", | ||
| 116 | - "backgroundColor": "#FFFFFF" | 123 | + "navigationBarBackgroundColor": "#ffffff", |
| 124 | + "backgroundColor": "#ffffff" | ||
| 117 | } | 125 | } |
| 118 | } | 126 | } |
yudao-ui-app/pages/category/category.vue
| 1 | <template> | 1 | <template> |
| 2 | <view class="container"> | 2 | <view class="container"> |
| 3 | + <!-- 搜索框 --> | ||
| 3 | <view class="search-wrap"> | 4 | <view class="search-wrap"> |
| 4 | - <u-search placeholder="搜索" disabled height="32" :show-action="false" @click="handleSearchClick"></u-search> | 5 | + <u-search placeholder="搜索" disabled height="32" bgColor="#f2f2f2" margin="0 20rpx" :show-action="false" |
| 6 | + @click="handleSearchClick"></u-search> | ||
| 5 | </view> | 7 | </view> |
| 8 | + | ||
| 9 | + <!-- 分类内容 --> | ||
| 6 | <view class="category-box"> | 10 | <view class="category-box"> |
| 7 | - <view class="box-left"> | ||
| 8 | - <view> | ||
| 9 | - <view class="category-item" v-for="(item, index) in categoryList" :key="item.id"> | ||
| 10 | - <view class="item-title" :class="{ active: currentIndex === index }" @click="handleCategoryClick(index)"> | ||
| 11 | - <text>{{ item.name }}</text> | ||
| 12 | - </view> | 11 | + <!-- 左侧导航栏 --> |
| 12 | + <scroll-view scroll-y="true" class='box-left'> | ||
| 13 | + <view class="category-item" v-for="(item, index) in categoryList" :key="item.id"> | ||
| 14 | + <view class="item-title" :class="{ active: currentIndex === index }" @click="handleCategoryClick(index)"> | ||
| 15 | + <text>{{ item.name }}</text> | ||
| 13 | </view> | 16 | </view> |
| 14 | </view> | 17 | </view> |
| 15 | - </view> | ||
| 16 | - <view class="box-right"> | ||
| 17 | - <image class="category-image" :showLoading="true" :src="categoryList[currentIndex].image" width="530rpx" height="160rpx" @click="click"></image> | 18 | + </scroll-view> |
| 19 | + | ||
| 20 | + <!-- 右侧分类内容 --> | ||
| 21 | + <scroll-view scroll-y="true" class="box-right"> | ||
| 22 | + <view class="category-image"> | ||
| 23 | + <image :showLoading="true" :src="categoryList[currentIndex].bannerUrl" mode='widthFix' @click="click"></image> | ||
| 24 | + </view> | ||
| 25 | + | ||
| 18 | <view class="sub-category-box" v-for="(item, index) in categoryList[currentIndex].children" :key="item.id"> | 26 | <view class="sub-category-box" v-for="(item, index) in categoryList[currentIndex].children" :key="item.id"> |
| 19 | <view class="sub-category-header"> | 27 | <view class="sub-category-header"> |
| 20 | - <view class="title">{{ item.title }}</view> | ||
| 21 | - <view class="more">查看更多</view> | 28 | + <view class="title">{{ item.name }}</view> |
| 29 | + <view class="more" @click="handleCategory(item, 0)">查看更多</view> | ||
| 30 | + </view> | ||
| 31 | + | ||
| 32 | + <view class="sub-category-grid"> | ||
| 33 | + <u-grid col="3"> | ||
| 34 | + <u-grid-item v-for="(subItem, subIndex) in item.children" :key="subItem.id"> | ||
| 35 | + <view class="sub-category-item" @click="handleCategory(item, subIndex)"> | ||
| 36 | + <u-icon name="photo" :size="80" v-if="subItem.bannerUrl === null"></u-icon> | ||
| 37 | + <image :src="item.bannerUrl" v-if="subItem.bannerUrl != null" mode='widthFix' /> | ||
| 38 | + <text class="sub-category-title">{{ subItem.name }}</text> | ||
| 39 | + </view> | ||
| 40 | + </u-grid-item> | ||
| 41 | + </u-grid> | ||
| 22 | </view> | 42 | </view> |
| 23 | - <u-grid class="sub-category-grid" col="3"> | ||
| 24 | - <u-grid-item v-for="(subItem, subIndex) in item.category" :key="subItem.id"> | ||
| 25 | - <view class="sub-category-item"> | ||
| 26 | - <u-icon name="photo" :size="80"></u-icon> | ||
| 27 | - <text class="sub-category-title">{{ subItem.title }}</text> | ||
| 28 | - </view> | ||
| 29 | - </u-grid-item> | ||
| 30 | - </u-grid> | ||
| 31 | </view> | 43 | </view> |
| 32 | - </view> | 44 | + </scroll-view> |
| 33 | </view> | 45 | </view> |
| 34 | </view> | 46 | </view> |
| 35 | </template> | 47 | </template> |
| 36 | 48 | ||
| 37 | <script> | 49 | <script> |
| 38 | -export default { | ||
| 39 | - data() { | ||
| 40 | - return { | ||
| 41 | - currentIndex: 0, | ||
| 42 | - categoryList: [] | ||
| 43 | - } | ||
| 44 | - }, | ||
| 45 | - onLoad() { | ||
| 46 | - for (let i = 0; i < 10; i++) { | ||
| 47 | - this.categoryList.push({ | ||
| 48 | - id: i, | ||
| 49 | - image: 'https://cdn.uviewui.com/uview/swiper/swiper1.png', | ||
| 50 | - name: '商品分类' + i, | ||
| 51 | - children: [ | ||
| 52 | - { | ||
| 53 | - id: 0, | ||
| 54 | - title: '分类' + i + '-1', | ||
| 55 | - category: [ | ||
| 56 | - { | ||
| 57 | - id: 0, | ||
| 58 | - image: '', | ||
| 59 | - title: '分类' + i + '-1-1' | ||
| 60 | - }, | ||
| 61 | - { | ||
| 62 | - id: 2, | ||
| 63 | - image: '', | ||
| 64 | - title: '分类' + i + '-1-2' | ||
| 65 | - }, | ||
| 66 | - { | ||
| 67 | - id: 3, | ||
| 68 | - image: '', | ||
| 69 | - title: '分类' + i + '-1-3' | ||
| 70 | - } | ||
| 71 | - ] | ||
| 72 | - }, | ||
| 73 | - { | ||
| 74 | - id: 1, | ||
| 75 | - title: '分类' + i + '-2', | ||
| 76 | - category: [ | ||
| 77 | - { | ||
| 78 | - id: 0, | ||
| 79 | - image: '', | ||
| 80 | - title: '分类' + i + '-2-1' | ||
| 81 | - }, | ||
| 82 | - { | ||
| 83 | - id: 2, | ||
| 84 | - image: '', | ||
| 85 | - title: '分类' + i + '-2-2' | ||
| 86 | - }, | ||
| 87 | - { | ||
| 88 | - id: 3, | ||
| 89 | - image: '', | ||
| 90 | - title: '分类' + i + '-2-3' | ||
| 91 | - } | ||
| 92 | - ] | ||
| 93 | - } | ||
| 94 | - ] | ||
| 95 | - }) | ||
| 96 | - } | ||
| 97 | - }, | ||
| 98 | - methods: { | ||
| 99 | - handleSearchClick(e) { | ||
| 100 | - uni.$u.route('/pages/search/search') | 50 | + import { categoryListData } from '../../api/category'; |
| 51 | + import { handleTree, convertTree } from '../../utils/tree.js'; | ||
| 52 | + | ||
| 53 | + export default { | ||
| 54 | + data() { | ||
| 55 | + return { | ||
| 56 | + currentIndex: 0, | ||
| 57 | + categoryList: [] | ||
| 58 | + } | ||
| 101 | }, | 59 | }, |
| 102 | - handleCategoryClick(index) { | ||
| 103 | - if (this.currentIndex !== index) { | ||
| 104 | - this.currentIndex = index | 60 | + onLoad() { |
| 61 | + this.handleCategoryList(); | ||
| 62 | + }, | ||
| 63 | + methods: { | ||
| 64 | + // 点击搜索框 | ||
| 65 | + handleSearchClick(e) { | ||
| 66 | + uni.$u.route('/pages/search/search') | ||
| 67 | + }, | ||
| 68 | + // 点击左侧导航栏 | ||
| 69 | + handleCategoryClick(index) { | ||
| 70 | + if (this.currentIndex !== index) { | ||
| 71 | + this.currentIndex = index | ||
| 72 | + } | ||
| 73 | + }, | ||
| 74 | + // 获取分类列表并构建树形结构 | ||
| 75 | + handleCategoryList() { | ||
| 76 | + categoryListData().then(res => { | ||
| 77 | + this.categoryList = handleTree(res.data, "id", "parentId"); | ||
| 78 | + }) | ||
| 79 | + }, | ||
| 80 | + handleCategory(item, index){ | ||
| 81 | + // console.log(item) | ||
| 82 | + // console.log(index) | ||
| 83 | + uni.navigateTo({ | ||
| 84 | + url:"./product-list?item="+encodeURIComponent(JSON.stringify(item))+"&index="+index | ||
| 85 | + }) | ||
| 105 | } | 86 | } |
| 106 | } | 87 | } |
| 107 | } | 88 | } |
| 108 | -} | ||
| 109 | </script> | 89 | </script> |
| 110 | 90 | ||
| 111 | <style lang="scss" scoped> | 91 | <style lang="scss" scoped> |
| 92 | + .search-wrap { | ||
| 93 | + background: #ffffff; | ||
| 94 | + position: fixed; | ||
| 95 | + top: 0; | ||
| 96 | + left: 0; | ||
| 97 | + box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.07); | ||
| 98 | + padding: 20rpx 0; | ||
| 99 | + width: 100%; | ||
| 100 | + z-index: 3; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + .category-box { | ||
| 104 | + position: fixed; | ||
| 105 | + display: flex; | ||
| 106 | + overflow: hidden; | ||
| 107 | + margin-top: 100rpx; | ||
| 108 | + height: calc(100% - 100rpx); | ||
| 109 | + | ||
| 110 | + .box-left { | ||
| 111 | + width: 200rpx; | ||
| 112 | + padding-top: 5rpx; | ||
| 113 | + overflow: scroll; | ||
| 114 | + z-index: 2; | ||
| 115 | + background-color: #f2f2f2; | ||
| 116 | + | ||
| 117 | + .category-item { | ||
| 118 | + line-height: 80rpx; | ||
| 119 | + height: 80rpx; | ||
| 120 | + text-align: center; | ||
| 121 | + color: #777; | ||
| 112 | 122 | ||
| 113 | -.search-wrap { | ||
| 114 | - background: $custom-bg-color; | ||
| 115 | - padding: 20rpx; | ||
| 116 | -} | ||
| 117 | - | ||
| 118 | -.category-box { | ||
| 119 | - display: flex; | ||
| 120 | - .box-left { | ||
| 121 | - width: 200rpx; | ||
| 122 | - padding-top: 20rpx; | ||
| 123 | - border-right: $custom-border-style; | ||
| 124 | - .category-item { | ||
| 125 | - border-bottom: $custom-border-style; | ||
| 126 | - padding: 20rpx 0; | ||
| 127 | - .item-title { | ||
| 128 | - padding-left: 30rpx; | ||
| 129 | - font-size: 28rpx; | ||
| 130 | - &.active { | ||
| 131 | - border-left: 6rpx solid $u-primary; | ||
| 132 | - font-weight: 700; | 123 | + .item-title { |
| 124 | + font-size: 28rpx; | ||
| 125 | + | ||
| 126 | + &.active { | ||
| 127 | + font-size: 28rpx; | ||
| 128 | + font-weight: bold; | ||
| 129 | + position: relative; | ||
| 130 | + background: #fff; | ||
| 131 | + color: $u-primary; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + &.active::before { | ||
| 135 | + position: absolute; | ||
| 136 | + left: 0; | ||
| 137 | + content: ""; | ||
| 138 | + width: 8rpx; | ||
| 139 | + height: 32rpx; | ||
| 140 | + top: 25rpx; | ||
| 141 | + background: $u-primary; | ||
| 142 | + } | ||
| 133 | } | 143 | } |
| 134 | } | 144 | } |
| 135 | } | 145 | } |
| 136 | - } | ||
| 137 | - .box-right { | ||
| 138 | - flex: 1; | ||
| 139 | - .category-image { | ||
| 140 | - width: 510rpx; | ||
| 141 | - height: 160rpx; | ||
| 142 | - padding: 20rpx; | ||
| 143 | - } | ||
| 144 | 146 | ||
| 145 | - .sub-category-box { | ||
| 146 | - .sub-category-header { | ||
| 147 | - @include flex-space-between; | ||
| 148 | - padding: 30rpx 20rpx; | 147 | + .box-right { |
| 148 | + width: 550rpx; | ||
| 149 | + height: 100%; | ||
| 150 | + box-sizing: border-box; | ||
| 151 | + z-index: 1; | ||
| 149 | 152 | ||
| 150 | - .title { | ||
| 151 | - font-size: 28rpx; | ||
| 152 | - font-weight: 700; | ||
| 153 | - } | ||
| 154 | - .more { | ||
| 155 | - font-size: 22rpx; | ||
| 156 | - color: #939393; | 153 | + .category-image { |
| 154 | + width: 510rpx; | ||
| 155 | + box-sizing: border-box; | ||
| 156 | + overflow: hidden; | ||
| 157 | + position: relative; | ||
| 158 | + margin: 30rpx 20rpx 0; | ||
| 159 | + | ||
| 160 | + image { | ||
| 161 | + width: 100%; | ||
| 157 | } | 162 | } |
| 158 | } | 163 | } |
| 159 | 164 | ||
| 160 | - .sub-category-grid { | ||
| 161 | - padding: 0 15rpx; | 165 | + .sub-category-box { |
| 166 | + .sub-category-header { | ||
| 167 | + @include flex-space-between; | ||
| 168 | + padding: 20rpx 20rpx; | ||
| 169 | + | ||
| 170 | + .title { | ||
| 171 | + font-size: 28rpx; | ||
| 172 | + font-weight: bolder; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + .more { | ||
| 176 | + font-size: 22rpx; | ||
| 177 | + color: #939393; | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + .sub-category-grid { | ||
| 182 | + padding: 0 15rpx; | ||
| 183 | + | ||
| 184 | + .sub-category-item { | ||
| 185 | + @include flex-center(column); | ||
| 186 | + background: #fff; | ||
| 162 | 187 | ||
| 163 | - .sub-category-item { | ||
| 164 | - @include flex-center(column); | ||
| 165 | - background: #fff; | 188 | + image { |
| 189 | + text-align: center; | ||
| 190 | + width: 150rpx; | ||
| 191 | + height: 150rpx; | ||
| 192 | + line-height: 150rpx; | ||
| 193 | + font-size: 0; | ||
| 194 | + } | ||
| 166 | 195 | ||
| 167 | - .sub-category-title { | ||
| 168 | - margin: 15rpx 0; | ||
| 169 | - font-size: 24rpx; | 196 | + .sub-category-title { |
| 197 | + margin: 15rpx 0; | ||
| 198 | + font-size: 22rpx; | ||
| 199 | + } | ||
| 170 | } | 200 | } |
| 171 | } | 201 | } |
| 172 | } | 202 | } |
| 173 | } | 203 | } |
| 174 | } | 204 | } |
| 175 | -} | ||
| 176 | </style> | 205 | </style> |
yudao-ui-app/pages/category/product-list.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="container"> | ||
| 3 | + <u-navbar :title="title" :autoBack="true" placeholder="true" titleStyle="font-size: 28rpx"> | ||
| 4 | + </u-navbar> | ||
| 5 | + <view class="context"> | ||
| 6 | + <view class="tabs-top"> | ||
| 7 | + <u-tabs :list="categoryList" @click="changeTabs" :current="current" lineHeight="2" lineWidth="85rpx" | ||
| 8 | + itemStyle="padding-left: 15px; padding-right: 15px; height: 85rpx;"></u-tabs> | ||
| 9 | + </view> | ||
| 10 | + <scroll-view scroll-y="true" class="product-list" enable-flex="true"> | ||
| 11 | + <view class="flex-box"> | ||
| 12 | + <block v-for="(item, index) in productList[current]" :key="index"> | ||
| 13 | + <view class="product-item"> | ||
| 14 | + <view class="product-image"> | ||
| 15 | + <image :src="item.picUrls[0]" mode='widthFix' /> | ||
| 16 | + </view> | ||
| 17 | + <view class="product-button"> | ||
| 18 | + <view class="product-text">【{{ item.sellPoint }}】{{ item.name }}</view> | ||
| 19 | + <view class="product-price-button"> | ||
| 20 | + <text class="product-price">¥ | ||
| 21 | + <text class="price-size">{{ towNumber(item.price) }}</text></text> | ||
| 22 | + <text class="product-like-ccount">销量 {{ item.likeCount }}</text> | ||
| 23 | + </view> | ||
| 24 | + </view> | ||
| 25 | + </view> | ||
| 26 | + </block> | ||
| 27 | + </view> | ||
| 28 | + </scroll-view> | ||
| 29 | + </view> | ||
| 30 | + </view> | ||
| 31 | +</template> | ||
| 32 | + | ||
| 33 | +<script> | ||
| 34 | + import { | ||
| 35 | + productSpuPage | ||
| 36 | + } from '../../api/product'; | ||
| 37 | + | ||
| 38 | + export default { | ||
| 39 | + data() { | ||
| 40 | + return { | ||
| 41 | + title: "", | ||
| 42 | + current: 0, | ||
| 43 | + categoryList: [], | ||
| 44 | + productList: {} | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + onLoad(option) { | ||
| 48 | + const item = JSON.parse(decodeURIComponent(option.item)) | ||
| 49 | + this.title = item.name | ||
| 50 | + this.categoryList = item.children | ||
| 51 | + this.handleProductSpu(option.index); | ||
| 52 | + }, | ||
| 53 | + methods: { | ||
| 54 | + changeTabs(item) { | ||
| 55 | + if (item.index != this.current) { | ||
| 56 | + this.handleProductSpu(item.index) | ||
| 57 | + } | ||
| 58 | + }, | ||
| 59 | + handleProductSpu(index) { | ||
| 60 | + let param = {} | ||
| 61 | + param.categoryId = this.categoryList[index].id | ||
| 62 | + console.log(this.categoryList) | ||
| 63 | + console.log(index) | ||
| 64 | + productSpuPage(param).then(res => { | ||
| 65 | + this.productList[index] = res.data.list | ||
| 66 | + this.current = index | ||
| 67 | + }) | ||
| 68 | + }, | ||
| 69 | + towNumber(val) { | ||
| 70 | + return (val / 100).toFixed(2) | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | +</script> | ||
| 75 | + | ||
| 76 | +<style lang="scss" scoped> | ||
| 77 | + .context { | ||
| 78 | + width: 100vw; | ||
| 79 | + position: fixed; | ||
| 80 | + top: 160rpx; | ||
| 81 | + left: 0; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + .tabs-top { | ||
| 85 | + position: relative; | ||
| 86 | + top: 0; | ||
| 87 | + width: 100%; | ||
| 88 | + height: 85rpx; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + .product-list { | ||
| 92 | + position: relative; | ||
| 93 | + background-color: #f2f2f2; | ||
| 94 | + height: calc(100vh - 88rpx - 100rpx - var(--status-bar-height)); | ||
| 95 | + width: 100%; | ||
| 96 | + | ||
| 97 | + .flex-box { | ||
| 98 | + width: 730rpx; | ||
| 99 | + margin: 0 auto; | ||
| 100 | + @include flex; | ||
| 101 | + flex-wrap: wrap; | ||
| 102 | + justify-content: left; | ||
| 103 | + | ||
| 104 | + .product-item { | ||
| 105 | + width: 345rpx; | ||
| 106 | + height: 450rpx; | ||
| 107 | + background-color: #ffffff; | ||
| 108 | + margin: 20rpx 10rpx 0; | ||
| 109 | + border-radius: 20rpx; | ||
| 110 | + | ||
| 111 | + .product-image { | ||
| 112 | + width: 100%; | ||
| 113 | + height: 300rpx; | ||
| 114 | + overflow: hidden; | ||
| 115 | + border-radius: 20rpx; | ||
| 116 | + image { | ||
| 117 | + width: 100%; | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + .product-button { | ||
| 122 | + width: 330rpx; | ||
| 123 | + margin: 15rpx auto 0; | ||
| 124 | + | ||
| 125 | + .product-text { | ||
| 126 | + font-size: 25rpx; | ||
| 127 | + height: 70rpx; | ||
| 128 | + overflow: hidden; | ||
| 129 | + -webkit-line-clamp: 2; | ||
| 130 | + text-overflow: ellipsis; | ||
| 131 | + display: -webkit-box; | ||
| 132 | + -webkit-box-orient: vertical; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + .product-price-button { | ||
| 136 | + font-size: 20rpx; | ||
| 137 | + margin-top: 20rpx; | ||
| 138 | + | ||
| 139 | + .product-price { | ||
| 140 | + color: red; | ||
| 141 | + | ||
| 142 | + .price-size { | ||
| 143 | + font-size: 26rpx; | ||
| 144 | + } | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + .product-like-ccount { | ||
| 148 | + font-size: 16rpx; | ||
| 149 | + margin-left: 10rpx; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + } | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + // } | ||
| 159 | + | ||
| 160 | + } | ||
| 161 | +</style> |