package com.xiaopeng.operation.service.impl; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.operation.PointMapQuery; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; import com.xiaopeng.api.dto.order.HistoryStartPointsDto; import com.xiaopeng.api.feignClient.account.XpAppUserCollectAddrClient; import com.xiaopeng.api.model.operation.*; import com.xiaopeng.api.query.operation.PointListQuery; import com.xiaopeng.api.query.operation.PointPageListListQuery; import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo; import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo; import com.xiaopeng.api.vo.order.XpPointsListVo; import com.xiaopeng.api.vo.order.XpPointsSearchVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.utils.GeodesyUtil; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.evi.oss.service.AliOssService; import com.xiaopeng.operation.dto.NearestDto; import com.xiaopeng.operation.mapper.XpPointMapper; import com.xiaopeng.operation.mapper.XpSystemSettingMapper; import com.xiaopeng.operation.query.PointByNameQuery; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.IXpElectronicFenceService; import com.xiaopeng.operation.service.XpPointService; import com.xiaopeng.operation.utils.TimeRangeChecker; import com.xiaopeng.operation.utils.holiday.HolidayUtil; import com.xiaopeng.operation.utils.map.FastDistanceCalculator; import com.xiaopeng.api.vo.operation.NearestNextVo; import com.xiaopeng.operation.vo.NearestVo; import com.xiaopeng.operation.vo.OrderDistanceVo; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; /** *

* 点位管理 服务实现类 *

* * @author liu * @author WuGuanFengYue * @since 2026-02-03 */ @Service public class XpPointServiceImpl extends ServiceImpl implements XpPointService { @Resource private XpSystemSettingMapper xpSystemSettingMapper; @Resource private RedisService redisService; @Resource private HolidayUtil holidayUtil; @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; @Resource private IXpElectronicFenceService xpElectronicFenceService; @Resource private XpPointMapper baseMapper; @Resource private XpAppUserCollectAddrClient xpAppUserCollectAddrClient; @Resource private AliOssService aliOssService; @Override public NearestVo nearest(NearestDto dto,String uid) { // 走缓存 Object orderDistanceObj = redisService.getCacheObject(CacheConstants.NEAR_POINT_DISTANCE); Integer orderDistance; if (orderDistanceObj != null) { orderDistance = Integer.valueOf(orderDistanceObj.toString()); } else { XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null); orderDistance = xpSystemSetting.getNearPointDistance(); } List list1 = list(new LambdaQueryWrapper().eq(XpPoint::getOperationStatus, 2).eq(XpPoint::getPointType,1).isNotNull(XpPoint::getElectronicAreaId)); if(list1.size()<2){ return new NearestVo(); } // 获取所有的站点信息 List list = list(new LambdaQueryWrapper().eq(XpPoint::getOperationStatus, 2).eq(XpPoint::getPointType,1).isNotNull(XpPoint::getElectronicAreaId) // 添加距离计算字段 .apply("ST_Distance_Sphere(point({0}, {1}), point(point_lon, point_lat)) <= {2}", dto.getLongitude(), dto.getLatitude(), orderDistance)); list = list.stream().filter(e->e.getElectronicAreaId().equals(dto.getElectronicAreaId())).collect(Collectors.toList()); NearestVo nearestVo = new NearestVo(); if(list.isEmpty()){ nearestVo.setPoints(new ArrayList<>()); nearestVo.setTotal(0); return nearestVo; } List nearestNextVos = new ArrayList<>(); LocalTime now = LocalTime.now(); List areaIds = list.stream().map(XpPoint::getElectronicAreaId).collect(Collectors.toList()); List xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } R> pointIdsByUserId = null; // 获取用户收藏的地址 if(uid!=null){ pointIdsByUserId = xpAppUserCollectAddrClient.getPointIdsByUserId(Long.valueOf(uid)); } //判断当前点位是否在运营时间范围内 for (XpPoint xpPoint : list) { Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { continue; } } // 计算距离 小于的站点 double v = FastDistanceCalculator.distanceFast(dto.getLatitude(), dto.getLongitude(), xpPoint.getPointLat(), xpPoint.getPointLon()); // m做判断 if ((v) < orderDistance) { NearestNextVo nearestNextVo = new NearestNextVo(); nearestNextVo.setId(xpPoint.getId()); nearestNextVo.setName(xpPoint.getPointName()); nearestNextVo.setLatitude(xpPoint.getPointLat()); nearestNextVo.setLongitude(xpPoint.getPointLon()); nearestNextVo.setDistance(new BigDecimal(v).setScale(2, RoundingMode.HALF_UP).doubleValue()); nearestNextVo.setAddress(xpPoint.getPointAddress()); nearestNextVo.setTime(xpPoint.getParkingTimeLimit()); nearestNextVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); // 判断是否收藏 if(pointIdsByUserId!=null && !pointIdsByUserId.getData().isEmpty()){ if(pointIdsByUserId.getData().contains(xpPoint.getId())){ nearestNextVo.setIsCollect(1); } } nearestNextVos.add(nearestNextVo); } } if (!nearestNextVos.isEmpty()) { nearestNextVos = nearestNextVos.stream().sorted(Comparator.comparing(NearestNextVo::getDistance)).collect(Collectors.toList()); } nearestVo.setPoints(nearestNextVos); nearestVo.setTotal(nearestNextVos.size()); return nearestVo; } public boolean getInTime(LocalTime now, Integer effectivePeriod, String effectiveTimePeriod){ // 2非工作日 0工作日 1节假日 3调休日 Integer holidayToday = holidayUtil.isHolidayToday(); if(effectivePeriod==1){ boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==2){ if(holidayToday!=0){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==3){ if(holidayToday!=2){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==4){ if(holidayToday!=1){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } } return true; } @Override public List pointMap(PointMapQuery query) { List list = this.baseMapper.pointMap(query); for (XpPoint xpPoint : list) { String pointPictures = xpPoint.getPointPictures(); if (org.apache.commons.lang3.StringUtils.isNotBlank(pointPictures)) { JSONArray jsonArray = JSONArray.parseArray(pointPictures); for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); if (Objects.isNull(jsonObject)) { continue; } String downloadUrl = jsonObject.getString("url");; try { downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); } catch (UnsupportedEncodingException e) { log.error("获取图片下载地址失败", e); } jsonObject.put("url", downloadUrl); } xpPoint.setPointPictures(JSONArray.toJSONString(jsonArray)); } } return list; } @Override public List listAll(PointListQuery query) { if(StringUtils.hasLength(query.getOperationStatus())){ String[] split = query.getOperationStatus().split(","); List statusIds = new ArrayList<>(); for (String s : split) { statusIds.add(Integer.valueOf(s)); } query.setOperationStatusIds(statusIds); } List list = this.baseMapper.listAll(query); for (XpPoint xpPoint : list) { String pointPictures = xpPoint.getPointPictures(); if (org.apache.commons.lang3.StringUtils.isNotBlank(pointPictures)) { JSONArray jsonArray = JSONArray.parseArray(pointPictures); for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); if (Objects.isNull(jsonObject)) { continue; } String downloadUrl = jsonObject.getString("url");; try { downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); } catch (UnsupportedEncodingException e) { log.error("获取图片下载地址失败", e); } jsonObject.put("url", downloadUrl); } xpPoint.setPointPictures(JSONArray.toJSONString(jsonArray)); } if(null != query.getLongitude() && null != query.getLatitude()){ Map distance = GeodesyUtil.getDistance(query.getLongitude() + "," + query.getLatitude(), xpPoint.getPointLon() + "," + xpPoint.getPointLat()); xpPoint.setDistance(new BigDecimal(distance.get("WGS84"))); } } if(null != query.getLongitude() && null != query.getLatitude()){ //对距离进行排序 list.sort((o1, o2) -> o1.getDistance().compareTo(o2.getDistance()) * -1); } return list; } @Override public List getHistoryStartPoints(HistoryStartPointsDto historyStartPointsDto) { List xpPoints = this.baseMapper.selectBatchIds(historyStartPointsDto.getPointIds()); ArrayList resultList = new ArrayList<>(10); LocalTime now = LocalTime.now(); List areaIds = xpPoints.stream().map(XpPoint::getElectronicAreaId).collect(Collectors.toList()); List xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } // 获取用户收藏的地址 R> pointIdsByUserId = xpAppUserCollectAddrClient.getPointIdsByUserId(historyStartPointsDto.getUserId()); for (XpPoint xpPoint : xpPoints) { if(xpPoint.getOperationStatus()!=2){ continue; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ // 不在运营段 continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ // 不在运营段 continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { // 不在运营段 continue; } } XpHistoryStartPointsVo xpHistoryStartPointsVo = new XpHistoryStartPointsVo(); xpHistoryStartPointsVo.setOperationStatus(1); xpHistoryStartPointsVo.setName(xpPoint.getPointName()); xpHistoryStartPointsVo.setAddress(xpPoint.getPointAddress()); xpHistoryStartPointsVo.setLatitude(xpPoint.getPointLat()); xpHistoryStartPointsVo.setLongitude(xpPoint.getPointLon()); xpHistoryStartPointsVo.setId(xpPoint.getId()); double distanced = FastDistanceCalculator.distanceFast(historyStartPointsDto.getLat(), historyStartPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon()); xpHistoryStartPointsVo.setDistance(distanced); xpHistoryStartPointsVo.setTime(xpPoint.getParkingTimeLimit()); xpHistoryStartPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); // 判断是否收藏 if(pointIdsByUserId!=null && !pointIdsByUserId.getData().isEmpty()){ if(pointIdsByUserId.getData().contains(xpPoint.getId())){ xpHistoryStartPointsVo.setIsCollect(1); } } resultList.add(xpHistoryStartPointsVo); } return resultList; } @Override public List getHistoryEndPoints(HistoryEndPointsDto historyEndPointsDto) { List xpPoints = this.baseMapper.selectBatchIds(historyEndPointsDto.getPointIds()); ArrayList resultList = new ArrayList<>(10); LocalTime now = LocalTime.now(); List areaIds = xpPoints.stream().map(XpPoint::getElectronicAreaId).collect(Collectors.toList()); List xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } // 获取用户收藏的地址 R> pointIdsByUserId = xpAppUserCollectAddrClient.getPointIdsByUserId(historyEndPointsDto.getUserId()); for (XpPoint xpPoint : xpPoints) { if(xpPoint.getOperationStatus()!=2){ continue; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ // 不在运营段 continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ // 不在运营段 continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { // 不在运营段 continue; } } XpHistoryEndPointsVo xpHistoryEndPointsVo = new XpHistoryEndPointsVo(); xpHistoryEndPointsVo.setOperationStatus(1); xpHistoryEndPointsVo.setName(xpPoint.getPointName()); xpHistoryEndPointsVo.setAddress(xpPoint.getPointAddress()); xpHistoryEndPointsVo.setLatitude(xpPoint.getPointLat()); xpHistoryEndPointsVo.setLongitude(xpPoint.getPointLon()); xpHistoryEndPointsVo.setId(xpPoint.getId()); double distanced = FastDistanceCalculator.distanceFast(historyEndPointsDto.getLat(), historyEndPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon()); xpHistoryEndPointsVo.setDistance(distanced); xpHistoryEndPointsVo.setTime(xpPoint.getParkingTimeLimit()); xpHistoryEndPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); // 判断是否收藏 if(pointIdsByUserId!=null && !pointIdsByUserId.getData().isEmpty()){ if(pointIdsByUserId.getData().contains(xpPoint.getId())){ xpHistoryEndPointsVo.setIsCollect(1); } } resultList.add(xpHistoryEndPointsVo); } return resultList; } @Override public XpPointsSearchVo queryPointByName(PointByNameQuery query,String uid) { XpPointsSearchVo searchVo = new XpPointsSearchVo(); List stationList = this.baseMapper.queryStationByName(query); List stationIds = stationList.stream() .map(this::getSearchResultStationId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); // 先把命中的场站id传给点位查询,避免同一场站下的点位和场站父胶囊重复返回。 List pointList = this.baseMapper.queryPointByName(query, stationIds); List stationChildren = CollUtil.isEmpty(stationIds) ? Collections.emptyList() : this.baseMapper.queryStationChildren(stationIds); if (CollUtil.isEmpty(stationList) && CollUtil.isEmpty(pointList)) { return searchVo; } // 搜索页需要拆分两套收藏态: // 1. 站点胶囊按 pointId 判定。 // 2. 场站胶囊按 stationId 判定。 Set collectedPointIds = getCollectedPointIds(uid); Set collectedStationIds = getCollectedStationIds(uid); List allRows = new ArrayList<>(stationList.size() + pointList.size() + stationChildren.size()); allRows.addAll(stationList); allRows.addAll(pointList); allRows.addAll(stationChildren); Map electronicFenceAreaMap = buildElectronicFenceAreaMap(allRows); Map electronicFenceMap = buildElectronicFenceMap(electronicFenceAreaMap); markSearchRows(allRows, collectedPointIds, collectedStationIds, electronicFenceAreaMap, electronicFenceMap); List resultList = new ArrayList<>(); List stationResults = buildStationSearchResults(stationList, stationChildren, query); Set displayedStationIds = stationResults.stream() .map(this::getSearchResultStationId) .filter(Objects::nonNull) .collect(Collectors.toSet()); resultList.addAll(stationResults); resultList.addAll(pointList.stream() .filter(vo -> vo.getState() == 1) .filter(vo -> vo.getStationId() == null || !displayedStationIds.contains(vo.getStationId())) .peek(vo -> fillDistance(vo, query)) .collect(Collectors.toList())); List availablePoints = resultList.stream() .filter(e -> query.getElectronicAreaId() != null && e.getElectronicAreaId().equals(query.getElectronicAreaId())) .sorted(Comparator.comparing(this::distanceOrMax)) .collect(Collectors.toList()); List unavailablePoints = resultList.stream() .filter(e -> query.getElectronicAreaId() == null || !e.getElectronicAreaId().equals(query.getElectronicAreaId())) .sorted(Comparator.comparing(this::distanceOrMax)) .collect(Collectors.toList()); searchVo.setAvailablePoints(availablePoints); searchVo.setUnavailablePoints(unavailablePoints); return searchVo; } private List buildStationSearchResults(List stationList, List stationChildren, PointByNameQuery query) { if (CollUtil.isEmpty(stationList)) { return Collections.emptyList(); } Map> childrenMap = stationChildren.stream() .filter(vo -> vo.getState() == 1) .peek(vo -> fillDistance(vo, query)) .collect(Collectors.groupingBy(this::getSearchResultStationId, LinkedHashMap::new, Collectors.toList())); List result = new ArrayList<>(); for (XpPointsListVo station : stationList) { if (station.getState() != 1) { continue; } Long stationId = getSearchResultStationId(station); List children = childrenMap.getOrDefault(stationId, Collections.emptyList()); if (CollUtil.isEmpty(children)) { continue; } XpPointsListVo firstChild = children.get(0); if (station.getCollectPointId() == null) { station.setCollectPointId(firstChild.getId()); } if (station.getLongitude() == null || station.getLatitude() == null) { station.setLongitude(firstChild.getLongitude()); station.setLatitude(firstChild.getLatitude()); } if (!StringUtils.hasLength(station.getAddress())) { station.setAddress(firstChild.getAddress()); } fillDistance(station, query); station.setChildren(children); result.add(station); } return result; } /** * 仅查询“站点收藏”。 * nearest / 历史上下车点等老接口仍然只对 pointId 打星,所以这里不能混入场站收藏。 */ private Set getCollectedPointIds(String uid) { if (uid == null) { return Collections.emptySet(); } R> pointIdsByUserId = xpAppUserCollectAddrClient.getPointIdsByUserId(Long.valueOf(uid)); if (pointIdsByUserId == null || CollUtil.isEmpty(pointIdsByUserId.getData())) { return Collections.emptySet(); } return new HashSet<>(pointIdsByUserId.getData()); } /** * 场站收藏需要单独查询。 * 搜索结果里的场站父级行应按 stationId 判断收藏态,不能继续复用 pointId 集合。 */ private Set getCollectedStationIds(String uid) { if (uid == null) { return Collections.emptySet(); } R> stationIdsByUserId = xpAppUserCollectAddrClient.getStationIdsByUserId(Long.valueOf(uid)); if (stationIdsByUserId == null || CollUtil.isEmpty(stationIdsByUserId.getData())) { return Collections.emptySet(); } return new HashSet<>(stationIdsByUserId.getData()); } private Map buildElectronicFenceAreaMap(List rows) { List areaIds = rows.stream() .map(XpPointsListVo::getElectronicAreaId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (CollUtil.isEmpty(areaIds)) { return Collections.emptyMap(); } return xpElectronicFenceAreaService.listByIds(areaIds).stream() .collect(Collectors.toMap(XpElectronicFenceArea::getId, area -> area, (left, right) -> left)); } private Map buildElectronicFenceMap(Map electronicFenceAreaMap) { if (electronicFenceAreaMap.isEmpty()) { return Collections.emptyMap(); } List fenceIds = electronicFenceAreaMap.values().stream() .map(XpElectronicFenceArea::getElectronicId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (CollUtil.isEmpty(fenceIds)) { return Collections.emptyMap(); } return xpElectronicFenceService.listByIds(fenceIds).stream() .collect(Collectors.toMap(XpElectronicFence::getId, fence -> fence, (left, right) -> left)); } private void markSearchRows(List rows, Set collectedPointIds, Set collectedStationIds, Map electronicFenceAreaMap, Map electronicFenceMap) { LocalTime now = LocalTime.now(); for (XpPointsListVo row : rows) { if (isCollectedSearchRow(row, collectedPointIds, collectedStationIds)) { row.setIsCollect(1); } if (!isSearchRowAvailable(row, electronicFenceAreaMap, electronicFenceMap, now)) { row.setState(0); } } } /** * 搜索结果收藏态判定规则: * 1. 站点行按 pointId / collectPointId 判定。 * 2. 场站行按 stationId 判定。 */ private boolean isCollectedSearchRow(XpPointsListVo row, Set collectedPointIds, Set collectedStationIds) { if (row.getItemType() != null && row.getItemType() == 2) { Long stationId = getSearchResultStationId(row); return stationId != null && collectedStationIds.contains(stationId); } Long collectPointId = row.getCollectPointId() != null ? row.getCollectPointId() : row.getId(); return collectPointId != null && collectedPointIds.contains(collectPointId); } private boolean isSearchRowAvailable(XpPointsListVo row, Map electronicFenceAreaMap, Map electronicFenceMap, LocalTime now) { Integer operationType = row.getOperationType(); if (operationType == null) { return false; } if (operationType == 1) { Long electronicAreaId = row.getElectronicAreaId(); if (electronicAreaId == null) { return false; } XpElectronicFenceArea electronicFenceArea = electronicFenceAreaMap.get(electronicAreaId); if (electronicFenceArea == null || electronicFenceArea.getElectronicId() == null) { return false; } XpElectronicFence electronicFence = electronicFenceMap.get(electronicFenceArea.getElectronicId()); if (electronicFence == null) { return false; } Integer failureType = electronicFence.getFailureType(); if (failureType == null) { return true; } if (failureType == 1 && LocalDateTime.now().isBefore(electronicFence.getEffectTime())) { return false; } return failureType != 2 || (!LocalDateTime.now().isBefore(electronicFence.getEffectTime()) && !LocalDateTime.now().isAfter(electronicFence.getFailureTime())); } if (row.getEffectivePeriod() == null || !StringUtils.hasLength(row.getEffectiveTimePeriod())) { return true; } return getInTime(now, row.getEffectivePeriod(), row.getEffectiveTimePeriod()); } private void fillDistance(XpPointsListVo row, PointByNameQuery query) { if (row.getLatitude() == null || row.getLongitude() == null) { return; } row.setDistance(BigDecimal.valueOf(FastDistanceCalculator.distanceFast(query.getLat(), query.getLon(), row.getLatitude(), row.getLongitude())) .setScale(2, RoundingMode.HALF_UP) .doubleValue()); } private Long getSearchResultStationId(XpPointsListVo row) { return row.getStationId() != null ? row.getStationId() : row.getId(); } private Double distanceOrMax(XpPointsListVo row) { return row.getDistance() == null ? Double.MAX_VALUE : row.getDistance(); } @Override public OrderDistanceVo getOrderDistance() { OrderDistanceVo orderDistanceVo = new OrderDistanceVo(); XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null); if (xpSystemSetting != null) { orderDistanceVo.setMaxDistance(xpSystemSetting.getOrderDistance()); orderDistanceVo.setMinDistance(xpSystemSetting.getMinOrderDistance()); orderDistanceVo.setAdsorptionDistance(xpSystemSetting.getAdsorptionDistance()); orderDistanceVo.setNearPointDistance(xpSystemSetting.getNearPointDistance()); return orderDistanceVo; } return orderDistanceVo; } @Override public PageInfo pageList(PointPageListListQuery query) { PageInfo pageInfo = new PageInfo<>(query.getPageNum(),query.getPageSize()); List list = this.baseMapper.pageList(pageInfo,query); pageInfo.setRecords(list); return pageInfo; } @Override public Boolean nowInTimePoint(Long pointId) { XpPoint xpPoint = this.getById(pointId); if(null == xpPoint){ return false; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaService.getById(xpPoint.getElectronicAreaId()); if(null == xpElectronicFenceArea){ return false; } XpElectronicFence xpElectronicFence = xpElectronicFenceService.getById(xpElectronicFenceArea.getElectronicId()); if(null == xpElectronicFence){ return false; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ return false; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 return false; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(LocalTime.now(), xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { return false; } } return true; } }