diff --git a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeUserBikeInfo.java b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeUserBikeInfo.java index d5ee6f5..8a5173d 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeUserBikeInfo.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeUserBikeInfo.java @@ -43,7 +43,7 @@ public class EbikeUserBikeInfo implements Serializable { /** * 车辆电量 */ - private Float soc; + private Integer soc; /** * 免费时长(分钟):使用服务前的免费时间 diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java index 600c84b..c4e66b8 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java @@ -2,6 +2,7 @@ package com.cdzy.operations.service.impl; import cn.dev33.satoken.stp.StpUtil; import com.cdzy.common.ex.EbikeException; +import com.cdzy.common.model.dto.ResGPSDto; import com.cdzy.common.model.request.PageParam; import com.cdzy.operations.enums.*; import com.cdzy.operations.mapper.*; @@ -15,6 +16,7 @@ import com.cdzy.operations.service.EbikeBikeInfoService; import com.cdzy.operations.service.EbikeEcuInfoService; import com.cdzy.operations.service.EbikeInventoryRecordService; import com.cdzy.operations.service.EbikeInventoryService; +import com.cdzy.operations.utils.RedisUtil; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.update.UpdateChain; @@ -65,9 +67,6 @@ public class EbikeBikeInfoServiceImpl extends ServiceImpl redisTemplate; + + private final String geoKey="ebike_geo"; + + @Autowired + public RedisUtil(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /* ------------------- key 相关操作 ------------------ */ + + /** + * 添加地理位置 + * + * @param point 经纬度 + * @param member 成员名称 + */ + public void addLocation(Point point, String member) { + redisTemplate.opsForGeo().add(geoKey, point, member); + } + + /** + * 查询指定范围内的成员 + * + * @param center 中心点 + * @param radius 半径(单位:公里) + * @return 范围内的成员列表 + */ + public List findNearbyMembers(Point center, double radius) { + Distance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.KILOMETERS); + Circle circle = new Circle(center, distance); + GeoResults> results = redisTemplate.opsForGeo() + .radius(geoKey, circle); + return results.getContent().stream() + .map(geoLocation -> geoLocation.getContent().getName().toString()) + .toList(); + } + + /** + * 多边形查询 + * @param polygonPoints 边界点 + * @return 成员列表 + */ + public List searchByPolygon( List polygonPoints ) { + + // 1. 构造多边形 + GeometryFactory factory = new GeometryFactory(); + Coordinate[] coordinates = polygonPoints.stream() + .map(p -> new Coordinate(p.getX(), p.getY())) + .toArray(Coordinate[]::new); + Polygon polygon = factory.createPolygon(coordinates); + + // 2. 计算最小外接圆 + Point center = calculateBoundingCircleCenter(polygonPoints); + double radius = calculateMaxRadius(polygonPoints, center); + + // 3. 查询圆内所有点 + GeoResults> results = + redisTemplate.opsForGeo() + .radius(geoKey, + new Circle(center, new Distance(radius, Metrics.KILOMETERS)), + RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs() + .includeCoordinates()); + + // 4. 过滤多边形内的点 + List matches = new ArrayList<>(); + for (GeoResult> result : results) { + Point point = result.getContent().getPoint(); + if (polygon.contains(factory.createPoint( + new Coordinate(point.getX(), point.getY())))) { + matches.add(result.getContent().getName().toString()); + } + } + return matches; + } + + // 计算外接圆中心(多边形顶点平均值) + private Point calculateBoundingCircleCenter(List points) { + double sumX = 0, sumY = 0; + for (Point p : points) { + sumX += p.getX(); + sumY += p.getY(); + } + return new Point(sumX / points.size(), sumY / points.size()); + } + + // 计算最大半径 + private double calculateMaxRadius(List points, Point center) { + return points.stream() + .mapToDouble(p -> Math.sqrt( + Math.pow(p.getX() - center.getX(), 2) + + Math.pow(p.getY() - center.getY(), 2))) + .max().orElse(0)*100; + } + + /** + * 判断点是否在多边形内 + * @param point 待判断点 + * @param polygon 多边形顶点 + * @return 是否在多边形内 + */ + public static boolean isPointInPolygon(Point point, List polygon) { + double x = point.getX(); + double y = point.getY(); + + boolean inside = false; + for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) { + double xi = polygon.get(i).getX(); + double yi = polygon.get(i).getY(); + double xj = polygon.get(j).getX(); + double yj = polygon.get(j).getY(); + + boolean intersect = ((yi > y) != (yj > y)) + && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + if (intersect) inside = !inside; + } + return inside; + } + + /** + * 删除 Redis 键 + * + */ + public void deleteGeoKey() { + redisTemplate.delete(geoKey); + } + + /** + * 设置过期时间 + * @param key 键 + * @param timeout 超时时间 + * @param unit 时间单位 + */ + public Boolean expire(String key, long timeout, TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获取过期时间 + * @param key 键 + * @param unit 时间单位 + */ + public Long getExpire(String key, TimeUnit unit) { + return redisTemplate.getExpire(key, unit); + } + + /** + * 判断key是否存在 + * @param key 键 + */ + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + /** + * 删除key + * @param key 键 + */ + public Boolean delete(String key) { + return redisTemplate.delete(key); + } + + /* ------------------- String 相关操作 ------------------ */ + + /** + * 设置键值对 + * @param key 键 + * @param value 值 + */ + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 设置键值对并设置过期时间 + * @param key 键 + * @param value 值 + * @param timeout 过期时间 + * @param unit 时间单位 + */ + public void set(String key, Object value, long timeout, TimeUnit unit) { + redisTemplate.opsForValue().set(key, value, timeout, unit); + } + + /** + * 获取值 + * @param key 键 + */ + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + /** + * 自增操作(增量=1) + * @param key 键 + */ + public Long increment(String key) { + return redisTemplate.opsForValue().increment(key); + } + + /** + * 自增操作(指定增量) + * @param key 键 + * @param delta 增量 + */ + public Long increment(String key, long delta) { + return redisTemplate.opsForValue().increment(key, delta); + } + + /* ------------------- Hash 相关操作 ------------------ */ + + /** + * 设置Hash键值对 + * @param key 键 + * @param hashKey Hash键 + * @param value 值 + */ + public void hSet(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + /** + * 批量设置Hash键值对 + * @param key 键 + * @param map 多个Hash键值对 + */ + public void hSetAll(String key, Map map) { + redisTemplate.opsForHash().putAll(key, map); + } + + /** + * 获取Hash值 + * @param key 键 + * @param hashKey Hash键 + */ + public Object hGet(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + /** + * 获取所有Hash键值对 + * @param key 键 + */ + public Map hGetAll(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 删除Hash键 + * @param key 键 + * @param hashKeys Hash键集合 + */ + public Long hDelete(String key, Object... hashKeys) { + return redisTemplate.opsForHash().delete(key, hashKeys); + } + + /* ------------------- List 相关操作 ------------------ */ + + /** + * 左推入元素 + * @param key 键 + * @param value 值 + */ + public Long lPush(String key, Object value) { + return redisTemplate.opsForList().leftPush(key, value); + } + + /** + * 右推入元素 + * @param key 键 + * @param value 值 + */ + public Long rPush(String key, Object value) { + return redisTemplate.opsForList().rightPush(key, value); + } + + /** + * 获取列表范围 + * @param key 键 + * @param start 开始索引 + * @param end 结束索引 + */ + public List lRange(String key, long start, long end) { + return redisTemplate.opsForList().range(key, start, end); + } + + /* ------------------- Set 相关操作 ------------------ */ + + /** + * 添加集合元素 + * @param key 键 + * @param values 值数组 + */ + public Long sAdd(String key, Object... values) { + return redisTemplate.opsForSet().add(key, values); + } + + /** + * 获取集合所有元素 + * @param key 键 + */ + public Set sMembers(String key) { + return redisTemplate.opsForSet().members(key); + } + + /* ------------------- ZSet 相关操作 ------------------ */ + + /** + * 添加有序集合元素 + * @param key 键 + * @param value 值 + * @param score 分数 + */ + public Boolean zAdd(String key, Object value, double score) { + return redisTemplate.opsForZSet().add(key, value, score); + } + + /** + * 获取有序集合范围 + * @param key 键 + * @param start 开始索引 + * @param end 结束索引 + */ + public Set zRange(String key, long start, long end) { + return redisTemplate.opsForZSet().range(key, start, end); + } + + /* ------------------- 其他操作 ------------------ */ + + /** + * 获取匹配的键 + * @param pattern 匹配模式 + */ + public Set keys(String pattern) { + return redisTemplate.keys(pattern); + } + + /** + * 分布式锁:尝试获取锁 + * @param key 锁键 + * @param value 锁值 + * @param timeout 超时时间 + * @param unit 时间单位 + */ + public Boolean tryLock(String key, Object value, long timeout, TimeUnit unit) { + return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit); + } + + /** + * 释放锁 + * @param key 锁键 + */ + public Boolean releaseLock(String key) { + return redisTemplate.delete(key); + } +}