From efdb99f8cecc4afb592afad79c761081d5d5cf22 Mon Sep 17 00:00:00 2001
From: lee <4766465@qq.com>
Date: Wed, 18 Dec 2024 13:27:00 +0800
Subject: [PATCH] init

---
 yami-shop-api/src/main/java/com/yami/shop/api/controller/ProdController.java |  285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 285 insertions(+), 0 deletions(-)

diff --git a/yami-shop-api/src/main/java/com/yami/shop/api/controller/ProdController.java b/yami-shop-api/src/main/java/com/yami/shop/api/controller/ProdController.java
new file mode 100644
index 0000000..6852b8f
--- /dev/null
+++ b/yami-shop-api/src/main/java/com/yami/shop/api/controller/ProdController.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
+ *
+ * https://www.mall4j.com/
+ *
+ * 未经允许,不可做商业用途!
+ *
+ * 版权所有,侵权必究!
+ */
+package com.yami.shop.api.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yami.shop.bean.app.dto.*;
+import com.yami.shop.bean.app.vo.ProductVO;
+import com.yami.shop.bean.enums.ProdStatusEnums;
+import com.yami.shop.bean.enums.ProdType;
+import com.yami.shop.bean.enums.ShopStatus;
+import com.yami.shop.bean.event.CheckAddrEvent;
+import com.yami.shop.bean.event.LoadProdActivistEvent;
+import com.yami.shop.bean.event.ProcessActivityProdPriceEvent;
+import com.yami.shop.bean.model.*;
+import com.yami.shop.bean.param.EsProductParam;
+import com.yami.shop.bean.param.ProductParam;
+import com.yami.shop.bean.vo.search.EsProductSearchVO;
+import com.yami.shop.bean.vo.search.ProductSearchVO;
+import com.yami.shop.common.config.Constant;
+import com.yami.shop.common.exception.YamiShopBindException;
+import com.yami.shop.common.i18n.I18nMessage;
+import com.yami.shop.common.response.ServerResponseEntity;
+import com.yami.shop.common.util.Json;
+import com.yami.shop.common.util.PageParam;
+import com.yami.shop.delivery.common.model.SameCity;
+import com.yami.shop.delivery.common.service.SameCityService;
+import com.yami.shop.search.common.param.EsPageParam;
+import com.yami.shop.search.common.service.SearchProductService;
+import com.yami.shop.search.common.vo.EsPageVO;
+import com.yami.shop.security.api.model.YamiUser;
+import com.yami.shop.security.api.util.SecurityUtils;
+import com.yami.shop.security.common.bo.UserInfoInTokenBO;
+import com.yami.shop.security.common.util.AuthUserContext;
+import com.yami.shop.service.*;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.Operation;
+import ma.glasnost.orika.MapperFacade;
+import org.springdoc.api.annotations.ParameterObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author LGH
+ */
+@RestController
+@RequestMapping("/prod")
+@Tag(name = "商品接口")
+public class ProdController {
+
+    @Autowired
+    private ProductService prodService;
+    @Autowired
+    private CategoryService categoryService;
+    @Autowired
+    private MapperFacade mapperFacade;
+    @Autowired
+    private SameCityService sameCityService;
+    @Autowired
+    private ApplicationContext applicationContext;
+    @Autowired
+    private SkuService skuService;
+    @Autowired
+    private ProdCommService prodCommService;
+    @Autowired
+    private ShopDetailService shopDetailService;
+    @Autowired
+    private ProdParameterService prodParameterService;
+    @Autowired
+    private SearchProductService searchProductService;
+
+    @GetMapping("/prodInfo")
+    @Operation(summary = "商品详情信息" , description = "根据商品ID(prodId)获取商品信息")
+    @Parameter(name = "prodId", description = "商品ID" , required = true)
+    public ServerResponseEntity<ProductVO> prodInfo(Long prodId, String userId) {
+        Integer dbLang = I18nMessage.getDbLang();
+        Product product = prodService.getProductInfo(prodId, dbLang);
+        if (product == null || product.getStatus() != 1) {
+            // 商品已下线
+            throw new YamiShopBindException("yami.product.off.shelves");
+        }
+        // 检查店铺是否处于营业状态
+        checkShopStatusIsOpen(product);
+        // 启用的sku列表
+        List<Sku> skuList = skuService.listPutOnSkuAndSkuStock(prodId, dbLang);
+        product.setSkuList(skuList);
+        ProductVO productVO = mapperFacade.map(product, ProductVO.class);
+        if(Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_ACTIVE.value()) || (Objects.nonNull(productVO.getMold()) && productVO.getMold() == 1)){
+            productVO.setIsDelivery(true);
+        }else{
+            // 判断用户默认地址是否在配送区域内
+            applicationContext.publishEvent(new CheckAddrEvent(0L, userId, productVO, null));
+        }
+        // 如果是积分商品, 所有数据已经获取完成了
+        if (Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_SCORE.value())) {
+            return ServerResponseEntity.success(productVO);
+        }
+        // 发送事件,获取商品可用的正在开播直播间、商品套餐、秒杀、团购、积分商品信息
+        applicationContext.publishEvent(new LoadProdActivistEvent(prodId, productVO, product.getProdType()));
+        // 普通商品有多种物流,需要加载物流模板信息
+//        if (Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_NORMAL.value())) {
+        loadDeliveryMode(product.getDeliveryMode(), productVO);
+//        }
+        // 商品参数列表
+        List<ProdParameter> prodParameters = prodParameterService.listParameter(prodId, I18nMessage.getDbLang());
+        productVO.setProdParameterList(prodParameters);
+        return ServerResponseEntity.success(productVO);
+    }
+
+    @GetMapping("/skuList")
+    @Operation(summary = "sku信息" , description = "根据商品ID(prodId)单独获取sku信息")
+    @Parameter(name = "prodId", description = "商品ID" , required = true)
+    public ServerResponseEntity<List<SkuDto>> skuList(@RequestParam("prodId") Long prodId) {
+        return ServerResponseEntity.success(skuService.getProdDetailSkuInfo(prodId));
+    }
+
+    @GetMapping("/isStatus")
+    @Operation(summary = "校验商品是否下架" , description = "根据商品ID(prodId)校验商品是否下架")
+    @Parameter(name = "prodId", description = "商品ID" , required = true)
+    public ServerResponseEntity<Boolean> isStatus(Long prodId) {
+        Product product = prodService.getProductByProdId(prodId, I18nMessage.getDbLang());
+        if (product == null || product.getStatus() != 1) {
+            return ServerResponseEntity.success(false);
+        }
+        return ServerResponseEntity.success(true);
+    }
+
+    @GetMapping("/listProdByIdsAndType")
+    @Operation(summary = "获取商品信息" , description = "根据商品ids获取商品信息")
+    public ServerResponseEntity<List<ProductDto>> listProdByIdsAndType(@ParameterObject ApiProdDto apiProdDto) {
+        ProductParam productParam = mapperFacade.map(apiProdDto, ProductParam.class);
+        apiProdDto.setLang(I18nMessage.getDbLang());
+        apiProdDto.setStatus(ProdStatusEnums.NORMAL.getValue());
+        List<Product> products = prodService.listProdByIdsAndType(productParam);
+        processActivityProdPrice(productParam, products);
+        List<ProductDto> productDtos = mapperFacade.mapAsList(products, ProductDto.class);
+        return ServerResponseEntity.success(productDtos);
+    }
+
+    /**
+     * 处理下活动商品的价格
+     *
+     * @param product  筛选参数
+     * @param products 商品列表
+     */
+    private void processActivityProdPrice(ProductParam product, List<Product> products) {
+        Map<Integer, List<Product>> prodMap = products.stream().collect(Collectors.groupingBy(Product::getProdType));
+        if (prodMap.containsKey(ProdType.PROD_TYPE_SECKILL.value())) {
+            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_SECKILL.value())));
+        }
+
+        if (prodMap.containsKey(ProdType.PROD_TYPE_GROUP.value())) {
+            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_GROUP.value())));
+        }
+    }
+
+    @GetMapping("/prodCommData")
+    @Operation(summary = "返回商品评论数据(好评率 好评数量 中评数 差评数)" , description = "根据商品id获取")
+    @Parameter(name = "prodId", description = "商品id" , required = true)
+    public ServerResponseEntity<ProdCommDataDto> getProdCommData(Long prodId) {
+        return ServerResponseEntity.success(prodCommService.getProdCommDataByProdId(prodId));
+    }
+
+    @GetMapping("/prodCommPageByProd")
+    @Operation(summary = "根据商品返回评论分页数据" , description = "传入商品id和页码")
+    @Parameters({
+            @Parameter(name = "prodId", description = "商品id" , required = true),
+            @Parameter(name = "evaluate", description = "-1或null 全部,0好评 1中评 2差评 3有图" , required = true),
+    })
+    public ServerResponseEntity<IPage<ProdCommDto>> getProdCommPageByProdId(PageParam page, Long prodId, Integer evaluate) {
+        return ServerResponseEntity.success(prodCommService.getProdCommDtoPageByProdId(page, prodId, evaluate));
+    }
+
+    /**
+     *  用户未登录情况下的商品推荐
+     * @param page
+     * @param productParam
+     * @return
+     */
+    @GetMapping("/recommendList")
+    @Operation(summary = "推荐商品列表" , description = "根据商品ID(prodId)获取商品信息")
+    public ServerResponseEntity<EsPageVO<EsProductSearchVO>> recommendList(PageParam page, @ParameterObject ProductParam productParam) {
+        EsProductParam esProductParam = new EsProductParam();
+        if (Objects.isNull(productParam.getProdType())) {
+            esProductParam.setProdType(ProdType.PROD_TYPE_NORMAL.value());
+        }
+        Long primaryCategoryId = null;
+        List<Category> categoryList = categoryService.getCategoryAndParent(productParam.getCategoryId());
+        if (CollUtil.isNotEmpty(categoryList)) {
+            primaryCategoryId = categoryList.get(0).getCategoryId();
+        }
+        esProductParam.setPrimaryCategoryId(primaryCategoryId);
+        //如果有商品id则过滤掉
+        if (Objects.nonNull(productParam.getProdId())) {
+            List<Long> prodIds = new ArrayList<>();
+            prodIds.add(productParam.getProdId());
+            esProductParam.setSpuIdsExclude(prodIds);
+        }
+        EsPageParam esPageParam = new EsPageParam();
+        esPageParam.setCurrent((int) page.getCurrent());
+        esPageParam.setSize((int) page.getSize());
+        EsPageVO<EsProductSearchVO> productPage = searchProductService.page(esPageParam, esProductParam, Boolean.FALSE);
+        List<ProductSearchVO> products = productPage.getRecords().get(0).getProducts();
+        long current = page.getCurrent();
+        long size = page.getSize();
+        int spuNum = products.size();
+        // 推荐商品的数量不足时,查询额外的商品进行填充
+        if (Objects.equals(current , 1L) && size > spuNum) {
+            esPageParam.setSize(Math.toIntExact(size - spuNum));
+            esPageParam.setCurrent(1);
+            // 查询该分类以外的商品
+            esProductParam.setPrimaryCategoryId(null);
+            esProductParam.setNotPrimaryCategoryId(primaryCategoryId);
+            EsPageVO<EsProductSearchVO> subProductPage = searchProductService.page(esPageParam, esProductParam, Boolean.FALSE);
+            for (EsProductSearchVO productSearchVO : subProductPage.getRecords()) {
+                if (CollUtil.isNotEmpty(productSearchVO.getProducts())) {
+                    products.addAll(productSearchVO.getProducts());
+                }
+            }
+            productPage.setTotal((long) products.size());
+            productPage.setPages(productPage.getTotal() > 0 ? (int)page.getCurrent() : 0);
+        }
+        return ServerResponseEntity.success(productPage);
+    }
+
+    private void checkShopStatusIsOpen(Product product) {
+        // 积分商品的平台店铺不需要检验
+        if (Objects.equals(product.getShopId(), Constant.PLATFORM_SHOP_ID)) {
+            return;
+        }
+        Date now = new Date();
+        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(product.getShopId());
+        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN.value())) {
+            return;
+        }
+        product.setShopName(shopDetail.getShopName());
+        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value()) || Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
+            throw new YamiShopBindException("店铺已下线");
+        }
+        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.STOP.value())) {
+            if (now.compareTo(shopDetail.getContractStartTime()) < 0) {
+                throw new YamiShopBindException("店铺未开始营业");
+            } else {
+                throw new YamiShopBindException("店铺已停止营业");
+            }
+        }
+        throw new YamiShopBindException("店铺状态异常");
+    }
+
+    /**
+     * 加载商品物流模板
+     * @param deliveryMode
+     * @param productVO
+     */
+    private void loadDeliveryMode(String deliveryMode, ProductVO productVO) {
+        // 物流模板
+        Product.DeliveryModeVO deliveryModeVO = Json.parseObject(deliveryMode, Product.DeliveryModeVO.class);
+        SameCity sameCity = sameCityService.getSameCityByShopId(productVO.getShopId());
+        // 如果同城配送是关闭了的,前端就不需要显示同城配送了
+        if (Objects.isNull(sameCity) || !Objects.equals(1, sameCity.getStatus()) || Objects.isNull(deliveryModeVO.getHasCityDelivery())) {
+            deliveryModeVO.setHasCityDelivery(false);
+        }
+        if (deliveryModeVO.getHasCityDelivery() != null && deliveryModeVO.getHasCityDelivery() && Objects.nonNull(sameCity)) {
+            productVO.setStartDeliveryFee(sameCity.getStartingFee());
+        }
+        productVO.setDeliveryModeVO(deliveryModeVO);
+    }
+}

--
Gitblit v1.9.3