RiderLocationServiceImpl.java
4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package com.diligrp.rider.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.diligrp.rider.dto.DeliveryPricingConfigDTO;
import com.diligrp.rider.dto.LocationDTO;
import com.diligrp.rider.entity.Rider;
import com.diligrp.rider.entity.RiderLocation;
import com.diligrp.rider.mapper.RiderLocationMapper;
import com.diligrp.rider.mapper.RiderMapper;
import com.diligrp.rider.service.CityService;
import com.diligrp.rider.service.RiderLocationService;
import com.diligrp.rider.util.GeoUtil;
import com.diligrp.rider.vo.NearbyRiderVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service
@RequiredArgsConstructor
@Slf4j
public class RiderLocationServiceImpl implements RiderLocationService {
private static final long ACTIVE_WINDOW_SECONDS = 300;
private final RiderLocationMapper locationMapper;
private final RiderMapper riderMapper;
private final CityService cityService;
/**
* 按骑手维度更新最新位置。
*/
@Override
public void updateLocation(Long riderId, LocationDTO dto) {
long now = System.currentTimeMillis() / 1000;
log.debug("更新骑手位置,参数 riderId={} lng={} lat={} updateTime={}",
riderId, dto.getLng(), dto.getLat(), now);
locationMapper.upsertLocation(
riderId,
dto.getLng().stripTrailingZeros().toPlainString(),
dto.getLat().stripTrailingZeros().toPlainString(),
now);
}
/**
* 查询当前骑手最近一次上报的位置。
*/
@Override
public LocationDTO getLocation(Long riderId) {
log.debug("查询骑手当前位置,参数 riderId={}", riderId);
RiderLocation loc = locationMapper.selectOne(new LambdaQueryWrapper<RiderLocation>()
.eq(RiderLocation::getUid, riderId));
if (loc == null) {
log.debug("未查询到骑手位置,riderId={}", riderId);
return null;
}
LocationDTO dto = new LocationDTO();
dto.setLng(new BigDecimal(loc.getLng()));
dto.setLat(new BigDecimal(loc.getLat()));
return dto;
}
/**
* 查询城市范围内最近活跃的附近骑手。
*/
@Override
public List<NearbyRiderVO> getNearby(Long cityId, BigDecimal lng, BigDecimal lat) {
List<NearbyRiderVO> result = new ArrayList<>();
log.debug("开始查询附近骑手,参数 cityId={} lng={} lat={}", cityId, lng, lat);
if (cityId == null || cityId < 1 || lng == null || lat == null) {
return result;
}
DeliveryPricingConfigDTO config = cityService.getConfig(cityId);
if (config == null) {
return result;
}
BigDecimal limitKm = config.getRiderDistance();
if (limitKm == null || limitKm.compareTo(BigDecimal.ZERO) <= 0) {
limitKm = BigDecimal.valueOf(3);
}
List<Rider> riders = riderMapper.selectList(new LambdaQueryWrapper<Rider>()
.eq(Rider::getCityId, cityId)
.eq(Rider::getIsRest, 0)
.eq(Rider::getUserStatus, 1));
if (riders.isEmpty()) {
log.debug("当前城市没有在线骑手,cityId={}", cityId);
return result;
}
List<Long> riderIds = riders.stream().map(Rider::getId).toList();
long minUpdateTime = System.currentTimeMillis() / 1000 - ACTIVE_WINDOW_SECONDS;
List<RiderLocation> locations = locationMapper.selectList(
new LambdaQueryWrapper<RiderLocation>()
.in(RiderLocation::getUid, riderIds)
.ge(RiderLocation::getUpdateTime, minUpdateTime));
double queryLat = lat.doubleValue();
double queryLng = lng.doubleValue();
double limitD = limitKm.doubleValue();
for (RiderLocation loc : locations) {
try {
double dist = GeoUtil.calcDistanceKm(
queryLat, queryLng,
Double.parseDouble(loc.getLat()),
Double.parseDouble(loc.getLng()));
if (dist <= limitD) {
NearbyRiderVO vo = new NearbyRiderVO();
vo.setLng(loc.getLng());
vo.setLat(loc.getLat());
vo.setDistance(dist);
result.add(vo);
}
} catch (Exception ignored) {
}
}
log.debug("附近骑手查询完成,cityId={} 在线骑手数={} 位置记录数={} 命中数={}",
cityId, riders.size(), locations.size(), result.size());
return result;
}
}