小白一只,在做电商项目使用vant的sku组件时遇到了很多问题,其中主要的就是数据的的绑定与格式问题,并不知道后台如何来传给我sku的数据格式,在网上大多都是前台简单的死数据实现的基础sku,并没有后台写后台数据怎么传的。对于小白来说还是有困难的,所以希望能帮到你
1.首先阅读手册了解sku的结构,大概来说就是一个对象里面有俩数组还有一些值
2.对于后台我们就可以建一个与之对应的实体类
@Data
@Accessors(chain = true)
public class MallGoodsSkuDto implements Serializable {
private List<SkuDto> tree; //规格树 里面存的具体规格
private JSONArray list;
private BigDecimal price;
private Integer quota;//
private Integer stock_num;
private Boolean hide_stock = false;
private String collection_id = "2261"; //无规格商品
private Boolean none_sku = false; //是否是无规格商品
@Data
@Accessors(chain = true)
class SkuDetails {
private String id;//: 2259, // skuId
private Map<String, String> s_list; //
// private String s1;//: '1', // 规格类目 k_s 为 s1 的对应规格值 id
// private String s2;//: '1', // 规格类目 k_s 为 s2 的对应规格值 id
private BigDecimal price;//: 100, // 价格(单位分)
private Integer stock_num;//: 110 // 当前 sku 组合对应的库存
}
@Data
@Accessors(chain = true)
public static class SkuDto {
private String k; //: '颜色', // skuKeyName:规格类目名称
private String k_s; //: 's1', // skuKeyStr:sku 组合列表(下方 list)中当前类目对应的 key 值,value 值会是从属于当前类目的一个规格值 id
private List<SkuValueDto> v;//: [
private Boolean largeImageMode = true; // 是否展示大图模式
}
@Data
@Accessors(chain = true)
public static class SkuValueDto {
private String id; // skuValueId:规格值 id
private String name; // skuValueName:规格值名称
private BigDecimal price;//每个规格对应的价格
private Integer stock_num;//规格对应库存
private String imgUrl; // 规格类目图片,只有第一个规格类目可以定义图片
private String previewImgUrl; // 用于预览显示的规格类目图片
}
}
3.建完类,就用get set方法给字段赋值就可以了 最后将这个实体类返回给前台
public class TestController implements Serializable {
@Autowired
MallGoodsSkuService goodsSkuService;
@Autowired
MallGoodsService goodsService;
@PostMapping("/skuTest")
public WebResult<MallGoodsSkuDto> test(String id) {
MallGoodsSkuDto mallGoodsSkuDto = new MallGoodsSkuDto();
//根据商品id找到对应的sku 得到sku实体数据
MallGoodsSkuEntity entity = new MallGoodsSkuEntity();
//创建一个QueryWrapper查询器
QueryWrapper<MallGoodsSkuEntity> queryWrapper = new QueryWrapper<>();
//将要查询的商品塞入实体类中
entity.setGoodsId(id);
//将实体类塞入查询器中
queryWrapper.setEntity(entity);
//将查询器放入查询
List<MallGoodsSkuEntity> entityList = goodsSkuService.list(queryWrapper);
//判断一下是否是无规格商品
if (entityList.size() == 0) {
// mallGoodsSkuDto.setNone_sku(true);
return WebResult.error("这个商品没有添加商品属性,暂时无法购买");
}
//得到数据后将数据存入到与前端相对应的sku格式中去
MallGoodsEntity mallGoodsEntity = goodsService.getById(id);
// 1.先实现sku中除数组之外的常规数据
//设置默认价格 为商品当前价格
mallGoodsSkuDto.setPrice(mallGoodsEntity.getNewPrice());
//设置限购
mallGoodsSkuDto.setQuota(mallGoodsEntity.getBuyNumber());
List<MallGoodsSkuDto.SkuDto> tree = new ArrayList<>();
for (MallGoodsSkuEntity goodsSkuEntity : entityList) {
//tree内包括 规格名称 和规格key值 以及规格详细数组(具体信息)
//1.准备规格详细数组
ArrayList<MallGoodsSkuDto.SkuValueDto> valueDtoArrayList = new ArrayList<>();
valueDtoArrayList.add(new MallGoodsSkuDto.SkuValueDto()
.setId(goodsSkuEntity.getId())
.setName(goodsSkuEntity.getName())
.setImgUrl(goodsSkuEntity.getImage())
.setPrice(mallGoodsSkuDto.getPrice()));
tree.add(new MallGoodsSkuDto.SkuDto()
//设置规格名称 如颜色
.setK(goodsSkuEntity.getSpecName())
//塞入详细信息列表
.setV(valueDtoArrayList)
//设置属性key值
.setK_s("s" + goodsSkuEntity.getId()));
}
//将组好的树放入实体类中
mallGoodsSkuDto.setTree(tree);
//准备list属性组合数据
JSONArray jsonArray = new JSONArray();
for (MallGoodsSkuDto.SkuDto skuDto : tree) {
JSONObject jsonObject = new JSONObject();
int i = 0;
for (MallGoodsSkuDto.SkuValueDto skuValueDto : skuDto.getV()) {
jsonObject.put("s" + skuValueDto.getId(), skuValueDto.getId());
jsonObject.put("price", skuValueDto.getPrice());
jsonObject.put("stock_num",skuValueDto.getStock_num());
jsonObject.put("stock_num",100);
}
jsonObject.put("id", ++i + "");
// jsonObject.put("price", );
jsonArray.add(jsonObject);
}
//设置总库存
mallGoodsSkuDto.setStock_num(100);
mallGoodsSkuDto.setList(jsonArray);
return WebResult.ok(mallGoodsSkuDto);
}
}
4.前台接数据的函数
Show(id, index) {
this.skuData.goods_info = this.godList[index]
// console.log("skudata",this.skuData.goods_info)
this.show = !this.show
this.$axios.post('/api/mall-seller/skuTest', {}, {params: {id: id}}).then(res => {
if (res.code == 1) {
this.skuData.sku = res.data
this.skuData.goods_info = this.godList[index];
this.skuData.goods_id = id;
console.log("list", res.data)
}
}, res => {
console.log('error') //调用失败
})
},
},
}
5.后来发现价格怎么显示都不对,阅读手册发现是vant给默认设置的金钱单位是分,就很烦,我用了一个插槽解决的
<van-sku
v-model="show"
v-if="show"
:sku="skuData.sku"
:goods="skuData.goods_info"
:goods-id="skuData.goods_id"
:hide-stock="skuData.sku.hide_stock"
:quota="skuData.sku.quota"
@buy-clicked="onBuyClicked"
@add-cart="onAddCartClicked"
>
<!-- 自定义 sku-header-price -->
<template #sku-header-price="props">
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol" >¥</span>
//重点注意 此处应设置vant手册中的初始化sku选择列表 不然只能支持单属性价格问题
<span class="van-sku__price-num">{{props.selectedSkuComb.price }}</span>
</div>
</template>
</van-sku>
6.前台最终样式
6.顺便看一下后台传来的数据格式 一个对象里面两个数组,还有树里面的对象都能对应上手册里的结构