记得上下班打卡 | git大法好,push需谨慎

Commit 3fc7d2f6 authored by 张国柄's avatar 张国柄

~api:店铺商品管理:批量导入数据;

parent 8806e550
...@@ -49,13 +49,22 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -49,13 +49,22 @@ public class GoblinStoreMgtGoodsImportService {
* 大小字母 || 数字 * 大小字母 || 数字
* 长度:0,50 * 长度:0,50
*/ */
public static final String ALPHABET_NUMBER_UNDER_50 = "^[a-zA-Z0-9]{0,50}$"; private static final String ALPHABET_NUMBER_UNDER_50 = "^[a-zA-Z0-9]{0,50}$";
/** /**
* 大小字母 || 数字 * 大小字母 || 数字
* 长度:0,32 * 长度:0,32
*/ */
public static final String ALPHABET_NUMBER_32 = "^[a-zA-Z0-9]{0,32}$"; private static final String ALPHABET_NUMBER_32 = "^[a-zA-Z0-9]{0,32}$";
/**
* 批量导入SPU.SQL队列入库分批处理数量
*/
private static final int BATCH_COUNT_SPU_SQL_TO_QUEUE = 10;
/**
* 批量导入SKU.SQL队列入库分批处理数量
*/
private static final int BATCH_COUNT_SKU_SQL_TO_QUEUE = 20;
private void goodsInformationDataAnalysisProcessingValid(GoblinGoodsImportDto dto, List<String> skuBarCodeTmpList, Integer rowNum) { private void goodsInformationDataAnalysisProcessingValid(GoblinGoodsImportDto dto, List<String> skuBarCodeTmpList, Integer rowNum) {
/* 商品编码校验|------------------------------------------------------------------------------ */ /* 商品编码校验|------------------------------------------------------------------------------ */
...@@ -98,9 +107,7 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -98,9 +107,7 @@ public class GoblinStoreMgtGoodsImportService {
throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行商品规格信息有误】", rowNum)); throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行商品规格信息有误】", rowNum));
} }
String[] specArr = skuSpec.split(":"); String[] specArr = skuSpec.split(":");
if (ArrayUtils.isEmpty(specArr) || specArr.length != 2 if (ArrayUtils.isEmpty(specArr) || specArr.length != 2 || specArr[0].length() > 5 || specArr[1].length() > 40) {
|| specArr[0].length() > 5 || specArr[1].length() > 40
) {
throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行商品规格信息有误】", rowNum)); throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行商品规格信息有误】", rowNum));
} }
...@@ -155,85 +162,121 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -155,85 +162,121 @@ public class GoblinStoreMgtGoodsImportService {
List<String> skuBarCodeTmpList = CollectionUtil.arrayListString(); List<String> skuBarCodeTmpList = CollectionUtil.arrayListString();
List<GoblinGoodsInfoVo> goodsInfoVos = ObjectUtil.goblinGoodsInfoVoArrayList(); List<GoblinGoodsInfoVo> goodsInfoVos = ObjectUtil.goblinGoodsInfoVoArrayList();
List<GoblinGoodsSkuInfoVo> goodsSkuInfoVos = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList(); List<GoblinGoodsSkuInfoVo> goodsSkuInfoVos = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
LinkedList<Object[]> initGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
EasyExcel.read(file.getInputStream(), GoblinGoodsImportDto.class, new AnalysisEventListener<GoblinGoodsImportDto>() { EasyExcel.read(file.getInputStream(), GoblinGoodsImportDto.class, new AnalysisEventListener<GoblinGoodsImportDto>() {
@Override @Override
public void onException(Exception exception, AnalysisContext context) throws Exception { public void onException(Exception exception, AnalysisContext context) throws Exception {
if (exception instanceof ExcelDataConvertException) { if (exception instanceof ExcelDataConvertException) {
Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex(); Integer rowIndex = ((ExcelDataConvertException) exception).getRowIndex();
Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex(); Integer columnIndex = ((ExcelDataConvertException) exception).getColumnIndex();
throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行,第%s列数据格式有误】", rowIndex + 1, columnIndex + 1)); throw new LiquidnetServiceException("-1", String.format("数据内容不规范【第%s行,第%s列数据格式有误】", rowIndex + 1, columnIndex + 1));
} }
super.onException(exception, context); super.onException(exception, context);
} }
@Override @Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) { public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
Integer approximateTotalRowNumber = context.readSheetHolder().getApproximateTotalRowNumber(); Integer approximateTotalRowNumber = context.readSheetHolder().getApproximateTotalRowNumber();
if (approximateTotalRowNumber > 501) { if (approximateTotalRowNumber > 501) {
log.warn("店铺商品管理:批量导入数据:异常[UID={},storeId={},totalRowNumber={}]", uid, storeId, approximateTotalRowNumber); log.warn("店铺商品管理:批量导入数据:异常[UID={},storeId={},totalRowNumber={}]", uid, storeId, approximateTotalRowNumber);
throw new LiquidnetServiceException("-1", "超出总行数限制500"); throw new LiquidnetServiceException("-1", "超出总行数限制500");
} }
super.invokeHead(headMap, context); super.invokeHead(headMap, context);
} }
@Override @Override
public void invoke(GoblinGoodsImportDto dto, AnalysisContext analysisContext) { public void invoke(GoblinGoodsImportDto dto, AnalysisContext analysisContext) {
Integer rowIndex = analysisContext.readRowHolder().getRowIndex(); Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
goodsInformationDataAnalysisProcessingValid(dto, skuBarCodeTmpList, rowIndex + 1); goodsInformationDataAnalysisProcessingValid(dto, skuBarCodeTmpList, rowIndex + 1);
GoblinGoodsInfoVo lastGoodsInfoVo = CollectionUtils.isEmpty(goodsInfoVos) ? null : goodsInfoVos.get(goodsInfoVos.size() - 1); GoblinGoodsInfoVo lastGoodsInfoVo = CollectionUtils.isEmpty(goodsInfoVos) ? null : goodsInfoVos.get(goodsInfoVos.size() - 1);
GoblinGoodsInfoVo goodsInfoVo = goodsInformationDataAnalysisProcessingForSpu(dto, lastGoodsInfoVo, uid, storeId, GoblinGoodsInfoVo goodsInfoVo = goodsInformationDataAnalysisProcessingForSpu(dto, lastGoodsInfoVo, uid, storeId, LocalDateTime.now(), goodsSkuInfoVos);
LocalDateTime.now(), goodsSkuInfoVos, initGoodsSkuObjs);
if (null != goodsInfoVo) { if (null != goodsInfoVo) {
log.debug("dt2:{}", goodsInfoVo); log.debug("dt2:{}", goodsInfoVo);
goodsInfoVos.add(goodsInfoVo); goodsInfoVos.add(goodsInfoVo);
} }
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {// 解析完成...
log.debug("dt3-1:{}", JsonUtils.toJson(goodsInfoVos));
log.debug("dt3-2:{}", JsonUtils.toJson(goodsSkuInfoVos));
List<String> existGoodsSkuNoList = goblinMongoUtils.existGoodsSkuNoBySkuNoList(storeId, skuBarCodeTmpList);
if (!CollectionUtils.isEmpty(existGoodsSkuNoList)) {
if (existGoodsSkuNoList.size() > 3) {
throw new LiquidnetServiceException("-1", String.format("规格条码与已添加商品条码重复,重复条码如下: %s,...", StringUtils.join(existGoodsSkuNoList.subList(0, 3), ",")));
}
throw new LiquidnetServiceException("-1", String.format("规格条码与已添加商品条码重复,重复条码如下: %s", StringUtils.join(existGoodsSkuNoList, ",")));
}
goblinMongoUtils.insertMgtGoodsInfoVos(goodsInfoVos);
goblinMongoUtils.insertMgtGoodsSkuInfoVos(goodsSkuInfoVos);
LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
toMqSqls.add(SqlMapping.get("goblin_goods.insert"));
LinkedList<Object[]> initGoodsObjs = CollectionUtil.linkedListObjectArr();
toMqSqls.add(SqlMapping.get("goblin_goods_image.insert_byreplace"));// SPU图片
LinkedList<Object[]> initGoodsImageObjs = CollectionUtil.linkedListObjectArr();
toMqSqls.add(SqlMapping.get("goblin_goods_spu_spec_value.insert_byreplace"));// SPU规格信息
LinkedList<Object[]> initGoodsSpuSpecValueObjs = CollectionUtil.linkedListObjectArr();
for (int i = 0, size = goodsInfoVos.size(); i < size; i++) {
GoblinGoodsInfoVo goodsInfoVo = goodsInfoVos.get(i);
initGoodsObjs.add(new Object[]{goodsInfoVo.getSpuId(), goodsInfoVo.getSpuNo(), goodsInfoVo.getName(), goodsInfoVo.getSubtitle(), goodsInfoVo.getSellPrice(), goodsInfoVo.getPriceGe(), goodsInfoVo.getPriceLe(), goodsInfoVo.getIntro(), goodsInfoVo.getDetails(), goodsInfoVo.getCoverPic(), goodsInfoVo.getVideo(), goodsInfoVo.getSpecMode(), goodsInfoVo.getStoreId(), goodsInfoVo.getCateFid(), goodsInfoVo.getCateSid(), goodsInfoVo.getCateTid(), goodsInfoVo.getStoreCateFid(), goodsInfoVo.getStoreCateSid(), goodsInfoVo.getStoreCateTid(), goodsInfoVo.getBrandId(), goodsInfoVo.getShelvesHandle(), goodsInfoVo.getShelvesTime(), goodsInfoVo.getSpuValidity(), goodsInfoVo.getVirtualFlg(), goodsInfoVo.getStatus(), goodsInfoVo.getShelvesStatus(), goodsInfoVo.getSpuAppear(), goodsInfoVo.getShelvesAt(), goodsInfoVo.getCreatedBy(), goodsInfoVo.getCreatedAt(), goodsInfoVo.getLogisticsTemplate()});
if (!CollectionUtils.isEmpty(goodsInfoVo.getImageList())) {
goodsInfoVo.getImageList().forEach(imageUrl -> initGoodsImageObjs.add(new Object[]{goodsInfoVo.getSpuId(), imageUrl}));
} }
goodsInfoVo.getSpecVoList().forEach(specVo -> {
specVo.getSpecValues().forEach(specValues -> {
initGoodsSpuSpecValueObjs.add(new Object[]{goodsInfoVo.getSpuId(), specVo.getSpecName(), specValues.getSpecVname(), specValues.getSpecVsort()});
});
});
if (initGoodsObjs.size() == BATCH_COUNT_SPU_SQL_TO_QUEUE) {
queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(), SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsImageObjs, initGoodsSpuSpecValueObjs));
initGoodsObjs.clear();
initGoodsImageObjs.clear();
initGoodsSpuSpecValueObjs.clear();
}
}
if (initGoodsObjs.size() > 0) {
queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(), SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsImageObjs, initGoodsSpuSpecValueObjs));
}
@Override toMqSqls.clear();
public void doAfterAllAnalysed(AnalysisContext analysisContext) {// 解析完成... toMqSqls.add(SqlMapping.get("goblin_goods_sku.insert"));
log.debug("dt3-1:{}", JsonUtils.toJson(goodsInfoVos)); LinkedList<Object[]> initGoodsSkuObjs = CollectionUtil.linkedListObjectArr();
log.debug("dt3-2:{}", JsonUtils.toJson(goodsSkuInfoVos)); toMqSqls.add(SqlMapping.get("goblin_goods_sku_spec_value.insert_byreplace"));// SKU规格信息
LinkedList<Object[]> initGoodsSkuSpecValueObjs = CollectionUtil.linkedListObjectArr();
List<String> existGoodsSkuNoList = goblinMongoUtils.existGoodsSkuNoBySkuNoList(storeId, skuBarCodeTmpList); goodsSkuInfoVos.forEach(goodsSkuInfoVo -> {
if (!CollectionUtils.isEmpty(existGoodsSkuNoList)) { goblinRedisUtils.setSkuStock(null, goodsSkuInfoVo.getSkuId(), goodsSkuInfoVo.getSkuStock());
if (existGoodsSkuNoList.size() > 3) { initGoodsSkuObjs.add(new Object[]{goodsSkuInfoVo.getSkuId(), goodsSkuInfoVo.getSpuId(), goodsSkuInfoVo.getSkuNo(), goodsSkuInfoVo.getName(), goodsSkuInfoVo.getSubtitle(),
throw new LiquidnetServiceException("-1", String.format("规格条码与已添加商品条码重复,重复条码如下: %s,...", StringUtils.join(existGoodsSkuNoList.subList(0, 3), ","))); goodsSkuInfoVo.getSellPrice(), goodsSkuInfoVo.getSkuPic(), goodsSkuInfoVo.getSkuIsbn(), goodsSkuInfoVo.getStock(), goodsSkuInfoVo.getSkuStock(),
} goodsSkuInfoVo.getWarningStock(), goodsSkuInfoVo.getPrice(), goodsSkuInfoVo.getPriceMember(), goodsSkuInfoVo.getWeight(), goodsSkuInfoVo.getBuyFactor(),
throw new LiquidnetServiceException("-1", String.format("规格条码与已添加商品条码重复,重复条码如下: %s", StringUtils.join(existGoodsSkuNoList, ","))); goodsSkuInfoVo.getBuyRoster(), goodsSkuInfoVo.getBuyLimit(), goodsSkuInfoVo.getStoreId(), goodsSkuInfoVo.getSkuValidity(), goodsSkuInfoVo.getVirtualFlg(),
} goodsSkuInfoVo.getStatus(), goodsSkuInfoVo.getShelvesStatus(), goodsSkuInfoVo.getSkuAppear(), goodsSkuInfoVo.getShelvesAt(), uid, goodsSkuInfoVo.getCreatedAt(), goodsSkuInfoVo.getLogisticsTemplate()
});
// goblinMongoUtils.insertMgtGoodsInfoVos(goodsInfoVos); goodsSkuInfoVo.getSkuSpecList().forEach(skuSpecDto -> initGoodsSkuSpecValueObjs.add(new Object[]{
// goblinMongoUtils.insertMgtGoodsSkuInfoVos(goodsSkuInfoVos); goodsSkuInfoVo.getSpuId(), goodsSkuInfoVo.getSkuId(), skuSpecDto.getSpecName(), skuSpecDto.getSpecVname()
// goodsSkuInfoVos.forEach(r -> goblinRedisUtils.setSkuStock(null, r.getSkuId(), r.getSkuStock())); }));
//
// LinkedList<String> toMqSqls = CollectionUtil.linkedListString(); if (initGoodsSkuObjs.size() == BATCH_COUNT_SKU_SQL_TO_QUEUE) {
// toMqSqls.add(SqlMapping.get("goblin_goods.insert")); queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(), SqlMapping.gets(toMqSqls, initGoodsSkuObjs, initGoodsSkuSpecValueObjs));
// LinkedList<Object[]> initGoodsObjs = CollectionUtil.linkedListObjectArr(); initGoodsSkuObjs.clear();
// goodsInfoVos.forEach(r -> initGoodsObjs.add(new Object[]{ initGoodsSkuSpecValueObjs.clear();
// r.getSpuId(), r.getSpuNo(), r.getName(), r.getSubtitle(), r.getSellPrice(),
// r.getPriceGe(), r.getPriceLe(), r.getIntro(), r.getDetails(), r.getCoverPic(),
// r.getVideo(), r.getSpecMode(), r.getStoreId(), r.getCateFid(), r.getCateSid(),
// r.getCateTid(), r.getStoreCateFid(), r.getStoreCateSid(), r.getStoreCateTid(), r.getBrandId(),
// r.getShelvesHandle(), r.getShelvesTime(), r.getSpuValidity(), r.getVirtualFlg(), r.getStatus(),
// r.getShelvesStatus(), r.getSpuAppear(), r.getShelvesAt(), r.getCreatedBy(), r.getCreatedAt(),
// r.getLogisticsTemplate()
// }));
// toMqSqls.add(SqlMapping.get("goblin_goods_sku.insert"));
// queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(), SqlMapping.gets(toMqSqls, initGoodsObjs, initGoodsSkuObjs));
} }
});
if (initGoodsSkuObjs.size() > 0) {
queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_GOODS.getKey(), SqlMapping.gets(toMqSqls, initGoodsSkuObjs, initGoodsSkuSpecValueObjs));
} }
).sheet(0).doReadSync();
}
}).sheet(0).doReadSync();
} }
private GoblinGoodsInfoVo goodsInformationDataAnalysisProcessingForSpu(GoblinGoodsImportDto dt,GoblinGoodsInfoVo lastGoodsInfoVo, private GoblinGoodsInfoVo goodsInformationDataAnalysisProcessingForSpu(GoblinGoodsImportDto dt, GoblinGoodsInfoVo lastGoodsInfoVo, String uid, String storeId, LocalDateTime now, List<GoblinGoodsSkuInfoVo> goodsSkuInfoVos) {
String uid, String storeId, LocalDateTime now,
List<GoblinGoodsSkuInfoVo> goodsSkuInfoVos, LinkedList<Object[]> initGoodsSkuObjs) {
log.debug("dt1:{}", dt.toString()); log.debug("dt1:{}", dt.toString());
boolean tobeNextSpuFlg = false; boolean tobeNextSpuFlg = false;
...@@ -251,7 +294,7 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -251,7 +294,7 @@ public class GoblinStoreMgtGoodsImportService {
// if (StringUtils.isNotEmpty(dt.getSpuBarCode())) { // if (StringUtils.isNotEmpty(dt.getSpuBarCode())) {
// lastGoodsInfoVo.setSpuNo(dt.getSpuBarCode());//* // lastGoodsInfoVo.setSpuNo(dt.getSpuBarCode());//*
// } else { // } else {
lastGoodsInfoVo.setSpuNo(lastGoodsInfoVo.getSpuId());//* lastGoodsInfoVo.setSpuNo(lastGoodsInfoVo.getSpuId());//*
// } // }
if (!CollectionUtils.isEmpty(dt.getSpuImgList())) { if (!CollectionUtils.isEmpty(dt.getSpuImgList())) {
lastGoodsInfoVo.setImageList(dt.getSpuImgList()); lastGoodsInfoVo.setImageList(dt.getSpuImgList());
...@@ -275,20 +318,11 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -275,20 +318,11 @@ public class GoblinStoreMgtGoodsImportService {
GoblinGoodsSkuInfoVo lastGoodsSkuInfoVo = this.goodsInformationDataAnalysisProcessingForSku(dt, lastGoodsInfoVo, uid, storeId, now, tobeNextSpuFlg); GoblinGoodsSkuInfoVo lastGoodsSkuInfoVo = this.goodsInformationDataAnalysisProcessingForSku(dt, lastGoodsInfoVo, uid, storeId, now, tobeNextSpuFlg);
if (null != lastGoodsSkuInfoVo) { if (null != lastGoodsSkuInfoVo) {
goodsSkuInfoVos.add(lastGoodsSkuInfoVo); goodsSkuInfoVos.add(lastGoodsSkuInfoVo);
initGoodsSkuObjs.add(new Object[]{
lastGoodsSkuInfoVo.getSkuId(), lastGoodsSkuInfoVo.getSpuId(), lastGoodsSkuInfoVo.getSkuNo(), lastGoodsSkuInfoVo.getName(), lastGoodsSkuInfoVo.getSubtitle(),
lastGoodsSkuInfoVo.getSellPrice(), lastGoodsSkuInfoVo.getSkuPic(), lastGoodsSkuInfoVo.getSkuIsbn(), lastGoodsSkuInfoVo.getStock(), lastGoodsSkuInfoVo.getSkuStock(),
lastGoodsSkuInfoVo.getWarningStock(), lastGoodsSkuInfoVo.getPrice(), lastGoodsSkuInfoVo.getPriceMember(), lastGoodsSkuInfoVo.getWeight(), lastGoodsSkuInfoVo.getBuyFactor(),
lastGoodsSkuInfoVo.getBuyRoster(), lastGoodsSkuInfoVo.getBuyLimit(), lastGoodsSkuInfoVo.getStoreId(), lastGoodsSkuInfoVo.getSkuValidity(), lastGoodsSkuInfoVo.getVirtualFlg(),
lastGoodsSkuInfoVo.getStatus(), lastGoodsSkuInfoVo.getShelvesStatus(), lastGoodsSkuInfoVo.getSkuAppear(), lastGoodsSkuInfoVo.getShelvesAt(), uid,
now, lastGoodsSkuInfoVo.getLogisticsTemplate()
});
} }
return tobeNextSpuFlg ? lastGoodsInfoVo : null; return tobeNextSpuFlg ? lastGoodsInfoVo : null;
} }
private GoblinGoodsSkuInfoVo goodsInformationDataAnalysisProcessingForSku(GoblinGoodsImportDto dt, GoblinGoodsInfoVo lastGoodsInfoVo, private GoblinGoodsSkuInfoVo goodsInformationDataAnalysisProcessingForSku(GoblinGoodsImportDto dt, GoblinGoodsInfoVo lastGoodsInfoVo, String uid, String storeId, LocalDateTime now, boolean tobeNextSpuFlg) {
String uid, String storeId, LocalDateTime now, boolean tobeNextSpuFlg) {
GoblinGoodsSkuInfoVo skuInfoVo = GoblinGoodsSkuInfoVo.getNew(); GoblinGoodsSkuInfoVo skuInfoVo = GoblinGoodsSkuInfoVo.getNew();
skuInfoVo.setName(""); skuInfoVo.setName("");
...@@ -312,9 +346,7 @@ public class GoblinStoreMgtGoodsImportService { ...@@ -312,9 +346,7 @@ public class GoblinStoreMgtGoodsImportService {
List<GoblinGoodsSpecValueVo> spuSpecValueVos = spuSpecVo.getSpecValues(); List<GoblinGoodsSpecValueVo> spuSpecValueVos = spuSpecVo.getSpecValues();
Optional<GoblinGoodsSpecValueVo> any = spuSpecValueVos.stream().filter(r -> r.getSpecVname().equals(skuSpecDto.getSpecVname())).findAny(); Optional<GoblinGoodsSpecValueVo> any = spuSpecValueVos.stream().filter(r -> r.getSpecVname().equals(skuSpecDto.getSpecVname())).findAny();
if (!any.isPresent()) { if (!any.isPresent()) {
spuSpecValueVos.add( spuSpecValueVos.add(GoblinGoodsSpecValueVo.getNew().setSpecVname(skuSpecDto.getSpecVname()).setSpecVsort(lastGoodsInfoVo.getSkuIdList().size() + 1));
GoblinGoodsSpecValueVo.getNew().setSpecVname(skuSpecDto.getSpecVname()).setSpecVsort(lastGoodsInfoVo.getSkuIdList().size() + 1)
);
spuSpecVo.setSpecValues(spuSpecValueVos); spuSpecVo.setSpecValues(spuSpecValueVos);
} }
} else {// 不匹配的规格直接跳过(默认只匹配商品第一行数据中的规格项) } else {// 不匹配的规格直接跳过(默认只匹配商品第一行数据中的规格项)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment