diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransport.java b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransport.java new file mode 100644 index 00000000..fc7f17b2 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransport.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.common.modules.store; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *
+ * 店铺同城快递运费设置(起送条件+优惠条件) + *
+ * + * @author panjunjie + * @since 2024-11-23 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("shop_store_same_city_transport") +@ApiModel(value = "ShopStoreSameCityTransport实体", description = "店铺同城快递运费设置(起送条件+优惠条件)") +public class ShopStoreSameCityTransport implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "运费自增ID") + @TableId(value = "transport_id", type = IdType.INPUT) + private Long transport_id; + + @ApiModelProperty(value = "基础运费自增ID") + private Long transport_base_id; + + @ApiModelProperty(value = "业务分类:1-圆半径;2-多边形;") + private Integer area_type; + + @ApiModelProperty(value = "配送范围半径(米)") + private Integer max_delivery_radius; + + @ApiModelProperty(value = "起送金额依据:1-订单原价;2-订单折扣价;3-订单实付金额;") + private Integer min_delivery_amount_type; + + @ApiModelProperty(value = "起送金额(元)") + private BigDecimal min_delivery_amount; + + @ApiModelProperty(value = "运费减免金额依据:1-订单原价;2-订单折扣价;3-订单实付金额;") + private Integer delivery_discount_type; + + @ApiModelProperty(value = "最低满足多少金额(元)才减免运费") + private BigDecimal min_delivery_discount_amount; + + @ApiModelProperty(value = "运费所减免的金额(元)") + private BigDecimal delivery_discount; + + @ApiModelProperty(value = "状态:1-有效;2-无效;") + private Integer status; + + @ApiModelProperty(value = "新增用户ID") + private Integer created_by; + + @ApiModelProperty(value = "更新用户ID") + private Integer updated_by; + + @ApiModelProperty(value = "新增时间") + private Date created_at; + + @ApiModelProperty(value = "修改时间") + private Date updated_at; +} diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransportBase.java b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransportBase.java new file mode 100644 index 00000000..22b34501 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreSameCityTransportBase.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.common.modules.store; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *+ * 店铺同城快递基础运费设置 + *
+ * + * @author panjunjie + * @since 2024-11-23 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("shop_store_same_city_transport_base") +@ApiModel(value = "ShopStoreSameCityTransportBase实体", description = "店铺同城快递基础运费设置") +public class ShopStoreSameCityTransportBase implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "基础运费自增ID") + @TableId(value = "transport_base_id", type = IdType.INPUT) + private Long transport_base_id; + + @ApiModelProperty(value = "店铺ID") + private Integer store_id; + + @ApiModelProperty(value = "店铺详细地址") + private String store_address; + + @ApiModelProperty(value = "店铺经度") + private BigDecimal store_longitude; + + @ApiModelProperty(value = "店铺纬度") + private BigDecimal store_latitude; + + @ApiModelProperty(value = "区域类型:1-按不同距离") + private Integer area_type; + + @ApiModelProperty(value = "运费设置依据:1-按距离和重量;2-仅距离;3-仅重量;") + private Integer basis; + + @ApiModelProperty(value = "基础距离(公里)") + private Integer distance_base; + + @ApiModelProperty(value = "基础重量(公斤)") + private Integer weight_base; + + @ApiModelProperty(value = "基础配送费(元)") + private BigDecimal delivery_base_fee; + + @ApiModelProperty(value = "距离每增加的公里的数") + private Integer distance_increase_km; + + @ApiModelProperty(value = "距离每增加n公里的配送费增加(元)") + private BigDecimal distance_increase_fee; + + @ApiModelProperty(value = "距离每增加的公斤的数") + private Integer weight_increase_kg; + + @ApiModelProperty(value = "重量每增加n公斤的配送费增加(元)") + private BigDecimal weight_increase_fee; + + @ApiModelProperty(value = "状态:1-有效;2-无效;") + private Integer status; + + @ApiModelProperty(value = "新增用户ID") + private Integer created_by; + + @ApiModelProperty(value = "更新用户ID") + private Integer updated_by; + + @ApiModelProperty(value = "新增时间") + private Date created_at; + + @ApiModelProperty(value = "修改时间") + private Date updated_at; +} diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/PositionUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/PositionUtil.java new file mode 100644 index 00000000..d944ef67 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/PositionUtil.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.common.utils; + +import org.apache.commons.lang3.StringUtils; + +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +/** + * 地图计算两点距离工具类,该类只是候选类, + * 建议优先从百度api或高德api上获取两点距离,这样更加准确 + * 无法获取到距离时,再使用该类的方法 + * + * @author 潘军杰 + * @since 2024-01-22 + */ +public class PositionUtil { + /** + * 方法一:(反余弦计算方式) + * + * @param longitude1 第一个点的经度 + * @param latitude1 第一个点的纬度 + * @param longitude2 第二个点的经度 + * @param latitude2 第二个点的纬度 + * @return 返回距离,单位m + */ + public static double getDistance1(double longitude1, double latitude1, double longitude2, double latitude2) { + // 纬度 + double lat1 = Math.toRadians(latitude1); + double lat2 = Math.toRadians(latitude2); + // 经度 + double lon1 = Math.toRadians(longitude1); + double lon2 = Math.toRadians(longitude2); + // 纬度之差 + double a = lat1 - lat2; + // 经度之差 + double b = lon1 - lon2; + // 计算两点距离的公式 + double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2))); + // 弧长乘赤道半径, 返回单位: 米 + + // 赤道半径(单位:米) + double EQUATOR_RADIUS = 6378137; + s = s * EQUATOR_RADIUS; + return s; + } + + + /** + * 方法二:(反余弦计算方式) + * + * @param longitude1 第一点的经度 + * @param latitude1 第一点的纬度 + * @param longitude2 第二点的经度 + * @param latitude2 第二点的纬度 + * @return 返回的距离,单位m + */ + public static double getDistance3(double longitude1, double latitude1, double longitude2, double latitude2) { + // 经纬度(角度)转弧度。弧度作为作参数,用以调用Math.cos和Math.sin + // A经弧度 + double radiansAX = Math.toRadians(longitude1); + // A纬弧度 + double radiansAY = Math.toRadians(latitude1); + // B经弧度 + double radiansBX = Math.toRadians(longitude2); + // B纬弧度 + double radiansBY = Math.toRadians(latitude2); + + // 公式中“cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2”的部分,得到∠AOB的cos值 + double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX) + Math.sin(radiansAY) * Math.sin(radiansBY); + // System.out.println("cos = " + cos); // 值域[-1,1] + + // 反余弦值 + double acos = Math.acos(cos); + // System.out.println("acos = " + acos); // 值域[0,π] + // System.out.println("∠AOB = " + Math.toDegrees(acos)); // 球心角 值域[0,180] + + // 地球平均半径(单位:米) + double EARTH_AVG_RADIUS = 6371000; + + // 最终结果 + return EARTH_AVG_RADIUS * acos; + } + + + /** + * 经纬度转化为弧度(rad) + * + * @param d 经度/纬度 + */ + private static double rad(double d) { + return d * Math.PI / 180.0; + } + + /** + * 方法三:(基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多。) + * + * @param longitude1 第一点的经度 + * @param latitude1 第一点的纬度 + * @param longitude2 第二点的经度 + * @param latitude2 第二点的纬度 + * @return 返回的距离,单位m + */ + public static double getDistance2(double longitude1, double latitude1, double longitude2, double latitude2) { + double radLat1 = rad(latitude1); + double radLat2 = rad(latitude2); + double a = radLat1 - radLat2; + double b = rad(longitude1) - rad(longitude2); + double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); + // 地球平均半径(单位:米) + double EARTH_AVG_RADIUS = 6371000; + s = s * EARTH_AVG_RADIUS; + s = Math.round(s * 10000d) / 10000d; + return s; + } + + /** + * 方法四:(高德地图计算方法) + * + * @param longitude1 第一点的经度 + * @param latitude1 第一点的纬度 + * @param longitude2 第二点的经度 + * @param latitude2 第二点的纬度 + * @return 返回的距离,单位m + */ + public static Double getDistance4(double longitude1, double latitude1, double longitude2, double latitude2) { + if (longitude1 == 0 || latitude1 == 0 || latitude2 == 0 || longitude2 == 0) { + return -1.0; + } + longitude1 *= 0.01745329251994329; + latitude1 *= 0.01745329251994329; + longitude2 *= 0.01745329251994329; + latitude2 *= 0.01745329251994329; + double var1 = Math.sin(longitude1); + double var2 = Math.sin(latitude1); + double var3 = Math.cos(longitude1); + double var4 = Math.cos(latitude1); + double var5 = Math.sin(longitude2); + double var6 = Math.sin(latitude2); + double var7 = Math.cos(longitude2); + double var8 = Math.cos(latitude2); + double[] var10 = new double[3]; + double[] var20 = new double[3]; + var10[0] = var4 * var3; + var10[1] = var4 * var1; + var10[2] = var2; + var20[0] = var8 * var7; + var20[1] = var8 * var5; + var20[2] = var6; + + return Math.asin(Math.sqrt((var10[0] - var20[0]) * (var10[0] - var20[0]) + (var10[1] - var20[1]) * (var10[1] - var20[1]) + (var10[2] - var20[2]) * (var10[2] - var20[2])) / 2.0) * 1.27420015798544E7; + // 结果四舍五入 保留2位小数 + //return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP).doubleValue(); + } + + + /** + * 判断坐标点是否在圆形区域内 + * 计算这个坐标点和圆心点之间的距离,然后跟圆的半径进行比较,如果比半径大,就不在圆形区域内,如果小于等于圆的半径,则该坐标点在圆形区域内 + * + * @param longitude1 第一点的经度 + * @param latitude1 第一点的纬度 + * @param longitude2 第二点的经度 + * @param latitude2 第二点的纬度 + * @param radius 圆形范围半径(单位:米) + * @return true:不在区域内; false:在区域内 + */ + public static boolean isInCircle(double longitude1, double latitude1, double longitude2, double latitude2, String radius) { + if (StringUtils.isBlank(radius)) { + throw new RuntimeException("请输入范围半径"); + } + return getDistance1(longitude1, latitude1, longitude2, latitude2) > Double.parseDouble(radius); + } + + /** + * 判断坐标点是否在多边形区域内 + * + * @param pointLon 要判断的点的经度 + * @param pointLat 要判断的点的纬度 + * @param lon 区域各顶点的经度数组 + * @param lat 区域各顶点的纬度数组 + * @return true:范围内; false:范围外 + */ + public static boolean isInPolygon(double pointLon, double pointLat, double[] lon, double[] lat) { + // 将要判断的横纵坐标组成一个点 + Point2D.Double point = new Point2D.Double(pointLon, pointLat); + // 将区域各顶点的横纵坐标放到一个点集合里面 + List