|
|
# 商品服务
|
|
|
|
|
|
## 1.新增商品
|
|
|
|
|
|
### 1.1 品牌的关联
|
|
|
|
|
|
#### 1.1.1 PubSub依赖缺失
|
|
|
|
|
|
打开新增商品页面的时候会出现的错误提示:
|
|
|
|
|
|

|
|
|
|
|
|
原因是缺少:PubSub相关依赖
|
|
|
|
|
|
解决办法
|
|
|
|
|
|
* 使用npm添加依赖:npm install --save pubsub-js(失败的话使用此命令:cnpm install --save pubsub-js)
|
|
|
* 在src下的main.js中引用:
|
|
|
import PubSub from 'pubsub-js'
|
|
|
Vue.prototype.PubSub = PubSub
|
|
|
* 在.eslintrc.js中添加一下配置
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.1.2 品牌关联
|
|
|
|
|
|
拷贝对应的前端页面文件
|
|
|
|
|
|

|
|
|
|
|
|
添加后端对应的服务
|
|
|
|
|
|

|
|
|
|
|
|
然后service中查询处理
|
|
|
|
|
|

|
|
|
|
|
|
最后的显示效果
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.1.3 会员等级
|
|
|
|
|
|
  首先我们需要启动会员模块,并且配置对应的网关路由信息
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
#### 1.1.4 规格参数
|
|
|
|
|
|
  在新增商品的第二步我们就需要设置对应的规格参数,而这些规格参数是根据前面一步选择的三级分类来查询出来的。
|
|
|
|
|
|

|
|
|
|
|
|
  响应对应的数据,我们需要先创建对应的VO对象。
|
|
|
|
|
|
```java
|
|
|
package com.msb.mall.product.vo;
|
|
|
|
|
|
import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
import com.msb.mall.product.entity.AttrEntity;
|
|
|
import lombok.Data;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
@Data
|
|
|
public class AttrGroupWithAttrsVo {
|
|
|
/**
|
|
|
* 分组id
|
|
|
*/
|
|
|
@TableId
|
|
|
private Long attrGroupId;
|
|
|
/**
|
|
|
* 组名
|
|
|
*/
|
|
|
private String attrGroupName;
|
|
|
/**
|
|
|
* 排序
|
|
|
*/
|
|
|
private Integer sort;
|
|
|
/**
|
|
|
* 描述
|
|
|
*/
|
|
|
private String descript;
|
|
|
/**
|
|
|
* 组图标
|
|
|
*/
|
|
|
private String icon;
|
|
|
/**
|
|
|
* 所属分类id
|
|
|
*/
|
|
|
private Long catelogId;
|
|
|
|
|
|
// 关联对应的属性信息
|
|
|
private List<AttrEntity> attrs;
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
  然后创建对应的controller
|
|
|
|
|
|

|
|
|
|
|
|
  然后创建对应的service
|
|
|
|
|
|

|
|
|
|
|
|
### 1.2 发布商品
|
|
|
|
|
|
#### 1.2.1 VO 接收数据
|
|
|
|
|
|
  前端页面提交的JSON数据非常复杂,我们需要在后端服务通过对应的VO对象来接收这些相关的数据。
|
|
|
|
|
|

|
|
|
|
|
|
然后通过在线的json格式处理工具生成对应的VO工具类
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.2 保存对应的数据
|
|
|
|
|
|
  需要保存的数据拆解为一下六个部分。
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.3 保存商品基本信息
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.4 保存商品描述
|
|
|
|
|
|

|
|
|
|
|
|
需要注意的地方:
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.4 保存图集信息
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.5 保存规格参数
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.6 SKU基本信息存储
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.7 SKU的图集
|
|
|
|
|
|

|
|
|
|
|
|
#### 1.2.8 SKU的销售属性
|
|
|
|
|
|

|
|
|
|
|
|
### 1.3 远程服务调用
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
#### 1.3.1 满减,折扣,会员价保存
|
|
|
|
|
|
在coupon服务中定义相关的接口及处理的service
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
然后我们在Product服务中来处理接口的调用
|
|
|
|
|
|

|
|
|
|
|
|
然后在商品的service中完成服务的调用
|
|
|
|
|
|

|
|
|
|
|
|
完成满减折扣和会员价的service存储
|
|
|
|
|
|
```java
|
|
|
public void saveSkuReduction(SkuReductionDTO dto) {
|
|
|
// 5.3 保存满减信息,折扣,会员价
|
|
|
// mall_sms: sms_sku_ladder sms_full_reduction sms_member_price
|
|
|
// 1.折扣
|
|
|
SkuLadderEntity ladderEntity = new SkuLadderEntity();
|
|
|
ladderEntity.setSkuId(dto.getSkuId());
|
|
|
ladderEntity.setFullCount(dto.getFullCount());
|
|
|
ladderEntity.setDiscount(dto.getDiscount());
|
|
|
ladderEntity.setAddOther(dto.getCountStatus());
|
|
|
if(ladderEntity.getFullCount() > 0){
|
|
|
ladderService.save(ladderEntity);
|
|
|
}
|
|
|
// 2.满减
|
|
|
SkuFullReductionEntity fullReductionEntity = new SkuFullReductionEntity();
|
|
|
BeanUtils.copyProperties(dto,fullReductionEntity);
|
|
|
if(fullReductionEntity.getFullPrice().compareTo(new BigDecimal(0)) == 1){
|
|
|
this.save(fullReductionEntity);
|
|
|
}
|
|
|
// 3.会员价
|
|
|
List<MemberPriceEntity> memberPriceEntities = dto.getMemberPrice().stream().map(item -> {
|
|
|
MemberPriceEntity priceEntity = new MemberPriceEntity();
|
|
|
priceEntity.setSkuId(dto.getSkuId());
|
|
|
priceEntity.setMemberLevelId(item.getId());
|
|
|
priceEntity.setMemberPrice(item.getPrice());
|
|
|
priceEntity.setAddOther(1); // 是否可叠加
|
|
|
return priceEntity;
|
|
|
}).collect(Collectors.toList());
|
|
|
memberPriceService.saveBatch(memberPriceEntities);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 1.3.2 会员积分存储
|
|
|
|
|
|
会员积分信息也是存储在Coupon服务中,我们同样需要通过Fegin来调用。
|
|
|
|
|
|

|
|
|
|
|
|
## 2.SPU管理
|
|
|
|
|
|
  提供不同条件的检索,分类,品牌,状态,关键字检索。
|
|
|
|
|
|

|
|
|
|
|
|
  后台我们需要在Service中完成对应的操作。
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
* SPU信息检索
|
|
|
* 分页查询
|
|
|
* 分类 品牌 状态 关键字查询
|
|
|
* @param params
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
public PageUtils queryPageByCondition(Map<String, Object> params) {
|
|
|
QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
|
|
|
// 设置对应的检索条件
|
|
|
// 1. 关键字查询
|
|
|
String key = (String) params.get("key");
|
|
|
if(!StringUtils.isEmpty(key)){
|
|
|
// 需要添加关键字查询
|
|
|
wrapper.and((w)->{
|
|
|
w.eq("id",key)
|
|
|
.or().like("spu_name",key)
|
|
|
.or().like("spu_description",key);
|
|
|
});
|
|
|
}
|
|
|
// status
|
|
|
String status = (String) params.get("status");
|
|
|
if(!StringUtils.isEmpty(status)){
|
|
|
wrapper.eq("publish_status",status);
|
|
|
}
|
|
|
// catalogId
|
|
|
String catalogId = (String) params.get("catalogId");
|
|
|
if(!StringUtils.isEmpty(catalogId) && !"0".equalsIgnoreCase(catalogId)){
|
|
|
wrapper.eq("catalog_id",catalogId);
|
|
|
}
|
|
|
// brandId
|
|
|
String brandId = (String) params.get("brandId");
|
|
|
if(!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)){
|
|
|
wrapper.eq("brand_id",brandId);
|
|
|
}
|
|
|
|
|
|
IPage<SpuInfoEntity> page = this.page(
|
|
|
new Query<SpuInfoEntity>().getPage(params),
|
|
|
wrapper
|
|
|
);
|
|
|
return new PageUtils(page);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
  然后解决页面显示数据的问题,比如类别和品牌显示的编号,创建时间和更新时间显示格式问题。
|
|
|
|
|
|

|
|
|
|
|
|
重启服务
|
|
|
|
|
|

|
|
|
|
|
|
上面的是设置全局的格式化方式,如果我也特殊设置,这时我们可以在对应的entity对象的属性上通过@JsonFormat 来指定,此处指定的会覆盖掉全局的设置。
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
针对显示的分类和品牌显示id的问题,我们需要通过对应的vo对象来传输,同时我们需要在service中完成对应的逻辑
|
|
|
|
|
|

|
|
|
|
|
|
显示的效果
|
|
|
|
|
|

|
|
|
|
|
|
## 3.商品管理
|
|
|
|
|
|
  商品管理也就是我们讲的SKU管理。实现多条件的检索,比如 类别,品牌,价格区间。关键字等查询。
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
* SKU 信息检索的方法
|
|
|
* 类别
|
|
|
* 品牌
|
|
|
* 价格区间
|
|
|
* 检索的关键字
|
|
|
* 分页查询
|
|
|
*
|
|
|
* @param params
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
public PageUtils queryPageByCondition(Map<String, Object> params) {
|
|
|
QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();
|
|
|
// 检索关键字
|
|
|
String key = (String) params.get("key");
|
|
|
if(!StringUtils.isEmpty(key)){
|
|
|
wrapper.and(w->{
|
|
|
w.eq("sku_id",key).or().like("sku_name",key);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 分类
|
|
|
String catalogId = (String)params.get("catalogId");
|
|
|
if(!StringUtils.isEmpty(catalogId) && !"0".equalsIgnoreCase(catalogId)){
|
|
|
wrapper.eq("catalog_id",catalogId);
|
|
|
}
|
|
|
// 品牌
|
|
|
String brandId = (String)params.get("brandId");
|
|
|
if(!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)){
|
|
|
wrapper.eq("brand_id",brandId);
|
|
|
}
|
|
|
// 价格区间
|
|
|
String min = (String) params.get("min");
|
|
|
if(!StringUtils.isEmpty(min)){
|
|
|
wrapper.ge("price",min);
|
|
|
}
|
|
|
String max = (String) params.get("max");
|
|
|
if(!StringUtils.isEmpty(max)){
|
|
|
try {
|
|
|
// 如果max=0那么我们也不需要加这个条件
|
|
|
BigDecimal bigDecimal = new BigDecimal(max);
|
|
|
if(bigDecimal.compareTo(new BigDecimal(0)) == 1){
|
|
|
// 说明 max > 0
|
|
|
wrapper.le("price",max);
|
|
|
}
|
|
|
}catch (Exception e){
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
IPage<SkuInfoEntity> page = this.page(
|
|
|
new Query<SkuInfoEntity>().getPage(params),
|
|
|
wrapper
|
|
|
);
|
|
|
|
|
|
return new PageUtils(page);
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|

|