From 2aa950e5f4168c66069aaaae2c847d796f97e596 Mon Sep 17 00:00:00 2001 From: Kroytz Date: Thu, 16 Jul 2026 00:22:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B6=B3=E9=A2=9D=E5=85=8D=E9=85=8D?= =?UTF-8?q?=E9=80=81=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/upgrade_free_delivery_amount.sql | 3 +++ yshop-drink-boot3/sql/yixiang-drink-open.sql | 5 ++-- .../storeorder/AppStoreOrderServiceImpl.java | 3 +++ .../admin/storeshop/vo/StoreShopBaseVO.java | 4 +++ .../app/storeshop/AppStoreController.java | 6 +++-- .../app/storeshop/vo/AppStoreShopVO.java | 3 +++ .../dal/dataobject/storeshop/StoreShopDO.java | 4 +++ .../storeshop/AppStoreShopService.java | 3 ++- .../storeshop/AppStoreShopServiceImpl.java | 5 ++-- .../service/storeshop/DeliveryCalculator.java | 8 ++++++ .../storeshop/DeliveryCalculatorTest.java | 25 +++++++++++++++++++ .../pages/components/pages/pay/pay.vue | 5 ++-- .../src/api/mall/store/shop/index.ts | 1 + .../src/views/mall/store/shop/ShopForm.vue | 6 +++++ 14 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 yshop-drink-boot3/sql/upgrade_free_delivery_amount.sql create mode 100644 yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/test/java/co/yixiang/yshop/module/store/service/storeshop/DeliveryCalculatorTest.java diff --git a/yshop-drink-boot3/sql/upgrade_free_delivery_amount.sql b/yshop-drink-boot3/sql/upgrade_free_delivery_amount.sql new file mode 100644 index 0000000..9439367 --- /dev/null +++ b/yshop-drink-boot3/sql/upgrade_free_delivery_amount.sql @@ -0,0 +1,3 @@ +ALTER TABLE `yshop_store_shop` + ADD COLUMN `free_delivery_amount` decimal(10,2) NOT NULL DEFAULT '0.00' + COMMENT '满额免配送费门槛,0表示不启用' AFTER `delivery_rules`; diff --git a/yshop-drink-boot3/sql/yixiang-drink-open.sql b/yshop-drink-boot3/sql/yixiang-drink-open.sql index 1049777..d9fc8c3 100644 --- a/yshop-drink-boot3/sql/yixiang-drink-open.sql +++ b/yshop-drink-boot3/sql/yixiang-drink-open.sql @@ -13702,6 +13702,7 @@ CREATE TABLE `yshop_store_shop` ( `min_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '起送价钱', `delivery_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '配送价格', `delivery_rules` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '配送规则JSON:[{minKm,maxKm,price}]', + `free_delivery_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '满额免配送费门槛,0表示不启用', `notice` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '公告', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否营业:0=否,1=是', `admin_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '管理员id', @@ -13718,8 +13719,8 @@ CREATE TABLE `yshop_store_shop` ( -- Records of yshop_store_shop -- ---------------------------- BEGIN; -INSERT INTO `yshop_store_shop` VALUES (2, '意向餐饮店', '18000000000', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', '源汇区人民东路', '河南省漯河市源汇区团结路50号-20', '2023-08-19 09:00:00', '2023-08-19 23:00:00', '114.04877877439665', '33.57093831826829', 10, 10.00, 20.00, '[{"minKm":0,"maxKm":3,"price":8},{"minKm":3,"maxKm":5,"price":12},{"minKm":5,"maxKm":10,"price":18}]', '新店开张', 1, '126', '1', '2023-08-06 11:48:43', '2023-09-14 17:30:59', '1', '1', b'0'); -INSERT INTO `yshop_store_shop` VALUES (3, 'yshop', '18000000000', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', '67号', '北京市东城区', '2023-08-06 13:35:02', '2023-08-06 15:35:02', '116.40403593222032', '39.91643892263258', 0, 1.00, 2.00, NULL, '2222', 1, '100', '2', '2023-08-06 13:14:53', '2024-03-26 15:42:20', '1', '1', b'0'); +INSERT INTO `yshop_store_shop` VALUES (2, '意向餐饮店', '18000000000', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', '源汇区人民东路', '河南省漯河市源汇区团结路50号-20', '2023-08-19 09:00:00', '2023-08-19 23:00:00', '114.04877877439665', '33.57093831826829', 10, 10.00, 20.00, '[{"minKm":0,"maxKm":3,"price":8},{"minKm":3,"maxKm":5,"price":12},{"minKm":5,"maxKm":10,"price":18}]', 0.00, '新店开张', 1, '126', '1', '2023-08-06 11:48:43', '2023-09-14 17:30:59', '1', '1', b'0'); +INSERT INTO `yshop_store_shop` VALUES (3, 'yshop', '18000000000', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', 'https://apidc.yixiang.co/admin-api/infra/file/4/get/44723283500f656cdd5906e13f2997cb292d17f516065ff4b3b38f9810bce4cb.jpg', '67号', '北京市东城区', '2023-08-06 13:35:02', '2023-08-06 15:35:02', '116.40403593222032', '39.91643892263258', 0, 1.00, 2.00, NULL, 0.00, '2222', 1, '100', '2', '2023-08-06 13:14:53', '2024-03-26 15:42:20', '1', '1', b'0'); COMMIT; -- ---------------------------- diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/AppStoreOrderServiceImpl.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/AppStoreOrderServiceImpl.java index babda71..9768d40 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/AppStoreOrderServiceImpl.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/AppStoreOrderServiceImpl.java @@ -234,6 +234,9 @@ public class AppStoreOrderServiceImpl extends ServiceImpl deliveryRules; + @Schema(description = "满额免配送费门槛,0或空表示不启用", example = "50") + @DecimalMin(value = "0", message = "免配送费门槛不能小于0") + private BigDecimal freeDeliveryAmount; + @Schema(description = "公告", required = true) @NotNull(message = "公告不能为空") private String notice; diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/AppStoreController.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/AppStoreController.java index ba6d7c2..d584376 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/AppStoreController.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/AppStoreController.java @@ -24,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.math.BigDecimal; import java.util.List; import static co.yixiang.yshop.framework.common.pojo.CommonResult.success; @@ -80,8 +81,9 @@ public class AppStoreController { @Operation(summary = "预估配送费") public CommonResult getDeliveryFee(@RequestParam("shopId") Long shopId, @RequestParam("lng") double lng, - @RequestParam("lat") double lat) { - return success(appStoreShopService.getDeliveryFee(shopId, lng, lat)); + @RequestParam("lat") double lat, + @RequestParam(value = "amount", required = false) BigDecimal amount) { + return success(appStoreShopService.getDeliveryFee(shopId, lng, lat, amount)); } diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/vo/AppStoreShopVO.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/vo/AppStoreShopVO.java index eeaefd3..892cab7 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/vo/AppStoreShopVO.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/controller/app/storeshop/vo/AppStoreShopVO.java @@ -57,6 +57,9 @@ public class AppStoreShopVO { @Schema(description = "配送规则JSON文本", example = "[{\"minKm\":1,\"maxKm\":3,\"price\":8}]") private String deliveryRules; + @Schema(description = "满额免配送费门槛,0或空表示不启用", example = "50") + private BigDecimal freeDeliveryAmount; + @Schema(description = "公告", required = true) private String notice; diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/dal/dataobject/storeshop/StoreShopDO.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/dal/dataobject/storeshop/StoreShopDO.java index 6427d19..7f0bb5f 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/dal/dataobject/storeshop/StoreShopDO.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/dal/dataobject/storeshop/StoreShopDO.java @@ -84,6 +84,10 @@ public class StoreShopDO extends BaseDO { */ @TableField(typeHandler = DeliveryRuleListTypeHandler.class) private List deliveryRules; + /** + * 满额免配送费门槛,0或空表示不启用 + */ + private BigDecimal freeDeliveryAmount; /** * 公告 */ diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopService.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopService.java index 90783fc..fe83415 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopService.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopService.java @@ -5,6 +5,7 @@ import co.yixiang.yshop.module.store.controller.app.storeshop.vo.DeliveryFeeResp import co.yixiang.yshop.module.store.dal.dataobject.storeshop.StoreShopDO; import com.baomidou.mybatisplus.extension.service.IService; +import java.math.BigDecimal; import java.util.List; /** @@ -30,6 +31,6 @@ public interface AppStoreShopService extends IService { * @param lat 收货地址纬度 * @return 配送费及是否超出配送范围 */ - DeliveryFeeRespVO getDeliveryFee(Long shopId, double lng, double lat); + DeliveryFeeRespVO getDeliveryFee(Long shopId, double lng, double lat, BigDecimal amount); } diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopServiceImpl.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopServiceImpl.java index c66c2e7..b1a46f1 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopServiceImpl.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/main/java/co/yixiang/yshop/module/store/service/storeshop/AppStoreShopServiceImpl.java @@ -38,7 +38,7 @@ public class AppStoreShopServiceImpl extends ServiceImpl 0 && orderAmount.compareTo(threshold) >= 0 + ? BigDecimal.ZERO : deliveryPrice; + } + } diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/test/java/co/yixiang/yshop/module/store/service/storeshop/DeliveryCalculatorTest.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/test/java/co/yixiang/yshop/module/store/service/storeshop/DeliveryCalculatorTest.java new file mode 100644 index 0000000..3aaa75d --- /dev/null +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-store-biz/src/test/java/co/yixiang/yshop/module/store/service/storeshop/DeliveryCalculatorTest.java @@ -0,0 +1,25 @@ +package co.yixiang.yshop.module.store.service.storeshop; + +import co.yixiang.yshop.module.store.dal.dataobject.storeshop.StoreShopDO; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class DeliveryCalculatorTest { + + @Test + void applyFreeDeliveryUsesConfiguredThreshold() { + StoreShopDO shop = StoreShopDO.builder() + .freeDeliveryAmount(new BigDecimal("30")) + .build(); + BigDecimal fee = new BigDecimal("8"); + + assertEquals(fee, DeliveryCalculator.applyFreeDelivery(shop, new BigDecimal("29.99"), fee)); + assertEquals(BigDecimal.ZERO, + DeliveryCalculator.applyFreeDelivery(shop, new BigDecimal("30"), fee)); + assertNull(DeliveryCalculator.applyFreeDelivery(shop, new BigDecimal("30"), null)); + } +} diff --git a/yshop-drink-uniapp-vue3/pages/components/pages/pay/pay.vue b/yshop-drink-uniapp-vue3/pages/components/pages/pay/pay.vue index e4815b2..ad825ad 100644 --- a/yshop-drink-uniapp-vue3/pages/components/pages/pay/pay.vue +++ b/yshop-drink-uniapp-vue3/pages/components/pages/pay/pay.vue @@ -163,7 +163,7 @@ const amount = computed(() =>{ }) // 选地址/切换外卖后预估配送费(基于收货地址距离匹配配送规则) -watch([address, store, orderType], async () => { +watch([address, store, orderType, total], async () => { if (orderType.value !== 'takeout' || !store.value.id) { deliveryFee.value = 0 outOfRange.value = false @@ -183,7 +183,8 @@ watch([address, store, orderType], async () => { const res = await getDeliveryFee({ shopId: store.value.id, lng: address.value.longitude, - lat: address.value.latitude + lat: address.value.latitude, + amount: total.value.toFixed(2) }) outOfRange.value = !!res.outOfRange deliveryFee.value = parseFloat(res.deliveryPrice) || 0 diff --git a/yshop-drink-vue3/src/api/mall/store/shop/index.ts b/yshop-drink-vue3/src/api/mall/store/shop/index.ts index 6219acc..2721f05 100644 --- a/yshop-drink-vue3/src/api/mall/store/shop/index.ts +++ b/yshop-drink-vue3/src/api/mall/store/shop/index.ts @@ -20,6 +20,7 @@ export interface ShopVO { minPrice: number deliveryPrice: number deliveryRules: DeliveryRule[] + freeDeliveryAmount?: number notice: string status: boolean adminId: string diff --git a/yshop-drink-vue3/src/views/mall/store/shop/ShopForm.vue b/yshop-drink-vue3/src/views/mall/store/shop/ShopForm.vue index 271a30f..0a0305b 100644 --- a/yshop-drink-vue3/src/views/mall/store/shop/ShopForm.vue +++ b/yshop-drink-vue3/src/views/mall/store/shop/ShopForm.vue @@ -49,6 +49,10 @@ + + + 元,0或不填表示不启用 +
@@ -127,6 +131,7 @@ const formData = ref({ minPrice: undefined, deliveryPrice: undefined, deliveryRules: [], + freeDeliveryAmount: undefined, notice: undefined, status: undefined, adminId: undefined, @@ -278,6 +283,7 @@ const resetForm = () => { minPrice: undefined, deliveryPrice: undefined, deliveryRules: [], + freeDeliveryAmount: undefined, notice: undefined, status: 1, adminId: undefined,