zhangxin 4 hete
szülő
commit
b84c243884

+ 105 - 2
yami-shop-api/src/main/java/com/yami/shop/api/controller/ProdController.java

@@ -10,31 +10,46 @@
 
 package com.yami.shop.api.controller;
 
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson2.util.UUIDUtils;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yami.shop.bean.app.dto.ProdCommDataDto;
 import com.yami.shop.bean.app.dto.ProdCommDto;
 import com.yami.shop.bean.app.dto.ProductDto;
 import com.yami.shop.bean.dto.ProdByCategoryIdAndShopIdDTO;
+import com.yami.shop.bean.dto.SearchProdDto;
+import com.yami.shop.bean.model.ChannelProd;
 import com.yami.shop.bean.model.Product;
 import com.yami.shop.bean.model.Sku;
+import com.yami.shop.bean.model.UserShopBehavior;
 import com.yami.shop.common.exception.GlobalException;
+import com.yami.shop.common.util.Arith;
 import com.yami.shop.common.util.PageParam;
+import com.yami.shop.security.api.model.YamiUser;
+import com.yami.shop.security.api.util.SecurityUtils;
 import com.yami.shop.service.ProdCommService;
 import com.yami.shop.service.ProductService;
 import com.yami.shop.service.SkuService;
+import com.yami.shop.service.UserShopBehaviorService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import ma.glasnost.orika.MapperFacade;
 import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.core.util.JsonUtils;
+import org.apache.logging.log4j.core.util.UuidUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.Comparator;
-import java.util.List;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @RestController
@@ -42,6 +57,8 @@ import java.util.stream.Collectors;
 @Api(tags = "商品接口")
 public class ProdController {
 
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
     @Autowired
     private ProductService prodService;
 
@@ -54,12 +71,57 @@ public class ProdController {
     @Autowired
     private ProdCommService prodCommService;
 
+    @Autowired
+    private UserShopBehaviorService userShopBehaviorService;
+
 
     @GetMapping("/prodInfo")
     @ApiOperation(value = "商品详情信息", notes = "根据商品ID(prodId)获取商品信息")
     @ApiImplicitParam(name = "prodId", value = "商品ID", required = true, dataType = "Long")
     public ResponseEntity<ProductDto> prodInfo(@RequestParam("prodId") Long prodId, @RequestParam("platform") Integer platform, @RequestParam("shopId") Long shopId) {
 
+        YamiUser user = null;
+        try {
+            user = SecurityUtils.getUser();
+        } catch (Exception e) {
+            System.out.println("订单详情:" + e.getMessage());
+            logger.error("订单详情:错误信息", e);
+        }
+        if (user != null) {
+            String userId = user.getUserId();
+            if (StringUtils.isNotEmpty(userId)) {
+                UserShopBehavior userShopBehavior = null;
+                userShopBehavior = userShopBehaviorService.findByUserIdAndProd(userId, prodId);
+                if (userShopBehavior == null) {
+                    int num = userShopBehaviorService.findByUserIdCount(userId);
+                    if (num < 6) {
+                        userShopBehavior = new UserShopBehavior();
+                        userShopBehavior.setId(UUID.randomUUID().toString());
+                        userShopBehavior.setUserId(userId);
+                        userShopBehavior.setShopId(shopId);
+                        userShopBehavior.setProdId(prodId);
+                        userShopBehavior.setCreateTime(new Date());
+                        userShopBehaviorService.save(userShopBehavior);
+                    } else {
+                        List<UserShopBehavior> userShopBehaviors = userShopBehaviorService.findByUserId(userId, 1);
+                        if (userShopBehaviors != null && !userShopBehaviors.isEmpty()) {
+                            userShopBehavior = userShopBehaviors.get(0);
+                        }
+                        if (userShopBehavior != null) {
+                            userShopBehavior.setProdId(prodId);
+                            userShopBehavior.setShopId(shopId);
+                            userShopBehavior.setCreateTime(new Date());
+                            userShopBehaviorService.updateById(userShopBehavior);
+                        }
+                    }
+                } else {
+                    userShopBehavior.setCreateTime(new Date());
+                    userShopBehaviorService.updateById(userShopBehavior);
+                }
+
+            }
+        }
+
         Product product = prodService.getProductByProdId(prodId, platform);
         if (product == null || product.getStatus() != 1) {
             throw new GlobalException("商品已下线");
@@ -150,4 +212,45 @@ public class ProdController {
         return ResponseEntity.ok(prodService.listProdByCategoryIdAndShopId(prodByCategoryIdAndShopIdDTO));
     }
 
+    @GetMapping("/prodRecommended")
+    @ApiOperation(value = "为你推荐", notes = "为你推荐")
+    public ResponseEntity<IPage<SearchProdDto>> getProdRecommended(PageParam<SearchProdDto> page) {
+        IPage<SearchProdDto>   searchProdDtos = page;
+        List<ProductDto> productDtos = new ArrayList<>();
+        YamiUser user = null;
+        try {
+            user = SecurityUtils.getUser();
+        } catch (Exception e) {
+            System.out.println("为你推荐:" + e.getMessage());
+            logger.error("为你推荐:错误信息", e);
+        }
+        if (user != null) {
+            String userId = user.getUserId();
+            if (StringUtils.isNotEmpty(userId)) {
+                List<UserShopBehavior> byUserId = userShopBehaviorService.findByUserId(userId, 5);
+                for (UserShopBehavior userShopBehavior : byUserId) {
+                    ChannelProd channelProd = userShopBehaviorService.findByProdId(userShopBehavior.getProdId(), userShopBehavior.getShopId());
+                    if (channelProd != null) {
+                        BigDecimal channelProdPrice = channelProd.getChannelProdPrice();
+                        if (channelProdPrice != null) {
+                            BigDecimal increased = channelProdPrice.multiply(new BigDecimal("1.10"))
+                                    .setScale(2, RoundingMode.HALF_UP);
+                            BigDecimal decreased = channelProdPrice.multiply(new BigDecimal("0.90"))
+                                    .setScale(2, RoundingMode.HALF_UP);
+                            List<ProductDto> productDtoList = userShopBehaviorService.findByProdIdAndShopIdAndPrice(userShopBehavior.getProdId(), userShopBehavior.getShopId(), increased, decreased);
+                            if (productDtoList != null && !productDtoList.isEmpty()) {
+                                productDtos.addAll(productDtoList);
+                            }
+                        }
+                    }
+
+                }
+            }
+            if (!productDtos.isEmpty()){
+                searchProdDtos =   userShopBehaviorService.findByProdAndShop(page,productDtos);
+            }
+        }
+
+        return ResponseEntity.ok(searchProdDtos);
+    }
 }

+ 43 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/model/UserShopBehavior.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
+ *
+ * https://www.gz-yami.com/
+ *
+ * 未经允许,不可做商业用途!
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.yami.shop.bean.model;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@TableName("tz_user_shop_behavior")
+public class UserShopBehavior implements Serializable {
+    private static final long serialVersionUID = -6013320537436191451L;
+    @TableId
+    @ApiModelProperty(value = "id",required=true)
+    private String id;
+
+    @ApiModelProperty(value = "用户id",required=true)
+    private String userId;
+
+    @ApiModelProperty(value = "商品id",required=true)
+    private Long prodId;
+
+    @ApiModelProperty(value = "店铺id",required=true)
+    private Long shopId;
+
+    @ApiModelProperty(value = "创建时间",required=true)
+    private Date createTime;
+}

+ 5 - 3
yami-shop-security/yami-shop-security-api/src/main/java/com/yami/shop/security/api/util/SecurityUtils.java

@@ -20,9 +20,11 @@ public class SecurityUtils {
      * 获取用户
      */
     public YamiUser getUser() {
-        if (!HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith("/p/") &&
-                !HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith("/user/registerOrBindUser")) {
-            throw new RuntimeException("用户相关的请求,应该以/p开头!!!");
+        if (!HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith("/prod/")){
+            if (!HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith("/p/") &&
+                    !HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith("/user/registerOrBindUser")) {
+                throw new RuntimeException("用户相关的请求,应该以/p开头!!!");
+            }
         }
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
 

+ 8 - 0
yami-shop-service/src/main/java/com/yami/shop/dao/ProductMapper.java

@@ -19,6 +19,7 @@ import com.yami.shop.bean.app.param.SearchParam;
 import com.yami.shop.bean.dto.ProdAndSkuListsDto;
 import com.yami.shop.bean.dto.ProdByCategoryIdAndShopIdDTO;
 import com.yami.shop.bean.dto.SearchProdDto;
+import com.yami.shop.bean.model.ChannelProd;
 import com.yami.shop.bean.model.OrderItem;
 import com.yami.shop.bean.model.Product;
 import com.yami.shop.bean.model.ShopDetail;
@@ -28,6 +29,7 @@ import com.yami.shop.bean.param.ProductParam;
 import com.yami.shop.common.util.PageParam;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -178,4 +180,10 @@ public interface ProductMapper extends BaseMapper<Product> {
      * @return 商品信息
      */
     Product selectByHbSpuId(@Param("hbSpuId") String hbSpuId);
+
+    ChannelProd findByProdIdAndShopId(@Param("prodId")Long prodId,@Param("shopId") Long shopId);
+
+    List<ProductDto> findByProdIdAndShopIdAndPrice(@Param("prodId")Long prodId, @Param("shopId")Long shopId, @Param("increased")BigDecimal increased, @Param("decreased")BigDecimal decreased);
+
+    IPage<SearchProdDto> findByProdAndShop(@Param("page") PageParam<SearchProdDto> page, @Param("list")List<ProductDto> productDtos);
 }

+ 27 - 0
yami-shop-service/src/main/java/com/yami/shop/dao/UserShopBehaviorMapper.java

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
+ *
+ * https://www.gz-yami.com/
+ *
+ * 未经允许,不可做商业用途!
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.yami.shop.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yami.shop.bean.dto.AreaDto;
+import com.yami.shop.bean.model.Area;
+import com.yami.shop.bean.model.UserShopBehavior;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface UserShopBehaviorMapper extends BaseMapper<UserShopBehavior> {
+    int findByUserIdCount(@Param("userId") String userId);
+
+    List<UserShopBehavior> findByUserId(@Param("userId")String userId,@Param("num")Integer num);
+
+    UserShopBehavior findByUserIdAndProd(@Param("userId")String userId,@Param("prodId") Long prodId);
+}

+ 60 - 0
yami-shop-service/src/main/java/com/yami/shop/service/UserShopBehaviorService.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
+ *
+ * https://www.gz-yami.com/
+ *
+ * 未经允许,不可做商业用途!
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.yami.shop.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yami.shop.bean.app.dto.ProductDto;
+import com.yami.shop.bean.dto.AreaDto;
+import com.yami.shop.bean.dto.SearchProdDto;
+import com.yami.shop.bean.model.Area;
+import com.yami.shop.bean.model.ChannelProd;
+import com.yami.shop.bean.model.UserShopBehavior;
+import com.yami.shop.common.util.PageParam;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author lgh on 2018/10/26.
+ */
+public interface UserShopBehaviorService extends IService<UserShopBehavior> {
+
+    /**
+     * 根据用户id查询当前用户有几条记录
+     * @param userId
+     * @return
+     */
+    int findByUserIdCount(String userId);
+
+    /**
+     * 根据用户id查询最初的几条记录
+     * @param userId 用户id
+     * @param num 取前几条数据
+     * @return
+     */
+    List<UserShopBehavior> findByUserId(String userId,Integer num);
+
+    /**
+     * 根据用户id和商品id查询当前用户是否有查询同一商品的痕迹
+     * @param userId
+     * @param prodId
+     * @return
+     */
+    UserShopBehavior findByUserIdAndProd(String userId, Long prodId);
+
+    ChannelProd findByProdId(Long prodId, Long shopId);
+
+    List<ProductDto> findByProdIdAndShopIdAndPrice(Long prodId, Long shopId, BigDecimal increased, BigDecimal decreased);
+
+    IPage<SearchProdDto> findByProdAndShop(PageParam<SearchProdDto> page, List<ProductDto> productDtos);
+
+}

+ 94 - 0
yami-shop-service/src/main/java/com/yami/shop/service/impl/UserShopBehaviorServiceImpl.java

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
+ *
+ * https://www.gz-yami.com/
+ *
+ * 未经允许,不可做商业用途!
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.yami.shop.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import com.yami.shop.bean.app.dto.ProductDto;
+import com.yami.shop.bean.app.dto.SkuDto;
+import com.yami.shop.bean.dto.AreaDto;
+import com.yami.shop.bean.dto.SearchProdDto;
+import com.yami.shop.bean.model.Area;
+import com.yami.shop.bean.model.ChannelProd;
+import com.yami.shop.bean.model.UserShopBehavior;
+import com.yami.shop.common.util.PageParam;
+import com.yami.shop.dao.AreaMapper;
+import com.yami.shop.dao.ProductMapper;
+import com.yami.shop.dao.SkuMapper;
+import com.yami.shop.dao.UserShopBehaviorMapper;
+import com.yami.shop.service.AreaService;
+import com.yami.shop.service.UserShopBehaviorService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author lgh on 2018/10/26.
+ */
+@Service
+public class UserShopBehaviorServiceImpl extends ServiceImpl<UserShopBehaviorMapper, UserShopBehavior> implements UserShopBehaviorService {
+
+    @Autowired
+    private ProductMapper productMapper;
+
+    @Autowired
+    private SkuMapper skuMapper;
+
+    @Override
+    public int findByUserIdCount(String userId) {
+
+        return  baseMapper.findByUserIdCount(userId);
+    }
+
+    @Override
+    public List<UserShopBehavior> findByUserId(String userId,Integer num) {
+        return baseMapper.findByUserId(userId,num);
+    }
+
+    @Override
+    public UserShopBehavior findByUserIdAndProd(String userId, Long prodId) {
+        return baseMapper.findByUserIdAndProd(userId,prodId);
+    }
+
+    @Override
+    public ChannelProd findByProdId(Long prodId, Long shopId) {
+        return productMapper.findByProdIdAndShopId(prodId,shopId);
+    }
+
+    @Override
+    public List<ProductDto> findByProdIdAndShopIdAndPrice(Long prodId, Long shopId, BigDecimal increased, BigDecimal decreased) {
+        return productMapper.findByProdIdAndShopIdAndPrice(prodId,shopId,increased,decreased);
+    }
+
+    @Override
+    public IPage<SearchProdDto> findByProdAndShop(PageParam<SearchProdDto> page, List<ProductDto> productDtos) {
+        IPage<SearchProdDto> byProdAndShop = productMapper.findByProdAndShop(page,productDtos);
+        if (byProdAndShop!=null&&byProdAndShop.getRecords()!=null&&!byProdAndShop.getRecords().isEmpty()){
+            for (SearchProdDto searchProdDto : byProdAndShop.getRecords()) {
+                List<SkuDto> skuList = skuMapper.listByProdId(searchProdDto.getProdId()).stream().map((sku) -> SkuDto.builder()
+                        .skuName(sku.getSkuName()).pic(sku.getPic()).skuScore(sku.getSkuScore()).price(sku.getPrice())
+                        .stocks(sku.getStocks()).properties(sku.getProperties()).skuId(sku.getSkuId())
+                        .build()).collect(Collectors.toList());
+                searchProdDto.setSkuList(skuList);
+            }
+        }
+
+
+        return byProdAndShop;
+    }
+}

+ 56 - 0
yami-shop-service/src/main/resources/mapper/ProductMapper.xml

@@ -871,5 +871,61 @@
     <select id="selectByHbSpuId" resultType="com.yami.shop.bean.model.Product">
         select * from tz_prod where hb_spu_id = #{hbSpuId} AND is_delete = 0;
     </select>
+    <select id="findByProdIdAndShopId" resultType="com.yami.shop.bean.model.ChannelProd">
+        select a.* from tz_channel_prod a
+        INNER join  tz_sku b  on  b.prod_id = #{prodId} and b.sku_id = a.sku_id and b.is_delete = 0
+        where a.shop_id=#{shopId} and a.is_delete = 0 ORDER BY a.channel_prod_price  LIMIT 1
+    </select>
+
+    <select id="findByProdIdAndShopIdAndPrice" resultType="com.yami.shop.bean.app.dto.ProductDto">
+        SELECT DISTINCT
+        d.prod_id,
+        d.shop_id,
+        IFNULL(i.count,0)
+        FROM tz_category_prod a  -- 商品类目关联表
+        INNER JOIN tz_shop_category b ON a.`code` = b.`code`   -- 商品类目表
+        INNER JOIN tz_category_prod c ON b.`code` = c.`code` AND c.shop_id = a.shop_id and c.is_delete =0 -- 商品类目关联表
+        INNER JOIN tz_prod d ON c.shop_id = d.shop_id AND c.prod_id = d.prod_id  AND d.`status` = 1 and d.is_delete=0  -- 商品表
+        INNER JOIN tz_sku e on  d.prod_id  =  e.prod_id and e.is_delete=0 -- 商品规格表
+        INNER JOIN tz_channel_prod f on  d.shop_id =f.shop_id and e.sku_id =f.sku_id and f.is_delete = 0  -- 渠道商品价格表
+        and f.channel_prod_price &gt;=#{decreased} and  f.channel_prod_price &lt;=#{increased}
+        LEFT JOIN (SELECT count(h.order_item_id) as count,h.prod_id  from  tz_order g LEFT JOIN tz_order_item h on g.order_number = h.order_number where g.refund_status is null and g.delete_status and g.hb_order_status = 80) i on d.prod_id = i.prod_id -- 统计销量
+        WHERE a.prod_id = #{prodId}
+        AND d.shop_id = #{shopId}
+        AND b.`level` = 2
+        and a.is_delete =0
+        ORDER BY i.count DESC limit 6
+    </select>
+    <select id="findByProdAndShop" resultType="com.yami.shop.bean.dto.SearchProdDto">
+        SELECT
+        SUM(tss.shop_sku_stocks) as stocks,
+        p.prod_id,
+        p.imgs as pic,
+        p.prod_name,
+        MIN(tcp.channel_prod_price) as price,
+        p.brief,
+        tss.shop_id AS shopId,
+        tss.self_label_id AS selfLabelId,
+        tss.return_label_id AS returnLabelId,
+        tss.hot_label_id AS hotLabelId,
+        COUNT(pc.prod_comm_id) as prod_comm_number,
+        COUNT(CASE WHEN pc.evaluate = 0 THEN pc.prod_comm_id ELSE null END) AS praise_number,
+        IFNULL(i.count,0)
+        FROM tz_prod p
+        INNER JOIN tz_shop_sku tss ON p.prod_id = tss.spu_id
+        INNER JOIN tz_shop_detail sd ON sd.shop_id = tss.shop_id
+        INNER JOIN tz_channel_prod tcp ON tss.sku_id = tcp.sku_id AND tcp.is_delete = 0
+        LEFT JOIN tz_prod_comm pc ON p.prod_id = pc.prod_id
+        LEFT JOIN tz_category_prod cp ON p.prod_id = cp.prod_id
+        LEFT JOIN tz_shop_category sc ON cp.code = sc.code
+        LEFT JOIN (SELECT count(h.order_item_id) as count,h.prod_id  from  tz_order g LEFT JOIN tz_order_item h on g.order_number = h.order_number where g.refund_status is null and g.delete_status and g.hb_order_status = 80) i on p.prod_id = i.prod_id -- 统计销量
+        WHERE p.status = 1
+        AND p.is_delete = 0
+        AND (p.shop_id, p.prod_id) IN
+        <foreach collection="list" item="item" open="(" close=")" separator=",">
+            (#{item.shopId}, #{item.prodId})
+        </foreach>
+        order by  i.count DESC
+    </select>
 
 </mapper>

+ 16 - 0
yami-shop-service/src/main/resources/mapper/UserShopBehaviorMapper.xml

@@ -0,0 +1,16 @@
+<?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.yami.shop.dao.UserShopBehaviorMapper">
+
+
+    <select id="findByUserIdCount" resultType="java.lang.Integer">
+        select ifNULL(count(1),0)  from  tz_user_shop_behavior where user_id = #{userId}
+
+    </select>
+    <select id="findByUserId" resultType="com.yami.shop.bean.model.UserShopBehavior">
+        select * from tz_user_shop_behavior  where user_id = #{userId} order by create_time limit #{num}
+    </select>
+    <select id="findByUserIdAndProd" resultType="com.yami.shop.bean.model.UserShopBehavior">
+        select * from tz_user_shop_behavior  where user_id = #{userId} and prod_id =#{prodId}
+    </select>
+</mapper>