README.md
@@ -1,4 +1,150 @@ ## Robotaxi # XPeng Robotaxi 小鹏汽车Robotaxi 基于 Spring Cloud Alibaba 的 Robotaxi 微服务系统,面向自动驾驶出行场景,包含账户、订单、地图、自动驾驶、远程驾驶等业务域,以及一组对应的 Spring Boot 应用(`xp-robotaxi-*-boot`)用于实际部署。 --- ## 一、技术栈概览 - Java 8 - Spring Boot 2.7.7 - Spring Cloud 2021.0.5 - Spring Cloud Alibaba 2021.0.4.0 - Nacos(注册中心 / 配置中心) - Sentinel(流量控制与熔断降级) - Seata(分布式事务) - MyBatis-Plus(ORM) - Druid(数据库连接池) - Swagger / Springfox(接口文档) - Redis、MySQL、MongoDB 等 --- ## 二、顶层模块结构 根工程 `robotaxi` 下包含以下子模块: - `xp-robotaxi-api`:对外和内部共享的 API、DTO、proto 风格 VO 定义 - `xp-robotaxi-common`:公共能力(日志、权限、安全、数据源、Redis 等) - 一组 `xp-robotaxi-*-boot`:每个业务域对应的 Spring Boot 应用,可独立部署 下面重点说明各个 `boot` 模块的功能职责。 --- ## 三、Boot 应用模块职责 ### 1. xp-robotaxi-gateway-boot(网关应用) - 基于 Spring Cloud Gateway 的统一入口网关 - 负责路由转发、鉴权校验、限流熔断、灰度发布 - 统一接入层日志与基本安全控制 ### 2. xp-robotaxi-account-boot(账户中心) - 账户/用户域的对外应用 - 用户注册登录、账号信息管理、角色与权限管理 - 为管理后台和其他业务服务提供账户相关 REST 接口 ### 3. xp-robotaxi-automatic-pilot-boot(自动驾驶业务) - Robotaxi 自动驾驶业务对外应用 - 负责云端与 XPU 的消息交互(MQTT / Kafka),包括下行指令和上行状态 - 订单与自动驾驶系统联动(创建任务、控制任务、状态应答等) - 封装自动驾驶相关业务接口,供运营平台和其他服务调用 ### 4. xp-robotaxi-itinerary-boot(行程管理) - 行程生命周期管理应用 - 行程创建、修改、取消 - 行程状态跟踪、历史行程查询 - 与订单、地图等服务协同进行路径规划与调度 ### 5. xp-robotaxi-maintenance-boot(运维与车辆维护) - 车辆运维与保障相关应用 - 车辆维护计划、保养记录、故障报修流程 - 保单管理和维修记录追踪 - 为运营平台提供车辆健康状态和维护数据 ### 6. xp-robotaxi-map-boot(地图与位置服务) - 地图与位置相关应用 - 路线规划、距离与时间预估 - POI 查询、地理围栏管理 - 与自动驾驶、行程、订单等服务协同提供位置能力 ### 7. xp-robotaxi-operation-boot(运营管理) - 平台运营域应用 - 车辆调度策略、运营数据统计与报表 - 价格策略配置、优惠活动管理 - 支持运营后台对 Robotaxi 业务进行集中管理 ### 8. xp-robotaxi-order-boot(订单服务) - 订单全生命周期管理应用 - 下单、改派、取消、完成等订单流程 - 订单状态机与状态变更通知 - 与支付、行程、自动驾驶等服务联动 ### 9. xp-robotaxi-payment-boot(支付与结算) - 支付结算域应用 - 集成微信等第三方支付渠道 - 支付请求、退款、对账、结算与发票管理 - 对订单服务提供支付能力,对财务提供对账数据 ### 10. xp-robotaxi-push-message-boot(消息推送) - 消息通知与推送应用 - 支持短信、APP 推送、邮件、站内信等多种渠道 - 提供统一消息模板与发送接口 - 与订单、行程、运营等服务集成,实现业务事件触达用户 ### 11. xp-robotaxi-remote-driving-boot(远程驾驶) - 云代驾 / 远程驾驶应用 - 远程控制指令下发、实时状态回传 - 支持紧急接管、远程辅助等场景 - 与自动驾驶、行程、车辆状态服务协同 ### 12. xp-robotaxi-vehicle-convoy-boot(车队管理) - 车队及编队管理应用 - 车队组建与成员管理 - 编队行驶控制与协同调度 - 提供面向车队运营场景的接口能力 ### 13. xp-robotaxi-job-boot(定时任务) - 统一定时任务调度应用 - 基于 Quartz,对多业务域的定时任务进行集中管理 - 任务配置、执行监控、失败重试等 ### 14. xp-robotaxi-file-boot(文件服务) - 文件上传/下载/存储应用 - 支持对象存储或分布式文件系统接入 - 提供统一的文件访问域名与权限控制能力 --- ## 四、基础能力模块概览 虽然具体代码在 `xp-robotaxi-common` 与 `xp-robotaxi-api` 中,这里简要说明它们的角色,方便理解整体结构: - `xp-robotaxi-common`:日志、安全、数据源、Redis、数据权限、分布式事务等通用能力 - `xp-robotaxi-api`:对各个 boot 应用暴露的统一 API/DTO/VO 定义,是服务间通信的契约层 --- ## 五、运行与部署提示(概览) - 所有 `xp-robotaxi-*-boot` 模块均为独立 Spring Boot 应用,可按需选择部署 - 网关(`xp-robotaxi-gateway-boot`)通常需要多实例部署以保证高可用 - 订单、支付、自动驾驶、运营等核心域建议根据业务量做水平扩展 - Nacos / Sentinel / Seata 等基础组件需先行部署,并在各 boot 应用中配置好连接信息 --- *文档更新时间: 2026-02-06* xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserServiceImpl.java
@@ -182,6 +182,7 @@ //保存审核记录 XpQualificationAudit xpQualificationAudit = BeanUtil.copyProperties(dto, XpQualificationAudit.class, "id"); xpQualificationAudit.setAuditStatus(1); xpQualificationAudit.setOperationsUserId(dto.getId()); xpQualificationAuditService.save(xpQualificationAudit); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/account/XpOperationsUserProfileVO.java
@@ -62,6 +62,21 @@ @ApiModelProperty(value = "关联车队信息") private FleetInfoVO fleet; @ApiModelProperty(value = "身份证正面") private String idCardFront; @ApiModelProperty(value = "身份证背面") private String idCardBack; @ApiModelProperty(value = "驾驶证") private String driverLicense; @ApiModelProperty(value = "无犯罪记录正面") private String certificateOfNoCriminalRecord; @ApiModelProperty(value = "培训结业证") private String trainingGraduationCertificate; /** * 角色列表 */ xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -153,9 +153,22 @@ * @return */ @GetMapping("/base/v1/order/acceptingOrder") public R acceptingOrder(Long orderId, Long vehicleId, Double startLon, Double startLat){ public R acceptingOrder(Long orderId, String code, Long vehicleId, Double startLon, Double startLat){ if(null == vehicleId){ vehicleId = 1L; } if(null == startLat || null == startLon){ startLat = 23.157155D; startLon = 113.382373D; } XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData(); XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); XpOrder xpOrder = null; if(null != orderId){ xpOrder = xpOrderClient.queryOrderById(orderId).getData(); } if(StringUtils.isNotEmpty(code)){ xpOrder = xpOrderClient.queryOrderByOrderNo(code).getData(); } OrderRouteAndFareDto dto = new OrderRouteAndFareDto(); dto.setOrderId(orderId); LonLatDto origin = new LonLatDto(); @@ -199,17 +212,6 @@ log.error("推送消息失败:{}", stringR.getMsg()); } xpOrderClient.updateOrderStatus(orderId, OrderStatusEnum.PICK_UP.getCode()); // PushOrderRouteDTO dto3 = new PushOrderRouteDTO(); // dto3.setOrderId(orderId); // dto3.setRouteType(1); // dto3.setLongitude(startLon); // dto3.setLatitude(startLat); // dto3.setDuration(10); // dto3.setDistance(2); // dto3.setDirection(60); // xpPushMessageClient.pushOrderRoute(dto3); return r; } @@ -219,9 +221,18 @@ * @param orderId */ @GetMapping("/base/v1/order/pushStartDriverLocation") private void pushStartDriverLocation(Long vehicleId, Long orderId){ private void pushStartDriverLocation(Long vehicleId, Long orderId, String code){ if(null == vehicleId){ vehicleId = 1L; } XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData(); XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); XpOrder xpOrder = null; if(null != orderId){ xpOrder = xpOrderClient.queryOrderById(orderId).getData(); } if(StringUtils.isNotEmpty(code)){ xpOrder = xpOrderClient.queryOrderByOrderNo(code).getData(); } String vin = xpVehicle.getVehicleVin(); Long appUserId = xpOrder.getAppUserId(); Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId()); @@ -309,8 +320,14 @@ * @return */ @GetMapping("/base/v1/order/updateOrderStatus") public R updateOrderStatus(Long orderId, Integer status) { XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); public R updateOrderStatus(Long orderId, String code, Integer status) { XpOrder xpOrder = null; if(null != orderId){ xpOrder = xpOrderClient.queryOrderById(orderId).getData(); } if(StringUtils.isNotEmpty(code)){ xpOrder = xpOrderClient.queryOrderByOrderNo(code).getData(); } //构建推送消息 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); @@ -368,9 +385,18 @@ * @param orderId */ @GetMapping("/base/v1/order/pushEndDriverLocation") private void pushEndDriverLocation(Long vehicleId, Long orderId){ private void pushEndDriverLocation(Long vehicleId, Long orderId, String code){ if(null == vehicleId){ vehicleId = 1L; } XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData(); XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); XpOrder xpOrder = null; if(null != orderId){ xpOrder = xpOrderClient.queryOrderById(orderId).getData(); } if(StringUtils.isNotEmpty(code)){ xpOrder = xpOrderClient.queryOrderByOrderNo(code).getData(); } String vin = xpVehicle.getVehicleVin(); Long appUserId = xpOrder.getAppUserId(); Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId()); xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/config/MyLocaleResolver.java
@@ -23,11 +23,9 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } if(language==null){ language="1"; } //如果请求不为空 //如果请求不为空 //If the request is not empty. if (language.equals("1")) { locale = new Locale("zh", "CN"); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/config/MyLocaleResolver.java
@@ -23,12 +23,10 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. if(null == language){ language = "1"; } if (language.equals("1")) { locale = new Locale("zh", "CN"); } else if (language.equals("2")) { xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -110,174 +110,169 @@ } @Override public R addElectronic(ElectronicFenceAddDto dto) { try { // 获取现有的运营区域(areaType=1) LambdaQueryWrapper<XpElectronicFenceArea> xpElectronicFenceAreaLambdaQueryWrapper = new LambdaQueryWrapper<>(); xpElectronicFenceAreaLambdaQueryWrapper.eq(XpElectronicFenceArea::getAreaType, 1); List<XpElectronicFenceArea> existingOperationAreas = xpElectronicFenceAreaMapper.selectList(xpElectronicFenceAreaLambdaQueryWrapper); // 获取现有的运营区域(areaType=1) LambdaQueryWrapper<XpElectronicFenceArea> xpElectronicFenceAreaLambdaQueryWrapper = new LambdaQueryWrapper<>(); xpElectronicFenceAreaLambdaQueryWrapper.eq(XpElectronicFenceArea::getAreaType, 1); List<XpElectronicFenceArea> existingOperationAreas = xpElectronicFenceAreaMapper.selectList(xpElectronicFenceAreaLambdaQueryWrapper); // 获取待添加的新区域 List<XpElectronicFenceArea> newElectronicFenceAreas = dto.getElectronicFenceAreas(); // 获取待添加的新区域 List<XpElectronicFenceArea> newElectronicFenceAreas = dto.getElectronicFenceAreas(); // 检查新区域与现有运营区域是否有重叠 for (XpElectronicFenceArea newArea : newElectronicFenceAreas) { if (newArea.getAreaType() == 1) { // 只检查运营区域 for (XpElectronicFenceArea existingArea : existingOperationAreas) { if (polygonOverlapService.checkPolygonOverlap( newArea.getFencePoints(), existingArea.getFencePoints())) { throw new ServiceException( "运营区域{}与现有运营区域{}发生重叠", I18nKeyConstant.EDIT_ELECTRONIC_ERROR, new Object[]{existingArea.getAreaName(), existingArea.getAreaName()} ); } } } } // 保存主表数据 XpElectronicFence xpElectronicFence = new XpElectronicFence(); BeanUtils.copyProperties(dto, xpElectronicFence); xpElectronicFence.setStatus(0); if (dto.getStatus() == 0) { xpElectronicFence.setStatus(0); } else if (dto.getStatus() == 1) { if (dto.getEffectType() == 1) { // 设置为启用中 xpElectronicFence.setStatus(2); xpElectronicFence.setEffectTime(LocalDateTime.now()); } else { if (dto.getEffectTime().isBefore(LocalDateTime.now())) { // 设置为启用中 xpElectronicFence.setStatus(2); } else { xpElectronicFence.setStatus(1); } } } xpElectronicFence.setCityCode(dto.getCityCode()); // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收 XpRegion xpRegion = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>() .eq(XpRegion::getCode, dto.getCityCode())); String name = xpRegion.getName(); this.save(xpElectronicFence); // 根据城市中文名,截取前两位的首字母并且大写 // 截取前两个字符 String prefix = name.substring(0, 2); // 获取拼音首字母并大写 String result = getPinyinInitials(prefix).toUpperCase(); xpElectronicFence.setElectronicNumber(result + "-OP-" + String.format("%04d", xpElectronicFence.getId())); if (dto.getStatus() == 0) { xpElectronicFence.setStatus(0); } else if (dto.getStatus() == 1) { if (dto.getEffectType() == 1) { // 设置为启用中 xpElectronicFence.setStatus(2); xpElectronicFence.setEffectTime(LocalDateTime.now()); } else { if (dto.getEffectTime().isBefore(LocalDateTime.now())) { // 设置为启用中 xpElectronicFence.setStatus(2); } else { // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效 Map<String, ? extends Object> maps = new ImmutableMap.Builder<String, Long>(). put("type", 1L) .put("id", xpElectronicFence.getId()) .build(); QuartzManager.addJob( ElectronicEffectJob.class, (ElectronicEffectJob.effect + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_EFFECT, DateUtils.localDateTimeToDate(dto.getEffectTime()), maps // 检查新区域与现有运营区域是否有重叠 for (XpElectronicFenceArea newArea : newElectronicFenceAreas) { if (newArea.getAreaType() == 1) { // 只检查运营区域 for (XpElectronicFenceArea existingArea : existingOperationAreas) { if (polygonOverlapService.checkPolygonOverlap( newArea.getFencePoints(), existingArea.getFencePoints())) { throw new ServiceException( "运营区域{}与现有运营区域{}发生重叠", I18nKeyConstant.EDIT_ELECTRONIC_ERROR, new Object[]{existingArea.getAreaName(), existingArea.getAreaName()} ); xpElectronicFence.setStatus(1); } } if (dto.getFailureType() != null && dto.getFailureType() == 2) { if (dto.getFailureTime().isBefore(LocalDateTime.now())) { // 设置待启用 xpElectronicFence.setStatus(1); } else { // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效 Map<String, ? extends Object> maps = new ImmutableMap.Builder<String, Long>(). put("type", 2L) .put("id", xpElectronicFence.getId()) .build(); QuartzManager.addJob( ElectronicEffectJob.class, (ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE, DateUtils.localDateTimeToDate(dto.getEffectTime()), maps ); xpElectronicFence.setStatus(1); } } } this.updateById(xpElectronicFence); if (xpElectronicFence.getStatus() == 2) { // 设置电子围栏ID并保存区域数据 for (XpElectronicFenceArea area : newElectronicFenceAreas) { area.setElectronicId(xpElectronicFence.getId()); area.setAreaStatus(1); area.setArea(area.getArea()); area.setCityCode(dto.getCityCode()); xpElectronicFenceAreaMapper.insert(area); } }else{ // 设置电子围栏ID并保存区域数据 for (XpElectronicFenceArea area : newElectronicFenceAreas) { area.setElectronicId(xpElectronicFence.getId()); area.setAreaStatus(2); area.setArea(area.getArea()); area.setCityCode(dto.getCityCode()); xpElectronicFenceAreaMapper.insert(area); } } if (xpElectronicFence.getStatus() == 2) { for (XpElectronicFenceArea newElectronicFenceArea : newElectronicFenceAreas) { if (newElectronicFenceArea.getAreaType() == 1 && newElectronicFenceArea.getAreaStatus() == 1) { XpGeoFencingPolygon xpGeoFencingPolygon = new XpGeoFencingPolygon(); xpGeoFencingPolygon.setFenceId(String.valueOf(xpElectronicFence.getId())); xpGeoFencingPolygon.setName(xpElectronicFence.getElectronicName()); xpGeoFencingPolygon.setAreaId(String.valueOf(newElectronicFenceArea.getId())); xpGeoFencingPolygon.setCityCode(xpElectronicFence.getCityCode()); xpGeoFencingPolygon.setOperationStrategy(xpElectronicFence.getOperationStrategy()); // 将围栏点转换为GeoJSON多边形 GeoJsonPolygon geoJsonPolygon = convertToGeoJsonPolygon(newElectronicFenceArea.getFencePoints()); xpGeoFencingPolygon.setPoints(geoJsonPolygon); mongoTemplate.insert(xpGeoFencingPolygon); } if (newElectronicFenceArea.getAreaType() == 2 && newElectronicFenceArea.getAreaStatus() == 1) { XpGeoFencingProhibitedPolygon xpGeoFencingProhibitedPolygon = new XpGeoFencingProhibitedPolygon(); xpGeoFencingProhibitedPolygon.setFenceId(String.valueOf(xpElectronicFence.getId())); xpGeoFencingProhibitedPolygon.setName(xpElectronicFence.getElectronicName()); xpGeoFencingProhibitedPolygon.setAreaId(String.valueOf(newElectronicFenceArea.getId())); // 将围栏点转换为GeoJSON多边形 GeoJsonPolygon geoJsonPolygon = convertToGeoJsonPolygon(newElectronicFenceArea.getFencePoints()); xpGeoFencingProhibitedPolygon.setPoints(geoJsonPolygon); mongoTemplate.save(xpGeoFencingProhibitedPolygon); } } } return R.ok(); } catch (Exception e) { log.error("新增电子围栏失败", e); throw new ServiceException("新增电子围栏失败", I18nKeyConstant.ADD_ELECTRONIC_ERROR); } // 保存主表数据 XpElectronicFence xpElectronicFence = new XpElectronicFence(); BeanUtils.copyProperties(dto, xpElectronicFence); xpElectronicFence.setStatus(0); if (dto.getStatus() == 0) { xpElectronicFence.setStatus(0); } else if (dto.getStatus() == 1) { if (dto.getEffectType() == 1) { // 设置为启用中 xpElectronicFence.setStatus(2); xpElectronicFence.setEffectTime(LocalDateTime.now()); } else { if (dto.getEffectTime().isBefore(LocalDateTime.now())) { // 设置为启用中 xpElectronicFence.setStatus(2); } else { xpElectronicFence.setStatus(1); } } } xpElectronicFence.setCityCode(dto.getCityCode()); // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收 XpRegion xpRegion = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>() .eq(XpRegion::getCode, dto.getCityCode())); String name = xpRegion.getName(); this.save(xpElectronicFence); // 根据城市中文名,截取前两位的首字母并且大写 // 截取前两个字符 String prefix = name.substring(0, 2); // 获取拼音首字母并大写 String result = getPinyinInitials(prefix).toUpperCase(); xpElectronicFence.setElectronicNumber(result + "-OP-" + String.format("%04d", xpElectronicFence.getId())); if (dto.getStatus() == 0) { xpElectronicFence.setStatus(0); } else if (dto.getStatus() == 1) { if (dto.getEffectType() == 1) { // 设置为启用中 xpElectronicFence.setStatus(2); xpElectronicFence.setEffectTime(LocalDateTime.now()); } else { if (dto.getEffectTime().isBefore(LocalDateTime.now())) { // 设置为启用中 xpElectronicFence.setStatus(2); } else { // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效 Map<String, ? extends Object> maps = new ImmutableMap.Builder<String, Long>(). put("type", 1L) .put("id", xpElectronicFence.getId()) .build(); QuartzManager.addJob( ElectronicEffectJob.class, (ElectronicEffectJob.effect + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_EFFECT, DateUtils.localDateTimeToDate(dto.getEffectTime()), maps ); xpElectronicFence.setStatus(1); } } if (dto.getFailureType() != null && dto.getFailureType() == 2) { if (dto.getFailureTime().isBefore(LocalDateTime.now())) { // 设置待启用 xpElectronicFence.setStatus(1); } else { // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效 Map<String, ? extends Object> maps = new ImmutableMap.Builder<String, Long>(). put("type", 2L) .put("id", xpElectronicFence.getId()) .build(); QuartzManager.addJob( ElectronicEffectJob.class, (ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE, DateUtils.localDateTimeToDate(dto.getEffectTime()), maps ); xpElectronicFence.setStatus(1); } } } this.updateById(xpElectronicFence); if (xpElectronicFence.getStatus() == 2) { // 设置电子围栏ID并保存区域数据 for (XpElectronicFenceArea area : newElectronicFenceAreas) { area.setElectronicId(xpElectronicFence.getId()); area.setAreaStatus(1); area.setArea(area.getArea()); area.setCityCode(dto.getCityCode()); xpElectronicFenceAreaMapper.insert(area); } }else{ // 设置电子围栏ID并保存区域数据 for (XpElectronicFenceArea area : newElectronicFenceAreas) { area.setElectronicId(xpElectronicFence.getId()); area.setAreaStatus(2); area.setArea(area.getArea()); area.setCityCode(dto.getCityCode()); xpElectronicFenceAreaMapper.insert(area); } } if (xpElectronicFence.getStatus() == 2) { for (XpElectronicFenceArea newElectronicFenceArea : newElectronicFenceAreas) { if (newElectronicFenceArea.getAreaType() == 1 && newElectronicFenceArea.getAreaStatus() == 1) { XpGeoFencingPolygon xpGeoFencingPolygon = new XpGeoFencingPolygon(); xpGeoFencingPolygon.setFenceId(String.valueOf(xpElectronicFence.getId())); xpGeoFencingPolygon.setName(xpElectronicFence.getElectronicName()); xpGeoFencingPolygon.setAreaId(String.valueOf(newElectronicFenceArea.getId())); xpGeoFencingPolygon.setCityCode(xpElectronicFence.getCityCode()); xpGeoFencingPolygon.setOperationStrategy(xpElectronicFence.getOperationStrategy()); // 将围栏点转换为GeoJSON多边形 GeoJsonPolygon geoJsonPolygon = convertToGeoJsonPolygon(newElectronicFenceArea.getFencePoints()); xpGeoFencingPolygon.setPoints(geoJsonPolygon); mongoTemplate.insert(xpGeoFencingPolygon); } if (newElectronicFenceArea.getAreaType() == 2 && newElectronicFenceArea.getAreaStatus() == 1) { XpGeoFencingProhibitedPolygon xpGeoFencingProhibitedPolygon = new XpGeoFencingProhibitedPolygon(); xpGeoFencingProhibitedPolygon.setFenceId(String.valueOf(xpElectronicFence.getId())); xpGeoFencingProhibitedPolygon.setName(xpElectronicFence.getElectronicName()); xpGeoFencingProhibitedPolygon.setAreaId(String.valueOf(newElectronicFenceArea.getId())); // 将围栏点转换为GeoJSON多边形 GeoJsonPolygon geoJsonPolygon = convertToGeoJsonPolygon(newElectronicFenceArea.getFencePoints()); xpGeoFencingProhibitedPolygon.setPoints(geoJsonPolygon); mongoTemplate.save(xpGeoFencingProhibitedPolygon); } } } return R.ok(); } @Override xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/config/MyLocaleResolver.java
@@ -23,8 +23,6 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); } if (!StringUtils.hasLength(language)){ language = "1"; } //如果请求不为空 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderDetailVO.java
@@ -38,7 +38,7 @@ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime rideTime; @ApiModelProperty(value = "状态 0=已取消,1=待接单,2=待出发,3=待到达预约点,4=待乘客上车,5=服务中,6=待支付,7=待评价,8=已完成") @ApiModelProperty(value = "状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成") private Integer status; @ApiModelProperty(value = "下单城市名称") xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderPageVO.java
@@ -57,7 +57,6 @@ @ApiModelProperty(value = "订单金额") private BigDecimal orderMoney; @ApiModelProperty(value = "状态 0=已取消,1=待接单,2=待出发,3=待到达预约点,4=待乘客上车,5=服务中,6=待支付,7=待评价,8=已完成") @ApiModelProperty(value = "状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成") private Integer status; } xp-robotaxi-payment-boot/src/main/java/com/xiaopeng/payment/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/config/MyLocaleResolver.java
@@ -1,80 +1,81 @@ //package com.xiaopeng.pushMessage.config; // //import com.alibaba.fastjson.JSON; //import com.alibaba.fastjson.JSONObject; //import org.springframework.util.StringUtils; //import org.springframework.web.servlet.LocaleResolver; // //import javax.servlet.ServletInputStream; //import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletResponse; //import java.io.BufferedReader; //import java.io.InputStreamReader; //import java.util.Locale; // //public class MyLocaleResolver implements LocaleResolver { // // @Override // public Locale resolveLocale(HttpServletRequest request) { // //1=中文,2=英文,3=印尼文 // //1=Chinese, 2=English, 3=Indonesian. // String language = getQueryParams(request, "language"); // // Locale locale = null; // if (StringUtils.isEmpty(language)) { // locale = Locale.getDefault(); // } // //如果请求不为空 // //If the request is not empty. // if (language.equals("1")) { // locale = new Locale("zh", "CN"); // } else if (language.equals("2")) { // locale = new Locale("en", "US"); // } // return locale; // } // // @Override // public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { // } // // // public String getQueryParams(HttpServletRequest request, String key) { // try { // String method = request.getMethod(); // if("POST".equals(method)){ // String parameter = request.getParameter(key); // if(!StringUtils.isEmpty(parameter)){ // return parameter; // } // Object attribute = request.getAttribute(key); // if(null != attribute){ // return attribute.toString(); // } // StringBuffer sb = new StringBuffer(); // ServletInputStream inputStream = request.getInputStream(); // BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); // String s; // while ((s = bufferedReader.readLine()) != null){ // sb.append(s); // } // bufferedReader.close(); // inputStream.close(); // JSONObject jsonObject = JSON.parseObject(sb.toString()); // return jsonObject.getString(key); // }else{ // String parameter = request.getParameter(key); // if(!StringUtils.isEmpty(parameter)){ // return parameter; // } // Object attribute = request.getAttribute(key); // if(null != attribute){ // return attribute.toString(); // } // } // }catch (Exception e){ // e.printStackTrace(); // } // return null; // } //} package com.xiaopeng.pushMessage.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.util.StringUtils; import org.springframework.web.servlet.LocaleResolver; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Locale; public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { //1=中文,2=英文,3=印尼文 //1=Chinese, 2=English, 3=Indonesian. String language = getQueryParams(request, "language"); Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. if (language.equals("1")) { locale = new Locale("zh", "CN"); } else if (language.equals("2")) { locale = new Locale("en", "US"); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } public String getQueryParams(HttpServletRequest request, String key) { try { String method = request.getMethod(); if("POST".equals(method)){ String parameter = request.getParameter(key); if(!StringUtils.isEmpty(parameter)){ return parameter; } Object attribute = request.getAttribute(key); if(null != attribute){ return attribute.toString(); } StringBuffer sb = new StringBuffer(); ServletInputStream inputStream = request.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String s; while ((s = bufferedReader.readLine()) != null){ sb.append(s); } bufferedReader.close(); inputStream.close(); JSONObject jsonObject = JSON.parseObject(sb.toString()); return jsonObject.getString(key); }else{ String parameter = request.getParameter(key); if(!StringUtils.isEmpty(parameter)){ return parameter; } Object attribute = request.getAttribute(key); if(null != attribute){ return attribute.toString(); } } }catch (Exception e){ e.printStackTrace(); } return null; } } xp-robotaxi-remote-driving-boot/src/main/java/com/xiaopeng/remoteDriving/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty. xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/MyLocaleResolver.java
@@ -23,6 +23,7 @@ Locale locale = null; if (StringUtils.isEmpty(language)) { locale = Locale.getDefault(); language = "1"; } //如果请求不为空 //If the request is not empty.