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)
@Override
public 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
*/
@Override
public 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());
}
}
//查询并设置分类名 catelogName
CategoryEntity 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对象
*/
@Override
public 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对象
*/
@Override
public 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);
}
}
}