在商品详情页,每一个商品后面,都会有一个编辑按钮:
点击这个按钮,就会打开一个商品编辑窗口,我们看下它所绑定的点击事件:
对应的方法:
async editGoods(oldGoods) {
// 发起请求,查询商品详情和skus
oldGoods.spuDetail = await this.$http.loadData("/item/spu/detail/" + oldGoods.id);
oldGoods.skus = await this.$http.loadData("/item/sku/list?id=" + oldGoods.id);
// 修改标记
this.isEdit = true;
// 控制弹窗可见:
this.show = true;
// 获取要编辑的goods
this.oldGoods = oldGoods;
},
可以看到这里发起了两个请求,在查询商品详情和sku信息。
因为在商品列表页面,只有spu的基本信息:id、标题、品牌、商品分类等。比较复杂的商品详情(spuDetail)和sku信息都没有,编辑页面要回显数据,就需要查询这些内容。
因此,接下来我们就编写后台接口,提供查询服务接口。
controller
需要分析的内容:
@GetMapping("/spu/detail/{id}")
public ResponseEntity<SpuDetail> querySpuDetailById(@PathVariable("id") Long id) {
SpuDetail detail = this.goodsService.querySpuDetailById(id);
if (detail == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return ResponseEntity.ok(detail);
}
service
public SpuDetail querySpuDetailById(Long id) {
return this.spuDetailMapper.selectByPrimaryKey(id);
}
分析
controller
@GetMapping("sku/list")
public ResponseEntity<List<Sku>> querySkuBySpuId(@RequestParam("id") Long id) {
List<Sku> skus = this.goodsService.querySkuBySpuId(id);
if (skus == null || skus.size() == 0) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return ResponseEntity.ok(skus);
}
service
需要注意的是,为了页面回显方便,我们一并把sku的库存stock也查询出来
public List<Sku> querySkuBySpuId(Long spuId) {
// 查询sku
Sku record = new Sku();
record.setSpuId(spuId);
List<Sku> skus = this.skuMapper.select(record);
for (Sku sku : skus) {
// 同时查询出库存
sku.setStock(this.stockMapper.selectByPrimaryKey(sku.getId()).getStock());
}
return skus;
}
测试:
随便点击一个编辑按钮,发现数据回显完成:
这里的保存按钮与新增其实是同一个,因此提交的逻辑也是一样的,这里不再赘述。
随便修改点数据,然后点击保存,可以看到浏览器已经发出请求:
接下来,我们编写后台,实现修改商品接口。
/**
* 新增商品
* @param spu
* @return
*/
@PutMapping
public ResponseEntity<Void> updateGoods(@RequestBody SpuBo spu) {
try {
this.goodsService.update(spu);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
spu数据可以修改,但是SKU数据无法修改,因为有可能之前存在的SKU现在已经不存在了,或者以前的sku属性都不存在了。比如以前内存有4G,现在没了。
因此这里直接删除以前的SKU,然后新增即可。
代码:
@Transactional
public void update(SpuBo spu) {
// 查询以前sku
List<Sku> skus = this.querySkuBySpuId(spu.getId());
// 如果以前存在,则删除
if(!CollectionUtils.isEmpty(skus)) {
List<Long> ids = skus.stream().map(s -> s.getId()).collect(Collectors.toList());
// 删除以前库存
Example example = new Example(Stock.class);
example.createCriteria().andIn("skuId", ids);
this.stockMapper.deleteByExample(example);
// 删除以前的sku
Sku record = new Sku();
record.setSpuId(spu.getId());
this.skuMapper.delete(record);
}
// 新增sku和库存
saveSkuAndStock(spu.getSkus(), spu.getId());
// 更新spu
spu.setLastUpdateTime(new Date());
spu.setCreateTime(null);
spu.setValid(null);
spu.setSaleable(null);
this.spuMapper.updateByPrimaryKeySelective(spu);
// 更新spu详情
this.spuDetailMapper.updateByPrimaryKeySelective(spu.getSpuDetail());
}
与以前一样。
对于商品模块的管理,在目前所写进度中为复杂繁琐的一块,后端返回的数据需要与前端模板字段一定要对应,在写代码遇到比较困难的地方是对前端所需要的获取的字段与后端不一致。由于对前端vue模版不是特别熟悉,所遇到的问题也是各种奇葩的都有。
该项目未实现的模板有:
商品的删除、上下架