1.分层领域模型规约
- DO( Data Object): 此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
- DTO( Data Transfer Object):数据传输对象, Service 或 Manager 向外传输的对象。
- BO( Business Object):业务对象, 可以由 Service 层输出的封装业务逻辑的对象。
- Query:数据查询对象,各层接收上层的查询请求。 注意超过 2 个参数的查询封装,禁止使用 Map
类来传输。 - VO( View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
2.规格参数-新增
前端Vue
2.1.抽取VO对象
- 将 AttrEntity 的属性抽取到 AttrVO 对象中,并新增四个属性
private Long attrGroupId;
private String catelogName;
private String groupName;
private Long[] catelogPath; - Controller层的Handler处理方法入参统一使用 VO 对象
package com.atguigu.gmall.product.vo;import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** 规格参数(基本属性) VO 对象** @author zhangwen* @email 1466787185@qq.com* @date 2023-02-22 12:20:05*/
@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;/*** 属性分组Id*/private Long attrGroupId;/*** 所属分类名*/private String catelogName;/*** 所属分组名*/private String groupName;/*** 三级分类完整路径*/private Long[] catelogPath;
}
2.2.商品常量类
在 gmall-common 公共服务中创建商品常量类 ProductConstant
package com.atguigu.common.constant;/*** @Description:商品服务常量类* @Auther: zhangwen* @Date: 2023-02-22 10:51* @version: 1.0*/
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 void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}
}
2.3.API
POST /product/attr/save
2.4.后台接口实现
AttrController
/*** 保存规格参数*/@RequestMapping("/save")public R save(@RequestBody AttrVO attrVO){attrService.saveAttr(attrVO);return R.ok();}
AttrServiceImpl
/*** 保存规则参数* @param attrVO*/@Transactional(rollbackFor = Exception.class)@Overridepublic void saveAttr(AttrVO attrVO) {//保存基本属性AttrEntity attrEntity = new AttrEntity();//属性拷贝BeanUtils.copyProperties(attrVO, attrEntity);this.save(attrEntity);//保存关联关系 - 基本属性(只有规格参数需要和属性分组建立关系,销售属性不建立关系)if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();relationEntity.setAttrId(attrEntity.getAttrId());relationEntity.setAttrGroupId(attrVO.getAttrGroupId());relationDao.insert(relationEntity);}}
3.规格参数-列表查询
3.1.API
GET /product/attr/base/list/{catelogId}//请求参数
{page: 1, //当前页码limit: 10, //每页记录数sidx: 'id', //排序字段order: 'asc', //排序方式key: '华为' //检索关键字
}//响应数据
{"msg": "success","code": 0,"page": {"totalCount": 0,"pageSize": 10,"totalPage": 0,"currPage": 1,"list": [{"attrId": 0, //属性id"attrName": "string", //属性名"attrType": 0, //属性类型,0-销售属性,1-基本属性"catelogName": "手机/数码/手机", //所属分类名字"groupName": "主体", //所属分组名字"enable": 0, //是否启用"icon": "string", //图标"searchType": 0, //是否需要检索[0-不需要,1-需要]"showDesc": 0, //是否展示在介绍上;0-否 1-是"valueSelect": "string", //可选值列表[用逗号分隔]"valueType": 0 //值类型[0-为单个值,1-可以选择多个值]}]}
}
3.2.后台接口实现
AttrController
/*** 查询规格参数和销售属性列表* @param params 分页信息和查询关键字key* @param catelogId 三级分类ID* @param attrType 属性类型* @return*/@GetMapping("/{attrType}/list/{catelogId}")public R listAttr(@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);}
AttrServiceImpl
/*** 查询规格参数和销售属性列表* @param params 分页信息和查询关键字key* @param catelogId 三级分类ID* @param attrType 属性类型* @return*/@Overridepublic PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(attrType)? 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)){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<AttrVO> attrVoList = records.stream().map(attrEntity -> {AttrVO attrVO = new AttrVO();BeanUtils.copyProperties(attrEntity, attrVO);//查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组if ("base".equalsIgnoreCase(attrType)) {AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));if(relationEntity != null && relationEntity.getAttrGroupId() != null ){AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());attrVO.setGroupName(attrGroupEntity.getAttrGroupName());}}//查询并设置分类名 catelogNameCategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());if(categoryEntity != null){attrVO.setCatelogName(categoryEntity.getName());}return attrVO;}).collect(Collectors.toList());pageUtils.setList(attrVoList);return pageUtils;}
运行结果如下:
4.规格参数-修改
4.1.所属分类及分组数据回显
4.1.1API
GET /product/attr/info/{attrId}
//响应数据
{
"msg": "success",
"code": 0,
"attr": {"attrId": 1,"attrName": "入网型号","searchType": 1,"valueType": 1,"icon": "icon-1","valueSelect": "v;q;w","attrType": 1,"enable": 1,"showDesc": 1,"attrGroupId": 1, //分组id"catelogId": 225, //分类id"catelogPath": [2, 34, 225] //分类完整路径}
}
4.1.2后台接口实现
AttrController
/*** 获取规格参数*/@RequestMapping("/info/{attrId}")public R info(@PathVariable("attrId") Long attrId){AttrVO attrVO = attrService.getAttrInfo(attrId);return R.ok().put("attr", attrVO);}
AttrServiceImpl
/*** 获取规格参数* @param attrId 属性id* @return 规格参数VO对象*/@Overridepublic AttrVO getAttrInfo(Long attrId) {AttrVO attrVO = new AttrVO();AttrEntity attrEntity = this.getById(attrId);BeanUtils.copyProperties(attrEntity,attrVO);//查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));if (relationEntity != null && relationEntity.getAttrGroupId() != null) {AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());attrVO.setAttrGroupId(attrGroupEntity.getAttrGroupId());if (attrGroupEntity != null) {attrVO.setGroupName(attrGroupEntity.getAttrGroupName());}}}//查询并设置所属分类信息//一个微服务内部,service之间调用没有问题,考虑到开发便捷性和代码重用//对于是否违背设计原则,高内聚低耦合,本身微服务划分从根本上就已经做到了高内聚低耦合CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());if(categoryEntity != null){attrVO.setCatelogName(categoryEntity.getName());}Long[] categoryPath = categoryService.findCategoryPath(attrEntity.getCatelogId());attrVO.setCatelogPath(categoryPath);return attrVO;}
运行结果:
4.2.修改规格参数
4.2.1.API
POST /product/attr/update
4.2.2.后台接口实现
AttrController
/*** 修改规格参数*/@RequestMapping("/update")public R update(@RequestBody AttrVO attrVO){attrService.updateAttr(attrVO);return R.ok();}
AttrServiceImpl
/*** 修改规格参数* @param attrVO 规格参数VO对象*/@Overridepublic void updateAttr(AttrVO attrVO) {//修改基本信息AttrEntity attrEntity = new AttrEntity();BeanUtils.copyProperties(attrVO,attrEntity);this.updateById(attrEntity);//修改分组关联 - 基本属性if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();relationEntity.setAttrGroupId(attrVO.getAttrGroupId());relationEntity.setAttrId(attrVO.getAttrId());Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVO.getAttrId()));if (count > 0) {//修改关联关系relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVO.getAttrId()));}else{//新增关联关系relationDao.insert(relationEntity);}}}