商品服务——品牌管理、平台属性(规格属性、销售属性)

一、完善品牌管理功能

1、分页信息有误:

后端的分页接口返回数据有问题,因为我们使用 mybatis-plus 要进行分页,需要引入分页插件:

https://mp.baomidou.com/guide/page.html

方法很简单,直接向容器中注入PaginationInterceptor即可:

package com.jiguiquan.zidanmall.product.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@MapperScan("com.jiguiquan.zidanmall.product.dao")
public class MybatisConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(1000);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

然后重启服务,刷新页面就可以了,而且其他的页面也自动都完成了;

2、完善品牌查询时候的模糊查询功能

@Override
public PageUtils queryPage(Map<String, Object> params) {
    //获取key
    String key = params.get("key").toString();
    QueryWrapper<BrandEntity> wrapper = new QueryWrapper<>();
    if (StringUtils.isNoneBlank(key)){
        wrapper.and(obj -> obj.eq("brand_id", key).or().like("name", key));
    }
    IPage<BrandEntity> page = this.page(new Query<BrandEntity>().getPage(params), wrapper);
    return new PageUtils(page);
}

3、上传一些有用数据待用;

同时,在前端加上“关联分类”的按钮功能;

50.jpg


二、完成关联分类功能

在电商系统中,每一个品牌都应该拥有自己的分类;

同时,一个品牌可能不止会关联一个分类,比如小米:可以关联“手机”分类,同时小米还有电视,所以也可能关联“家用电器”分类;

所以,“品牌”和“分类”之间必定是N:N的关系,需要一张中间表;

品牌-分类 关联的模块为:product/categorybrandrelation 

1、查询关联列表:

@GetMapping("/catelog/list")
//@RequiresPermissions("product:categorybrandrelation:list")
public R catelogList(@RequestParam("brandId") Long brandId){
    List<CategoryBrandRelationEntity> data = categoryBrandRelationService.list(new QueryWrapper<CategoryBrandRelationEntity>().eq("brand_id", brandId));
    return R.ok().put("data", data);
}

2、新增:略

3、在修改brand和category的时候,需要更新categorybrandrelation表中的名称:

BrandServiceImpl.java:

@Transactional
@Override
public void updateDetail(BrandEntity brand) {
    this.updateById(brand);
    //更新其他表中的字段
    categoryBrandRelationService.updateBrandName(brand.getBrandId(), brand.getName());
}

CategoryBrandRelationServiceImpl.java:

@Override
public void updateBrandName(Long brandId, String name) {
    CategoryBrandRelationEntity relationEntity = new CategoryBrandRelationEntity();
    relationEntity.setBrandId(brandId);
    relationEntity.setBrandName(name);
    this.update(relationEntity, new UpdateWrapper<CategoryBrandRelationEntity>().eq("brand_id", brandId));
}

关联分类功能就全部完成了;

51.jpg


三、平台属性——规格参数

1、完成新增“规格参数”功能:

Service层核心代码:

@Transactional
@Override
public void saveAttr(AttrVo attrVo) {
    AttrEntity attrEntity = new AttrEntity();
    BeanUtils.copyProperties(attrVo, attrEntity);
    this.save(attrEntity);
    //保存属性与属性分组关联关系
    AttrAttrgroupRelationEntity relation = new AttrAttrgroupRelationEntity();
    relation.setAttrGroupId(attrVo.getAttrGroupId());
    relation.setAttrId(attrEntity.getAttrId());
    attrAttrgroupRelationService.save(relation);
}

其中AttrVo是在AttrEntity上增加传输值attrGroupId,用来完成attr和attrGroup的关系绑定;

52.jpg

新增成功!

2、获取指定分类的规格参数分页列表

 GET  /product/attr/base/list/{catelogId}  

Service层核心代码:

@Override
public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
    QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if (catelogId != 0){
        wrapper.eq("catelog_id", catelogId);
    }
    if (StringUtils.isNoneBlank(key)){
        wrapper.and(obj -> obj.eq("attr_id", key).or().like("attr_name", key));
    }
    IPage<AttrEntity> page = this.page(
            new Query<AttrEntity>().getPage(params), wrapper);

    PageUtils pageUtils = new PageUtils(page);
    List<AttrRespVo> respVos = page.getRecords().stream().map(a -> {
        AttrRespVo attrRespVo = new AttrRespVo();
        BeanUtils.copyProperties(a, attrRespVo);
        AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", a.getAttrId()));
        if (relationEntity != null) {
            AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
            attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
        CategoryEntity categoryEntity = categoryDao.selectById(a.getCatelogId());
        if (categoryEntity != null) {
            attrRespVo.setCatelogName(categoryEntity.getName());
        }
        return attrRespVo;
    }).collect(Collectors.toList());
    pageUtils.setList(respVos);
    return pageUtils;
}

效果如下:

53.jpg

3、“规格参数”的修改功能,能够回显所属分类的“级联菜单”;

  GET  /product/attr/info/{attrId}

Service层核心代码:

@Override
public AttrRespVo getAttrInfo(Long attrId) {
    AttrRespVo attrRespVo = new AttrRespVo();
    AttrEntity attrEntity = this.getById(attrId);
    BeanUtils.copyProperties(attrEntity, attrRespVo);
    //查询分组名称
    AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
    if (relationEntity != null) {
        attrRespVo.setAttrGroupId(relationEntity.getAttrGroupId());
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
        if (attrGroupEntity != null){
            attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
    }
    //查询分类的详细路径catelogPath
    if (attrEntity.getCatelogId() != 0){
        Long[] catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId());
        attrRespVo.setCatelogPath(catelogPath);
    }
    return attrRespVo;
}

4、“规格参数”修改接口:

Service层核心代码:

@Override
public void updateAttr(AttrVo attrVo) {
    AttrEntity attrEntity = new AttrEntity();
    BeanUtils.copyProperties(attrVo, attrEntity);
    this.updateById(attrEntity);
    //修改分组关联
    AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
    relationEntity.setAttrId(attrVo.getAttrId());
    relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
    Integer count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
    if (count > 0){
        attrAttrgroupRelationDao.update(relationEntity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
    }else {
        attrAttrgroupRelationDao.insert(relationEntity);
    }
}

四、平台属性——销售属性

销售属性和基本属性一样,使用的是attr表,唯一不一样的地方是:

attr_type:1基本属性;0销售属性;

还有当为销售属性的时候是没有属性分组的概念的,所以在Service的代码中多次要进行判断:

@Override
public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
    QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    wrapper.eq("attr_type", "base".equalsIgnoreCase(type)? 1 : 0);
    if (catelogId != 0){
        wrapper.eq("catelog_id", catelogId);
    }
    if (StringUtils.isNoneBlank(key)){
        wrapper.and(obj -> obj.eq("attr_id", key).or().like("attr_name", key));
    }

    IPage<AttrEntity> page = this.page(
            new Query<AttrEntity>().getPage(params), wrapper);

    PageUtils pageUtils = new PageUtils(page);
    List<AttrRespVo> respVos = page.getRecords().stream().map(a -> {
        AttrRespVo attrRespVo = new AttrRespVo();
        BeanUtils.copyProperties(a, attrRespVo);
        //设置分组信息,只有基本属性才有分组
        if ("base".equalsIgnoreCase(type)){
            AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", a.getAttrId()));
            if (relationEntity != null) {
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
            }
        }
        //设置分类信息
        CategoryEntity categoryEntity = categoryDao.selectById(a.getCatelogId());
        if (categoryEntity != null) {
            attrRespVo.setCatelogName(categoryEntity.getName());
        }
        return attrRespVo;
    }).collect(Collectors.toList());
    pageUtils.setList(respVos);
    return pageUtils;
}

@Override
public AttrRespVo getAttrInfo(Long attrId) {
    AttrRespVo attrRespVo = new AttrRespVo();
    AttrEntity attrEntity = this.getById(attrId);
    BeanUtils.copyProperties(attrEntity, attrRespVo);
    //查询分组名称
    if (attrEntity.getAttrType() == 1){
        AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
        if (relationEntity != null) {
            attrRespVo.setAttrGroupId(relationEntity.getAttrGroupId());
            AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
            if (attrGroupEntity != null){
                attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
            }
        }
    }
    //查询分类的详细路径catelogPath
    if (attrEntity.getCatelogId() != 0){
        Long[] catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId());
        attrRespVo.setCatelogPath(catelogPath);
    }
    return attrRespVo;
}

@Override
public void updateAttr(AttrVo attrVo) {
    AttrEntity attrEntity = new AttrEntity();
    BeanUtils.copyProperties(attrVo, attrEntity);
    this.updateById(attrEntity);
    //修改分组关联
    if (attrVo.getAttrType() == 1){
        AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
        relationEntity.setAttrId(attrVo.getAttrId());
        relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
        Integer count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
        if (count > 0){
            attrAttrgroupRelationDao.update(relationEntity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
        }else {
            attrAttrgroupRelationDao.insert(relationEntity);
        }
    }
}

五、分组关联基本属性

再来回顾一下这张图:我们需要将“属性分组”与“属性”建立关系:

SPU_SKU.jpg

1、获取属性分组关联的所有基本属性:——销售属性没有分组信息

  GET  /product/attrgroup/{attrgroupId}/attr/relation  

Service层核心代码:

//根据分组Id查找所有关联的基本属性————销售属性没有分组信息
@Override
public List<AttrEntity> getRelationAttr(Long attrgroupId) {
    List<AttrAttrgroupRelationEntity> relations = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));
    List<Long> ids = relations.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());

    return (List<AttrEntity>) this.listByIds(ids);
}

2、删除属性与分组的关联关系:

  POST /product/attrgroup/attr/relation/delete  

AttrGroupController.java:

@PostMapping("/attr/relation/delete")
public R deleteRelation(@RequestBody AttrGroupRelationVo[] vos){
    attrService.deleteRelation(vos);
    return R.ok();
}

AttrServiceImpl.java:

@Override
public void deleteRelation(AttrGroupRelationVo[] vos) {
    List<AttrAttrgroupRelationEntity> collect = Arrays.asList(vos).stream().map(r -> {
        AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
        BeanUtils.copyProperties(r, relationEntity);
        return relationEntity;
    }).collect(Collectors.toList());
    attrAttrgroupRelationDao.deleteBatchRelation(collect);
}

Dao层Mapper中遍历:可直接批量删除记录:

<delete id="deleteBatchRelation">
    delete from `pms_attr_attrgroup_relation` where
    <foreach collection="entities" item="item" separator=" or ">
        (attr_id = #{item.attrId} and attr_group_id = #{item.attrGroupId})
    </foreach>
</delete>

3、新增关联时,先查询出当前未跟自己关联的属性列表:

且所关联的属性所属分类 必须 与属性分组所属分类 一样;即catelogId一样;

  GET    /product/attrgroup/{attrgroupId}/noattr/relation  

Service层核心代码:

/**
 * 获取当前分组可以关联的基本属性列表:
 * 1、属性必须与本分组属于同一个分类;
 * 2、这个属性,必须没有被“本分类”下的“其他分组”关联过
 * @param params
 * @param attrgroupId
 * @return
 */
@Override
public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
    Long catelogId = attrGroupEntity.getCatelogId();
    //1、获取当前“分类”下的所有“其它”分组
    List<AttrGroupEntity> groups = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
    //2、查找到这些分组关联的所有属性
    List<Long> groupIds = groups.stream().map(AttrGroupEntity::getAttrGroupId).collect(Collectors.toList());
    List<AttrAttrgroupRelationEntity> binds = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", groupIds));
    //3、分页查询出那些“本分类下”,且不再binds中的基本属性列表
    List<Long> collect = binds.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
    QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type", 1);
    if (!CollectionUtils.isEmpty(collect)){
        wrapper.notIn("attr_id", collect);
    }
    String key = params.get("key").toString();
    if (StringUtils.isNoneBlank(key)){
        wrapper.and(obj -> obj.eq("attr_id", key).or().like("attr_name", key));
    }
    IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
    return new PageUtils(page);
}

4、新增“属性分组”与“属性”的关联:

  POST /product/attrgroup/attr/relation  

Service层核心代码如下:

@Override
public void addRelations(AttrGroupRelationVo[] vos) {
    List<AttrAttrgroupRelationEntity> collect = Arrays.asList(vos).stream().map(v -> {
        AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
        entity.setAttrId(v.getAttrId());
        entity.setAttrGroupId(v.getAttrGroupId());
        return entity;
    }).collect(Collectors.toList());
    this.saveBatch(collect);
}

最终效果:

54.jpg

至此,平台属性(规格属性、销售属性)部分的代码就全部实现了:

55.jpg

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐