Browse Source

对接拼团数据

master
wangfukang 1 month ago
parent
commit
52f4bbe8fa
  1. 19
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/DictDataController.java
  2. 4
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java
  3. 27
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/serviceimpl/DictDataServiceImpl.java
  4. 40
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductCategoryController.java
  5. 67
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ProductController.java
  6. 59
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java
  7. 139
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java
  8. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Shop.java
  9. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java
  10. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java
  11. 31
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopAreaServiceImpl.java
  12. 65
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java
  13. 40
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/ProductCategoryServiceImpl.java
  14. 2
      hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml

19
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<Page<DictData>> getByCondition(DictData dictData,
PageVo pageVo) {
List<Object> values = redisTemplate.hValues("DICTDATA_CACHE:" + dictData.getDictId());
if (values != null && !values.isEmpty()) {
List<DictData> allDatas = new ArrayList<>();
for (Object v : values) {
DictData dto = JSONUtil.toBean(v.toString(), DictData.class);
allDatas.add(dto);
}
Page<DictData> pageResult = new PageImpl<>(allDatas, PageUtil.initPage(pageVo), allDatas.size());
return new ResultUtil<Page<DictData>>().setData(pageResult);
}
Page<DictData> page = dictDataService.findByCondition(dictData, PageUtil.initPage(pageVo));
return new ResultUtil<Page<DictData>>().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删除数据成功");
}

4
hiver-modules/hiver-base/src/main/java/cc/hiver/base/service/DictDataService.java

@ -45,4 +45,8 @@ public interface DictDataService extends HiverBaseService<DictData, String> {
* @return
*/
DictData findByDictIdAndValue(String dictId, String value);
void removeShopCache(String dictId,String diacDataId);
void refreshShopCache(String dictId,String diacDataId);
}

27
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));
}
}

40
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<Object> values = redisTemplate.hValues("PRODUCT_CATEGORY_CACHE:" + shopId);
if (values != null && !values.isEmpty()) {
List<ProductCategoryVo2> 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<List<ProductCategoryVo2>>().setData(list);
}
List<ProductCategoryVo2> list = productCategoryService.getCategoryListByShopId(shopId);
if (list != null && list.size() > 0) {
for(ProductCategoryVo2 sa : list){
productCategoryService.refreshProductCategoryCache(shopId, sa.getId());
}
}
return new ResultUtil<List<ProductCategoryVo2>>().setData(list);
}

67
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<ProductPageVO> allProducts = JSONUtil.toList(productsJson, ProductPageVO.class);
if (allProducts != null) {
// 内存过滤
List<ProductPageVO> 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<ProductPageVO> pageList;
if (fromIndex >= filteredProducts.size()) {
pageList = new ArrayList<>();
} else {
pageList = filteredProducts.subList(fromIndex, toIndex);
}
Page<ProductPageVO> pageResult = new Page<>(pageNum, pageSize, filteredProducts.size());
pageResult.setRecords(pageList);
return new ResultUtil<IPage<ProductPageVO>>().setData(pageResult);
}
}
}
// --- 核心优化结束 ---
final IPage<ProductPageVO> result = productService.getShareList(productPageQuery);
return new ResultUtil<IPage<ProductPageVO>>().setData(result);
}

59
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<ShopArea> 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<List<ShopArea>>() {
}.getType());
List<Object> 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<String> depIds = securityUtil.getDeparmentIds();
if (openDataFilter && depIds != null && depIds.size() > 0) {
List<ShopArea> filteredDatas = new java.util.ArrayList<>();
for (ShopArea allData : list) {
if(depIds.contains(allData.getId())){
filteredDatas.add(allData);
}
}
list = filteredDatas;
}
//setInfo(list);
return new ResultUtil<List<ShopArea>>().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<List<ShopArea>>().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);

139
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<List<Shop>> 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<ProductPageVO> 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<Shop> pageList;
@ -272,6 +313,40 @@ public class ShopController {
pageList = allShops.subList(fromIndex, toIndex);
}
// --- 核心优化:获取当前页的商品数据(二层缓存架构的核心拼装) ---
if (!pageList.isEmpty()) {
List<String> productKeys = new ArrayList<>();
for (Shop s : pageList) {
productKeys.add("SHOP_PRODUCTS:" + s.getId());
}
List<String> 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<ProductPageVO> productsReturn = new ArrayList<>();
List<ProductPageVO> 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<Shop> pageResult = new PageImpl<>(pageList, PageUtil.initPage(pageVo), allShops.size());
return new ResultUtil<Page<Shop>>().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<ProductPageVO> productList = shopService.getShareList(productPageQuery);
page.getContent().forEach(e -> {
final List<ProductPageVO> 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<ShopTakeaway> 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<ProductPageVO> productList = shopService.getShareList(productPageQuery);
page.getContent().forEach(e -> {
final List<ProductPageVO> 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<Page<Shop>>().setData(page);
}

5
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;
}

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/ShopAreaService.java

@ -47,4 +47,8 @@ public interface ShopAreaService extends HiverBaseService<ShopArea, String> {
* @date 2023/10/12
*/
ShopArea findTopShopAreaById(String id);
void removeShopAreaCache(String parentId,String shopAreaId);
void refreshShopAreaCache(String parentId,String shopAreaId);
}

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/ProductCategoryService.java

@ -63,4 +63,8 @@ public interface ProductCategoryService extends IService<ProductCategory> {
List<ProductCategoryVo2> getCategoryListByShopId(String shopId);
void removeProductCategoryCache(String shopId, String categoryId);
void refreshProductCategoryCache(String shopId, String categoryId);
}

31
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));
}
}

65
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<Shop> findByCondition(Shop Shop, Pageable pageable) {
public Page<Shop> findByCondition(Shop shop, Pageable pageable) {
return shopDao.findAll(new Specification<Shop>() {
@Nullable
@Override
@ -115,14 +115,38 @@ public class ShopServiceImpl implements ShopService {
final List<Predicate> 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<cc.hiver.mall.entity.Product> qw = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
qw.select("shop_id").like("product_name", keyword);
List<cc.hiver.mall.entity.Product> productList = productMapper.selectList(qw);
List<String> 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<String> 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<String> shopIdList = new ArrayList<>();
shopIdList.add(shopId);
query.setShopIdList(shopIdList);
query.setIsPush(1); // 推荐
//query.setIsPush(1); // 推荐
IPage<ProductPageVO> 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);
}
}

40
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<ProductCategoryMappe
@Autowired
private ProductCategoryService productCategoryService;
@Autowired
private RedisTemplateHelper redisTemplateHelper;
@Transactional(rollbackFor = Exception.class)
@Override
public String batchSaveCategoryAndAttribute(ProductCategoryVo productCategoryVo) {
@ -579,4 +585,38 @@ public class ProductCategoryServiceImpl extends ServiceImpl<ProductCategoryMappe
public List<ProductCategoryVo2> 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<ProductCategoryVo2> 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));
}
}

2
hiver-modules/hiver-mall/src/main/resources/mapper/ProductMapper.xml

@ -789,7 +789,7 @@
)
</if>
</where>
ORDER BY t.order_filed asc,
ORDER BY t.order_filed desc,
<!--销量排序
<if test='queryParams.startDate !=null and queryParams.startDate.trim() neq "" and queryParams.endDate !=null and queryParams.endDate.trim() neq ""'>
<if test='queryParams.sortField!=null and queryParams.sortField.trim() neq "" and queryParams.sortField eq "totalSold"'>

Loading…
Cancel
Save