Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
a1e31e5ca4
@ -72,4 +72,7 @@ public class ShopProductSpecItem implements Serializable {
|
||||
@TableField(exist=false)
|
||||
private boolean isUpdate;
|
||||
|
||||
@ApiModelProperty(value = "规格名称")
|
||||
@TableField(exist=false)
|
||||
private String specName;
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
package com.suisung.mall.common.modules.sync;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@TableName("sycn_store_specs")
|
||||
@ApiModel("多规格数据表,用来执行导入的规格后续操作")
|
||||
public class SyncStoreSpecs {
|
||||
@TableId(value = "sycn_specs_id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "多规格编号", required = true, example = "10001")
|
||||
private Long sycnSpecsId;
|
||||
|
||||
@TableField(value = "product_number",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(value = "条形码", required = true, example = "10001")
|
||||
private String productNumber;
|
||||
|
||||
@TableField(value = "json_specs",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(
|
||||
value = "多规格JSON数据,格式如:[{\"spec\": [{\"name\": \"颜色\",\"value\": \"红色\"},{\"name\": \"尺寸\",\"value\": \"10\"}],\"priceAndstock\": {\"price\": 100,\"stock\": 10}}]",
|
||||
example = "[{\"spec\": [{\"name\": \"颜色\",\"value\": \"红色\"},{\"name\": \"尺寸\",\"value\": \"10\"}],\"priceAndstock\": {\"price\": 100,\"stock\": 10}}]"
|
||||
)
|
||||
private String jsonSpecs;
|
||||
|
||||
@TableField(value = "store_id",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(value = "店铺编号", required = true, example = "2001")
|
||||
private Integer storeId;
|
||||
|
||||
@TableField(value = "is_deal",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(value = "是否处理完成(1:是, 0:否)", required = true, example = "0")
|
||||
private String isDeal;
|
||||
|
||||
@TableField(value = "created_at",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(value = "新建时间", example = "2023-01-01T12:00:00")
|
||||
private Date createdAt;
|
||||
|
||||
@TableField(value = "updated_at",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
@ApiModelProperty(value = "更新时间", example = "2023-01-02T14:30:00")
|
||||
private Date updatedAt;
|
||||
|
||||
@ApiModelProperty(value = "分类id")
|
||||
@TableField(exist = false)
|
||||
private Integer categoryId;
|
||||
|
||||
@ApiModelProperty(value = "产品id")
|
||||
@TableField(exist = false)
|
||||
private Long productId;
|
||||
|
||||
@ApiModelProperty(value = "产品itemId")
|
||||
@TableField(exist = false)
|
||||
private Long itemId;
|
||||
}
|
||||
@ -47,9 +47,10 @@ public class JiebaUtils {
|
||||
private static final Pattern UNIT_REGEX = Pattern.compile("\\d+[.]?\\d*[a-zA-Z]+"); // 匹配500ml/1.8L
|
||||
private static final Pattern SPEC_REGEX = Pattern.compile("\\d+[a-zA-Z]+[*]\\d+"); // 匹配500L*10
|
||||
private static final Pattern MIXED_REGEX = Pattern.compile("[a-zA-Z]+[-]?\\d+"); // 匹配RSCW-1949
|
||||
private static final Pattern DIMENSION_REGEX = Pattern.compile("\\d+(?:\\\\.\\\\d+)?[\\\\u4e00-\\\\u9fa5a-zA-Z]+"); // 匹配维度(如2.0*2.3)
|
||||
private static final Pattern UNIT_CHN_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)(条|个|卷)\\b");//匹配只有数字+单位的,如牛油果2个
|
||||
private static final Pattern UNIT_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)([个条份根盒包])(?:\\s*([0-9]+)(g|克|ml|毫升)|\\s*/([袋箱盒份]))");//匹配商品名称+数量+数量单位+重量的 如牛油果2个150克
|
||||
private static final Pattern DIMENSION_REGEX = Pattern.compile("\\d+(?:\\\\.\\\\d+)?[\\u4e00-\\u9fa5a-zA-Z]+"); // 匹配维度(如2.0*2.3)
|
||||
private static final Pattern UNIT_CHN_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+|\\d*\\.?\\d+)\\s*(g|条|个|卷|kg|L)+\\*\\b");//匹配只有数字+单位的,如牛油果2个
|
||||
private static final Pattern UNIT_CHN_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+|\\d*\\.?\\d+)\\s*(g|条|个|卷|kg|L)+\\s*/([袋箱盒份条])");//匹配只有数字+单位的,如牛油果2个
|
||||
private static final Pattern UNIT_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)([个条份根盒包])(?:\\s*([0-9]+)(g|克|ml|毫升)|\\s*/([袋箱盒份条]))");//匹配商品名称+数量+数量单位+重量的 如牛油果2个150克
|
||||
//private static final Pattern DIMENSION_REGEX = Pattern.compile("([\\u4e00-\\u9fa5]+)(\\d+\\.?\\d*\\*\\d+\\.?\\d*(?:米)?)([\\u4e00-\\u9fa5]+)");
|
||||
private static final Map<String,Pattern> PROTECT_PATTERNS = new HashMap<String,Pattern>(){{
|
||||
put(PROTECT_UNIT,UNIT_REGEX);
|
||||
@ -65,6 +66,10 @@ public class JiebaUtils {
|
||||
put("dot","\\.");
|
||||
}};
|
||||
|
||||
public static final Set<String> filterWords=Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
|
||||
"袋","/","包","盒","个","箱","*","瓶","条","一级","木盒","特级","二级","条盒","礼盒","三级","整袋","塑料","把","整件"
|
||||
)));
|
||||
|
||||
|
||||
private static void loadUserDict() {
|
||||
// 方法1:通过文件加载
|
||||
@ -123,14 +128,30 @@ public class JiebaUtils {
|
||||
boolean unit = isUnitShop(text);
|
||||
if(special&&unit){
|
||||
Matcher matcher = UNIT_EVERY_REGEX.matcher(text);
|
||||
String original ="";
|
||||
String original2 ="";
|
||||
if(matcher.find()) {
|
||||
String original = matcher.group();
|
||||
original = matcher.group();
|
||||
}
|
||||
Matcher matcher2 = UNIT_CHN_REGEX.matcher(text);
|
||||
if(matcher2.find()) {
|
||||
original2= matcher2.group();
|
||||
}
|
||||
int originalINdex= text.indexOf(original);
|
||||
int originalINdex2= text.indexOf(original2);
|
||||
if(originalINdex>0&&originalINdex2>0){
|
||||
if(originalINdex<originalINdex2){
|
||||
// 使用中文保护标记包裹原始值
|
||||
String protectedText = PROTECT_START + original+ PROTECT_END;
|
||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||
matcher.appendTail(sb);
|
||||
}else {
|
||||
String protectedText = PROTECT_START +original2+original + PROTECT_END;
|
||||
matcher2.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||
matcher2.appendTail(sb);
|
||||
}
|
||||
}else if(special){
|
||||
}
|
||||
}else if(special||unit){
|
||||
Matcher matcher = UNIT_CHN_REGEX.matcher(text);
|
||||
if(matcher.find()) {
|
||||
String original = matcher.group();
|
||||
@ -140,6 +161,7 @@ public class JiebaUtils {
|
||||
matcher.appendTail(sb);
|
||||
}
|
||||
}else {
|
||||
stop:
|
||||
for (Map.Entry<String, Pattern> entry : PROTECT_PATTERNS.entrySet()) {
|
||||
Matcher matcher = entry.getValue().matcher(text);
|
||||
while (matcher.find()) {
|
||||
@ -148,10 +170,10 @@ public class JiebaUtils {
|
||||
String protectedText = PROTECT_START + original + PROTECT_END;
|
||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||
matcher.appendTail(sb);
|
||||
break;
|
||||
break stop;
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
break;
|
||||
break stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,7 +276,7 @@ public class JiebaUtils {
|
||||
JiebaSegmenter segmenter = new JiebaSegmenter();
|
||||
loadUserDict();
|
||||
String protectedText = protectPatterns(text);
|
||||
System.out.println("protectedText: " + protectedText);
|
||||
log.info("protectedText: {}", protectedText);
|
||||
List<String> tokens = segmenter.sentenceProcess(protectedText).stream()
|
||||
//.filter(word -> word.length() > 1) // 过滤单字
|
||||
// .sorted(Comparator.reverseOrder()) // 按词典词频降序
|
||||
@ -285,7 +307,13 @@ public class JiebaUtils {
|
||||
} else if (CATEGORY_LIBRARY.contains(word)) {
|
||||
fields.putIfAbsent("category", word);
|
||||
} else if (startsWithDigit(word)) {
|
||||
fields.putIfAbsent("specs", word.toLowerCase());
|
||||
for (String unit:UNITS){
|
||||
if (word.contains(unit)) {
|
||||
fields.putIfAbsent("specs", word);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//fields.putIfAbsent("specs", word.toLowerCase());
|
||||
}else if(SPECIAL_NAME.contains(word)){
|
||||
fields.putIfAbsent("productShortName", word);
|
||||
}else {
|
||||
@ -311,12 +339,12 @@ public class JiebaUtils {
|
||||
*
|
||||
*/
|
||||
if(words.size()>1){
|
||||
int index=words.size()-1;
|
||||
if(!startsWithLetterOrDigitRegex(words.get(index))){
|
||||
fields.putIfAbsent("productShortName", words.get(index));
|
||||
}else {
|
||||
fields.putIfAbsent("productShortName", words.get(index-1));
|
||||
}
|
||||
// int index=words.size()-1;
|
||||
// if(!startsWithLetterOrDigitRegex(words.get(index))){
|
||||
fields.putIfAbsent("productShortName", machProductName(words,fields.get("brand")));
|
||||
// }else {
|
||||
// fields.putIfAbsent("productShortName", words.get(index-1));
|
||||
// }
|
||||
}else {
|
||||
fields.putIfAbsent("productShortName", words.get(0));
|
||||
}
|
||||
@ -324,6 +352,31 @@ public class JiebaUtils {
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 倒叙匹查询配商品名称
|
||||
* @param words
|
||||
* @return
|
||||
*/
|
||||
private static String machProductName(List<String> words,String brand){
|
||||
int index=words.size()-1;
|
||||
String productName=words.get(index);
|
||||
while (index>-1){
|
||||
productName = words.get(index);
|
||||
if(productName.length()<2){
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
if(startsWithLetterOrDigitRegex(productName)||containsFilterWord(productName)||containsNumberLoop(productName)
|
||||
||(StringUtils.isNotEmpty(brand)&&productName.contains(brand))){
|
||||
index--;
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return productName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 特色字段匹配
|
||||
* @return
|
||||
@ -396,18 +449,50 @@ public class JiebaUtils {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含数字
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static boolean containsNumberLoop(String input) {
|
||||
for (char c : input.toCharArray()) {
|
||||
if (Character.isDigit(c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断过滤词
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static boolean containsFilterWord(String input) {
|
||||
for (String word : filterWords) {
|
||||
if ("\\*".equals(word)) {
|
||||
if (input.contains("*")) return true;
|
||||
}
|
||||
if (input.contains(word)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// JiebaUtils jiebaUtils = new JiebaUtils();
|
||||
String text = "云计算和区块链是热门技术";
|
||||
String text = "四海油彩米10Kg";
|
||||
// String text = "新鲜牛肉饺子500g";
|
||||
//String text = "志高1.8L电热水壶";
|
||||
// String text = "(单充)数据线2m";
|
||||
// String text = "雅安利2.0*2.3四件套";
|
||||
// String text = "RSCW-1949剃须刀";
|
||||
System.out.println(cleanNumberAndDigit("日本豆腐3条"));
|
||||
// System.out.println(cleanNumberAndDigit("双汇王中王火腿肠400G10*40g/包"));
|
||||
//String text="六指鼠童袜001";
|
||||
List<String> words = JiebaUtils.extractKeywords(text);
|
||||
System.out.println(words);
|
||||
// List<String> words = JiebaUtils.extractKeywords(text);
|
||||
//System.out.println(words);
|
||||
|
||||
Map<String,String> shopMap= JiebaUtils.getShopDetails(ProductTitleUtil.cleanTitle2(text));
|
||||
System.out.println(shopMap);
|
||||
|
||||
@ -53,14 +53,17 @@ public class ProductTitleUtil {
|
||||
Arrays.asList("华为", "苹果", "小米", "三星", "美的", "格力", "耐克", "阿迪达斯", "海尔","雀巢","伊利","蒙牛","达能","乐事","多力多滋","三只松鼠","良品铺子","可口可乐",
|
||||
"农夫山泉","元气森林","红牛","雅诗兰黛","欧莱雅","玉兰油","科颜氏","宝洁","汰渍","帮宝适","联合利华","Unilever","含多芬","清扬","大窑","谢村桥牌阡糯","谢村桥牌阡",
|
||||
"六个核桃","大豫竹","优乐多","安慕希","纳爱斯","舒客","宜轩", "蓝月亮","海尔","美的","松下","戴森","耐克","安踏","李宁","特仑苏","纯甄","安井","三全","哇哈哈",
|
||||
"龙江家园","达利园","春光","妙芙","南星","利嘉旺","卡得福","泓一","爱乡亲","思念","得力","中雪","江南点心局","德庄","六指鼠",
|
||||
"依水塬","乌苏啤酒","阿尔卑斯", "瑞旗","振雷","中狗","宝视达","冷酸灵","骆驼","NIKE","PAMU","康师傅","信智利","双兔","安足莱","新博美","新博","创利")
|
||||
"龙江家园","达利园","春光","妙芙","南星","利嘉旺","卡得福","泓一","爱乡亲","思念","得力","中雪","江南点心局","德庄","六指鼠","娃哈哈","开古","不二家","湘亮牌",
|
||||
"依水塬","乌苏啤酒","阿尔卑斯", "瑞旗","振雷","中狗","宝视达","冷酸灵","骆驼","NIKE","PAMU","康师傅","信智利","双兔","安足莱","新博美","湘亮牌","忆江南","张骞牌",
|
||||
"新博","创利","哈奇利","好口福","银鹭","开古","百事可乐","邛池","天旭牌","泗泉山","银狼","象芽王","拜将坛","健民","湘亮牌","周大黑","盛华牌","盛华","碗碗香","龙凤王",
|
||||
"陕南健源","百州红","八度名苑","旭美","今麦郞","勇闯天涯","青岛","一起赢","元気森林","云南红茶","盈亮","树堂","乡糯香","汉中魏","金源","疆丝麦耘","四海油","亿家康",
|
||||
"利民")
|
||||
));
|
||||
/**
|
||||
* 品类词库(初始化后不可变)
|
||||
*/
|
||||
public static final Set<String> CATEGORY_LIBRARY = Collections.unmodifiableSet(new HashSet<>(
|
||||
Arrays.asList("手机", "电脑", "空调", "冰箱", "运动鞋", "T恤", "洗发水", "洗衣液","猪脚")
|
||||
Arrays.asList("手机", "电脑", "空调", "冰箱", "运动鞋", "T恤", "洗发水", "洗衣液","猪脚","花生牛奶")
|
||||
));
|
||||
|
||||
static {
|
||||
@ -88,7 +91,8 @@ public class ProductTitleUtil {
|
||||
|
||||
//特殊商品
|
||||
public static final Set<String> SPECIAL_NAME = Collections.unmodifiableSet(new HashSet<>(
|
||||
Arrays.asList("水饺", "面条", "包子","卷纸","卫生纸","紫菜汤","猪肉包","叉烧包","香菇青菜包","面包","黑米")
|
||||
Arrays.asList("水饺", "面条", "包子","卷纸","卫生纸","紫菜汤","猪肉包","叉烧包","香菇青菜包","面包","黑米","棒棒糖","梳子","谢村花雕","古秦洋精","通裕梨花",
|
||||
"台式烤香肠")
|
||||
));
|
||||
|
||||
static {
|
||||
@ -104,8 +108,9 @@ public class ProductTitleUtil {
|
||||
Arrays.asList("个","条","份","盒","份","袋")
|
||||
));
|
||||
public static final Set<String> UNITS = Collections.unmodifiableSet(new HashSet<>(
|
||||
Arrays.asList("g","克","kg","千克","ml","毫升","l","升","cm","厘米","mm","毫米","份","盒","份","袋")
|
||||
Arrays.asList("g","克","kg","千克","ml","毫升","l","升","cm","厘米","mm","毫米","份","盒","份","袋","L")
|
||||
));
|
||||
|
||||
private ProductTitleUtil() {
|
||||
}
|
||||
|
||||
|
||||
@ -34,3 +34,105 @@ PAMU 500 n
|
||||
香菇青菜包 500 n
|
||||
老鸭汤炖料 500 n
|
||||
六指鼠 500 n
|
||||
花生牛奶 500 n
|
||||
碧螺春 500 n
|
||||
红薯仔 500 n
|
||||
棒棒糖 500 n
|
||||
哈密瓜桃味 500 n
|
||||
益生菌 500 n
|
||||
茉莉花茶 500 n
|
||||
棉花糖 500 n
|
||||
照相机 500 n
|
||||
涂鸦画 500 n
|
||||
火腿肠 500 n
|
||||
苏打水 500 n
|
||||
薏米粥 500 n
|
||||
好口福 500 n
|
||||
面条 500 n
|
||||
红豆花生奶 500 n
|
||||
绣花被 500 n
|
||||
黄山小毛峰 500 n
|
||||
宜兴毛尖 500 n
|
||||
龙井八宝茶 500 n
|
||||
忆江南 500 n
|
||||
山楂知己茶 500 n
|
||||
枸杞茶 500 n
|
||||
菊花茶 500 n
|
||||
铁观音 500 n
|
||||
汉中绿茶 500 n
|
||||
汉中炒青 500 n
|
||||
西乡毛尖 500 n
|
||||
西乡特炒 500 n
|
||||
西乡炒青 500 n
|
||||
汉中特炒 500 n
|
||||
汉中仙毫 500 n
|
||||
百事可乐 500 n
|
||||
胚芽茶 500 n
|
||||
黑苦荞 500 n
|
||||
茉莉银毫 500 n
|
||||
茉莉花茶 500 n
|
||||
茉莉毛尖 500 n
|
||||
苦荞茶 500 n
|
||||
云雾绿茶 500 n
|
||||
黄山毛尖 500 n
|
||||
汉中仙毫 500 n
|
||||
拜将坛 500 n
|
||||
汉中功夫红茶 500 n
|
||||
汉中毛尖 500 n
|
||||
云雾毛尖茶 500 n
|
||||
信阳毛尖 500 n
|
||||
雨前毛尖茶 500 n
|
||||
雨前毛尖 500 n
|
||||
速溶饮料 500 n
|
||||
水蜜桃味 500 n
|
||||
枣味茶 500 n
|
||||
果味茶 500 n
|
||||
黑米茶青柑茶 500 n
|
||||
毛尖茶 500 n
|
||||
冻干柠檬 500 n
|
||||
汉中仙毫 500 n
|
||||
云南滇红 500 n
|
||||
决明子 500 n
|
||||
清热下火茶 500 n
|
||||
柠檬干 500 n
|
||||
汉中大米 500 n
|
||||
面皮粉 500 n
|
||||
压榨油 500 n
|
||||
百州红 500 n
|
||||
八度名苑 500 n
|
||||
苦荞 500 n
|
||||
牛肉卷 500 n
|
||||
迷尔山楂 500 n
|
||||
九制梅肉 500 n
|
||||
白馒头 500 n
|
||||
山楂片茶 500 n
|
||||
汉中红茶 500 n
|
||||
电热锅 500 n
|
||||
玫瑰花茶 500 n
|
||||
冰糖雪梨 500 n
|
||||
今麦郞 500 n
|
||||
乌龙茶 500 n
|
||||
雪花啤酒 500 n
|
||||
勇闯天涯 500 n
|
||||
谢村花雕 500 n
|
||||
古秦洋酒 500 n
|
||||
汉斯啤酒 500 n
|
||||
北京二锅头 500 n
|
||||
一起赢 500 n
|
||||
古秦洋精 500 n
|
||||
桃花浪漫 500 n
|
||||
台式烤香肠 500 n
|
||||
孜然散 500 n
|
||||
香甜王 500 n
|
||||
元気森林 500 n
|
||||
苏打气泡水 500 n
|
||||
云南红茶 500 n
|
||||
碗碗香 500 n
|
||||
丝苗香米 500 n
|
||||
压榨菜籽油 500 n
|
||||
乡糯香 500 n
|
||||
鸡蛋面片 500 n
|
||||
疆丝麦耘 500 n
|
||||
亿家康 500 n
|
||||
汉中香米 500 n
|
||||
菜籽油 500 n
|
||||
@ -284,13 +284,16 @@ public class EsProductImageServiceImpl implements EsProductImageService {
|
||||
|
||||
// 2. 为每个关键词构建查询
|
||||
for (String keyword : keywords) {
|
||||
//keyword=keyword.split(" ")[0];
|
||||
String cleanKeyword= ProductTitleUtil.cleanTitle2(keyword);
|
||||
// String[] cleanKeywords = cleanWord.split(" ");
|
||||
// String cleanKeyword=cleanKeywords[0];
|
||||
keywordToCleanMap.put(cleanKeyword, keyword); // 保留原始关键词映射
|
||||
|
||||
// 构建组合查询
|
||||
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
|
||||
//.should(QueryBuilders.matchQuery("barcode", cleanKeyword).boost(1.0f))
|
||||
.should(QueryBuilders.matchQuery("productName", JiebaUtils.cleanNumberAndDigit(cleanKeyword)).boost(1.0f))
|
||||
.should(QueryBuilders.matchQuery("productName", JiebaUtils.cleanNumberAndDigit(keyword)).boost(1.0f))
|
||||
.should(QueryBuilders.fuzzyQuery("cleanName.keyword", JiebaUtils.cleanNumberAndDigit(cleanKeyword))
|
||||
.fuzziness(Fuzziness.ONE)
|
||||
.maxExpansions(20)
|
||||
@ -314,7 +317,6 @@ public class EsProductImageServiceImpl implements EsProductImageService {
|
||||
.boost(0.5f));
|
||||
count+=1;
|
||||
}
|
||||
|
||||
if(StringUtil.isNotEmpty(shopDetailMap.get("specs"))){
|
||||
boolQuery.should(QueryBuilders.fuzzyQuery("specs.keyword", shopDetailMap.get("specs")) // 模糊查询权重
|
||||
.fuzziness(Fuzziness.TWO) // 自动确定模糊度
|
||||
|
||||
@ -33,4 +33,8 @@ public interface ShopNumberSeqService extends IBaseService<ShopNumberSeq> {
|
||||
List<Integer> getBatchUserAccountBaseId(int batchSize);
|
||||
|
||||
void clearKeyStoreAccountBaseId();
|
||||
|
||||
List<Integer> getBatchSpecId(int batchSize);
|
||||
|
||||
void clearKeyStoreSepcId();
|
||||
}
|
||||
|
||||
@ -3,10 +3,12 @@ package com.suisung.mall.shop.number.service.impl;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.feignService.AccountService;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.number.mapper.ShopNumberSeqMapper;
|
||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
@ -45,6 +47,9 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
@Autowired
|
||||
private ShopProductSpecItemService shopProductSpecItemService;
|
||||
|
||||
@Autowired
|
||||
private ShopBaseProductSpecService shopBaseProductSpecService;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@ -208,7 +213,9 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
redisService.del(RedisKey.STOREDATACCOUNTBASEID);
|
||||
}
|
||||
|
||||
|
||||
public void clearKeyStoreSepcId(){
|
||||
redisService.del(RedisKey.STOREDATASPECID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存,专门给并发使用,防止redis的缓存没有加载
|
||||
@ -244,6 +251,33 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
edit(seq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||
* @param batchSize
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public synchronized List<Integer> getBatchSpecId(int batchSize) {
|
||||
int start=0;
|
||||
if(null!=redisService.get(RedisKey.STOREDATASPECID)){
|
||||
start=(Integer) redisService.get(RedisKey.STOREDATASPECID);
|
||||
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||
}
|
||||
QueryWrapper<ShopBaseProductSpec> queryWrapper= new QueryWrapper<>();
|
||||
queryWrapper.select("max(spec_id) as spec_id");
|
||||
ShopBaseProductSpec shopBaseProductSpec=shopBaseProductSpecService.getOne(queryWrapper);
|
||||
if(null!=shopBaseProductSpec){
|
||||
start=shopBaseProductSpec.getSpec_id();
|
||||
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||
}
|
||||
if(start==0){
|
||||
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||
}
|
||||
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||
* @param batchSize
|
||||
@ -272,6 +306,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||
* @param batchSize
|
||||
|
||||
@ -13,6 +13,7 @@ import com.suisung.mall.common.modules.page.ShopPageApp;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreInfo;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.ContextUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.core.web.service.CloundService;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
@ -71,7 +72,7 @@ public class ShopPageAppController extends BaseControllerImpl {
|
||||
@RequestParam(name = "pageSize", defaultValue = "100") Integer pageSize) {
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
UserDto user = getCurrentUser();
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
|
||||
//读取模板
|
||||
Map data_arr = null;
|
||||
@ -198,7 +199,7 @@ public class ShopPageAppController extends BaseControllerImpl {
|
||||
@RequestParam(name = "app_page_list") String app_page_list,
|
||||
@RequestParam(name = "page_config", defaultValue = "{}") String page_config,
|
||||
@RequestParam(name = "app_member_center", defaultValue = "{}") String app_member_center) {
|
||||
UserDto user = getCurrentUser();
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import com.suisung.mall.common.modules.page.ShopPageBase;
|
||||
import com.suisung.mall.common.modules.product.ShopPageUserForm;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.ContextUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.core.web.CommonRes;
|
||||
import com.suisung.mall.shop.page.dto.PageBaseListReq;
|
||||
@ -151,7 +152,7 @@ public class ShopPageBaseController extends BaseControllerImpl {
|
||||
@RequestMapping(value = "/remove", method = RequestMethod.POST)
|
||||
public CommonResult remove(@RequestParam(name = "page_id") Long page_id) {
|
||||
try {
|
||||
UserDto user = getCurrentUser();
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
|
||||
// 用户未登录,禁止操作
|
||||
if (user == null) {
|
||||
@ -250,7 +251,7 @@ public class ShopPageBaseController extends BaseControllerImpl {
|
||||
|
||||
*/
|
||||
|
||||
UserDto user = getCurrentUser();
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import lombok.Data;
|
||||
public class BrandModelExcel{
|
||||
public static final String TEMPLATE_NAME = "品牌导入模板.xlsx";
|
||||
@ApiModelProperty("品牌名称")
|
||||
@ExcelProperty(value = "商品名称", index = 0)
|
||||
@ExcelProperty(value = "品牌名称", index = 0)
|
||||
private String brand_name;
|
||||
|
||||
@ApiModelProperty("品牌描述")
|
||||
|
||||
@ -62,5 +62,12 @@ public class SxGoosModelExcel {
|
||||
@ExcelProperty(value = "品牌名称", index = 8)
|
||||
private String brand_name;
|
||||
|
||||
@ApiModelProperty(value = "多规格参数,[规格名称:规格值]",example = "[颜色:白色][尺码:28][价格:]")
|
||||
@ExcelProperty(value = "多规格参数", index = 9)
|
||||
private String shop_specs;
|
||||
|
||||
@ExcelProperty(value = "多规格json数据", index = 9)
|
||||
@ExcelIgnore
|
||||
private String jsonSpecs;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,188 @@
|
||||
package com.suisung.mall.shop.sync.keymanage;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ProductSpecManager {
|
||||
// 定义商品规格项
|
||||
public static class SpecItem {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public SpecItem() {}
|
||||
|
||||
public SpecItem(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getValue() { return value; }
|
||||
public void setValue(String value) { this.value = value; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + ": " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义价格库存项
|
||||
public static class PriceStockItem {
|
||||
private BigDecimal price;
|
||||
private BigDecimal stock;
|
||||
|
||||
public PriceStockItem() {}
|
||||
|
||||
public PriceStockItem(BigDecimal price, BigDecimal stock) {
|
||||
this.price = price;
|
||||
this.stock = stock;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public BigDecimal getPrice() { return price; }
|
||||
public void setPrice(BigDecimal price) { this.price = price; }
|
||||
public BigDecimal getStock() { return stock; }
|
||||
public void setStock(BigDecimal stock) { this.stock = stock; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("¥%.2f (%d件)", price, stock);
|
||||
}
|
||||
}
|
||||
|
||||
// 定义完整的商品规格信息
|
||||
public static class ProductSpecInfo {
|
||||
private List<SpecItem> spec;
|
||||
private PriceStockItem priceAndstock;
|
||||
|
||||
public ProductSpecInfo() {
|
||||
this.spec = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public List<SpecItem> getSpec() { return spec; }
|
||||
public void setSpec(List<SpecItem> spec) { this.spec = spec; }
|
||||
public PriceStockItem getPriceAndstock() { return priceAndstock; }
|
||||
public void setPriceAndstock(PriceStockItem priceAndstock) {
|
||||
this.priceAndstock = priceAndstock;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 商品规格映射表:商品ID -> JSON字符串
|
||||
private Map<String, List<String>> specsMap;
|
||||
private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
public Map<String, List<String>> getSpecsMap() {
|
||||
return specsMap;
|
||||
}
|
||||
|
||||
public void setSpecsMap(Map<String, List<String>> specsMap) {
|
||||
this.specsMap = specsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品规格
|
||||
*
|
||||
* @param productId 商品ID
|
||||
* @param specItems 规格项列表
|
||||
* @param price 价格
|
||||
* @param stock 库存
|
||||
*/
|
||||
public void addProductSpec(String productId, List<SpecItem> specItems,
|
||||
BigDecimal price, BigDecimal stock) {
|
||||
// 创建价格库存项
|
||||
PriceStockItem priceStockItem = new PriceStockItem(price, stock);
|
||||
|
||||
// 创建商品规格信息
|
||||
ProductSpecInfo specInfo = new ProductSpecInfo();
|
||||
specInfo.setSpec(specItems);
|
||||
specInfo.setPriceAndstock(priceStockItem);
|
||||
|
||||
// 转换为JSON字符串
|
||||
String json = gson.toJson(specInfo);
|
||||
|
||||
// 添加到Map
|
||||
if (!specsMap.containsKey(productId)) {
|
||||
specsMap.put(productId, new ArrayList<>());
|
||||
}
|
||||
specsMap.get(productId).add(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品所有规格信息
|
||||
*
|
||||
* @param productId 商品ID
|
||||
* @return 商品规格信息列表
|
||||
*/
|
||||
public String getProductSpecsString(String productId) {
|
||||
if (!specsMap.containsKey(productId)) {
|
||||
return "";
|
||||
}
|
||||
return gson.toJson(specsMap.get(productId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品所有规格信息
|
||||
*
|
||||
* @param productId 商品ID
|
||||
* @return 商品规格信息列表
|
||||
*/
|
||||
public List<String> getSepcMapValue(String productId) {
|
||||
if (!specsMap.containsKey(productId)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return specsMap.get(productId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品所有规格信息
|
||||
*
|
||||
* @param productId 商品ID
|
||||
* @return 商品规格信息列表
|
||||
*/
|
||||
public List<ProductSpecInfo> getProductSpecs(String productId) {
|
||||
if (!specsMap.containsKey(productId)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<ProductSpecInfo> result = new ArrayList<>();
|
||||
for (String json : specsMap.get(productId)) {
|
||||
ProductSpecInfo info = gson.fromJson(json, ProductSpecInfo.class);
|
||||
result.add(info);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析规格字符串为SpecItem列表
|
||||
*
|
||||
* @param specStr 规格字符串,格式如"[颜色:黑色][尺寸:30]"
|
||||
* @return SpecItem列表
|
||||
*/
|
||||
public List<SpecItem> parseSpecString(String specStr) {
|
||||
List<SpecItem> specItems = new ArrayList<>();
|
||||
|
||||
// 正则表达式匹配格式:[key:value]
|
||||
Pattern pattern = Pattern.compile("\\[(.*?):(.*?)\\]");
|
||||
Matcher matcher = pattern.matcher(specStr);
|
||||
|
||||
while (matcher.find()) {
|
||||
if (matcher.groupCount() == 2) {
|
||||
String name = matcher.group(1).trim();
|
||||
String value = matcher.group(2).trim();
|
||||
specItems.add(new SpecItem(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
return specItems;
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,4 +20,7 @@ public class RedisKey {
|
||||
|
||||
|
||||
public static final String STOREDATACCOUNTBASEID="storedata:accountBaseId";
|
||||
|
||||
|
||||
public static final String STOREDATASPECID="storedata:SpecId";
|
||||
}
|
||||
|
||||
@ -4,10 +4,15 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.suisung.mall.common.enums.DicEnum;
|
||||
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||
import com.suisung.mall.common.utils.CommonUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.shop.sync.exelModel.SxGoosModelExcel;
|
||||
import com.suisung.mall.shop.sync.keymanage.ProductSpecManager;
|
||||
import com.suisung.mall.shop.sync.service.SyncStoreSpecsService;
|
||||
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -15,13 +20,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -30,15 +30,20 @@ import java.util.stream.Collectors;
|
||||
public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelExcel> {
|
||||
// 批处理阈值
|
||||
private static final int BATCH_SIZE = 500;
|
||||
// 数据缓存
|
||||
private List<SxGoosModelExcel> cachedDataList = new ArrayList<>(BATCH_SIZE);
|
||||
|
||||
private SyncThirdDataService syncThirdDataService;
|
||||
|
||||
private SyncStoreSpecsService syncStoreSpecsService;
|
||||
|
||||
// 线程池配置
|
||||
private final ExecutorService executorService;
|
||||
// 数据缓存
|
||||
private final List<SxGoosModelExcel> cachedDataList = new ArrayList<>(BATCH_SIZE);
|
||||
private final SyncThirdDataService syncThirdDataService;
|
||||
private final List<Future<?>> futures;
|
||||
private final AtomicInteger success;
|
||||
private final AtomicInteger fails;
|
||||
private final AtomicInteger batchSize;
|
||||
|
||||
private List<Future<?>> futures ;
|
||||
private AtomicInteger success;
|
||||
private AtomicInteger fails;
|
||||
private AtomicInteger batchSize;
|
||||
@Setter
|
||||
@Getter
|
||||
private String storeId;
|
||||
@ -51,17 +56,22 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
@Getter
|
||||
private Map<String,Integer> brandMaps;
|
||||
|
||||
private ProductSpecManager productSpecManager;
|
||||
|
||||
public ShopBatchSubmitListener(SyncThirdDataService syncThirdDataService) {
|
||||
public ShopBatchSubmitListener(SyncThirdDataService syncThirdDataService,SyncStoreSpecsService syncStoreSpecsService) {
|
||||
this.syncThirdDataService = syncThirdDataService;
|
||||
this.syncStoreSpecsService = syncStoreSpecsService;
|
||||
// 创建线程池(根据CPU核心数优化)
|
||||
int corePoolSize = Runtime.getRuntime().availableProcessors();
|
||||
// log.info("核心线程数量{}", corePoolSize);
|
||||
this.executorService = Executors.newFixedThreadPool(corePoolSize);
|
||||
log.info("核心线程数量{}" , corePoolSize);
|
||||
this.executorService = Executors.newFixedThreadPool(6);
|
||||
this.futures = new ArrayList<>();
|
||||
this.success = new AtomicInteger();
|
||||
this.fails = new AtomicInteger();
|
||||
this.batchSize= new AtomicInteger();
|
||||
this.productSpecManager=new ProductSpecManager();
|
||||
Map<String, List<String>> specsMap=new HashMap<>();
|
||||
productSpecManager.setSpecsMap(specsMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,6 +84,7 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
submitBatch();
|
||||
// 提交后清空缓存
|
||||
cachedDataList.clear();
|
||||
productSpecManager.getSpecsMap().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,6 +97,7 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
batchSize.incrementAndGet();
|
||||
submitBatch();
|
||||
cachedDataList.clear();
|
||||
productSpecManager.getSpecsMap().clear();
|
||||
}
|
||||
}
|
||||
// 等待所有任务完成
|
||||
@ -105,6 +117,7 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
private void submitBatch() {
|
||||
// 复制当前批次数据(避免异步修改)
|
||||
List<SxGoosModelExcel> batchCopy = new ArrayList<>(deduplicateById(cachedDataList));
|
||||
Map<String,List<String>> sepcsMap = new HashMap<>(productSpecManager.getSpecsMap());
|
||||
log.info("去重前:{};去重后:{}" , cachedDataList.size(), batchCopy.size());
|
||||
final int index = batchSize.get();
|
||||
futures.add(executorService.submit(()->{
|
||||
@ -118,6 +131,7 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
syncThirdDataService.baseSaveOrUpdateGoodsBatch(jsonArray,storeId,isNegativeAllowed,brandMaps);
|
||||
log.info("已提交批次: {} 条", batchCopy.size());
|
||||
success.getAndIncrement();
|
||||
saveSnycStoreSpec(sepcsMap);
|
||||
return "完成批次:"+index;
|
||||
} catch (Exception e) {
|
||||
if(i<2){
|
||||
@ -132,7 +146,6 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
*
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
@ -156,10 +169,121 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
||||
}
|
||||
sxGoosModelExcel.setProduct_number(sxGoosModelExcel.getProduct_barcode());
|
||||
sxGoosModelExcel.setOriginal_price(sxGoosModelExcel.getRetail_price());
|
||||
|
||||
if(StringUtils.isNotEmpty(sxGoosModelExcel.getShop_specs())){
|
||||
List<ProductSpecManager.SpecItem> specItems= productSpecManager.parseSpecString(sxGoosModelExcel.getShop_specs());
|
||||
sxGoosModelExcel.setJsonSpecs(specItems.toString());
|
||||
productSpecManager.addProductSpec(sxGoosModelExcel.getProduct_barcode(),specItems,sxGoosModelExcel.getRetail_price(),sxGoosModelExcel.getStock());
|
||||
}
|
||||
})
|
||||
.filter(CommonUtil.distinctByKey(SxGoosModelExcel::getProduct_number))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存多规格数据
|
||||
*/
|
||||
private void saveSnycStoreSpec(Map<String,List<String>> listMap){
|
||||
if(listMap==null){
|
||||
return;
|
||||
}
|
||||
//List<SyncStoreSpecs> syncStoreSpecs=new ArrayList<>();
|
||||
List<SyncStoreSpecs> addSyncStoreSpecs=new ArrayList<>();
|
||||
List<SyncStoreSpecs> updateSyncStoreSpecs=new ArrayList<>();
|
||||
Map<String,Long> existId= getExistProductId(listMap);
|
||||
if(existId==null){
|
||||
return;
|
||||
}
|
||||
listMap.forEach((k,v)->{
|
||||
SyncStoreSpecs syncStoreSpec=new SyncStoreSpecs();
|
||||
syncStoreSpec.setProductNumber(k);
|
||||
syncStoreSpec.setJsonSpecs(v.toString());
|
||||
syncStoreSpec.setIsDeal(DicEnum.YESORNO_0.getCode());
|
||||
syncStoreSpec.setStoreId(Integer.valueOf(storeId));
|
||||
if(existId.containsKey(k)){
|
||||
syncStoreSpec.setSycnSpecsId(existId.get(k));
|
||||
updateSyncStoreSpecs.add(syncStoreSpec);
|
||||
}else {
|
||||
addSyncStoreSpecs.add(syncStoreSpec);
|
||||
}
|
||||
});
|
||||
if(!addSyncStoreSpecs.isEmpty()){
|
||||
syncStoreSpecsService.saveBatch(addSyncStoreSpecs,addSyncStoreSpecs.size());
|
||||
}
|
||||
if(!updateSyncStoreSpecs.isEmpty()){
|
||||
syncStoreSpecsService.updateBatchById(updateSyncStoreSpecs,updateSyncStoreSpecs.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找存量数据
|
||||
* @param listMap
|
||||
* @return
|
||||
*/
|
||||
private Map<String,Long> getExistProductId(Map<String,List<String>> listMap){
|
||||
QueryWrapper<SyncStoreSpecs> queryWrapper = new QueryWrapper<>();
|
||||
listMap.forEach((k,v)->{
|
||||
queryWrapper.or(q->q.eq("store_id",storeId).eq("product_number",k));
|
||||
});
|
||||
|
||||
List<SyncStoreSpecs> syncStoreSpecs = syncStoreSpecsService.list(queryWrapper);
|
||||
if(syncStoreSpecs==null){
|
||||
return null;
|
||||
}
|
||||
Map<String,Long> resultMap=new HashMap<>();
|
||||
syncStoreSpecs.forEach(m->{
|
||||
resultMap.put(String.valueOf(m.getProductNumber()),m.getSycnSpecsId());
|
||||
});
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SxGoosModelExcel sxGoosModelExcel = new SxGoosModelExcel();
|
||||
sxGoosModelExcel.setProduct_barcode("1");
|
||||
sxGoosModelExcel.setProduct_name("产品1");
|
||||
sxGoosModelExcel.setShop_specs("颜色");
|
||||
sxGoosModelExcel.setRetail_price(new BigDecimal("100"));
|
||||
sxGoosModelExcel.setStock(new BigDecimal("10"));
|
||||
sxGoosModelExcel.setJsonSpecs("[颜色:红色][尺寸:10]");
|
||||
|
||||
SxGoosModelExcel sxGoosModelExcel1 = new SxGoosModelExcel();
|
||||
sxGoosModelExcel1.setProduct_barcode("2");
|
||||
sxGoosModelExcel1.setProduct_name("产品2");
|
||||
sxGoosModelExcel1.setShop_specs("颜色");
|
||||
sxGoosModelExcel1.setShop_spec("红色");
|
||||
sxGoosModelExcel1.setRetail_price(new BigDecimal("200"));
|
||||
sxGoosModelExcel1.setStock(new BigDecimal("20"));
|
||||
sxGoosModelExcel1.setJsonSpecs("[颜色:黑色][尺寸:20]");
|
||||
|
||||
SxGoosModelExcel sxGoosModelExcel3 = new SxGoosModelExcel();
|
||||
sxGoosModelExcel3.setProduct_barcode("1");
|
||||
sxGoosModelExcel3.setProduct_name("产品3");
|
||||
sxGoosModelExcel3.setShop_specs("颜色");
|
||||
sxGoosModelExcel3.setShop_spec("黑色");
|
||||
sxGoosModelExcel3.setRetail_price(new BigDecimal("300"));
|
||||
sxGoosModelExcel3.setStock(new BigDecimal("30"));
|
||||
sxGoosModelExcel3.setJsonSpecs("[颜色:黑色][尺寸:30]");
|
||||
|
||||
List<SxGoosModelExcel> sxGoosModelExcelList = new ArrayList<>();
|
||||
sxGoosModelExcelList.add(sxGoosModelExcel);
|
||||
sxGoosModelExcelList.add(sxGoosModelExcel1);
|
||||
sxGoosModelExcelList.add(sxGoosModelExcel3);
|
||||
ProductSpecManager productSpecManager=new ProductSpecManager();
|
||||
Map<String, List<String>> specsMap=new HashMap<>();
|
||||
productSpecManager.setSpecsMap(specsMap);
|
||||
|
||||
sxGoosModelExcelList=sxGoosModelExcelList.stream().peek(gm -> {
|
||||
if(StringUtils.isNotEmpty(gm.getJsonSpecs())){
|
||||
List<ProductSpecManager.SpecItem> specItems= productSpecManager.parseSpecString(gm.getJsonSpecs());
|
||||
productSpecManager.addProductSpec(gm.getProduct_barcode(),specItems,gm.getRetail_price(),gm.getStock());
|
||||
}
|
||||
}).filter(CommonUtil.distinctByKey(SxGoosModelExcel::getProduct_barcode))
|
||||
.collect(Collectors.toList());
|
||||
Gson goson=new Gson();
|
||||
log.info("规格:{}",productSpecManager.getSepcMapValue("1"));
|
||||
log.info("规格数量:{}",productSpecManager.getSepcMapValue("1").size());
|
||||
log.info(String.valueOf(sxGoosModelExcelList.size()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.suisung.mall.shop.sync.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||
import feign.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface SyncStoreSpecsMapper extends BaseMapper<SyncStoreSpecs> {
|
||||
|
||||
List<SyncStoreSpecs> findSyncStoreSpecsList(SyncStoreSpecs syncStoreSpecs,@Param("limit") Integer limit,@Param("pageSize") Integer pageSize);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.suisung.mall.shop.sync.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||
|
||||
public interface SyncStoreSpecsService extends IService<SyncStoreSpecs> {
|
||||
|
||||
void dealSyncStoreSpecs(Integer storeId);
|
||||
}
|
||||
@ -130,7 +130,7 @@ public class ProductMappingServiceImpl extends BaseServiceImpl<ProductMappingMap
|
||||
|
||||
@Override
|
||||
public void computeProductMapping(List<ShopProductBase> shopProductBaseList,Integer storeId,Map shopProductSpecItemMap,Map ShopBaseProductSpecMap, Map productMappingMap,boolean isUpdate,String isPubish) {
|
||||
shopProductBaseList= shopProductBaseList.stream().filter(base ->StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK==(base.getProduct_state_id())).collect(Collectors.toList());
|
||||
shopProductBaseList= shopProductBaseList.stream().filter(base ->ObjectUtil.isNotEmpty(base.getUnit_name())).collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||
log.info("没有规格数据要处理");
|
||||
return;
|
||||
@ -266,6 +266,7 @@ public class ProductMappingServiceImpl extends BaseServiceImpl<ProductMappingMap
|
||||
if(null!=shopProductSpecItem){
|
||||
item_spec=shopProductSpecItem.getItem_spec();
|
||||
productSpec=shopProductSpecItem.getProduct_spec();
|
||||
item.setItem_name(shopProductSpecItem.getSpec_item_name());
|
||||
if(isUpdate){
|
||||
item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||
}else {
|
||||
|
||||
@ -17,10 +17,7 @@ import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import com.suisung.mall.shop.sync.excleHandle.TemplateStyleHandler;
|
||||
import com.suisung.mall.shop.sync.exelModel.*;
|
||||
import com.suisung.mall.shop.sync.listen.ShopBatchSubmitListener;
|
||||
import com.suisung.mall.shop.sync.service.ProductMappingService;
|
||||
import com.suisung.mall.shop.sync.service.ShopSyncImportService;
|
||||
import com.suisung.mall.shop.sync.service.StoreDbConfigService;
|
||||
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
||||
import com.suisung.mall.shop.sync.service.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -58,6 +55,8 @@ public class ShopSyncImportServiceImpl implements ShopSyncImportService {
|
||||
private ShopNumberSeqService shopNumberSeqService;
|
||||
@Autowired
|
||||
private ShopBaseProductCategoryService shopBaseProductCategoryService;
|
||||
@Autowired
|
||||
private SyncStoreSpecsService syncStoreSpecsService;
|
||||
|
||||
private final int limitCnt = 100;
|
||||
|
||||
@ -224,11 +223,12 @@ public class ShopSyncImportServiceImpl implements ShopSyncImportService {
|
||||
storeDbConfigQueryWrapper.eq("store_id", storeId);
|
||||
StoreDbConfig storeDbConfig = storeDbConfigService.getOne(storeDbConfigQueryWrapper);
|
||||
String isNegativeAllowed = storeDbConfig.getIsNegativeAllowed();
|
||||
ShopBatchSubmitListener shopBatchSubmitListener=new ShopBatchSubmitListener(syncThirdDataService);
|
||||
ShopBatchSubmitListener shopBatchSubmitListener=new ShopBatchSubmitListener(syncThirdDataService,syncStoreSpecsService);
|
||||
shopBatchSubmitListener.setStoreId(storeId);
|
||||
shopBatchSubmitListener.setBrandMaps(brandMaps);
|
||||
shopBatchSubmitListener.setIsNegativeAllowed(isNegativeAllowed);
|
||||
EasyExcel.read(filePath,SxGoosModelExcel.class,shopBatchSubmitListener).sheet().doRead();
|
||||
syncStoreSpecsService.dealSyncStoreSpecs(Integer.valueOf(storeId));
|
||||
productMappingService.syncAllProductMapping(Integer.valueOf(storeId), DicEnum.YESORNO_0.getCode());
|
||||
syncThirdDataService.syncShopImages(Integer.valueOf(storeId));
|
||||
cleanCache(storeId);//清理redis数据
|
||||
|
||||
@ -0,0 +1,593 @@
|
||||
package com.suisung.mall.shop.sync.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.gson.Gson;
|
||||
import com.suisung.mall.common.enums.DicEnum;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductType;
|
||||
import com.suisung.mall.common.modules.product.*;
|
||||
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductTypeService;
|
||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import com.suisung.mall.shop.product.service.*;
|
||||
import com.suisung.mall.shop.sixun.utils.CommonUtil;
|
||||
import com.suisung.mall.shop.sync.Utils.ShopJsonUtils;
|
||||
import com.suisung.mall.shop.sync.keymanage.ProductSpecManager;
|
||||
import com.suisung.mall.shop.sync.mapper.SyncStoreSpecsMapper;
|
||||
import com.suisung.mall.shop.sync.service.SyncStoreSpecsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@lombok.extern.slf4j.Slf4j
|
||||
@Transactional
|
||||
public class SyncStoreSpecsServiceImpl extends ServiceImpl<SyncStoreSpecsMapper, SyncStoreSpecs> implements SyncStoreSpecsService {
|
||||
|
||||
private final Integer batchSize = 500;
|
||||
@Autowired
|
||||
private ShopBaseProductSpecService shopBaseProductSpecService;
|
||||
@Autowired
|
||||
private ShopProductSpecItemService shopProductSpecItemService;
|
||||
@Autowired
|
||||
private ShopNumberSeqService shopNumberSeqService;
|
||||
@Autowired
|
||||
private ShopBaseProductTypeService shopBaseProductTypeService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductItemService shopProductItemService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductItemSeqService shopProductItemSeqService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductInfoService shopProductInfoService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductIndexService shopProductIndexService;
|
||||
|
||||
@Autowired
|
||||
private SyncStoreSpecsMapper syncStoreSpecsMapper;
|
||||
|
||||
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@Override
|
||||
public void dealSyncStoreSpecs(Integer storeId) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(6);
|
||||
AtomicInteger success=new AtomicInteger(0);
|
||||
AtomicInteger fails=new AtomicInteger(0);
|
||||
shopNumberSeqService.clearKeyStoreSepcId();
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
QueryWrapper<SyncStoreSpecs> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("store_id", storeId);
|
||||
wrapper.eq("is_deal", DicEnum.YESORNO_0.getCode());
|
||||
SyncStoreSpecs queryDto = new SyncStoreSpecs();
|
||||
queryDto.setStoreId(storeId);
|
||||
queryDto.setIsDeal(DicEnum.YESORNO_0.getCode());
|
||||
long total= this.count(wrapper);
|
||||
int pages= CommonUtil.getPagesCount(Math.toIntExact(total),batchSize);
|
||||
for (int i=1;i<=pages;i++){
|
||||
int finalI = i;
|
||||
futures.add(executor.submit(() -> {
|
||||
try {
|
||||
List<SyncStoreSpecs> syncStoreSpecsList= syncStoreSpecsMapper.findSyncStoreSpecsList(queryDto, finalI -1,batchSize);
|
||||
//处理多规格数据
|
||||
dealShopItemSpec(syncStoreSpecsList,storeId);
|
||||
success.getAndIncrement();
|
||||
syncStoreSpecsList.forEach(syncStoreSpecs -> {
|
||||
syncStoreSpecs.setIsDeal(DicEnum.YESORNO_1.getCode());
|
||||
});
|
||||
this.updateBatchById(syncStoreSpecsList,syncStoreSpecsList.size());
|
||||
}catch (Exception e){
|
||||
log.error("失败原因:"+e.getMessage(),e);
|
||||
fails.getAndIncrement();
|
||||
}
|
||||
}));
|
||||
}
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
try {
|
||||
System.out.println("规格任务结果: " + future.get());
|
||||
} catch (Exception e) {
|
||||
System.err.println("规格任务执行异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
executor.shutdown();
|
||||
shopNumberSeqService.clearKeyStoreSepcId();
|
||||
log.info("处理多规格数据成功:{}批,失败:{}批", success.get(), fails.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理多规格商品
|
||||
*/
|
||||
@Transactional
|
||||
public void dealShopItemSpec(List<SyncStoreSpecs> syncStoreSpecsList,Integer storeId){
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
|
||||
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||
transactionTemplate.setTimeout(200); // 60秒超时
|
||||
transactionTemplate.execute(status -> {
|
||||
try {
|
||||
ProductSpecManager productSpecManager=new ProductSpecManager();
|
||||
Map<String,List<String>> specMap=new HashMap<>();//存储规格类型
|
||||
Map<String,List<String>> specValueMap=new HashMap<>();//存储规格的值
|
||||
Map<String,Integer> specCateGoryMap=new HashMap<>();//存储分类id
|
||||
Map<String,Long> specsProductIdMap=new HashMap<>();//存储product_id
|
||||
//Map<String,Long> existProductItemMap=new HashMap<>();//存储item_id
|
||||
Gson gson=new Gson();
|
||||
//规格定义
|
||||
List<ShopBaseProductSpec> shopBaseProductSpecList=new ArrayList<>();
|
||||
//规格值定义
|
||||
//解析json
|
||||
for (SyncStoreSpecs syncStoreSpecs : syncStoreSpecsList) {
|
||||
List<String> jsonSpec= new ArrayList<>();
|
||||
cn.hutool.json.JSONArray jsonArray=JSONUtil.parseArray(syncStoreSpecs.getJsonSpecs());
|
||||
for (Object obj : jsonArray) {
|
||||
jsonSpec.add(obj.toString());
|
||||
}
|
||||
specMap.put(String.valueOf(syncStoreSpecs.getProductNumber()),jsonSpec);
|
||||
specCateGoryMap.put(String.valueOf(syncStoreSpecs.getProductNumber()),syncStoreSpecs.getCategoryId());
|
||||
specsProductIdMap.put(syncStoreSpecs.getProductNumber(),syncStoreSpecs.getProductId());
|
||||
// existProductItemMap.put(syncStoreSpecs.getProductNumber(),syncStoreSpecs.getItemId());
|
||||
}
|
||||
productSpecManager.setSpecsMap(specMap);
|
||||
List<ShopProductItem> shopProductItems=new ArrayList<>();
|
||||
specMap.forEach((k,v)->{
|
||||
List<ProductSpecManager.ProductSpecInfo> specInfos= productSpecManager.getProductSpecs(k);
|
||||
for (ProductSpecManager.ProductSpecInfo specInfo : specInfos) {
|
||||
List<ProductSpecManager.SpecItem> specList=specInfo.getSpec();
|
||||
StringBuilder specValue=new StringBuilder();
|
||||
for (ProductSpecManager.SpecItem specItem : specList) {
|
||||
ShopBaseProductSpec shopBaseProductSpec=new ShopBaseProductSpec();
|
||||
shopBaseProductSpec.setStore_id(storeId);
|
||||
shopBaseProductSpec.setSpec_name(specItem.getName());
|
||||
shopBaseProductSpec.setSpec_format("text");
|
||||
shopBaseProductSpec.setSpec_order(50);
|
||||
shopBaseProductSpec.setSpec_category_id(specCateGoryMap.get(k));
|
||||
shopBaseProductSpecList.add(shopBaseProductSpec);
|
||||
List<String> specValueList=new ArrayList<>();
|
||||
if(specValueMap.containsKey(specItem.getName())){
|
||||
specValueList=specValueMap.get(specItem.getName());
|
||||
}
|
||||
if(StringUtils.isNotEmpty(specValue)){
|
||||
specValue.append(",").append(specItem.getValue());
|
||||
}else {
|
||||
specValue.append(specItem.getValue());
|
||||
}
|
||||
specValueList.add(specItem.getValue());
|
||||
specValueMap.put(specItem.getName(),specValueList);
|
||||
}
|
||||
ProductSpecManager.PriceStockItem stockItem= specInfo.getPriceAndstock();
|
||||
ShopProductItem spuItem=new ShopProductItem();
|
||||
spuItem.setItem_barcode(k);
|
||||
spuItem.setItem_number(k);
|
||||
spuItem.setItem_name(specValue.toString());
|
||||
spuItem.setItem_unit_price(stockItem.getPrice());
|
||||
spuItem.setItem_market_price(stockItem.getPrice());
|
||||
spuItem.setItem_quantity(stockItem.getStock().intValue());
|
||||
shopProductItems.add(spuItem);
|
||||
}
|
||||
});
|
||||
//1.新增规格
|
||||
//过滤
|
||||
List<ShopBaseProductSpec> addShopBaseProductSpecList=new ArrayList<>();
|
||||
List<ShopBaseProductSpec> updateShopBaseProductSpecList=new ArrayList<>();
|
||||
List<ShopBaseProductSpec> shopBaseProductSpecs=shopBaseProductSpecList.stream()
|
||||
.filter(com.suisung.mall.common.utils.CommonUtil.distinctByKey(ShopBaseProductSpec::getSpec_name))
|
||||
.collect(Collectors.toList());
|
||||
Map<String,Integer> existsMap= getExistShopBaseSpec(shopBaseProductSpecs,storeId);
|
||||
Map<String,Integer> specCateGoryIdMap=new HashMap<>();
|
||||
Map<Integer,List<Integer>> cateGoryIdSpecIdMap=new HashMap<>();
|
||||
for(ShopBaseProductSpec spec:shopBaseProductSpecs){
|
||||
if(existsMap.containsKey(spec.getSpec_name())){
|
||||
spec.setSpec_id(existsMap.get(spec.getSpec_name()));
|
||||
specCateGoryIdMap.put(spec.getSpec_name(),spec.getSpec_id());
|
||||
updateShopBaseProductSpecList.add(spec);
|
||||
}else {
|
||||
addShopBaseProductSpecList.add(spec);
|
||||
}
|
||||
}
|
||||
|
||||
if(!addShopBaseProductSpecList.isEmpty()){
|
||||
List<Integer> specIds= shopNumberSeqService.getBatchSpecId(addShopBaseProductSpecList.size());//计算specId
|
||||
for (int i=0;i<specIds.size();i++){
|
||||
addShopBaseProductSpecList.get(i).setSpec_id(specIds.get(i));
|
||||
List<Integer> specIdList=new ArrayList<>();
|
||||
if(cateGoryIdSpecIdMap.containsKey(addShopBaseProductSpecList.get(i).getSpec_category_id())){
|
||||
specIdList=cateGoryIdSpecIdMap.get(addShopBaseProductSpecList.get(i).getSpec_category_id());
|
||||
}
|
||||
specIdList.add(specIds.get(i));
|
||||
cateGoryIdSpecIdMap.put(addShopBaseProductSpecList.get(i).getSpec_category_id(),specIdList);
|
||||
specCateGoryIdMap.put(addShopBaseProductSpecList.get(i).getSpec_name(),specIds.get(i));
|
||||
}
|
||||
//shopBaseProductSpecService.saveBatch(addShopBaseProductSpecList,addShopBaseProductSpecList.size());
|
||||
}
|
||||
// if(!updateShopBaseProductSpecList.isEmpty()){
|
||||
// shopBaseProductSpecService.updateBatchById(updateShopBaseProductSpecList,updateShopBaseProductSpecList.size());
|
||||
// }
|
||||
//2.新增规格的值
|
||||
List<ShopProductSpecItem> specItems=new ArrayList<>();
|
||||
specValueMap.forEach((k,v)->{
|
||||
for (String specVal : v) {
|
||||
ShopProductSpecItem specItem = new ShopProductSpecItem();
|
||||
specItem.setSpec_id(specCateGoryIdMap.get(k));
|
||||
specItem.setCategory_id(specCateGoryMap.get(k));
|
||||
specItem.setStore_id(storeId);
|
||||
specItem.setSpec_item_enable(1);
|
||||
specItem.setSpec_item_name(specVal);
|
||||
specItem.setSpec_item_order("10");
|
||||
specItem.setSpecName(k);
|
||||
specItems.add(specItem);
|
||||
}
|
||||
});
|
||||
Map<String,ShopProductSpecItem> specItemMap=new HashMap<>();//存储specItemValue对应的ShopProductSpecItem
|
||||
List<ShopProductSpecItem> specItemList=specItems.stream()
|
||||
.filter(com.suisung.mall.common.utils.CommonUtil.distinctByKey(ShopProductSpecItem::getSpec_item_name))
|
||||
.collect(Collectors.toList());//去重
|
||||
List<ShopProductSpecItem> addSpecItemList=new ArrayList<>();
|
||||
List<ShopProductSpecItem> updateSpecItemList=new ArrayList<>();
|
||||
Map<String,Integer> specItemIdMap=getExistShopSpecItem(specItemList,storeId);
|
||||
for(ShopProductSpecItem specItem:specItemList){
|
||||
if(specItemIdMap.containsKey(specItem.getSpec_item_name())){
|
||||
specItem.setSpec_item_id(specItemIdMap.get(specItem.getSpec_item_name()));
|
||||
updateSpecItemList.add(specItem);
|
||||
}else {
|
||||
addSpecItemList.add(specItem);
|
||||
}
|
||||
specItemMap.put(specItem.getSpec_item_name(),specItem);
|
||||
}
|
||||
|
||||
if(!addSpecItemList.isEmpty()){
|
||||
List<Integer> specItemIds= shopNumberSeqService.getBatchSpecItemId(addSpecItemList.size());//计算specId
|
||||
for (int i=0;i<specItemIds.size();i++){
|
||||
addSpecItemList.get(i).setSpec_item_id(specItemIds.get(i));
|
||||
specItemMap.put(addSpecItemList.get(i).getSpec_item_name(),addSpecItemList.get(i));
|
||||
}
|
||||
// shopProductSpecItemService.saveBatch(addSpecItemList,addSpecItemList.size());
|
||||
}
|
||||
// if(!updateSpecItemList.isEmpty()){
|
||||
// shopProductSpecItemService.updateBatchById(updateSpecItemList,updateSpecItemList.size());
|
||||
// }
|
||||
//3、新增规格类型
|
||||
List<ShopBaseProductType> shopBaseProductTypes= getShopBaseProductTypeList(syncStoreSpecsList,storeId);
|
||||
for(ShopBaseProductType shopBaseProductType:shopBaseProductTypes){
|
||||
List<Integer> specIdList=new ArrayList<>();
|
||||
if(cateGoryIdSpecIdMap.containsKey(shopBaseProductType.getType_category_id())){
|
||||
specIdList=cateGoryIdSpecIdMap.get(shopBaseProductType.getType_category_id());
|
||||
String [] type_spec_ids=shopBaseProductType.getType_spec_ids().split(",");
|
||||
for (String specId : type_spec_ids) {
|
||||
specIdList.add(Integer.parseInt(specId));
|
||||
}
|
||||
String typeSpecIds= specIdList.stream().map(String::valueOf).distinct().collect(Collectors.joining(","));
|
||||
shopBaseProductType.setType_spec_ids(typeSpecIds);
|
||||
}else {
|
||||
specIdList=cateGoryIdSpecIdMap.get(shopBaseProductType.getType_category_id());
|
||||
if(null!=specIdList){
|
||||
String typeSpecIds= specIdList.stream().map(String::valueOf).distinct().collect(Collectors.joining(","));
|
||||
shopBaseProductType.setType_spec_ids(typeSpecIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!shopBaseProductTypes.isEmpty()){//更新规格类型
|
||||
shopBaseProductTypeService.updateBatchById(shopBaseProductTypes,shopBaseProductTypes.size());
|
||||
}
|
||||
//4、新增shopItem
|
||||
List<ShopProductItem> addShopProductItemList=new ArrayList<>();
|
||||
List<ShopProductItem> updateShopProductItemList=new ArrayList<>();
|
||||
Map<String,Long> existProductItemMap= getExistShopItemList(shopProductItems,storeId);
|
||||
shopProductItems.forEach(item->{
|
||||
item.setProduct_id(specsProductIdMap.get(item.getItem_barcode()));
|
||||
StringBuilder pIspecItemIds= new StringBuilder();
|
||||
String[] pIspecItemNames=item.getItem_name().split(",");
|
||||
List<Map<String, Object>> spectItems=new ArrayList<>();
|
||||
List<Map<String, Object>> specJson=new ArrayList<>();
|
||||
for (String pIspecItemName : pIspecItemNames) {
|
||||
ShopProductSpecItem specItem = specItemMap.get(pIspecItemName);
|
||||
Integer specItemId=specItem.getSpec_item_id();
|
||||
if (StringUtils.isNotEmpty(pIspecItemIds)) {
|
||||
pIspecItemIds.append(",").append(specItemId);
|
||||
} else {
|
||||
pIspecItemIds.append(specItemId);
|
||||
}
|
||||
Map<String,Object> specItemJson=new HashMap<>();
|
||||
specItemJson.put("name",specItem.getSpec_item_name());//规格列表
|
||||
specItemJson.put("id",specItem.getSpec_item_id());
|
||||
spectItems.add(specItemJson);
|
||||
|
||||
Map<String,Object> specJsonMap=new HashMap<>();
|
||||
specJsonMap.put("name",specItem.getSpecName());//规格名称
|
||||
specJsonMap.put("id",specItem.getSpec_id());
|
||||
specJson.add(specJsonMap);
|
||||
}
|
||||
item.setSpec_item_ids(pIspecItemIds.toString());
|
||||
String item_spec= ShopJsonUtils.generateJsonWithOrgJsonItemSpec(spectItems,specJson);
|
||||
// String productInfoSpec= ShopJsonUtils.generateJsonWithOrgJsonProducSpec(spectItems,specJson);
|
||||
item.setItem_spec(item_spec);
|
||||
item.setItem_title("");
|
||||
item.setItem_freetime(0);
|
||||
item.setCategory_id(specCateGoryMap.get(item.getItem_barcode()));
|
||||
if(existProductItemMap.containsKey(item.getItem_name())){
|
||||
item.setItem_id(existProductItemMap.get(item.getItem_barcode()));
|
||||
updateShopProductItemList.add(item);
|
||||
}else {
|
||||
addShopProductItemList.add(item);
|
||||
}
|
||||
});
|
||||
if(!addShopProductItemList.isEmpty()){
|
||||
List<Long> generatedIds = shopNumberSeqService.batchCreateNextNo("item_id", addShopProductItemList.size());
|
||||
for (int i = 0; i < generatedIds.size(); i++) {
|
||||
addShopProductItemList.get(i).setItem_id(generatedIds.get(i));
|
||||
addShopProductItemList.get(i).setItem_src_id(String.valueOf(generatedIds.get(i)));
|
||||
}
|
||||
shopProductItemService.saveBatch(addShopProductItemList,addShopProductItemList.size());
|
||||
}
|
||||
if(!updateShopProductItemList.isEmpty()){
|
||||
shopProductItemService.updateBatchById(updateShopProductItemList,updateShopProductItemList.size());
|
||||
}
|
||||
List<ShopProductItemSeq> addShopProductItemSeqList=new ArrayList<>();
|
||||
addShopProductItemList.forEach(item->{
|
||||
ShopProductItemSeq shopProductItemSeq=new ShopProductItemSeq();
|
||||
shopProductItemSeq.setItem_id(item.getItem_id());
|
||||
shopProductItemSeq.setProduct_id(item.getProduct_id());
|
||||
String item_spec=item.getItem_spec();
|
||||
Long productId=item.getProduct_id();
|
||||
cn.hutool.json.JSONArray array_item_spec = cn.hutool.json.JSONUtil.parseArray(item_spec);
|
||||
List<Integer> spec_item_ids=new ArrayList<>();
|
||||
for (Object josn_item_spec : array_item_spec) {
|
||||
cn.hutool.json.JSONObject itemJson = (cn.hutool.json.JSONObject) ((cn.hutool.json.JSONObject) josn_item_spec).get("item");
|
||||
Integer id = Convert.toInt(itemJson.get("id"));
|
||||
if (ObjectUtil.isNotNull(id)) {
|
||||
spec_item_ids.add(id);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(spec_item_ids)) {
|
||||
Collections.sort(spec_item_ids);
|
||||
}
|
||||
String sku_uniqid = "default";
|
||||
if(CollUtil.isNotEmpty(spec_item_ids)){
|
||||
sku_uniqid = CollUtil.join(spec_item_ids, "-");
|
||||
}
|
||||
String product_item_seq_val = String.format("%s:%s", productId, sku_uniqid);
|
||||
String product_item_seq_id = SecureUtil.md5(product_item_seq_val);
|
||||
shopProductItemSeq.setProduct_item_seq_id(product_item_seq_id);
|
||||
shopProductItemSeq.setProduct_item_seq_val(product_item_seq_val);
|
||||
addShopProductItemSeqList.add(shopProductItemSeq);
|
||||
});
|
||||
if(!addShopProductItemSeqList.isEmpty()){
|
||||
shopProductItemSeqService.saveOrUpdateBatch(addShopProductItemSeqList,addShopProductItemSeqList.size());
|
||||
}
|
||||
//更新shopProductInfo
|
||||
Map<Long, List<ShopProductItem>> shopInfoItems=new HashMap<>();
|
||||
List<ShopProductInfo> updateShopProductInfoList=new ArrayList<>();
|
||||
for (ShopProductItem shopProductItem: addShopProductItemList) {
|
||||
Long productId=shopProductItem.getProduct_id();
|
||||
List<ShopProductItem> shopProductItemList=new ArrayList<>();
|
||||
if(shopInfoItems.containsKey(shopProductItem.getProduct_id())){
|
||||
shopProductItemList=shopInfoItems.get(shopProductItem.getProduct_id());
|
||||
}
|
||||
shopProductItemList.add(shopProductItem);
|
||||
shopInfoItems.put(productId,shopProductItemList);
|
||||
}
|
||||
Map<Long,Integer> itemQualityMap=new HashMap<>();
|
||||
shopInfoItems.forEach((productId,sItemList)->{
|
||||
ShopProductInfo spui=new ShopProductInfo();
|
||||
spui.setProduct_id(productId);
|
||||
String item_spec=sItemList.get(0).getItem_spec();
|
||||
cn.hutool.json.JSONArray array_item_spec = cn.hutool.json.JSONUtil.parseArray(item_spec);
|
||||
List<Integer> spec_item_ids=new ArrayList<>();
|
||||
for (Object josn_item_spec : array_item_spec) {
|
||||
Integer specId = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("id"));
|
||||
spec_item_ids.add(specId);
|
||||
}
|
||||
String spec_ids=CollUtil.join(spec_item_ids,",");
|
||||
spui.setSpec_ids(spec_ids);
|
||||
|
||||
Map<String,cn.hutool.json.JSONArray> specItemJson=new HashMap<>();
|
||||
cn.hutool.json.JSONArray productUniqidjsonArray=new cn.hutool.json.JSONArray();
|
||||
AtomicReference<Integer> itemQuantity= new AtomicReference<>(0);
|
||||
sItemList.forEach(item->{
|
||||
String itemSpec=item.getItem_spec();
|
||||
cn.hutool.json.JSONArray arrayItemSpec = cn.hutool.json.JSONUtil.parseArray(itemSpec);
|
||||
cn.hutool.json.JSONObject uniqidItemJson=new cn.hutool.json.JSONObject();
|
||||
String specItemIdSpecItemId="";
|
||||
for (Object josn_item_spec : arrayItemSpec) {
|
||||
Integer specId = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("id"));
|
||||
Integer specName = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("name"));
|
||||
String specIdName=specId+"-"+specName;
|
||||
cn.hutool.json.JSONObject itemJson = (cn.hutool.json.JSONObject) ((cn.hutool.json.JSONObject) josn_item_spec).get("item");
|
||||
cn.hutool.json.JSONArray itemsJsonArray=new cn.hutool.json.JSONArray();
|
||||
if(specItemJson.containsKey(specIdName)){
|
||||
itemsJsonArray=specItemJson.get(specIdName);
|
||||
}
|
||||
itemsJsonArray.add(itemJson);
|
||||
specItemJson.put(specIdName,itemsJsonArray);
|
||||
if(StringUtils.isNotEmpty(specItemIdSpecItemId)){
|
||||
specItemIdSpecItemId=specItemIdSpecItemId+"-"+itemJson.getStr("id");
|
||||
}else {
|
||||
specItemIdSpecItemId=itemJson.getStr("id");
|
||||
}
|
||||
}
|
||||
uniqidItemJson.set(specItemIdSpecItemId,new Object[]{item.getItem_id(),item.getItem_quantity(),"","1001"});
|
||||
productUniqidjsonArray.add(uniqidItemJson);
|
||||
itemQuantity.updateAndGet(v -> v + item.getItem_quantity());
|
||||
});
|
||||
itemQualityMap.put(productId,itemQuantity.get());
|
||||
cn.hutool.json.JSONArray jsonArraySpecItem=new cn.hutool.json.JSONArray();
|
||||
specItemJson.forEach((key,jsonArray)->{
|
||||
cn.hutool.json.JSONObject itemJson = new cn.hutool.json.JSONObject();
|
||||
itemJson.set("item",jsonArray);
|
||||
String[] specIdName=key.split("-");
|
||||
String specId=specIdName[0];
|
||||
String specName=specIdName[1];
|
||||
itemJson.set("name",specName);
|
||||
itemJson.set("spec_format","text");
|
||||
itemJson.set("id",specId);
|
||||
jsonArraySpecItem.add(itemJson);
|
||||
});
|
||||
String product_spec= JSONUtil.toJsonStr(jsonArraySpecItem);
|
||||
String product_uniqid=JSONUtil.toJsonStr(productUniqidjsonArray);
|
||||
spui.setProduct_spec(product_spec);
|
||||
spui.setProduct_uniqid(product_uniqid);
|
||||
updateShopProductInfoList.add(spui);
|
||||
});
|
||||
if(!updateShopProductInfoList.isEmpty()){
|
||||
shopProductInfoService.updateBatchById(updateShopProductInfoList,updateShopProductInfoList.size());
|
||||
}
|
||||
//5、更新shopindex数量
|
||||
List<ShopProductIndex> shopProductIndexList=new ArrayList<>();
|
||||
itemQualityMap.forEach((productId,stock)->{
|
||||
ShopProductIndex shopProductIndex=new ShopProductIndex();
|
||||
shopProductIndex.setProduct_id(productId);
|
||||
shopProductIndex.setProduct_quantity(stock);
|
||||
shopProductIndexList.add(shopProductIndex);
|
||||
});
|
||||
if(!shopProductIndexList.isEmpty()){
|
||||
shopProductIndexService.updateBatchById(shopProductIndexList,shopProductIndexList.size());
|
||||
}
|
||||
|
||||
//最后保存
|
||||
if(!addShopBaseProductSpecList.isEmpty()){//规格大类
|
||||
shopBaseProductSpecService.saveBatch(addShopBaseProductSpecList,addShopBaseProductSpecList.size());
|
||||
}
|
||||
if(!updateShopBaseProductSpecList.isEmpty()){//规格大类
|
||||
shopBaseProductSpecService.updateBatchById(updateShopBaseProductSpecList,updateShopBaseProductSpecList.size());
|
||||
}
|
||||
if(!addSpecItemList.isEmpty()){//规格值
|
||||
shopProductSpecItemService.saveBatch(addSpecItemList,addSpecItemList.size());
|
||||
}
|
||||
if(!updateSpecItemList.isEmpty()){//规格值
|
||||
shopProductSpecItemService.updateBatchById(updateSpecItemList,updateSpecItemList.size());
|
||||
}
|
||||
//shopitem 最后删除没有规格的商品
|
||||
QueryWrapper<ShopProductItem> queryWrapper=new QueryWrapper<>();
|
||||
queryWrapper.select("item_id");
|
||||
for (ShopProductIndex shopProductIndex:shopProductIndexList) {
|
||||
queryWrapper.or(q->q.eq("store_id",storeId)
|
||||
.eq("product_id",shopProductIndex.getProduct_id())
|
||||
.and(wrapper->wrapper.eq("item_name","")
|
||||
.or()
|
||||
.isNull("item_name")));
|
||||
}
|
||||
List<ShopProductItem> queryShopProductItemList=shopProductItemService.list(queryWrapper);
|
||||
if(!queryShopProductItemList.isEmpty()){
|
||||
List<Long> ItemIds= queryShopProductItemList.stream().map(ShopProductItem::getItem_id).collect(Collectors.toList());
|
||||
QueryWrapper<ShopProductItemSeq> shopProductItemSeqQueryWrapper=new QueryWrapper<>();
|
||||
shopProductItemSeqQueryWrapper.select("product_item_seq_id");
|
||||
shopProductItemSeqQueryWrapper.eq("item_id",ItemIds);
|
||||
List<ShopProductItemSeq> rmSeq= shopProductItemSeqService.list(shopProductItemSeqQueryWrapper);
|
||||
List<String> rmSeqIds=rmSeq.stream().map(ShopProductItemSeq::getProduct_item_seq_id).collect(Collectors.toList());
|
||||
shopProductItemSeqService.removeBatchByIds(rmSeqIds);
|
||||
shopProductItemService.removeBatchByIds(ItemIds,ItemIds.size());
|
||||
}
|
||||
}catch (Exception e){
|
||||
status.setRollbackOnly();
|
||||
log.error("批量操作异常", e);
|
||||
return Pair.of(false, "批量操作异常: " + e.getMessage());
|
||||
}
|
||||
return "success";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询分类规格
|
||||
* @param shopBaseProductSpecs
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
private Map<String,Integer> getExistShopBaseSpec(List<ShopBaseProductSpec> shopBaseProductSpecs,Integer storeId){
|
||||
Map<String,Integer> result=new HashMap<>();
|
||||
QueryWrapper<ShopBaseProductSpec> wrapper = new QueryWrapper<>();
|
||||
for (ShopBaseProductSpec shopBaseProductSpec : shopBaseProductSpecs) {
|
||||
wrapper.or(q->q.eq("spec_name",shopBaseProductSpec.getSpec_name()).eq("store_id",storeId));
|
||||
}
|
||||
List<ShopBaseProductSpec> shopBaseProductSpecList=shopBaseProductSpecService.list(wrapper);
|
||||
for (ShopBaseProductSpec shopBaseProductSpec : shopBaseProductSpecList) {
|
||||
result.put(shopBaseProductSpec.getSpec_name(),shopBaseProductSpec.getSpec_id());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分类规格
|
||||
* @param shopProductSpecItems
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
private Map<String,Integer> getExistShopSpecItem(List<ShopProductSpecItem> shopProductSpecItems,Integer storeId){
|
||||
Map<String,Integer> result=new HashMap<>();
|
||||
QueryWrapper<ShopProductSpecItem> wrapper = new QueryWrapper<>();
|
||||
for (ShopProductSpecItem shopProductSpecItem : shopProductSpecItems) {
|
||||
wrapper.or(q->q.eq("spec_item_name",shopProductSpecItem.getSpec_item_name()).eq("store_id",storeId));
|
||||
}
|
||||
List<ShopProductSpecItem> shopProductSpecItemList=shopProductSpecItemService.list(wrapper);
|
||||
for (ShopProductSpecItem shopProductSpecItem : shopProductSpecItemList) {
|
||||
result.put(shopProductSpecItem.getSpec_item_name(),shopProductSpecItem.getSpec_item_id());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找分类的类型
|
||||
* @param syncStoreSpecsList
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
private List<ShopBaseProductType> getShopBaseProductTypeList(List<SyncStoreSpecs> syncStoreSpecsList,Integer storeId){
|
||||
QueryWrapper<ShopBaseProductType> wrapper = new QueryWrapper<>();
|
||||
for (SyncStoreSpecs syncStoreSpecs : syncStoreSpecsList) {
|
||||
wrapper.or(q->q.eq("store_id",storeId).eq("type_category_id",syncStoreSpecs.getCategoryId()));
|
||||
}
|
||||
return shopBaseProductTypeService.list(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找分类的类型
|
||||
* @param syncStoreSpecsList
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
private Map<String,Long> getExistShopItemList(List<ShopProductItem> syncStoreSpecsList,Integer storeId){
|
||||
QueryWrapper<ShopProductItem> wrapper = new QueryWrapper<>();
|
||||
for (ShopProductItem shopProductItem : syncStoreSpecsList) {
|
||||
wrapper.or(q->q.eq("store_id",storeId)
|
||||
.eq("item_barcode",shopProductItem.getItem_barcode())
|
||||
.eq("item_name",shopProductItem.getItem_name()));
|
||||
}
|
||||
List<ShopProductItem> shopProductItemList=shopProductItemService.list(wrapper);
|
||||
Map<String,Long> result=new HashMap<>();
|
||||
for (ShopProductItem shopProductItem : shopProductItemList) {
|
||||
result.put(shopProductItem.getItem_name(),shopProductItem.getItem_id());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<String> spec_item_ids= Arrays.asList("12","13","14","15","16","17","18","19","20");
|
||||
System.out.println(CollUtil.join(spec_item_ids, "-"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.suisung.mall.shop.sync.mapper.SyncStoreSpecsMapper">
|
||||
|
||||
<resultMap id="syncStoreSpecsMap" type="com.suisung.mall.common.modules.sync.SyncStoreSpecs">
|
||||
<result property="sycnSpecsId" column="sycn_specs_id"/>
|
||||
<result property="productNumber" column="product_number"/>
|
||||
<result property="jsonSpecs" column="json_specs"/>
|
||||
<result property="storeId" column="store_id"/>
|
||||
<result property="isDeal" column="is_deal"/>
|
||||
<result property="productId" column="product_id"/>
|
||||
<result property="categoryId" column="category_id"/>
|
||||
<result property="itemId" column="item_id"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="findSyncStoreSpecsList" resultMap="syncStoreSpecsMap">
|
||||
SELECT s.sycn_specs_id ,
|
||||
s.product_number,
|
||||
s.json_specs ,
|
||||
s.store_id,
|
||||
s.is_deal,
|
||||
spi.product_id,
|
||||
spi.category_id,
|
||||
spi.item_id
|
||||
from sycn_store_specs s
|
||||
left join shop_product_item spi
|
||||
on s.product_number =spi.item_barcode
|
||||
<where>
|
||||
s.store_id=#{syncStoreSpecs.storeId}
|
||||
and
|
||||
s.is_deal=#{syncStoreSpecs.isDeal}
|
||||
</where>
|
||||
limit #{limit},#{pageSize}
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
</mapper>
|
||||
13
sql/shop/dev/20250819_ddl.sql
Normal file
13
sql/shop/dev/20250819_ddl.sql
Normal file
@ -0,0 +1,13 @@
|
||||
CREATE TABLE `sycn_store_specs` (
|
||||
`sycn_specs_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '多规格编号',
|
||||
`json_specs` json DEFAULT NULL COMMENT '多规格json数据,如[{"spec": [{"name": "颜色","value": "红色"},{"name": "尺寸","value": "10"}],"priceAndstock": {"price": 100,"stock": 10}},{"spec": [{ "name": "颜色","value": "黑色"},{"name": "尺寸","value": "30"}],
|
||||
"priceAndstock": {"price": 300,"stock": 30}}]',
|
||||
`product_number` varchar(50) DEFAULT '' COMMENT '条形码',
|
||||
`store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号',
|
||||
`is_deal` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否处理完成,1:是,0:否',
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '新建时间',
|
||||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`sycn_specs_id`) USING BTREE,
|
||||
KEY `index_store_id` (`store_id`) USING BTREE,
|
||||
KEY `index_is_deal` (`is_deal`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='多规格数据表';
|
||||
Loading…
Reference in New Issue
Block a user