Commit e2a6530acb94de6a36be483162bc3b66804c4a2c

Authored by luowenfeng
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
  1 +//请求工具参考https://ext.dcloud.net.cn/plugin?id=392
  2 +const { http } = uni.$u
  3 +
  4 +// 查询分类列表
  5 +export const categoryListData = params => http.get('product/category/list', { params })
yudao-ui-app/api/product.js 0 → 100644
  1 +//请求工具参考https://ext.dcloud.net.cn/plugin?id=392
  2 +const { http } = uni.$u
  3 +
  4 +// 查询商品spu列表
  5 +export const productSpuPage = params => http.get('/product/spu/page', { params })
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>