谷粒商城–商品发布–笔记九
1.基本信息页面
1.选择分类后品牌列表不显示问题
原因
使用到了PubSub 但是没有依赖
解决
- npm install --save pubsub-js
- 在src下的main.js中引用:
① import PubSub from pubsub-js
② Vue.prototype.PubSub = PubSub
效果
报错消失了,取而代之的是找不到接口,问题解决
2.编写根据商品分类查询品牌列表接口
新增品牌vo对象
gulimall-product/src/main/java/site/zhourui/gulimall/product/vo/BrandVo.java
@Data
public class BrandVo {
/**
* "brandId": 0,
* "brandName": "string",
*/
private Long brandId;
private String brandName;
}
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/CategoryBrandRelationService.java
新增接口
List<BrandEntity> getBrandsByCatId(Long catId);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/CategoryBrandRelationServiceImpl.java
新增接口实现
@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;
}
gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/CategoryBrandRelationController.java 新增接口
/**
* 获取当前品牌关联的所有分类列表
*/
@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);
}
重启gulimall-product服务
观察效果 商品列表出现
3.获取会员等级列表
发现还需要会员等级接口
1.网关配置
因为之前配置过会员模块,这里就不配置了
但是在网关中需要配置会员服务路由,并重启网关
gulimall-gateway/src/main/resources/application.yml
- id: member_route
uri: lb://gulimall-member
predicates:
- Path=/api/member/**
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
2.添加会员等级
启动 gulimall-member服务
设置会员等级
此时会员列表接口也能查询到会员等级列表信息了
2.规格参数页面
规格参数属如果需要多选
需要在对应的属性
3.销售属性页面
1.根据分类id查出所有的分组以及这些组里面的属性
com/atguigu/gulimall/product/vo/AttrGroupWithAttrsVo.java
属性分组带有属性集合的vo
package site.zhourui.gulimall.product.vo;
import lombok.Data;
import site.zhourui.gulimall.product.entity.AttrEntity;
import java.util.List;
@Data
public class AttrGroupWithAttrsVo {
/**
* 分组id
*/
private Long attrGroupId;
/**
* 组名
*/
private String attrGroupName;
/**
* 排序
*/
private Integer sort;
/**
* 描述
*/
private String descript;
/**
* 组图标
*/
private String icon;
/**
* 所属分类id
*/
private Long catelogId;
private List<AttrEntity> attrs;
}
com/atguigu/gulimall/product/service/AttrGroupService.java
新增根据分类id查出所有的分组以及这些组里面的属性接口
//根据分类id查出所有的分组以及这些组里面的属性
List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId);
com/atguigu/gulimall/product/service/impl/AttrGroupServiceImpl.java
/**
* 根据分类id查出所有的分组以及这些组里面的属性
* @param catelogId
* @return
*/
@Override
public List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId) {
//com.atguigu.gulimall.product.vo
//1、查询分组信息
List<AttrGroupEntity> attrGroupEntities = this.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
//2、查询所有属性
List<AttrGroupWithAttrsVo> collect = attrGroupEntities.stream().map(group -> {
AttrGroupWithAttrsVo attrsVo = new AttrGroupWithAttrsVo();
BeanUtils.copyProperties(group,attrsVo);
List<AttrEntity> attrs = attrService.getRelationAttr(attrsVo.getAttrGroupId());
attrsVo.setAttrs(attrs);
return attrsVo;
}).collect(Collectors.toList());
return collect;
}
gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/AttrGroupController.java
编写获取会员等级列表接口
///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);
}
效果
4.SKU信息页面
此页面主要是前端生成的
根据步骤二中选中的属性进行笛卡尔乘积生成的数据
具体实现代码
generateSkus() {
this.step = 3;
//根据笛卡尔积运算进行生成sku
let selectValues = [];
this.dataResp.tableAttrColumn = [];
this.dataResp.tempSaleAttrs.forEach(item => {
if (item.attrValues.length > 0) {
selectValues.push(item.attrValues);
this.dataResp.tableAttrColumn.push(item);
}
});
let descartes = this.descartes(selectValues);
//[["黑色","6GB","移动"],["黑色","6GB","联通"],["黑色","8GB","移动"],["黑色","8GB","联通"],
//["白色","6GB","移动"],["白色","6GB","联通"],["白色","8GB","移动"],["白色","8GB","联通"],
//["蓝色","6GB","移动"],["蓝色","6GB","联通"],["蓝色","8GB","移动"],["蓝色","8GB","联通"]]
console.log("生成的组合", JSON.stringify(descartes));
//有多少descartes就有多少sku
let skus = [];
descartes.forEach((descar, descaridx) => {
let attrArray = []; //sku属性组
descar.forEach((de, index) => {
//构造saleAttr信息
let saleAttrItem = {
attrId: this.dataResp.tableAttrColumn[index].attrId,
attrName: this.dataResp.tableAttrColumn[index].attrName,
attrValue: de
};
attrArray.push(saleAttrItem);
});
//先初始化几个images,后面的上传还要加
let imgs = [];
this.spu.images.forEach((img, idx) => {
imgs.push({ imgUrl: "", defaultImg: 0 });
});
//会员价,也必须在循环里面生成,否则会导致数据绑定问题
let memberPrices = [];
if (this.dataResp.memberLevels.length > 0) {
for (let i = 0; i < this.dataResp.memberLevels.length; i++) {
if (this.dataResp.memberLevels[i].priviledgeMemberPrice == 1) {
memberPrices.push({
id: this.dataResp.memberLevels[i].id,
name: this.dataResp.memberLevels[i].name,
price: 0
});
}
}
}
//;descaridx,判断如果之前有就用之前的值;
let res = this.hasAndReturnSku(this.spu.skus, descar);
if (res === null) {
skus.push({
attr: attrArray,
skuName: this.spu.spuName + " " + descar.join(" "),
price: 0,
skuTitle: this.spu.spuName + " " + descar.join(" "),
skuSubtitle: "",
images: imgs,
descar: descar,
fullCount: 0,
discount: 0,
countStatus: 0,
fullPrice: 0.0,
reducePrice: 0.0,
priceStatus: 0,
memberPrice: new Array().concat(memberPrices)
});
} else {
skus.push(res);
}
});
this.spu.skus = skus;
console.log("结果!!!", this.spu.skus, this.dataResp.tableAttrColumn);
},
//判断如果包含之前的sku的descar组合,就返回这个sku的详细信息;
hasAndReturnSku(skus, descar) {
let res = null;
if (skus.length > 0) {
for (let i = 0; i < skus.length; i++) {
if (skus[i].descar.join(" ") == descar.join(" ")) {
res = skus[i];
}
}
}
return res;
},
生成效果
5.新增商品vo抽取
1.新增商品保存json
保存时会向后端发送一个这样的json对象
{"spuName":"2","spuDescription":"2","catalogId":225,"brandId":9,"weight":0.1,"publishStatus":0,"decript":["https://zr-gulimall-images.oss-cn-chengdu.aliyuncs.com/2021-10-14/04854fc0-7f1b-4505-8b34-e53f97f7fb81_2021-07-07.png"],"images":["https://zr-gulimall-images.oss-cn-chengdu.aliyuncs.com/2021-10-14/6697a7e5-294a-4e74-8389-4fd5fd1b826b_2021-06-28.png"],"bounds":{"buyBounds":0,"growBounds":0},"baseAttrs":[{"attrId":7,"attrValues":"A2217;C3J","showDesc":1},{"attrId":8,"attrValues":"2018","showDesc":0},{"attrId":11,"attrValues":"白色","showDesc":1},{"attrId":13,"attrValues":"135.9","showDesc":0},{"attrId":14,"attrValues":"以官网信息为准;陶瓷","showDesc":0},{"attrId":15,"attrValues":"高通(Qualcomm)","showDesc":1},{"attrId":16,"attrValues":"骁龙665","showDesc":0}],"skus":[{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"黑色"},{"attrId":10,"attrName":"内存","attrValue":"6GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"158.3"}],"skuName":"2 黑色 6GB 158.3","price":0,"skuTitle":"2 黑色 6GB 158.3","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["黑色","6GB","158.3"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"黑色"},{"attrId":10,"attrName":"内存","attrValue":"6GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"135.9"}],"skuName":"2 黑色 6GB 135.9","price":0,"skuTitle":"2 黑色 6GB 135.9","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["黑色","6GB","135.9"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"黑色"},{"attrId":10,"attrName":"内存","attrValue":"4GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"158.3"}],"skuName":"2 黑色 4GB 158.3","price":0,"skuTitle":"2 黑色 4GB 158.3","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["黑色","4GB","158.3"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"黑色"},{"attrId":10,"attrName":"内存","attrValue":"4GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"135.9"}],"skuName":"2 黑色 4GB 135.9","price":0,"skuTitle":"2 黑色 4GB 135.9","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["黑色","4GB","135.9"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"白色"},{"attrId":10,"attrName":"内存","attrValue":"6GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"158.3"}],"skuName":"2 白色 6GB 158.3","price":0,"skuTitle":"2 白色 6GB 158.3","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["白色","6GB","158.3"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"白色"},{"attrId":10,"attrName":"内存","attrValue":"6GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"135.9"}],"skuName":"2 白色 6GB 135.9","price":0,"skuTitle":"2 白色 6GB 135.9","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["白色","6GB","135.9"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"白色"},{"attrId":10,"attrName":"内存","attrValue":"4GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"158.3"}],"skuName":"2 白色 4GB 158.3","price":0,"skuTitle":"2 白色 4GB 158.3","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["白色","4GB","158.3"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]},{"attr":[{"attrId":9,"attrName":"颜色","attrValue":"白色"},{"attrId":10,"attrName":"内存","attrValue":"4GB"},{"attrId":13,"attrName":"机身长度(mm)","attrValue":"135.9"}],"skuName":"2 白色 4GB 135.9","price":0,"skuTitle":"2 白色 4GB 135.9","skuSubtitle":"","images":[{"imgUrl":"","defaultImg":0}],"descar":["白色","4GB","135.9"],"fullCount":0,"discount":0,"countStatus":0,"fullPrice":0,"reducePrice":0,"priceStatus":0,"memberPrice":[{"id":2,"name":"铜牌会员","price":0},{"id":3,"name":"银牌会员","price":0}]}]}
2.将json字符串格式化
{
"spuName": "2",
"spuDescription": "2",
"catalogId": 225,
"brandId": 9,
"weight": 0.1,
"publishStatus": 0,
"decript": ["https://zr-gulimall-images.oss-cn-chengdu.aliyuncs.com/2021-10-14/04854fc0-7f1b-4505-8b34-e53f97f7fb81_2021-07-07.png"],
"images": ["https://zr-gulimall-images.oss-cn-chengdu.aliyuncs.com/2021-10-14/6697a7e5-294a-4e74-8389-4fd5fd1b826b_2021-06-28.png"],
"bounds": {
"buyBounds": 0,
"growBounds": 0
},
"baseAttrs": [{
"attrId": 7,
"attrValues": "A2217;C3J",
"showDesc": 1
}, {
"attrId": 8,
"attrValues": "2018",
"showDesc": 0
}, {
"attrId": 11,
"attrValues": "白色",
"showDesc": 1
}, {
"attrId": 13,
"attrValues": "135.9",
"showDesc": 0
}, {
"attrId": 14,
"attrValues": "以官网信息为准;陶瓷",
"showDesc": 0
}, {
"attrId": 15,
"attrValues": "高通(Qualcomm)",
"showDesc": 1
}, {
"attrId": 16,
"attrValues": "骁龙665",
"showDesc": 0
}],
"skus": [{
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "黑色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "6GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "158.3"
}],
"skuName": "2 黑色 6GB 158.3",
"price": 0,
"skuTitle": "2 黑色 6GB 158.3",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["黑色", "6GB", "158.3"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "黑色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "6GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "135.9"
}],
"skuName": "2 黑色 6GB 135.9",
"price": 0,
"skuTitle": "2 黑色 6GB 135.9",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["黑色", "6GB", "135.9"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "黑色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "4GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "158.3"
}],
"skuName": "2 黑色 4GB 158.3",
"price": 0,
"skuTitle": "2 黑色 4GB 158.3",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["黑色", "4GB", "158.3"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "黑色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "4GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "135.9"
}],
"skuName": "2 黑色 4GB 135.9",
"price": 0,
"skuTitle": "2 黑色 4GB 135.9",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["黑色", "4GB", "135.9"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "白色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "6GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "158.3"
}],
"skuName": "2 白色 6GB 158.3",
"price": 0,
"skuTitle": "2 白色 6GB 158.3",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["白色", "6GB", "158.3"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "白色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "6GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "135.9"
}],
"skuName": "2 白色 6GB 135.9",
"price": 0,
"skuTitle": "2 白色 6GB 135.9",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["白色", "6GB", "135.9"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "白色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "4GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "158.3"
}],
"skuName": "2 白色 4GB 158.3",
"price": 0,
"skuTitle": "2 白色 4GB 158.3",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["白色", "4GB", "158.3"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}, {
"attr": [{
"attrId": 9,
"attrName": "颜色",
"attrValue": "白色"
}, {
"attrId": 10,
"attrName": "内存",
"attrValue": "4GB"
}, {
"attrId": 13,
"attrName": "机身长度(mm)",
"attrValue": "135.9"
}],
"skuName": "2 白色 4GB 135.9",
"price": 0,
"skuTitle": "2 白色 4GB 135.9",
"skuSubtitle": "",
"images": [{
"imgUrl": "",
"defaultImg": 0
}],
"descar": ["白色", "4GB", "135.9"],
"fullCount": 0,
"discount": 0,
"countStatus": 0,
"fullPrice": 0,
"reducePrice": 0,
"priceStatus": 0,
"memberPrice": [{
"id": 2,
"name": "铜牌会员",
"price": 0
}, {
"id": 3,
"name": "银牌会员",
"price": 0
}]
}]
}
3.生成JavaBean
下载代码
将生成的代码放入
gulimall-product/src/main/java/site/zhourui/gulimall/product/vo
4.使用lombok
将所有生成的的实体类删除getter/setter方法,替换为@Data
将所有Double类型的字段换成BigDecimal
将所有id的类型换成Long
5.完整示例
1.Attr
package site.zhourui.gulimall.product.vo;
import lombok.Data;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class Attr {
private Long attrId;
private String attrName;
private String attrValue;
}
2.BaseAttrs
package site.zhourui.gulimall.product.vo;
import lombok.Data;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class BaseAttrs {
private Long attrId;
private String attrValues;
private int showDesc;
}
3.Bounds
package site.zhourui.gulimall.product.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class Bounds {
private BigDecimal buyBounds;
private BigDecimal growBounds;
}
4.BrandVo
package site.zhourui.gulimall.product.vo;
import lombok.Data;
@Data
public class BrandVo {
/**
* "brandId": 0,
* "brandName": "string",
*/
private Long brandId;
private String brandName;
}
5.Images
package site.zhourui.gulimall.product.vo;
import lombok.Data;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class Images {
private String imgUrl;
private int defaultImg;
}
6.MemberPrice
package site.zhourui.gulimall.product.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class MemberPrice {
private Long id;
private String name;
private BigDecimal price;
}
7.Skus
package site.zhourui.gulimall.product.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class Skus {
private List<Attr> attr;
private String skuName;
private BigDecimal price;
private String skuTitle;
private String skuSubtitle;
private List<Images> images;
private List<String> descar;
private int fullCount;
private BigDecimal discount;
private int countStatus;
private BigDecimal fullPrice;
private BigDecimal reducePrice;
private int priceStatus;
private List<MemberPrice> memberPrice;
}
8.SpuSaveVo
package site.zhourui.gulimall.product.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* Auto-generated: 2021-10-14 17:59:35
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
@Data
public class SpuSaveVo {
private String spuName;
private String spuDescription;
private Long catalogId;
private Long brandId;
private BigDecimal weight;
private int publishStatus;
private List<String> decript;
private List<String> images;
private Bounds bounds;
private List<BaseAttrs> baseAttrs;
private List<Skus> skus;
}
6.商品新增业务流程分析
修改商品保存接口
com/atguigu/gulimall/product/controller/SpuInfoController.java
/**
* 保存
*/
@RequestMapping("/save")
//@RequiresPermissions("product:spuinfo:save")
public R save(@RequestBody SpuSaveVo vo){
//spuInfoService.save(spuInfo);
spuInfoService.saveSpuInfo(vo);
return R.ok();
}
新增saveSpuInfo方法
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SpuInfoService.java
void saveSpuInfo(SpuSaveVo vo);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SpuInfoServiceImpl.java
新增saveSpuInfo方法实现(完整示例)
1.商品新增业务流程分析
-
保存spu基本信息 pms_spu_info
-
保存Spu的描述图片 pms_spu_info_desc
-
保存spu的图片集 pms_spu_images
-
保存spu的规格参数;pms_product_attr_value
-
保存spu的积分信息;gulimall_sms->sms_spu_bounds (此处需要调用优惠模块服务(gulimall-coupon)的积分接口)
-
保存当前spu对应的所有sku信息;
-
sku的基本信息;pms_sku_info
-
sku的图片信息;pms_sku_image
-
sku的销售属性信息:pms_sku_sale_attr_value
-
sku的优惠、满减等信息;gulimall_sms->sms_sku_ladder\sms_sku_full_reduction\sms_member_price
(此处需要调用优惠模块服务(gulimall-coupon)优惠阶段接口\满减优惠接口\会员价接口)
-
/**
* //TODO 高级部分完善
* @param vo
*/
@Transactional
@Override
public void saveSpuInfo(SpuSaveVo vo) {
//1、保存spu基本信息 pms_spu_info
SpuInfoEntity infoEntity = new SpuInfoEntity();
BeanUtils.copyProperties(vo,infoEntity);
infoEntity.setCreateTime(new Date());
infoEntity.setUpdateTime(new Date());
this.saveBaseSpuInfo(infoEntity);
//2、保存Spu的描述图片 pms_spu_info_desc
List<String> decript = vo.getDecript();
SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
descEntity.setSpuId(infoEntity.getId());
descEntity.setDecript(String.join(",",decript));
spuInfoDescService.saveSpuInfoDesc(descEntity);
//3、保存spu的图片集 pms_spu_images
List<String> images = vo.getImages();
imagesService.saveImages(infoEntity.getId(),images);
//4、保存spu的规格参数;pms_product_attr_value
List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
List<ProductAttrValueEntity> collect = baseAttrs.stream().map(attr -> {
ProductAttrValueEntity valueEntity = new ProductAttrValueEntity();
valueEntity.setAttrId(attr.getAttrId());
AttrEntity id = attrService.getById(attr.getAttrId());
valueEntity.setAttrName(id.getAttrName());
valueEntity.setAttrValue(attr.getAttrValues());
valueEntity.setQuickShow(attr.getShowDesc());
valueEntity.setSpuId(infoEntity.getId());
return valueEntity;
}).collect(Collectors.toList());
attrValueService.saveProductAttr(collect);
//5、保存spu的积分信息;gulimall_sms->sms_spu_bounds
Bounds bounds = vo.getBounds();
SpuBoundTo spuBoundTo = new SpuBoundTo();
BeanUtils.copyProperties(bounds,spuBoundTo);
spuBoundTo.setSpuId(infoEntity.getId());
R r = couponFeignService.saveSpuBounds(spuBoundTo);
if(r.getCode() != 0){
log.error("远程保存spu积分信息失败");
}
//5、保存当前spu对应的所有sku信息;
List<Skus> skus = vo.getSkus();
if(skus!=null && skus.size()>0){
skus.forEach(item->{
String defaultImg = "";
for (Images image : item.getImages()) {
if(image.getDefaultImg() == 1){
defaultImg = image.getImgUrl();
}
}
// private String skuName;
// private BigDecimal price;
// private String skuTitle;
// private String skuSubtitle;
SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
BeanUtils.copyProperties(item,skuInfoEntity);
skuInfoEntity.setBrandId(infoEntity.getBrandId());
skuInfoEntity.setCatalogId(infoEntity.getCatalogId());
skuInfoEntity.setSaleCount(0L);
skuInfoEntity.setSpuId(infoEntity.getId());
skuInfoEntity.setSkuDefaultImg(defaultImg);
//5.1)、sku的基本信息;pms_sku_info
skuInfoService.saveSkuInfo(skuInfoEntity);
Long skuId = skuInfoEntity.getSkuId();
List<SkuImagesEntity> imagesEntities = item.getImages().stream().map(img -> {
SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
skuImagesEntity.setSkuId(skuId);
skuImagesEntity.setImgUrl(img.getImgUrl());
skuImagesEntity.setDefaultImg(img.getDefaultImg());
return skuImagesEntity;
}).filter(entity->{
//返回true就是需要,false就是剔除
return !StringUtils.isEmpty(entity.getImgUrl());
}).collect(Collectors.toList());
//5.2)、sku的图片信息;pms_sku_image
skuImagesService.saveBatch(imagesEntities);
//TODO 没有图片路径的无需保存
List<Attr> attr = item.getAttr();
List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(a -> {
SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
BeanUtils.copyProperties(a, attrValueEntity);
attrValueEntity.setSkuId(skuId);
return attrValueEntity;
}).collect(Collectors.toList());
//5.3)、sku的销售属性信息:pms_sku_sale_attr_value
skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
// //5.4)、sku的优惠、满减等信息;gulimall_sms->sms_sku_ladder\sms_sku_full_reduction\sms_member_price
SkuReductionTo skuReductionTo = new SkuReductionTo();
BeanUtils.copyProperties(item,skuReductionTo);
skuReductionTo.setSkuId(skuId);
if(skuReductionTo.getFullCount() >0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1){
R r1 = couponFeignService.saveSkuReduction(skuReductionTo);
if(r1.getCode() != 0){
log.error("远程保存sku优惠信息失败");
}
}
});
}
}
7.流程分析所需接口
1.保存spu基本信息
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SpuInfoService.java
void saveBaseSpuInfo(SpuInfoEntity infoEntity);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SpuInfoServiceImpl.java
@Override
public void saveBaseSpuInfo(SpuInfoEntity infoEntity) {
this.baseMapper.insert(infoEntity);
}
2.保存Spu的描述图片
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SpuInfoDescService.java
void saveSpuInfoDesc(SpuInfoDescEntity descEntity);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SpuInfoDescServiceImpl.java
@Override
public void saveSpuInfoDesc(SpuInfoDescEntity descEntity) {
this.baseMapper.insert(descEntity);
}
3.保存spu的图片集
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SpuImagesService.java
void saveImages(Long id, List<String> images);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SpuImagesServiceImpl.java
@Override
public void saveImages(Long id, List<String> images) {
if(images == null || images.size() == 0){
}else{
List<SpuImagesEntity> collect = images.stream().map(img -> {
SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
spuImagesEntity.setSpuId(id);
spuImagesEntity.setImgUrl(img);
return spuImagesEntity;
}).collect(Collectors.toList());
this.saveBatch(collect);
}
}
4.保存spu的规格参数
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/ProductAttrValueService.java
void saveProductAttr(List<ProductAttrValueEntity> collect);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/ProductAttrValueServiceImpl.java
@Override
public void saveProductAttr(List<ProductAttrValueEntity> collect) {
this.saveBatch(collect);
}
5.保存spu的积分信息(远程调用)
此处需要调用远程服务
新增新增spu积分传输对象
调用者和被调用者可能都需要这个对象,所以放在gulimall-common模块下
gulimall-common/src/main/java/site/zhourui/common/to/SpuBoundTo.java
调用者
调用者需要开启远程调用
@EnableFeignClients
gulimall-product/src/main/java/site/zhourui/gulimall/product/GulimallProductApplication.java
@EnableFeignClients
不加属性值会默认扫描主类同级下的所有包下带有@FeignClient
的接口,加了会扫描指定包下的所有接口
//@EnableFeignClients
@EnableFeignClients("site.zhourui.gulimall.product.feign")
@SpringBootApplication
@EnableDiscoveryClient
public class GulimallProductApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallProductApplication.class, args);
}
}
@FeignClient("gulimall-coupon")
public interface CouponFeignService {
/**
* 1、CouponFeignService.saveSpuBounds(spuBoundTo);
* 1)、@RequestBody将这个对象转为json。
* 2)、找到gulimall-coupon服务,给/coupon/spubounds/save发送请求。
* 将上一步转的json放在请求体位置,发送请求;
* 3)、对方服务收到请求。请求体里有json数据。
* (@RequestBody SpuBoundsEntity spuBounds);将请求体的json转为SpuBoundsEntity;
* 只要json数据模型是兼容的。双方服务无需使用同一个to
* @param spuBoundTo
* @return
*/
@PostMapping("/coupon/spubounds/save")
R saveSpuBounds(@RequestBody SpuBoundTo spuBoundTo);
}
被调用者
gulimall-coupon/src/main/java/site/zhourui/gulimall/coupon/controller/SpuBoundsController.java
此方法是逆向生成的
/**
* 保存
*/
@RequestMapping("/save")
public R save(@RequestBody SpuBoundsEntity spuBounds){
spuBoundsService.save(spuBounds);
return R.ok();
}
gulimall-common/src/main/java/site/zhourui/common/to/SpuBoundTo.java
package site.zhourui.common.to;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class SpuBoundTo {
private Long spuId;
private BigDecimal buyBounds;
private BigDecimal growBounds;
}
调用者传的参数是SpuBoundTo,被调用者接收的参数是SpuBoundsEntity,这样使用的原因是@RequestBody
将对象转化为json,这样只需要属性名相同就可以接收,如果不这样就需要相同的对象才能接收
6.保存当前spu对应的所有sku信息
1.sku的基本信息
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SkuInfoService.java
void saveSkuInfo(SkuInfoEntity skuInfoEntity);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SkuInfoServiceImpl.java
@Override
public void saveSkuInfo(SkuInfoEntity skuInfoEntity) {
this.baseMapper.insert(skuInfoEntity);
}
2.sku的图片信息
保存sku图片信息是利用逆向工程生成的批量保存方法saveBatch
skuImagesService.saveBatch(imagesEntities);
3.sku的销售属性信息
保存sku销售属性是利用逆向工程生成的批量保存方法saveBatch
skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
4.sku的优惠、满减等信息(远程调用)
所需to
gulimall-common/src/main/java/site/zhourui/common/to/SkuReductionTo.java
package site.zhourui.common.to;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class SkuReductionTo {
private Long skuId;
private int fullCount;
private BigDecimal discount;
private int countStatus;
private BigDecimal fullPrice;
private BigDecimal reducePrice;
private int priceStatus;
private List<MemberPrice> memberPrice;
}
gulimall-coupon/src/main/java/site/zhourui/gulimall/coupon/controller/SpuBoundsController.java
新增方法
@PostMapping("/coupon/skufullreduction/saveinfo")
R saveSkuReduction(@RequestBody SkuReductionTo skuReductionTo);
被调用者
gulimall-coupon/src/main/java/site/zhourui/gulimall/coupon/controller/SkuFullReductionController.java
@PostMapping("/saveinfo")
public R saveInfo(@RequestBody SkuReductionTo reductionTo){
skuFullReductionService.saveSkuReduction(reductionTo);
return R.ok();
}
被调用者中需要实现对优惠信息的保存的接口
gulimall-coupon/src/main/java/site/zhourui/gulimall/coupon/service/SkuFullReductionService.java
新增接口
void saveSkuReduction(SkuReductionTo reductionTo);
gulimall-coupon/src/main/java/site/zhourui/gulimall/coupon/service/impl/SkuFullReductionServiceImpl.java
新增接口实现
@Override
public void saveSkuReduction(SkuReductionTo reductionTo) {
//1、// //5.4)、sku的优惠、满减等信息;gulimall_sms->sms_sku_ladder\sms_sku_full_reduction\sms_member_price
//sms_sku_ladder
SkuLadderEntity skuLadderEntity = new SkuLadderEntity();
skuLadderEntity.setSkuId(reductionTo.getSkuId());
skuLadderEntity.setFullCount(reductionTo.getFullCount());
skuLadderEntity.setDiscount(reductionTo.getDiscount());
skuLadderEntity.setAddOther(reductionTo.getCountStatus());
if(reductionTo.getFullCount() > 0){
skuLadderService.save(skuLadderEntity);
}
//2、sms_sku_full_reduction
SkuFullReductionEntity reductionEntity = new SkuFullReductionEntity();
BeanUtils.copyProperties(reductionTo,reductionEntity);
if(reductionEntity.getFullPrice().compareTo(new BigDecimal("0"))==1){
this.save(reductionEntity);
}
//3、sms_member_price
List<MemberPrice> memberPrice = reductionTo.getMemberPrice();
List<MemberPriceEntity> collect = memberPrice.stream().map(item -> {
MemberPriceEntity priceEntity = new MemberPriceEntity();
priceEntity.setSkuId(reductionTo.getSkuId());
priceEntity.setMemberLevelId(item.getId());
priceEntity.setMemberLevelName(item.getName());
priceEntity.setMemberPrice(item.getPrice());
priceEntity.setAddOther(1);
return priceEntity;
}).filter(item->{
return item.getMemberPrice().compareTo(new BigDecimal("0")) == 1;
}).collect(Collectors.toList());
memberPriceService.saveBatch(collect);
}
8.分组批量启用模块,及设置模块最大内存
1.分组批量启用模块
选着需要批量保存的服务并添加
添加完成后重命名后就可批量启动了
2.设置模块最大使用内存
每个模块都设置相同的值
9.新增商品测试
1.mysql设置事务隔离级别(方便事务调试)
mysql默认的隔离级别为
读已提交
,为了能够在调试过程中,获取到数据库中的数据信息,可以调整隔离级别为读未提交
:但是它对于当前的事务窗口生效,如果想要设置全局的,需要加上global字段。
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM `pms_spu_info`
一旦报错了事务回滚了,该条数据就消失了
2.数据库自增,存入自己的数据
比如此处报错信息
Cause: java.sql.SQLException: Field ‘spu_id’ doesn’t have a default value
解释:数据库spu_id字段有默认值,但是我们传入了值
原因:数据库spu_id字段设置了自增,但是我们传入了值
1.解决方案一
将该字段实体类的@TableId加上type = IdType.INPUT,表示可输入
/**
* 商品id
*/
@TableId(type = IdType.INPUT)
private Long spuId;
2.解决方法二
将该字段的自动递增关闭
3.存入空图片地址问题
原因:
前端传入spu图片时没有选中图片时该路径会是空
解决保存sku的图片信息时,先筛选一次,imgurl为空的话就不保存了
10.SPU检索
1.检索条件
2.后端增加接口
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SpuInfoService.java
新增接口
PageUtils queryPageByCondition(Map<String, Object> params);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SpuInfoServiceImpl.java
新增接口实现
@Override
public PageUtils queryPageByCondition(Map<String, Object> params) {
QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if(!StringUtils.isEmpty(key)){
wrapper.and((w)->{
w.eq("id",key).or().like("spu_name",key);
});
}
// status=1 and (id=1 or spu_name like xxx)
String status = (String) params.get("status");
if(!StringUtils.isEmpty(status)){
wrapper.eq("publish_status",status);
}
String brandId = (String) params.get("brandId");
if(!StringUtils.isEmpty(brandId)&&!"0".equalsIgnoreCase(brandId)){
wrapper.eq("brand_id",brandId);
}
String catelogId = (String) params.get("catelogId");
if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId)){
wrapper.eq("catalog_id",catelogId);
}
/**
* status: 2
* key:
* brandId: 9
* catelogId: 225
*/
IPage<SpuInfoEntity> page = this.page(
new Query<SpuInfoEntity>().getPage(params),
wrapper
);
return new PageUtils(page);
}
gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/SpuInfoController.java
修改查询方法,调用条件查询
/**
* 列表
*/
@RequestMapping("/list")
//@RequiresPermissions("product:spuinfo:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = spuInfoService.queryPageByCondition(params);
return R.ok().put("page", page);
}
3.时间格式问题
解决
gulimall-product/src/main/resources/application.yml加上如下配置
该配置会将该模块下的所有时间转化为指定格式
jackson:
date-format: yyyy-MM-dd HH:mm:ss
4.重启并测试
测试结果
11.SKU检索
1.检索条件
2.后端新增接口
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/SkuInfoService.java
新增接口
PageUtils queryPageByCondition(Map<String, Object> params);
gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/SkuInfoServiceImpl.java
新增接口实现
@Override
public PageUtils queryPageByCondition(Map<String, Object> params) {
QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<>();
/**
* key:
* catelogId: 0
* brandId: 0
* min: 0
* max: 0
*/
String key = (String) params.get("key");
if(!StringUtils.isEmpty(key)){
queryWrapper.and((wrapper)->{
wrapper.eq("sku_id",key).or().like("sku_name",key);
});
}
String catelogId = (String) params.get("catelogId");
if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId)){
queryWrapper.eq("catalog_id",catelogId);
}
String brandId = (String) params.get("brandId");
if(!StringUtils.isEmpty(brandId)&&!"0".equalsIgnoreCase(catelogId)){
queryWrapper.eq("brand_id",brandId);
}
String min = (String) params.get("min");
if(!StringUtils.isEmpty(min)){
queryWrapper.ge("price",min);
}
String max = (String) params.get("max");
if(!StringUtils.isEmpty(max) ){
try{
BigDecimal bigDecimal = new BigDecimal(max);
if(bigDecimal.compareTo(new BigDecimal("0"))==1){
queryWrapper.le("price",max);
}
}catch (Exception e){
}
}
IPage<SkuInfoEntity> page = this.page(
new Query<SkuInfoEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/SkuInfoController.java
修改list方法
/**
* 列表
*/
@RequestMapping("/list")
//@RequiresPermissions("product:skuinfo:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = skuInfoService.queryPageByCondition(params);
return R.ok().put("page", page);
}