From 412fa709df33fcad4647f394fcebba8f68c2d471 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 06 三月 2026 11:47:16 +0800
Subject: [PATCH] feat(app):运维APP用户帐号权限获取
---
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java | 125 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
index d00a7e9..b0d84c4 100644
--- a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
+++ b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
@@ -3,10 +3,13 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xiaopeng.api.dto.operation.PointAddDto;
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.model.operation.XpElectronicFenceArea;
import com.xiaopeng.api.model.operation.XpPoint;
+import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.api.model.operation.XpSystemSetting;
import com.xiaopeng.api.query.operation.PointListQuery;
import com.xiaopeng.api.query.operation.PointPageListListQuery;
@@ -15,12 +18,17 @@
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.exception.ServiceException;
+import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
+import com.xiaopeng.map.constant.I18nKeyConstant;
import com.xiaopeng.map.dto.NearestDto;
import com.xiaopeng.map.mapper.XpPointMapper;
+import com.xiaopeng.map.mapper.XpRegionMapper;
import com.xiaopeng.map.mapper.XpSystemSettingMapper;
import com.xiaopeng.map.query.PointByNameQuery;
+import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import com.xiaopeng.map.service.XpPointService;
import com.xiaopeng.map.utils.TimeRangeChecker;
import com.xiaopeng.map.utils.holiday.HolidayUtil;
@@ -28,6 +36,12 @@
import com.xiaopeng.map.vo.NearestNextVo;
import com.xiaopeng.map.vo.NearestVo;
import com.xiaopeng.map.vo.OrderDistanceVo;
+import lombok.extern.slf4j.Slf4j;
+import net.sourceforge.pinyin4j.PinyinHelper;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -35,6 +49,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -47,7 +62,13 @@
* @since 2026-02-03
*/
@Service
+@Slf4j
public class XpPointServiceImpl extends ServiceImpl<XpPointMapper, XpPoint> implements XpPointService {
+
+ private static final String POINT_BIZ_TYPE = "PUD";
+ private static final int SERIAL_WIDTH = 6;
+ private static final int LOCK_WAIT_SECONDS = 5;
+ private static final int LOCK_LEASE_SECONDS = 30;
@Resource
private XpSystemSettingMapper xpSystemSettingMapper;
@@ -58,6 +79,59 @@
@Resource
private HolidayUtil holidayUtil;
+ @Resource
+ private XpElectronicFenceAreaService xpElectronicFenceAreaService;
+
+ @Resource
+ private XpRegionMapper xpRegionMapper;
+
+ @Autowired
+ private RedissonClient redissonClient;
+
+ @Override
+ public void addPointWithGeneratedNumber(PointAddDto pointAddDto) {
+ if (pointAddDto == null) {
+ throw new ServiceException("参数不能为空", I18nKeyConstant.SYSTEM_EXCEPTION);
+ }
+ if (pointAddDto.getElectronicAreaId() == null) {
+ throw new ServiceException("运营区域ID不能为空", I18nKeyConstant.POINT_ELECTRONIC_AREA_ID_EMPTY);
+ }
+
+ String cityPrefix = buildCityPrefix(pointAddDto.getElectronicAreaId());
+ String lockKey = buildPointNumberLockKey(cityPrefix, POINT_BIZ_TYPE);
+
+ RLock lock = redissonClient.getLock(lockKey);
+ boolean locked = false;
+ String pointNumber;
+ try {
+ locked = lock.tryLock(LOCK_WAIT_SECONDS, LOCK_LEASE_SECONDS, TimeUnit.SECONDS);
+ if (!locked) {
+ throw new ServiceException("点位编号生成繁忙,请稍后重试", I18nKeyConstant.POINT_NUMBER_LOCK_FAIL);
+ }
+ String maxPointNumber = this.baseMapper.selectMaxPointNumber(cityPrefix, POINT_BIZ_TYPE);
+ int nextSerial = 1;
+ if (StringUtils.hasText(maxPointNumber)) {
+ nextSerial = parseSerialOrThrow(maxPointNumber) + 1;
+ }
+ pointNumber = cityPrefix + "-" + POINT_BIZ_TYPE + "-" + String.format("%0" + SERIAL_WIDTH + "d", nextSerial);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new ServiceException("点位编号生成繁忙,请稍后重试", I18nKeyConstant.POINT_NUMBER_LOCK_FAIL);
+ } finally {
+ try {
+ if (locked && lock.isHeldByCurrentThread()) {
+ lock.unlock();
+ }
+ } catch (Exception e) {
+ log.warn("释放点位编号生成锁失败 lockKey={}", lockKey, e);
+ }
+ }
+
+ XpPoint xpPoint = new XpPoint();
+ BeanUtils.copyProperties(pointAddDto, xpPoint);
+ xpPoint.setPointNumber(pointNumber);
+ this.save(xpPoint);
+ }
@Override
public NearestVo nearest(NearestDto dto) {
@@ -112,6 +186,57 @@
}
+ private String buildCityPrefix(Long electronicAreaId) {
+ XpElectronicFenceArea area = xpElectronicFenceAreaService.getById(electronicAreaId);
+ if (area == null) {
+ throw new ServiceException("运营区域不存在", I18nKeyConstant.POINT_ELECTRONIC_AREA_NOT_EXIST);
+ }
+ if (!StringUtils.hasText(area.getCityCode())) {
+ throw new ServiceException("城市信息不存在", I18nKeyConstant.POINT_CITY_NOT_EXIST);
+ }
+
+ XpRegion region = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>()
+ .eq(XpRegion::getCode, area.getCityCode()));
+ if (region == null || !StringUtils.hasText(region.getName())) {
+ throw new ServiceException("城市信息不存在", I18nKeyConstant.POINT_CITY_NOT_EXIST);
+ }
+
+ String name = region.getName();
+ String prefix = name.length() <= 2 ? name : name.substring(0, 2);
+ return getPinyinInitials(prefix).toUpperCase();
+ }
+
+ private static String buildPointNumberLockKey(String cityPrefix, String bizType) {
+ return "xp:point:number:" + cityPrefix + ":" + bizType;
+ }
+
+ private static String getPinyinInitials(String chinese) {
+ StringBuilder pinyinInitials = new StringBuilder();
+ for (char c : chinese.toCharArray()) {
+ String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
+ if (pinyinArray != null && pinyinArray.length > 0) {
+ pinyinInitials.append(pinyinArray[0].charAt(0));
+ }
+ }
+ return pinyinInitials.toString();
+ }
+
+ private static int parseSerialOrThrow(String pointNumber) {
+ String[] parts = pointNumber.split("-");
+ if (parts.length < 3) {
+ throw new ServiceException("点位编号生成失败(历史编号格式异常)", I18nKeyConstant.POINT_NUMBER_PARSE_FAIL);
+ }
+ String serialPart = parts[parts.length - 1];
+ if (serialPart.length() != SERIAL_WIDTH) {
+ throw new ServiceException("点位编号生成失败(历史编号格式异常)", I18nKeyConstant.POINT_NUMBER_PARSE_FAIL);
+ }
+ try {
+ return Integer.parseInt(serialPart);
+ } catch (NumberFormatException e) {
+ throw new ServiceException("点位编号生成失败(历史编号格式异常)", I18nKeyConstant.POINT_NUMBER_PARSE_FAIL);
+ }
+ }
+
public boolean getInTime(LocalTime now, Integer effectivePeriod, String effectiveTimePeriod){
--
Gitblit v1.7.1