九、属性分组、平台属性--谷粒商城
一、快速导入导航数据
打开数据库gulimall_admin命令行界面,
导入sql文件
二、快速整合前端
将modules下两个文件与自己的前端项目替换
项目接口文档:https://easydoc.net/s/78237135/ZUqEdvA4/4XuREIJe
2 属性分组
2.1获取分类属性分组
2.1.1 后端调试
controller
/** * 列表 传一个三级目录id查出其下的数据 */ @RequestMapping("/list/{catelogId}") //接受一个map 的 参数params 和catelogId public R list(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Long catelogId){ //调用service层方法 PageUtils page = attrGroupService.queryPage(params,catelogId); return R.ok().put("page", page); }
Service
public interface AttrGroupService extends IService<AttrGroupEntity> { PageUtils queryPage(Map<String, Object> params); PageUtils queryPage(Map<String, Object> params, Long catelogId); }
ServiceImpl
// 请求参数 params // { // page: 1,//当前页码 // limit: 10,//每页记录数 // sidx: 'id',//排序字段 // order: 'asc/desc',//排序方式 // key: '华为'//检索关键字 // } @Override public PageUtils queryPage(Map<String, Object> params, Long catelogId) { //1 首先拿到传过来参数中的key对应的参数 String key = (String) params.get("key"); //select * from pms_attr_group where catelog_id=? and (attr_group_id=key or attr_group_name like %key%) //2 创造一个对应实体类的queryWrapper QueryWrapper<AttrGroupEntity> wrapper = new QueryWrapper<AttrGroupEntity>(); //3 如果key关键字对应的不为空的话 if(!StringUtils.isEmpty(key)){ //要满足and (attr_group_id=key or attr_group_name like %key%) wrapper.and((obj)->{ obj.eq("attr_group_id",key).or().like("attr_group_name",key); }); } //4 如果传来的catelogId为0 if( catelogId == 0){ //直接根据params和wrapper生成page //Query utils不过是把params 变为 page IPage<AttrGroupEntity> page = this.page(new Query<AttrGroupEntity>().getPage(params), wrapper); //把Ipage对象通过PageUtils进行处理 处理成我们自定义的字段返回给前端 return new PageUtils(page); }else { // 5 如果传来的cateLogId不为0 wrapper再次匹配这个字段 //Query utils不过是把params 变为 page wrapper.eq("catelog_id",catelogId); IPage<AttrGroupEntity> page = this.page(new Query<AttrGroupEntity>().getPage(params), wrapper); //把Ipage对象通过PageUtils进行处理 处理成我们自定义的字段返回给前端 return new PageUtils(page); } }
2.2分组新增&级联选择器
2.2.1我们在添加属性分组上
https://element.eleme.cn/#/zh-CN/component/cascader
<el-form-item label="所属分类id" prop="catelogId"> <!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input>--> <el-cascader v-model="dataForm.catelogIds" :options="categorys" :props="props"></el-cascader> </el-form-item>
:options=“categorys”
代表选择器的数据来源
我们访问catagoty controller来获取并对其赋值
created () { this.getMenus() }, methods: { getMenus() { this.$http({ url: this.$http.adornUrl("/product/category/list/tree"), method: 'get' }).then(({ data }) => { this.categorys = data.data; }); },
:props="props"绑定属性设置
value是什么
显示的name是什么
子节点是什么
data () { return { props:{ value:"catId", label:"name", children:"children" },
由于我们的三级目录仍然包含children[]空集合
因此我们要在后端进行设置
否则级联选择器在三级目录后会跟上一个空目录
但我们选择三级目录级联选择器的value值是一个数组
因此我们在添加时要选择最后一个值
前端总代码:
<template> <el-dialog :title="!dataForm.attrGroupId ? '新增' : '修改'" :close-on-click-modal="false" :visible.sync="visible"> <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px"> <el-form-item label="组名" prop="attrGroupName"> <el-input v-model="dataForm.attrGroupName" placeholder="组名"></el-input> </el-form-item> <el-form-item label="排序" prop="sort"> <el-input v-model="dataForm.sort" placeholder="排序"></el-input> </el-form-item> <el-form-item label="描述" prop="descript"> <el-input v-model="dataForm.descript" placeholder="描述"></el-input> </el-form-item> <el-form-item label="组图标" prop="icon"> <el-input v-model="dataForm.icon" placeholder="组图标"></el-input> </el-form-item> <el-form-item label="所属分类id" prop="catelogId"> <!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input>--> <el-cascader v-model="dataForm.catelogIds" :options="categorys" :props="props"></el-cascader> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="visible = false">取消</el-button> <el-button type="primary" @click="dataFormSubmit()">确定</el-button> </span> </el-dialog> </template> <script> export default { data () { return { props:{ value:"catId", label:"name", children:"children" }, categorys:[], visible: false, dataForm: { attrGroupId: 0, attrGroupName: '', sort: '', descript: '', icon: '', catelogIds: [], catelogId: 0 }, dataRule: { attrGroupName: [ { required: true, message: '组名不能为空', trigger: 'blur' } ], sort: [ { required: true, message: '排序不能为空', trigger: 'blur' } ], descript: [ { required: true, message: '描述不能为空', trigger: 'blur' } ], icon: [ { required: true, message: '组图标不能为空', trigger: 'blur' } ], catelogId: [ { required: true, message: '所属分类id不能为空', trigger: 'blur' } ] } } }, created () { this.getMenus() }, methods: { getMenus() { this.$http({ url: this.$http.adornUrl("/product/category/list/tree"), method: 'get' }).then(({ data }) => { this.categorys = data.data; }); }, init (id) { this.dataForm.attrGroupId = id || 0 this.visible = true this.$nextTick(() => { this.$refs['dataForm'].resetFields() if (this.dataForm.attrGroupId) { this.$http({ url: this.$http.adornUrl(`/product/attrgroup/info/${this.dataForm.attrGroupId}`), method: 'get', params: this.$http.adornParams() }).then(({data}) => { if (data && data.code === 0) { this.dataForm.attrGroupName = data.attrGroup.attrGroupName this.dataForm.sort = data.attrGroup.sort this.dataForm.descript = data.attrGroup.descript this.dataForm.icon = data.attrGroup.icon this.dataForm.catelogId = this.dataForm.catelogIds[2] } }) } }) }, // 表单提交 dataFormSubmit () { this.$refs['dataForm'].validate((valid) => { if (valid) { this.$http({ url: this.$http.adornUrl(`/product/attrgroup/${!this.dataForm.attrGroupId ? 'save' : 'update'}`), method: 'post', data: this.$http.adornData({ 'attrGroupId': this.dataForm.attrGroupId || undefined, 'attrGroupName': this.dataForm.attrGroupName, 'sort': this.dataForm.sort, 'descript': this.dataForm.descript, 'icon': this.dataForm.icon, 'catelogId': this.dataForm.catelogIds[2] }) }).then(({data}) => { if (data && data.code === 0) { this.$message({ message: '操作成功', type: 'success', duration: 1500, onClose: () => { this.visible = false this.$emit('refreshDataList') } }) } else { this.$message.error(data.msg) } }) } }) } } } </script>
2.2.2分组修改-级联选择器回显
我们可以让后端返回我们需要的这个数据
1 实体类修改(AttrGroupEntity)
新增一个字段 这个字段就是我们回显需要的数据
/** * 修改组时候的回显需要的数据 */ @TableField(exist = false) private Long[] catelogPath
controller
@RequestMapping("/info/{attrGroupId}") //@RequiresPermissions("product:attrgroup:info") public R info(@PathVariable("attrGroupId") Long attrGroupId){ //根据attrGroupId查出对应的实体类 AttrGroupEntity attrGroup = attrGroupService.getById(attrGroupId); //从实体类中获取catelogId Long catelogId = attrGroup.getCatelogId(); //调用categoryService categoryService 查出 路径 Long[] path = categoryService.findCatelogPath(catelogId); //把路径设置到其中 返回给前端 attrGroup.setCatelogPath(path); return R.ok().put("attrGroup", attrGroup); }
categroyServiceImpl修改
@Override public Long[] findCatelogPath(Long catelogId) { //新建一个ArrayList集合 接受Long List<Long> paths = new ArrayList<>(); //调用方法找到完整路径[225,22,2] List<Long> parentPath = findParentPath(catelogId, paths); //调用逆序方法获得正确顺序[2,25,225] Collections.reverse(parentPath); return parentPath.toArray(new Long[parentPath.size()]); } /** * 找到一个三级目录对应的完整路径 [2,25,225] /电器/好电器/手机 */ private List<Long> findParentPath(Long catelogId,List<Long> paths){ //1、收集当前节点id paths.add(catelogId); //2 根据当前节点ID拿到其对应的实体类 CategoryEntity byId = this.getById(catelogId); //3 当实体类父id不为0继续调用这个方法 if(byId.getParentCid()!=0){ findParentPath(byId.getParentCid(),paths); } //4 跳出递归循环返回数据 return paths; }
前端修改
绑定diglog事件:关闭dialog时清空Path 不影响我们新增时的操作
methods: { dialogClose(){ this.dataForm.catelogPath = [] },
2.3品牌管理 品牌分类关联与级联更新
2.3.1新建MP配置文件
配置分页插件
@Configuration @EnableTransactionManagement //开启事务 @MapperScan("com.atguigu.gulimall.product.dao") public class MybatisPlusConfig { //引入分页插件 @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false paginationInterceptor.setOverflow(true); // 设置最大单页限制数量,默认 500 条,-1 不受限制 paginationInterceptor.setLimit(1000); return paginationInterceptor; } }
2.3.2品牌管理中的搜索生效
来到list的serviceimpl层加一些代码
@Service("brandService") public class BrandServiceImpl extends ServiceImpl<BrandDao, BrandEntity> implements BrandService { @Override public PageUtils queryPage(Map<String, Object> params) { //参数列表中拿关键字 String key = (String) params.get("key"); QueryWrapper<BrandEntity> brandEntityQueryWrapper = new QueryWrapper<>(); if (StringUtils.isNotEmpty(key)){ brandEntityQueryWrapper.eq("brand_id",key).or().like("name",key); } IPage<BrandEntity> page = this.page( new Query<BrandEntity>().getPage(params), brandEntityQueryWrapper ); return new PageUtils(page); } }
2.3.3让品牌管理的关联分类生效
编写两个controller
@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); }
@RequestMapping("/save")
//@RequiresPermissions("product:categorybrandrelation:save")
public R save(@RequestBody CategoryBrandRelationEntity categoryBrandRelation){
categoryBrandRelationService.saveDetail(categoryBrandRelation);
return R.ok();
}
Service
public interface CategoryBrandRelationService extends IService<CategoryBrandRelationEntity> { PageUtils queryPage(Map<String, Object> params); void saveDetail(CategoryBrandRelationEntity categoryBrandRelation); }
serviceimpl
package com.atguigu.gulimall.product.service.impl; import com.atguigu.gulimall.product.dao.BrandDao; import com.atguigu.gulimall.product.dao.CategoryDao; import com.atguigu.gulimall.product.entity.BrandEntity; import com.atguigu.gulimall.product.entity.CategoryEntity; import com.atguigu.gulimall.product.service.BrandService; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.atguigu.common.utils.PageUtils; import com.atguigu.common.utils.Query; import com.atguigu.gulimall.product.dao.CategoryBrandRelationDao; import com.atguigu.gulimall.product.entity.CategoryBrandRelationEntity; import com.atguigu.gulimall.product.service.CategoryBrandRelationService; @Service("categoryBrandRelationService") public class CategoryBrandRelationServiceImpl extends ServiceImpl<CategoryBrandRelationDao, CategoryBrandRelationEntity> implements CategoryBrandRelationService { @Autowired BrandDao brandDao; @Autowired CategoryDao categoryDao; @Autowired CategoryBrandRelationDao relationDao; @Autowired BrandService brandService; @Override public PageUtils queryPage(Map<String, Object> params) { IPage<CategoryBrandRelationEntity> page = this.page( new Query<CategoryBrandRelationEntity>().getPage(params), new QueryWrapper<CategoryBrandRelationEntity>() ); return new PageUtils(page); } @Override public void saveDetail(CategoryBrandRelationEntity categoryBrandRelation) { Long brandId = categoryBrandRelation.getBrandId(); Long catelogId = categoryBrandRelation.getCatelogId(); //1、查询详细名字 BrandEntity brandEntity = brandDao.selectById(brandId); CategoryEntity categoryEntity = categoryDao.selectById(catelogId); categoryBrandRelation.setBrandName(brandEntity.getName()); categoryBrandRelation.setCatelogName(categoryEntity.getName()); this.save(categoryBrandRelation); } @Override public void updateBrand(Long brandId, String name) { CategoryBrandRelationEntity relationEntity = new CategoryBrandRelationEntity(); relationEntity.setBrandId(brandId); relationEntity.setBrandName(name); this.update(relationEntity,new UpdateWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId)); } @Override public void updateCategory(Long catId, String name) { this.baseMapper.updateCategory(catId,name); } @Override public List<BrandEntity> getBrandsByCatId(Long catId) { List<CategoryBrandRelationEntity> catelogId = relationDao.selectList(new QueryWrapper<CategoryBrandRelationEntity>().eq("catelog_id", catId)); List<BrandEntity> collect = catelogId.stream().map(item -> { Long brandId = item.getBrandId(); BrandEntity byId = brandService.getById(brandId); return byId; }).collect(Collectors.toList()); return collect; } }
2.4连带更新
当我们更新brand表时候pms_category_brand_relation里的name字段并不会更新
因此我们在更新brand时需要连带更新这个表中的数据
否则会出现字段属性不一致的问题
2.4.1更改品牌名称时关系表中的冗余字段同步更新
/** * 修改 */ @RequestMapping("/update") //@RequiresPermissions("product:brand:update") public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){ // brandService.updateById(brand); brandService.updateDetail(brand); return R.ok(); }
BrandService
public interface BrandService extends IService<BrandEntity> { PageUtils queryPage(Map<String, Object> params); void updateDetail(BrandEntity brand); }
BrandServiceImpl
@Service("brandService") public class BrandServiceImpl extends ServiceImpl<BrandDao, BrandEntity> implements BrandService { @Autowired CategoryBrandRelationService categoryBrandRelationService; @Transactional @Override public void updateDetail(BrandEntity brand) { //保证冗余字段的数据一致 this.updateById(brand); //如果brand中的name更改的话 if(!org.springframework.util.StringUtils.isEmpty(brand.getName())){ //同步更新其他关联表中的数据 categoryBrandRelationService.updateBrand(brand.getBrandId(),brand.getName()); //TODO 更新其他关联 } }
CategoryBrandRelationService
public interface CategoryBrandRelationService extends IService<CategoryBrandRelationEntity> { PageUtils queryPage(Map<String, Object> params); void saveDetail(CategoryBrandRelationEntity categoryBrandRelation); void updateBrand(Long brandId, String name); }
CategoryBrandRelationServiceImpl
@Override public void updateBrand(Long brandId, String name) { //创建一个新的关系实体类 CategoryBrandRelationEntity relationEntity = new CategoryBrandRelationEntity(); //设置ID和name为我们传来的 relationEntity.setBrandId(brandId); relationEntity.setBrandName(name); //更新ID为xxx的name字段完成级联更新 this.update(relationEntity,new UpdateWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId)); }
2.4.2 来更改目录名称时关系表中的冗余字段同步更新
具体操作和1一样在categorycontroller的update调用relation中的update进行级联更新
我们前端在新增规格参数时还没有把传来的groupid
传到属性 分组 realation表当中
现在我们来进行代码编写
我们首先来到attr实体类
发现里面没有Groupid字段如果新增一个字段并加上 @TableField(exist = false)会和数据库不对应 并且很不规范
2.5.3解决方案
创建一个attrVo来接受前端传来数据
其中新建一个属性
因为其不和数据库绑定 所以不用加很多数据库注解
@Data public class AttrVo { /** * 属性id */ private Long attrId; /** * 属性名 */ private String attrName; /** * 是否需要检索[0-不需要,1-需要] */ private Integer searchType; /** * 值类型[0-为单个值,1-可以选择多个值] */ private Integer valueType; /** * 属性图标 */ private String icon; /** * 可选值列表[用逗号分隔] */ private String valueSelect; /** * 属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性] */ private Integer attrType; /** * 启用状态[0 - 禁用,1 - 启用] */ private Long enable; /** * 所属分类 */ private Long catelogId; /** * 快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整 */ private Integer showDesc; private Long attrGroupId; }
我们的attr实体类属性就和数据库进行对应 不再进行更改
controller编写
@RequestMapping("/save") //@RequiresPermissions("product:attr:save") public R save(@RequestBody AttrVo attr){ attrService.saveAttr(attr); return R.ok(); }
service
public interface AttrService extends IService<AttrEntity> { PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); }
serviceimpl
@Transactional @Override public void saveAttr(AttrVo attr) { //创建一个dao实体类 AttrEntity attrEntity = new AttrEntity(); // attrEntity.setAttrName(attr.getAttrName()); //把传来的基本数据传给dao实体类 BeanUtils.copyProperties(attr,attrEntity); //1、保存基本数据 this.save(attrEntity); //2、保存关联关系 AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attr.getAttrGroupId()); relationEntity.setAttrId(attrEntity.getAttrId()); relationDao.insert(relationEntity); }
2.6平台属性-规格参数列表
2.6.1创建AttrRespVo
由于前端返回要求一些数据
我们创建一个返回的VO
在serviceimpl层会封装这个VO并且进行返回
@Data public class AttrRespVo extends AttrVo { /** * "catelogName": "手机/数码/手机", //所属分类名字 * "groupName": "主体", //所属分组名字 */ private String catelogName; private String groupName; private Long[] catelogPath;
AttrController
@GetMapping("/{attrType}/list/{catelogId}") public R baseAttrList(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Long catelogId, @PathVariable("attrType")String type){ //1 把传入的type 参数列表 要查询哪个目录下的目录ID 用其调用service层方法 PageUtils page = attrService.queryBaseAttrPage(params,catelogId,type); return R.ok().put("page", page); }
AttrService
public interface AttrService extends IService<AttrEntity> { PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type); PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); }
AttrServiceImpl
@Override public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) { QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(type)? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode()); //1 创建一个新的queryWrapper AttrEntity // QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>(); //2 如果传入的catelogId不为0 我们才查询catelogId if(catelogId != 0){ queryWrapper.eq("catelog_id",catelogId); } //3 得到params参数列表中的Key 如果不为空 进行规则匹配(返回属性id等于Key或者是属性name like key) String key = (String) params.get("key"); if(!StringUtils.isEmpty(key)){ //attr_id attr_name queryWrapper.and((wrapper)->{ wrapper.eq("attr_id",key).or().like("attr_name",key); }); } //4 调用mybatis-plus serviceImpl层的page方法返回Ipage对象 // 其参数是根据Query工具类生成的Page对象 和 queryWrapper IPage<AttrEntity> page = this.page( new Query<AttrEntity>().getPage(params), queryWrapper ); //5 把生成的Ipage对象封装到pageUtils里 PageUtils pageUtils = new PageUtils(page); //6 从Ipage得到记录 List<AttrEntity> records = page.getRecords(); List<AttrRespVo> respVos = records.stream().map((attrEntity) -> { // 生成一个AttrRespVo的VO对象 AttrRespVo attrRespVo = new AttrRespVo(); // 先把原来的数据copy到其中 BeanUtils.copyProperties(attrEntity, attrRespVo); //1、设置分类和分组的名字 if("base".equalsIgnoreCase(type)){ AttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId())); if (attrId != null && attrId.getAttrGroupId()!=null) { AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId()); attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId()); if (categoryEntity != null) { attrRespVo.setCatelogName(categoryEntity.getName()); } return attrRespVo; }).collect(Collectors.toList()); pageUtils.setList(respVos); return pageUtils; }
2.7平台属性-规格修改
2.7.1完善规格修改回显功能
回显是查询后端的@RequestMapping(“/info/{attrId}”)、
我们对其进行修改
AttrController
/** * 信息 */ @RequestMapping("/info/{attrId}") //@RequiresPermissions("product:attr:info") public R info(@PathVariable("attrId") Long attrId){ //AttrEntity attr = attrService.getById(attrId); //我们自定义查询详情 返回带有详细信息的respVo对象 AttrRespVo respVo = attrService.getAttrInfo(attrId); return R.ok().put("attr", respVo); }
AttrService
public interface AttrService extends IService<AttrEntity> { PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type); PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); AttrRespVo getAttrInfo(Long attrId); void updateAttr(AttrVo attr); }
impl
@Override public AttrRespVo getAttrInfo(Long attrId) { //1 新建一个respVo AttrRespVo respVo = new AttrRespVo(); //2 根据传入id获取当前属性的实体类 AttrEntity attrEntity = this.getById(attrId); //3 先把部分数据封装到respVO当中 BeanUtils.copyProperties(attrEntity,respVo); //4 如果是基本属性 if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){ //1、设置分组信息 AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId)); if(attrgroupRelation!=null){ respVo.setAttrGroupId(attrgroupRelation.getAttrGroupId()); AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrGroupId()); if(attrGroupEntity!=null){ respVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } } //2、设置分类信息 Long catelogId = attrEntity.getCatelogId(); Long[] catelogPath = categoryService.findCatelogPath(catelogId); respVo.setCatelogPath(catelogPath); CategoryEntity categoryEntity = categoryDao.selectById(catelogId); if(categoryEntity!=null){ respVo.setCatelogName(categoryEntity.getName()); } return respVo; }
2.7.2 完善规格修改功能
/** * 修改 */ @RequestMapping("/update") //@RequiresPermissions("product:attr:update") public R update(@RequestBody AttrVo attr){ attrService.updateAttr(attr); return R.ok(); }
service
public interface AttrService extends IService<AttrEntity> { PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type); PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); AttrRespVo getAttrInfo(Long attrId); void updateAttr(AttrVo attr); }
impl
@Transactional @Override public void updateAttr(AttrVo attr) { //1 接受前端传来的AttrVo AttrEntity attrEntity = new AttrEntity(); //2 copy BeanUtils.copyProperties(attr,attrEntity); //3 先更新attrEntity this.updateById(attrEntity); //4 如果是基本属性再修改 if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){ //1、修改分组关联 AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attr.getAttrGroupId()); relationEntity.setAttrId(attr.getAttrId()); //判断数据库中是否有这个relationEntity 有了更新 没有添加 Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId())); if(count>0){ relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId())); }else{ relationDao.insert(relationEntity); } } }
2.8平台属性-查询分组关联属性&删除关联
2.8.1编写查询分组关联属性接口
AttrGroupController
/** * 获取属性分组的关联的所有属性 * @param attrgroupId * @return */ ///product/attrgroup/{attrgroupId}/attr/relation @GetMapping("/{attrgroupId}/attr/relation") public R attrRelation(@PathVariable("attrgroupId") Long attrgroupId){ List<AttrEntity> entities = attrService.getRelationAttr(attrgroupId); return R.ok().put("data",entities); }
AttrService
public interface AttrService extends IService<AttrEntity> { PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type); PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); AttrRespVo getAttrInfo(Long attrId); void updateAttr(AttrVo attr); List<AttrEntity> getRelationAttr(Long attrgroupId); void deleteRelation(AttrGroupRelationVo[] vos); }
AttrServiceImpl
@Override public List<AttrEntity> getRelationAttr(Long attrgroupId) { //1 在realation表中查出所有与attrgroupId相关的realation实体类 List<AttrAttrgroupRelationEntity> entities = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId)); //2 拿出这些实体类对应的 属性ids List<Long> attrIds = entities.stream().map((attr) -> { return attr.getAttrId(); }).collect(Collectors.toList()); if(attrIds == null || attrIds.size() == 0){ return null; } //3 返回查询的数据 Collection<AttrEntity> attrEntities = this.listByIds(attrIds); return (List<AttrEntity>) attrEntities; }
2.8.2编写删除关联接口
AttrGroupController
package com.atguigu.gulimall.product.controller; import java.util.Arrays; import java.util.List; import java.util.Map; import com.atguigu.gulimall.product.entity.AttrEntity; import com.atguigu.gulimall.product.entity.CategoryEntity; import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService; import com.atguigu.gulimall.product.service.AttrService; import com.atguigu.gulimall.product.service.CategoryService; import com.atguigu.gulimall.product.vo.AttrGroupRelationVo; import com.atguigu.gulimall.product.vo.AttrGroupWithAttrsVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import com.atguigu.gulimall.product.entity.AttrGroupEntity; import com.atguigu.gulimall.product.service.AttrGroupService; import com.atguigu.common.utils.PageUtils; import com.atguigu.common.utils.R; /** * 属性分组 * @author lailai * @create 2023-05-07-下午1:25 */ @RestController @RequestMapping("product/attrgroup") public class AttrGroupController { @Autowired private AttrGroupService attrGroupService; @Autowired private CategoryService categoryService; @Autowired AttrService attrService; @Autowired AttrAttrgroupRelationService relationService; ///product/attrgroup/attr/relation @PostMapping("/attr/relation") public R addRelation(@RequestBody List<AttrGroupRelationVo> vos){ relationService.saveBatch(vos); return R.ok(); } ///product/attrgroup/{catelogId}/withattr @GetMapping("/{catelogId}/withattr") public R getAttrGroupWithAttrs(@PathVariable("catelogId")Long catelogId){ //1、查出当前分类下的所有属性分组, //2、查出每个属性分组的所有属性 List<AttrGroupWithAttrsVo> vos = attrGroupService.getAttrGroupWithAttrsByCatelogId(catelogId); return R.ok().put("data",vos); } ///product/attrgroup/{attrgroupId}/attr/relation @GetMapping("/{attrgroupId}/attr/relation") public R attrRelation(@PathVariable("attrgroupId") Long attrgroupId){ List<AttrEntity> entities = attrService.getRelationAttr(attrgroupId); return R.ok().put("data",entities); } ///product/attrgroup/{attrgroupId}/noattr/relation @GetMapping("/{attrgroupId}/noattr/relation") public R attrNoRelation(@PathVariable("attrgroupId") Long attrgroupId, @RequestParam Map<String, Object> params){ PageUtils page = attrService.getNoRelationAttr(params,attrgroupId); return R.ok().put("page",page); } @PostMapping("/attr/relation/delete") public R deleteRelation(@RequestBody AttrGroupRelationVo[] vos){ attrService.deleteRelation(vos); return R.ok(); } /** * 列表 */ @RequestMapping("/list/{catelogId}") //@RequiresPermissions("product:attrgroup:list") public R list(@RequestParam Map<String, Object> params, @PathVariable("catelogId") Long catelogId){ // PageUtils page = attrGroupService.queryPage(params); PageUtils page = attrGroupService.queryPage(params,catelogId); return R.ok().put("page", page); } /** * 信息 */ @RequestMapping("/info/{attrGroupId}") //@RequiresPermissions("product:attrgroup:info") public R info(@PathVariable("attrGroupId") Long attrGroupId){ AttrGroupEntity attrGroup = attrGroupService.getById(attrGroupId); Long catelogId = attrGroup.getCatelogId(); Long[] path = categoryService.findCatelogPath(catelogId); attrGroup.setCatelogPath(path); return R.ok().put("attrGroup", attrGroup); } /** * 保存 */ @RequestMapping("/save") //@RequiresPermissions("product:attrgroup:save") public R save(@RequestBody AttrGroupEntity attrGroup){ attrGroupService.save(attrGroup); return R.ok(); } /** * 修改 */ @RequestMapping("/update") //@RequiresPermissions("product:attrgroup:update") public R update(@RequestBody AttrGroupEntity attrGroup){ attrGroupService.updateById(attrGroup); return R.ok(); } /** * 删除 */ @RequestMapping("/delete") //@RequiresPermissions("product:attrgroup:delete") public R delete(@RequestBody Long[] attrGroupIds){ attrGroupService.removeByIds(Arrays.asList(attrGroupIds)); return R.ok(); } }
AttrService
package com.atguigu.gulimall.product.service; import com.atguigu.gulimall.product.vo.AttrGroupRelationVo; import com.atguigu.gulimall.product.vo.AttrRespVo; import com.atguigu.gulimall.product.vo.AttrVo; import com.baomidou.mybatisplus.extension.service.IService; import com.atguigu.common.utils.PageUtils; import com.atguigu.gulimall.product.entity.AttrEntity; import java.util.List; import java.util.Map; /** * 商品属性 * @author lailai * @create 2023-05-07-下午1:25 */ public interface AttrService extends IService<AttrEntity> { PageUtils queryPage(Map<String, Object> params); void saveAttr(AttrVo attr); PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type); AttrRespVo getAttrInfo(Long attrId); void updateAttr(AttrVo attr); List<AttrEntity> getRelationAttr(Long attrgroupId); void deleteRelation(AttrGroupRelationVo[] vos); PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId); }
AttrServiceImpl
package com.atguigu.gulimall.product.service.impl; import com.atguigu.common.constant.ProductConstant; import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao; import com.atguigu.gulimall.product.dao.AttrGroupDao; import com.atguigu.gulimall.product.dao.CategoryDao; import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity; import com.atguigu.gulimall.product.entity.AttrGroupEntity; import com.atguigu.gulimall.product.entity.CategoryEntity; import com.atguigu.gulimall.product.service.CategoryService; import com.atguigu.gulimall.product.vo.AttrGroupRelationVo; import com.atguigu.gulimall.product.vo.AttrRespVo; import com.atguigu.gulimall.product.vo.AttrVo; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.atguigu.common.utils.PageUtils; import com.atguigu.common.utils.Query; import com.atguigu.gulimall.product.dao.AttrDao; import com.atguigu.gulimall.product.entity.AttrEntity; import com.atguigu.gulimall.product.service.AttrService; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @Service("attrService") public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService { @Autowired AttrAttrgroupRelationDao relationDao; @Autowired AttrGroupDao attrGroupDao; @Autowired CategoryDao categoryDao; @Autowired CategoryService categoryService; @Override public PageUtils queryPage(Map<String, Object> params) { IPage<AttrEntity> page = this.page( new Query<AttrEntity>().getPage(params), new QueryWrapper<AttrEntity>() ); return new PageUtils(page); } @Transactional @Override public void saveAttr(AttrVo attr) { AttrEntity attrEntity = new AttrEntity(); // attrEntity.setAttrName(attr.getAttrName()); BeanUtils.copyProperties(attr,attrEntity); //1、保存基本数据 this.save(attrEntity); //2、保存关联关系 if(attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId()!=null){ AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attr.getAttrGroupId()); relationEntity.setAttrId(attrEntity.getAttrId()); relationDao.insert(relationEntity); } } @Override public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) { QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(type)?ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode()); if(catelogId != 0){ queryWrapper.eq("catelog_id",catelogId); } String key = (String) params.get("key"); if(!StringUtils.isEmpty(key)){ //attr_id attr_name queryWrapper.and((wrapper)->{ wrapper.eq("attr_id",key).or().like("attr_name",key); }); } IPage<AttrEntity> page = this.page( new Query<AttrEntity>().getPage(params), queryWrapper ); PageUtils pageUtils = new PageUtils(page); List<AttrEntity> records = page.getRecords(); List<AttrRespVo> respVos = records.stream().map((attrEntity) -> { AttrRespVo attrRespVo = new AttrRespVo(); BeanUtils.copyProperties(attrEntity, attrRespVo); //1、设置分类和分组的名字 if("base".equalsIgnoreCase(type)){ AttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId())); if (attrId != null && attrId.getAttrGroupId()!=null) { AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId()); attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.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 respVo = new AttrRespVo(); AttrEntity attrEntity = this.getById(attrId); BeanUtils.copyProperties(attrEntity,respVo); if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){ //1、设置分组信息 AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId)); if(attrgroupRelation!=null){ respVo.setAttrGroupId(attrgroupRelation.getAttrGroupId()); AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrGroupId()); if(attrGroupEntity!=null){ respVo.setGroupName(attrGroupEntity.getAttrGroupName()); } } } //2、设置分类信息 Long catelogId = attrEntity.getCatelogId(); Long[] catelogPath = categoryService.findCatelogPath(catelogId); respVo.setCatelogPath(catelogPath); CategoryEntity categoryEntity = categoryDao.selectById(catelogId); if(categoryEntity!=null){ respVo.setCatelogName(categoryEntity.getName()); } return respVo; } @Transactional @Override public void updateAttr(AttrVo attr) { AttrEntity attrEntity = new AttrEntity(); BeanUtils.copyProperties(attr,attrEntity); this.updateById(attrEntity); if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){ //1、修改分组关联 AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attr.getAttrGroupId()); relationEntity.setAttrId(attr.getAttrId()); Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId())); if(count>0){ relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId())); }else{ relationDao.insert(relationEntity); } } } /** * 根据分组id查找关联的所有基本属性 * @param attrgroupId * @return */ @Override public List<AttrEntity> getRelationAttr(Long attrgroupId) { List<AttrAttrgroupRelationEntity> entities = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId)); List<Long> attrIds = entities.stream().map((attr) -> { return attr.getAttrId(); }).collect(Collectors.toList()); if(attrIds == null || attrIds.size() == 0){ return null; } Collection<AttrEntity> attrEntities = this.listByIds(attrIds); return (List<AttrEntity>) attrEntities; } @Override public void deleteRelation(AttrGroupRelationVo[] vos) { //relationDao.delete(new QueryWrapper<>().eq("attr_id",1L).eq("attr_group_id",1L)); // List<AttrAttrgroupRelationEntity> entities = Arrays.asList(vos).stream().map((item) -> { AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); BeanUtils.copyProperties(item, relationEntity); return relationEntity; }).collect(Collectors.toList()); relationDao.deleteBatchRelation(entities); } /** * 获取当前分组没有关联的所有属性 * @param params * @param attrgroupId * @return */ @Override public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) { //1、当前分组只能关联自己所属的分类里面的所有属性 AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId); Long catelogId = attrGroupEntity.getCatelogId(); //2、当前分组只能关联别的分组没有引用的属性 //2.1)、当前分类下的其他分组 List<AttrGroupEntity> group = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId)); List<Long> collect = group.stream().map(item -> { return item.getAttrGroupId(); }).collect(Collectors.toList()); //2.2)、这些分组关联的属性 List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect)); List<Long> attrIds = groupId.stream().map(item -> { return item.getAttrId(); }).collect(Collectors.toList()); //2.3)、从当前分类的所有属性中移除这些属性; QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()); if(attrIds!=null && attrIds.size()>0){ wrapper.notIn("attr_id", attrIds); } String key = (String) params.get("key"); if(!StringUtils.isEmpty(key)){ wrapper.and((w)->{ w.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; } }
2.9平台属性-查询分组未关联的属性
AttrAttrgroupRelationController
package com.atguigu.gulimall.product.controller; import java.util.Arrays; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity; import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService; import com.atguigu.common.utils.PageUtils; import com.atguigu.common.utils.R; /** * 属性&属性分组关联 * * @author lailai * @create 2023-05-07-下午1:25 */ @RestController @RequestMapping("product/attrattrgrouprelation") public class AttrAttrgroupRelationController { @Autowired private AttrAttrgroupRelationService attrAttrgroupRelationService; /** * 列表 */ @RequestMapping("/list") //@RequiresPermissions("product:attrattrgrouprelation:list") public R list(@RequestParam Map<String, Object> params){ PageUtils page = attrAttrgroupRelationService.queryPage(params); return R.ok().put("page", page); } /** * 信息 */ @RequestMapping("/info/{id}") //@RequiresPermissions("product:attrattrgrouprelation:info") public R info(@PathVariable("id") Long id){ AttrAttrgroupRelationEntity attrAttrgroupRelation = attrAttrgroupRelationService.getById(id); return R.ok().put("attrAttrgroupRelation", attrAttrgroupRelation); } /** * 保存 */ @RequestMapping("/save") //@RequiresPermissions("product:attrattrgrouprelation:save") public R save(@RequestBody AttrAttrgroupRelationEntity attrAttrgroupRelation){ attrAttrgroupRelationService.save(attrAttrgroupRelation); return R.ok(); } /** * 修改 */ @RequestMapping("/update") //@RequiresPermissions("product:attrattrgrouprelation:update") public R update(@RequestBody AttrAttrgroupRelationEntity attrAttrgroupRelation){ attrAttrgroupRelationService.updateById(attrAttrgroupRelation); return R.ok(); } /** * 删除 */ @RequestMapping("/delete") //@RequiresPermissions("product:attrattrgrouprelation:delete") public R delete(@RequestBody Long[] ids){ attrAttrgroupRelationService.removeByIds(Arrays.asList(ids)); return R.ok(); } }
AttrAttrgroupRelationService
package com.atguigu.gulimall.product.service; import com.atguigu.gulimall.product.vo.AttrGroupRelationVo; import com.baomidou.mybatisplus.extension.service.IService; import com.atguigu.common.utils.PageUtils; import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity; import java.util.List; import java.util.Map; /** * 属性&属性分组关联 * * @author lailai * @create 2023-05-07-下午1:25 */ public interface AttrAttrgroupRelationService extends IService<AttrAttrgroupRelationEntity> { PageUtils queryPage(Map<String, Object> params); void saveBatch(List<AttrGroupRelationVo> vos); }
AttrAttrgroupRelationServiceImpl
package com.atguigu.gulimall.product.service.impl; import com.atguigu.gulimall.product.vo.AttrGroupRelationVo; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.atguigu.common.utils.PageUtils; import com.atguigu.common.utils.Query; import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao; import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity; import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService; @Service("attrAttrgroupRelationService") public class AttrAttrgroupRelationServiceImpl extends ServiceImpl<AttrAttrgroupRelationDao, AttrAttrgroupRelationEntity> implements AttrAttrgroupRelationService { @Override public PageUtils queryPage(Map<String, Object> params) { IPage<AttrAttrgroupRelationEntity> page = this.page( new Query<AttrAttrgroupRelationEntity>().getPage(params), new QueryWrapper<AttrAttrgroupRelationEntity>() ); return new PageUtils(page); } @Override public void saveBatch(List<AttrGroupRelationVo> vos) { List<AttrAttrgroupRelationEntity> collect = vos.stream().map(item -> { AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); BeanUtils.copyProperties(item, relationEntity); return relationEntity; }).collect(Collectors.toList()); this.saveBatch(collect); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)