diff --git a/hiver-admin/src/main/resources/application.yml b/hiver-admin/src/main/resources/application.yml index a96ad229..92ef6bc9 100644 --- a/hiver-admin/src/main/resources/application.yml +++ b/hiver-admin/src/main/resources/application.yml @@ -442,6 +442,7 @@ ignored: - /hiver/mall/delivery/page - /hiver/app/shopArea/getByParentId/** - /hiver/app/shopArea/matchByLocation + - /hiver/app/shopArea/transferDeliverySwitch/get - /hiver/mall/delivery/countOrderByStatus - /hiver/mall/admin/orderGroup/page - /hiver/mall/order/countByShop/** @@ -479,6 +480,7 @@ ignored: # 获取微信二维码 - /hiver/order/ow/getWechatQrcode - /hiver/app/shop/getShopInfoById + - /hiver/app/shop/gateLocation/list - /hiver/app/purchaseReturn/getPurchaseReturnById - /hiver/app/purchase/getPurchaseAllData - /hiver/app/dealingRecord/getDealingsRecordList diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index 14b1cb3a..ae6e26bc 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -ʮһÔÂ 11, 2026 00:26:01 +ʮһÔÂ 12, 2026 09:26:52
  • @@ -84,7 +84,7 @@

    passTest

    -

    00:26:02 ÉÏÎç / 0.033 secs

    +

    09:26:52 ÉÏÎç / 0.024 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -11.11.2026 00:26:02 -11.11.2026 00:26:02 -0.033 secs +11.12.2026 09:26:52 +11.12.2026 09:26:52 +0.024 secs
    @@ -104,7 +104,7 @@ Pass - 0:26:02 + 9:26:52 Test passed @@ -128,13 +128,13 @@

    Started

    -

    ʮһÔÂ 11, 2026 00:26:01

    +

    ʮһÔÂ 12, 2026 09:26:52

    Ended

    -

    ʮһÔÂ 11, 2026 00:26:02

    +

    ʮһÔÂ 12, 2026 09:26:52

    diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java index 0759cd06..670a6973 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopAreaController.java @@ -219,6 +219,42 @@ public class ShopAreaController { return ResultUtil.success("保存成功"); } + private static final String TARGET_TRANSFER_DELIVERY_REGION_ID = "2110300467664916480"; + + @RequestMapping(value = "/transferDeliverySwitch/get", method = RequestMethod.GET) + @ApiOperation(value = "根据校区ID查询中转配送开关") + public Result getTransferDeliverySwitch(@RequestParam String regionId) { + if (!TARGET_TRANSFER_DELIVERY_REGION_ID.equals(regionId)) { + return new ResultUtil().setData(1); + } + ShopArea shopArea = shopAreaService.get(regionId); + if (shopArea == null) { + return ResultUtil.error("校区不存在"); + } + Integer transferDeliveryEnabled = shopArea.getTransferDeliveryEnabled() == null ? 1 : shopArea.getTransferDeliveryEnabled(); + return new ResultUtil().setData(transferDeliveryEnabled); + } + + @RequestMapping(value = "/transferDeliverySwitch/update", method = RequestMethod.POST) + @ApiOperation(value = "根据校区ID更新中转配送开关") + public Result updateTransferDeliverySwitch(@RequestParam String regionId, @RequestParam Integer transferDeliveryEnabled) { + if (!TARGET_TRANSFER_DELIVERY_REGION_ID.equals(regionId)) { + return ResultUtil.error("当前区域不支持中转配送设置"); + } + if (transferDeliveryEnabled == null || (transferDeliveryEnabled != 0 && transferDeliveryEnabled != 1)) { + return ResultUtil.error("中转配送开关参数错误"); + } + ShopArea shopArea = shopAreaService.get(regionId); + if (shopArea == null) { + return ResultUtil.error("校区不存在"); + } + shopArea.setTransferDeliveryEnabled(transferDeliveryEnabled); + ShopArea updated = shopAreaService.update(shopArea); + shopAreaService.refreshShopAreaCache(updated.getParentId(), updated.getId()); + redisTemplate.deleteByPattern("ShopArea:*"); + return ResultUtil.success("保存成功"); + } + @RequestMapping(value = "/delByIds", method = RequestMethod.POST) @ApiOperation(value = "批量通过id删除") public Result delByIds(@RequestParam String[] ids) { 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 0022fa8b..79b5b36a 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 @@ -29,10 +29,8 @@ import cc.hiver.core.entity.User; import cc.hiver.core.entity.Worker; import cc.hiver.core.service.UserService; import cc.hiver.core.service.WorkerService; -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.dao.ShopGateLocationDao; +import cc.hiver.mall.entity.*; import cc.hiver.mall.invitelog.service.InviteLogService; import cc.hiver.mall.pojo.dto.ShopCacheDTO; import cc.hiver.mall.pojo.dto.ShopRevenue; @@ -78,6 +76,7 @@ import java.util.stream.Collectors; @Api(tags = "店铺管理接口") @RequestMapping("/hiver/app/shop/") public class ShopController { + private static final String TARGET_GATE_LOCATION_REGION_ID = "2110300467664916480"; 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 DateTimeFormatter BUSINESS_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); @@ -87,6 +86,9 @@ public class ShopController { @Autowired private ShopService shopService; + @Autowired + private ShopGateLocationDao shopGateLocationDao; + @Autowired private ShopAreaService shopAreaService; @@ -498,6 +500,83 @@ public class ShopController { return ResultUtil.success("编辑成功"); } + @RequestMapping(value = "/gateLocation/list", method = RequestMethod.GET) + @ApiOperation("查询商家送达地点") + public Result> listGateLocation(@RequestParam String shopId) { + Shop shop = requireTargetGateLocationShop(shopId); + if (shop == null) { + return ResultUtil.error("当前区域不支持送达地点"); + } + return new ResultUtil>().setData(shopGateLocationDao.findByShopIdOrderByCreateTimeAsc(shopId)); + } + + @RequestMapping(value = "/gateLocation/save", method = RequestMethod.POST) + @ApiOperation("新增或编辑商家送达地点") + public Result saveGateLocation(@RequestParam String shopId, + @RequestParam(required = false) String id, + @RequestParam String locationName) { + Shop shop = requireTargetGateLocationShop(shopId); + if (shop == null) { + return ResultUtil.error("当前区域不支持送达地点"); + } + String name = locationName == null ? "" : locationName.trim(); + if (CharSequenceUtil.isBlank(name)) { + return ResultUtil.error("请输入送达地点"); + } + if (name.length() > 50) { + return ResultUtil.error("送达地点不能超过50个字"); + } + List exists = shopGateLocationDao.findByShopIdOrderByCreateTimeAsc(shopId); + for (ShopGateLocation item : exists) { + if (name.equals(item.getLocationName()) && (CharSequenceUtil.isBlank(id) || !id.equals(item.getId()))) { + return ResultUtil.error("送达地点已存在"); + } + } + if (CharSequenceUtil.isNotBlank(id)) { + ShopGateLocation old = shopGateLocationDao.findById(id).orElse(null); + if (old == null || !shopId.equals(old.getShopId())) { + return ResultUtil.error("送达地点不存在"); + } + old.setLocationName(name); + shopGateLocationDao.save(old); + return ResultUtil.success("保存成功"); + } + ShopGateLocation location = new ShopGateLocation(); + location.setShopId(shopId); + location.setLocationName(name); + shopGateLocationDao.save(location); + return ResultUtil.success("保存成功"); + } + + @RequestMapping(value = "/gateLocation/delete", method = RequestMethod.POST) + @ApiOperation("删除商家送达地点") + public Result deleteGateLocation(@RequestParam String id) { + if (CharSequenceUtil.isBlank(id)) { + return ResultUtil.error("送达地点不存在"); + } + ShopGateLocation old = shopGateLocationDao.findById(id).orElse(null); + if (old == null) { + return ResultUtil.error("送达地点不存在"); + } + Shop shop = requireTargetGateLocationShop(old.getShopId()); + if (shop == null) { + return ResultUtil.error("当前区域不支持送达地点"); + } + shopGateLocationDao.deleteById(id); + return ResultUtil.success("删除成功"); + } + + private Shop requireTargetGateLocationShop(String shopId) { + if (CharSequenceUtil.isBlank(shopId)) { + return null; + } + Shop shop = shopService.findById(shopId); + if (shop == null || !TARGET_GATE_LOCATION_REGION_ID.equals(String.valueOf(shop.getRegionId()))) { + return null; + } + return shop; + } + @RequestMapping(value = "/findWorkerByMobile", method = RequestMethod.GET) @ApiOperation("根据手机号查询配送员") public Result> findWorkerByMobile(@RequestParam String mobile) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/ShopGateLocationDao.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/ShopGateLocationDao.java new file mode 100644 index 00000000..4ec69eb1 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/ShopGateLocationDao.java @@ -0,0 +1,10 @@ +package cc.hiver.mall.dao; + +import cc.hiver.core.base.HiverBaseDao; +import cc.hiver.mall.entity.ShopGateLocation; + +import java.util.List; + +public interface ShopGateLocationDao extends HiverBaseDao { + List findByShopIdOrderByCreateTimeAsc(String shopId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopArea.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopArea.java index 051c89fd..7191a1ed 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopArea.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopArea.java @@ -55,6 +55,10 @@ public class ShopArea extends HiverBaseEntity { @Column(nullable = false, columnDefinition = "int default 1") private Integer deliveryEnabled = 1; + @ApiModelProperty(value = "是否开启中转配送:1开启,0关闭。仅指定区域使用") + @Column(nullable = false, columnDefinition = "int default 1") + private Integer transferDeliveryEnabled = 1; + @ApiModelProperty(value = "上级代理id") private String parentAgentId; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopGateLocation.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopGateLocation.java new file mode 100644 index 00000000..b370eff8 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/ShopGateLocation.java @@ -0,0 +1,38 @@ +package cc.hiver.mall.entity; + +import cc.hiver.core.base.HiverBaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Index; +import javax.persistence.Table; + +/** + * 指定区域商家送到大门时的送达地点。 + */ +@Data +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "t_shop_gate_location", indexes = { + @Index(name = "idx_shop_gate_location_shop_id", columnList = "shop_id") +}) +@TableName("t_shop_gate_location") +@ApiModel(value = "商家送达地点") +public class ShopGateLocation extends HiverBaseEntity { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "店铺id") + @Column(name = "shop_id", nullable = false, length = 64) + private String shopId; + + @ApiModelProperty(value = "送达地点名称") + @Column(name = "location_name", nullable = false, length = 50) + private String locationName; +} 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 d93be99d..b48844ef 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 @@ -85,9 +85,7 @@ public final class DaQuReceiptRenderUtil { if (order.getGoodsList() != null) { for (MallOrderGoods goods : order.getGoodsList()) { largeLeft(sb, defaultString(goods.getProductName())); - if (StringUtils.contains(goods.getSpecs(), ",")) { - boldLeft(sb, delNode(goods.getSpecs())); - } + appendSpecs(sb, goods.getSpecs()); largeLeft(sb, "¥" + amount(goods.getPrice()) + " X" + safeQuantity(goods.getQuantity())); } } @@ -134,9 +132,7 @@ public final class DaQuReceiptRenderUtil { separator(sb); for (MallReturnOrderGoods goods : refund.getItems()) { largeLeft(sb, defaultString(goods.getProductName())); - if (StringUtils.contains(goods.getSpecs(), ",")) { - boldLeft(sb, delNode(goods.getSpecs())); - } + appendSpecs(sb, goods.getSpecs()); largeLeft(sb, "¥" + amount(goods.getPrice()) + " X" + safeQuantity(goods.getQuantity())); } } @@ -364,6 +360,14 @@ public final class DaQuReceiptRenderUtil { return date == null ? "" : new SimpleDateFormat(APPOINTMENT_TIME_PATTERN).format(date); } + private static void appendSpecs(StringBuilder sb, String specs) { + String text = delNode(specs).trim(); + if (StringUtils.isBlank(text)) { + return; + } + boldLeft(sb, text); + } + private static String delNode(String text) { return defaultString(text).replace("{", "").replace("}", "").replace("\"", ""); } diff --git a/hiver-modules/hiver-mall/src/main/resources/db/shop_area_transfer_delivery_enabled.sql b/hiver-modules/hiver-mall/src/main/resources/db/shop_area_transfer_delivery_enabled.sql new file mode 100644 index 00000000..79bd3ca2 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/resources/db/shop_area_transfer_delivery_enabled.sql @@ -0,0 +1,2 @@ +ALTER TABLE `t_shop_area` + ADD COLUMN `transfer_delivery_enabled` int(11) NOT NULL DEFAULT 1 COMMENT '是否开启中转配送:1开启,0关闭'; diff --git a/hiver-modules/hiver-mall/src/main/resources/db/shop_gate_location.sql b/hiver-modules/hiver-mall/src/main/resources/db/shop_gate_location.sql new file mode 100644 index 00000000..03697849 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/resources/db/shop_gate_location.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS `t_shop_gate_location` ( + `id` varchar(64) NOT NULL COMMENT '唯一标识', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(255) DEFAULT NULL COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int(11) DEFAULT 0 COMMENT '删除标志 默认0', + `shop_id` varchar(64) NOT NULL COMMENT '店铺id', + `location_name` varchar(50) NOT NULL COMMENT '送达地点名称', + PRIMARY KEY (`id`), + KEY `idx_shop_gate_location_shop_id` (`shop_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商家送达地点';