收音机 / 客户端 商品列表

This commit is contained in:
2026-04-09 16:54:57 +08:00
parent caec6b2d0f
commit 3448331b31
4 changed files with 32 additions and 78 deletions

View File

@@ -56,9 +56,6 @@ public class ProductController {
@Resource @Resource
private ShopSyncService shopSyncService; private ShopSyncService shopSyncService;
@Resource
private UProductService uProductService;
@Resource @Resource
private ShopInfoService shopInfoService; private ShopInfoService shopInfoService;
@@ -87,12 +84,8 @@ public class ProductController {
*/ */
@GetMapping("list") @GetMapping("list")
@OperationLog("商品-列表") @OperationLog("商品-列表")
//@SaAdminCheckPermission("product:list") public CzgResult<List<ProductDTO>> getProductList(@RequestParam Long categoryId) {
public CzgResult<List<ProductDTO>> getProductList(ProductDTO param) { List<ProductDTO> productList = productService.getProductCacheList(StpKit.USER.getShopId(), categoryId);
Long shopId = StpKit.USER.getShopId();
param.setShopId(shopId);
List<ProductDTO> productList = productService.getProductCacheList(param);
productList.forEach(prod -> prod.setIsSaleTime(uProductService.calcIsSaleTime(prod.getDays(), prod.getStartTime(), prod.getEndTime())));
return CzgResult.success(productList); return CzgResult.success(productList);
} }

View File

@@ -5,6 +5,7 @@ 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.JSONArray;
import com.alibaba.fastjson2.annotation.JSONField; import com.alibaba.fastjson2.annotation.JSONField;
import com.czg.product.entity.ProdConsRelation;
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;
@@ -217,6 +218,8 @@ public class ProductDTO implements Serializable {
* 商品关联耗材列表 * 商品关联耗材列表
*/ */
private List<ProdConsRelationDTO> consList; private List<ProdConsRelationDTO> consList;
//
private List<ProdConsRelation> prodConsRelations;
/** /**
* 耗材信息 * 耗材信息
*/ */
@@ -240,13 +243,6 @@ public class ProductDTO implements Serializable {
return JSON.parseArray(Convert.toStr(images, "[]")); return JSON.parseArray(Convert.toStr(images, "[]"));
} }
/**
* {"口味":[{"甜度":["少甜","中甜","多甜"]},{"辣度":["微辣","重辣","变态辣"]},{"小料":["葱花","香菜","折耳根"]}]}
*/
public Object getSelectSpecInfo() {
return JSON.parseObject(Convert.toStr(selectSpecInfo, "{}"));
}
public Object getGroupSnap() { public Object getGroupSnap() {
return JSON.parseArray(Convert.toStr(groupSnap, "[]")); return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
} }

View File

@@ -38,10 +38,11 @@ public interface ProductService extends IService<Product> {
/** /**
* 从缓存里面获取商品列表 * 从缓存里面获取商品列表
* *
* @param param 查询参数 * @param shopId 店铺ID
* @param categoryId 商品分类ID
* @return 商品列表数据 * @return 商品列表数据
*/ */
List<ProductDTO> getProductCacheList(ProductDTO param); List<ProductDTO> getProductCacheList(Long shopId, Long categoryId);
/** /**
* 清除某个商品分类的缓存 * 清除某个商品分类的缓存

View File

@@ -27,10 +27,8 @@ import com.czg.service.product.mapper.*;
import com.czg.utils.PageUtil; import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.update.UpdateChain; import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -46,7 +44,6 @@ import java.time.LocalDate;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.TextStyle; import java.time.format.TextStyle;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import static com.czg.constant.CacheConstant.ADMIN_CLIENT_PRODUCT_LIST; import static com.czg.constant.CacheConstant.ADMIN_CLIENT_PRODUCT_LIST;
import static com.czg.product.entity.table.ProductTableDef.PRODUCT; import static com.czg.product.entity.table.ProductTableDef.PRODUCT;
@@ -172,9 +169,20 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
@Override @Override
public List<ProductDTO> getProductList(ProductDTO param) { public List<ProductDTO> getProductList(ProductDTO param) {
QueryWrapper queryWrapper = buildFullQueryWrapper(param); QueryWrapper queryWrapper = buildFullQueryWrapper(param);
//queryWrapper.eq(Product::getIsSale, SystemConstants.OneZero.ONE);
List<ProductDTO> records = super.listAs(queryWrapper, ProductDTO.class); List<ProductDTO> records = super.listAs(queryWrapper, ProductDTO.class);
buildProductExtInfo(records); records.forEach(record -> {
record.setProGroupVo(JSONArray.parseArray(record.getGroupSnap().toString(), ProductGroupVo.class));
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query().eq(ProdSku::getProductId, record.getId()).eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
if (CollUtil.isNotEmpty(skuList)) {
Optional<BigDecimal> lowPriceIsPresent = skuList.stream().map(obj -> NumberUtil.nullToZero(obj.getSalePrice())).min(BigDecimal::compareTo);
lowPriceIsPresent.ifPresent(record::setLowPrice);
Optional<BigDecimal> lowMemberPriceIsPresent = skuList.stream().map(obj -> NumberUtil.nullToZero(obj.getMemberPrice())).min(BigDecimal::compareTo);
lowMemberPriceIsPresent.ifPresent(record::setLowMemberPrice);
}
record.setSkuList(skuList);
record.setProdConsRelations(prodConsRelationMapper.selectListByQuery(query().eq(ProdConsRelation::getProductId, record.getId()).eq(ProdConsRelation::getShopId, record.getShopId())));
});
return records; return records;
} }
@@ -326,27 +334,14 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
@Override @Override
public List<ProductDTO> getProductCacheList(ProductDTO param) { public List<ProductDTO> getProductCacheList(Long shopId, Long categoryId) {
Long shopId = param.getShopId(); String key = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::" + categoryId;
initProductCache(shopId);
String prefix = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::";
List<ProductDTO> list; List<ProductDTO> list;
if (param.getCategoryId() == null) { if (!redisService.hasKey(key)) {
list = new ArrayList<>(); list = initProductCacheByCategoryId(shopId, categoryId);
Set<String> keys = redisService.rightLikeKey(prefix);
for (String key : keys) {
List<ProductDTO> prodList = redisService.getJsonToBeanList(key, ProductDTO.class);
if(CollUtil.isNotEmpty(prodList)) {
list.addAll(prodList);
}
}
} else { } else {
String key = prefix + param.getCategoryId();
list = redisService.getJsonToBeanList(key, ProductDTO.class); list = redisService.getJsonToBeanList(key, ProductDTO.class);
} }
if (StrUtil.isNotEmpty(param.getName())) {
list = list.stream().filter(obj -> StrUtil.contains(obj.getName(), param.getName())).toList();
}
// 重新进行排序 // 重新进行排序
list = list.stream() list = list.stream()
.sorted(Comparator.comparingInt(ProductDTO::getIsSoldStock)) .sorted(Comparator.comparingInt(ProductDTO::getIsSoldStock))
@@ -360,28 +355,14 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
/** /**
* 初始化商品缓存数据 * 初始化商品缓存数据
*/ */
private void initProductCache(Long shopId) { private List<ProductDTO> initProductCacheByCategoryId(Long shopId, Long categoryId) {
ProductDTO param = new ProductDTO(); ProductDTO param = new ProductDTO();
param.setShopId(shopId); param.setShopId(shopId);
param.setCategoryId(categoryId);
List<ProductDTO> productList = getProductList(param); List<ProductDTO> productList = getProductList(param);
Map<Long, List<ProductDTO>> categoryMap = productList.stream().filter(item -> item.getCategoryId() != null).collect(Collectors.groupingBy(ProductDTO::getCategoryId)); String key = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::" + categoryId;
ShopProdCategoryDTO dto = new ShopProdCategoryDTO(); redisService.setJsonStr(key, productList);
dto.setShopId(shopId); return productList;
List<ShopProdCategoryDTO> categoryList = shopProdCategoryService.getShopProdCategoryList(dto);
String prefix = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::";
for (ShopProdCategoryDTO category : categoryList) {
String key = prefix + category.getId();
boolean b = redisService.hasKey(key);
if (!b) {
List<ProductDTO> list = categoryMap.get(category.getId());
if (CollUtil.isNotEmpty(list)) {
redisService.setJsonStr(key, list);
} else {
List<ProductDTO> empty = new ArrayList<>();
redisService.setJsonStr(key, empty);
}
}
}
} }
/** /**
@@ -396,23 +377,6 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
} }
/**
* 系统启动会一次性加载商品缓存数据,防止首次访问时加载缓慢的问题
*/
@PostConstruct
public void initProductListCache() {
log.info("系统启动后初始化商品列表缓存,开始...");
List<Long> shopIdList = DbChain.table("tb_shop_info").select("id").listAs(Long.class);
for (Long shopId : shopIdList) {
log.info("商品列表缓存>>当前店铺:{}", shopId);
ProductDTO dto = new ProductDTO();
dto.setShopId(shopId);
getProductCacheList(dto);
log.info("商品列表缓存>>当前店铺:{},初始化结束", shopId);
}
log.info("系统启动后初始化商品列表缓存,结束。");
}
/** /**
* 计算是否在可售时间内 * 计算是否在可售时间内
* *
@@ -625,7 +589,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
.eq(Product::getId, prodSku.getProductId()) .eq(Product::getId, prodSku.getProductId())
.eq(Product::getShopId, shopId) .eq(Product::getShopId, shopId)
.update(); .update();
}else if(normalCount > 0 && product.getIsSale() == SystemConstants.OneZero.ZERO) { } else if (normalCount > 0 && product.getIsSale() == SystemConstants.OneZero.ZERO) {
UpdateChain.of(Product.class) UpdateChain.of(Product.class)
.set(Product::getIsSale, SystemConstants.OneZero.ONE) .set(Product::getIsSale, SystemConstants.OneZero.ONE)
.eq(Product::getId, prodSku.getProductId()) .eq(Product::getId, prodSku.getProductId())
@@ -634,7 +598,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
sensitiveOperation = sensitiveOperation + "商品:" + product.getName() + " 规格:" + prodSku.getSpecInfo(); sensitiveOperation = sensitiveOperation + "商品:" + product.getName() + " 规格:" + prodSku.getSpecInfo();
} else if (ProductIsSaleTypeEnum.PRODUCT.value().equals(type)) { } else if (ProductIsSaleTypeEnum.PRODUCT.value().equals(type)) {
if("sale".equals(param.getOptType())){ if ("sale".equals(param.getOptType())) {
UpdateChain.of(Product.class) UpdateChain.of(Product.class)
.set(Product::getIsSale, isSale) .set(Product::getIsSale, isSale)
.eq(Product::getId, id) .eq(Product::getId, id)