xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointAddDto.java
@@ -18,6 +18,9 @@ public class PointAddDto implements Serializable { @ApiModelProperty(value = "电子围栏区域id") private Long electronicAreaId; @ApiModelProperty(value = "电子围栏id") private String fenceId; @ApiModelProperty(value = "点位名称") @NotEmpty(message = "点位名称不能为空") private String pointName; xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointUpdateDto.java
@@ -17,6 +17,10 @@ private Long id; @ApiModelProperty(value = "电子围栏区域id") private Long electronicAreaId; @ApiModelProperty(value = "围栏id") private String fenceId; @ApiModelProperty(value = "点位名称") @NotBlank(message = "点位名称不能为空") xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/XpOperationUserClient.java
@@ -2,6 +2,7 @@ import com.xiaopeng.api.dto.account.XpOperationsUserQueryDTO; import com.xiaopeng.api.factory.account.XpAppUserClientFallbackFactory; import com.xiaopeng.api.factory.account.XpOperationUserClientFallbackFactory; import com.xiaopeng.api.model.account.XpOperationsRole; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.vo.account.XpOperationsUserWithRoleVO; @@ -23,7 +24,7 @@ */ @FeignClient(contextId = "XpOperationUserClient", value = ServiceNameConstantsEnum.XP_ACCOUNT_SERVICE, fallbackFactory = XpAppUserClientFallbackFactory.class) fallbackFactory = XpOperationUserClientFallbackFactory.class) public interface XpOperationUserClient { /** * 根据ID列表批量查询运维用户信息 xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/maintenance/VehicleCleanQuery.java
@@ -10,4 +10,13 @@ public class VehicleCleanQuery extends BasePage { @ApiModelProperty(value = "车辆ID") private Long vehicleId; @ApiModelProperty(value = "开始时间") private String startTime; @ApiModelProperty(value = "结束时间") private String endTime; @ApiModelProperty(value = "操作人") private String operationUserName; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/operation/ElectronicPageListQuery.java
@@ -33,7 +33,7 @@ @ApiModelProperty(value = "更新结束时间") private String updateEndTime; @ApiModelProperty(value = "开始时间 1正序 2倒序") private String createSort; private Integer createSort; @ApiModelProperty(value = "更新时间 1正序 2倒序") private String updateSort; private Integer updateSort; } xp-robotaxi-automatic-pilot-boot/pom.xml
@@ -143,16 +143,6 @@ <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- <plugin>--> <!-- <groupId>org.apache.maven.plugins</groupId>--> <!-- <artifactId>maven-surefire-plugin</artifactId>--> <!-- <configuration>--> <!-- <argLine>--> <!-- --add-opens java.base/java.lang=ALL-UNNAMED--> <!-- --add-opens java.base/java.util=ALL-UNNAMED--> <!-- </argLine>--> <!-- </configuration>--> <!-- </plugin>--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -837,7 +837,6 @@ //下车完成 buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence); xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode()); // 下发巡游任务 R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId)); if(xpOrderR.getCode()==200){ xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java
@@ -10,7 +10,7 @@ /** * 缓存有效期,默认720(分钟) */ public final static long EXPIRATION = 720; public final static long EXPIRATION = 720 * 2; //24小时 public final static long EXPIRATION_APPLET = 365 * 24 * 60; /** xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/SecurityConstants.java
@@ -42,7 +42,7 @@ public static final String OPERATION_USER_KEY = "operation_user_key"; /** * 用户类型(system/applet) * 用户类型(system/operation) */ public static final String USER_TYPE = "user_type"; /** @@ -59,4 +59,9 @@ * 角色权限 */ public static final String ROLE_PERMISSION = "role_permission"; /** * 登录运维人员 */ public static final String LOGIN_OPERATION_USER = "login_oeeration_user"; } xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/context/SecurityContextHolder.java
@@ -76,11 +76,20 @@ return get(SecurityConstants.USER_KEY); } public static String getOperationUserKey() { return get(SecurityConstants.OPERATION_USER_KEY); } public static void setUserKey(String userKey) { set(SecurityConstants.USER_KEY, userKey); } public static void setOperationUserKey(String userKey) { set(SecurityConstants.OPERATION_USER_KEY, userKey); } public static String getPermission() { return get(SecurityConstants.ROLE_PERMISSION); xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/utils/JwtUtils.java
@@ -73,6 +73,17 @@ { return getValue(claims, SecurityConstants.USER_KEY); } /** * 根据令牌获取运维用户标识 * * @param claims 身份信息 * @return 用户ID */ public static String getOperationUserKey(Claims claims) { return getValue(claims, SecurityConstants.OPERATION_USER_KEY); } /** * 根据令牌获取用户类型 xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthLogic.java
@@ -4,6 +4,7 @@ import java.util.HashSet; import java.util.Set; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.common.core.utils.JwtUtils; import com.xiaopeng.api.vo.account.LoginUser; import io.jsonwebtoken.Claims; @@ -106,6 +107,16 @@ } /** * 获取当前运维用户缓存信息, 如果未登录,则抛出异常 * * @param token 前端传递的认证信息 * @return 用户缓存信息 */ public LoginOperationUser getOperationLoginUser(String token) { return tokenService.getLoginOperationUser(token); } /** * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存 * * @param loginUser 当前用户信息 @@ -116,6 +127,16 @@ } /** * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存 * * @param loginOperationUser 当前用户信息 */ public void verifyOperationLoginUserExpire(LoginOperationUser loginOperationUser) { tokenService.verifyToken(loginOperationUser); } /** * 验证用户是否具备某权限 * * @param permission 权限字符串 xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthUtil.java
@@ -1,5 +1,6 @@ package com.xiaopeng.common.security.auth; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.common.security.annotation.RequiresPermissions; import com.xiaopeng.common.security.annotation.RequiresRoles; import com.xiaopeng.api.vo.account.LoginUser; @@ -54,6 +55,17 @@ } /** * 获取当前登录用户信息 * * @param token 指定token * @return 用户信息 */ public static LoginOperationUser getOperationLoginUser(String token) { return authLogic.getOperationLoginUser(token); } /** * 验证当前用户有效期 * * @param loginUser 用户信息 @@ -62,7 +74,15 @@ { authLogic.verifyLoginUserExpire(loginUser); } /** * 验证当前用户有效期 * * @param loginOperationUser 用户信息 */ public static void verifyOperationLoginUserExpire(LoginOperationUser loginOperationUser) { authLogic.verifyOperationLoginUserExpire(loginOperationUser); } /** * 当前账号是否含有指定角色标识, 返回true或false * xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/interceptor/HeaderInterceptor.java
@@ -3,7 +3,10 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.api.vo.account.LoginUser; import com.xiaopeng.common.core.utils.JwtUtils; import io.jsonwebtoken.Claims; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.AsyncHandlerInterceptor; import com.xiaopeng.common.core.constant.SecurityConstants; @@ -32,15 +35,27 @@ SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID)); SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME)); SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY)); SecurityContextHolder.setOperationUserKey(ServletUtils.getHeader(request, SecurityConstants.OPERATION_USER_KEY)); String token = SecurityUtils.getToken(); if (StringUtils.isNotEmpty(token)) { LoginUser loginUser = AuthUtil.getLoginUser(token); if (StringUtils.isNotNull(loginUser)) { AuthUtil.verifyLoginUserExpire(loginUser); SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); String userType = JwtUtils.getUserType(token); if ("system".equals(userType)) { LoginUser loginUser = AuthUtil.getLoginUser(token); if (StringUtils.isNotNull(loginUser)) { AuthUtil.verifyLoginUserExpire(loginUser); SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); } } if ("operation".equals(userType)) { LoginOperationUser operationLoginUser = AuthUtil.getOperationLoginUser(token); if (StringUtils.isNotNull(operationLoginUser)) { AuthUtil.verifyOperationLoginUserExpire(operationLoginUser); SecurityContextHolder.set(SecurityConstants.LOGIN_OPERATION_USER, operationLoginUser); } } } return true; xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/service/TokenService.java
@@ -207,6 +207,19 @@ refreshToken(loginUser); } } /** * 验证令牌有效期,相差不足120分钟,自动刷新缓存 * * @param loginOperationUser */ public void verifyToken(LoginOperationUser loginOperationUser) { long expireTime = loginOperationUser.getExpireTime(); long currentTime = System.currentTimeMillis(); if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { refreshTokenOperationUser(loginOperationUser); } } /** * 刷新令牌有效期 xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/utils/SecurityUtils.java
@@ -2,6 +2,7 @@ import javax.servlet.http.HttpServletRequest; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.api.vo.account.LoginUser; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import com.xiaopeng.common.core.constant.SecurityConstants; @@ -50,6 +51,13 @@ } /** * 获取登录运维人员信息 */ public static LoginOperationUser getLoginOperationUser() { return SecurityContextHolder.get(SecurityConstants.LOGIN_OPERATION_USER, LoginOperationUser.class); } /** * 获取请求token */ public static String getToken() xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/filter/AuthFilter.java
@@ -66,18 +66,37 @@ }catch (Exception e){ return unauthorizedResponse(exchange, e.getMessage()); } String token = getToken(request); Claims claims = JwtUtils.parseToken(token); String userkey = JwtUtils.getUserKey(claims); String userid = JwtUtils.getUserId(claims); String username = JwtUtils.getUserName(claims); String userType = JwtUtils.getUserType(claims); String operationUserKey = JwtUtils.getOperationUserKey(claims); String redisKey = ""; if ("system".equals(userType)) { redisKey = StringUtils.isNotBlank(userkey) ? getTokenKey(userkey) : ""; } if ("operation".equals(userType)) { redisKey = StringUtils.isNotBlank(operationUserKey) ? getTokenKey(operationUserKey) : ""; } if (StringUtils.isBlank(redisKey)) { return unauthorizedResponse(exchange, "登录状态已过期"); } boolean islogin = redisService.hasKey(redisKey); if (!islogin) { return unauthorizedResponse(exchange, "登录状态已过期"); } // 设置用户信息到请求 addHeader(mutate, SecurityConstants.USER_KEY, userkey); addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); addHeader(mutate, SecurityConstants.USER_TYPE, userType); addHeader(mutate, SecurityConstants.OPERATION_USER_KEY, operationUserKey); // 内部请求来源参数清除 removeHeader(mutate, SecurityConstants.FROM_SOURCE); return chain.filter(exchange.mutate().request(mutate.build()).build()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java
@@ -9,4 +9,5 @@ String TASK_NOT_EXIST = "task.not.exist"; String VEHICLE_NOT_EXIST = "vehicle.not.exist"; String REPAIR_MONEY_TOO_LONG = "repair.money.too.long"; } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleCleanController.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xiaopeng.api.feignClient.account.XpOperationUserClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.model.maintenance.XpVehicleClean; import com.xiaopeng.api.query.maintenance.VehicleCleanQuery; import com.xiaopeng.common.core.domain.R; @@ -22,6 +23,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.stream.Collectors; /** * <p> @@ -84,7 +88,40 @@ @PostMapping("/api/v1/vehicleClean/list") public R<PageInfo<XpVehicleClean>> list(@RequestBody VehicleCleanQuery query) { PageInfo<XpVehicleClean> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); PageInfo<XpVehicleClean> page = xpVehicleCleanService.page(pageInfo, new LambdaQueryWrapper<XpVehicleClean>().eq(XpVehicleClean::getVehicleId, query.getVehicleId()).orderByDesc(BaseModel::getCreateTime)); LambdaQueryWrapper<XpVehicleClean> wrapper = new LambdaQueryWrapper<XpVehicleClean>().eq(XpVehicleClean::getVehicleId, query.getVehicleId()); List<XpOperationsUser> data=null; if(query.getOperationUserName()!=null && !query.getOperationUserName().isEmpty()){ R<List<XpOperationsUser>> r = xpOperationUserClient.listByName(query.getOperationUserName()); if(r.getCode()!=200 || r.getData().isEmpty()){ return R.ok(pageInfo); } data = r.getData(); wrapper.in(XpVehicleClean::getOperationsUserId, data.stream().map(XpOperationsUser::getId).collect(Collectors.toList())); } if(query.getStartTime()!=null && !query.getStartTime().isEmpty() && query.getEndTime()!=null && !query.getEndTime().isEmpty()){ wrapper.between(XpVehicleClean::getCreateTime, query.getStartTime(), query.getEndTime()); } PageInfo<XpVehicleClean> page = xpVehicleCleanService.page(pageInfo, wrapper.orderByDesc(BaseModel::getCreateTime)); List<XpVehicleClean> records = page.getRecords(); if(data==null){ List<Long> userIds = records.stream().map(XpVehicleClean::getOperationsUserId).collect(Collectors.toList()); if(userIds.isEmpty()){ return R.ok(page); } R<List<XpOperationsUser>> r = xpOperationUserClient.listByIds(userIds); if(r.getData().isEmpty()){ return R.ok(page); } data = r.getData(); } for (XpVehicleClean record : records) { data.stream().filter(xpOperationsUser -> xpOperationsUser.getId().equals(record.getOperationsUserId())).findFirst().ifPresent(xpOperationsUser -> record.setCreateBy(xpOperationsUser.getNickName())); } return R.ok(page); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java
@@ -3,8 +3,10 @@ import com.xiaopeng.api.model.maintenance.XpVehicleRepair; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.service.TokenService; import com.xiaopeng.maintenance.constant.I18nKeyConstant; import com.xiaopeng.maintenance.dto.XpVehicleRepairReturnDTO; import com.xiaopeng.maintenance.dto.XpVehicleRepairStartDTO; import com.xiaopeng.maintenance.model.query.XpVehicleRepairPageQuery; @@ -56,6 +58,9 @@ @PostMapping("/api/v1/vehicleRepair/saveReturnRepair") public R<String> saveReturnRepair(@Validated @RequestBody XpVehicleRepairReturnDTO dto) { Long id = tokenService.getLoginOperationUser().getId(); if (dto.getRepairMoney().toString().length() > 200) { throw new ServiceException("维修费用不能超过200字符", I18nKeyConstant.REPAIR_MONEY_TOO_LONG); } xpVehicleRepairService.saveReturnRepair(dto,id); return R.ok(); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/XpVehicleRepairReturnDTO.java
@@ -5,6 +5,7 @@ import lombok.Data; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Max; import java.io.Serializable; @Data @@ -14,7 +15,6 @@ @ApiModelProperty(value = "维修id") private Long id; @Length(max = 200, message = "维修费用长度不能超过200字") @ApiModelProperty(value = "维修费用") private Double repairMoney; xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -1,4 +1,5 @@ # 中文 welcome.message=欢迎来到我们的应用程序! task.not.exist=任务不存在 vehicle.not.exist=车辆不存在 vehicle.not.exist=车辆不存在 repair.money.too.long=维修费用不能超过200字符 xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -2,4 +2,5 @@ welcome.message=Welcome to our application! task.not.exist=The task does not exist. vehicle.not.exist=The vehicle does not exist. repair.money.too.long=The maintenance cost cannot exceed 200 characters task.rule.not.config=The vehicle accident task allocation rules have not been configured xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -2,4 +2,5 @@ welcome.message=欢迎来到我们的应用程序! task.not.exist=任务不存在 vehicle.not.exist=车辆不存在 repair.money.too.long=维修费用不能超过200字符 task.rule.not.config=未配置车辆事故任务分配规则 xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java
@@ -16,6 +16,7 @@ import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.api.dto.map.XpPointExportExcelQuery; import com.xiaopeng.map.exportExcel.XpPointExportExcel; import com.xiaopeng.map.mangodb.service.XpGeoFencingPolygonService; import com.xiaopeng.map.service.XpElectronicFenceAreaService; import com.xiaopeng.map.service.XpElectronicFenceService; import com.xiaopeng.map.service.XpPointService; @@ -64,6 +65,8 @@ private XpElectronicFenceAreaService xpElectronicFenceAreaService; @Resource private XpElectronicFenceService xpElectronicFenceService; @Resource private XpGeoFencingPolygonService xpGeoFencingPolygonService; @ApiOperation(value = "获取所有运营中的区域", response = XpElectronicFenceArea.class) @@ -151,7 +154,10 @@ @PostMapping("/add") @ResponseBody @ApiOperation(value = "新增点位") public R<XpPoint> add(@Validated @RequestBody PointAddDto pointAddDto) { public R<?> add(@Validated @RequestBody PointAddDto pointAddDto) { if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } return R.ok(xpPointService.addPointWithGeneratedNumber(pointAddDto)); } @@ -177,8 +183,17 @@ XpPoint xpPoint = xpPointService.getById(pointAddDto.getId()); if (!xpPoint.getElectronicAreaId().equals(pointAddDto.getElectronicAreaId())) { BeanUtils.copyProperties(pointAddDto, xpPoint); if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } xpPointService.updateById(xpPoint); } else { if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } //先删除原有的数据,因为会存在点位的从属区域变化的情况,所以先删除原有的数据后添加新的数据重新分片到新的库中 BeanUtils.copyProperties(pointAddDto, xpPoint); xpPointService.removeById(pointAddDto.getId()); xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -86,9 +86,6 @@ } normalizeProhibitedAreaCountFilter(query); PageInfo<XpElectronicFence> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); if (StringUtils.isEmpty(query.getCreateSort())&& StringUtils.isEmpty(query.getUpdateSort())){ query.setCreateSort("2"); } List<XpElectronicFence> list = this.baseMapper.pageList(pageInfo, query); if (list.isEmpty()) { return new PageInfo<>(); xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java
@@ -254,10 +254,10 @@ if(routePlanRule!=null){ params.put("strategy", routePlanRule); } log.info("高德地图接口:{}", url); log.info("高德地图参数:{}", params); String post = HttpUtils.post(url, JSON.toJSONString(params)); System.out.println("高德地图返回结果:"+ post); // String forObject = restTemplate.getForObject(url, String.class, params); log.info("高德地图返回结果:"+ post); JSONObject jsonObject = JSON.parseObject(post); String data = jsonObject.getString("data"); xp-robotaxi-map-boot/src/main/resources/mapper/XpElectronicFenceMapper.xml
@@ -30,7 +30,7 @@ from xp_electronic_fence ef left join xp_electronic_fence_area efa on efa.electronic_id = ef.id and efa.is_deleted = 0 where ef.is_deleted = 0 <if test="query.electronicNumberOrName != null"> <if test="query.electronicNumberOrName != null and query.electronicNumberOrName != ''"> and( ef.electronic_name like concat('%',#{query.electronicNumberOrName},'%') or ef.electronic_number like concat('%',#{query.electronicNumberOrName},'%') ) @@ -71,39 +71,27 @@ having sum(case when efa.area_type = 2 then 1 else 0 end) <= #{query.prohibitedAreaCountMax} </when> </choose> <if test="query.createSort != null and query.updateSort != null"> order by <if test="query.createSort == 1"> ef.create_time asc, </if> <if test="query.createSort == 2"> ef.create_time desc, </if> <if test="query.updateSort == 1"> ef.update_time asc </if> <if test="query.updateSort == 2"> ef.update_time desc </if> </if> <if test="query.createSort != null"> order by <if test="query.createSort == 1"> ef.create_time asc </if> <if test="query.createSort == 2"> ef.create_time desc </if> </if> <if test="query.updateSort != null"> order by <if test="query.updateSort == 1"> ef.update_time asc </if> <if test="query.updateSort == 2"> ef.update_time desc </if> </if> <choose> <when test="query.createSort == 1 or query.createSort == 2 or query.updateSort == 1 or query.updateSort == 2"> <trim prefix="order by" suffixOverrides=","> <if test="query.createSort == 1"> ef.create_time asc, </if> <if test="query.createSort == 2"> ef.create_time desc, </if> <if test="query.updateSort == 1"> ef.update_time asc, </if> <if test="query.updateSort == 2"> ef.update_time desc, </if> </trim> </when> <otherwise> order by ef.update_time desc </otherwise> </choose> </select> xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -60,7 +60,7 @@ @PostMapping("/base/v1/mini-program/navigation/route-and-fare") @ApiOperation(value = "导航-获取路线和费用", tags = {"小程序-获取路线和费用"}, response = RouteAndFareVo.class) @ApiOperation(value = "导航-获取路线和费用(弃用)", tags = {"小程序-获取路线和费用(弃用)"}, response = RouteAndFareVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<RouteAndFareVo> getRouteAndFare(@RequestBody @Valid RouteAndFareDto routeAndFareDto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 @@ -83,7 +83,7 @@ @GetMapping("/base/v1/mini-program/pricing/rules/{openCityId}") @ApiOperation(value = "获取费用规则", tags = {"小程序-根据开通城市获取费用规则"}, response = String.class) @ApiOperation(value = "获取费用规则(弃用)", tags = {"小程序-根据开通城市获取费用规则(弃用)"}, response = String.class) public R<?> getPricingRules(@PathVariable Long openCityId) { XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, openCityId).eq(XpPricing::getPricingType, 1).last("limit 1")); if (xpPricing != null) { @@ -99,7 +99,7 @@ * @return */ @PostMapping("/base/v1/mini-program/pricing/getWaitTime") @ApiOperation(value = "获取等待时间", tags = {"小程序-获取等待时间"}, response = Integer.class) @ApiOperation(value = "获取等待时间(弃用)", tags = {"小程序-获取等待时间(弃用)"}, response = Integer.class) public R<Integer> getWaitTime(@RequestBody LonLatDto dto) { return R.ok(xpPricingService.getWaitTime(dto.getLongitude(), dto.getLatitude())); } @@ -151,7 +151,7 @@ * 播单 */ @PostMapping("/base/v1/mini-program/order/save") @ApiOperation(value = "保存订单", tags = {"小程序-保存订单"}) @ApiOperation(value = "保存订单(弃用)", tags = {"小程序-保存订单(弃用)"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<SaveOrderVo> saveOrder(@RequestBody @Validated XpOrderDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpElectronicFenceMapper.xml
@@ -12,7 +12,7 @@ from xp_electronic_fence ef left join xp_electronic_fence_area efa on efa.electronic_id = ef.id where ef.is_deleted = 0 <if test="query.electronicNumberOrName != null"> <if test="query.electronicNumberOrName != null and query.electronicNumberOrName != ''"> and( ef.electronic_name like concat('%',#{query.electronicNumberOrName},'%') or ef.electronic_number like concat('%',#{query.electronicNumberOrName},'%') ) @@ -45,39 +45,27 @@ and #{query.updateEndTime} >= ef.update_time </if> group by ef.id <if test="query.createSort != null and query.updateSort != null"> order by <if test="query.createSort == 1"> ef.create_time asc, </if> <if test="query.createSort == 2"> ef.create_time desc, </if> <if test="query.updateSort == 1"> ef.update_time asc </if> <if test="query.updateSort == 2"> ef.update_time desc </if> </if> <if test="query.createSort != null"> order by <if test="query.createSort == 1"> ef.create_time asc </if> <if test="query.createSort == 2"> ef.create_time desc </if> </if> <if test="query.updateSort != null"> order by <if test="query.updateSort == 1"> ef.update_time asc </if> <if test="query.updateSort == 2"> ef.update_time desc </if> </if> <choose> <when test="query.createSort == 1 or query.createSort == 2 or query.updateSort == 1 or query.updateSort == 2"> <trim prefix="order by" suffixOverrides=","> <if test="query.createSort == 1"> ef.create_time asc, </if> <if test="query.createSort == 2"> ef.create_time desc, </if> <if test="query.updateSort == 1"> ef.update_time asc, </if> <if test="query.updateSort == 2"> ef.update_time desc, </if> </trim> </when> <otherwise> order by ef.update_time desc </otherwise> </choose> </select> xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -97,9 +97,9 @@ */ @PostMapping("/inner/order/has-unpaid-order") @ApiOperation(value = "查询是否有未支付订单 或 正在进行的订单", tags = {"内部接口"}) public R<Long> hasUnPaodOrder(String uid){ public R<Long> hasUnPaodOrder(String uid) { List<XpOrder> list = xpOrderService.list(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.parseLong(uid)).in(XpOrder::getStatus, Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8))); if(!list.isEmpty()){ if (!list.isEmpty()) { return R.ok(list.get(0).getId()); } return R.ok(0l); @@ -113,12 +113,12 @@ * @return 订单详情 */ @PostMapping("/inner/order/queryOrderById") public R<XpOrder> queryOrderById(@RequestParam Long orderId){ public R<XpOrder> queryOrderById(@RequestParam Long orderId) { return R.ok(xpOrderService.getById(orderId)); } @PostMapping("/inner/order/queryOrderByOrderNo") public R<XpOrder> queryOrderByOrderNo(@RequestParam String orderNo){ public R<XpOrder> queryOrderByOrderNo(@RequestParam String orderNo) { return R.ok(xpOrderService.getOne(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getOrderNumber, orderNo))); } @@ -128,17 +128,16 @@ * @return 订单数量 */ @PostMapping("/inner/order/getOrderNum") public R<Integer> getOrderNum(@RequestBody GetOrderNumDto dto){ public R<Integer> getOrderNum(@RequestBody GetOrderNumDto dto) { return R.ok(xpOrderService.getOrderNum(dto)); } /** * 成功操作下发命令后调用 用于弹出redis队列的获取成功的数据 */ @PostMapping("/inner/order/popOrder") public R<?> popOrder(@RequestBody PopOrderDto dto){ public R<?> popOrder(@RequestBody PopOrderDto dto) { xpOrderService.popOrder(dto); return R.ok(); } @@ -149,9 +148,9 @@ * @param xpOrder 订单信息 */ @PostMapping("/inner/order/updateOrder") public R<?> updateOrder(@RequestBody XpOrder xpOrder){ public R<?> updateOrder(@RequestBody XpOrder xpOrder) { xpOrder.setAppUserId(null); return xpOrderService.updateById(xpOrder)?R.ok():R.fail(); return xpOrderService.updateById(xpOrder) ? R.ok() : R.fail(); } @@ -162,9 +161,9 @@ * @return 订单ID */ @PostMapping("/inner/order/addOrder") public R<Long> addOrder(@RequestBody XpOrder xpOrder){ public R<Long> addOrder(@RequestBody XpOrder xpOrder) { boolean save = xpOrderService.addOrder(xpOrder); if(!save){ if (!save) { return R.fail("新增失败"); } return R.ok(xpOrder.getId()); @@ -178,7 +177,7 @@ * @return 操作结果 */ @PostMapping("/inner/order/cancelOrder") public R<?> cancelOrder(@RequestParam("orderId") String orderId){ public R<?> cancelOrder(@RequestParam("orderId") String orderId) { xpOrderService.cancelOrder(orderId); return R.ok(); } @@ -281,38 +280,42 @@ * @param dto 改派请求参数 * @return 操作结果 */ @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"},notes = "车辆列表在vehicleConvoy服务") @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"}, notes = "车辆列表在vehicleConvoy服务") @PostMapping("/api/v1/order/reassignById") public R<?> reassignById(@Validated @RequestBody XpOrderReassignDTO dto) { xpOrderService.reassignOrder( dto.getOrderId(), dto.getVehicleId(), dto.getReassignReason() dto.getOrderId(), dto.getVehicleId(), dto.getReassignReason() ); return R.ok(); } @ApiOperation(value = "订单改价", tags = {"管理后台-交易管理-订单管理"}) @PostMapping("/api/v1/order/changeAmount") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "amount", value = "新的订单金额", required = true, dataType = "BigDecimal") }) public R<?> changeAmount(@RequestParam("id") Long id ,@RequestParam("amount") BigDecimal amount) { public R<?> changeAmount(@RequestParam("id") Long id, @RequestParam("amount") BigDecimal amount) { xpOrderService.changeAmount(id, amount); return R.ok(); } /** * 获取用户快捷胶囊 历史 时段 终点高点 */ @ApiOperation(value = "获取用户快捷胶囊 历史 时段 终点高点", tags = {"小程序-获取用户快捷胶囊 历史 时段 终点高点"}) @GetMapping("/api/v1/mini-program/order/getUserQuickCapsule") @XpClientCheck(checkToken = false, checkOtpToken = true) public R<XpPointInfoVo> getUserQuickCapsule(HttpServletRequest request) { public R<XpPointInfoVo> getUserQuickCapsule(HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getUserQuickCapsule(uid)); } /** * 获取订单详情 */ @@ -322,7 +325,7 @@ public R<OrderDetailVo> orderDetail(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.orderDetail(orderId,uid)); return R.ok(xpOrderService.orderDetail(orderId, uid)); } @@ -332,21 +335,22 @@ @ApiOperation(value = "获取历史下单成功起点10条数据列表", tags = {"小程序-获取历史下单成功起点10条数据列表"}) @GetMapping("/base/v1/mini-program/history/startPoints") @XpClientCheck(checkToken = false, checkOtpToken = true) public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon,double lat,HttpServletRequest request) { public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon, double lat, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryStartPoints(uid,lon,lat)); return R.ok(xpOrderService.getHistoryStartPoints(uid, lon, lat)); } /** * 获取历史下单成功终点点10条数据列表 */ @ApiOperation(value = "获取历史下单成功终点10条数据列表", tags = {"小程序-获取历史下单成功终点10条数据列表"}) @GetMapping("/base/v1/mini-program/history/endPoints") @XpClientCheck(checkToken = false, checkOtpToken = true) public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat, HttpServletRequest request) { public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryEndPoints(uid,lon,lat)); return R.ok(xpOrderService.getHistoryEndPoints(uid, lon, lat)); } @@ -356,7 +360,7 @@ @ApiOperation(value = "获取正在进行中的订单", tags = {"小程序-获取正在进行中的订单"}) @GetMapping("/api/v1/mini-program/order/active") @XpClientCheck(checkToken = false, checkOtpToken = true) public R<XpOrderDetailVO> getActiveOrder(HttpServletRequest request) { public R<XpOrderDetailVO> getActiveOrder(HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getActiveOrder(uid)); @@ -369,49 +373,50 @@ @ApiOperation(value = "查询历史订单列表", tags = {"小程序-查询历史订单列表"}) @PostMapping("/api/v1/mini-program/order/history/list") @XpClientCheck(checkToken = false, checkOtpToken = true) public R<XpOrderHistoryVO> getHistoryOrderList(@RequestBody XpHistoryOrderListQuery query, HttpServletRequest request) { public R<XpOrderHistoryVO> getHistoryOrderList(@RequestBody XpHistoryOrderListQuery query, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.getHistoryOrderList(query, uid)); } /**+ /** * + * 取消订单 */ @PutMapping("/api/v1/mini-program/order/cancel/{orderId}") @ApiOperation(value = "取消订单", tags = {"小程序-取消订单"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R cancelOrder(@PathVariable("orderId") Long orderId,HttpServletRequest request) { public R cancelOrder(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); xpOrderService.cancelOrder(orderId,uid); xpOrderService.cancelOrder(orderId, uid); return R.ok(); } /**+ /** * + * 手动结束订单 */ @PutMapping("/api/v1/mini-program/order/endTrip/{orderId}") @ApiOperation(value = "结束行程", tags = {"小程序-结束行程"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R endTrip(@PathVariable("orderId") Long orderId,HttpServletRequest request) { public R endTrip(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); try { xpOrderService.endTrip(orderId,uid); }catch (Exception e){ xpOrderService.endTrip(orderId, uid); } catch (Exception e) { return R.ok(); } return R.ok(); } /**+ /** * + * 获取行程费用明细 */ @PutMapping("/api/v1/mini-program/order/fare-breakdown/{orderId}") @@ -420,9 +425,11 @@ public R<FareBreakdownVo> fareBreakdown(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.fareBreakdown(orderId,uid); return xpOrderService.fareBreakdown(orderId, uid); } /**+ /** * + * 获取行程费用明细 */ @PutMapping("/api/v1/mini-program/order/feeDescription/{orderId}") @@ -431,8 +438,9 @@ public R<String> feeDescription(@PathVariable("orderId") Long orderId, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.feeDescription(orderId,uid); return xpOrderService.feeDescription(orderId, uid); } /** * 订单评价 */ @@ -442,7 +450,7 @@ public R payment(@Validated @RequestBody XpOrderPayDto dto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return xpOrderService.payment(dto,uid); return xpOrderService.payment(dto, uid); } /** @@ -454,7 +462,7 @@ public R comment(@Validated @RequestBody XpOrderCommentDto dto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); xpOrderService.comment(dto,uid); xpOrderService.comment(dto, uid); return R.ok(); } @@ -465,7 +473,7 @@ @PostMapping("/inner/v1/order/updateOrderStatus") public R<String> updateOrderStatus(@RequestParam Long orderId, @RequestParam Integer status) { return xpOrderService.updateOrderStatus(orderId,status); return xpOrderService.updateOrderStatus(orderId, status); } /** @@ -476,7 +484,7 @@ @GetMapping("/api/v1/mini-program/order/queryVehicleByOrderId") public R<XpVehicle> queryVehicleByOrderId(@RequestParam Long orderId, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpOrderService.queryVehicleByOrderId(orderId,uid)); return R.ok(xpOrderService.queryVehicleByOrderId(orderId, uid)); } /** @@ -505,11 +513,11 @@ String key = ""; //接驾情况,获取车辆位置到起点的导航 if(xpOrder.getStatus() < 5){ if (xpOrder.getStatus() < 5) { key = "ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId(); } //服务中,获取起点到终点的导航数据 if(xpOrder.getStatus() >= 5){ if (xpOrder.getStatus() >= 5) { key = "ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId(); } Object cacheObject = redisService.getCacheObject(key); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/OrderCancelJob.java
@@ -1,8 +1,11 @@ package com.xiaopeng.order.job.jobs; import com.alibaba.fastjson2.JSONObject; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.core.enums.PushMessageTypeEnum; @@ -37,8 +40,23 @@ XpOrder xpOrder = xpOrderService.getById(orderId); if(Objects.nonNull(xpOrder) && xpOrder.getStatus()==4){ log.info("订单取消开始"); xpOrderService.cancelOrder(String.valueOf(xpOrder.getId())); log.info("订单取消状态修改完成"); XpOrder order = xpOrderService.cancelOrder(String.valueOf(xpOrder.getId())); // 下发命令 if (null != order.getVehicleId()) { R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); XpVehicle xpVehicle = xpVehicleR.getData(); //还原车辆状态为空闲 xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0)); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); //车辆继续巡游单 xpOrderService.addCruiseMission(xpVehicle); } log.info("订单取消状态修改完成"); } }catch(Exception e){ e.printStackTrace(); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -142,7 +142,7 @@ * 取消订单 * @param orderId */ void cancelOrder(String orderId); XpOrder cancelOrder(String orderId); /** * 评价订单 @@ -169,6 +169,12 @@ */ void addCruiseMission(XpVehicle vehicle, XpOrder order); /** * 取消订单后的继续巡游任务 * @param vehicle */ void addCruiseMission(XpVehicle vehicle); R<FareBreakdownVo> fareBreakdown(Long orderId, String uid); R payment(XpOrderPayDto dto, String uid); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -316,7 +316,7 @@ // 6. 获取评价信息 LambdaQueryWrapper<XpOrderEvaluate> evaluateWrapper = new LambdaQueryWrapper<>(); evaluateWrapper.eq(XpOrderEvaluate::getOrderId, id); XpOrderEvaluate evaluate = xpOrderEvaluateService.getOne(evaluateWrapper); XpOrderEvaluate evaluate = xpOrderEvaluateService.getOne(evaluateWrapper.orderByDesc(XpOrderEvaluate::getCreateTime).last(" limit 0,1")); if (Objects.nonNull(evaluate)) { vo.setOrderRating(evaluate.getOrderRating()); } @@ -641,8 +641,22 @@ orderCancel.setUserId(SecurityUtils.getUserId()); // 当前登录用户ID orderCancel.setCancelReason("运营人员取消订单"); xpOrderCancelService.save(orderCancel); // 消息推送 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); content.put("orderId", order.getId().toString()); content.put("status", OrderStatusEnum.CANCELED.getCode()); params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc()); params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content)); params.put("timestamp", new Date().getTime() + ""); String message = JSONObject.toJSONString(params); SendMessageDTO sendMessageDTO = new SendMessageDTO(); sendMessageDTO.setMessage(message); sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId())); xpPushMessageClient.sendStatus(sendMessageDTO); //查询车辆信息 R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getId()); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); if (xpVehicleR.getCode() == HttpStatus.SUCCESS && Objects.nonNull(xpVehicleR.getData())) { XpVehicle xpVehicle = xpVehicleR.getData(); // 组装调用车机参数 @@ -650,9 +664,7 @@ cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(order.getAppUserId().toString()); cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(appid); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); if (baseVehicleUserDto == null) { // TODO 本地无法调通 @@ -660,33 +672,17 @@ } //还原车辆状态 if (1 == xpVehicle.getState()) { xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0)); } // 消息推送 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); content.put("orderId", order.getId().toString()); content.put("status", OrderStatusEnum.CANCELED.getCode()); params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc()); params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content)); params.put("timestamp", new Date().getTime() + ""); String message = JSONObject.toJSONString(params); SendMessageDTO sendMessageDTO = new SendMessageDTO(); sendMessageDTO.setMessage(message); sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId())); xpPushMessageClient.sendStatus(sendMessageDTO); xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0)); // 下发命令 if (order.getStatus() > 1) { PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); //车辆继续巡游 addCruiseMission(xpVehicle); } else { log.info("查询车辆信息失败,订单ID: {}, 下发取消订单命令失败", order.getId()); } @@ -1184,26 +1180,6 @@ return; } order.setStatus(0); // 组装调用车机参数 CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); Long vehicleId = order.getVehicleId(); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId); XpVehicle xpVehicle = xpVehicleR.getData(); if (xpVehicle == null) { throw new ServiceException("车辆不存在", I18nKeyConstant.VEHICLE_NOT_EXISTS); } cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(order.getAppUserId().toString()); cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(appid); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); if (baseVehicleUserDto == null) { // TODO 本地无法调通 // throw new RuntimeException("取消订单失败"); } order.setAppUserId(null); baseMapper.updateById(order); XpOrderCancel xpOrderCancel = new XpOrderCancel(); @@ -1212,10 +1188,7 @@ xpOrderCancel.setCancelSource(1); xpOrderCancel.setCancelReason("用户取消订单"); xpOrderCancelService.save(xpOrderCancel); //还原车辆状态 if (1 == xpVehicle.getState()) { xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0)); } // 设置当天的取消次数缓存 Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + uid); @@ -1246,11 +1219,37 @@ // 下发命令 if (null != order.getVehicleId()) { R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); // 组装调用车机参数 CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); XpVehicle xpVehicle = xpVehicleR.getData(); if (xpVehicle == null) { throw new ServiceException("车辆不存在", I18nKeyConstant.VEHICLE_NOT_EXISTS); } cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(order.getAppUserId().toString()); cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber()); cancelTaxiPassengerVo.setAppId(appid); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); if (baseVehicleUserDto == null) { // TODO 本地无法调通 // throw new RuntimeException("取消订单失败"); } //还原车辆状态 if (1 == xpVehicle.getState()) { xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0)); } //下发XPU报文 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); //车辆继续巡游 addCruiseMission(xpVehicle); } } @@ -1258,7 +1257,7 @@ @Override @Transactional @ShardingSphereTransactionType(TransactionType.BASE) public void cancelOrder(String orderId) { public XpOrder cancelOrder(String orderId) { XpOrder order = this.getById(orderId); if (order == null) { throw new ServiceException("订单不存在", I18nKeyConstant.ORDER_NOT_EXISTS); @@ -1275,10 +1274,6 @@ xpOrderCancelService.save(xpOrderCancel); redisService.removeByPattern(order.getQueueName(), order.getOrderNumber()); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); XpVehicle xpVehicle = xpVehicleR.getData(); // 消息推送 @@ -1298,16 +1293,16 @@ // 移除mongo数据 xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString()); // 下发命令 if (null != order.getVehicleId()) { PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); Long uid = order.getAppUserId(); // 设置当天的取消次数缓存 Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + uid); if (cacheObject == null) { redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, 1); } else { Integer i = Integer.valueOf(cacheObject.toString()); redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, i + 1); } return order; } /** @@ -1476,19 +1471,19 @@ throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS); } // 费用 // // 查询订单轨迹 // List<OrderTrajectory> trajectories = mongoTemplate.find( // new Query(Criteria.where("orderId").is(orderId)) // .with(Sort.by(Sort.Direction.ASC, "locatetime")), // OrderTrajectory.class // ); // List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>(); // for (OrderTrajectory trajectory : trajectories) { // TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime()); // gpsPoints.add(point); // } // 补充临时轨迹数据 List<TaxiPricingDemoService.GpsPoint> gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime())); // 查询订单轨迹 List<OrderTrajectory> trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(orderId)) .with(Sort.by(Sort.Direction.ASC, "locatetime")), OrderTrajectory.class ); List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>(); for (OrderTrajectory trajectory : trajectories) { TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime()); gpsPoints.add(point); } // 补充临时轨迹数据 // List<TaxiPricingDemoService.GpsPoint> gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime())); TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig(); @@ -1502,39 +1497,57 @@ double paramNum5 =0.0; for (int i = 0; i < startingFareJsonArray.size(); i++) { com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i); String num1 = jsonObject.getString("num1"); String num2 = jsonObject.getString("num2"); String num3 = jsonObject.getString("num3"); String num4 = jsonObject.getString("num4"); String num5 = jsonObject.getString("num5"); String num6 = jsonObject.getString("num6"); String num7 = jsonObject.getString("num7"); //一口价 if(pricing.getPricingType() == 2){ JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); String num1 = "00:00"; String num2 = "23:59"; String num3 = basicPricingJson.getString("num1"); String num4 = basicPricingJson.getString("num2"); String num5 = basicPricingJson.getString("num3"); String num6 = basicPricingJson.getString("num4"); String num7 = basicPricingJson.getString("num5"); config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); // 判断当前是那个时段 Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(date); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(date); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1])); // 找到符合条件的直接跳出循环 if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) { paramNum4 = jsonObject.getDouble("num4"); paramNum5 = jsonObject.getDouble("num5"); break; } paramNum4 = basicPricingJson.getDouble("num2"); paramNum5 = basicPricingJson.getDouble("num3"); } //动态计费 if (pricing.getPricingType() == 1) { for (int i = 0; i < startingFareJsonArray.size(); i++) { com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i); String num1 = jsonObject.getString("num1"); String num2 = jsonObject.getString("num2"); String num3 = jsonObject.getString("num3"); String num4 = jsonObject.getString("num4"); String num5 = jsonObject.getString("num5"); String num6 = jsonObject.getString("num6"); String num7 = jsonObject.getString("num7"); config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); // 判断当前是那个时段 Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(date); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(date); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1])); // 找到符合条件的直接跳出循环 if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) { paramNum4 = jsonObject.getDouble("num4"); paramNum5 = jsonObject.getDouble("num5"); break; } } JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split(" - ")[0], basicPricingJson.getString("num21").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")),paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split(" - ")[0], basicPricingJson.getString("num22").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); @@ -1551,17 +1564,14 @@ TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService(); Integer holidayToday = holidayUtil.isHolidayToday(); Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getBoardingTime()), order.getMileageKilometers(), gpsPoints, config,holidayToday); System.err.println("======= 订单计费账单 ======="); bill.forEach((detail, price) -> System.err.println(detail + ": " + price + " 元")); log.info("======= 订单计费账单 ======="); bill.forEach((detail, price) -> log.info(detail + ": " + price + " 元")); BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); System.err.println("--------------------------"); System.err.println("应付总额: " + totalAmount + " 元"); log.info("--------------------------"); log.info("应付总额: " + totalAmount + " 元"); BigDecimal startMoney = BigDecimal.ZERO; // 默认费率1 double priceRate = 1; @@ -1789,8 +1799,7 @@ if (vehicle != null) { // 修改车辆状态 vehicle.setState(0); //发送巡游订单 addCruiseMission(vehicle, order); // // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作 // R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail(); @@ -1961,6 +1970,97 @@ jobMaps ); } /** * 取消订单后的继续巡游任务 * @param vehicle */ public void addCruiseMission(XpVehicle vehicle) { if (vehicle.getState() != 0 || vehicle.getOperatingStatus() != 1) { return; } if (vehicle.getState() != 0 || vehicle.getOperatingStatus() != 1) { return; } // 判断是否有计划 R<XpCruisePlanVehicle> xpCruisePlanR = xpCruisePlanClient.getCruisePlan(vehicle.getId()); if (xpCruisePlanR == null || xpCruisePlanR.getData() == null) { return; } VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vehicle.getVehicleVin())), VehiclePosition.class); // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作 R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail(); XpTaskRule xpTaskRule = xpTaskRuleR.getData(); // 生成新的巡游单子 回到最新巡游的初始起点位置 XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1")); int temp = 0; if (xpCruiseOrders == null) { temp = 1; //特殊情况 可能没有产生终止的订单 (到站点就被正常接单了)所以找正常订单 xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 3).orderByDesc(BaseModel::getCreateTime).last("limit 1")); } XpCruiseOrder xpCruiseOrder = new XpCruiseOrder(); xpCruiseOrder.setVehicleId(vehicle.getId()); xpCruiseOrder.setFleetId(vehicle.getFleetId()); xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin()); xpCruiseOrder.setOrderType(2); // 返程起点是当前正常订单的终点 xpCruiseOrder.setStartPointId(null); xpCruiseOrder.setStartPointName(null); xpCruiseOrder.setStartLon(vehiclePosition.getPoint().getX()); xpCruiseOrder.setStartLat(vehiclePosition.getPoint().getY()); // 完成的直接走终点 终止的走起点 if (temp == 0) { xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat()); } else { xpCruiseOrder.setEndPointId(xpCruiseOrders.getEndPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getEndPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getEndLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getEndLat()); } xpCruiseOrder.setStatus(0); xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId()); xpCruiseOrder.setCreateTime(LocalDateTime.now()); // 判断当前时分秒是否大于收车时间 LocalTime vehicleCollectionTime = xpTaskRule.getVehicleCollectionTime(); if (vehicleCollectionTime.isBefore(LocalTime.now())) { vehicle.setOperatingStatus(3); //找到车辆的收车点位 更新终点点位 R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder); xpCruiseOrder = returnCruisePoint.getData(); } xpVehicleClient.updateVehicleById(vehicle); xpCruiseOrderMapper.insert(xpCruiseOrder); //下发XPU消息报文 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(xpCruiseOrder.getVehicleVin()); pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId()); pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat()); pushOrderDto.setStartLongitude(xpCruiseOrder.getStartLon()); pushOrderDto.setEndLatitude(xpCruiseOrder.getEndLat()); pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon()); pushOrderDto.setOrderType(OrderType.CRUISE_ORDER); pushOrderDto.setStage(2); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); } private MileageDto mileageType(MileageDto param, JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) { // 计算出是在哪个普通时间段内 @@ -2212,7 +2312,7 @@ res.setRedPacketMoney(order.getRedPacketMoney()); res.setCouponMoney(order.getCouponMoney()); res.setOrderMoney(order.getOrderMoney()); res.setKilometer(order.getMileageKilometers() == null ? BigDecimal.ZERO : BigDecimal.valueOf(order.getMileageKilometers())); res.setKilometer(order.getMileageKilometers() == null ? BigDecimal.ZERO : BigDecimal.valueOf(order.getMileageKilometers()).multiply(BigDecimal.valueOf(1000))); LocalDateTime createTime = order.getCreateTime(); LocalDateTime tripEnd = order.getTripEnd(); if (tripEnd == null) { xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaskOrderCancelUtil.java
New file @@ -0,0 +1,62 @@ package com.xiaopeng.order.utils; import com.alibaba.nacos.common.utils.CollectionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.order.service.IXpOrderService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.List; @Slf4j @Component public class TaskOrderCancelUtil { @Autowired private IXpOrderService xpOrderService; /** * 30秒执行一次 */ @Scheduled(cron = "0/30 * * * * ?") public void taskOrder() { // 计算30分钟前的时间 LocalDateTime thirtyMinutesAgo = LocalDateTime.now().minusMinutes(30); // 查询状态为1且创建时间超过30分钟的订单 List<XpOrder> expiredOrders = xpOrderService.list(new LambdaQueryWrapper<XpOrder>() .eq(XpOrder::getStatus, 1) .lt(XpOrder::getCreateTime, thirtyMinutesAgo) // 使用lt避免边界问题 .orderByAsc(XpOrder::getCreateTime) // 按创建时间正序处理,先处理最早的 .last("LIMIT 1000") // 防止一次处理太多数据,可以分批处理 ); if (CollectionUtils.isNotEmpty(expiredOrders)) { for (XpOrder order : expiredOrders) { try { // 处理过期订单 processExpiredOrder(order); } catch (Exception e) { log.error("处理过期订单失败,订单ID: {}", order.getId(), e); } } } } private void processExpiredOrder(XpOrder order){ Long appUserId = order.getAppUserId(); order.setAppUserId(null); order.setStatus(0); xpOrderService.updateById(order); } } xp-robotaxi-push-message-boot/pom.xml
@@ -108,11 +108,11 @@ </exclusion> </exclusions> </dependency> <!-- <dependency>--> <!-- <groupId>org.apache.shardingsphere</groupId>--> <!-- <artifactId>shardingsphere-transaction-base-seata-at</artifactId>--> <!-- <version>5.2.1</version>--> <!-- </dependency>--> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-transaction-base-seata-at</artifactId> <version>5.2.1</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/DataUpdateHandlerConfig.java
@@ -47,7 +47,6 @@ } this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); this.setFieldValByName("createBy", userName, metaObject); } /**