Merge branch '1.0' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi into 1.0
| | |
| | | |
| | | @PostMapping("/v1/api/appUserCoupon/deleteByIds") |
| | | @ApiOperation(value = "根据ids删除用户优惠券", tags = {"管理后台-白名单-删除用户优惠券"}) |
| | | public R<Boolean> deleteByIds(@RequestBody List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | public R<Boolean> deleteByIds(@RequestBody XpAppUserCouponPageListQuery query ) { |
| | | if (query.getIds() == null || query.getIds().isEmpty()) { |
| | | return R.fail("ID列表不能为空"); |
| | | } |
| | | boolean result = xpAppUserCouponService.removeByIds(ids); |
| | | boolean result = xpAppUserCouponService.removeByIds(query.getIds()); |
| | | return R.ok(result); |
| | | } |
| | | |
| | |
| | | @ApiModelProperty(value = "消息类型") |
| | | private String messageType; |
| | | |
| | | @ApiModelProperty("连环单上一单的终点经度") |
| | | private Double endLongitude; |
| | | |
| | | @ApiModelProperty("连环单上一单的终点维度") |
| | | private Double endLatitude; |
| | | |
| | | } |
| | |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; |
| | | import com.xiaopeng.api.vo.operation.VehiclePositionVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | |
| | | log.error("获取服务车辆列表失败,原因: {}", cause.getMessage()); |
| | | return R.fail("获取服务车辆列表失败:" + cause.getMessage()); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public R<VehicleDoorStatusVo> getVehicleDoorStatus(Long orderId) { |
| | | log.error("获取车辆四门三盖状态失败,原因: {}", cause.getMessage()); |
| | | return R.fail("获取车辆四门三盖状态失败:" + cause.getMessage()); |
| | | } |
| | | }; |
| | | } |
| | | } |
| | |
| | | import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto; |
| | | import com.xiaopeng.api.factory.vehicleConvoy.XpVehicleClientFallbackFactory; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | @PostMapping("/logan/inner/vehicle/getServiceVehicleList") |
| | | R<List<XpVehicle>> getServiceVehicleList(@RequestBody ServiceVehicleListDto dto); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 根据订单id查询四门三盖状态 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/logan/inner/vehicle/getVehicleDoorStatus/{orderId}") |
| | | R<VehicleDoorStatusVo> getVehicleDoorStatus(@PathVariable Long orderId); |
| | | } |
| | |
| | | @ApiModelProperty(value = "场站编号唯一 规则:城市首字母-HUB-4位流水号") |
| | | private String stationNumber; |
| | | |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效") |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效") |
| | | private Integer status; |
| | | |
| | | |
| | |
| | | if(status == 0){ |
| | | return "草稿"; |
| | | }else if(status == 1){ |
| | | return "待测试"; |
| | | return "待启用"; |
| | | } else if(status == 2){ |
| | | return "测试中"; |
| | | }else if(status == 3){ |
| | | return "测试未通过"; |
| | | }else if(status == 4){ |
| | | return "可运营"; |
| | | }else if(status == 5){ |
| | | return "待生效"; |
| | | }else if(status == 6){ |
| | | return "启用中"; |
| | | }else if(status == 7){ |
| | | }else if(status == 3){ |
| | | return "已停用"; |
| | | }else if(status == 8){ |
| | | }else if(status == 4){ |
| | | return "失效"; |
| | | } |
| | | } |
| | |
| | | @Data |
| | | public class XpAppUserCouponPageListQuery extends BasePage { |
| | | |
| | | |
| | | private List<Long> ids; |
| | | @ApiModelProperty(value = "用户id 根据手机号获取") |
| | | private Long appUserId; |
| | | |
| | |
| | | |
| | | @ApiModelProperty(value = "场站名称编码") |
| | | private String stationNameOrNumber; |
| | | @ApiModelProperty(value = "点位经纬度") |
| | | private String pointLonAndLat; |
| | | |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效") |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效") |
| | | @ApiModelProperty(value = "场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效") |
| | | private List<Integer> statusList; |
| | | |
| | | @ApiModelProperty(value = "创建人") |
| | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "定向服务 query") |
| | | public class XpTargetedServiceQuery extends BasePage { |
| | | |
| | | |
| | | @ApiModelProperty(value = "ids") |
| | | private List<Long> ids; |
| | | |
| | | @ApiModelProperty(value = "省份名称") |
| | | private String provinceName; |
| | | @ApiModelProperty(value = "省份code") |
| New file |
| | |
| | | package com.xiaopeng.api.vo.automaticPilot; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.data.mongodb.core.geo.GeoJsonPoint; |
| | | import org.springframework.data.mongodb.core.index.CompoundIndex; |
| | | import org.springframework.data.mongodb.core.index.CompoundIndexes; |
| | | import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; |
| | | import org.springframework.data.mongodb.core.index.GeoSpatialIndexed; |
| | | import org.springframework.data.mongodb.core.mapping.Document; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * 车辆实时位置信息 |
| | | */ |
| | | @Data |
| | | @Document(collection = "app_user_position") |
| | | @CompoundIndexes({ |
| | | @CompoundIndex(name = "appUserId", def = "{'appUserId': 1}"), |
| | | @CompoundIndex(name = "location_index", def = "{'point': '2dsphere'}") |
| | | } |
| | | ) |
| | | public class AppUserPosition implements Serializable { |
| | | /** |
| | | * 用户id |
| | | */ |
| | | private Long appUserId; |
| | | /** |
| | | * 车辆实时位置信息 |
| | | */ |
| | | @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE) |
| | | private GeoJsonPoint point; |
| | | /** |
| | | * 添加时间 |
| | | */ |
| | | private Long addTime; |
| | | } |
| | |
| | | |
| | | @ApiModelProperty("被截取的点位,用于前端使用") |
| | | private List<LonLatDto> served; |
| | | |
| | | @ApiModelProperty("连环单上一单的终点经度") |
| | | private Double endLongitude; |
| | | |
| | | @ApiModelProperty("连环单上一单的终点维度") |
| | | private Double endLatitude; |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.api.vo.vehicleConvoy; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class VehicleDoorStatusVo { |
| | | @ApiModelProperty("前左门状态(开=1/关=0)") |
| | | private Integer frontLeftDoor; |
| | | @ApiModelProperty("前右门状态(开=1/关=0)") |
| | | private Integer frontRightDoor; |
| | | @ApiModelProperty("后左门状态(开=1/关=0)") |
| | | private Integer rearLeftDoor; |
| | | @ApiModelProperty("后右门状态(开=1/关=0)") |
| | | private Integer rearRightDoor; |
| | | @ApiModelProperty("后备箱盖状态(开=1/关=0)") |
| | | private Integer trunk; |
| | | @ApiModelProperty("前备箱盖状态(开=1/关=0)") |
| | | private Integer frunk; |
| | | @ApiModelProperty("充电口盖状态(开=1/关=0)") |
| | | private Integer chargePort; |
| | | } |
| | |
| | | DOOR_TRUNK_CLOSE("DOOR_TRUNK_CLOSE", "后备箱关闭"), |
| | | DOOR_UNLOCK("DOOR_UNLOCK", "车门开锁"), |
| | | HVAC_TEMP_SET_FLOAT("HVAC_TEMP_SET_FLOAT", "设定温度"), |
| | | STATUS_REPORT_NOW("STATUS_REPORT_NOW", "上报实时车况"); |
| | | STATUS_REPORT_NOW("STATUS_REPORT_NOW", "上报实时车况"), |
| | | HVAC_ON("HVAC_ON", "空调开启"), |
| | | HVAC_OFF("HVAC_OFF", "空调关闭"); |
| | | /** |
| | | * 命令 |
| | | */ |
| | |
| | | if(!order_id.contains("TEST")){ |
| | | xpPushMessageClient.pushOrderRoute(dto);//存储历史轨迹 |
| | | // 给连环派单的用户推送 |
| | | Long nextOrderId = redisService.getCacheObject(CacheConstants.nextOrder(order_id)); |
| | | if (null != nextOrderId){ |
| | | dto.setOrderId(nextOrderId); |
| | | String json = redisService.getCacheObject(CacheConstants.nextOrder(order_id)); |
| | | if (StringUtils.isNotEmpty(json)){ |
| | | JSONObject jsonObject = JSON.parseObject(json); |
| | | dto.setOrderId(jsonObject.getLong("orderId")); |
| | | dto.setEndLongitude(jsonObject.getDouble("endLongitude")); |
| | | dto.setEndLatitude(jsonObject.getDouble("endLatitude")); |
| | | xpPushMessageClient.pushOrderRoute(dto); |
| | | } |
| | | xpOrderClient.saveVehicleLocation(orderTrajectory); |
| | |
| | | xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode(), true); |
| | | redisService.setCacheObject("ORDER_STATUS:" + orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode(), 24L, TimeUnit.HOURS); |
| | | // 判断当前订单的车辆是否有连环派单,然后判断是都还满足连环派单的条件,不满足则需要重新派单 |
| | | Long nextOrderId = redisService.getCacheObject(CacheConstants.nextOrder(orderId)); |
| | | if(null != nextOrderId){ |
| | | String json = redisService.getCacheObject(CacheConstants.nextOrder(orderId)); |
| | | if (StringUtils.isNotEmpty(json)){ |
| | | JSONObject jsonObject = JSON.parseObject(json); |
| | | Long nextOrderId = jsonObject.getLong("orderId"); |
| | | XpOrder nextOrder = xpOrderClient.queryOrderById(nextOrderId).getData(); |
| | | if(null != nextOrder && nextOrder.getStatus() == OrderStatusEnum.PICK_UP.getCode()){ |
| | | redisService.setCacheObject(CacheConstants.nextOrder(orderId),null); |
| | |
| | | if (!SmsType.ACCEPT_RIDES.name().equals(smsType)) { |
| | | return null; |
| | | } |
| | | // XpVehicle vehicle = xpVehicleClient.findByVehicleVin(vin).getData(); |
| | | // if (vehicle == null) { |
| | | // return XpCommonResponse.fail(RobotaxiErrorEnum.MOBILE_VIN_MISMATCH); |
| | | // } |
| | | // Integer status = vehicle.getStatus(); |
| | | // Integer operatingStatus = vehicle.getOperatingStatus(); |
| | | // if (status == null || status != 2 || operatingStatus == null || operatingStatus != 1) { |
| | | // return XpCommonResponse.fail(RobotaxiErrorEnum.VEHICLE_NOT_READY); |
| | | // } |
| | | |
| | | XpVehicle vehicle = xpVehicleClient.findByVehicleVin(vin).getData(); |
| | | if (vehicle == null) { |
| | | return XpCommonResponse.fail(RobotaxiErrorEnum.MOBILE_VIN_MISMATCH); |
| | | } |
| | | Integer status = vehicle.getStatus(); |
| | | Integer operatingStatus = vehicle.getOperatingStatus(); |
| | | if (smsType.equals(SmsType.ACCEPT_RIDES.name()) && operatingStatus != 1) { |
| | | return XpCommonResponse.fail(RobotaxiErrorEnum.VEHICLE_NOT_READY); |
| | | } |
| | | if (smsType.equals(SmsType.STOP_ACCEPT_RIDES.name()) && operatingStatus != 3) { |
| | | return XpCommonResponse.fail(RobotaxiErrorEnum.VEHICLE_NOT_READY); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; |
| | | import com.xiaopeng.api.dto.operation.ReassignOrderDTO; |
| | | import com.xiaopeng.api.dto.order.OrderChangeDto; |
| | |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.enums.OrderStatusEnum; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.itinerary.constant.I18nKeyConstant; |
| | | import com.xiaopeng.itinerary.mapper.XpElectronicFenceAreaMapper; |
| | |
| | | |
| | | |
| | | // 判断当前订单的车辆是否有连环派单,然后判断是都还满足连环派单的条件,不满足则需要重新派单 |
| | | Long nextOrderId = redisService.getCacheObject(CacheConstants.nextOrder(order.getId().toString())); |
| | | if(null != nextOrderId){ |
| | | String json = redisService.getCacheObject(CacheConstants.nextOrder(order.getId().toString())); |
| | | if (StringUtils.isNotEmpty(json)){ |
| | | JSONObject jsonObject = JSON.parseObject(json); |
| | | Long nextOrderId = jsonObject.getLong("orderId"); |
| | | XpOrder nextOrder = xpOrderClient.queryOrderById(nextOrderId).getData(); |
| | | if(null != nextOrder && nextOrder.getStatus() == OrderStatusEnum.PICK_UP.getCode()){ |
| | | redisService.setCacheObject(CacheConstants.nextOrder(order.getId().toString()),null); |
| | |
| | | |
| | | @Override |
| | | public boolean logicalRemoveById(String id) { |
| | | XpVehicleModel entity = this.getById(id); |
| | | if (entity != null) { |
| | | entity.setDeleted(true); |
| | | return this.updateById(entity); |
| | | } |
| | | return false; |
| | | // XpVehicleModel entity = this.getById(id); |
| | | // if (entity != null) { |
| | | // entity.setDeleted(true); |
| | | // return this.updateById(entity); |
| | | // } |
| | | return this.removeById(id); |
| | | } |
| | | /** |
| | | * 获取指定车型ID关联的车辆数量 |
| | |
| | | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.ExportParams; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; |
| | | import com.xiaopeng.api.dto.map.XpPointExportExcelQuery; |
| | | import com.xiaopeng.api.dto.operation.PointAddDto; |
| | | import com.xiaopeng.api.dto.operation.PointUpdateDto; |
| | |
| | | import com.xiaopeng.map.service.XpElectronicFenceService; |
| | | import com.xiaopeng.map.service.XpPointService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | |
| | | |
| | | @ApiOperation(value = "获取所有运营中的区域", response = XpElectronicFenceArea.class) |
| | | @PostMapping("/listElectronicFenceArea") |
| | | public R<List<XpElectronicFenceArea>> listElectronicFenceArea() { |
| | | public R<List<XpElectronicFenceArea>> listElectronicFenceArea(@RequestParam(required = false) String cityCode) { |
| | | // 获取所有启用的电子围栏 |
| | | List<XpElectronicFence> electronicFences = xpElectronicFenceService.lambdaQuery() |
| | | .eq(XpElectronicFence::getStatus, 2).list(); |
| | | |
| | | LambdaQueryWrapper<XpElectronicFence> queryWrapper= new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(XpElectronicFence::getStatus, 2); |
| | | if(StrUtil.isNotBlank(cityCode)){ |
| | | queryWrapper.eq(XpElectronicFence::getCityCode, cityCode); |
| | | } |
| | | |
| | | List<XpElectronicFence> electronicFences = xpElectronicFenceService.list(queryWrapper); |
| | | List<Long> electronicFenceIds = electronicFences.stream().map(XpElectronicFence::getId).collect(Collectors.toList()); |
| | | if (electronicFenceIds.isEmpty()) { |
| | | return R.ok(new ArrayList<XpElectronicFenceArea>()); |
| | |
| | | } |
| | | } |
| | | xpPoint.setFpElectronicAreaId(null); |
| | | |
| | | Long stationId = pointAddDto.getStationId(); |
| | | Integer stationSortNo = pointAddDto.getStationSortNo(); //点位在场站内排序 |
| | | if(stationId != null && stationId > 0){ |
| | | if(stationSortNo == null){ |
| | | stationSortNo = 0; |
| | | } |
| | | } |
| | | |
| | | // 使用 lambdaUpdate 确保 pointPictures 为 null 时也能将数据库字段清空 |
| | | // (updateById 默认策略 NOT_NULL 会跳过 null 值,导致删除图片后数据库仍保留旧图片) |
| | | xpPointService.lambdaUpdate() |
| | |
| | | .set(XpPoint::getCityName, xpPoint.getCityName()) |
| | | .set(XpPoint::getDistrictName, xpPoint.getDistrictName()) |
| | | .set(XpPoint::getDistrictCode, xpPoint.getDistrictCode()) |
| | | .set(XpPoint::getStationId, xpPoint.getStationId()) |
| | | .set(XpPoint::getStationSortNo, xpPoint.getStationSortNo()) |
| | | .set(XpPoint::getStationId, stationId) |
| | | .set(XpPoint::getStationSortNo, stationSortNo) |
| | | .update(); |
| | | |
| | | //场站点位排序 后添加的点位 排第一个。 |
| | | xpPointService.setStationSortNo(xpPoint.getStationId(),stationSortNo); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.ExportParams; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.xiaopeng.api.model.operation.XpStation; |
| | | import com.xiaopeng.api.query.operation.XpStationQuery; |
| | | import com.xiaopeng.api.vo.account.LoginUser; |
| | |
| | | private TokenService tokenService; |
| | | |
| | | |
| | | @ApiOperation(value = "场站管理列表", tags = {"管理后台-运营-场站管理"}) |
| | | @ApiOperation(value = "场站管理已经启动列表", tags = {"管理后台-运营-场站管理"}) |
| | | @GetMapping("/findListEnable") |
| | | public R<List<XpStation>> findListEnable(@RequestParam String cityCode) { |
| | | LambdaQueryWrapper<XpStation> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(XpStation::getStatus, 2); |
| | | queryWrapper.eq(XpStation::getCityCode, cityCode); |
| | | queryWrapper.eq(XpStation::getDeleted, false); |
| | | return R.ok( xpStationService.list(queryWrapper)); |
| | | } |
| | | |
| | | @ApiOperation(value = "场站管理分页列表", tags = {"管理后台-运营-场站管理"}) |
| | | @PostMapping("/pageList") |
| | | public R<PageInfo<XpStation>> pageList(@RequestBody XpStationQuery query) { |
| | | PageInfo<XpStation> pageList = xpStationService.pageList(query); |
| | |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | |
| | | vo.setCreateBy(loginUser.getUsername()); |
| | | vo.setUpdateBy(loginUser.getUsername()); |
| | | vo.setCreateTime(LocalDateTime.now()); |
| | | |
| | | vo.setUpdateBy(loginUser.getUsername()); |
| | | vo.setUpdateTime(LocalDateTime.now()); |
| | | |
| | | |
| | | return xpStationService.add(vo); |
| | | } |
| | |
| | | if(bean == null){ |
| | | return R.fail("参数错误"); |
| | | } |
| | | //场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | if(bean.getStatus() == 2){ |
| | | return R.fail("场站在启动中不能编辑"); |
| | | } |
| | | |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | |
| | |
| | | * - 否:子点位维持当前状态,但自动退回为“独立点位”。 |
| | | */ |
| | | @ApiOperation(value = "停用" , tags = {"管理后台-运营-场站管理"}) |
| | | @PostMapping("/updateStatus/{id}") |
| | | public R updateStatusStop(@PathVariable Long id, @RequestParam Boolean pointStop) { |
| | | @GetMapping("/updateStatus/{id}") |
| | | public R updateStatusStop(@PathVariable Long id, @RequestParam Boolean isEnable, @RequestParam Boolean pointStop) { |
| | | XpStation bean = xpStationService.getById(id); |
| | | if (bean == null) { |
| | | throw new ServiceException("场站不存在,请刷新重试"); |
| | | } |
| | | // Integer status =6; |
| | | // if(!statusEnable){ |
| | | // status = 7; |
| | | // } |
| | | //场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | xpStationService.updateStatusStop(bean,pointStop); |
| | | if(isEnable){ |
| | | xpStationService.updateStatusEnable(bean); |
| | | }else{ |
| | | if(bean.getStatus() == 2){//场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | return R.fail("场站状态未启动,不能停用"); |
| | | } |
| | | //场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | xpStationService.updateStatusStop(bean,pointStop); |
| | | } |
| | | |
| | | return R.ok(); |
| | | } |
| | | /** |
| | |
| | | if (bean == null) { |
| | | throw new ServiceException("场站不存在,请刷新重试"); |
| | | } |
| | | // 场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | // 场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | // 只有状态为已停用(7)时才能删除 |
| | | if (bean.getStatus() == 4 || bean.getStatus() == 5 || bean.getStatus() == 6) { |
| | | String msg = ""; |
| | | if(bean.getStatus() == 4){ |
| | | msg = "可运营"; |
| | | }else if (bean.getStatus() == 5){ |
| | | msg = "待生效"; |
| | | }else { |
| | | msg = "启用中"; |
| | | } |
| | | throw new ServiceException("场站"+msg+",无法删除"); |
| | | if (bean.getStatus() == 2 ) { |
| | | throw new ServiceException("场站启用中,无法删除"); |
| | | } |
| | | boolean b = xpStationService.removeById(bean,pointDelete); |
| | | if (b){ |
| | |
| | | |
| | | import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; |
| | | import com.xiaopeng.map.job.utils.SpringContextsUtil; |
| | | import com.xiaopeng.map.service.AdcFencePushService; |
| | | import com.xiaopeng.map.service.XpElectronicFenceAreaService; |
| | | import com.xiaopeng.map.service.XpElectronicFenceService; |
| | | import com.xiaopeng.map.service.XpPointService; |
| | | import com.xiaopeng.map.service.*; |
| | | import org.quartz.Job; |
| | | import org.quartz.JobExecutionContext; |
| | | import org.quartz.JobExecutionException; |
| | |
| | | protected XpPointService xpPointService; |
| | | protected XpPushMessageClient xpPushMessageClient; |
| | | protected AdcFencePushService adcFencePushService; |
| | | protected XpStationService xpStationService; |
| | | |
| | | public AbstractJob(){ |
| | | this.xpElectronicFenceService = SpringContextsUtil.getBean(XpElectronicFenceService.class); |
| | |
| | | this.xpPointService = SpringContextsUtil.getBean(XpPointService.class); |
| | | this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class); |
| | | this.adcFencePushService = SpringContextsUtil.getBean(AdcFencePushService.class); |
| | | this.xpStationService = SpringContextsUtil.getBean(XpStationService.class); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | xpElectronicFenceAreaService.updateBatchById(electronicFenceAreaList); |
| | | |
| | | xpStationService.setStatusFailure(electronicId);//场站失效 |
| | | // 清除绑定车辆的 FBS 数据 |
| | | try { |
| | | adcFencePushService.deactivateFenceForVehicles(electronicId); |
| | |
| | | */ |
| | | XpPoint addPointWithGeneratedNumber(@Valid PointAddDto pointAddDto); |
| | | |
| | | |
| | | @Transactional |
| | | void setStationSortNo(Long stationId, Integer stationSortNo); |
| | | |
| | | String getPointNumber(Long electronicAreaId); |
| | | |
| | | /** |
| | |
| | | void statusStopByStationId(Long stationId, Boolean pointStop); |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | void statusEnableByStationId(Long stationId); |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | void pointDeleteByStationId(Long stationId, Boolean pointDelete); |
| | | } |
| | |
| | | |
| | | PageInfo<XpStation> pageList(XpStationQuery query); |
| | | |
| | | boolean isPolygonInPolygon(String innerFencePoints, String outerFencePoints); |
| | | |
| | | void validate(XpStationVo dto); |
| | | |
| | | @Transactional |
| | |
| | | R edit(XpStationVo dto); |
| | | |
| | | |
| | | void setStatusFailure(Long electronicId); |
| | | |
| | | boolean setStatus(XpStation bean, Integer status); |
| | | |
| | | boolean updateStatusEnable(XpStation bean); |
| | | |
| | | boolean updateStatusStop(XpStation bean, Boolean pointStop); |
| | | |
| | | |
| | |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 失效 |
| | | * @param electronicId |
| | | * @param failureType |
| | | * @param failureTime |
| | | * @param now |
| | | */ |
| | | private void registerFailureJobIfNeeded(Long electronicId, Integer failureType, LocalDateTime failureTime, LocalDateTime now) { |
| | | QuartzManager.removeJob((ElectronicEffectJob.failure + electronicId).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE); |
| | | if (failureType == null || failureType != 2 || failureTime == null || failureTime.isBefore(now)) { |
| | |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | private XpElectronicFenceMapper xpElectronicFenceMapper; |
| | | |
| | | @Resource |
| | | @Lazy |
| | | private XpStationService xpStationService; |
| | | |
| | | @Resource |
| | |
| | | BeanUtils.copyProperties(pointAddDto, xpPoint); |
| | | xpPoint.setFpElectronicAreaId(pointAddDto.getElectronicAreaId()); |
| | | xpPoint.setPointNumber(pointNumber); |
| | | xpPoint.setStationSortNo(0); |
| | | this.save(xpPoint); |
| | | |
| | | //场站点位排序 后添加的点位 排第一个。 |
| | | this.setStationSortNo(xpPoint.getStationId(),0); |
| | | |
| | | return xpPoint; |
| | | } |
| | | |
| | | /** |
| | | * 场站 点位排序 |
| | | * @param stationId |
| | | * @param stationSortNo |
| | | */ |
| | | @Transactional |
| | | @Override |
| | | public void setStationSortNo(Long stationId, Integer stationSortNo){ |
| | | if(null != stationId && stationSortNo != null && stationSortNo ==0){ |
| | | // 查询该场站下的所有点位,按 stationSortNo 排序 |
| | | List<XpPoint> points = this.lambdaQuery() |
| | | .eq(XpPoint::getStationId, stationId) |
| | | .orderByAsc(XpPoint::getStationSortNo) |
| | | .list(); |
| | | |
| | | if (CollUtil.isNotEmpty(points)) { |
| | | int newSortNo = 1; |
| | | for (XpPoint point : points) { |
| | | point.setStationSortNo(newSortNo++); |
| | | } |
| | | this.updateBatchById(points); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String getPointNumber(Long electronicAreaId) { |
| | | String cityPrefix = buildCityPrefix(electronicAreaId); |
| | |
| | | continue; |
| | | } |
| | | String downloadUrl =""; |
| | | try { |
| | | downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); |
| | | log.info("downloadUrl:{}", downloadUrl); |
| | | } catch (UnsupportedEncodingException e) { |
| | | log.error("获取图片下载地址失败", e); |
| | | } |
| | | // try { todo 20260422 yyy暂时注释 |
| | | // downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); |
| | | // log.info("downloadUrl:{}", downloadUrl); |
| | | // } catch (UnsupportedEncodingException e) { |
| | | // log.error("获取图片下载地址失败", e); |
| | | // } |
| | | jsonObject.put("url", downloadUrl); |
| | | } |
| | | log.info("jsonArray:{}", jsonArray); |
| | |
| | | } |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void statusEnableByStationId(Long stationId) { |
| | | if (stationId == null) { |
| | | return; |
| | | } |
| | | this.lambdaUpdate() |
| | | .eq(XpPoint::getStationId, stationId) |
| | | .set(XpPoint::getOperationStatus, 2)//运营状态 1=待启用 2=启用中 3=已停用 4=已失效 |
| | | .update(); |
| | | } |
| | | |
| | | /** |
| | | * 场站删除 |
| | | * - 删除拦截逻辑: |
| | |
| | | import com.xiaopeng.api.model.map.XpGeoFencingPolygon; |
| | | import com.xiaopeng.api.model.operation.*; |
| | | import com.xiaopeng.api.query.operation.XpStationQuery; |
| | | import com.xiaopeng.api.vo.account.LoginUser; |
| | | import com.xiaopeng.api.vo.operation.XpStationVo; |
| | | 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.map.constant.I18nKeyConstant; |
| | | import com.xiaopeng.map.mapper.XpRegionMapper; |
| | | import com.xiaopeng.map.mapper.XpStationMapper; |
| | |
| | | import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType; |
| | | import org.apache.shardingsphere.transaction.core.TransactionType; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.data.mongodb.core.MongoTemplate; |
| | | import org.springframework.data.mongodb.core.geo.GeoJsonPolygon; |
| | | import org.springframework.data.mongodb.core.query.Criteria; |
| | |
| | | import javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | public class XpStationServiceImpl extends ServiceImpl<XpStationMapper, XpStation> implements XpStationService { |
| | | |
| | | |
| | | @Resource |
| | | private TokenService tokenService; |
| | | |
| | | @Autowired |
| | | private MongoTemplate mongoTemplate; |
| | |
| | | private GDMapGeocodingUtil gdMapGeocodingUtil; |
| | | @Autowired |
| | | private XpRegionMapper xpRegionMapper; |
| | | @Lazy |
| | | @Resource |
| | | private XpPointService xpPointService; |
| | | |
| | |
| | | * @param outerFencePoints 外部围栏点位字符串(参考围栏),格式为 "lng1_lat1,lng2_lat2,..." |
| | | * @return 是否在内 true在内 false不在 |
| | | */ |
| | | @Override |
| | | public boolean isPolygonInPolygon(String innerFencePoints, String outerFencePoints) { |
| | | if (innerFencePoints == null || innerFencePoints.trim().isEmpty() |
| | | || outerFencePoints == null || outerFencePoints.trim().isEmpty()) { |
| | |
| | | ); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | public static String getPinyinInitials(String chinese) { |
| | | StringBuilder pinyinInitials = new StringBuilder(); |
| | |
| | | |
| | | this.updateById(dto); |
| | | |
| | | save_operatingArea(dto); |
| | | |
| | | savePoint(dto); |
| | | |
| | | saveMongo_operatingArea(dto); |
| | | |
| | | |
| | | return R.ok(); |
| | | } catch (Exception e) { |
| | | log.error("新增场站失败", e); |
| | |
| | | try { |
| | | // dto.setStatus(0); //status = 场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | this.updateById(dto); |
| | | // 删除旧的区域数据,然后保存新的区域数据 |
| | | remove_operatingArea(dto); |
| | | save_operatingArea(dto); |
| | | xpPointService.clearStationInfoByStationId(dto.getId()); |
| | | savePoint(dto); |
| | | // 删除旧的区域数据,然后保存新的区域数据 |
| | | removeMongo_operatingArea(dto); |
| | | saveMongo_operatingArea(dto); |
| | | return R.ok(); |
| | | } catch (Exception e) { |
| | | log.error("新增场站失败", e); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 场站 失效-围栏失效 场站失效 |
| | | * @param electronicId |
| | | */ |
| | | @Override |
| | | public void setStatusFailure(Long electronicId){ |
| | | LambdaQueryWrapper<XpStation> query = new LambdaQueryWrapper<>(); |
| | | query.eq(XpStation::getElectronicId, electronicId); |
| | | query.eq(XpStation::getDeleted, 0); |
| | | |
| | | List<XpStation> list = this.list(query); |
| | | if(!list.isEmpty()){ |
| | | for (XpStation xpStation : list) { |
| | | this.setStatus(xpStation,4); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public boolean setStatus(XpStation bean, Integer status){ |
| | | |
| | | bean.setStatus(status); |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | bean.setUpdateBy(loginUser.getUsername()); |
| | | bean.setUpdateTime(LocalDateTime.now()); |
| | | bean.setStatus(status);//场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | boolean b = updateById(bean); |
| | | if(b){ |
| | | //场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | List<Integer> statusList = Arrays.asList(4, 5, 6, 7) ; |
| | | if(statusList.contains(status) ){ |
| | | save_operatingArea(bean); |
| | | } |
| | | if(status == 7 ){ |
| | | remove_operatingArea(bean); |
| | | if(status == 2){ |
| | | saveMongo_operatingArea(bean); |
| | | }else if(status == 3 || status == 4){ |
| | | removeMongo_operatingArea(bean); |
| | | } |
| | | } |
| | | return b; |
| | | } |
| | | |
| | | private void remove_operatingArea(XpStation bean) { |
| | | private void removeMongo_operatingArea(XpStation bean) { |
| | | // 同步删除Mongo电子围栏多边形 |
| | | Query delMongoQuery = new Query(); |
| | | delMongoQuery.addCriteria(Criteria.where("stationId").is(String.valueOf(bean.getId()))); |
| | | mongoTemplate.remove(delMongoQuery, XpGeoFencingPolygon.class); |
| | | } |
| | | |
| | | private void save_operatingArea (XpStation bean) { |
| | | XpGeoFencingPolygon xpGeoFencingPolygon = new XpGeoFencingPolygon(); |
| | | xpGeoFencingPolygon.setFenceId(String.valueOf(bean.getElectronicId())); |
| | | xpGeoFencingPolygon.setName(bean.getStationName()); |
| | | xpGeoFencingPolygon.setAreaId(String.valueOf(bean.getElectronicAreaId())); |
| | | xpGeoFencingPolygon.setCityCode(bean.getCityCode()); |
| | | xpGeoFencingPolygon.setStationId(String.valueOf(bean.getId())); |
| | | xpGeoFencingPolygon.setOperationStrategy(null);//运营策略 |
| | | // 将围栏点转换为GeoJSON多边形 |
| | | GeoJsonPolygon geoJsonPolygon = xpElectronicFenceService.convertToGeoJsonPolygon(bean.getFencePoints()); |
| | | xpGeoFencingPolygon.setPoints(geoJsonPolygon); |
| | | mongoTemplate.insert(xpGeoFencingPolygon); |
| | | private void saveMongo_operatingArea (XpStation bean) { |
| | | |
| | | //场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | if(bean.getStatus() == 2){ |
| | | XpGeoFencingPolygon xpGeoFencingPolygon = new XpGeoFencingPolygon(); |
| | | xpGeoFencingPolygon.setFenceId(String.valueOf(bean.getElectronicId())); |
| | | xpGeoFencingPolygon.setName(bean.getStationName()); |
| | | xpGeoFencingPolygon.setAreaId(String.valueOf(bean.getElectronicAreaId())); |
| | | xpGeoFencingPolygon.setCityCode(bean.getCityCode()); |
| | | xpGeoFencingPolygon.setStationId(String.valueOf(bean.getId())); |
| | | xpGeoFencingPolygon.setOperationStrategy(null);//运营策略 |
| | | // 将围栏点转换为GeoJSON多边形 |
| | | GeoJsonPolygon geoJsonPolygon = xpElectronicFenceService.convertToGeoJsonPolygon(bean.getFencePoints()); |
| | | xpGeoFencingPolygon.setPoints(geoJsonPolygon); |
| | | mongoTemplate.insert(xpGeoFencingPolygon); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 启用操作 |
| | | * @param bean |
| | | * @return |
| | | */ |
| | | @Override |
| | | public boolean updateStatusEnable(XpStation bean){ |
| | | |
| | | xpPointService.statusEnableByStationId(bean.getId()); |
| | | return setStatus(bean, 2); |
| | | } |
| | | |
| | | /** |
| | | * 停用 |
| | |
| | | public boolean updateStatusStop(XpStation bean, Boolean pointStop){ |
| | | |
| | | xpPointService.statusStopByStationId(bean.getId(),pointStop); |
| | | return setStatus(bean, 7); |
| | | return setStatus(bean, 3); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Override |
| | | public boolean removeById(XpStation bean, Boolean pointDelete){ |
| | | boolean b = true; |
| | | //场站状态 0=草稿 1=待测试 2=测试中 3=测试不通过 4=可运营 5=待生效 6=启用中 7=已停用 8=失效 |
| | | if(bean.getStatus() == 1 || bean.getStatus() == 2 || bean.getStatus() == 3 || bean.getStatus() == 7 || bean.getStatus() == 8){ |
| | | //场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | if(bean.getStatus() != 2){ |
| | | b = super.removeById(bean.getId()); |
| | | } |
| | | if(bean.getStatus() == 7 || bean.getStatus() == 8){ |
| | | xpPointService.pointDeleteByStationId(bean.getId(),pointDelete); |
| | | } |
| | | if(b){ |
| | | // 同步删除Mongo电子围栏多边形 |
| | | Query delMongoQuery = new Query(); |
| | | delMongoQuery.addCriteria(Criteria.where("stationId").is(String.valueOf(bean.getId()))); |
| | | mongoTemplate.remove(delMongoQuery, XpGeoFencingPolygon.class); |
| | | xpPointService.pointDeleteByStationId(bean.getId(),pointDelete); |
| | | if(b){ |
| | | // 同步删除Mongo电子围栏多边形 |
| | | Query delMongoQuery = new Query(); |
| | | delMongoQuery.addCriteria(Criteria.where("stationId").is(String.valueOf(bean.getId()))); |
| | | mongoTemplate.remove(delMongoQuery, XpGeoFencingPolygon.class); |
| | | } |
| | | } |
| | | return b; |
| | | |
| | |
| | | select t1.* |
| | | from xp_point t1 |
| | | where t1.is_deleted = 0 |
| | | <if test="query.cityCode != null and query.cityCode != ''"> |
| | | and t1.city_code = #{query.cityCode} |
| | | </if> |
| | | <if test="query.queryParams != null and query.queryParams != ''"> |
| | | and ( |
| | | t1.point_name like concat('%',#{query.queryParams},'%') |
| | |
| | | return R.ok(xpOpenCityService.citiesList()); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取开通城市启用列表",tags = {"管理后台-开通城市-获取启用的数据"},response = XpOpenCityVo.class) |
| | | @GetMapping("/api/v1/openCity/findLstEnable") |
| | | public R<XpOpenCityVo> openCityFindList() { |
| | | return R.ok(xpOpenCityService.citiesList()); |
| | | } |
| | | /** |
| | | * 获取开通城市列表(管理后台使用) |
| | | * 用于路线规划配置的新增和编辑 |
| | |
| | | package com.xiaopeng.operation.controller; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import com.xiaopeng.api.model.account.SysUser; |
| | | import com.xiaopeng.api.model.operation.XpTargetedService; |
| | | import com.xiaopeng.api.model.operation.XpWhitelist; |
| | |
| | | /** |
| | | * 批量删除 |
| | | */ |
| | | @GetMapping("/api/v1/targetedService/deleteByIds") |
| | | @PostMapping("/api/v1/targetedService/deleteByIds") |
| | | @ApiOperation(value = "定向服务-批量删除", tags = {"管理后台-定向服务批量删除"}) |
| | | public R deleteByIds(String ids) { |
| | | public R deleteByIds(@RequestBody XpTargetedServiceQuery query ) { |
| | | if(CollUtil.isEmpty(query.getIds())){ |
| | | return R.fail("ID列表不能为空"); |
| | | } |
| | | SysUser sysUser = tokenService.getLoginUser().getSysUser(); |
| | | List<Long> whiteIds = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList()); |
| | | return xpTargetedServiceService.deleteByIds(whiteIds, sysUser); |
| | | return xpTargetedServiceService.deleteByIds(query.getIds(), sysUser); |
| | | } |
| | | |
| | | } |
| | |
| | | public class WhitelistPageListQuery extends BasePage { |
| | | @ApiModelProperty(value = "白名单账号") |
| | | private String account; |
| | | @ApiModelProperty(value = "用户名称") |
| | | private String nickName; |
| | | @ApiModelProperty(value = "状态 0=冻结 1=正常") |
| | | private Boolean status; |
| | | @ApiModelProperty(value = "来源 1=添加 2=邀请码") |
| | |
| | | .orderByAsc(XpOpenCity::getId) |
| | | ); |
| | | List<Long> existsOpenCityIds = new ArrayList<>(); |
| | | //2.根据type过滤已配置的开通城市 |
| | | //2.根据type过滤已配置的开通城市 类型:1-路线规划配置使用 2-定价管理配置使用 |
| | | if (Integer.valueOf(1).equals(type)) { |
| | | //路径规划 |
| | | existsOpenCityIds = xpRoutePlanService.list().stream().map(XpRoutePlan::getOpenCityId).collect(Collectors.toList()); |
| | | } else { |
| | | } else if (Integer.valueOf(2).equals(type)){ |
| | | //定价管理 |
| | | existsOpenCityIds = xpPricingService.list().stream().map(XpPricing::getCityId).collect(Collectors.toList()); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public XpTargetedServiceVo getById(Long id) { |
| | | XpTargetedService entity = this.getById(id); |
| | | XpTargetedService entity = baseMapper.selectById(id); |
| | | if (entity == null) { |
| | | return null; |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public R deleteByIds(List<Long> ids, SysUser sysUser) { |
| | | List<XpTargetedService> list = new ArrayList<>(); |
| | | for (Long id : ids) { |
| | | list.add(new XpTargetedService(){{ |
| | | setId(id); |
| | | setUpdateBy(sysUser.getNickName()); |
| | | setDeleted(true); |
| | | }}); |
| | | // List<XpTargetedService> list = new ArrayList<>(); |
| | | // for (Long id : ids) { |
| | | // list.add(new XpTargetedService(){{ |
| | | // setId(id); |
| | | // setUpdateBy(sysUser.getNickName()); |
| | | // setUpdateTime(LocalDateTime.now()); |
| | | // setDeleted(true); |
| | | // }}); |
| | | // |
| | | // } |
| | | // this.updateBatchById(list); |
| | | |
| | | } |
| | | this.updateBatchById(list); |
| | | removeBatchByIds(ids); |
| | | return R.ok(); |
| | | } |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; |
| | | import com.xiaopeng.api.dto.map.RouteAndFareDto; |
| | | import com.xiaopeng.api.dto.operation.LonLatDto; |
| | |
| | | |
| | | /** |
| | | * 5秒执行一次 |
| | | * 播单 |
| | | */ |
| | | @Scheduled(cron = "0/5 * * * * ?") |
| | | public void taskOrder() { |
| | |
| | | pushOrderDto.setTaskId(xpOrder.getXpuTaskId()); |
| | | // 订单流转 |
| | | orderMissionClient.pushOrder(pushOrderDto); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), xpOrder.getId()); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderId", xpOrder.getId()); |
| | | jsonObject.put("endLongitude", xpOrder.getEndLat()); |
| | | jsonObject.put("endLatitude", xpOrder.getEndLat()); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString()); |
| | | redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), routeToOrigin); |
| | | redisService.removeByPattern(quoteName,xpOrder.getOrderNumber()); |
| | | log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); |
| | |
| | | pushOrderDto.setVin(xpVehicle.getVehicleVin()); |
| | | // 订单流转 |
| | | orderMissionClient.pushOrder(pushOrderDto); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), data.getId()); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderId", data.getId()); |
| | | jsonObject.put("endLongitude", data.getEndLat()); |
| | | jsonObject.put("endLatitude", data.getEndLat()); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString()); |
| | | redisService.setCacheObject(CacheConstants.navigationStart(data.getAppUserId().toString()), routeToOrigin); |
| | | break; |
| | | } |
| | |
| | | |
| | | <select id="pageList" resultType="com.xiaopeng.api.vo.operation.XpTargetedServiceVo"> |
| | | select a.* , |
| | | (select count(1) from xp_targeted_service_vehicle where xp_targeted_service_id = a.id) as vehicleCount, |
| | | (select count(1) from xp_targeted_service_whitelist where xp_targeted_service_id = a.id) as whitelistCount |
| | | (select count(1) from xp_targeted_service_vehicle where targeted_service_id = a.id) as vehicleCount, |
| | | (select count(1) from xp_targeted_service_whitelist where targeted_service_id = a.id) as whitelistCount |
| | | |
| | | from xp_targeted_service as a |
| | | where a.is_deleted = 0 |
| | |
| | | <if test="query.account != null and query.account != ''"> |
| | | and account like concat('%',#{query.account},'%') |
| | | </if> |
| | | <if test="query.nickName != null and query.nickName != ''"> |
| | | and nick_name like concat('%',#{query.nickName},'%') |
| | | </if> |
| | | <if test="query.status != null"> |
| | | and status = #{query.status} |
| | | </if> |
| | |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; |
| | | import com.xiaopeng.api.model.order.XpOrder; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.automaticPilot.AppUserPosition; |
| | | import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | import com.xiaopeng.order.dto.UserOrderListDto; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | |
| | | |
| | | |
| | | /** |
| | | * 8. 查询乘客位置 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/getAppUserLocation/{orderId}") |
| | | @ApiOperation(value = "查询乘客位置", notes = "客服系统对接") |
| | | @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long", paramType = "path") |
| | | public R<AppUserLocationVo> getAppUserLocation(@PathVariable Long orderId){ |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if(null == xpOrder){ |
| | | return R.ok(); |
| | | } |
| | | AppUserLocationVo vo = new AppUserLocationVo(); |
| | | AppUserPosition userPosition = mongoTemplate.findOne(Query.query(Criteria.where("appUserId").is(xpOrder.getAppUserId())), AppUserPosition.class); |
| | | if(null != userPosition){ |
| | | vo.setPassengerLng(userPosition.getPoint().getX()); |
| | | vo.setPassengerLat(userPosition.getPoint().getY()); |
| | | return R.ok(vo); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 9. 根据 订单查询安全带及座椅传感器状态 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/getVehicleSeatStatus/{orderId}") |
| | | @ApiOperation(value = "根据 订单查询安全带及座椅传感器状态", notes = "客服系统对接") |
| | | @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long", paramType = "path") |
| | | public R<VehicleSeatStatusVo> getVehicleSeatStatus(@PathVariable Long orderId){ |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if(null == xpOrder){ |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 10. 根据 VIN 查询剩余电量及预估续航 |
| | | * @param vin |
| | | * @return |
| | |
| | | vo.setEstimatedRange(Double.valueOf(vehiclePositions.getMileageRange())); |
| | | return R.ok(vo); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 11. 根据 订单查询四门三盖状态 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/getVehicleDoorStatus/{orderId}") |
| | | @ApiOperation(value = "根据 订单查询四门三盖状态", notes = "客服系统对接") |
| | | @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long", paramType = "path") |
| | | public R<VehicleDoorStatusVo> getVehicleDoorStatus(@PathVariable Long orderId){ |
| | | VehicleDoorStatusVo data = xpVehicleClient.getVehicleDoorStatus(orderId).getData(); |
| | | return R.ok(data); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 12. 根据 订单查询车辆位置及电子围栏信息 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/getVehicleFenceInformation/{orderId}") |
| | | @ApiOperation(value = "根据 订单查询车辆位置及电子围栏信息", notes = "客服系统对接") |
| | | @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long", paramType = "path") |
| | | public R<VehicleFenceInformationVo> getVehicleFenceInformation(@PathVariable Long orderId){ |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if(null == xpOrder){ |
| | | return R.ok(); |
| | | } |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); |
| | | VehiclePosition vehiclePositions = mongoTemplate.findOne(Query.query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | if(null == vehiclePositions){ |
| | | return R.ok(); |
| | | } |
| | | VehicleFenceInformationVo vo = new VehicleFenceInformationVo(); |
| | | vo.setVehicleLng(vehiclePositions.getPoint().getX()); |
| | | vo.setVehicleLat(vehiclePositions.getPoint().getY()); |
| | | vo.setGeofenceBoundary(new ArrayList<>()); |
| | | vo.setIsOutOfGeofence(false); |
| | | return R.ok(vo); |
| | | } |
| | | } |
| | |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); |
| | | |
| | | Long vehicleId = xpOrder.getVehicleId(); |
| | | XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("vehicle_id", vehicleId).in("status", Arrays.asList(6, 7)).eq("is_deleted", 0)); |
| | | if(null != one){ |
| | | routeVo.setEndLongitude(one.getEndLon()); |
| | | routeVo.setEndLatitude(one.getEndLat()); |
| | | } |
| | | |
| | | return R.ok(routeVo); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | //判断是否有连环单 |
| | | Long id = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder.getId().toString())); |
| | | if(id != null){ |
| | | String json = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder.getId().toString())); |
| | | if (StringUtils.isNotEmpty(json)){ |
| | | JSONObject jsonObject = JSON.parseObject(json); |
| | | Long id = jsonObject.getLong("orderId"); |
| | | QuartzManager.addJob( |
| | | PushChainReactionOrderJob.class, |
| | | (PushChainReactionOrderJob.name + id).toUpperCase(), |
| New file |
| | |
| | | package com.xiaopeng.order.vo; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class AppUserLocationVo { |
| | | @ApiModelProperty("经度") |
| | | private Double passengerLng; |
| | | @ApiModelProperty("纬度") |
| | | private Double passengerLat; |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.order.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class FenceVo { |
| | | @ApiModelProperty("经度") |
| | | private Double lng; |
| | | @ApiModelProperty("纬度") |
| | | private Double lat; |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.order.vo; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class VehicleFenceInformationVo { |
| | | @ApiModelProperty("车辆经度") |
| | | private Double vehicleLng; |
| | | @ApiModelProperty("车辆纬度") |
| | | private Double vehicleLat; |
| | | @ApiModelProperty("电子围栏经纬度数组") |
| | | private List<FenceVo> geofenceBoundary; |
| | | @ApiModelProperty("是否超越电子围栏边界") |
| | | private Boolean isOutOfGeofence; |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.order.vo; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class VehicleSeatStatusVo { |
| | | @ApiModelProperty("主驾") |
| | | private String frontLeft; |
| | | @ApiModelProperty("副驾") |
| | | private String frontRight; |
| | | @ApiModelProperty("左后") |
| | | private String rearLeft; |
| | | @ApiModelProperty("右后") |
| | | private String rearRight; |
| | | } |
| | |
| | | content.put("routeType",routeType); |
| | | content.put("direction",dto.getDirection()); |
| | | content.put("route",JSONObject.toJSONString(route)); |
| | | content.put("endLongitude", dto.getEndLongitude()); |
| | | content.put("endLatitude", dto.getEndLatitude()); |
| | | |
| | | // 封装轨迹信息 |
| | | Map<String, Object> params = new HashMap<>(); |
| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xiaopeng.api.vo.automaticPilot.AppUserPosition; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.pushMessage.webSocket.service.WebSocketUserConnectionManager; |
| | | import io.netty.channel.ChannelHandler; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | |
| | | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.mongodb.core.MongoTemplate; |
| | | import org.springframework.data.mongodb.core.geo.GeoJsonPoint; |
| | | import org.springframework.data.mongodb.core.query.Criteria; |
| | | import org.springframework.data.mongodb.core.query.Query; |
| | | import org.springframework.data.mongodb.core.query.Update; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | |
| | | |
| | | @Autowired |
| | | private WebSocketAuthHandler authHandler; |
| | | |
| | | @Resource |
| | | private MongoTemplate mongoTemplate; |
| | | |
| | | Map<String, BusinessMsgHandler> businessMsgHandlers; |
| | | |
| | |
| | | log.info("收到用户 {} 的实时位置消息: {}", appUserId, messageObj.toJSONString()); |
| | | Double latitude = messageObj.getDouble("latitude"); |
| | | Double longitude = messageObj.getDouble("longitude"); |
| | | String timestamp = messageObj.getString("timestamp"); |
| | | |
| | | saveAppUserLocation(Long.parseLong(appUserId), latitude, longitude); |
| | | } |
| | | |
| | | // 回复消息 |
| | |
| | | log.error("WebSocket连接异常: {}", cause.getMessage(), cause); |
| | | ctx.channel().close(); |
| | | } |
| | | |
| | | |
| | | |
| | | private void saveAppUserLocation(Long appUserId, Double latitude, Double longitude) { |
| | | AppUserPosition userPosition = mongoTemplate.findOne(Query.query(Criteria.where("appUserId").is(appUserId)), AppUserPosition.class); |
| | | GeoJsonPoint point = new GeoJsonPoint(longitude, latitude); |
| | | if(null != userPosition){ |
| | | mongoTemplate.updateFirst(Query.query(Criteria.where("appUserId").is(appUserId)), |
| | | Update.update("point", point).set("addTime", System.currentTimeMillis()), AppUserPosition.class); |
| | | }else{ |
| | | userPosition = new AppUserPosition(); |
| | | userPosition.setAppUserId(appUserId); |
| | | userPosition.setPoint(point); |
| | | userPosition.setAddTime(System.currentTimeMillis()); |
| | | mongoTemplate.save(userPosition); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleStateVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.vehicleConvoy.model.dto.CarControlCallbackDTO; |
| | | import com.xiaopeng.vehicleConvoy.service.AsyncVehicleStateService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * 控车回调接口 |
| | |
| | | |
| | | @Resource |
| | | private AsyncVehicleStateService asyncVehicleStateService; |
| | | private RedisService redisService; |
| | | |
| | | /** |
| | | * 车控指令执行的回调接口 |
| | |
| | | // 通知异步服务处理回调 |
| | | asyncVehicleStateService.handleStateCallback(request.getMsgRef(), stateData); |
| | | } |
| | | // 尝试解析车辆空调数据 |
| | | parseAirConditioningSwitchFromCallback(request); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("处理车辆状态回调异常: msgId={}", request.getMsgRef(), e); |
| | |
| | | // 解析door信息 |
| | | Map<String, Object> door = (Map<String, Object>) instant.get("door"); |
| | | if (door != null) { |
| | | //存入缓存用于后续使用 |
| | | redisService.setCacheObject("DOOR:" + callback.getMsgId(), JSON.toJSONString(door), 30L, TimeUnit.SECONDS); |
| | | // 获取trunk_ajar_st_new值 |
| | | Object trunkAjarStNewObj = door.get("trunk_ajar_st_new"); |
| | | if (trunkAjarStNewObj != null) { |
| | |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从回调消息中解析车辆空调状态数据 |
| | | */ |
| | | private VehicleTemperatureDto parseAirConditioningSwitchFromCallback(CarControlCallbackDTO callback) { |
| | | try { |
| | | if (callback.getMsgContent() == null) { |
| | | return null; |
| | | } |
| | | |
| | | log.debug("解析空调状态数据: msgId={}, content={}", callback.getMsgRef(), JSON.toJSONString(callback.getMsgContent())); |
| | | |
| | | // 解析msgContent为Map结构 |
| | | Map<String, Object> msgContent = (Map<String, Object>) callback.getMsgContent(); |
| | | |
| | | // 检查返回码 |
| | | Integer code = (Integer) msgContent.get("code"); |
| | | if (code == null || code != 200) { |
| | | log.warn("空调状态回调返回错误码: msgId={}, code={}", callback.getMsgRef(), code); |
| | | return null; |
| | | } |
| | | |
| | | // 获取instant数据 |
| | | Map<String, Object> instant = (Map<String, Object>) msgContent.get("instant"); |
| | | if (instant == null) { |
| | | log.warn("回调数据中缺少instant字段: msgId={}", callback.getMsgRef()); |
| | | return null; |
| | | } |
| | | |
| | | // 创建VehicleTemperatureDto对象 |
| | | VehicleTemperatureDto stateData = new VehicleTemperatureDto(); |
| | | Map<String, VehicleStateVo> stateMap = new HashMap<>(); |
| | | |
| | | // 解析hvac信息 |
| | | Map<String, Object> hvac = (Map<String, Object>) instant.get("hvac"); |
| | | if (hvac != null) { |
| | | log.info("解析到空调: msgId={}, hvac_on={}", callback.getMsgRef(), JSON.toJSONString(hvac)); |
| | | //存入缓存用于后续使用 |
| | | redisService.setCacheObject("HVAC:" + callback.getMsgId(), JSON.toJSONString(hvac), 30L, TimeUnit.SECONDS); |
| | | } |
| | | stateData.setStateMap(stateMap); |
| | | return stateData; |
| | | } catch (Exception e) { |
| | | log.warn("解析空调状态数据失败: msgId={}", callback.getMsgRef(), e); |
| | | return null; |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicleAnnualRecord; |
| | | import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleStateVo; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehiclesCommandCallbackVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | |
| | | @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataTypeClass = Long.class), |
| | | @ApiImplicitParam(name = "orderType", value = "订单类型(1=用户单,2=测试单)", required = true, dataTypeClass = Integer.class) |
| | | }) |
| | | public R<List<XpVehicle>> listAvailableVehicles(@RequestParam Long orderId, Integer orderType) { |
| | | List<XpVehicle> list = xpVehicleService.listAvailableVehicles(orderId, orderType); |
| | | public R<List<XpVehicleVO>> listAvailableVehicles(@RequestParam Long orderId, Integer orderType, String plateNumber, String fleetName) { |
| | | List<XpVehicleVO> list = xpVehicleService.listAvailableVehicles(orderId, orderType,plateNumber,fleetName); |
| | | return R.ok(list); |
| | | } |
| | | |
| | |
| | | XpOperationsUser xpOperationsUser = tokenService.getLoginOperationUser().getXpOperationsUser(); |
| | | return R.ok(xpVehicleService.unlockDoor(dto, xpOperationsUser)); |
| | | } |
| | | |
| | | |
| | | |
| | | @ApiOperation(value = "通过订单id查询当前车辆空调状态", tags = {"小程序-业务流程"}) |
| | | @GetMapping("/api/v1/mini-program/order/queryVehicleAirConditionerSwitch") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<Boolean> queryVehicleAirConditionerSwitch(@RequestParam Long orderId, HttpServletRequest request) { |
| | | String uid = request.getHeader("XP-Uid"); |
| | | Boolean hasKey = xpVehicleService.queryVehicleAirConditionerSwitch(orderId, uid); |
| | | return R.ok(hasKey); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 业务流程-车门解锁/后备箱解锁 |
| | | */ |
| | | @ApiOperation(value = "打开/关闭车内空调", tags = {"小程序-业务流程"}) |
| | | @PostMapping("/api/v1/mini-program/order/airConditionerUnlock") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<Integer> airConditionerUnlock(@RequestBody AirConditionerUnlockDTO dto, HttpServletRequest request) { |
| | | String uid = request.getHeader("XP-Uid"); |
| | | return R.ok(xpVehicleService.airConditionerUnlock(dto, uid)); |
| | | } |
| | | |
| | | /** |
| | | * 根据订单id查询四门三盖状态 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @GetMapping("/logan/inner/vehicle/getVehicleDoorStatus/{orderId}") |
| | | public R<VehicleDoorStatusVo> getVehicleDoorStatus(@PathVariable Long orderId){ |
| | | VehicleDoorStatusVo vehicleDoorStatus = xpVehicleService.getVehicleDoorStatus(orderId); |
| | | return R.ok(vehicleDoorStatus); |
| | | } |
| | | } |
| | |
| | | */ |
| | | List<XpVehicleVO> pageList(@Param("pageInfo") PageInfo<XpVehicleVO> pageInfo, @Param("query") VehicleMapQuery query); |
| | | |
| | | List<XpVehicleVO> findList(@Param("query") VehicleMapQuery query); |
| | | |
| | | /** |
| | | * 在库车辆管理分页查询 |
| | | * |
| New file |
| | |
| | | package com.xiaopeng.vehicleConvoy.model.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | |
| | | @Data |
| | | @ApiModel |
| | | public class AirConditionerUnlockDTO { |
| | | |
| | | @ApiModelProperty(value = "订单id") |
| | | private Long orderId; |
| | | |
| | | @ApiModelProperty(value = "开关控制(开=true, 关=false)") |
| | | private Boolean open; |
| | | } |
| | |
| | | private String plateNumber; |
| | | @ApiModelProperty(value = "运营状态 1运营中 2维修中 3已收车 4车辆异常") |
| | | private String status; |
| | | @ApiModelProperty(value = "运营状态 1运营中 2维修中 3已收车 4车辆异常") |
| | | private Integer operatingStatus; |
| | | @ApiModelProperty(value = "车辆接单状态 1接单中 0空闲") |
| | | private Integer state; |
| | | @ApiModelProperty(value = "围栏id") |
| | | private String electronicId; |
| | | |
| | |
| | | private Long operationsUserId; |
| | | @ApiModelProperty(value = "车辆id集合 前端忽略") |
| | | private List<Long> vehicleIds; |
| | | |
| | | @ApiModelProperty(value = "车辆类型 1=在库 2=运营") |
| | | private Integer vehicleType; |
| | | |
| | | |
| | | @ApiModelProperty(value = "车队名称") |
| | | private String fleetName; |
| | | } |
| | |
| | | import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto; |
| | | import com.xiaopeng.api.model.account.XpOperationsUser; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import com.xiaopeng.vehicleConvoy.model.dto.*; |
| | | import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel; |
| | | import com.xiaopeng.vehicleConvoy.model.query.*; |
| | | import com.xiaopeng.vehicleConvoy.model.vo.XpVehicleVO; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | |
| | | * @return |
| | | */ |
| | | Integer unlockDoor(UnlockAppDTO dto, XpOperationsUser xpOperationsUser); |
| | | |
| | | |
| | | /** |
| | | * 根据订单id获取空调开关状态 |
| | | * @param orderId |
| | | * @param uid |
| | | * @return |
| | | */ |
| | | Boolean queryVehicleAirConditionerSwitch(Long orderId, String uid); |
| | | |
| | | |
| | | /** |
| | | * 开关空调 |
| | | * @param dto |
| | | * @param uid |
| | | * @return |
| | | */ |
| | | Integer airConditionerUnlock(AirConditionerUnlockDTO dto, String uid); |
| | | |
| | | |
| | | /** |
| | | * 获取车辆车门和后备箱状态 |
| | | * @param vehicleId |
| | | * @return |
| | | */ |
| | | VehicleDoorStatusVo getVehicleDoorStatus(Long orderId); |
| | | } |
| | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.Validator; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | |
| | | import com.xiaopeng.common.core.constant.CacheConstants; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.exception.base.BaseException; |
| | | import com.xiaopeng.common.core.utils.GeodesyUtil; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | |
| | | import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel; |
| | | import com.xiaopeng.vehicleConvoy.model.query.*; |
| | | import com.xiaopeng.vehicleConvoy.model.vo.XpVehicleVO; |
| | | import com.xiaopeng.vehicleConvoy.service.AsyncVehicleStateService; |
| | | import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService; |
| | | import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService; |
| | | import com.xiaopeng.vehicleConvoy.service.IXpVehicleService; |
| | |
| | | |
| | | @Resource |
| | | private UserResourcesClient userResourcesClient; |
| | | @Resource |
| | | private AsyncVehicleStateService asyncVehicleStateService; |
| | | |
| | | @Value("${vehicle.control.distance-threshold:100}") |
| | | private int distanceThreshold; |
| | |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<XpVehicle> listAvailableVehicles(Long orderId, Integer orderType) { |
| | | public List<XpVehicleVO> listAvailableVehicles(Long orderId, Integer orderType, String plateNumber, String fleetName) { |
| | | // 1. 通过订单ID查询订单信息,获取区域ID |
| | | Long areaId = null; |
| | | |
| | |
| | | } |
| | | |
| | | // 3. 根据围栏ID查询车辆列表 (operatingStatus=1 且 state=0) |
| | | LambdaQueryWrapper<XpVehicle> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(XpVehicle::getElectronicId, electronicId) |
| | | .eq(XpVehicle::getOperatingStatus, 1) |
| | | .eq(XpVehicle::getVehicleType, 2) |
| | | .eq(XpVehicle::getState, 0); |
| | | VehicleMapQuery query = new VehicleMapQuery(); |
| | | query.setState(0); |
| | | query.setVehicleType(2); |
| | | query.setOperatingStatus(1); |
| | | query.setElectronicId(electronicId.toString()); |
| | | query.setFleetName(fleetName); |
| | | query.setPlateNumber(plateNumber); |
| | | |
| | | // 排序:按电量降序、入库时间降序 |
| | | wrapper.orderByDesc(XpVehicle::getCurrentElectricity) |
| | | .orderByDesc(XpVehicle::getWarehousingTime); |
| | | List<XpVehicle> list = this.list(wrapper); |
| | | List<XpVehicleVO> list = baseMapper.findList(query); |
| | | //获取车的位置 和订单的位置 并计算 距离 和 时间 |
| | | if(!list.isEmpty()){ |
| | | for (XpVehicle xpVehicle : list) { |
| | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 根据订单id获取空调开关状态 |
| | | * @param orderId |
| | | * @param uid |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Boolean queryVehicleAirConditionerSwitch(Long orderId, String uid) { |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); |
| | | if(null == xpOrder){ |
| | | return false; |
| | | } |
| | | XpVehicle vehicle = this.getById(xpOrder.getVehicleId()); |
| | | String vin = vehicle.getVehicleVin(); |
| | | // 1. 创建车辆控制指令 |
| | | VehiclesCommandVo commandVo = new VehiclesCommandVo(); |
| | | commandVo.setVin(vin); |
| | | commandVo.setCommandCode(VehiclesCommandEnum.STATUS_REPORT_NOW.getCommand()); |
| | | |
| | | // 2. 下发指令获取消息ID |
| | | String msgId = vehicleControlUtil.vehiclesCommand(commandVo, Long.valueOf(uid)); |
| | | if (StrUtil.isEmpty(msgId)) { |
| | | throw new BaseException("获取消息ID失败: " + msgId); |
| | | } |
| | | log.info("同步查询车辆空调状态成功,开始等到查询回调结果"); |
| | | try { |
| | | Thread.sleep(2000); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | String cacheObject = redisService.getCacheObject("HVAC:" + msgId); |
| | | if(StringUtils.isEmpty(cacheObject)){ |
| | | return false; |
| | | } |
| | | JSONObject jsonObject = JSON.parseObject(cacheObject); |
| | | Integer hvac_on = jsonObject.getInteger("hvac_on"); |
| | | return hvac_on == 1; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 开关空调 |
| | | * @param dto |
| | | * @param uid |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Integer airConditionerUnlock(AirConditionerUnlockDTO dto, String uid) { |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(dto.getOrderId()).getData(); |
| | | if(null == xpOrder){ |
| | | return 0; |
| | | } |
| | | XpVehicle vehicle = this.getById(xpOrder.getVehicleId()); |
| | | VehiclesCommandVo vehiclesCommandVo = new VehiclesCommandVo(); |
| | | vehiclesCommandVo.setVin(vehicle.getVehicleVin()); |
| | | vehiclesCommandVo.setCommandCode(dto.getOpen() ? VehiclesCommandEnum.HVAC_ON.getCommand() : VehiclesCommandEnum.HVAC_OFF.getCommand()); |
| | | String msgId = vehicleControlUtil.vehiclesCommand(vehiclesCommandVo, Long.valueOf(uid)); |
| | | log.info("空调控制结果:{}", msgId); |
| | | if (StringUtils.isEmpty(msgId)) { |
| | | return 0; |
| | | } else { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取车辆门锁状态 |
| | | * @param orderId |
| | | * @return |
| | | */ |
| | | @Override |
| | | public VehicleDoorStatusVo getVehicleDoorStatus(Long orderId) { |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(orderId).getData(); |
| | | if(null == xpOrder){ |
| | | return null; |
| | | } |
| | | XpVehicle vehicle = this.getById(xpOrder.getVehicleId()); |
| | | String vin = vehicle.getVehicleVin(); |
| | | // 1. 创建车辆控制指令 |
| | | VehiclesCommandVo commandVo = new VehiclesCommandVo(); |
| | | commandVo.setVin(vin); |
| | | commandVo.setCommandCode(VehiclesCommandEnum.STATUS_REPORT_NOW.getCommand()); |
| | | |
| | | // 2. 下发指令获取消息ID |
| | | String msgId = vehicleControlUtil.vehiclesCommand(commandVo, xpOrder.getAppUserId()); |
| | | if (StrUtil.isEmpty(msgId)) { |
| | | throw new BaseException("获取消息ID失败: " + msgId); |
| | | } |
| | | log.info("同步查询车辆空调状态成功,开始等到查询回调结果"); |
| | | try { |
| | | Thread.sleep(2000); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | String cacheObject = redisService.getCacheObject("DOOR:" + msgId); |
| | | if(StringUtils.isEmpty(cacheObject)){ |
| | | return null; |
| | | } |
| | | // todo 待文档补充后再更新代码 |
| | | VehicleDoorStatusVo vo = new VehicleDoorStatusVo(); |
| | | JSONObject jsonObject = JSON.parseObject(cacheObject); |
| | | Integer driver_door_ajar_st = jsonObject.getInteger("driver_door_ajar_st"); |
| | | Integer passenger_door_ajar_st = jsonObject.getInteger("passenger_door_ajar_st"); |
| | | Integer rear_left_door_ajar_st = jsonObject.getInteger("rear_left_door_ajar_st"); |
| | | Integer rear_right_door_ajar_st = jsonObject.getInteger("rear_right_door_ajar_st"); |
| | | Integer trunk_ajar_st_new = jsonObject.getInteger("trunk_ajar_st_new"); |
| | | vo.setTrunk(trunk_ajar_st_new == 5 ? 1 : 0); |
| | | return vo; |
| | | } |
| | | } |
| | |
| | | ORDER BY create_time DESC |
| | | </select> |
| | | |
| | | |
| | | <select id="findList" resultType="com.xiaopeng.vehicleConvoy.model.vo.XpVehicleVO"> |
| | | SELECT a.* |
| | | FROM xp_vehicle as a |
| | | <where> a.is_deleted = 0 |
| | | <if test="query.vehicleType != null and query.vehicleType != ''"> |
| | | AND a.vehicle_type = #{query.vehicleType} |
| | | </if> |
| | | <if test="query.plateNumber != null and query.plateNumber != ''"> |
| | | AND a.plate_number LIKE CONCAT('%', #{query.plateNumber}, '%') |
| | | </if> |
| | | <!-- 运营状态 1运营中 2维修中 3已收车 4车辆异常 --> |
| | | <if test="query.operatingStatus != null and query.operatingStatus != ''"> |
| | | AND a.operating_status = #{query.operatingStatus} |
| | | </if> |
| | | <!-- 车辆接单状态 1接单中 0空闲 --> |
| | | <if test="query.state != null and query.state != ''"> |
| | | AND a.state = #{query.state} |
| | | </if> |
| | | <if test="query.statusList != null and query.statusList.size()>0"> |
| | | AND a.operating_status in |
| | | <foreach item="item" collection="query.statusList" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.electronicId != null and query.electronicId != ''"> |
| | | AND a.electronic_id #{query.electronicId} |
| | | </if> |
| | | <if test="query.electronicIdList != null and query.electronicIdList.size()>0"> |
| | | AND a.electronic_id in |
| | | <foreach item="item" collection="query.electronicIdList" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.vehicleIds != null and query.vehicleIds.size()>0"> |
| | | AND a.id in |
| | | <foreach item="item" collection="query.vehicleIds" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.fleetName != null and query.fleetName != ''"> |
| | | AND EXISTS ( |
| | | SELECT 1 FROM xp_fleet_vehicle xfv |
| | | LEFT JOIN xp_fleet xf ON xfv.fleet_id = xf.id |
| | | WHERE xfv.vehicle_id = a.id |
| | | AND xf.fleet_name LIKE CONCAT('%', #{query.fleetName}, '%') |
| | | ) |
| | | </if> |
| | | </where> |
| | | ORDER BY a.current_electricity DESC,a.warehousing_time desc |
| | | </select> |
| | | |
| | | <!-- 在库车辆管理分页查询条件 --> |
| | | <sql id="Vehicle_Page_Where"> |
| | | AND vehicle_type = 1 |