9.商品服务-平台属性

介绍:

 

规格参数即:基本属性--有关联关系,需要属性分组

销售属性:销售属性-没有关联关系,不需要属性分组

1.规格参数新增与vo

在查询全部的时候如果带了key值,我们也应该把key带上模糊查询

 

 

 修改queryPage方法

//分页查询,需要匹配key的模糊查询
    @Override
    public PageUtils queryPage(Map<String, Object> params, Long catlogId) {
        String key= (String) params.get("key");
        QueryWrapper<AttrGroupEntity> wrapper = new QueryWrapper<AttrGroupEntity>();
        if(!StringUtils.isEmpty(key)){
            wrapper.and((obj)->{
                obj.eq("attr_group_id",key).or().like("attr_group_name",key);
            });
        }
        if(catlogId==0){
            IPage<AttrGroupEntity> page =
                    this.page(new Query<AttrGroupEntity>().getPage(params), wrapper);
            return new PageUtils(page);
        }else{
            wrapper.eq("catelog_id",catlogId);//有id的时候才判断是否相等
            IPage<AttrGroupEntity> page =
                    this.page(new Query<AttrGroupEntity>().getPage(params), wrapper);
            return new PageUtils(page);
        }
    }

2.vo值对象:用于业务层之间的数据传递,用new关键字创建,由gc回收

在这里其实也可以叫view Object:视图对象,之前我们在实体类上添加了很多注解:例如JsonInclude,TableField这样的操作是不规范的

vo以后的作用就是:1.接收页面传递来的数据,封装对象 2.将业务处理完成的对象,封装成页面需要使用的工具

不需要任何与数据库相关的注解

Request URL: http://localhost:88/api/product/attr/save,现在的情况是,它在保存的时候,只是保存了attr,并没有保存attrgroup,为了解决这个问题,我们新建了一个vo/AttrVo.java

@Data
public class AttrVo implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 属性id
     */
    private Long attrId;
    /**
     * 属性名
     */
    private String attrName;
    /**
     * 是否需要检索[0-不需要,1-需要]
     */
    private Integer searchType;
    /**
     * 属性图标
     */
    private String icon;
    /**
     * 可选值列表[用逗号分隔]
     */
    private String valueSelect;
    /**
     * 属性类型[0-销售属性,1-基本属性
     */
    private Integer attrType;
    /**
     * 启用状态[0 - 禁用,1 - 启用]
     */
    private Long enable;
    /**
     * 所属分类
     */
    private Long catelogId;
    /**
     * 快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整
     */
    private Integer showDesc;
    
    //分组的id
    private Long attrGroupId;
    
}

3.修改attrController的save方法

改为使用Vo对象

 @RequestMapping("/save")
    //@RequiresPermissions("product:attr:save")
    public R save(@RequestBody AttrVo attr){
        attrService.saveAttr(attr);

        return R.ok();
    }

实现的方法

    @Override
    @Transactional//事务原子性
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();//这是一个po持久对象用于保存数据库信息
        BeanUtils.copyProperties(attr,attrEntity);//使用BeanUtils拷贝属性,两者属性名必须一一对应
        this.save(attrEntity);//保存基本数据
        //保存关联关系
        AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
        entity.setAttrGroupId(attr.getAttrGroupId());
        entity.setAttrId(attrEntity.getAttrId());
        relationService.save(entity);//最好是注入service
    }

这样在保存规格参数的时候就可以关联表一起保存了

4.规格参数列表

 

 @GetMapping("/base/list/{catelogId}")
    //@RequiresPermissions("product:attr:list")
    public R baseAttrList(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Long catelogId){
        PageUtils page = attrService.queryBaseAttrPage(params,catelogId);

        return R.ok().put("page", page);
    }

    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
        if(catelogId!=0){//不为0=存在,就添加eq条件
            wrapper.eq("catelog_Id",catelogId);
        }
        //由于上面有可能添加了eq所以我们下面要使用and
        String key= (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((qwrapper)->{
                qwrapper.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);//得到分页
        return new PageUtils(page);
    }

可以看到已经查询出来了,但是还有两个字段是空的

 

 从接口文档中也可以看到,需要这两个参数 catelogName和groupName

 

 自定义封装一个Vo,其实不建议用继承

@Data
public class AttrRespVo extends AttrVo implements Serializable {
    private String catelogName;//分类名字
    private String groupName;//所属分组

}

逻辑分析:

要查询这两个属性,我们目前有的东西:catelogId

那么我们就可以之间拿到catelog的service直接进行查询

需要获取groupName,我们首先得有groupId

groupId在AttrAttrgroupRelation这张表中有attr_id和group_id的对应关系

于是乎我们通过attr_id相等这一条件,查询到AttrAttrgroupRelation的group_id,再获取名字

@Autowired
    AttrAttrgroupRelationService relationService;//最好是注入service
    @Autowired
    AttrGroupService attrGroupService;
    @Autowired
    CategoryService categoryService;

 @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
        if(catelogId!=0){//不为0=存在,就添加eq条件
            wrapper.eq("catelog_Id",catelogId);
        }
        //由于上面有可能添加了eq所以我们下面要使用and
        String key= (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((qwrapper)->{
                qwrapper.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<AttrEntity> attrEntities=page.getRecords();
        List<AttrRespVo> collect = attrEntities.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);//拷贝属性
            //获得当前关联的对象
            AttrAttrgroupRelationEntity attrId = relationService.getOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                    .eq("attr_id", attrEntity.getAttrId()));//通过属性id相等查到关联对象

            if (attrId != null) {//分组关联信息有可能是空的
                //分组
                AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrId.getAttrGroupId());
                attrRespVo.setCatelogName(attrGroupEntity.getAttrGroupName());
            }
            //分类
            CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                attrRespVo.setGroupName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());
        pageUtils.setList(collect);
        return pageUtils;
    }

可以看到模糊查询,分类分组都有了

5.平台属性规格参数修改的时候回显列表

需要两个格外的属性一个是path一个是groupid

 

 

    @RequestMapping("/info/{attrId}")
    //@RequiresPermissions("product:attr:info")
    public R info(@PathVariable("attrId") Long attrId){
        AttrRespVo respVo = attrService.getAttrInfo(attrId);

        return R.ok().put("attr", respVo);
    }

  @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        //需要额外携带的东西:attrgroup_id和catelogPath
        AttrEntity attrEntity = this.getById(attrId);
        AttrRespVo respVo = new AttrRespVo();
        BeanUtils.copyProperties(attrEntity, respVo);
        //获取分组的id
        AttrAttrgroupRelationEntity one = relationService.getOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
        if (one != null) {
            Long attrGroupId = one.getAttrGroupId();
            respVo.setAttrGroupId(attrGroupId);
            //把名字也顺便带进去
            AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId);
            if(attrGroupEntity!=null){
                respVo.setGroupName(attrGroupEntity.getAttrGroupName());
            }
        }
        //获取分类的路径,这个在之前的项目里做过,所以直接调用接口
        Long[] catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId());
        respVo.setCatelogPath(catelogPath);
        //同样也可以设置分类的名字
        CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
        if(categoryEntity!=null)//每次查询之后都得判断
        respVo.setCatelogName(categoryEntity.getName());
        return respVo;
    }

6.修改更新时的关联属性

 

 在修改点击确定后,所属分类也会跟着修改了

 @RequestMapping("/update")
    //@RequiresPermissions("product:attr:update")
    public R update(@RequestBody AttrVo attr){//在修改点击确定的时候我们获得的是一个vo属性,因为不需要path,但是又需要级联更新attrgroup所以需要groupid
        attrService.updateDetail(attr);

        return R.ok();
    }

 @Transactional
    @Override
    public void updateDetail(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);//复制到数据库属性中
        this.updateById(attrEntity);//更新
        //修改分组的关联
        AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
        entity.setAttrGroupId(attr.getAttrGroupId());
        entity.setAttrId(attr.getAttrId());
        //判断是否有这一条记录,如果一开始就没有这条记录的话就应该是增加操作
        int count = relationService.count(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
        if(count==0){
            relationService.save(entity);
        }else{
            //使用这个属性替换掉表里原有的关联属性
            relationService.update(entity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));
        }
    }

 7.维护销售属性

1.显示列表

因为销售属性和基本属性基本一致所以我们用同一个方法来写

@GetMapping("/{attrType}/list/{catelogId}")
    //@RequiresPermissions("product:attr:list")
    public R baseAttrList(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Long catelogId,@PathVariable("attrType")String attrType){
        
        PageUtils page = attrService.queryBaseAttrPage(params,catelogId,attrType);
        return R.ok().put("page", page);
    }

 @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {
        //如果是基本类型,就让他查type为1的基本类型否则就查type为0的销售属性
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("attr_type", "base".equalsIgnoreCase(attrType) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.aTTR_TYPE_SALE.getCode());
        if (catelogId != 0) {//不为0=存在,就添加eq条件
            wrapper.eq("catelog_Id", catelogId);
        }
        //由于上面有可能添加了eq所以我们下面要使用and
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and((qwrapper) -> {
                qwrapper.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<AttrEntity> attrEntities = page.getRecords();
        List<AttrRespVo> collect = attrEntities.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);//拷贝属性
            //销售属性是没有attrGroup的
            if ("base".equalsIgnoreCase(attrType)) {
                //获得当前关联的对象
                AttrAttrgroupRelationEntity attrId = relationService.getOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_id", attrEntity.getAttrId()));//通过属性id相等查到关联对象
                if (attrId != null&&attrId.getAttrGroupId()!=null) {//分组关联信息有可能是空的,里面的id也有可能是空的
                    //分组
                    AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrId.getAttrGroupId());
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
            //分类
            CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());
        pageUtils.setList(collect);
        return pageUtils;
    }

 

在关联关系列表中,如果是销售属性,我们新增多给销售属性多添加一个字段,所以这一块也要判断

 @Override
    @Transactional//事务原子性
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();//这是一个po持久对象用于保存数据库信息
        BeanUtils.copyProperties(attr, attrEntity);//使用BeanUtils拷贝属性,两者属性名必须一一对应
        this.save(attrEntity);//保存基本数据
        //保存关联关系,在是基本属性的时候才保存,销售属性是没有的
        if(attr.getAttrType()== ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()&&attr.getAttrGroupId()!=null){//AttrGroupId不为空才保存
            AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            entity.setAttrGroupId(attr.getAttrGroupId());
            entity.setAttrId(attrEntity.getAttrId());
            relationService.save(entity);//最好是注入service
        }
    }

在获取信息的时候也是,如果是销售属性是没有关联信息的

@Override
    public AttrRespVo getAttrInfo(Long attrId) {
        //需要额外携带的东西:attrgroup_id和catelogPath
        AttrEntity attrEntity = this.getById(attrId);
        AttrRespVo respVo = new AttrRespVo();
        BeanUtils.copyProperties(attrEntity, respVo);
        //获取分组的id,基本信息才需要分组的id
        if(attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) 
      { AttrAttrgroupRelationEntity one = relationService.getOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId)); if (one != null) { Long attrGroupId = one.getAttrGroupId(); respVo.setAttrGroupId(attrGroupId); //把名字也顺便带进去 AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId); if (attrGroupEntity != null) { respVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } } //获取分类的路径,这个在之前的项目里做过,所以直接调用接口 Long[] catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId()); respVo.setCatelogPath(catelogPath); //同样也可以设置分类的名字 CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId()); if (categoryEntity != null)//每次查询之后都得判断 respVo.setCatelogName(categoryEntity.getName()); return respVo; }

更新信息的时候也是

  @Transactional
    @Override
    public void updateDetail(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);//复制到数据库属性中
        this.updateById(attrEntity);//更新
        if(attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            //修改分组的关联
            AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            entity.setAttrGroupId(attr.getAttrGroupId());
            entity.setAttrId(attr.getAttrId());
            //判断是否有这一条记录,如果一开始就没有这条记录的话就应该是增加操作
            int count = relationService.count(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if (count == 0) {
                relationService.save(entity);
            } else {
                //使用这个属性替换掉表里原有的关联属性
                relationService.update(entity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            }
        }
    }

我们发现,我们经常需要判断是基础属性还是销售属性,于是乎我们在common模块中添加

public class ProductConstant {
    public enum AttrEnum{
        ATTR_TYPE_BASE(1,"基本属性"),
        aTTR_TYPE_SALE(0,"销售属性");
        private int code;
        private String msg;

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        AttrEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    }
}

这样做的好处是,以后数据库修改规则了,我们只需要修改枚举类型就可以了

判断的时候如此判断

 测试:

在销售属性中添加一个数据,attr成功添加数据,但是attrattrgroupreleation表并不新增数据

8.编写属性分组的关联功能

 

返回的数据就是我们当前分组里关联到的所有基本信息(规格参数)

 

 

 @GetMapping("/{attrgroupId}/attr/relation")
    public R attrRelation(@PathVariable("attrgroupId") Long attrGroupId){
        List<AttrEntity> entities= attrService.getRelationAttr(attrGroupId);
        return R.ok().put("data",entities);
    }

 @Override
    public List<AttrEntity> getRelationAttr(Long attrGroupId) {
        List<AttrAttrgroupRelationEntity> entities = relationService.list(new QueryWrapper<AttrAttrgroupRelationEntity>()
                .eq("attr_group_id", attrGroupId));
        //我们只需要属性id就行了
        List<Long> list = entities.stream().map((attr) -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());
        //根据id集合查出所有属性信息
        if(list==null||list.size()==0){
           return null;
        }
        List<AttrEntity> res = this.listByIds(list);
        return res;
    }

此时列表就显示出来了

 

 

 9.编写批量删除功能

 

 

 添加Vo

@Data
public class AttrGroupRelationVo {
    private Long attrId;
    private Long attrGroupId;
}

编写Controller

    /**
     * 关联删除
     */
    @PostMapping("/attr/relation/delete")
    public R deleteRelation(@RequestBody AttrGroupRelationVo[] vos){//post请求有数据提交必须加上注解RequestBody
        attrService.deleteRelation(vos);
        return R.ok();
    }

 

 @Autowired
    AttrAttrgroupRelationDao relationDao;

    @Override
    public void deleteRelation(AttrGroupRelationVo[] vos) {
        //我们希望只发一次删除请求完成批量删除而不是用relationService.remove(new QueryWrapper<>().eq())
        List<AttrAttrgroupRelationEntity> collect = Arrays.asList(vos).stream().map((item) -> {
            AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(item, entity);
            return entity;
        }).collect(Collectors.toList());
        relationDao.deleteBatchRelation(collect);
    }
}

标注一个自定义属性方便来写sql

@Mapper
public interface AttrAttrgroupRelationDao extends BaseMapper<AttrAttrgroupRelationEntity> {

    void deleteBatchRelation(@Param("collect") List<AttrAttrgroupRelationEntity> collect);
}

 需要注意的是or一定要加上前后空格

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

 10.编写新建关联中显示列表的功能

当前分组能关联的肯定是本分类下的,而且还不能被其他分组所关联

 

 

 @RequestBody获取的信息在请求体中,@RequestParm获取的信息在请求头中

/**
     * 新增关联列表显示
     */
    @GetMapping("/{attrgroupId}/attr/relation")
    public R attrNoRelation(@RequestParam Map<String, Object> params,@PathVariable("attrgroupId") Long attrGroupId){
        PageUtils page= attrService.getNoRelationAttr(params,attrGroupId);
        return R.ok().put("data",page);
    }

 

 @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrGroupId) {
        //1.当前分组只能关联自己所属分类里面的所有属性
        AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId);
        Long catelogId = attrGroupEntity.getCatelogId();
        //2.当前分组只能关联别的分组没有引用的属性
        //2.1找到当前分类下的所有分组--》自己也要查,后续会连同自己的属性一起收集到collect里后进行剔除
        List<AttrGroupEntity> attrGroupEntityList = attrGroupService.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        List<Long> collect = attrGroupEntityList.stream().map((item) -> {
            return item.getAttrGroupId();//我们只需要属性组id就行了
        }).collect(Collectors.toList());
        //2.2这些分组关联的属性-->获取所有attr_group_id字段与collect集合里一致的对象
        List<AttrAttrgroupRelationEntity> relationEntities = relationService.list(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));
        List<Long> collect1 = relationEntities.stream().map((item) -> {
            return item.getAttrId();//只需要属性id就可以了
        }).collect(Collectors.toList());
        //2.3从当前分类的所有属性中筛选掉这些属性,并且不查销售属性(销售属性没有关联关系)
        QueryWrapper<AttrEntity> attrEntityQueryWrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        if(collect1!=null&&collect1.size()>0){
            attrEntityQueryWrapper.notIn("attr_id", collect1);//不为空并且大于0才进行判断
        }
        //模糊查询
        String key=(String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            attrEntityQueryWrapper.and((w)->{
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), attrEntityQueryWrapper);
        PageUtils pageUtils = new PageUtils(page);
        return pageUtils;
    }

11.新建关联中确认新增功能编写

 

 

 /**
     * 新增关联新增功能
     */
    @PostMapping("/attr/relation")
    public R addRelation(@RequestBody List<AttrGroupRelationVo> vos){
        attrAttrgroupRelationService.saveBatch(vos);
        return R.ok();
    }

@Override
    public void saveBatch(List<AttrGroupRelationVo> vos) {
        //保存修改映射
        List<AttrAttrgroupRelationEntity> collect = vos.stream().map(item -> {
            AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(item, entity);
            return entity;
        }).collect(Collectors.toList());
        this.saveBatch(collect);
    }

 

 


posted @ 2021-08-08 11:16  一拳超人的逆袭  阅读(116)  评论(0编辑  收藏  举报