谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)-2

简介: 谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)

发布商品


调试会员等级接口

启动会员微服务,添加网关,添加前端页面…


添加如下会员:


462d24bbc773b7c1d20a7e4637431c27_0aef3b5dc4a4d6677944260afcebfcef.png


获取分类关联的品牌

controller


/**
 * 1.获取分类关联的品牌
 * /product/categorybrandrelation/brands/list
 */
@GetMapping("/brands/list")
public R relationBrandList(@RequestParam(value = "catId", required = true) Long catId) {
    List<BrandEntity> vos = categoryBrandRelationService.getBrandsByCatId(catId);
    //品牌对象集合在进行筛选,赋予品牌对象id和name,返回封装的vo给前端
    List<BrandVo> collect = vos.stream().map(item -> {
        BrandVo brandVo = new BrandVo();
        brandVo.setBrandId(item.getBrandId());
        brandVo.setBrandName(item.getName());
        return brandVo;
    }).collect(Collectors.toList());
    return R.ok().put("data",collect);
}

service


@Override
public List<BrandEntity> getBrandsByCatId(Long catId) {
    //获得CategoryBrandRelationEntity集合对象
    List<CategoryBrandRelationEntity> catelogId = relationDao.selectList(new QueryWrapper<CategoryBrandRelationEntity>().eq("catelog_id", catId));
    //获得所有集合对象中brandid,通过brandService查询所有品牌,封装成品牌对象集合
    List<BrandEntity> collect = catelogId.stream().map(item -> {
        Long brandId = item.getBrandId();
        BrandEntity entity = brandService.getById(brandId);
        return entity;
    }).collect(Collectors.toList());
    //返回品牌对象集合
    return collect;
}

测试


开发规范


  1. Controller:处理请求,接受和校验数据
  2. Service接受controlLer传来的数据,进行业务处理
  3. Controller接受service处理完的数据,封装页面指定的vo


9534ea7975f9a4690b5fbb9b1b672435_aa2f5c515ff0520b8e077c7cbecc1693.png

获取分类下所有分组&关联属性

接口功能如下


也就是说当我们选择手机分类时,那就查出手机相关的分组信息,并查出每个分组相应属性信息


377fa922d27390be215c3fdd26287a65_f5cf2503385803367fcac0a0faf6c2d6.png


vo


@Data
public class AttrGroupWithAttrsVo {
    /**
     * 分组id
     */
    @TableId
    private Long attrGroupId;
    /**
     * 组名
     */
    private String attrGroupName;
    /**
     * 排序
     */
    private Integer sort;
    /**
     * 描述
     */
    private String descript;
    /**
     * 组图标
     */
    private String icon;
    /**
     * 所属分类id
     */
    private Long catelogId;
    private List<AttrEntity> attrs;
}

controller


/**
 * 7.获取分类下所有分组&关联属性
 * /product/attrgroup/{catelogId}/withattr
 */
@GetMapping("/{catelogId}/withattr")
public R getAttrGroupWithAttrs(@PathVariable("catelogId") Long catelogId) {
    List<AttrGroupWithAttrsVo> vos = attrGroupService.getAttrGroupWithAttrsByCatelogId(catelogId);
    return R.ok().put("data",vos);
}

service


vo的重要性:


vo(value object)当相应数据需要自定义时,用vo是最好的选择,不需要对实体类字段进行修改



/**
     * 获取分类下的所有分组及属性
     * @param catelogId
     * @return
     */
    @Override
    public List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId) {
        /** 1.获取分类下的所有分组,封装成集合
         *  分类和组的关系在pms_group表中,所以(where catelog_id = ?)即可查出分类对应的组
         *  由于这是mp,它会得出所有的这种关系,并把结果封装成集合
         */
        List<AttrGroupEntity> list = this.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        /** 2.获得分组下的属性
         *  要第三张关联表,直接调用关联表的service即查询分组对应的属性id
         *  获得属性id在去调用属性表的service即可查询属性名
         *  以上两步前面已经写好逻辑了直接调用即可attrService.getRelationAttr(groupId)
         */
        List<AttrGroupWithAttrsVo> collect = list.stream().map((item) -> {
            AttrGroupWithAttrsVo attrGroupWithAttrsVo = new AttrGroupWithAttrsVo();
            BeanUtils.copyProperties(item, attrGroupWithAttrsVo);
            List<AttrEntity> attrs = attrService.getRelationAttr(attrGroupWithAttrsVo.getAttrGroupId());
            if (attrs != null) {
                attrGroupWithAttrsVo.setAttrs(attrs);
            }
            return attrGroupWithAttrsVo;
        }).filter((attrvo) -> {
            return attrvo.getAttrs() != null && attrvo.getAttrs().size() > 0;
        }).collect(Collectors.toList());
        return collect;
    }

测试


2bf11cc47e25eb6c560cbe68f334f580_513a9af5921b1c20fd6a960e5b56d4a5.png


商品新增vo抽取

设置完属性,点击保存之后取消保存,复制控制台输出


65677956a4b736af667622546c2f3505_3d8671d857cde6cd313dddc3bc80e12e.png


[在线JSON字符串转Java实体类(JavaBean、Entity)-BeJSON.com](https://www.bejson.com/json2javapojo/new/)


直接解析json数据封装成实体类


这里我简单截取一个主要的Vo


此Vo包括每个步骤所携带的数据,有的是单个字段有的是一个集合


逻辑不难,难点是要理清逻辑,注意细节!


@Data
public class SpuSaveVo {
    @NotEmpty(groups = {AddGroup.class})
    private String spuName;
    private String spuDescription;
    @NotEmpty(groups = {AddGroup.class})
    private Long catalogId;
    @NotEmpty(groups = {AddGroup.class})
    private Long brandId;
    private double weight;
    private int publishStatus;
    private List<String> decript;
    private List<String> images;
    private Bounds bounds;
    @NotEmpty(groups = {AddGroup.class})
    private List<BaseAttrs> baseAttrs;
    @NotEmpty(groups = {AddGroup.class})
    private List<Skus> skus;
}

商品新增业务流程分析

逻辑很简单那,就是把数据保存到多张表中


因为这个Vo收集的数据很多,包括每个步骤你所选择的数据


1.保存spu基本信息 pms_spu_info


因为所有传来的信息都在vo里,所以我们把信息拷贝到对应的实体类中,如果vo没有的那就可以自己赋值


表结构如下:


5abf12cf608b096aa80c3479e617c648_d9c836dc5538ec4ed6302139259c5db4.png


这里的infoEntity.setCreateTime(new Date());infoEntity.setUpdateTime(new Date());是因为前端传入的是没有这两个字段的,我们自己赋值即可

SpuInfoEntity infoEntity = new SpuInfoEntity();
BeanUtils.copyProperties(vo, infoEntity);
infoEntity.setCreateTime(new Date());
infoEntity.setUpdateTime(new Date());
this.saveBaseInfo(infoEntity);

2.保存spu的描述图片 pms_spu_info_desc

保存哪个数据到哪个表,就注入那个service


String.join()的作用是把集合中的元素通过","分割形成一个一个的字符串


List<String> decript = vo.getDecript();
SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
descEntity.setSpuId(infoEntity.getId());
descEntity.setDecript(String.join(",", decript));
spuInfoDescService.saveSpuInfoDesc(descEntity);

3.保存spu的图片集 pms_spu_images

从vo中获取所有图片集合

调用图片service进行保存,保存只需要两个点

图片id和url地址,传入对象即可


List<String> images = vo.getImages();
imagesService.saveImages(infoEntity.getId(), images);

4.保存spu的规格参数 pms_product_attr_value

从vo中获取所有规格参数集合

对规格参数集合进行遍历,设置每项的属性


List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
List<ProductAttrValueEntity> collect = baseAttrs.stream().map((attr) -> {
    ProductAttrValueEntity valueEntity = new ProductAttrValueEntity();
    valueEntity.setAttrId(attr.getAttrId());
    AttrEntity id = attrService.getById(attr.getAttrId());
    valueEntity.setAttrName(id.getAttrName());
    valueEntity.setAttrValue(attr.getAttrValues());
    valueEntity.setQuickShow(attr.getShowDesc());
    valueEntity.setSpuId(infoEntity.getId());
    return valueEntity;
}).collect(Collectors.toList());
attrValueService.saveProductAttr(collect);

5.保存spu的积分信息 mall_sms -> sms_spu_bounds

Bounds bounds = vo.getBounds();
SpuBoundTo spuBoundTo = new SpuBoundTo();
BeanUtils.copyProperties(bounds, spuBoundTo);
spuBoundTo.setSpuId(infoEntity.getId());
R r0 = couponFeignService.saveSpuBounds(spuBoundTo);
if (r0.getCode() != 0) {
    log.error("远程保存spu积分信息异常");
}
couponFeignService.saveSpuBounds(spuBoundTo);

6.保存当前spu对应的所有sku信息;


//6.1sku的基本信息;pms_sku_info
List<Skus> skus = vo.getSkus();
if (skus != null && skus.size() > 0) {
    skus.forEach(item -> {
        String defalutImg = "";
        for (Images image : item.getImages()) {
            if (image.getDefaultImg() == 1) {
                defalutImg = image.getImgUrl();
            }
        }
        SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
        BeanUtils.copyProperties(item, skuInfoEntity);
        //添加vo中没有的信息
        skuInfoEntity.setBrandId(infoEntity.getBrandId());
        skuInfoEntity.setCatalogId(infoEntity.getCatalogId());
        skuInfoEntity.setSaleCount(0L);
        skuInfoEntity.setSpuId(infoEntity.getId());
        skuInfoEntity.setSkuDefaultImg(defalutImg);
        skuInfoService.saveSkuInfo(skuInfoEntity);
        //6.2sku图片信息;pms_sku_images
        //没有图片路径的无需保存
        Long skuId = skuInfoEntity.getSkuId();
        List<SkuImagesEntity> imageEntities = item.getImages().stream().map(img -> {
            SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
            skuImagesEntity.setSkuId(skuId);
            skuImagesEntity.setImgUrl(img.getImgUrl());
            skuImagesEntity.setDefaultImg(img.getDefaultImg());
            return skuImagesEntity;
        }).filter(entity -> {
            return !StringUtils.isEmpty(entity.getImgUrl());
        }).collect(Collectors.toList());
        skuImagesService.saveBatch(imageEntities);
        //6.3sku的销售属性;pms_sku_sale_attr_value
        List<Attr> attr = item.getAttr();
        List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(a -> {
            SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
            BeanUtils.copyProperties(a, attrValueEntity);
            attrValueEntity.setSkuId(skuId);
            return attrValueEntity;
        }).collect(Collectors.toList());
        skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
        //6.4sku的优惠满减信息(跨服务);
        SkuReductionTo skuReductionTo = new SkuReductionTo();
        BeanUtils.copyProperties(item, skuReductionTo);
        skuReductionTo.setSkuId(skuId);
        if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
            R r1 = couponFeignService.saveSkuReduction(skuReductionTo);
            if (r1.getCode() != 0) {
                log.error("远程保存spu积分信息异常");
            }
        }
    });
}

测试


c35064056a97515b72bd34f13e111324_c5020970aa0252e8f25bd3481c2fe048.png


检索功能

也就是多条件分页查询,很常见的功能!


spu检索


controller


/**
 * 列表
 */
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = spuInfoService.queryPageByCondition(params);
    return R.ok().put("page", page);
}

service


@Override
public PageUtils queryPageByCondition(Map<String, Object> params) {
    QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
        //等价sql: status=1 and (id=1 or spu_name like xxx)
        queryWrapper.and((w) -> {
            w.eq("id", key).or().like("spu_name", key);
        });
    }
    String status = (String) params.get("status");
    if (!StringUtils.isEmpty(status)) {
        queryWrapper.eq("publish_status", status);
    }
    String brandId = (String) params.get("brandId");
    if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
        queryWrapper.eq("brand_id", brandId);
    }
    String catelogId = (String) params.get("catelogId");
    if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
        queryWrapper.eq("catalog_id", catelogId);
    }
    IPage<SpuInfoEntity> page = this.page(
            new Query<SpuInfoEntity>().getPage(params),
            queryWrapper
    );
    return new PageUtils(page);
}

sku检索


controller


/**
 * 列表
 */
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = skuInfoService.queryPageByParams(params);
    return R.ok().put("page", page);
}

service


@Override
public PageUtils queryPageByParams(Map<String, Object> params) {
    QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
        queryWrapper.and((w) -> {
            w.eq("sku_id", key).or().like("sku_name", key);
        });
    }
    String catelogId = (String) params.get("catelogId");
    if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
        queryWrapper.eq("catalog_id", catelogId);
    }
    String brandId = (String) params.get("brandId");
    if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
        queryWrapper.eq("brand_id", brandId);
    }
    String max = (String) params.get("max");
    if (!StringUtils.isEmpty(max)) {
        try {
            BigDecimal bigDecimal = new BigDecimal(max);
            if (bigDecimal.compareTo(new BigDecimal("0")) == 1) {
                queryWrapper.le("price", max);
            }
        } catch (Exception e) {
        }
    }
    String min = (String) params.get("min");
    if (!StringUtils.isEmpty(min)) {
        queryWrapper.ge("price", min);
    }
    IPage<SkuInfoEntity> page = this.page(
            new Query<SkuInfoEntity>().getPage(params),
            queryWrapper
    );
    return new PageUtils((page));
}
相关文章
|
20天前
|
存储 JSON API
淘宝API接口实战:高效获取商品标题、分类及店铺名称
在淘宝API接口实战中,通过以下步骤高效获取商品标题、分类及店铺名称:1. 准备工作:了解淘宝开放平台文档,注册开发者账号,选择开发语言和工具。2. 获取API访问权限:申请相应权限,提供应用场景说明。3. 调用API接口:构建HTTP请求,提供必要参数。4. 解析响应数据:提取JSON数据中的所需信息。5. 数据处理和存储:进一步处理并存储数据。6. 注意事项:遵守使用规范,注意调用频率和数据安全。示例代码使用Python调用淘宝API。
|
2月前
|
XML 前端开发 Java
谷粒商城笔记+踩坑(5)——商品服务-属性分组、品牌关联分类,spu+sku+分页拦截器
SPU和SKU、属性分组的增删改查、QueryWrapper的and和or用法、获取当前品牌关联的所有分类
谷粒商城笔记+踩坑(5)——商品服务-属性分组、品牌关联分类,spu+sku+分页拦截器
|
3月前
|
数据采集 JSON API
淘系商品详情图属性sku价格解析,API接口系列
淘宝(Taobao)作为阿里巴巴集团旗下的电商平台,其商品详情图、属性、SKU和价格的采集通常不直接通过公开的API接口来实现,因为淘宝的API主要面向商家和开发者提供店铺管理、订单处理、物流查询等功能,并不直接提供商品详情页的完整数据抓取接口
|
5月前
|
存储 JSON API
批量采集抖音商品详情数据:推荐你使用API(通过商品id取商品详情商品主图sku属性)
批量采集抖音商品详情,建议使用API接口。步骤包括:注册抖音开放平台获取App Key和Secret,调用商品详情API接口传入商品ID及相关参数,解析返回的JSON获取商品信息(如名称、价格、主图和SKU)。此外,接口列表提供商品搜索、销售量查询、历史价格、订单管理等多种功能。已封装的API接口地址:c0b.cc/R4rbK2,可测试并联系获取SDK文件。
|
6月前
|
存储 数据采集 JSON
电商API分享:如何批量获取商品详情页数据(属性图价格sku视频评论)
电商API(应用程序接口)通常提供了丰富的数据获取功能,使开发者能够方便地获取商品详情页的各种数据,包括商品属性、图片、价格、SKU(库存量单位)、视频以及评论等。以下是一个基本的步骤指南,用于通过电商API批量获取商品详情页数据:
|
测试技术 API 微服务
谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)-3
谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)
68 0
|
JSON 数据格式
谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)-1
谷粒商城--SPU和SKU(分组与属性关联、发布商品、仓库服务)
54 0
|
SQL 前端开发 测试技术
谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)-1
谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)
208 0
|
前端开发 API 数据库
谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)-2
谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)
153 0
电商API接口开发系列-商品采集接口、关键字搜索接口,获取商品ID、商品主图接口
目前各大电商平台都有自己的开放平台,通过API接口开放本电商平台的相关数据和功能,以自由开放的姿态来占领更多的市场份额。也让更多的人能来电商市场分得一杯羹。 通过电商API接口可以实现获取电商平台商品数据、订单数据、上下架商品、批量处理订单、批量发货、批量购买、买家信息、卖家信息等等功能。
电商API接口开发系列-商品采集接口、关键字搜索接口,获取商品ID、商品主图接口