RiderLocationServiceImpl.java 4.26 KB
package com.diligrp.rider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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 org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class RiderLocationServiceImpl implements RiderLocationService {

    private final RiderLocationMapper locationMapper;
    private final RiderMapper riderMapper;
    private final CityService cityService;

    @Override
    public void updateLocation(Long riderId, LocationDTO dto) {
        RiderLocation existing = locationMapper.selectOne(new LambdaQueryWrapper<RiderLocation>()
                .eq(RiderLocation::getUid, riderId));
        long now = System.currentTimeMillis() / 1000;
        if (existing == null) {
            RiderLocation loc = new RiderLocation();
            loc.setUid(riderId);
            loc.setLng(dto.getLng());
            loc.setLat(dto.getLat());
            loc.setUpdateTime(now);
            locationMapper.insert(loc);
        } else {
            locationMapper.update(null, new LambdaUpdateWrapper<RiderLocation>()
                    .eq(RiderLocation::getUid, riderId)
                    .set(RiderLocation::getLng, dto.getLng())
                    .set(RiderLocation::getLat, dto.getLat())
                    .set(RiderLocation::getUpdateTime, now));
        }
    }

    @Override
    public LocationDTO getLocation(Long riderId) {
        RiderLocation loc = locationMapper.selectOne(new LambdaQueryWrapper<RiderLocation>()
                .eq(RiderLocation::getUid, riderId));
        if (loc == null) return null;
        LocationDTO dto = new LocationDTO();
        dto.setLng(loc.getLng());
        dto.setLat(loc.getLat());
        return dto;
    }

    @Override
    public List<NearbyRiderVO> getNearby(Long cityId, String lng, String lat) {
        List<NearbyRiderVO> result = new ArrayList<>();
        if (cityId == null || cityId < 1 || lng == null || lat == null) return result;

        // 获取城市配置的附近距离范围(km)
        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); // 默认3km
        }

        // 查该城市所有在线(未休息)骑手
        List<Rider> riders = riderMapper.selectList(new LambdaQueryWrapper<Rider>()
                .eq(Rider::getCityId, cityId)
                .eq(Rider::getIsRest, 0)
                .eq(Rider::getUserStatus, 1));
        if (riders.isEmpty()) return result;

        List<Long> riderIds = riders.stream().map(Rider::getId).toList();

        // 查骑手位置
        List<RiderLocation> locations = locationMapper.selectList(
                new LambdaQueryWrapper<RiderLocation>().in(RiderLocation::getUid, riderIds));

        double queryLat = Double.parseDouble(lat);
        double queryLng = Double.parseDouble(lng);
        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) {}
        }
        return result;
    }
}