添加商品关联推荐
This commit is contained in:
@@ -72,6 +72,15 @@ public class UProductController {
|
|||||||
return CzgResult.success(list);
|
return CzgResult.success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取相关推荐商品
|
||||||
|
*/
|
||||||
|
@GetMapping("/related/{id}")
|
||||||
|
public CzgResult<List<ShopProductVo>> getRelatedProduct(@PathVariable("id") Long id) {
|
||||||
|
AssertUtil.isNull(id, "商品id不能为空");
|
||||||
|
return CzgResult.success(uProductService.queryProductRelatedList(id));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小程序点餐-商品详情
|
* 小程序点餐-商品详情
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.czg.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.czg.product.dto.ProductDTO;
|
||||||
|
import com.czg.product.service.ProductService;
|
||||||
|
import com.czg.product.service.UProductService;
|
||||||
|
import com.czg.product.vo.ShopGroupProductVo;
|
||||||
|
import com.czg.product.vo.ShopProductVo;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2025/12/24 13:36
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
public class ProductTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProductService productService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UProductService uProductService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetById() {
|
||||||
|
// ProductDTO product = productService.getProductById(169L);
|
||||||
|
// System.out.println(JSONObject.toJSONString( product));
|
||||||
|
|
||||||
|
List<ShopProductVo> productVos = uProductService.queryProductRelatedList(169L);
|
||||||
|
System.out.println(JSONObject.toJSONString(productVos));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
package com.czg.product.dto;
|
package com.czg.product.dto;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.annotation.JSONField;
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
import com.czg.product.vo.ProductGroupVo;
|
import com.czg.product.vo.ProductGroupVo;
|
||||||
import com.czg.validator.group.DefaultGroup;
|
import com.czg.validator.group.DefaultGroup;
|
||||||
import com.czg.validator.group.InsertGroup;
|
import com.czg.validator.group.InsertGroup;
|
||||||
import com.czg.validator.group.UpdateGroup;
|
import com.czg.validator.group.UpdateGroup;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -235,6 +238,12 @@ public class ProductDTO implements Serializable {
|
|||||||
* 是否可售时间 1-是 0-否
|
* 是否可售时间 1-是 0-否
|
||||||
*/
|
*/
|
||||||
private Integer isSaleTime;
|
private Integer isSaleTime;
|
||||||
|
/**
|
||||||
|
* 相关推荐商品
|
||||||
|
*/
|
||||||
|
private List<RelatedProductDTO> relatedRecommendJson;
|
||||||
|
@JsonIgnore
|
||||||
|
private String relatedRecommend;
|
||||||
|
|
||||||
public Object getImages() {
|
public Object getImages() {
|
||||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||||
@@ -250,4 +259,16 @@ public class ProductDTO implements Serializable {
|
|||||||
public Object getGroupSnap() {
|
public Object getGroupSnap() {
|
||||||
return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
|
return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRelatedRecommendStr() {
|
||||||
|
if (CollUtil.isNotEmpty(relatedRecommendJson)) {
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for (RelatedProductDTO relatedProductDTO : relatedRecommendJson) {
|
||||||
|
array.add(relatedProductDTO.getId());
|
||||||
|
}
|
||||||
|
return array.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.czg.product.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相关推荐 商品 DTO
|
||||||
|
*
|
||||||
|
* @author yjjie
|
||||||
|
* @date 2025/12/24 13:34
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RelatedProductDTO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品 ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 商品名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 商品图片
|
||||||
|
*/
|
||||||
|
private String coverImg;
|
||||||
|
}
|
||||||
@@ -142,6 +142,10 @@ public class Product implements Serializable {
|
|||||||
* 退款是否退回库存
|
* 退款是否退回库存
|
||||||
*/
|
*/
|
||||||
private Integer isRefundStock;
|
private Integer isRefundStock;
|
||||||
|
/**
|
||||||
|
* 相关推荐
|
||||||
|
*/
|
||||||
|
private String relatedRecommend;
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.czg.product.service;
|
package com.czg.product.service;
|
||||||
|
|
||||||
import com.czg.product.dto.ProductDTO;
|
import com.czg.product.dto.ProductDTO;
|
||||||
|
import com.czg.product.dto.RelatedProductDTO;
|
||||||
import com.czg.product.entity.Product;
|
import com.czg.product.entity.Product;
|
||||||
import com.czg.product.entity.ProductStockFlow;
|
import com.czg.product.entity.ProductStockFlow;
|
||||||
import com.czg.product.param.*;
|
import com.czg.product.param.*;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.czg.product.service;
|
package com.czg.product.service;
|
||||||
|
|
||||||
|
import com.czg.product.dto.RelatedProductDTO;
|
||||||
import com.czg.product.entity.Product;
|
import com.czg.product.entity.Product;
|
||||||
import com.czg.product.param.ShopProductSkuParam;
|
import com.czg.product.param.ShopProductSkuParam;
|
||||||
import com.czg.product.vo.ShopGroupProductVo;
|
import com.czg.product.vo.ShopGroupProductVo;
|
||||||
@@ -95,4 +96,6 @@ public interface UProductService extends IService<Product> {
|
|||||||
* @return 是否可售时间 1-是,0-否
|
* @return 是否可售时间 1-是,0-否
|
||||||
*/
|
*/
|
||||||
Integer calcIsSaleTime(String days, LocalTime startTime, LocalTime endTime);
|
Integer calcIsSaleTime(String days, LocalTime startTime, LocalTime endTime);
|
||||||
|
|
||||||
|
List<ShopProductVo> queryProductRelatedList(Long productId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ import com.czg.exception.CzgException;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -35,8 +32,8 @@ public class AliOcrUtil {
|
|||||||
/**
|
/**
|
||||||
* <b>description</b> :
|
* <b>description</b> :
|
||||||
* <p>使用凭据初始化账号Client</p>
|
* <p>使用凭据初始化账号Client</p>
|
||||||
* @return Client
|
|
||||||
*
|
*
|
||||||
|
* @return Client
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static com.aliyun.bailian20231229.Client createClient() {
|
public static com.aliyun.bailian20231229.Client createClient() {
|
||||||
@@ -56,7 +53,6 @@ public class AliOcrUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
|
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
|
||||||
|
|
||||||
String md5 = DigestUtil.md5Hex(bytes);
|
String md5 = DigestUtil.md5Hex(bytes);
|
||||||
@@ -158,9 +154,8 @@ public class AliOcrUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String appCall(byte[] bytes, String fileName) {
|
public static String appCall(byte[] bytes, String fileName) {
|
||||||
String id = null;
|
String id;
|
||||||
try {
|
try {
|
||||||
id = getSessionId(bytes, fileName);
|
id = getSessionId(bytes, fileName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -187,11 +182,4 @@ public class AliOcrUtil {
|
|||||||
return result.getOutput().getText();
|
return result.getOutput().getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void main() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public interface ProductMapper extends BaseMapper<Product> {
|
|||||||
|
|
||||||
List<ShopProductVo> selectHotsProductList(@Param("shopId") Long shopId);
|
List<ShopProductVo> selectHotsProductList(@Param("shopId") Long shopId);
|
||||||
|
|
||||||
List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId);
|
List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId, @Param("idList") List<Long> idList);
|
||||||
|
|
||||||
ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId);
|
ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId);
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import cn.hutool.core.util.NumberUtil;
|
|||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONWriter;
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
import com.czg.constant.CacheConstant;
|
import com.czg.constant.CacheConstant;
|
||||||
import com.czg.constants.SystemConstants;
|
import com.czg.constants.SystemConstants;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
import com.czg.product.dto.ProdConsRelationDTO;
|
import com.czg.product.dto.*;
|
||||||
import com.czg.product.dto.ProdSkuDTO;
|
|
||||||
import com.czg.product.dto.ProductDTO;
|
|
||||||
import com.czg.product.dto.ShopProdCategoryDTO;
|
|
||||||
import com.czg.product.entity.*;
|
import com.czg.product.entity.*;
|
||||||
import com.czg.product.enums.*;
|
import com.czg.product.enums.*;
|
||||||
import com.czg.product.param.*;
|
import com.czg.product.param.*;
|
||||||
@@ -310,6 +308,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
|||||||
dto.setSkuList(skuList);
|
dto.setSkuList(skuList);
|
||||||
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId());
|
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId());
|
||||||
dto.setConsList(consList);
|
dto.setConsList(consList);
|
||||||
|
dto.setRelatedRecommendJson(getRelateProductList(dto.getRelatedRecommend()));
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +335,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
|||||||
}
|
}
|
||||||
entity.setIsDel(SystemConstants.OneZero.ZERO);
|
entity.setIsDel(SystemConstants.OneZero.ZERO);
|
||||||
entity.setShopId(shopId);
|
entity.setShopId(shopId);
|
||||||
|
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
|
||||||
super.save(entity);
|
super.save(entity);
|
||||||
dto.setId(entity.getId());
|
dto.setId(entity.getId());
|
||||||
// 清除商品分类列表缓存
|
// 清除商品分类列表缓存
|
||||||
@@ -404,6 +404,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
|||||||
if (!ProductTypeEnum.SKU.value().equals(entity.getType())) {
|
if (!ProductTypeEnum.SKU.value().equals(entity.getType())) {
|
||||||
UpdateChain.of(Product.class).set(Product::getSpecId, null).eq(Product::getId, dto.getId()).update();
|
UpdateChain.of(Product.class).set(Product::getSpecId, null).eq(Product::getId, dto.getId()).update();
|
||||||
}
|
}
|
||||||
|
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
|
||||||
super.updateById(entity);
|
super.updateById(entity);
|
||||||
// 清除商品分类列表缓存
|
// 清除商品分类列表缓存
|
||||||
clearProductCache(old.getCategoryId());
|
clearProductCache(old.getCategoryId());
|
||||||
@@ -788,4 +789,16 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
|
|||||||
String key = StrUtil.format(CacheConstant.SHOP_PRODUCT_STOCK, shopId, productId);
|
String key = StrUtil.format(CacheConstant.SHOP_PRODUCT_STOCK, shopId, productId);
|
||||||
redisService.set(key, stockNumber);
|
redisService.set(key, stockNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<RelatedProductDTO> getRelateProductList(String relatedProduct) {
|
||||||
|
if (StrUtil.isNotBlank(relatedProduct) && !"[]".equals(relatedProduct)) {
|
||||||
|
List<Long> idList = JSONArray.parseArray(relatedProduct, Long.class);
|
||||||
|
|
||||||
|
QueryWrapper wrapper = QueryWrapper.create().select(Product::getId, Product::getName, Product::getCoverImg).eq(Product::getIsDel, SystemConstants.OneZero.ZERO)
|
||||||
|
.in(Product::getId, idList);
|
||||||
|
return super.listAs(wrapper, RelatedProductDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
|
|||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.czg.constant.CacheConstant;
|
import com.czg.constant.CacheConstant;
|
||||||
import com.czg.constants.SystemConstants;
|
import com.czg.constants.SystemConstants;
|
||||||
import com.czg.exception.CzgException;
|
import com.czg.exception.CzgException;
|
||||||
@@ -27,6 +28,7 @@ import com.czg.service.product.mapper.ProdGroupMapper;
|
|||||||
import com.czg.service.product.mapper.ProdGroupRelationMapper;
|
import com.czg.service.product.mapper.ProdGroupRelationMapper;
|
||||||
import com.czg.service.product.mapper.ProdSkuMapper;
|
import com.czg.service.product.mapper.ProdSkuMapper;
|
||||||
import com.czg.service.product.mapper.ProductMapper;
|
import com.czg.service.product.mapper.ProductMapper;
|
||||||
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -78,7 +80,7 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
|
|||||||
query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime)
|
query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime)
|
||||||
.eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE)
|
.eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE)
|
||||||
.orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class);
|
.orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class);
|
||||||
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId);
|
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, null);
|
||||||
productAllList.forEach(item -> {
|
productAllList.forEach(item -> {
|
||||||
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
|
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
|
||||||
.eq(ProdSku::getProductId, item.getId())
|
.eq(ProdSku::getProductId, item.getId())
|
||||||
@@ -233,6 +235,31 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
|
|||||||
return SystemConstants.OneZero.ZERO;
|
return SystemConstants.OneZero.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ShopProductVo> queryProductRelatedList(Long productId) {
|
||||||
|
Product product = getOne(QueryWrapper.create().eq(Product::getId, productId)
|
||||||
|
.eq(Product::getShopId, StpKit.USER.getShopId())
|
||||||
|
.eq(Product::getIsDel, SystemConstants.OneZero.ZERO));
|
||||||
|
|
||||||
|
if (product == null) {
|
||||||
|
throw new CzgException("商品信息不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(product.getRelatedRecommend()) || "[]".equals(product.getRelatedRecommend())) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(product.getShopId(), JSONArray.parseArray(product.getRelatedRecommend(), Long.class));
|
||||||
|
productAllList.forEach(item -> {
|
||||||
|
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
|
||||||
|
.eq(ProdSku::getProductId, item.getId())
|
||||||
|
.eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
|
||||||
|
.eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
|
||||||
|
item.setSkuList(skuList);
|
||||||
|
});
|
||||||
|
return productAllList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算是否在可售时间内
|
* 计算是否在可售时间内
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -147,6 +147,12 @@
|
|||||||
and t2.sale_price is not null
|
and t2.sale_price is not null
|
||||||
and t1.shop_id = #{shopId}
|
and t1.shop_id = #{shopId}
|
||||||
</where>
|
</where>
|
||||||
|
<if test="idList != null">
|
||||||
|
and t1.id in
|
||||||
|
<foreach item="item" collection="idList" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
order by t1.sort desc,t1.id desc
|
order by t1.sort desc,t1.id desc
|
||||||
</select>
|
</select>
|
||||||
<select id="selectOneProductInfo" resultType="com.czg.product.vo.ShopProductInfoVo">
|
<select id="selectOneProductInfo" resultType="com.czg.product.vo.ShopProductInfoVo">
|
||||||
|
|||||||
Reference in New Issue
Block a user