diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index 60d9cedf..7daf3683 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -¾ÅÔ 21, 2026 15:37:23 +¾ÅÔ 22, 2026 11:55:05
  • @@ -84,7 +84,7 @@

    passTest

    -

    15:37:24 ÏÂÎç / 0.022 secs

    +

    11:55:05 ÉÏÎç / 0.025 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -09.21.2026 15:37:24 -09.21.2026 15:37:24 -0.022 secs +09.22.2026 11:55:05 +09.22.2026 11:55:05 +0.025 secs
    @@ -104,7 +104,7 @@ Pass - 15:37:24 + 11:55:05 Test passed @@ -128,13 +128,13 @@

    Started

    -

    ¾ÅÔ 21, 2026 15:37:23

    +

    ¾ÅÔ 22, 2026 11:55:05

    Ended

    -

    ¾ÅÔ 21, 2026 15:37:24

    +

    ¾ÅÔ 22, 2026 11:55:05

    diff --git a/hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java b/hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java index 40d5c47c..411844fd 100644 --- a/hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java +++ b/hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java @@ -60,6 +60,7 @@ public class WorkerServiceImpl implements WorkerService { final Path createTimeField = root.get("createTime"); //final Path signPersonField = root.get("signPerson"); final Path isOnLineField = root.get("isOnLine"); + final Path canTransferOrderField = root.get("canTransferOrder"); final Path userIdField = root.get("userId"); @@ -96,6 +97,11 @@ public class WorkerServiceImpl implements WorkerService { list.add(cb.equal(isOnLineField, worker.getIsOnLine())); } + // 是否允许接中转单 + if (worker.getCanTransferOrder() != null) { + list.add(cb.equal(canTransferOrderField, worker.getCanTransferOrder())); + } + // 是否接收指派单状态 if (worker.getGetPushOrder() != null) { list.add(cb.equal(getPushOrderField, worker.getGetPushOrder())); diff --git a/hiver-core/src/main/java/cc/hiver/core/vo/WorkerQueryVO.java b/hiver-core/src/main/java/cc/hiver/core/vo/WorkerQueryVO.java index ba0e064f..0f346c81 100644 --- a/hiver-core/src/main/java/cc/hiver/core/vo/WorkerQueryVO.java +++ b/hiver-core/src/main/java/cc/hiver/core/vo/WorkerQueryVO.java @@ -67,6 +67,9 @@ public class WorkerQueryVO extends HiverBasePageQuery { @ApiModelProperty("上下线状态:0:下线;1:上线") private Integer isOnLine; + @ApiModelProperty(value = "是否可以接中转单:0否 1是") + private Integer canTransferOrder; + /** * 联系方式 */ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java index 03b99767..fb9a3d10 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminMallOrderGroupController.java @@ -4,12 +4,15 @@ import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.vo.Result; import cc.hiver.mall.dao.mapper.MallOrderGoodsMapper; +import cc.hiver.mall.dao.mapper.ProductMapper; import cc.hiver.mall.dao.mapper.ShopMapper; import cc.hiver.mall.dao.mapper.ShopTakeawayMapper; import cc.hiver.mall.entity.*; import cc.hiver.mall.pojo.dto.ShopCacheDTO; import cc.hiver.mall.service.mybatis.MallOrderGroupService; import cc.hiver.mall.service.mybatis.MallOrderService; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -30,6 +33,9 @@ import java.util.stream.Collectors; @RequestMapping("/hiver/mall/admin/orderGroup") public class AdminMallOrderGroupController { + private static final String MOCK_REGION_ID = "2097949297042657280"; + private static final String SHOP_CACHE_PREFIX = "SHOP_CACHE:"; + private static final String SHOP_GROUP_ORDERS_PREFIX = "SHOP_GROUP_ORDERS:"; private static final int GROUP_STATUS_FACE_TO_FACE = 3; @Autowired @@ -50,6 +56,9 @@ public class AdminMallOrderGroupController { @Autowired private ShopTakeawayMapper shopTakeawayMapper; + @Autowired + private ProductMapper productMapper; + @Data public static class OrderGroupQuery { private String shopId; @@ -98,7 +107,7 @@ public class AdminMallOrderGroupController { return ResultUtil.error("regionId不能为空"); } - List groups = listGroupsFromDb(query); + List groups = listGroups(query); groups = filterGroups(groups, query); Map shopMap = buildShopMap(groups, query.getRegionId()); @@ -111,8 +120,10 @@ public class AdminMallOrderGroupController { int pageSize = Math.max(query.getPageSize(), 1); int fromIndex = Math.min((pageNumber - 1) * pageSize, groups.size()); int toIndex = Math.min(fromIndex + pageSize, groups.size()); - List records = groups.subList(fromIndex, toIndex).stream() - .map(group -> toListVo(group, shopMap.get(group.getShopId()))) + List pageGroups = groups.subList(fromIndex, toIndex); + Map productMap = buildProductMap(pageGroups); + List records = pageGroups.stream() + .map(group -> toListVo(group, shopMap.get(group.getShopId()), productMap.get(group.getProductId()))) .collect(Collectors.toList()); Page result = new Page<>(pageNumber, pageSize, total); @@ -120,6 +131,79 @@ public class AdminMallOrderGroupController { return new ResultUtil>().setData(result); } + private List listGroups(OrderGroupQuery query) { + if (MOCK_REGION_ID.equals(query.getRegionId())) { + return listGroupsFromCache(query); + } + return listGroupsFromDb(query); + } + + private List listGroupsFromCache(OrderGroupQuery query) { + Set shopIds = getRegionShopIds(query); + if (shopIds.isEmpty()) { + return new ArrayList<>(); + } + + List groups = new ArrayList<>(); + for (String shopId : shopIds) { + Map orderCache = redisTemplateHelper.hGetAll(buildShopGroupOrdersKey(shopId)); + if (orderCache == null || orderCache.isEmpty()) { + continue; + } + for (Object value : orderCache.values()) { + MallOrderGroup group = parseOrderGroupFromCache(value, shopId, query.getRegionId()); + if (group != null) { + groups.add(group); + } + } + } + return groups; + } + + private Set getRegionShopIds(OrderGroupQuery query) { + String shopCacheKey = buildShopCacheKey(query.getRegionId()); + if (StringUtils.isNotBlank(query.getShopId())) { + if (redisTemplateHelper.hExists(shopCacheKey, query.getShopId())) { + Set shopIds = new LinkedHashSet<>(); + shopIds.add(query.getShopId()); + return shopIds; + } + return Collections.emptySet(); + } + + Set cacheShopIds = redisTemplateHelper.hKeys(shopCacheKey); + if (cacheShopIds == null || cacheShopIds.isEmpty()) { + return Collections.emptySet(); + } + return cacheShopIds.stream() + .filter(Objects::nonNull) + .map(Object::toString) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + private MallOrderGroup parseOrderGroupFromCache(Object value, String shopId, String regionId) { + if (value == null) { + return null; + } + try { + MallOrderGroup group = JSONUtil.toBean(value.toString(), MallOrderGroup.class); + if (group == null) { + return null; + } + if (StringUtils.isBlank(group.getShopId())) { + group.setShopId(shopId); + } + if (StringUtils.isBlank(group.getRegionId())) { + group.setRegionId(regionId); + } + return group; + } catch (Exception e) { + log.info("解析待成团缓存失败 shopId={}", shopId, e); + return null; + } + } + private List listGroupsFromDb(OrderGroupQuery query) { LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(query.getShopId())) { @@ -179,7 +263,7 @@ public class AdminMallOrderGroupController { Map result = new HashMap<>(); List missingShopIds = new ArrayList<>(); - String shopCacheKey = "SHOP_CACHE:" + regionId; + String shopCacheKey = buildShopCacheKey(regionId); List cacheFields = new ArrayList<>(shopIds); List cacheValues = redisTemplateHelper.hMultiGet(shopCacheKey, cacheFields); int index = 0; @@ -262,7 +346,38 @@ public class AdminMallOrderGroupController { return value != null && keyword != null && value.contains(keyword); } - private OrderGroupListVo toListVo(MallOrderGroup group, Shop shop) { + private Map buildProductMap(List groups) { + if (groups == null || groups.isEmpty()) { + return Collections.emptyMap(); + } + List productIds = groups.stream() + .map(MallOrderGroup::getProductId) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + if (productIds.isEmpty()) { + return Collections.emptyMap(); + } + + List products = productMapper.selectBatchIds(productIds); + if (products == null || products.isEmpty()) { + return Collections.emptyMap(); + } + return products.stream() + .filter(Objects::nonNull) + .filter(product -> StringUtils.isNotBlank(product.getId())) + .collect(Collectors.toMap(Product::getId, product -> product, (a, b) -> a)); + } + + private String buildShopCacheKey(String regionId) { + return SHOP_CACHE_PREFIX + regionId; + } + + private String buildShopGroupOrdersKey(String shopId) { + return SHOP_GROUP_ORDERS_PREFIX + shopId; + } + + private OrderGroupListVo toListVo(MallOrderGroup group, Shop shop, Product product) { OrderGroupListVo vo = new OrderGroupListVo(); vo.setId(group.getId()); vo.setShopId(group.getShopId()); @@ -282,13 +397,42 @@ public class AdminMallOrderGroupController { vo.setCreateTime(group.getCreateTime()); vo.setExpireTime(group.getExpireTime()); vo.setSuccessTime(group.getSuccessTime()); - vo.setProductName(group.getProductName()); + vo.setProductName(buildDisplayProductName(group, product)); vo.setProductPicture(group.getProductPicture()); vo.setProductId(group.getProductId()); vo.setShopItem(shop); return vo; } + private String buildDisplayProductName(MallOrderGroup group, Product product) { + String productName = group.getProductName(); + if (StringUtils.isBlank(productName) && product != null) { + productName = product.getProductName(); + } + String specPrice = getFirstSpecPrice(product == null ? null : product.getAttributeListPrice()); + if (StringUtils.isBlank(productName) || StringUtils.isBlank(specPrice)) { + return productName; + } + return productName + "-店内原价" + specPrice + "元"; + } + + private String getFirstSpecPrice(String attributeListPrice) { + if (StringUtils.isBlank(attributeListPrice)) { + return null; + } + try { + JSONArray specs = JSONUtil.parseArray(attributeListPrice); + if (specs.isEmpty()) { + return null; + } + JSONObject firstSpec = specs.getJSONObject(0); + return firstSpec == null ? null : firstSpec.getStr("specPrice"); + } catch (Exception e) { + log.warn("解析商品规格原价失败 attributeListPrice={}: {}", attributeListPrice, e.getMessage()); + return null; + } + } + @Data public static class OrderGroupDetailVo { private MallOrderGroup group; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java index 6e2d9315..c6aabe1f 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java @@ -239,7 +239,15 @@ public class MallDeliveryOrderController { @ApiOperation(value = "后台管理端分页查询配送中订单", notes = "直接查数据库,不按 workerId 缓存维度查询") public Result adminPageByWorker(@RequestBody MallDeliveryOrderPageQuery q) { IPage page = mallDeliveryOrderService.pageDeliveryByStatusAdmin(q); - return new ResultUtil().setData(page); + Map result = new HashMap<>(); + result.put("records", page.getRecords()); + result.put("total", page.getTotal()); + result.put("size", page.getSize()); + result.put("current", page.getCurrent()); + result.put("pages", page.getPages()); + result.put("transferUnacceptedCount", mallDeliveryOrderService.countTransferUnacceptedOrdersAdmin(q)); + result.put("transferPendingArriveCount", mallDeliveryOrderService.countTransferPendingArriveOrdersAdmin(q)); + return new ResultUtil().setData(result); } @PostMapping("/pageShopDelivery") @@ -316,6 +324,53 @@ public class MallDeliveryOrderController { return ResultUtil.success("接单成功"); } + @PostMapping("/transferReassign") + @ApiOperation(value = "后台改派中转配送员") + public Result transferReassign(@RequestParam String deliveryId, + @RequestParam String workerId, + @RequestParam(required = false) String workerName, + @RequestParam(required = false) String workerMobile) { + Worker worker = workerService.findByWorkerId(workerId); + if (worker == null) { + return ResultUtil.error("配送员不存在"); + } + if (!Integer.valueOf(1).equals(worker.getCanTransferOrder())) { + return ResultUtil.error("当前配送员未开启中转接单"); + } + MallDeliveryOrder delivery = mallDeliveryOrderService.getById(deliveryId); + if (delivery == null) { + return ResultUtil.error("配送单不存在"); + } + if (!Integer.valueOf(1).equals(delivery.getTransferDelivery())) { + return ResultUtil.error("非中转配送单"); + } + if (delivery.getTransferArriveTime() != null) { + return ResultUtil.error("该中转单已送达中转点"); + } + if (StrUtil.isBlank(delivery.getTransferWorkerId())) { + return ResultUtil.error("该中转单未接单"); + } + if (StrUtil.isBlank(workerName)) { + workerName = worker.getWorkerName(); + } + if (StrUtil.isBlank(workerMobile)) { + workerMobile = worker.getMobile(); + } + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(MallDeliveryOrder::getId, deliveryId) + .eq(MallDeliveryOrder::getTransferDelivery, 1) + .isNull(MallDeliveryOrder::getTransferArriveTime) + .isNotNull(MallDeliveryOrder::getTransferWorkerId) + .ne(MallDeliveryOrder::getTransferWorkerId, "") + .set(MallDeliveryOrder::getTransferWorkerId, workerId) + .set(MallDeliveryOrder::getTransferWorkerName, workerName) + .set(MallDeliveryOrder::getTransferWorkerMobile, workerMobile); + if (!mallDeliveryOrderService.update(updateWrapper)) { + return ResultUtil.error("该中转单不可改派"); + } + return ResultUtil.success("改派成功"); + } + @PostMapping("/transferArrive") @ApiOperation(value = "商家送达中转点") public Result transferArrive(@RequestParam String deliveryId, 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 cc9d11a1..7c39e4b3 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,7 +79,6 @@ 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"; @@ -459,31 +458,25 @@ public class ShopController { @ApiOperation("多条件分页获取公司列表") public Result> getByCondition(Shop shop, PageVo pageVo) { - ShopListStageTimer timer = new ShopListStageTimer(); String regionId = shop.getRegionId(); boolean adminQuery = CharSequenceUtil.isNotBlank(shop.getShopIcon()); boolean hasKeyword = hasSearchKeyword(shop); - boolean useRegionCache = CharSequenceUtil.isNotBlank(regionId) + boolean useRegionCache = !adminQuery + && CharSequenceUtil.isNotBlank(regionId) && !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); } } @@ -495,14 +488,10 @@ 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) { - String shopCacheJson = v.toString(); - hvalsBytes += shopCacheJson.length(); - ShopCacheDTO dto = parseShopCacheBase(shopCacheJson); + ShopCacheDTO dto = parseShopCacheBase(v.toString()); Shop s = dto.getShop(); if (s == null) { continue; @@ -563,9 +552,6 @@ public class ShopController { } allShops.add(s); } - timer.mark("parseShops"); - timer.note("hvalsShops", values.size()); - timer.note("hvalsBytes", hvalsBytes); if (adminQuery) { applyAdminShopListSort(allShops, pageVo); @@ -574,7 +560,6 @@ public class ShopController { 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; @@ -594,17 +579,12 @@ 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 (isSearchMatchedProduct(p, shop.getKeyWord())) { @@ -625,40 +605,27 @@ 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()); - 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; @@ -668,16 +635,11 @@ 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()); - timer.mark("pageCacheWrite"); - logShopListQuery("db", timer, page.getTotalElements(), page.getContent().size(), shop.getRegionId()); return new ResultUtil>().setData(page); } @@ -929,45 +891,6 @@ public class ShopController { return ShopBusinessHourUtil.getBusinessTimeOrder(takeaway, currentTime); } - 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(); - } - } - private void cacheDefaultGroupBuyPage(String cacheKey, List content, long totalElements) { if (CharSequenceUtil.isBlank(cacheKey) || content == null) { return; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java index ee29e574..dbd5f6a8 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java @@ -23,6 +23,7 @@ import cc.hiver.mall.service.RechargeService; import cc.hiver.mall.service.ShopAreaService; import cc.hiver.mall.service.ShopService; import cc.hiver.mall.service.mybatis.BaseDeliveryFeeSettingService; +import cc.hiver.mall.service.mybatis.MallDeliveryOrderService; import cc.hiver.mall.service.mybatis.WorkerRelaPriceService; import cc.hiver.mall.utils.WaitOrderCacheUtil; import cc.hiver.mall.utils.WorkerOrderCacheUtil; @@ -98,6 +99,9 @@ public class WorkerController { @Autowired private BaseDeliveryFeeSettingService baseDeliveryFeeSettingService; + @Autowired + private MallDeliveryOrderService mallDeliveryOrderService; + @RequestMapping(value = "/getByCondition", method = RequestMethod.POST) @ApiOperation(value = "多条件分页获取订单列表") public Result> getByCondition(@RequestBody WorkerQueryVO worker) { @@ -445,6 +449,8 @@ public class WorkerController { * 为 true 时:优先按取收货区域规则匹配,未匹配到则补充返回全职且上线的配送员 */ private Boolean fromAdmin; + /** true 时仅查询可接中转单的上线配送员 */ + private Boolean transferWorkerOnly; /** 页码(从1开始),默认1 */ private Integer pageNum = 1; /** 每页条数,默认10 */ @@ -459,6 +465,9 @@ public class WorkerController { public Result> getMatchingWorkerList(@RequestBody WorkerMatchDTO dto) { int pageNum = dto.getPageNum() != null && dto.getPageNum() > 0 ? dto.getPageNum() : 1; int pageSize = dto.getPageSize() != null && dto.getPageSize() > 0 ? dto.getPageSize() : 10; + if (Boolean.TRUE.equals(dto.getTransferWorkerOnly())) { + return new ResultUtil>().setData(getTransferWorkerList(dto, pageNum, pageSize)); + } if (dto.getCommissionAmount() != null && (StrUtil.isBlank(dto.getShopAreaId()) || StrUtil.isBlank(dto.getPutAreaId()))) { IPage emptyPage = new Page<>(pageNum, pageSize); @@ -641,6 +650,48 @@ public class WorkerController { return new ResultUtil>().setData(pageResult); } + private IPage getTransferWorkerList(WorkerMatchDTO dto, int pageNum, int pageSize) { + WorkerQueryVO query = new WorkerQueryVO(); + query.setPageNum(pageNum); + query.setPageSize(pageSize); + query.setRegion(dto.getRegionId()); + query.setWorkerStatus(1); + query.setIsOnLine(CommonConstant.ON_LINE); + query.setCanTransferOrder(1); + if (StrUtil.isNotBlank(dto.getKeyword())) { + query.setSearchStr(dto.getKeyword().trim()); + } + org.springframework.data.domain.Page workerPage = workerService.findByCondition(query); + List workers = workerPage.getContent(); + List workerIds = new ArrayList<>(); + for (Worker worker : workers) { + if (worker != null && StrUtil.isNotBlank(worker.getWorkerId())) { + workerIds.add(worker.getWorkerId()); + } + } + Map pendingCountMap = mallDeliveryOrderService.countPendingTransferArriveOrdersByWorkerIds(workerIds); + List records = new ArrayList<>(); + for (Worker worker : workers) { + WorkerMatchVO vo = new WorkerMatchVO(); + vo.setWorkerId(worker.getWorkerId()); + vo.setWorkerName(worker.getWorkerName()); + vo.setMobile(worker.getMobile()); + vo.setIcon(worker.getIcon()); + vo.setGeolocation(worker.getGeolocation()); + vo.setScore(worker.getScore()); + vo.setAvgTime(worker.getAvgTime()); + vo.setRebateAmount(worker.getRebateAmount()); + vo.setIsFullTime(worker.getIsFullTime()); + vo.setHighFloorFee(worker.getHighFloorFee()); + vo.setDeliveryLocation(worker.getDeliveryLocation()); + vo.setOrderTransferPendingCount(pendingCountMap.getOrDefault(worker.getWorkerId(), 0)); + records.add(vo); + } + IPage page = new Page<>(pageNum, pageSize, workerPage.getTotalElements()); + page.setRecords(records); + return page; + } + @RequestMapping(value = "/getOnlineWorkerByArea", method = RequestMethod.GET) @ApiOperation(value = "查询各食堂区域在线配送员数量") public Result> getOnlineWorkerByArea(@RequestParam(value = "parentId")String parentId) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java index f84d87bf..9eae8870 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java @@ -51,6 +51,12 @@ public interface MallDeliveryOrderMapper extends BaseMapper { long countAssignedWaitOrdersAdmin(@Param("q") MallDeliveryOrderPageQuery q); + long countTransferUnacceptedOrdersAdmin(@Param("q") MallDeliveryOrderPageQuery q); + + long countTransferPendingArriveOrdersAdmin(@Param("q") MallDeliveryOrderPageQuery q); + + List> countPendingTransferArriveOrdersByWorkerIds(@Param("workerIds") List workerIds); + List countOrdersLimit(@Param("regionId") String regionId); /** diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncProducer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncProducer.java index 84925e53..4f1c75c0 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncProducer.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncProducer.java @@ -18,7 +18,7 @@ import java.util.Set; @Slf4j @Component public class OrderAsyncProducer { - private static final long CLOUD_PRINT_INITIAL_DELAY_MILLIS = 5 * 1000L; + private static final long CLOUD_PRINT_INITIAL_DELAY_MILLIS = 2 * 1000L; @Autowired private RabbitTemplate rabbitTemplate; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java index 8a740788..1d7d8848 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java @@ -71,6 +71,12 @@ public class MallDeliveryOrderPageQuery extends HiverBasePageQuery { @ApiModelProperty("中转配送员ID") private String transferWorkerId; + @ApiModelProperty("是否只查询未指派中转配送员") + private Boolean transferWorkerEmpty; + + @ApiModelProperty("是否只查询已指派中转配送员") + private Boolean transferWorkerNotEmpty; + @ApiModelProperty("是否配送员中转接单视角") private Boolean transferWorkerView; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java index 266dc629..64e731e4 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java @@ -60,4 +60,7 @@ public class WorkerMatchVO { @ApiModelProperty("当前待送达数(status=2)") private Integer orderPutCount; + + @ApiModelProperty("当前待送达中转点订单数") + private Integer orderTransferPendingCount; } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java index 44ec7d78..eed60ede 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java @@ -1,16 +1,27 @@ package cc.hiver.mall.quartz; +import cc.hiver.core.common.redis.RedisTemplateHelper; +import cc.hiver.core.common.utils.SnowFlakeUtil; import cc.hiver.mall.entity.MallOrderGroup; +import cc.hiver.mall.entity.ProductGroupBuyPrice; +import cc.hiver.mall.entity.Shop; import cc.hiver.mall.planet.service.PlanetAdventurePkService; +import cc.hiver.mall.pojo.dto.ShopCacheDTO; +import cc.hiver.mall.pojo.vo.ProductPageVO; import cc.hiver.mall.service.mybatis.MallOrderGroupService; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.util.Date; -import java.util.List; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; /** * 拼团超时自动失败定时任务 @@ -20,17 +31,31 @@ import java.util.List; @Component public class GroupBuyExpireTask { + private static final String MOCK_REGION_ID = "2097949297042657280"; + private static final String SHOP_CACHE_PREFIX = "SHOP_CACHE:"; + private static final String SHOP_PRODUCTS_PREFIX = "SHOP_PRODUCTS:"; + private static final String SHOP_GROUP_ORDERS_PREFIX = "SHOP_GROUP_ORDERS:"; + private static final int MOCK_GROUP_SHOP_COUNT = 20; + private static final int MOCK_GROUP_TARGET_MEMBERS = 2; + private static final int SALE_SHOP_COUNT = 40; + private static final int SALE_INCREMENT_TOTAL = 100; + private static final long MOCK_GROUP_EXPIRE_MILLIS = 60 * 60 * 1000L; + @Autowired private MallOrderGroupService mallOrderGroupService; @Autowired private PlanetAdventurePkService planetAdventurePkService; + @Autowired + private RedisTemplateHelper redisTemplateHelper; + /** * 每5分钟执行一次 */ @Scheduled(cron = "0 0/5 * * * ?") public void expireOverdueGroups() { + refreshMockGroupOrderCache(); log.info("[拼团过期任务] 开始扫描超时拼团..."); try { LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); @@ -59,6 +84,40 @@ public class GroupBuyExpireTask { expireOverduePkRooms(); } + /** + * 每30分钟随机增加店铺列表和商品缓存销量,仅用于展示缓存假数据。 + */ + @Scheduled(cron = "0 0/30 * * * ?") + public void increaseMockShopSales() { + try { + Map shopCache = redisTemplateHelper.hGetAll(buildShopCacheKey(MOCK_REGION_ID)); + if (shopCache == null || shopCache.isEmpty()) { + log.info("[模拟销量任务] 区域 {} 无店铺缓存", MOCK_REGION_ID); + return; + } + + List> selectedShops = selectCachedShops(shopCache, SALE_SHOP_COUNT, true); + if (selectedShops.isEmpty()) { + log.info("[模拟销量任务] 区域 {} 无可用店铺缓存", MOCK_REGION_ID); + return; + } + + List increments = randomPositiveParts(SALE_INCREMENT_TOTAL, selectedShops.size()); + int updatedCount = 0; + int actualIncrement = 0; + for (int i = 0; i < selectedShops.size(); i++) { + if (increaseShopSaleCache(selectedShops.get(i), increments.get(i))) { + updatedCount++; + actualIncrement += increments.get(i); + } + } + log.info("[模拟销量任务] 区域 {} 已为 {} 个商家累计增加 {} 销量", + MOCK_REGION_ID, updatedCount, actualIncrement); + } catch (Exception e) { + log.error("[模拟销量任务] 执行异常: {}", e.getMessage(), e); + } + } + private void expireOverduePkRooms() { try { int settled = planetAdventurePkService.autoSettleOverdueRooms(); @@ -67,4 +126,259 @@ public class GroupBuyExpireTask { log.error("[拼团过期任务] 星球擂台超时结算异常: {}", e.getMessage(), e); } } + + private void refreshMockGroupOrderCache() { + try { + Map shopCache = redisTemplateHelper.hGetAll(buildShopCacheKey(MOCK_REGION_ID)); + if (shopCache == null || shopCache.isEmpty()) { + log.info("[模拟待成团任务] 区域 {} 无店铺缓存", MOCK_REGION_ID); + return; + } + + clearRegionShopGroupOrderCache(shopCache); + List> selectedShops = selectCachedShops(shopCache, shopCache.size(), false); + int mockCount = 0; + for (Map.Entry shopEntry : selectedShops) { + if (mockCount >= MOCK_GROUP_SHOP_COUNT) { + break; + } + ShopCacheDTO cacheDTO = parseShopCacheDTO(shopEntry.getValue()); + Shop shop = cacheDTO == null ? null : cacheDTO.getShop(); + String shopId = getShopId(shopEntry); + if (shop == null || StringUtils.isBlank(shopId)) { + continue; + } + + List products = loadVisibleGroupBuyProducts(shopId); + if (products.isEmpty()) { + continue; + } + + ProductPageVO product = products.get(ThreadLocalRandom.current().nextInt(products.size())); + MallOrderGroup mockGroup = buildMockGroup(shopId, shop.getShopName(), product); + String json = JSONUtil.toJsonStr(mockGroup); + redisTemplateHelper.hPut(buildShopGroupOrdersKey(shopId), mockGroup.getId(), json); + mockCount++; + } + log.info("[模拟待成团任务] 区域 {} 已刷新 {} 个店铺待成团缓存", MOCK_REGION_ID, mockCount); + } catch (Exception e) { + log.error("[模拟待成团任务] 执行异常: {}", e.getMessage(), e); + } + } + + private void clearRegionShopGroupOrderCache(Map shopCache) { + List keys = new ArrayList<>(); + for (Object shopIdObj : shopCache.keySet()) { + String shopId = shopIdObj == null ? null : shopIdObj.toString(); + if (StringUtils.isNotBlank(shopId)) { + keys.add(buildShopGroupOrdersKey(shopId)); + } + } + if (!keys.isEmpty()) { + redisTemplateHelper.delete(keys); + } + } + + private List> selectCachedShops(Map shopCache, int limit, boolean requireProducts) { + List> entries = new ArrayList<>(shopCache.entrySet()); + Collections.shuffle(entries); + + List> selected = new ArrayList<>(); + for (Map.Entry entry : entries) { + if (selected.size() >= limit) { + break; + } + String shopId = getShopId(entry); + ShopCacheDTO cacheDTO = parseShopCacheDTO(entry.getValue()); + if (StringUtils.isNotBlank(shopId) + && cacheDTO != null + && cacheDTO.getShop() != null + && (!requireProducts || hasVisibleProductCache(shopId))) { + selected.add(entry); + } + } + return selected; + } + + private boolean increaseShopSaleCache(Map.Entry shopEntry, int increment) { + String shopId = getShopId(shopEntry); + ShopCacheDTO cacheDTO = parseShopCacheDTO(shopEntry.getValue()); + if (StringUtils.isBlank(shopId) || cacheDTO == null || cacheDTO.getShop() == null || increment <= 0) { + return false; + } + + Shop shop = cacheDTO.getShop(); + int oldSaleCount = shop.getSaleCount() == null ? 0 : shop.getSaleCount(); + if (!increaseProductTailWarnCache(shopId, increment)) { + return false; + } + shop.setSaleCount(oldSaleCount + increment); + redisTemplateHelper.hPut(buildShopCacheKey(MOCK_REGION_ID), shopId, JSONUtil.toJsonStr(cacheDTO)); + return true; + } + + private boolean increaseProductTailWarnCache(String shopId, int totalIncrement) { + String productsKey = SHOP_PRODUCTS_PREFIX + shopId; + String productsJson = redisTemplateHelper.get(productsKey); + if (StringUtils.isBlank(productsJson) || totalIncrement <= 0) { + return false; + } + + try { + JSONArray productArray = JSONUtil.parseArray(productsJson); + if (productArray.isEmpty()) { + return false; + } + + List productIndexes = new ArrayList<>(); + for (int i = 0; i < productArray.size(); i++) { + JSONObject productObj = productArray.getJSONObject(i); + if (productObj != null && Integer.valueOf(1).equals(productObj.getInt("delFlag", 1))) { + productIndexes.add(i); + } + } + if (productIndexes.isEmpty()) { + return false; + } + + Collections.shuffle(productIndexes); + int productCount = Math.min(productIndexes.size(), totalIncrement); + List productIncrements = randomPositiveParts(totalIncrement, productCount); + for (int i = 0; i < productCount; i++) { + JSONObject productObj = productArray.getJSONObject(productIndexes.get(i)); + int oldTailWarn = productObj.getInt("tailWarn", 0); + productObj.set("tailWarn", oldTailWarn + productIncrements.get(i)); + } + redisTemplateHelper.set(productsKey, productArray.toString()); + return true; + } catch (Exception e) { + log.warn("[模拟销量任务] 更新商品销量缓存失败 shopId={}: {}", shopId, e.getMessage()); + return false; + } + } + + private boolean hasVisibleProductCache(String shopId) { + return !loadVisibleProducts(shopId).isEmpty(); + } + + private List loadVisibleProducts(String shopId) { + String productsJson = redisTemplateHelper.get(SHOP_PRODUCTS_PREFIX + shopId); + if (StringUtils.isBlank(productsJson)) { + return Collections.emptyList(); + } + + try { + List products = JSONUtil.toList(productsJson, ProductPageVO.class); + if (products == null || products.isEmpty()) { + return Collections.emptyList(); + } + List visibleProducts = new ArrayList<>(); + for (ProductPageVO product : products) { + if (product != null + && StringUtils.isNotBlank(product.getId()) + && StringUtils.isNotBlank(product.getProductName()) + && Integer.valueOf(1).equals(product.getDelFlag())) { + visibleProducts.add(product); + } + } + return visibleProducts; + } catch (Exception e) { + log.warn("[模拟待成团任务] 读取商品缓存失败 shopId={}: {}", shopId, e.getMessage()); + return Collections.emptyList(); + } + } + + private MallOrderGroup buildMockGroup(String shopId, String shopName, ProductPageVO product) { + String orderId = SnowFlakeUtil.nextId().toString(); + MallOrderGroup group = new MallOrderGroup(); + group.setId(SnowFlakeUtil.nextId().toString()); + group.setShopId(shopId); + group.setShopName(shopName); + group.setRegionId(MOCK_REGION_ID); + group.setHeadUserId("2092548901814013952"); + group.setHeadOrderId(orderId); + group.setGroupOrderIds(orderId); + group.setTargetMembers(MOCK_GROUP_TARGET_MEMBERS); + group.setCurrentMembers(1); + group.setIsFace(0); + group.setStatus(0); + group.setGroupPrice(getTwoMemberGroupPrice(product)); + group.setWorkerCommission(new BigDecimal("0.01")); + group.setTotalDeliveryFee(BigDecimal.ZERO); + group.setCreateTime(new Date()); + group.setExpireTime(new Date(System.currentTimeMillis() + MOCK_GROUP_EXPIRE_MILLIS)); + group.setProductName(product.getProductName()); + group.setProductPicture(product.getProductPicture()); + group.setProductId(product.getId()); + return group; + } + + private List loadVisibleGroupBuyProducts(String shopId) { + List products = loadVisibleProducts(shopId); + if (products.isEmpty()) { + return Collections.emptyList(); + } + + List groupBuyProducts = new ArrayList<>(); + for (ProductPageVO product : products) { + if (getTwoMemberGroupPrice(product) != null) { + groupBuyProducts.add(product); + } + } + return groupBuyProducts; + } + + private BigDecimal getTwoMemberGroupPrice(ProductPageVO product) { + if (product != null && product.getProductGroupBuyPrices() != null) { + for (ProductGroupBuyPrice price : product.getProductGroupBuyPrices()) { + if (price != null + && Integer.valueOf(MOCK_GROUP_TARGET_MEMBERS).equals(price.getGroupCount()) + && price.getGroupPrice() != null) { + return price.getGroupPrice(); + } + } + } + return null; + } + + private List randomPositiveParts(int total, int count) { + if (total <= 0 || count <= 0) { + return Collections.emptyList(); + } + int actualCount = Math.min(total, count); + List parts = new ArrayList<>(actualCount); + for (int i = 0; i < actualCount; i++) { + parts.add(1); + } + for (int remaining = total - actualCount; remaining > 0; remaining--) { + int index = ThreadLocalRandom.current().nextInt(actualCount); + parts.set(index, parts.get(index) + 1); + } + Collections.shuffle(parts); + return parts; + } + + private ShopCacheDTO parseShopCacheDTO(Object value) { + if (value == null) { + return null; + } + try { + return JSONUtil.toBean(value.toString(), ShopCacheDTO.class); + } catch (Exception e) { + log.warn("[模拟缓存任务] 店铺缓存解析失败: {}", e.getMessage()); + return null; + } + } + + private String getShopId(Map.Entry shopEntry) { + return shopEntry == null || shopEntry.getKey() == null ? null : shopEntry.getKey().toString(); + } + + private String buildShopCacheKey(String regionId) { + return SHOP_CACHE_PREFIX + regionId; + } + + private String buildShopGroupOrdersKey(String shopId) { + return SHOP_GROUP_ORDERS_PREFIX + shopId; + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java index 22b0b695..3b6e6f0f 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java @@ -98,6 +98,12 @@ public interface MallDeliveryOrderService extends IService { long countAssignedWaitOrdersAdmin(MallDeliveryOrderPageQuery q); + long countTransferUnacceptedOrdersAdmin(MallDeliveryOrderPageQuery q); + + long countTransferPendingArriveOrdersAdmin(MallDeliveryOrderPageQuery q); + + Map countPendingTransferArriveOrdersByWorkerIds(List workerIds); + List> countOrdersByStatus(String workerId,String regionId); List> countOrdersByStatus1(String workerId,String regionId); 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 794dff14..d167fb06 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 @@ -185,13 +185,12 @@ public class ShopServiceImpl implements ShopService { final Predicate[] arr = new Predicate[list.size()]; cq.where(list.toArray(arr)); - if (adminQuery) { + if (adminQuery && !isCountQuery(cq)) { List orderList = new ArrayList<>(); - 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)); + Expression disabledStatusOrder = cb.selectCase() + .when(cb.equal(statusField, ShopConstant.SHOP_STATUS_LOCK), 1) + .otherwise(0); + orderList.add(cb.asc(disabledStatusOrder)); Sort.Order shoprankOrder = null; for (Sort.Order order : pageSort) { if ("shoprank".equals(order.getProperty())) { @@ -204,7 +203,7 @@ public class ShopServiceImpl implements ShopService { ? cb.asc(shoprankField) : cb.desc(shoprankField)); for (Sort.Order order : pageSort) { - if ("status".equals(order.getProperty()) || "shoprank".equals(order.getProperty())) { + if ("shoprank".equals(order.getProperty())) { continue; } Path sortField = root.get(order.getProperty()); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java index 3c979bea..0fa9f880 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java @@ -1200,6 +1200,36 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl countPendingTransferArriveOrdersByWorkerIds(List workerIds) { + Map countMap = new HashMap<>(); + if (workerIds == null || workerIds.isEmpty()) { + return countMap; + } + List> rows = this.baseMapper.countPendingTransferArriveOrdersByWorkerIds(workerIds); + if (rows == null) { + return countMap; + } + for (Map row : rows) { + if (row == null || row.get("workerId") == null) { + continue; + } + Object count = row.get("orderCount"); + countMap.put(String.valueOf(row.get("workerId")), count == null ? 0 : Integer.parseInt(String.valueOf(count))); + } + return countMap; + } + @Override public List> countOrdersByStatus(String workerId,String regionId) { List> returnList = new ArrayList<>(); diff --git a/hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml b/hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml index 95b7b3ec..4e838599 100644 --- a/hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml +++ b/hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml @@ -386,6 +386,16 @@ AND d.transfer_arrive_time IS NULL + + AND d.transfer_delivery = 1 + AND (d.transfer_worker_id IS NULL OR d.transfer_worker_id = '') + + + AND d.transfer_delivery = 1 + AND d.transfer_arrive_time IS NULL + AND d.transfer_worker_id IS NOT NULL + AND d.transfer_worker_id != '' + @@ -572,6 +582,100 @@ + + + + + +