规格参数详情
接口如下:
什么是规格参数?
保存规格参数
controller
/** * 保存 */ @RequestMapping("/save") public R save(@RequestBody AttrVo vo){ attrService.saveAttr(vo); return R.ok(); }
service
这里注意,因为添加规格参数的时候会有选择属性组,因为属性组和属性是通过关联关系表连接的所以要有级联操作。
在往pms_attr表插入数据的时候,pms_attr_group_relation也要插入
小bug:这里有个注意点,当添加规格参数的时候如果没有指定规格参数所属分组,那么就不应该在关联表中保存关联关系!!!
@Override public void saveAttr(AttrVo attr) { AttrEntity attrEntity = new AttrEntity(); //1.将前端接收数据的对象vo赋值给attrEntity对象,从而更新数据库 BeanUtils.copyProperties(attr, attrEntity); this.save(attrEntity); if (attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId() != null) { //2.保存关联关系 //因为属性组和属性是通过关联关系表连接的 AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attr.getAttrGroupId()); relationEntity.setAttrId(attrEntity.getAttrId()); relationService.save(relationEntity); } }
显示规格参数
controller
/** * 显示规格参数 */ @GetMapping("/base/list/{catelogId}") public R baseAttrList(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Integer catelogId) { PageUtils page = attrService.queryBaseAttrPage(params, catelogId); return R.ok().put("page", page); }
service
//分页查询规格参数 @Override public PageUtils queryBaseAttrPage(Map<String, Object> params, Integer catelogId) { QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>(); if (catelogId != 0) { //如果不是一级分类,那么查询的时候加上where catelog_id = ? wrapper.eq("catelog_id", catelogId); } //多条件模糊查询 //搜索框里的key不但可以对catelog_id进行模糊查询,对attr_name也模糊查询 String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { wrapper.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); return pageUtils; }
测试
如下:
这些属性的分类和所属分组怎么查呢?
规格参数表(pms_attr)中,有所属分类的信息,可以直接调用分类的service进行查询
那分组信息怎么查询呢?规格参数表中没有所属分类相关的信息…
这里我们就要借助第三张表,属性和分组表(pms_attr_attrgroup_relation)进行查询
通过规格参数表(pms_attr)获得attr_id,之后在调用属性和分组表的service获得属性和分组表的实体类,从而获得该属性的分组
下面通过stream流的方式,通过map给list集合中的每一项做映射给新实体类(AttrRespVo)赋值,最后返回AttrRespVo
小bug:这里显示规格参数的时候,会显示规格。参数对应的分组、分类,那么如果它们查出对象分组id或分类id为空那就不设置名字if (attrId != null && attrId.getAttrGroupId() != null) {…}
//分页查询规格参数 @Override public PageUtils queryBaseAttrPage(Map<String, Object> params, String type, Integer catelogId) { QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>() .eq("attr_type", "base".equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode()); if (catelogId != 0) { //如果不是一级分类,那么查询的时候加上where catelog_id = ? //IgnoreCase忽略大小写 wrapper.eq("catelog_id", catelogId); } //多条件模糊查询 //搜索框里的key不但可以对catelog_id进行模糊查询,对attr_name也模糊查询 String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { wrapper.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> list = page.getRecords(); // .map()这个方法是对被筛选过后的流进行映射,一般是对属性进行赋值。 List<AttrRespVo> resultList = list.stream().map(item -> { AttrRespVo attrRespvo = new AttrRespVo(); BeanUtils.copyProperties(item, attrRespvo); //设置分类和分组的名字 if ("base".equalsIgnoreCase(type)) { AttrAttrgroupRelationEntity attrId = relationService. getOne(new QueryWrapper<AttrAttrgroupRelationEntity>() .eq("attr_id", item.getAttrId())); if (attrId != null && attrId.getAttrGroupId() != null) { //attrgroupRelationEntity.getAttrGroupId()也可以,这里可以直接放进去对象 AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrId.getAttrGroupId()); attrRespvo.setGroupName(attrGroupEntity.getAttrGroupName()); } } CategoryEntity categoryEntity = categoryService.getById(item.getCatelogId()); if (categoryEntity != null) { attrRespvo.setCatelogName(categoryEntity.getName()); } //返回最后的封装结果 return attrRespvo; }).collect(Collectors.toList()); //返回的结果是一个集合 pageUtils.setList(resultList); // 返回分页后的集合对象 return pageUtils; }
AttrRespVo
@Data public class AttrRespVo extends AttrVo { private String catelogName; private String groupName; }
测试
规格参数回显
可以看出所属分类和分组都是由这条请求查询的,那么我们改这个接口功能就行
相当于在原来查询基础上返回分类路径信息,分组信息
controller
/** * 信息 */ @RequestMapping("/info/{attrId}") public R info(@PathVariable("attrId") Long attrId) { AttrRespVo respVo = attrService.getAttrInfo(attrId); return R.ok().put("attr", respVo); }
service
@Override public AttrRespVo getAttrInfo(Long attrId) { AttrRespVo respVo = new AttrRespVo(); AttrEntity attrEntity = this.getById(attrId); BeanUtils.copyProperties(attrEntity, respVo); /** * 设置分组信息 */ AttrAttrgroupRelationEntity attrgroupRelationEntity = relationService. getOne(new QueryWrapper<AttrAttrgroupRelationEntity>() .eq("attr_id", attrEntity.getAttrId())); if (attrgroupRelationEntity != null){ respVo.setAttrGroupId(attrgroupRelationEntity.getAttrGroupId()); Long attrGroupId = attrgroupRelationEntity.getAttrGroupId(); AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId); if (attrGroupEntity != null) { respVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } /** * 设置分类信息 */ Long catelogId = attrEntity.getCatelogId(); //有了分类的完整路径,接下来就设置分类名字 Long[] catelogPath = categoryService.findCatelogPath(catelogId); respVo.setCatelogPath(catelogPath); //获得分类名字 CategoryEntity categoryEntity = categoryService.getById(catelogId); if (categoryEntity != null) { respVo.setCatelogName(categoryEntity.getName()); } return respVo; }
测试
修改Or增加
提交修改分类和分组是无效的?
更改用的还是默认的update方法,所以我们改update接口!
controller
/** * 修改 */ @RequestMapping("/update") public R update(@RequestBody AttrVo attr) { attrService.updateAttr(attr); return R.ok(); }
service
这里做了优化,对于规格参数中没有所属分组的,如果指定了不在是修改而是添加!
怎么判断规格参数有没有所属分组呢?
拿attr_id去pms_attr_attrgroup_relation表中查询,如果改attr_id存在与该表,那就修改关联关系
如果没有数据,那么就在此表添加数据!
@Transactional @Override public void updateAttr(AttrVo attr) { AttrEntity attrEntity = new AttrEntity(); BeanUtils.copyProperties(attr, attrEntity); this.updateById(attrEntity); //修改分组关联 AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity(); attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId()); attrAttrgroupRelationEntity.setAttrId(attr.getAttrId()); //统计attr_id的关联属性,如果没有初始分组,则进行添加操作;有则进行修改操作 Integer count = relation.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId())); if (count > 0) { relation.update(attrAttrgroupRelationEntity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId())); } else { relation.insert(attrAttrgroupRelationEntity); } }
spu规格维护
出现400页面,在数据库添加
INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (76, 37, '规格维护', 'product/attrupdate', '', 2, 'log', 0); 更新index.js,哪里更新?找老师的源码
controller
@PostMapping("/update/{spuId}") public R updateSpuAttr(@PathVariable("spuId") Long spuId, @RequestBody List<ProductAttrValueEntity> entities){ productAttrValueService.updateSpuAttr(spuId,entities); return R.ok(); }
impl
这里的修改其实是先把原来的spu_id下的属性都删除掉
之后在把前端传来的属性集合进行批量保存
@Transactional(rollbackFor = Exception.class) @Override public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) { //1、删除spuId之前对应的所有属性 this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId)); //2、添加商品规格信息 List<ProductAttrValueEntity> collect = entities.stream().map(item -> { item.setSpuId(spuId); return item; }).collect(Collectors.toList()); //批量新增 this.saveBatch(collect); }
销售属性详情
显示销售属性
如图http://localhost:88/api/product/attr/sale/list/0?t=1660181297434&page=1&limit=10&key=这个接口有问题!
所以我们就去后端改这个接口即可!
controller
规格参数和销售参数的区别在于type的值,type为 1是规格参数,type为0是销售参数
这里采用一个方法当两个来用!
@GetMapping("/{attrType}/list/{catelogId}") public R baseAttrList(@RequestParam Map<String, Object> params, @PathVariable("attrType") String type, @PathVariable("catelogId") Integer catelogId) { PageUtils page = attrService.queryBaseAttrPage(params, type, catelogId); return R.ok().put("page", page); }
service
在原来对规格参数的基础上加了限制条件,如果是规格参数那就是WHERE attr_type = 1,否则就是WHERE attr_type = 0;
下面的逻辑和查询规格参数一致,都要模糊查询
这里为了使代码更通用,1和0的值我们写一个常量来控制,如过后期换值了我们直接更改常量的值即可
ProductConstant
package com.caq.common.constant; public class ProductConstant { public enum AttrEnum{ ATTR_TYPE_BASE(1,"基本属性"), ATTR_TYPE_SALE(0,"销售属性"); private int code; private String msg; AttrEnum(int code,String msg){ this.code = code; this.msg = msg; } public int getCode(){ return code; } public String getMsg(){ return msg; } } }
在原来对规格参数的基础上加了限制条件,如果是规格参数那就是WHERE attr_type = 1,否则就是WHERE attr_type = 0;
@Override public PageUtils queryBaseAttrPage(Map<String, Object> params, String type, Integer catelogId) { QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>() .eq("attr_type", "base".equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode()); if (catelogId != 0) { //如果不是一级分类,那么查询的时候加上where catelog_id = ? //IgnoreCase忽略大小写 wrapper.eq("catelog_id", catelogId); } //多条件模糊查询 //搜索框里的key不但可以对catelog_id进行模糊查询,对attr_name也模糊查询 String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { wrapper.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> list = page.getRecords(); // .map()这个方法是对被筛选过后的流进行映射,一般是对属性进行赋值。 List<AttrRespVo> resultList = list.stream().map(item -> { AttrRespVo attrRespvo = new AttrRespVo(); BeanUtils.copyProperties(item, attrRespvo); AttrAttrgroupRelationEntity attrgroupRelationEntity = relationService. getOne(new QueryWrapper<AttrAttrgroupRelationEntity>() .eq("attr_id", item.getAttrId())); if (attrgroupRelationEntity != null) { //attrgroupRelationEntity.getAttrGroupId()也可以,这里可以直接放进去对象 AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrgroupRelationEntity); attrRespvo.setGroupName(attrGroupEntity.getAttrGroupName()); } CategoryEntity categoryEntity = categoryService.getById(item.getCatelogId()); if (categoryEntity != null) { attrRespvo.setCatelogName(categoryEntity.getName()); } //返回最后的封装结果 return attrRespvo; }).collect(Collectors.toList()); //返回的结果是一个集合 pageUtils.setList(resultList); // 返回分页后的集合对象 return pageUtils; }
销售属性回显
可以看到,销售属性回显是不需要所属分组的
但是销售属性和规格参数用的是同一个回显方法,我们也进行更改,只有是规格参数的时候才进行分组回显!
在原分组回显的逻辑上加上判断,后面逻辑不变!
if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) { ... }
修改销售属性
销售属性和规格参数用的是同一个修改方法,销售属性进行修改时,会对关联表进行一个级联更新,但销售属性不需要
所以也在对关联表级联更新的时候进行判断,只有销售属性修改的时候才进行级联更新!
if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) { ... }
保存销售属性
销售属性和规格参数用的是同一个保存方法,销售属性进行保存时,会对关联表进行一个级联保存,但销售属性不需要
所以也在对关联表级联保存的时候进行判断,只有销售属性保存的时候才进行级联保存!
if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) { ... }