diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DictDataController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DictDataController.java index c580d638..a41dd284 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DictDataController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DictDataController.java @@ -9,6 +9,7 @@ import cc.hiver.core.common.utils.PageUtil; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.vo.PageVo; import cc.hiver.core.common.vo.Result; +import cn.hutool.json.JSONUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -16,9 +17,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.List; /** @@ -46,10 +49,20 @@ public class DictDataController { @ApiOperation(value = "多条件分页获取用户列表") public Result> getByCondition(DictData dictData, PageVo pageVo) { + List values = redisTemplate.hValues("DICTDATA_CACHE:" + dictData.getDictId()); + if (values != null && !values.isEmpty()) { + List allDatas = new ArrayList<>(); + for (Object v : values) { + DictData dto = JSONUtil.toBean(v.toString(), DictData.class); + allDatas.add(dto); + } + Page pageResult = new PageImpl<>(allDatas, PageUtil.initPage(pageVo), allDatas.size()); + return new ResultUtil>().setData(pageResult); + } Page page = dictDataService.findByCondition(dictData, PageUtil.initPage(pageVo)); return new ResultUtil>().setData(page); - } + } @RequestMapping(value = "/getByType/{type}", method = RequestMethod.GET) @ApiOperation(value = "通过类型获取") @Cacheable(key = "#type") @@ -71,6 +84,7 @@ public class DictDataController { redisTemplate.delete("dictData::" + dict.getType()); } dictDataService.save(dictData); + dictDataService.refreshShopCache(dictData.getDictId(),dictData.getId()); return ResultUtil.success("添加成功"); } @@ -82,6 +96,7 @@ public class DictDataController { // 删除缓存 Dict dict = dictService.get(dictData.getDictId()); redisTemplate.delete("dictData::" + dict.getType()); + dictDataService.refreshShopCache(dictData.getDictId(),dictData.getId()); } return ResultUtil.success("编辑成功"); } @@ -95,6 +110,8 @@ public class DictDataController { dictDataService.delete(id); // 删除缓存 redisTemplate.delete("dictData::" + dict.getType()); + dictDataService.removeShopCache(dictData.getDictId(),id); + } return ResultUtil.success("批量通过id删除数据成功"); } diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java index 346da641..eddb2bc8 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java @@ -45,4 +45,8 @@ public interface DictDataService extends HiverBaseService { * @return */ DictData findByDictIdAndValue(String dictId, String value); + + void removeShopCache(String dictId,String diacDataId); + + void refreshShopCache(String dictId,String diacDataId); } \ No newline at end of file diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/serviceimpl/DictDataServiceImpl.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/serviceimpl/DictDataServiceImpl.java index 86bac65e..5f3d74a0 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/serviceimpl/DictDataServiceImpl.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/serviceimpl/DictDataServiceImpl.java @@ -4,7 +4,10 @@ import cc.hiver.base.dao.DictDataDao; import cc.hiver.base.entity.DictData; import cc.hiver.base.service.DictDataService; import cc.hiver.core.common.constant.CommonConstant; +import cc.hiver.core.common.redis.RedisTemplateHelper; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -30,6 +33,9 @@ public class DictDataServiceImpl implements DictDataService { @Autowired private DictDataDao dictDataDao; + @Autowired + private RedisTemplateHelper redisTemplateHelper; + @Override public DictDataDao getRepository() { return dictDataDao; @@ -84,4 +90,25 @@ public class DictDataServiceImpl implements DictDataService { public DictData findByDictIdAndValue(String dictId, String value) { return dictDataDao.findByDictIdAndValue(dictId, value); } + @Override + public void removeShopCache(String dictId,String diacDataId) { + if (CharSequenceUtil.isBlank(dictId)) { + return; + } + String redisKey = "DICTDATA_CACHE:" + dictId; + redisTemplateHelper.hDelete(redisKey, diacDataId); + } + @Override + public void refreshShopCache(String dictId,String diacDataId) { + if (CharSequenceUtil.isBlank(dictId)) { + return; + } + DictData dictData = dictDataDao.getById(diacDataId); + if (dictData == null) { + removeShopCache(dictId,diacDataId); + return; + } + String redisKey = "DICTDATA_CACHE:" + dictId; + redisTemplateHelper.hPut(redisKey, diacDataId, JSONUtil.toJsonStr(dictData)); + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductCategoryController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductCategoryController.java index 3612df97..297d98c9 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductCategoryController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductCategoryController.java @@ -1,5 +1,6 @@ package cc.hiver.mall.controller; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.common.vo.Result; @@ -38,6 +39,9 @@ public class ProductCategoryController { @Autowired private SecurityUtil securityUtil; + + @Autowired + private RedisTemplateHelper redisTemplate; @RequestMapping(value = "/save", method = RequestMethod.POST) @ApiOperation(value = "新增货品类别") @@ -47,6 +51,7 @@ public class ProductCategoryController { productCategory.setShopId(shopId); boolean result = productCategoryService.save(productCategory); if (result) { + productCategoryService.refreshProductCategoryCache(shopId, productCategory.getId()); return ResultUtil.success("添加成功"); } else { return ResultUtil.error("添加失败"); @@ -65,6 +70,7 @@ public class ProductCategoryController { } boolean result = productCategoryService.updateById(productCategory); if (result) { + productCategoryService.refreshProductCategoryCache(productCategory.getShopId(), productCategory.getId()); return ResultUtil.success("修改成功"); } else { return ResultUtil.error("修改失败"); @@ -74,10 +80,15 @@ public class ProductCategoryController { @RequestMapping(value = "/delById", method = RequestMethod.POST) @ApiOperation(value = "根据id删除货品类别") public Result delete(ProductCategory productCategory) { - boolean result = productCategoryService.removeById(productCategory); + ProductCategory old = productCategoryService.getById(productCategory.getId()); + if(old == null) { + return ResultUtil.error("分类不存在"); + } + boolean result = productCategoryService.removeById(productCategory.getId()); // 将该分类下的商品id删除掉 productService.deleteProductByCategoryId(productCategory.getId()); if (result) { + productCategoryService.removeProductCategoryCache(old.getShopId(), old.getId()); return ResultUtil.success("删除成功"); } else { return ResultUtil.error("删除失败"); @@ -94,7 +105,34 @@ public class ProductCategoryController { } // final String shopId = "1759768115375378438"; // queryWrapper.eq("shop_id", shopId); + + List values = redisTemplate.hValues("PRODUCT_CATEGORY_CACHE:" + shopId); + if (values != null && !values.isEmpty()) { + List list = new ArrayList<>(); + for (Object v : values) { + ProductCategoryVo2 dto = cn.hutool.json.JSONUtil.toBean(v.toString(), ProductCategoryVo2.class); + list.add(dto); + } + // Sort by sort + list.sort((o1, o2) -> { + if(o1.getSort() == null && o2.getSort() == null) return 0; + if(o1.getSort() == null) return -1; + if(o2.getSort() == null) return 1; + try { + return Integer.valueOf(o1.getSort()).compareTo(Integer.valueOf(o2.getSort())); + } catch(NumberFormatException e) { + return o1.getSort().compareTo(o2.getSort()); + } + }); + return new ResultUtil>().setData(list); + } + List list = productCategoryService.getCategoryListByShopId(shopId); + if (list != null && list.size() > 0) { + for(ProductCategoryVo2 sa : list){ + productCategoryService.refreshProductCategoryCache(shopId, sa.getId()); + } + } return new ResultUtil>().setData(list); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductController.java index 19007f10..4493c9f1 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductController.java @@ -3,26 +3,30 @@ package cc.hiver.mall.controller; import cc.hiver.core.common.annotation.RateLimiter; import cc.hiver.core.common.constant.CommonConstant; import cc.hiver.core.common.constant.ProductConstant; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.BeanUtils; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.common.vo.Result; import cc.hiver.mall.entity.Product; import cc.hiver.mall.entity.ProductGroupBuyPrice; +import cc.hiver.mall.entity.Shop; import cc.hiver.mall.pojo.query.ProductPageQuery; import cc.hiver.mall.pojo.vo.ProductLastBuyVo; import cc.hiver.mall.pojo.vo.ProductPageVO; import cc.hiver.mall.pojo.vo.ProductVo; import cc.hiver.mall.productpicture.entity.ProductPicture; import cc.hiver.mall.productpicture.service.ProductPictureService; +import cc.hiver.mall.service.ShopService; import cc.hiver.mall.service.mybatis.ProductCategoryService; import cc.hiver.mall.service.mybatis.ProductGroupBuyPriceService; import cc.hiver.mall.service.mybatis.ProductService; -import cc.hiver.mall.service.ShopService; -import cc.hiver.mall.entity.Shop; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -31,7 +35,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Slf4j @RestController @@ -57,6 +63,9 @@ public class ProductController { @Autowired private ShopService shopService; + @Autowired + private RedisTemplateHelper redisTemplateHelper; + private void triggerCacheRefreshByProductId(String productId) { Product product = productService.getById(productId); if (product != null && StringUtils.isNotEmpty(product.getShopId())) { @@ -422,7 +431,7 @@ public class ProductController { // shopId从缓存中设置 /*final String shopId = securityUtil.getShopId(); productPageQuery.setShopId(shopId);*/ - if(productPageQuery.getCategoryId() != null){ + if(CharSequenceUtil.isNotBlank(productPageQuery.getCategoryId())){ if(productPageQuery.getCategoryId().equals(ProductConstant.SERCHCATEGORY[0])){ productPageQuery.setIsMust(ProductConstant.DEL_FLAG[1]); productPageQuery.setCategoryId(null); @@ -431,6 +440,58 @@ public class ProductController { productPageQuery.setCategoryId(null); } } + + // --- 核心优化:尝试从缓存中读取商品列表 --- + String shopIdStr = productPageQuery.getShopId(); + if (CharSequenceUtil.isBlank(shopIdStr) && productPageQuery.getShopIdList() != null && productPageQuery.getShopIdList().size() == 1) { + shopIdStr = productPageQuery.getShopIdList().get(0); + } + + if (CharSequenceUtil.isNotBlank(shopIdStr) && (productPageQuery.getIdList() == null || productPageQuery.getIdList().isEmpty())) { + String productsJson = redisTemplateHelper.get("SHOP_PRODUCTS:" + shopIdStr); + if (CharSequenceUtil.isNotBlank(productsJson)) { + List allProducts = JSONUtil.toList(productsJson, ProductPageVO.class); + if (allProducts != null) { + // 内存过滤 + List filteredProducts = allProducts.stream().filter(p -> { + if (CharSequenceUtil.isNotBlank(productPageQuery.getCategoryId()) && !productPageQuery.getCategoryId().equals(p.getCategoryId())) return false; + if (productPageQuery.getIsPush() != null && !productPageQuery.getIsPush().equals(p.getIsPush())) return false; + if (productPageQuery.getIsMust() != null && !productPageQuery.getIsMust().equals(p.getIsMust())) return false; + if (productPageQuery.getDelFlag() != null && !productPageQuery.getDelFlag().equals(p.getDelFlag())) return false; + if (CharSequenceUtil.isNotBlank(productPageQuery.getKeywords())) { + if (p.getProductName() == null || !p.getProductName().contains(productPageQuery.getKeywords())) { + return false; + } + } + if (CharSequenceUtil.isNotBlank(productPageQuery.getProductName())) { + if (p.getProductName() == null || !p.getProductName().contains(productPageQuery.getProductName())) { + return false; + } + } + return true; + }).collect(Collectors.toList()); + + // 内存分页 + int pageNum = productPageQuery.getPageNum() > 0 ? productPageQuery.getPageNum() : 1; + int pageSize = productPageQuery.getPageSize() > 0 ? productPageQuery.getPageSize() : 10; + int fromIndex = (pageNum - 1) * pageSize; + int toIndex = Math.min(fromIndex + pageSize, filteredProducts.size()); + + List pageList; + if (fromIndex >= filteredProducts.size()) { + pageList = new ArrayList<>(); + } else { + pageList = filteredProducts.subList(fromIndex, toIndex); + } + + Page pageResult = new Page<>(pageNum, pageSize, filteredProducts.size()); + pageResult.setRecords(pageList); + return new ResultUtil>().setData(pageResult); + } + } + } + // --- 核心优化结束 --- + final IPage result = productService.getShareList(productPageQuery); return new ResultUtil>().setData(result); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java index 2adcf11a..b8b3d7ba 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java @@ -3,19 +3,14 @@ package cc.hiver.mall.controller; import cc.hiver.core.common.constant.CommonConstant; import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.CommonUtil; -import cc.hiver.core.common.utils.HibernateProxyTypeAdapter; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.common.vo.Result; import cc.hiver.core.dao.mapper.DeleteMapper; -import cc.hiver.core.entity.User; import cc.hiver.mall.entity.ShopArea; import cc.hiver.mall.service.ShopAreaService; import cc.hiver.mall.service.ShopService; import cn.hutool.core.util.StrUtil; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -26,7 +21,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; -import java.util.concurrent.TimeUnit; /** * 圈层管理接口 @@ -61,20 +55,41 @@ public class ShopAreaController { @ApiParam("是否开始数据权限过滤") @RequestParam(required = false, defaultValue = "true") Boolean openDataFilter) { List list; - User u = securityUtil.getCurrUserSimple(); - String key = "ShopArea::" + parentId + ":" + u.getId() + "_" + openDataFilter; - String v = redisTemplate.get(key); - if (StrUtil.isNotBlank(v)) { - Gson oldShopArea = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create(); - list = oldShopArea.fromJson(v, new TypeToken>() { - }.getType()); + List values = redisTemplate.hValues("SHOPAREA_CACHE:" + parentId); + if (values != null && !values.isEmpty()) { + list = new java.util.ArrayList<>(); + for (Object v : values) { + ShopArea dto = cn.hutool.json.JSONUtil.toBean(v.toString(), ShopArea.class); + list.add(dto); + } + // Sort by sortOrder + list.sort((o1, o2) -> { + if(o1.getSortOrder() == null && o2.getSortOrder() == null) return 0; + if(o1.getSortOrder() == null) return -1; + if(o2.getSortOrder() == null) return 1; + return o1.getSortOrder().compareTo(o2.getSortOrder()); + }); + // data permission filter + List depIds = securityUtil.getDeparmentIds(); + if (openDataFilter && depIds != null && depIds.size() > 0) { + List filteredDatas = new java.util.ArrayList<>(); + for (ShopArea allData : list) { + if(depIds.contains(allData.getId())){ + filteredDatas.add(allData); + } + } + list = filteredDatas; + } + //setInfo(list); return new ResultUtil>().setData(list); } list = shopAreaService.findByParentIdOrderBySortOrder(parentId, openDataFilter); setInfo(list); - Gson gson = new GsonBuilder().registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY) - .setDateFormat("yyyy-MM-dd hh:mm:ss").create(); - redisTemplate.set(key, gson.toJson(list), 15L, TimeUnit.DAYS); + if (list != null && list.size() > 0) { + for(ShopArea sa : list){ + shopAreaService.refreshShopAreaCache(sa.getParentId(), sa.getId()); + } + } return new ResultUtil>().setData(list); } @@ -90,7 +105,10 @@ public class ShopAreaController { shopAreaService.update(parent); } } - // 更新缓存 + + shopAreaService.refreshShopAreaCache(d.getParentId(), d.getId()); + + // 更新旧的树形缓存(如果用到) redisTemplate.deleteByPattern("ShopArea::*"); // 删除数据权限缓存 //redisTemplate.deleteByPattern("userRole::depIds:*"); @@ -119,11 +137,13 @@ public class ShopAreaController { parent.setIsParent(false); shopAreaService.update(parent); } + shopAreaService.removeShopAreaCache(oldParentId, ShopArea.getId()); } shopService.updateShopAreaTitle(ShopArea.getId(),ShopArea.getTitle()); + shopAreaService.refreshShopAreaCache(d.getParentId(), d.getId()); - // 手动删除所有圈层缓存 + // 手动删除所有圈层缓存(旧) redisTemplate.deleteByPattern("ShopArea:*"); return ResultUtil.success("编辑成功"); } @@ -152,7 +172,8 @@ public class ShopAreaController { parent = shopAreaService.findById(dep.getParentId()); } shopAreaService.delete(id); - + + shopAreaService.removeShopAreaCache(dep.getParentId(), id); // 删除流程关联节点 // deleteMapper.deleteActNode(id); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java index e108ec05..a9f3ff5d 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java @@ -18,6 +18,7 @@ package cc.hiver.mall.controller; import cc.hiver.core.common.constant.ShopConstant; import cc.hiver.core.common.constant.ShopUserConstant; import cc.hiver.core.common.constant.UserConstant; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.PageUtil; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.utils.SecurityUtil; @@ -28,27 +29,28 @@ import cc.hiver.core.entity.User; import cc.hiver.core.service.UserService; import cc.hiver.mall.entity.Shop; import cc.hiver.mall.entity.ShopArea; +import cc.hiver.mall.entity.ShopTakeaway; import cc.hiver.mall.entity.ShopUser; import cc.hiver.mall.invitelog.service.InviteLogService; +import cc.hiver.mall.pojo.dto.ShopCacheDTO; import cc.hiver.mall.pojo.dto.ShopRevenue; import cc.hiver.mall.pojo.query.ProductPageQuery; import cc.hiver.mall.pojo.vo.ProductPageVO; import cc.hiver.mall.pojo.vo.QueryShopRevenueVO; import cc.hiver.mall.service.ShopAreaService; import cc.hiver.mall.service.ShopService; +import cc.hiver.mall.service.ShopTakeawayService; import cc.hiver.mall.service.ShopUserService; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; -import cn.hutool.json.JSONUtil; -import cc.hiver.core.common.redis.RedisTemplateHelper; -import cc.hiver.mall.pojo.dto.ShopCacheDTO; -import org.springframework.data.domain.PageImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; @@ -87,6 +89,9 @@ public class ShopController { @Autowired private RedisTemplateHelper redisTemplateHelper; + @Autowired + private ShopTakeawayService shopTakeawayService; + @RequestMapping(value = "/getAll", method = RequestMethod.GET) @ApiOperation("获取全部数据") public Result> getAll() { @@ -230,11 +235,43 @@ public class ShopController { ShopCacheDTO dto = JSONUtil.toBean(v.toString(), ShopCacheDTO.class); Shop s = dto.getShop(); s.setProducts(dto.getProducts()); + s.setShopTakeaway(dto.getShopTakeaway()); if (CharSequenceUtil.isNotBlank(shop.getShopArea())) { if (!shop.getShopArea().equals(s.getShopArea())) { continue; } } + if(s.getStatus() != 1){ + continue; + } + if (CharSequenceUtil.isNotBlank(shop.getShopType())) { + if (!shop.getShopType().equals(s.getShopType())) { + continue; + } + } + if (CharSequenceUtil.isNotBlank(shop.getKeyWord())) { + String kw = shop.getKeyWord(); + boolean match = false; + if (s.getShopName() != null && s.getShopName().contains(kw)) { + match = true; + } else { + String productsJson = redisTemplateHelper.get("SHOP_PRODUCTS:" + s.getId()); + if (CharSequenceUtil.isNotBlank(productsJson)) { + List products = JSONUtil.toList(productsJson, ProductPageVO.class); + if (products != null) { + for (ProductPageVO p : products) { + if (p.getDelFlag() == 1 && p.getProductName() != null && p.getProductName().contains(kw)) { + match = true; + break; + } + } + } + } + } + if (!match) { + continue; + } + } allShops.add(s); } @@ -253,6 +290,10 @@ public class ShopController { BigDecimal score1 = s1.getShopScore() == null ? BigDecimal.ZERO : s1.getShopScore(); BigDecimal score2 = s2.getShopScore() == null ? BigDecimal.ZERO : s2.getShopScore(); compareResult = score1.compareTo(score2); + } else if ("shoprank".equals(sort)) { + Integer shoprank1 = s1.getShoprank() == null ? 0 : s1.getShoprank(); + Integer shoprank2 = s2.getShoprank() == null ? 0 : s2.getShoprank(); + compareResult = shoprank1.compareTo(shoprank2); } if ("desc".equalsIgnoreCase(order)) { return -compareResult; @@ -261,8 +302,8 @@ public class ShopController { }); } - int pageNumber = pageVo.getPageNumber() == null ? 1 : pageVo.getPageNumber(); - int pageSize = pageVo.getPageSize() == null ? 10 : pageVo.getPageSize(); + int pageNumber = pageVo.getPageNumber() > 0 ? pageVo.getPageNumber() : 1; + int pageSize = pageVo.getPageSize() > 0 ? pageVo.getPageSize() : 10; int fromIndex = (pageNumber - 1) * pageSize; int toIndex = Math.min(fromIndex + pageSize, allShops.size()); List pageList; @@ -272,6 +313,40 @@ public class ShopController { pageList = allShops.subList(fromIndex, toIndex); } + // --- 核心优化:获取当前页的商品数据(二层缓存架构的核心拼装) --- + if (!pageList.isEmpty()) { + List productKeys = new ArrayList<>(); + for (Shop s : pageList) { + productKeys.add("SHOP_PRODUCTS:" + s.getId()); + } + List productsJsonList = redisTemplateHelper.multiGet(productKeys); + if (productsJsonList != null && productsJsonList.size() == pageList.size()) { + for (int i = 0; i < pageList.size(); i++) { + String productsJson = productsJsonList.get(i); + if (CharSequenceUtil.isNotBlank(productsJson)) { + List productsReturn = new ArrayList<>(); + List products = JSONUtil.toList(productsJson, ProductPageVO.class); + if (CharSequenceUtil.isNotBlank(shop.getKeyWord())) { + for (ProductPageVO p : products) { + if (p.getDelFlag() == 1 && p.getProductName() != null && p.getProductName().contains(shop.getKeyWord())) { + productsReturn.add(p); + } + } + }else{ + for (ProductPageVO p : products) { + if (p.getDelFlag() == 1 && p.getIsPush() == 1) { + productsReturn.add(p); + } + } + } + pageList.get(i).setProducts(productsReturn); + } else { + pageList.get(i).setProducts(new ArrayList<>()); + } + } + } + } + Page pageResult = new PageImpl<>(pageList, PageUtil.initPage(pageVo), allShops.size()); return new ResultUtil>().setData(pageResult); } @@ -283,27 +358,39 @@ public class ShopController { page.getContent().forEach(e -> { shopIdList.add(e.getId()); }); - //查询推荐商品 - final ProductPageQuery productPageQuery = new ProductPageQuery(); - productPageQuery.setShopIdList(shopIdList); - productPageQuery.setIsPush(ShopUserConstant.SHOP_ADMIN_COST[1]); - IPage productList = shopService.getShareList(productPageQuery); - - page.getContent().forEach(e -> { - final List products = new ArrayList<>(); - if(productList.getRecords() != null && productList.getRecords().size() > 0){ - productList.getRecords().forEach(productPageVO -> { - if (e.getId().equals(productPageVO.getShopId())) { - products.add(productPageVO); - } - }); + if(shopIdList.size() > 0){ + //查询业务信息 + List shopTakeaways = shopTakeawayService.selectListByshopId(shopIdList); + //查询推荐商品 + final ProductPageQuery productPageQuery = new ProductPageQuery(); + productPageQuery.setPageNum(1); + productPageQuery.setPageSize(100); + productPageQuery.setShopIdList(shopIdList); + productPageQuery.setDelFlag(1); + if(CharSequenceUtil.isBlank(shop.getKeyWord())){ + productPageQuery.setIsPush(ShopUserConstant.SHOP_ADMIN_COST[1]); + }else{ + productPageQuery.setProductName(shop.getKeyWord()); } - - e.setProducts(products); - if (CharSequenceUtil.isNotBlank(regionId)) { - shopService.refreshShopCache(e.getId(), regionId); - } - }); + IPage productList = shopService.getShareList(productPageQuery); + + page.getContent().forEach(e -> { + final List products = new ArrayList<>(); + if(productList.getRecords().size() > 0){ + productList.getRecords().forEach(productPageVO -> { + if (e.getId().equals(productPageVO.getShopId())) { + products.add(productPageVO); + } + }); + } + e.setProducts(products); + for(ShopTakeaway shopTakeawa : shopTakeaways) { + if (e.getId().equals(shopTakeawa.getShopId())) { + e.setShopTakeaway(shopTakeawa); + } + } + }); + } return new ResultUtil>().setData(page); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Shop.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Shop.java index f7ac5aeb..ccdd1ee7 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Shop.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Shop.java @@ -173,4 +173,9 @@ public class Shop extends HiverBaseEntity { @TableField(exist = false) @ApiModelProperty(value = "店铺抽佣等设置") private ShopTakeaway shopTakeaway; + + @Transient + @TableField(exist = false) + @ApiModelProperty(value = "模糊搜索条件") + private String keyWord; } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java index ada3b3df..23b5bab2 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java @@ -47,4 +47,8 @@ public interface ShopAreaService extends HiverBaseService { * @date 2023/10/12 */ ShopArea findTopShopAreaById(String id); + + void removeShopAreaCache(String parentId,String shopAreaId); + + void refreshShopAreaCache(String parentId,String shopAreaId); } \ No newline at end of file diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java index b52d6b6b..bf7ad2b9 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java @@ -63,4 +63,8 @@ public interface ProductCategoryService extends IService { List getCategoryListByShopId(String shopId); + + void removeProductCategoryCache(String shopId, String categoryId); + + void refreshProductCategoryCache(String shopId, String categoryId); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopAreaServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopAreaServiceImpl.java index 13747a77..e7594376 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopAreaServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopAreaServiceImpl.java @@ -1,9 +1,12 @@ package cc.hiver.mall.serviceimpl; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.mall.dao.ShopAreaDao; import cc.hiver.mall.entity.ShopArea; import cc.hiver.mall.service.ShopAreaService; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -26,6 +29,9 @@ public class ShopAreaServiceImpl implements ShopAreaService { @Autowired private SecurityUtil securityUtil; + @Autowired + private RedisTemplateHelper redisTemplateHelper; + @Override public ShopAreaDao getRepository() { return shopAreaDao; @@ -75,4 +81,29 @@ public class ShopAreaServiceImpl implements ShopAreaService { } } } + + @Override + public void removeShopAreaCache(String parentId,String shopAreaId) { + if (CharSequenceUtil.isBlank(parentId)) { + return; + } + String redisKey = "SHOPAREA_CACHE:" + parentId; + redisTemplateHelper.hDelete(redisKey, shopAreaId); + } + + @Override + public void refreshShopAreaCache(String parentId,String shopAreaId) { + if (CharSequenceUtil.isBlank(parentId)) { + return; + } + ShopArea shopArea = shopAreaDao.getById(shopAreaId); + ShopArea shopAreaParent = shopAreaDao.getById(parentId); + shopArea.setParentTitle(shopAreaParent.getTitle()); + if (shopArea == null) { + removeShopAreaCache(parentId, shopAreaId); + return; + } + String redisKey = "SHOPAREA_CACHE:" + parentId; + redisTemplateHelper.hPut(redisKey, shopAreaId, JSONUtil.toJsonStr(shopArea)); + } } \ No newline at end of file diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java index d0997789..96b4ede6 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java @@ -16,16 +16,20 @@ limitations under the License. package cc.hiver.mall.serviceimpl; import cc.hiver.core.base.HiverBaseDao; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.common.utils.StringUtils; import cc.hiver.mall.dao.ShopDao; import cc.hiver.mall.dao.mapper.ProductMapper; import cc.hiver.mall.dao.mapper.SaleMapper; import cc.hiver.mall.dao.mapper.ShopMapper; +import cc.hiver.mall.dao.mapper.ShopTakeawayMapper; import cc.hiver.mall.deductlog.service.DeductLogService; import cc.hiver.mall.entity.ProductGroupBuyPrice; import cc.hiver.mall.entity.Shop; +import cc.hiver.mall.entity.ShopTakeaway; import cc.hiver.mall.invitelog.service.InviteLogService; +import cc.hiver.mall.pojo.dto.ShopCacheDTO; import cc.hiver.mall.pojo.dto.ShopRevenue; import cc.hiver.mall.pojo.query.ProductPageQuery; import cc.hiver.mall.pojo.vo.ProductPageVO; @@ -37,10 +41,6 @@ import cc.hiver.mall.service.mybatis.ProductGroupBuyPriceService; import cc.hiver.mall.utils.DateUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONUtil; -import cc.hiver.core.common.redis.RedisTemplateHelper; -import cc.hiver.mall.dao.mapper.ShopTakeawayMapper; -import cc.hiver.mall.entity.ShopTakeaway; -import cc.hiver.mall.pojo.dto.ShopCacheDTO; import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -104,7 +104,7 @@ public class ShopServiceImpl implements ShopService { } @Override - public Page findByCondition(Shop Shop, Pageable pageable) { + public Page findByCondition(Shop shop, Pageable pageable) { return shopDao.findAll(new Specification() { @Nullable @Override @@ -115,14 +115,38 @@ public class ShopServiceImpl implements ShopService { final List list = new ArrayList<>(); - if (CharSequenceUtil.isNotBlank(Shop.getShopName())) { - list.add(cb.like(ShopNameField, '%' + Shop.getShopName() + '%')); + if (CharSequenceUtil.isNotBlank(shop.getKeyWord()) && !"zhuyesearch".equals(shop.getKeyWord())) { + String keyword = shop.getKeyWord(); + com.baomidou.mybatisplus.core.conditions.query.QueryWrapper qw = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>(); + qw.select("shop_id").like("product_name", keyword); + List productList = productMapper.selectList(qw); + + List shopIds = new ArrayList<>(); + if (productList != null && !productList.isEmpty()) { + for (cc.hiver.mall.entity.Product p : productList) { + if (p.getShopId() != null && !shopIds.contains(p.getShopId())) { + shopIds.add(p.getShopId()); + } + } + } + + if (!shopIds.isEmpty()) { + Path idField = root.get("id"); + Predicate namePredicate = cb.like(ShopNameField, '%' + keyword + '%'); + Predicate idPredicate = idField.in(shopIds); + list.add(cb.or(namePredicate, idPredicate)); + } else { + list.add(cb.like(ShopNameField, '%' + keyword + '%')); + } + } + if (CharSequenceUtil.isNotBlank(shop.getShopName())) { + list.add(cb.like(ShopNameField, '%' + shop.getShopName() + '%')); } - if (CharSequenceUtil.isNotBlank(Shop.getRegionId())) { - list.add(cb.equal(regionField, Shop.getRegionId())); + if (CharSequenceUtil.isNotBlank(shop.getRegionId())) { + list.add(cb.equal(regionField, shop.getRegionId())); } - if (CharSequenceUtil.isNotBlank(Shop.getShopArea())) { - list.add(cb.equal(shopAreaField, Shop.getShopArea())); + if (CharSequenceUtil.isNotBlank(shop.getShopArea())) { + list.add(cb.equal(shopAreaField, shop.getShopArea())); } @@ -256,16 +280,25 @@ public class ShopServiceImpl implements ShopService { ProductPageQuery query = new ProductPageQuery(); query.setPageNum(1); - query.setPageSize(200); + query.setPageSize(1000); List shopIdList = new ArrayList<>(); shopIdList.add(shopId); query.setShopIdList(shopIdList); - query.setIsPush(1); // 推荐 + //query.setIsPush(1); // 推荐 IPage productList = getShareList(query); - cacheDTO.setProducts(productList.getRecords()); + // 不再将商品列表放入第一层缓存,以防产生大Key + // cacheDTO.setProducts(productList.getRecords()); String redisKey = "SHOP_CACHE:" + regionId; redisTemplateHelper.hPut(redisKey, shopId, JSONUtil.toJsonStr(cacheDTO)); + + // 第二层缓存:单独存储商品列表 + String productsRedisKey = "SHOP_PRODUCTS:" + shopId; + if (productList != null && productList.getRecords() != null && !productList.getRecords().isEmpty()) { + redisTemplateHelper.set(productsRedisKey, JSONUtil.toJsonStr(productList.getRecords())); + } else { + redisTemplateHelper.delete(productsRedisKey); + } } @Override @@ -275,6 +308,10 @@ public class ShopServiceImpl implements ShopService { } String redisKey = "SHOP_CACHE:" + regionId; redisTemplateHelper.hDelete(redisKey, shopId); + + // 同步删除第二层商品缓存 + String productsRedisKey = "SHOP_PRODUCTS:" + shopId; + redisTemplateHelper.delete(productsRedisKey); } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java index 798b269e..ace7d144 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java @@ -1,5 +1,6 @@ package cc.hiver.mall.serviceimpl.mybatis; +import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.SecurityUtil; import cc.hiver.core.entity.User; import cc.hiver.mall.dao.mapper.ProductCategoryMapper; @@ -12,6 +13,8 @@ import cc.hiver.mall.service.ShopService; import cc.hiver.mall.service.mybatis.ProductAttributeService; import cc.hiver.mall.service.mybatis.ProductAttributeValueService; import cc.hiver.mall.service.mybatis.ProductCategoryService; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -45,6 +48,9 @@ public class ProductCategoryServiceImpl extends ServiceImpl getCategoryListByShopId(String shopId){ return productCategoryMapper.getCategoryListByShopId(shopId); } + + @Override + public void removeProductCategoryCache(String shopId, String categoryId) { + if (CharSequenceUtil.isBlank(shopId)) { + return; + } + String redisKey = "PRODUCT_CATEGORY_CACHE:" + shopId; + redisTemplateHelper.hDelete(redisKey, categoryId); + } + + @Override + public void refreshProductCategoryCache(String shopId, String categoryId) { + if (CharSequenceUtil.isBlank(shopId)) { + return; + } + // 由于可能需要补充查询一些商品数量等(Vo2结构),我们借用已经写好的列表查询 + List list = getCategoryListByShopId(shopId); + ProductCategoryVo2 targetVo = null; + if (list != null) { + for (ProductCategoryVo2 vo : list) { + if (categoryId.equals(vo.getId())) { + targetVo = vo; + break; + } + } + } + + if (targetVo == null) { + removeProductCategoryCache(shopId, categoryId); + return; + } + String redisKey = "PRODUCT_CATEGORY_CACHE:" + shopId; + redisTemplateHelper.hPut(redisKey, categoryId, JSONUtil.toJsonStr(targetVo)); + } } diff --git a/hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml b/hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml index 971d37cf..325b8ed5 100644 --- a/hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml +++ b/hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml @@ -789,7 +789,7 @@ ) - ORDER BY t.order_filed asc, + ORDER BY t.order_filed desc,