diff --git a/hiver-admin/src/main/resources/application.yml b/hiver-admin/src/main/resources/application.yml
index 79de7f07..942975ed 100644
--- a/hiver-admin/src/main/resources/application.yml
+++ b/hiver-admin/src/main/resources/application.yml
@@ -29,6 +29,12 @@ ie:
server:
port: 8888
+ # 响应 gzip 压缩 店铺列表这类大 JSON 字段名高度重复 压缩率约 6-8 倍 小程序端会自动解压
+ compression:
+ enabled: true
+ mime-types: application/json,application/xml,text/html,text/xml,text/plain,text/css,text/javascript,application/javascript
+ # 小于该阈值的响应不压缩 避免小响应白付 CPU
+ min-response-size: 2KB
servlet:
context-path: /
tomcat:
@@ -50,7 +56,7 @@ spring:
# 数据源
datasource:
# url: jdbc:mysql://154.8.162.157:3306/hiver_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
- url: jdbc:mysql://8.140.253.224:3306/school?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
+ url: jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
username: root
# Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果) 以下解密结果为123456
password: ENC(87YloapnWG6mLejOa27eLN0afFhCrbAGxoHXXrSUrGJ0trM/BndC2kx/gfoJsXIi)
@@ -58,8 +64,16 @@ spring:
driver-class-name: com.mysql.jdbc.Driver
# Druid StatViewServlet配置
druid:
- test-on-borrow: true
+ initial-size: 5
+ min-idle: 5
+ max-active: 30
+ max-wait: 3000
validation-query: SELECT 1
+ test-on-borrow: false
+ test-while-idle: true
+ test-on-return: false
+ time-between-eviction-runs-millis: 60000
+ min-evictable-idle-time-millis: 300000
stat-view-servlet:
# 默认true 内置监控页面首页/druid/index.html
enabled: true
@@ -94,7 +108,7 @@ spring:
# Redis 若设有密码自行添加配置password
redis:
# host: 154.8.162.157
- host: 8.140.253.224
+ host: 127.0.0.1
password: reddoor168
# 数据库索引 默认0
database: 1
@@ -120,7 +134,7 @@ spring:
uris: http://localhost:9200
# RabbitMQ配置
rabbitmq:
- host: 8.140.253.224
+ host: 127.0.0.1
port: 5672
username: root
password: ziyi123QQ
diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html
index cd4018e9..60d9cedf 100644
--- a/hiver-admin/test-output/test-report.html
+++ b/hiver-admin/test-output/test-report.html
@@ -35,7 +35,7 @@
Hiver
- 20, 2026 17:27:21
+ 21, 2026 15:37:23
@@ -84,7 +84,7 @@
passTest
-
17:27:22 / 0.025 secs
+
15:37:24 / 0.022 secs
@@ -92,9 +92,9 @@
#test-id=1
passTest
-
09.20.2026 17:27:22
-
09.20.2026 17:27:22
-
0.025 secs
+
09.21.2026 15:37:24
+
09.21.2026 15:37:24
+
0.022 secs
@@ -104,7 +104,7 @@
Pass
- 17:27:22
+ 15:37:24
Test passed
@@ -128,13 +128,13 @@
Started
-
20, 2026 17:27:21
+
21, 2026 15:37:23
Ended
-
20, 2026 17:27:22
+
21, 2026 15:37:24
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java
index c0448d77..73707058 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java
@@ -165,7 +165,8 @@ public class MallOrderController {
@PostMapping("/cloudPrint/{id}")
@ApiOperation("手动云打印订单小票")
- public Result
cloudPrint(@ApiParam("订单ID") @PathVariable String id) {
+ public Result cloudPrint(@ApiParam("订单ID") @PathVariable String id,
+ @RequestParam(value = "scanVerify", required = false) Boolean scanVerify) {
MallOrderVO vo = mallOrderService.getOrderDetail(id);
if (vo == null) {
return ResultUtil.error("订单不存在");
@@ -173,7 +174,10 @@ public class MallOrderController {
if (!daQuCloudPrintService.isCloudPrintShop(vo.getShopId())) {
return ResultUtil.error("当前商家未配置云打印");
}
- orderAsyncProducer.sendCloudPrint(id, "MANUAL-" + System.currentTimeMillis());
+ String printReason = Boolean.TRUE.equals(scanVerify)
+ ? "SCAN_VERIFY-" + System.currentTimeMillis()
+ : "MANUAL-" + System.currentTimeMillis();
+ orderAsyncProducer.sendCloudPrint(id, printReason);
return ResultUtil.success("云打印任务已发送");
}
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 e8da4e72..c57dde68 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
@@ -5,8 +5,10 @@ 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.ProductCategory;
+import cc.hiver.mall.entity.Shop;
import cc.hiver.mall.pojo.vo.ProductCategoryVo;
import cc.hiver.mall.pojo.vo.ProductCategoryVo2;
+import cc.hiver.mall.service.ShopService;
import cc.hiver.mall.service.mybatis.ProductCategoryService;
import cc.hiver.mall.service.mybatis.ProductService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -37,6 +39,9 @@ public class ProductCategoryController {
@Autowired
private ProductService productService;
+ @Autowired
+ private ShopService shopService;
+
@Autowired
private SecurityUtil securityUtil;
@@ -84,6 +89,10 @@ public class ProductCategoryController {
// 将该分类下的商品id删除掉
productService.deleteProductByCategoryId(productCategory.getId());
productCategoryService.removeProductCategoryCache(old.getShopId(), old.getId());
+ Shop shop = shopService.get(old.getShopId());
+ if (shop != null) {
+ shopService.refreshShopCache(shop.getId(), shop.getRegionId());
+ }
return ResultUtil.success("删除成功");
}
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 8180892e..cc9d11a1 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
@@ -79,6 +79,7 @@ import java.util.stream.Collectors;
public class ShopController {
private static final String GROUP_BUY_DEFAULT_PAGE_CACHE_PREFIX = "GROUP_BUY_DEFAULT_SHOP_PAGE:";
private static final long GROUP_BUY_DEFAULT_PAGE_CACHE_SECONDS = 30L;
+ private static final long SHOP_LIST_SLOW_THRESHOLD_MS = 10L;
private static final DateTimeFormatter BUSINESS_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
private static final String PRINTING_METHOD_BLUETOOTH = "bluetooth";
private static final String PRINTING_METHOD_CLOUD = "cloud";
@@ -458,7 +459,7 @@ public class ShopController {
@ApiOperation("多条件分页获取公司列表")
public Result> getByCondition(Shop shop,
PageVo pageVo) {
- long queryStartTime = System.currentTimeMillis();
+ ShopListStageTimer timer = new ShopListStageTimer();
String regionId = shop.getRegionId();
boolean adminQuery = CharSequenceUtil.isNotBlank(shop.getShopIcon());
boolean hasKeyword = hasSearchKeyword(shop);
@@ -466,17 +467,23 @@ public class ShopController {
&& !hasKeyword
&& CharSequenceUtil.isBlank(shop.getShopName());
String defaultPageCacheKey = buildDefaultGroupBuyPageCacheKey(shop, pageVo, adminQuery);
+ timer.note("pageCacheKey", defaultPageCacheKey == null ? "null" : defaultPageCacheKey);
if (CharSequenceUtil.isNotBlank(defaultPageCacheKey)) {
String cacheJson = redisTemplateHelper.get(defaultPageCacheKey);
+ timer.mark("pageCacheGet");
+ timer.note("pageCacheBytes", cacheJson == null ? 0 : cacheJson.length());
if (CharSequenceUtil.isNotBlank(cacheJson)) {
try {
ShopListPageCache cache = JSONUtil.toBean(cacheJson, ShopListPageCache.class);
+ timer.mark("pageCacheParse");
if (cache != null && cache.getContent() != null) {
if (containsUserHiddenShop(cache.getContent())) {
redisTemplateHelper.delete(defaultPageCacheKey);
} else {
fillBaseDeliveryFee(cache.getContent(), regionId);
+ timer.mark("baseFee");
Page pageResult = new PageImpl<>(cache.getContent(), PageUtil.initPage(pageVo), cache.getTotalElements());
+ logShopListQuery("pageCache", timer, cache.getTotalElements(), cache.getContent().size(), regionId);
return new ResultUtil>().setData(pageResult);
}
}
@@ -488,10 +495,14 @@ public class ShopController {
}
if (useRegionCache) {
List values = redisTemplateHelper.hValues("SHOP_CACHE:" + regionId);
+ timer.mark("hvals");
if (values != null && !values.isEmpty()) {
List allShops = new ArrayList<>();
+ long hvalsBytes = 0L;
for (Object v : values) {
- ShopCacheDTO dto = parseShopCacheBase(v.toString());
+ String shopCacheJson = v.toString();
+ hvalsBytes += shopCacheJson.length();
+ ShopCacheDTO dto = parseShopCacheBase(shopCacheJson);
Shop s = dto.getShop();
if (s == null) {
continue;
@@ -552,50 +563,18 @@ public class ShopController {
}
allShops.add(s);
}
+ timer.mark("parseShops");
+ timer.note("hvalsShops", values.size());
+ timer.note("hvalsBytes", hvalsBytes);
- String sort = pageVo.getSort();
- String order = pageVo.getOrder();
- if (CharSequenceUtil.isNotBlank(sort)) {
- allShops.sort((s1, s2) -> {
- int compareResult = 0;
- if ("saleCount".equals(sort)) {
- Integer count1 = s1.getSaleCount();
- Integer count2 = s2.getSaleCount();
- Integer c1 = count1 == null ? 0 : count1;
- Integer c2 = count2 == null ? 0 : count2;
- compareResult = c1.compareTo(c2);
- } else if ("shopScore".equals(sort)) {
- 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)) {
- compareResult = -compareResult;
- }
- return compareResult;
- });
- }
-
- // 稳定排序:用户端优先展示营业中的商家,后台仍将禁用商家置底。
if (adminQuery) {
- allShops.sort((s1, s2) -> {
- boolean disabled1 = ShopConstant.SHOP_STATUS_LOCK.equals(s1.getStatus());
- boolean disabled2 = ShopConstant.SHOP_STATUS_LOCK.equals(s2.getStatus());
- if (disabled1 != disabled2) {
- return disabled1 ? 1 : -1;
- }
- Integer status1 = s1.getStatus() == null ? ShopConstant.SHOP_STATUS_LOCK : s1.getStatus();
- Integer status2 = s2.getStatus() == null ? ShopConstant.SHOP_STATUS_LOCK : s2.getStatus();
- return status1.compareTo(status2);
- });
+ applyAdminShopListSort(allShops, pageVo);
} else {
+ applyUserShopListSort(allShops, pageVo);
String currentBusinessTime = LocalTime.now().format(BUSINESS_TIME_FORMATTER);
allShops.sort((s1, s2) -> compareUserShopPriority(s1, s2, currentBusinessTime));
}
+ timer.mark("sort");
int pageNumber = pageVo.getPageNumber() > 0 ? pageVo.getPageNumber() : 1;
int pageSize = pageVo.getPageSize() > 0 ? pageVo.getPageSize() : 10;
@@ -615,21 +594,27 @@ public class ShopController {
productKeys.add("SHOP_PRODUCTS:" + s.getId());
}
List productsJsonList = redisTemplateHelper.multiGet(productKeys);
+ timer.mark("mgetProducts");
+ long productBytes = 0L;
+ int productCount = 0;
if (productsJsonList != null && productsJsonList.size() == pageList.size()) {
for (int i = 0; i < pageList.size(); i++) {
String productsJson = productsJsonList.get(i);
if (CharSequenceUtil.isNotBlank(productsJson)) {
+ productBytes += productsJson.length();
List productsReturn = new ArrayList<>();
List products = JSONUtil.toList(productsJson, ProductPageVO.class);
+ productCount += products == null ? 0 : products.size();
if (hasKeyword) {
for (ProductPageVO p : products) {
- if (p.getDelFlag() == 1 && p.getProductName() != null && p.getProductName().contains(shop.getKeyWord())) {
+ if (isSearchMatchedProduct(p, shop.getKeyWord())) {
+ p.setIsPush(1);
productsReturn.add(p);
}
}
}else{
for (ProductPageVO p : products) {
- if (p.getDelFlag() == 1 && p.getIsPush() == 1) {
+ if (Integer.valueOf(1).equals(p.getDelFlag()) && Integer.valueOf(1).equals(p.getIsPush())) {
productsReturn.add(p);
}
}
@@ -640,28 +625,40 @@ public class ShopController {
}
}
}
+ timer.mark("parseProducts");
+ timer.note("productBytes", productBytes);
+ timer.note("productCount", productCount);
}
fillGroupDeliveryTime(pageList, regionId);
+ timer.mark("deliveryTime");
fillBaseDeliveryFee(pageList, regionId);
+ timer.mark("baseFee");
Page pageResult = new PageImpl<>(pageList, PageUtil.initPage(pageVo), allShops.size());
cacheDefaultGroupBuyPage(defaultPageCacheKey, pageList, allShops.size());
- logSlowShopListQuery("redis", queryStartTime, allShops.size(), pageList.size(), regionId);
+ timer.mark("pageCacheWrite");
+ logShopListQuery("redis", timer, allShops.size(), pageList.size(), regionId);
return new ResultUtil>().setData(pageResult);
}
}
Page page;
if (adminQuery) {
page = shopService.findByCondition(shop, PageUtil.initPage(pageVo));
+ timer.mark("dbQuery");
fillShopTakeawayAndProducts(page.getContent(), shop, false);
+ timer.mark("dbFill");
} else {
// 用户端:全量查询 → 挂 takeaway → 按多时段营业状态排序 → 再分页(与缓存路径一致)
Page allPage = shopService.findByCondition(shop, Pageable.unpaged());
List allShops = new ArrayList<>(allPage.getContent());
+ timer.mark("dbQuery");
+ timer.note("dbShops", allShops.size());
fillShopTakeawayOnly(allShops);
+ timer.mark("dbTakeaway");
applyUserShopListSort(allShops, pageVo);
String currentBusinessTime = LocalTime.now().format(BUSINESS_TIME_FORMATTER);
allShops.sort((s1, s2) -> compareUserShopPriority(s1, s2, currentBusinessTime));
+ timer.mark("sort");
int pageNumber = pageVo.getPageNumber() > 0 ? pageVo.getPageNumber() : 1;
int pageSize = pageVo.getPageSize() > 0 ? pageVo.getPageSize() : 10;
@@ -671,15 +668,85 @@ public class ShopController {
? new ArrayList<>()
: new ArrayList<>(allShops.subList(fromIndex, toIndex));
fillShopProducts(pageList, shop);
+ timer.mark("dbProducts");
fillGroupDeliveryTime(pageList, shop.getRegionId());
+ timer.mark("deliveryTime");
fillBaseDeliveryFee(pageList, shop.getRegionId());
+ timer.mark("baseFee");
page = new PageImpl<>(pageList, PageUtil.initPage(pageVo), allShops.size());
}
cacheDefaultGroupBuyPage(defaultPageCacheKey, page.getContent(), page.getTotalElements());
- logSlowShopListQuery("db", queryStartTime, page.getTotalElements(), page.getContent().size(), shop.getRegionId());
+ timer.mark("pageCacheWrite");
+ logShopListQuery("db", timer, page.getTotalElements(), page.getContent().size(), shop.getRegionId());
return new ResultUtil>().setData(page);
}
+ private void applyAdminShopListSort(List allShops, PageVo pageVo) {
+ if (allShops == null || allShops.isEmpty()) {
+ return;
+ }
+ String shoprankOrder = getShoprankOrder(pageVo);
+ String sort = pageVo == null ? null : pageVo.getSort();
+ String order = pageVo == null ? null : pageVo.getOrder();
+ allShops.sort((s1, s2) -> {
+ int compareResult = Integer.compare(getAdminShopStatusOrder(s1), getAdminShopStatusOrder(s2));
+ if (compareResult != 0) {
+ return compareResult;
+ }
+ compareResult = compareShoprank(s1, s2, shoprankOrder);
+ if (compareResult != 0 || CharSequenceUtil.isBlank(sort)
+ || "status".equals(sort) || "shoprank".equals(sort)) {
+ return compareResult;
+ }
+ compareResult = compareShopBySortField(s1, s2, sort);
+ if ("desc".equalsIgnoreCase(order)) {
+ compareResult = -compareResult;
+ }
+ return compareResult;
+ });
+ }
+
+ private int getAdminShopStatusOrder(Shop shop) {
+ Integer status = shop == null ? null : shop.getStatus();
+ if (ShopConstant.SHOP_STATUS_NORMAL.equals(status)) {
+ return 0;
+ }
+ return ShopConstant.SHOP_STATUS_LOCK.equals(status) ? 2 : 1;
+ }
+
+ private String getShoprankOrder(PageVo pageVo) {
+ if (pageVo == null) {
+ return "desc";
+ }
+ if ("shoprank".equals(pageVo.getSortOrder())) {
+ return CharSequenceUtil.isBlank(pageVo.getOrderOrder()) ? "desc" : pageVo.getOrderOrder();
+ }
+ if ("shoprank".equals(pageVo.getSort())) {
+ return CharSequenceUtil.isBlank(pageVo.getOrder()) ? "desc" : pageVo.getOrder();
+ }
+ return "desc";
+ }
+
+ private int compareShoprank(Shop s1, Shop s2, String order) {
+ Integer shoprank1 = s1.getShoprank() == null ? 0 : s1.getShoprank();
+ Integer shoprank2 = s2.getShoprank() == null ? 0 : s2.getShoprank();
+ int compareResult = shoprank1.compareTo(shoprank2);
+ return "asc".equalsIgnoreCase(order) ? compareResult : -compareResult;
+ }
+
+ private int compareShopBySortField(Shop s1, Shop s2, String sort) {
+ if ("saleCount".equals(sort)) {
+ Integer c1 = s1.getSaleCount() == null ? 0 : s1.getSaleCount();
+ Integer c2 = s2.getSaleCount() == null ? 0 : s2.getSaleCount();
+ return c1.compareTo(c2);
+ } else if ("shopScore".equals(sort)) {
+ BigDecimal score1 = s1.getShopScore() == null ? BigDecimal.ZERO : s1.getShopScore();
+ BigDecimal score2 = s2.getShopScore() == null ? BigDecimal.ZERO : s2.getShopScore();
+ return score1.compareTo(score2);
+ }
+ return 0;
+ }
+
private void applyUserShopListSort(List allShops, PageVo pageVo) {
if (allShops == null || allShops.isEmpty() || pageVo == null) {
return;
@@ -747,6 +814,9 @@ public class ShopController {
Map> productsByShopId = new HashMap<>();
if (productList != null && productList.getRecords() != null) {
productList.getRecords().forEach(productPageVO -> {
+ if (CharSequenceUtil.isNotBlank(query.getKeyWord())) {
+ productPageVO.setIsPush(1);
+ }
productsByShopId.computeIfAbsent(productPageVO.getShopId(), key -> new ArrayList<>()).add(productPageVO);
});
}
@@ -755,6 +825,14 @@ public class ShopController {
}
}
+ private boolean isSearchMatchedProduct(ProductPageVO product, String keyword) {
+ return product != null
+ && Integer.valueOf(1).equals(product.getDelFlag())
+ && CharSequenceUtil.isNotBlank(product.getProductName())
+ && CharSequenceUtil.isNotBlank(keyword)
+ && product.getProductName().contains(keyword);
+ }
+
private void fillShopTakeawayAndProducts(List shops, Shop query) {
fillShopTakeawayAndProducts(shops, query, true);
}
@@ -851,11 +929,42 @@ public class ShopController {
return ShopBusinessHourUtil.getBusinessTimeOrder(takeaway, currentTime);
}
- private void logSlowShopListQuery(String source, long startTime, long totalElements, int pageSize, String regionId) {
- long cost = System.currentTimeMillis() - startTime;
- if (cost > 300) {
- log.warn("app/shop/getByCondition slow source={}, cost={}ms, regionId={}, total={}, pageSize={}",
- source, cost, regionId, totalElements, pageSize);
+ private void logShopListQuery(String source, ShopListStageTimer timer, long totalElements, int pageSize, String regionId) {
+ long cost = timer.totalMs();
+ if (cost > SHOP_LIST_SLOW_THRESHOLD_MS) {
+ log.warn("app/shop/getByCondition slow source={}, cost={}ms, regionId={}, total={}, pageSize={}, stages=[{}]",
+ source, cost, regionId, totalElements, pageSize, timer.detail());
+ } else if (log.isDebugEnabled()) {
+ log.debug("app/shop/getByCondition source={}, cost={}ms, regionId={}, total={}, pageSize={}, stages=[{}]",
+ source, cost, regionId, totalElements, pageSize, timer.detail());
+ }
+ }
+
+ /**
+ * 分段计时:mark 记录距上一个 mark 的耗时,note 记录传输字节数等辅助指标,
+ * 用于定位 getByCondition 的耗时分布(Redis 取数 / JSON 解析 / 排序 / DB)。
+ */
+ private static final class ShopListStageTimer {
+ private final long startNano = System.nanoTime();
+ private final StringBuilder detail = new StringBuilder();
+ private long lastNano = startNano;
+
+ void mark(String stage) {
+ long now = System.nanoTime();
+ detail.append(stage).append('=').append((now - lastNano) / 1_000_000L).append("ms ");
+ lastNano = now;
+ }
+
+ void note(String name, Object value) {
+ detail.append(name).append('=').append(value).append(' ');
+ }
+
+ long totalMs() {
+ return (System.nanoTime() - startNano) / 1_000_000L;
+ }
+
+ String detail() {
+ return detail.toString().trim();
}
}
@@ -1032,7 +1141,7 @@ public class ShopController {
if (shop.getStoreFlag() != null) {
oldShop.setStoreFlag(shop.getStoreFlag());
}
-
+
// 新增字段处理
if (shop.getShopImages() != null) {
oldShop.setShopImages(shop.getShopImages());
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 2af53e2e..794dff14 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
@@ -187,13 +187,24 @@ public class ShopServiceImpl implements ShopService {
cq.where(list.toArray(arr));
if (adminQuery) {
List orderList = new ArrayList<>();
- Expression disabledOrder = cb.selectCase()
- .when(cb.equal(statusField, ShopConstant.SHOP_STATUS_LOCK), 1)
- .otherwise(0);
- orderList.add(cb.asc(disabledOrder));
- orderList.add(cb.asc(statusField));
+ Expression statusOrder = cb.selectCase()
+ .when(cb.equal(statusField, ShopConstant.SHOP_STATUS_NORMAL), 0)
+ .when(cb.equal(statusField, ShopConstant.SHOP_STATUS_LOCK), 2)
+ .otherwise(1);
+ orderList.add(cb.asc(statusOrder));
+ Sort.Order shoprankOrder = null;
for (Sort.Order order : pageSort) {
- if ("status".equals(order.getProperty())) {
+ if ("shoprank".equals(order.getProperty())) {
+ shoprankOrder = order;
+ break;
+ }
+ }
+ Path shoprankField = root.get("shoprank");
+ orderList.add(shoprankOrder != null && shoprankOrder.isAscending()
+ ? cb.asc(shoprankField)
+ : cb.desc(shoprankField));
+ for (Sort.Order order : pageSort) {
+ if ("status".equals(order.getProperty()) || "shoprank".equals(order.getProperty())) {
continue;
}
Path sortField = root.get(order.getProperty());
@@ -384,10 +395,25 @@ public class ShopServiceImpl implements ShopService {
// 第二层缓存:单独存储商品列表
String productsRedisKey = "SHOP_PRODUCTS:" + shopId;
+ String pushProductsRedisKey = "SHOP_PUSH_PRODUCTS:" + shopId;
if (productList != null && productList.getRecords() != null && !productList.getRecords().isEmpty()) {
- redisTemplateHelper.set(productsRedisKey, JSONUtil.toJsonStr(productList.getRecords()));
+ List products = productList.getRecords();
+ redisTemplateHelper.set(productsRedisKey, JSONUtil.toJsonStr(products));
+
+ List pushProducts = new ArrayList<>();
+ for (ProductPageVO product : products) {
+ if (Integer.valueOf(1).equals(product.getDelFlag()) && Integer.valueOf(1).equals(product.getIsPush())) {
+ pushProducts.add(product);
+ }
+ }
+ if (!pushProducts.isEmpty()) {
+ redisTemplateHelper.set(pushProductsRedisKey, JSONUtil.toJsonStr(pushProducts));
+ } else {
+ redisTemplateHelper.delete(pushProductsRedisKey);
+ }
} else {
redisTemplateHelper.delete(productsRedisKey);
+ redisTemplateHelper.delete(pushProductsRedisKey);
}
}
@@ -403,6 +429,8 @@ public class ShopServiceImpl implements ShopService {
// 同步删除第二层商品缓存
String productsRedisKey = "SHOP_PRODUCTS:" + shopId;
redisTemplateHelper.delete(productsRedisKey);
+ String pushProductsRedisKey = "SHOP_PUSH_PRODUCTS:" + shopId;
+ redisTemplateHelper.delete(pushProductsRedisKey);
}
private void removeGroupBuyDefaultPageCache(String regionId) {
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/DaQuReceiptRenderUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/DaQuReceiptRenderUtil.java
index 40957ad7..14974025 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/DaQuReceiptRenderUtil.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/DaQuReceiptRenderUtil.java
@@ -12,6 +12,7 @@ import java.util.List;
public final class DaQuReceiptRenderUtil {
private static final String LINE = "--------------------------------";
private static final String TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ private static final String APPOINTMENT_TIME_PATTERN = "yyyy-MM-dd HH:mm";
private DaQuReceiptRenderUtil() {
}
@@ -22,12 +23,14 @@ public final class DaQuReceiptRenderUtil {
List refunds = order.getMallRefundRecord();
boolean refundPrint = isRefundPrint(printReason);
boolean forcedOrderPrint = isOrderEventPrint(printReason);
+ boolean scanVerifyPrint = isScanVerifyPrint(printReason);
boolean hasRefund = refundPrint && refunds != null && !refunds.isEmpty();
centerLarge(sb, orderNo(order));
- centerLarge(sb, orderTypeText(order, delivery, refundPrint, forcedOrderPrint));
+ centerLarge(sb, orderTypeText(order, delivery, refundPrint, forcedOrderPrint, scanVerifyPrint));
if (delivery != null && Integer.valueOf(1).equals(delivery.getAppointmentDelivery())) {
- largeLeft(sb, "要求送达时间:" + formatTime(delivery.getMustFinishTime()));
+ left(sb, "要求送达时间:");
+ largeLeft(sb, formatAppointmentTime(delivery.getMustFinishTime()));
}
if (isFaceToFaceDelivery(order)) {
largeLeft(sb, "本单编号:" + defaultString(order.getNumberCode()));
@@ -143,7 +146,7 @@ public final class DaQuReceiptRenderUtil {
return defaultString(order.getNumberCode());
}
- private static String orderTypeText(MallOrderVO order, MallDeliveryOrder delivery, boolean refundPrint, boolean forcedOrderPrint) {
+ private static String orderTypeText(MallOrderVO order, MallDeliveryOrder delivery, boolean refundPrint, boolean forcedOrderPrint, boolean scanVerifyPrint) {
Integer status = order.getStatus();
if (delivery != null && Integer.valueOf(1).equals(delivery.getAppointmentDelivery())
&& !refundPrint) {
@@ -167,6 +170,9 @@ public final class DaQuReceiptRenderUtil {
&& !Integer.valueOf(1).equals(order.getUserRequireMake())) {
return "待消费";
}
+ if (scanVerifyPrint) {
+ return "到店核销";
+ }
if (Integer.valueOf(5).equals(status)) {
return "已完成";
}
@@ -196,6 +202,10 @@ public final class DaQuReceiptRenderUtil {
return StringUtils.containsIgnoreCase(printReason, "REFUND");
}
+ private static boolean isScanVerifyPrint(String printReason) {
+ return StringUtils.containsIgnoreCase(printReason, "SCAN_VERIFY");
+ }
+
private static boolean isFaceToFaceDelivery(MallOrderVO order) {
return Integer.valueOf(1).equals(order.getDeliveryType())
&& Integer.valueOf(3).equals(order.getOrderType());
@@ -293,6 +303,10 @@ public final class DaQuReceiptRenderUtil {
return date == null ? "" : new SimpleDateFormat(TIME_PATTERN).format(date);
}
+ private static String formatAppointmentTime(Date date) {
+ return date == null ? "" : new SimpleDateFormat(APPOINTMENT_TIME_PATTERN).format(date);
+ }
+
private static String delNode(String text) {
return defaultString(text).replace("{", "").replace("}", "").replace("\"", "");
}