商品上架功能实现

develop
ddyd 5 days ago
parent 7ae2f66ea4
commit 77d56ad27c

@ -6,11 +6,7 @@ import java.util.Map;
import com.bookstore.bookmall.product.vo.SpuSaveVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.bookstore.bookmall.product.entity.SpuInfoEntity;
import com.bookstore.bookmall.product.service.SpuInfoService;
@ -32,6 +28,17 @@ public class SpuInfoController {
@Autowired
private SpuInfoService spuInfoService;
//POST /product/spuinfo/{spuId}/up 商品上架保存在es
@PostMapping("/{spuId}/up")
//@RequiresPermissions("product:spuinfo:list")
public R list(@PathVariable("spuId") Long spuId){
spuInfoService.up(spuId);
return R.ok();
}
/**
*
*/

@ -3,6 +3,9 @@ package com.bookstore.bookmall.product.dao;
import com.bookstore.bookmall.product.entity.AttrEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
*
@ -13,5 +16,6 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface AttrDao extends BaseMapper<AttrEntity> {
List<Long> selectSearchAttrIds(@Param("attrIds") List<Long> attrIds);
}

@ -3,6 +3,7 @@ package com.bookstore.bookmall.product.dao;
import com.bookstore.bookmall.product.entity.SpuInfoEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* spu
@ -13,5 +14,6 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface SpuInfoDao extends BaseMapper<SpuInfoEntity> {
void updateSpuStatus(@Param("spuId") Long spuId, @Param("code") int code);
}

@ -0,0 +1,16 @@
package com.bookstore.bookmall.product.feign;
import com.bookstore.common.to.es.SkuEsModel;
import com.bookstore.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient("mall-search")
public interface SearchFeignService {
@PostMapping("/search/save/product")
R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels);
}

@ -0,0 +1,19 @@
package com.bookstore.bookmall.product.feign;
import com.bookstore.bookmall.product.to.SkuHasStockTo;
import com.bookstore.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient("mall-ware")
public interface WareFeignService {
//查询sku是否有库存
@PostMapping("ware/waresku/hasstock")
R getSkusHasStock(@RequestBody List<Long> skuIds);
}

@ -32,6 +32,13 @@ public interface AttrService extends IService<AttrEntity> {
PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId);
/**
*
* @param attrIds
* @return
*/
List<Long> selectSearchAttrIds(List<Long> attrIds);
}

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.bookstore.common.utils.PageUtils;
import com.bookstore.bookmall.product.entity.SkuInfoEntity;
import java.util.List;
import java.util.Map;
/**
@ -20,5 +21,7 @@ public interface SkuInfoService extends IService<SkuInfoEntity> {
void saveSkuInfo(SkuInfoEntity skuInfoEntity);
PageUtils queryPageByCondition(Map<String, Object> params);
List<SkuInfoEntity> getSkusBySpuId(Long spuId);
}

@ -23,5 +23,15 @@ public interface SpuInfoService extends IService<SpuInfoEntity> {
void saveBaseSpuInfo(SpuInfoEntity spuInfoEntity);
PageUtils queryPageByCondition(Map<String, Object> params);
/*
* @Description:
* @param: spuId
* @return:
* @Author:
* @date:
*/
void up(Long spuId);
}

@ -266,5 +266,14 @@ public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements
return pageUtils;
}
@Override
public List<Long> selectSearchAttrIds(List<Long> attrIds) {
// SELECT attr_id FROM `pms_attr` WHERE attr_id IN (?) AND search_type = 1
return baseMapper.selectSearchAttrIds(attrIds);
}
}

@ -4,6 +4,7 @@ import com.mysql.cj.util.StringUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -88,4 +89,10 @@ public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> i
return new PageUtils(page);
}
@Override
public List<SkuInfoEntity> getSkusBySpuId(Long spuId){
List<SkuInfoEntity> skus = this.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
return skus;
}
}

@ -1,11 +1,17 @@
package com.bookstore.bookmall.product.service.impl;
import com.alibaba.fastjson.TypeReference;
import com.bookstore.bookmall.product.entity.*;
import com.bookstore.bookmall.product.feign.CouponFeignService;
import com.bookstore.bookmall.product.feign.SearchFeignService;
import com.bookstore.bookmall.product.feign.WareFeignService;
import com.bookstore.bookmall.product.service.*;
import com.bookstore.bookmall.product.to.SkuHasStockTo;
import com.bookstore.bookmall.product.vo.*;
import com.bookstore.common.constant.ProductConstant;
import com.bookstore.common.to.SkuReductionTo;
import com.bookstore.common.to.SpuBoundsTo;
import com.bookstore.common.to.es.SkuEsModel;
import com.bookstore.common.utils.R;
import com.fasterxml.jackson.databind.annotation.JsonAppend;
import com.mysql.cj.util.StringUtils;
@ -16,9 +22,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -50,6 +54,14 @@ public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> i
SkuSaleAttrValueService skuSaleAttrValueService;
@Autowired
CouponFeignService couponFeignService;
@Autowired
BrandService brandService;
@Autowired
CategoryService categoryService;
@Autowired
WareFeignService wareFeignService;
@Autowired
SearchFeignService searchFeignService;
@Override
public PageUtils queryPage(Map<String, Object> params) {
@ -232,5 +244,113 @@ public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> i
return new PageUtils(page);
}
//商品上架
@Override
public void up(Long spuId) {
//查出所有skuinfo
List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);
//TODO 查出当前sku可以被检索的规格属性
List<ProductAttrValueEntity> valueEntities = valueService.baseAttrlistforspu(spuId);
List<Long> attrIds = valueEntities.stream().map(entity -> {
return entity.getAttrId();
}).collect(Collectors.toList());
List<Long> selectSearchAttrs = attrService.selectSearchAttrIds(attrIds);
Set<Long> idSet = new HashSet<>(selectSearchAttrs);
List<SkuEsModel.Attrs> attrsList = valueEntities.stream().filter(item -> {
return idSet.contains(item.getAttrId());
}).map(item->{
SkuEsModel.Attrs attrs1= new SkuEsModel.Attrs();
BeanUtils.copyProperties(item, attrs1);
return attrs1;
}).collect(Collectors.toList());
List<Long> skuIds = skus.stream().map(item -> {
return item.getSkuId();
}).collect(Collectors.toList());
Map<Long, Boolean> stockMap = null;
try {
//TODO 远程调用库存服务,查询是否有库存
R skusHasStock = wareFeignService.getSkusHasStock(skuIds);
TypeReference<List<SkuHasStockTo>> typeReference = new TypeReference<List<SkuHasStockTo>>() {
};
stockMap = skusHasStock.getData(typeReference).stream()
.collect(Collectors.toMap(SkuHasStockTo::getSkuId, item -> item.getHasStock()));
}catch (Exception e) {
log.error("库存服务查询异常:原因{}", e);
}
Map<Long, Boolean> finalStockMap = stockMap;
List<SkuEsModel> esModels = skus.stream().map((sku) -> {
//组装需要的数据
SkuEsModel skuEsModel = new SkuEsModel();
BeanUtils.copyProperties(sku, skuEsModel);
//skuPrice, skuImg, hotStock, hotScore
skuEsModel.setSkuPrice(sku.getPrice());
skuEsModel.setSkuImg(sku.getSkuDefaultImg());
//hotStock
if (finalStockMap == null) {
skuEsModel.setHasStock(true);
}else {
skuEsModel.setHasStock(finalStockMap.get(sku.getSkuId()));
}
//TODO 热度评分 默认0
skuEsModel.setHotScore(0L);
// /*
// * private String brandName;
//
// private String brandImg;
//
// private String catalogName;
//
// * */
BrandEntity brand = brandService.getById(sku.getBrandId());
skuEsModel.setBrandName(brand.getName());
skuEsModel.setBrandImg(brand.getLogo());
CategoryEntity categoryEntity = categoryService.getById(sku.getCatalogId());
skuEsModel.setCatalogName(categoryEntity.getName());
// @Data
// public static class Attrs {
//
// private Long attrId;
//
// private String attrName;
//
// private String attrValue;
//
// }
skuEsModel.setAttrs(attrsList);
return skuEsModel;
}).collect(Collectors.toList());
//TODO 将数据发送给es保存
R r = searchFeignService.productStatusUp(esModels);
if (r.getCode() == 0) {
//远程调用成功
//TODO 修改商品上架状态
baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
}else {
//远程调用失败
//重复调用,接口幂等性
}
}
}

@ -0,0 +1,10 @@
package com.bookstore.bookmall.product.to;
import lombok.Data;
@Data
public class SkuHasStockTo {
private Long skuId;
private Boolean hasStock;
}

@ -16,6 +16,12 @@
<result property="catelogId" column="catelog_id"/>
<result property="showDesc" column="show_desc"/>
</resultMap>
<select id="selectSearchAttrIds" resultType="java.lang.Long">
SELECT attr_id FROM `pms_attr` WHERE attr_id IN
<foreach collection="attrIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
AND search_type = 1
</select>
</mapper>

@ -15,6 +15,8 @@
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<update id="updateSpuStatus">
UPDATE `pms_spu_info` SET publish_status=#{code}, update_time=NOW() WHERE id=#{spuId}
</update>
</mapper>

@ -1,15 +1,13 @@
package com.bookstore.bookmall.ware.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.bookstore.bookmall.ware.to.SkuHasStockTo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.bookstore.bookmall.ware.entity.WareSkuEntity;
import com.bookstore.bookmall.ware.service.WareSkuService;
@ -31,6 +29,15 @@ public class WareSkuController {
@Autowired
private WareSkuService wareSkuService;
//查询sku是否有库存
@PostMapping("/hasstock")
public R getSkusHasStock(@RequestBody List<Long> skuIds) {
List<SkuHasStockTo> vos = wareSkuService.getSkusHasStock(skuIds);
return R.ok().setData(vos);
}
/**
*
*/

@ -3,6 +3,7 @@ package com.bookstore.bookmall.ware.dao;
import com.bookstore.bookmall.ware.entity.WareSkuEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
*
@ -13,5 +14,6 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {
Long getSkuStock(Long skuId);
}

@ -4,5 +4,5 @@ package com.bookstore.bookmall.ware.feign;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient("book-product")
public class ProductFeignService {
public interface ProductFeignService {
}

@ -1,9 +1,11 @@
package com.bookstore.bookmall.ware.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bookstore.bookmall.ware.to.SkuHasStockTo;
import com.bookstore.common.utils.PageUtils;
import com.bookstore.bookmall.ware.entity.WareSkuEntity;
import java.util.List;
import java.util.Map;
/**
@ -16,5 +18,7 @@ import java.util.Map;
public interface WareSkuService extends IService<WareSkuEntity> {
PageUtils queryPage(Map<String, Object> params);
List<SkuHasStockTo> getSkusHasStock(List<Long> skuIds);
}

@ -1,8 +1,13 @@
package com.bookstore.bookmall.ware.service.impl;
import com.bookstore.bookmall.ware.to.SkuHasStockTo;
import com.mysql.cj.util.StringUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -43,4 +48,21 @@ public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> i
return new PageUtils(page);
}
@Override
public List<SkuHasStockTo> getSkusHasStock(List<Long> skuIds) {
List<SkuHasStockTo> collect = skuIds.stream().map(skuId -> {
SkuHasStockTo vo = new SkuHasStockTo();
//查询当前库存
//SELECT SUM(stock-stock_locked) FROM `wms_ware_sku` WHERE sku_id=1
Long count = baseMapper.getSkuStock(skuId);
vo.setHasStock(count == null ? false : count>0);
vo.setSkuId(skuId);
return vo;
}).collect(Collectors.toList());
return collect;
}
}

@ -0,0 +1,10 @@
package com.bookstore.bookmall.ware.to;
import lombok.Data;
@Data
public class SkuHasStockTo {
private Long skuId;
private Boolean hasStock;
}

@ -12,6 +12,8 @@
<result property="skuName" column="sku_name"/>
<result property="stockLocked" column="stock_locked"/>
</resultMap>
<select id="getSkuStock" resultType="java.lang.Long">
SELECT SUM(stock-stock_locked) FROM `wms_ware_sku` WHERE sku_id=#{skuId}
</select>
</mapper>

@ -39,6 +39,7 @@
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.79" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.17" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.4.0" level="project" />
<orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-alibaba-commons:2021.0.4.0" level="project" />

@ -51,6 +51,12 @@
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.shiro</groupId>-->

@ -21,4 +21,24 @@ public class ProductConstant {
}
public enum StatusEnum{
SPU_NEW(0, "新建"), SPU_UP(1,"商品上架"), SPU_DOWN(2,"商品下架");
private int code;
private String msg;
StatusEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
}

@ -17,7 +17,8 @@ import java.sql.Struct;
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000, "系统未知错误"),
VAILD_EXCEPTION(10001, "参数格式校验失败");
VAILD_EXCEPTION(10001, "参数格式校验失败"),
PRODUCT_EXPRESSION(11000, "商品上架异常");
private int code;
private String message;

@ -0,0 +1,51 @@
package com.bookstore.common.to.es;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class SkuEsModel {
private Long skuId;
private Long spuId;
private String skuTitle;
private BigDecimal skuPrice;
private String skuImg;
private Long saleCount;
private Boolean hasStock;
private Long hotScore;
private Long brandId;
private Long catalogId;
private String brandName;
private String brandImg;
private String catalogName;
private List<Attrs> attrs;
@Data
public static class Attrs {
private Long attrId;
private String attrName;
private String attrValue;
}
}

@ -8,6 +8,8 @@
package com.bookstore.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.HttpStatus;
import java.util.HashMap;
@ -18,9 +20,22 @@ import java.util.Map;
*
* @author Mark sunlightcs@gmail.com
*/
//!!!!以后设计R时加上泛型
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public <T> T getData(TypeReference<T> typeReference) {
Object data = get("data");
String s = JSON.toJSONString(data);
T t = JSON.parseObject(s, typeReference);
return t;
}
public R setData(Object data){
put("data", data);
return this;
}
public R() {
put("code", 0);
put("msg", "success");

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bookstore.bookmall</groupId>
<artifactId>mall-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mall-search</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.11.1</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>com.bookstore.bookmall</groupId>
<artifactId>mall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId> org.elasticsearch.client </groupId>
<artifactId> elasticsearch-rest-high-level-client </artifactId>
<version>7.11.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,16 @@
package com.bookstore.bookmall.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class MallSearchApplication {
public static void main(String[] args) {
SpringApplication.run(MallSearchApplication.class, args);
}
}

@ -0,0 +1,35 @@
package com.bookstore.bookmall.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class mallElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("192.168.88.131", 9200, "http")));
return client;
}
}

@ -0,0 +1,6 @@
package com.bookstore.bookmall.search.constant;
public class EsConstant {
public static final String PRODUCT_INDEX = "product"; //sku数据在es中的索引
}

@ -0,0 +1,40 @@
package com.bookstore.bookmall.search.controller;
import com.bookstore.bookmall.search.service.ProductSaveService;
import com.bookstore.common.exception.BizCodeEnume;
import com.bookstore.common.to.es.SkuEsModel;
import com.bookstore.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RequestMapping("/search/save")
@RestController
public class ElasticSaveController {
@Autowired
ProductSaveService productSaveService;
//上架商品
@PostMapping("/product")
public R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels) {
boolean b = false;
try {
b = productSaveService.productStatusUp(skuEsModels);
}catch (Exception e){
log.error("商品上架异常:{}",e);
return R.error(BizCodeEnume.PRODUCT_EXPRESSION.getCode(), BizCodeEnume.PRODUCT_EXPRESSION.getMessage());
}
if (b) {
return R.ok();
} else {
return R.error(BizCodeEnume.PRODUCT_EXPRESSION.getCode(), BizCodeEnume.PRODUCT_EXPRESSION.getMessage());
}
}
}

@ -0,0 +1,12 @@
package com.bookstore.bookmall.search.service;
import com.bookstore.common.to.es.SkuEsModel;
import java.io.IOException;
import java.util.List;
public interface ProductSaveService {
boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException;
}

@ -0,0 +1,57 @@
package com.bookstore.bookmall.search.service.impl;
import com.bookstore.bookmall.search.config.mallElasticSearchConfig;
import com.bookstore.bookmall.search.constant.EsConstant;
import com.bookstore.bookmall.search.service.ProductSaveService;
import com.bookstore.common.to.es.SkuEsModel;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.alibaba.fastjson.JSON;
@Slf4j
@Service
public class ProductSaveServiceImpl implements ProductSaveService {
@Autowired
RestHighLevelClient restHighLevelClient;
@Override
public boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException {
//保存到es
//1、给es中建立索引product建立好映射关系
//2、在es中保存这些数据
BulkRequest bulkRequest = new BulkRequest();
for (SkuEsModel skuEsModel : skuEsModels) {
IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
indexRequest.id(skuEsModel.getSkuId().toString());
String s = JSON.toJSONString(skuEsModel);
indexRequest.source(s, XContentType.JSON);
bulkRequest.add(indexRequest);
}
BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, mallElasticSearchConfig.COMMON_OPTIONS);
boolean b = bulk.hasFailures();
List<String> collect = Arrays.stream(bulk.getItems()).map(item -> {
return item.getId();
}).collect(Collectors.toList());
log.error("商品上架错误:{}", collect);
return !b;
}
}

@ -0,0 +1,5 @@
spring.application.name=mall-search
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
server.port=12000

@ -0,0 +1,71 @@
PUT product
{
"mappings": {
"properties": {
"skuId": {
"type": "long"
},
"spuId": {
"type": "long"
},
"skuTitle": {
"type": "text",
"analyzer": "ik_smart"
},
"skuPrice": {
"type": "keyword"
},
"skuImg": {
"type": "keyword",
"index": false,
"doc_values": false
},
"saleCount": {
"type": "long"
},
"hosStock": {
"type": "boolean"
},
"hotScore": {
"type": "long"
},
"brandId": {
"type": "long"
},
"catelogId": {
"type": "long"
},
"brandName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"brandImg": {
"type": "keyword",
"index": false,
"doc_values": false
},
"catelogName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"attrs": {
"type": "nested",
"properties": {
"attrId": {
"type": "long"
},
"attrName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"attrValue": {
"type": "keyword"
}
}
}
}
}
}

@ -0,0 +1,22 @@
package com.bookstore.bookmall.search;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class MallSearchApplicationTests {
@Autowired
private RestHighLevelClient client;
@Test
public void contextLoads() {
System.out.println(client);
}
}

@ -76,5 +76,3 @@ export default {
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -74,5 +74,3 @@ export default {
}
};
</script>
<style scoped>
</style>

@ -1,217 +1,186 @@
<template>
<el-row :gutter="20">
<el-col :span="6">
<category @tree-node-click="treenodeclick"></category>
</el-col>
<el-col :span="18">
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button type="success" @click="getAllDataList()"></el-button>
<el-button
v-if="isAuth('product:attrgroup:save')"
type="primary"
@click="addOrUpdateHandle()"
>新增</el-button>
<el-button
v-if="isAuth('product:attrgroup:delete')"
type="danger"
@click="deleteHandle()"
:disabled="dataListSelections.length <= 0"
>批量删除</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="attrGroupId" header-align="center" align="center" label="分组id"></el-table-column>
<el-table-column prop="attrGroupName" header-align="center" align="center" label="组名"></el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序"></el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="描述"></el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="组图标"></el-table-column>
<el-table-column prop="catelogId" header-align="center" align="center" label="所属分类id"></el-table-column>
<el-table-column
fixed="right"
header-align="center"
align="center"
width="150"
label="操作"
>
<template slot-scope="scope">
<el-button type="text" size="small" @click="relationHandle(scope.row.attrGroupId)"></el-button>
<el-button
type="text"
size="small"
@click="addOrUpdateHandle(scope.row.attrGroupId)"
>修改</el-button>
<el-button type="text" size="small" @click="deleteHandle(scope.row.attrGroupId)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
<!-- 修改关联关系 -->
<relation-update v-if="relationVisible" ref="relationUpdate" @refreshData="getDataList"></relation-update>
</div>
</el-col>
</el-row>
</template>
<script>
/**
* 父子组件传递数据
* 1)子组件给父组件传递数据事件机制
* 子组件给父组件发送一个事件携带上数据
* // this.$emit("",...)
*/
//jsjsjson
//import  from '';
import Category from "../common/category";
import AddOrUpdate from "./attrgroup-add-or-update";
import RelationUpdate from "./attr-group-relation";
export default {
//import使
components: { Category, AddOrUpdate, RelationUpdate },
props: {},
data() {
return {
catId: 0,
dataForm: {
key: ""
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
relationVisible: false
};
},
activated() {
this.getDataList();
},
methods: {
//
relationHandle(groupId) {
this.relationVisible = true;
this.$nextTick(() => {
this.$refs.relationUpdate.init(groupId);
});
},
//
treenodeclick(data, node, component) {
if (node.level == 3) {
this.catId = data.catId;
this.getDataList(); //
}
},
getAllDataList(){
this.catId = 0;
this.getDataList();
},
//
getDataList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/list/${this.catId}`),
method: "get",
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val;
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
//
deleteHandle(id) {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.attrGroupId;
});
this.$confirm(
`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
this.$http({
url: this.$http.adornUrl("/product/attrgroup/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList();
}
});
} else {
this.$message.error(data.msg);
}
});
});
}
}
};
</script>
<style scoped>
</style>
<!-- -->
<template>
<el-row :gutter="20">
<el-col :span="6">
<category @tree-node-click="treeNodeClick"></category>
</el-col>
<el-col :span="18">
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button v-if="isAuth('product:attrgroup:save')" type="primary"
@click="addOrUpdateHandle()">新增</el-button>
<el-button v-if="isAuth('product:attrgroup:delete')" type="danger" @click="deleteHandle()"
:disabled="dataListSelections.length <= 0">批量删除</el-button>
</el-form-item>
</el-form>
<el-table :data="dataList" border v-loading="dataListLoading" @selection-change="selectionChangeHandle"
style="width: 100%;">
<el-table-column type="selection" header-align="center" align="center" width="50">
</el-table-column>
<el-table-column prop="attrGroupId" header-align="center" align="center" label="分组id">
</el-table-column>
<el-table-column prop="attrGroupName" header-align="center" align="center" label="组名">
</el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序">
</el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="描述">
</el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="组图标">
</el-table-column>
<el-table-column prop="catelogId" header-align="center" align="center" label="所属分类id">
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small"
@click="addOrUpdateHandle(scope.row.attrGroupId)">修改</el-button>
<el-button type="text" size="small"
@click="deleteHandle(scope.row.attrGroupId)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
:current-page="pageIndex" :page-sizes="[10, 20, 50, 100]" :page-size="pageSize" :total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate"
@refreshDataList="getDataList"></add-or-update>
</div>
</el-col>
</el-row>
</template>
<script>
/*
父子组件传递数据
1子组件给父组件传递数据事件机制
子组件给父子件发送一个事件携带上数据
*/
//jsjsjson
//import from '';
import Category from "../common/category.vue";
import AddOrUpdate from "./attrgroup-add-or-update.vue";
export default {
//import使
components: { Category, AddOrUpdate },
data() {
return {
catId: 0,
dataForm: {
key: ''
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
}
},
// data
//data
watch: {},
//
methods: {
//
treeNodeClick(data, node, component) {
console.log("attrgroup感知到节点被点击", data, node, component);
console.log("菜单id:", data.catId);
if(node.childNodes.length == 0) {
this.catId=data.catId;
this.getDataList();
}
},
//
getDataList() {
this.dataListLoading = true
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/list/${this.catId}`),
method: 'get',
params: this.$http.adornParams({
'page': this.pageIndex,
'limit': this.pageSize,
'key': this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list
this.totalPage = data.page.totalCount
} else {
this.dataList = []
this.totalPage = 0
}
this.dataListLoading = false
})
},
//
sizeChangeHandle(val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
//
currentChangeHandle(val) {
this.pageIndex = val
this.getDataList()
},
//
selectionChangeHandle(val) {
this.dataListSelections = val
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
},
//
deleteHandle(id) {
var ids = id ? [id] : this.dataListSelections.map(item => {
return item.attrGroupId
})
this.$confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl('/product/attrgroup/delete'),
method: 'post',
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList()
}
})
} else {
this.$message.error(data.msg)
}
})
})
}
},
created(){
this.getDataList();
}
}
</script>

@ -247,5 +247,3 @@ export default {
}
};
</script>
<style scoped>
</style>

@ -379,5 +379,3 @@ export default {
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -91,5 +91,3 @@ export default {
activated() {} //keep-alive
};
</script>
<style scoped>
</style>
Loading…
Cancel
Save