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 4  
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6  
  7 +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
7 8 import org.mapstruct.Mapper;
8 9 import org.mapstruct.factory.Mappers;
9 10 import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
... ... @@ -31,4 +32,5 @@ public interface CategoryConvert {
31 32  
32 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 4  
5 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 9 import org.mapstruct.Mapper;
8 10 import org.mapstruct.Mapping;
9 11 import org.mapstruct.Named;
... ... @@ -40,6 +42,11 @@ public interface ProductSpuConvert {
40 42  
41 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 50 @Named("tokenizeToStringArray")
44 51 default List<String> translatePicUrlsArrayFromString(String picUrls) {
45 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 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
  5 +import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
5 6 import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
6 7  
7 8 import javax.validation.Valid;
... ... @@ -83,4 +84,11 @@ public interface CategoryService {
83 84 * @param categoryId 分类id
84 85 */
85 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 1 package cn.iocoder.yudao.module.product.service.category;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 5 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
... ... @@ -13,6 +14,7 @@ import org.springframework.validation.annotation.Validated;
13 14 import javax.annotation.Resource;
14 15 import java.util.Collection;
15 16 import java.util.List;
  17 +import java.util.stream.Collectors;
16 18  
17 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
18 20 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
... ... @@ -106,4 +108,13 @@ public class CategoryServiceImpl implements CategoryService {
106 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 3 import java.util.*;
4 4 import javax.validation.*;
5 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 8 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
7 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 10  
... ... @@ -67,4 +69,13 @@ public interface ProductSpuService {
67 69 */
68 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 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
9 9 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
10 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 13 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
12 14 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
13   -import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
14 15 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
15 16 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
16 17 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
... ... @@ -175,4 +176,17 @@ public class ProductSpuServiceImpl implements ProductSpuService {
175 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 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 24 "path": "pages/cart/cart",
17 25 "style": {
... ... @@ -112,7 +120,7 @@
112 120 "globalStyle": {
113 121 "navigationBarTextStyle": "black",
114 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 1 <template>
2 2 <view class="container">
  3 + <!-- 搜索框 -->
3 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 7 </view>
  8 +
  9 + <!-- 分类内容 -->
6 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 16 </view>
14 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 26 <view class="sub-category-box" v-for="(item, index) in categoryList[currentIndex].children" :key="item.id">
19 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 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 43 </view>
32   - </view>
  44 + </scroll-view>
33 45 </view>
34 46 </view>
35 47 </template>
36 48  
37 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 89 </script>
110 90  
111 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 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>
... ...