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