Commit 1f910992d6a8f5aa5b24dc652bde62de9b341ab8
1 parent
fdb10aec
trade:新增是否自提的配置项
Showing
12 changed files
with
100 additions
and
42 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java
| ... | ... | @@ -13,4 +13,28 @@ public class NumberUtils { |
| 13 | 13 | return StrUtil.isNotEmpty(str) ? Long.valueOf(str) : null; |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | + /** | |
| 17 | + * 通过经纬度获取地球上两点之间的距离 | |
| 18 | + * | |
| 19 | + * 参考 <<a href="https://gitee.com/dromara/hutool/blob/1caabb586b1f95aec66a21d039c5695df5e0f4c1/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java">DistanceUtil</a>> 实现,目前它已经被 hutool 删除 | |
| 20 | + * | |
| 21 | + * @param lat1 经度1 | |
| 22 | + * @param lng1 纬度1 | |
| 23 | + * @param lat2 经度2 | |
| 24 | + * @param lng2 纬度2 | |
| 25 | + * @return 距离,单位:千米 | |
| 26 | + */ | |
| 27 | + public static double getDistance(double lat1, double lng1, double lat2, double lng2) { | |
| 28 | + double radLat1 = lat1 * Math.PI / 180.0; | |
| 29 | + double radLat2 = lat2 * Math.PI / 180.0; | |
| 30 | + double a = radLat1 - radLat2; | |
| 31 | + double b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0; | |
| 32 | + double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) | |
| 33 | + + Math.cos(radLat1) * Math.cos(radLat2) | |
| 34 | + * Math.pow(Math.sin(b / 2), 2))); | |
| 35 | + distance = distance * 6378.137; | |
| 36 | + distance = Math.round(distance * 10000d) / 10000d; | |
| 37 | + return distance; | |
| 38 | + } | |
| 39 | + | |
| 16 | 40 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/TradeConfigController.java
| ... | ... | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; |
| 8 | 8 | import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; |
| 9 | 9 | import io.swagger.v3.oas.annotations.Operation; |
| 10 | 10 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 11 | +import org.springframework.beans.factory.annotation.Value; | |
| 11 | 12 | import org.springframework.security.access.prepost.PreAuthorize; |
| 12 | 13 | import org.springframework.validation.annotation.Validated; |
| 13 | 14 | import org.springframework.web.bind.annotation.*; |
| ... | ... | @@ -26,6 +27,9 @@ public class TradeConfigController { |
| 26 | 27 | @Resource |
| 27 | 28 | private TradeConfigService tradeConfigService; |
| 28 | 29 | |
| 30 | + @Value("${yudao.tencent-lbs-key}") | |
| 31 | + private String tencentLbsKey; | |
| 32 | + | |
| 29 | 33 | @PutMapping("/save") |
| 30 | 34 | @Operation(summary = "更新交易中心配置") |
| 31 | 35 | @PreAuthorize("@ss.hasPermission('trade:config:save')") |
| ... | ... | @@ -39,7 +43,11 @@ public class TradeConfigController { |
| 39 | 43 | @PreAuthorize("@ss.hasPermission('trade:config:query')") |
| 40 | 44 | public CommonResult<TradeConfigRespVO> getConfig() { |
| 41 | 45 | TradeConfigDO config = tradeConfigService.getTradeConfig(); |
| 42 | - return success(TradeConfigConvert.INSTANCE.convert(config)); | |
| 46 | + TradeConfigRespVO configVO = TradeConfigConvert.INSTANCE.convert(config); | |
| 47 | + if (configVO != null) { | |
| 48 | + configVO.setTencentLbsKey(tencentLbsKey); | |
| 49 | + } | |
| 50 | + return success(configVO); | |
| 43 | 51 | } |
| 44 | 52 | |
| 45 | 53 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java
| ... | ... | @@ -44,6 +44,10 @@ public class TradeConfigBaseVO { |
| 44 | 44 | @PositiveOrZero(message = "全场包邮的最小金额不能是负数") |
| 45 | 45 | private Integer deliveryExpressFreePrice; |
| 46 | 46 | |
| 47 | + @Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 48 | + @NotNull(message = "是否开启自提不能为空") | |
| 49 | + private Boolean deliveryPickUpEnabled; | |
| 50 | + | |
| 47 | 51 | // ========== 分销相关 ========== |
| 48 | 52 | |
| 49 | 53 | @Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigRespVO.java
| ... | ... | @@ -14,4 +14,7 @@ public class TradeConfigRespVO extends TradeConfigBaseVO { |
| 14 | 14 | @Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 15 | 15 | private Long id; |
| 16 | 16 | |
| 17 | + @Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") | |
| 18 | + private String tencentLbsKey; | |
| 19 | + | |
| 17 | 20 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java
| ... | ... | @@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.Operation; |
| 10 | 10 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 11 | 11 | import lombok.RequiredArgsConstructor; |
| 12 | 12 | import lombok.extern.slf4j.Slf4j; |
| 13 | +import org.springframework.beans.factory.annotation.Value; | |
| 13 | 14 | import org.springframework.validation.annotation.Validated; |
| 14 | 15 | import org.springframework.web.bind.annotation.GetMapping; |
| 15 | 16 | import org.springframework.web.bind.annotation.RequestMapping; |
| ... | ... | @@ -30,11 +31,14 @@ public class AppTradeConfigController { |
| 30 | 31 | @Resource |
| 31 | 32 | private TradeConfigService tradeConfigService; |
| 32 | 33 | |
| 34 | + @Value("${yudao.tencent-lbs-key}") | |
| 35 | + private String tencentLbsKey; | |
| 36 | + | |
| 33 | 37 | @GetMapping("/get") |
| 34 | 38 | @Operation(summary = "获得交易配置") |
| 35 | 39 | public CommonResult<AppTradeConfigRespVO> getTradeConfig() { |
| 36 | - TradeConfigDO tradeConfig = ObjUtil.defaultIfNull(tradeConfigService.getTradeConfig(), new TradeConfigDO()); | |
| 37 | - return success(TradeConfigConvert.INSTANCE.convert02(tradeConfig)); | |
| 40 | + TradeConfigDO config = ObjUtil.defaultIfNull(tradeConfigService.getTradeConfig(), new TradeConfigDO()); | |
| 41 | + return success(TradeConfigConvert.INSTANCE.convert02(config).setTencentLbsKey(tencentLbsKey)); | |
| 38 | 42 | } |
| 39 | 43 | |
| 40 | 44 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java
| ... | ... | @@ -3,12 +3,22 @@ package cn.iocoder.yudao.module.trade.controller.app.config.vo; |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +import javax.validation.constraints.NotNull; | |
| 6 | 7 | import java.util.List; |
| 7 | 8 | |
| 8 | 9 | @Schema(description = "用户 App - 交易配置 Response VO") |
| 9 | 10 | @Data |
| 10 | 11 | public class AppTradeConfigRespVO { |
| 11 | 12 | |
| 13 | + @Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") | |
| 14 | + private String tencentLbsKey; | |
| 15 | + | |
| 16 | + // ========== 配送相关 ========== | |
| 17 | + | |
| 18 | + @Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 19 | + @NotNull(message = "是否开启自提不能为空") | |
| 20 | + private Boolean deliveryPickUpEnabled; | |
| 21 | + | |
| 12 | 22 | // ========== 售后相关 ========== |
| 13 | 23 | |
| 14 | 24 | @Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED) | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/AppDeliverPickUpStoreController.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.controller.app.delivery; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.util.RandomUtil; | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.module.trade.controller.app.delivery.vo.pickup.AppDeliveryPickUpStoreRespVO; |
| 6 | +import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert; | |
| 7 | +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; | |
| 8 | +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService; | |
| 6 | 9 | import io.swagger.v3.oas.annotations.Operation; |
| 7 | 10 | import io.swagger.v3.oas.annotations.Parameter; |
| 11 | +import io.swagger.v3.oas.annotations.Parameters; | |
| 8 | 12 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 9 | 13 | import org.springframework.validation.annotation.Validated; |
| 10 | 14 | import org.springframework.web.bind.annotation.GetMapping; |
| ... | ... | @@ -12,9 +16,8 @@ import org.springframework.web.bind.annotation.RequestMapping; |
| 12 | 16 | import org.springframework.web.bind.annotation.RequestParam; |
| 13 | 17 | import org.springframework.web.bind.annotation.RestController; |
| 14 | 18 | |
| 15 | -import java.util.ArrayList; | |
| 19 | +import javax.annotation.Resource; | |
| 16 | 20 | import java.util.List; |
| 17 | -import java.util.Random; | |
| 18 | 21 | |
| 19 | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 20 | 23 | |
| ... | ... | @@ -24,51 +27,29 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 24 | 27 | @Validated |
| 25 | 28 | public class AppDeliverPickUpStoreController { |
| 26 | 29 | |
| 27 | - // TODO 待实现[门店自提]:如果 latitude、longitude 非空,计算经纬度,并排序。计算的库,可以使用 hutool 的 DistanceUtil 计算。 | |
| 30 | + @Resource | |
| 31 | + private DeliveryPickUpStoreService deliveryPickUpStoreService; | |
| 32 | + | |
| 28 | 33 | @GetMapping("/list") |
| 29 | 34 | @Operation(summary = "获得自提门店列表") |
| 35 | + @Parameters({ | |
| 36 | + @Parameter(name = "latitude", description = "精度", example = "110"), | |
| 37 | + @Parameter(name = "longitude", description = "纬度", example = "120") | |
| 38 | + }) | |
| 30 | 39 | public CommonResult<List<AppDeliveryPickUpStoreRespVO>> getDeliveryPickUpStoreList( |
| 31 | 40 | @RequestParam(value = "latitude", required = false) Double latitude, |
| 32 | 41 | @RequestParam(value = "longitude", required = false) Double longitude) { |
| 33 | - List<AppDeliveryPickUpStoreRespVO> list = new ArrayList<>(); | |
| 34 | - Random random = new Random(); | |
| 35 | - for (int i = 0; i < 10; i++) { | |
| 36 | - AppDeliveryPickUpStoreRespVO store = new AppDeliveryPickUpStoreRespVO(); | |
| 37 | - store.setId(random.nextLong()); | |
| 38 | - store.setName(RandomUtil.randomString(10)); | |
| 39 | - store.setLogo("https://www.iocoder.cn/" + (i + 1) + ".png"); | |
| 40 | - store.setPhone("15601691300"); | |
| 41 | - store.setAreaId(random.nextInt(100000)); | |
| 42 | - store.setAreaName("上海-" + RandomUtil.randomString(10)); | |
| 43 | - store.setDetailAddress("普陀区-" + RandomUtil.randomString(10)); | |
| 44 | - store.setLatitude(random.nextDouble() * 10); | |
| 45 | - store.setLongitude(random.nextDouble() * 10); | |
| 46 | - store.setDistance(random.nextInt(1000)); | |
| 47 | - | |
| 48 | - list.add(store); | |
| 49 | - } | |
| 50 | - | |
| 51 | - return success(list); | |
| 42 | + List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus( | |
| 43 | + CommonStatusEnum.ENABLE.getStatus()); | |
| 44 | + return success(DeliveryPickUpStoreConvert.INSTANCE.convertList(list, latitude, longitude)); | |
| 52 | 45 | } |
| 53 | 46 | |
| 54 | - // TODO 待实现[门店自提]: | |
| 55 | 47 | @GetMapping("/get") |
| 56 | 48 | @Operation(summary = "获得自提门店") |
| 57 | 49 | @Parameter(name = "id", description = "门店编号") |
| 58 | 50 | public CommonResult<AppDeliveryPickUpStoreRespVO> getOrder(@RequestParam("id") Long id) { |
| 59 | - AppDeliveryPickUpStoreRespVO store = new AppDeliveryPickUpStoreRespVO(); | |
| 60 | - Random random = new Random(); | |
| 61 | - store.setId(random.nextLong()); | |
| 62 | - store.setName(RandomUtil.randomString(10)); | |
| 63 | - store.setLogo("https://www.iocoder.cn/" + (1) + ".png"); | |
| 64 | - store.setPhone("15601691300"); | |
| 65 | - store.setAreaId(random.nextInt(100000)); | |
| 66 | - store.setAreaName("上海-" + RandomUtil.randomString(10)); | |
| 67 | - store.setDetailAddress("普陀区-" + RandomUtil.randomString(10)); | |
| 68 | - store.setLatitude(random.nextDouble() * 10); | |
| 69 | - store.setLongitude(random.nextDouble() * 10); | |
| 70 | - store.setDistance(random.nextInt(1000)); | |
| 71 | - return success(store); | |
| 51 | + DeliveryPickUpStoreDO store = deliveryPickUpStoreService.getDeliveryPickUpStore(id); | |
| 52 | + return success(DeliveryPickUpStoreConvert.INSTANCE.convert03(store)); | |
| 72 | 53 | } |
| 73 | 54 | |
| 74 | 55 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java
| ... | ... | @@ -34,7 +34,7 @@ public class AppDeliveryPickUpStoreRespVO { |
| 34 | 34 | @Schema(description = "经度", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.99") |
| 35 | 35 | private Double longitude; |
| 36 | 36 | |
| 37 | - @Schema(description = "距离,单位:米", example = "100") // 只有在用户传递了经纬度时,才进行计算 | |
| 38 | - private Integer distance; | |
| 37 | + @Schema(description = "距离,单位:千米", example = "100") // 只有在用户传递了经纬度时,才进行计算 | |
| 38 | + private Double distance; | |
| 39 | 39 | |
| 40 | 40 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.convert.delivery; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | |
| 4 | 6 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; |
| 5 | 7 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreCreateReqVO; |
| 6 | 8 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreRespVO; |
| 7 | 9 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreSimpleRespVO; |
| 8 | 10 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO; |
| 11 | +import cn.iocoder.yudao.module.trade.controller.app.delivery.vo.pickup.AppDeliveryPickUpStoreRespVO; | |
| 9 | 12 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; |
| 10 | 13 | import org.mapstruct.Mapper; |
| 11 | 14 | import org.mapstruct.Mapping; |
| ... | ... | @@ -38,4 +41,18 @@ public interface DeliveryPickUpStoreConvert { |
| 38 | 41 | return AreaUtils.format(areaId); |
| 39 | 42 | } |
| 40 | 43 | |
| 44 | + default List<AppDeliveryPickUpStoreRespVO> convertList(List<DeliveryPickUpStoreDO> list, | |
| 45 | + Double latitude, Double longitude) { | |
| 46 | + List<AppDeliveryPickUpStoreRespVO> voList = CollectionUtils.convertList(list, store -> { | |
| 47 | + AppDeliveryPickUpStoreRespVO storeVO = convert03(store); | |
| 48 | + if (latitude != null && longitude != null) { | |
| 49 | + storeVO.setDistance(NumberUtils.getDistance(latitude, longitude, storeVO.getLatitude(), storeVO.getLongitude())); | |
| 50 | + } | |
| 51 | + return storeVO; | |
| 52 | + }); | |
| 53 | + return voList; | |
| 54 | + } | |
| 55 | + @Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName") | |
| 56 | + AppDeliveryPickUpStoreRespVO convert03(DeliveryPickUpStoreDO bean); | |
| 57 | + | |
| 41 | 58 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java
yudao-server/src/main/resources/application-dev.yaml
| ... | ... | @@ -170,6 +170,7 @@ yudao: |
| 170 | 170 | order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 |
| 171 | 171 | refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 |
| 172 | 172 | demo: true # 开启演示模式 |
| 173 | + tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc | |
| 173 | 174 | |
| 174 | 175 | justauth: |
| 175 | 176 | enabled: true | ... | ... |
yudao-server/src/main/resources/application-local.yaml
| ... | ... | @@ -213,6 +213,7 @@ yudao: |
| 213 | 213 | error-code: # 错误码相关配置项 |
| 214 | 214 | enable: false |
| 215 | 215 | demo: false # 关闭演示模式 |
| 216 | + tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc | |
| 216 | 217 | clean-job: |
| 217 | 218 | access-retain-day: 7 |
| 218 | 219 | error-retain-day: 8 | ... | ... |