From 924b62671fec280437016d4a7611bde71b115c1a08a3ebc70397624b2a285d02 Mon Sep 17 00:00:00 2001 From: attiya <2413103649@qq.com> Date: Wed, 3 Dec 2025 16:45:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=B0=E5=9D=80=E6=98=A0=E5=B0=84=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=B1=BB=E3=80=81=E5=B7=A5=E5=8D=95=E8=BD=A6=E8=BE=86?= =?UTF-8?q?=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../operations/config/GeoCodingConfig.java | 22 ++ .../controller/EbikeBikeOrderController.java | 12 ++ .../model/dto/EbikeBikeInfoDto.java | 6 +- .../model/dto/EbikeOrderBikeInfoDto.java | 129 ++++++++++++ .../service/EbikeBikeOrderService.java | 8 + .../impl/EbikeBikeOrderServiceImpl.java | 6 + .../cdzy/operations/utils/GeoCodingUtil.java | 193 ++++++++++++++++++ 7 files changed, 371 insertions(+), 5 deletions(-) create mode 100644 ebike-operations/src/main/java/com/cdzy/operations/config/GeoCodingConfig.java create mode 100644 ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeOrderBikeInfoDto.java create mode 100644 ebike-operations/src/main/java/com/cdzy/operations/utils/GeoCodingUtil.java diff --git a/ebike-operations/src/main/java/com/cdzy/operations/config/GeoCodingConfig.java b/ebike-operations/src/main/java/com/cdzy/operations/config/GeoCodingConfig.java new file mode 100644 index 0000000..cecea23 --- /dev/null +++ b/ebike-operations/src/main/java/com/cdzy/operations/config/GeoCodingConfig.java @@ -0,0 +1,22 @@ +package com.cdzy.operations.config; + +import com.cdzy.operations.utils.GeoCodingUtil; +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Setter +@Getter +@Configuration +@ConfigurationProperties(prefix = "geo-coding") +public class GeoCodingConfig { + private String apiUrl; + private String accessKey; + + @Bean + public GeoCodingUtil geoCodingUtil() { + return new GeoCodingUtil(apiUrl, accessKey); + } +} diff --git a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java index d8daf33..c5b1483 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/controller/EbikeBikeOrderController.java @@ -7,6 +7,7 @@ import com.cdzy.common.model.response.JsonResult; import com.cdzy.operations.enums.BikeOrderHandleState; import com.cdzy.operations.model.dto.EbikeBikeOrderInfoDto; import com.cdzy.operations.model.dto.EbikeBikeOrderPageDto; +import com.cdzy.operations.model.dto.EbikeOrderBikeInfoDto; import com.cdzy.operations.model.vo.EbikeBatteryChangeVo; import com.cdzy.operations.model.vo.EbikeBatteryClaimReturnVo; import com.cdzy.operations.model.vo.FaultOrderVo; @@ -207,4 +208,15 @@ public class EbikeBikeOrderController { ebikeBikeOrderService.batteryChange(changeVo); return JsonResult.success(Message.SUCCESS); } + + /** + * 车辆详情(工单用) + * + * @return 操作结果 + */ + @GetMapping("bikeInfo") + public JsonResult bikeInfo(@RequestParam("bikeCode") String bikeCode) { + EbikeOrderBikeInfoDto info = ebikeBikeOrderService.bikeInfo(bikeCode); + return JsonResult.success(info); + } } diff --git a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeBikeInfoDto.java b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeBikeInfoDto.java index 31acbea..449df05 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeBikeInfoDto.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeBikeInfoDto.java @@ -6,8 +6,6 @@ import com.cdzy.operations.handler.PGpointTypeHandler; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.mybatisflex.annotation.Column; -import com.mybatisflex.annotation.Id; -import com.mybatisflex.annotation.Table; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -19,7 +17,7 @@ import java.io.Serializable; import java.time.LocalDateTime; /** - * 实体类。 + * 车辆详情。 * * @author attiya * @since 2025-10-21 @@ -28,7 +26,6 @@ import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor -@Table("ebike_bike_info") public class EbikeBikeInfoDto implements Serializable { @Serial @@ -37,7 +34,6 @@ public class EbikeBikeInfoDto implements Serializable { /** * 车辆详情ID */ - @Id private Long bikeInfoId; /** diff --git a/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeOrderBikeInfoDto.java b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeOrderBikeInfoDto.java new file mode 100644 index 0000000..8229ab5 --- /dev/null +++ b/ebike-operations/src/main/java/com/cdzy/operations/model/dto/EbikeOrderBikeInfoDto.java @@ -0,0 +1,129 @@ +package com.cdzy.operations.model.dto; + +import com.cdzy.operations.handler.PGpointDeserializer; +import com.cdzy.operations.handler.PGpointSerializer; +import com.cdzy.operations.handler.PGpointTypeHandler; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.mybatisflex.annotation.Column; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.postgresql.geometric.PGpoint; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 车辆详情。 + * + * @author attiya + * @since 2025-10-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EbikeOrderBikeInfoDto implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 车辆详情ID + */ + private Long bikeInfoId; + + /** + * 运营商ID + */ + private Long operatorId; + + /** + * 运营区ID + */ + private Long regionId; + + /** + * 运营区名称 + */ + private String regionName; + + /** + * 车辆编号(与车辆二维码编号相同 + */ + private String bikeCode; + + /** + * 电池ID + */ + private Long batteryId; + + /** + * 中控ID + */ + private Long ecuId; + + /** + * 头盔ID + */ + private Long helmetId; + + /** + * 定位 + */ + @Column(typeHandler = PGpointTypeHandler.class) + @JsonSerialize(using = PGpointSerializer.class) + @JsonDeserialize(using = PGpointDeserializer.class) + private PGpoint location; + + /** + * 备注 + */ + private String remarks; + + /** + * 车辆状态 + */ + private Integer status; + + /** + * 车辆使用状态 + */ + private Integer usageStatus; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createdAt; + + /** + * 创建人 + */ + private Long createdBy; + + /** + * 修改时间 + */ + @Column(onUpdateValue = "now()") + private LocalDateTime updatedAt; + + /** + * 修改人 + */ + private Long updatedBy; + + /** + * 删除与否 + */ + private Boolean isDeleted; + + /** + * 是否包含头盔 + */ + private Boolean hasHelme; + +} diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java b/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java index 3367dae..42db049 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/EbikeBikeOrderService.java @@ -1,6 +1,7 @@ package com.cdzy.operations.service; import com.cdzy.operations.model.dto.EbikeBikeOrderInfoDto; +import com.cdzy.operations.model.dto.EbikeOrderBikeInfoDto; import com.cdzy.operations.model.entity.EbikeBikeOrder; import com.cdzy.operations.model.vo.EbikeBatteryChangeVo; import com.cdzy.operations.model.vo.EbikeBatteryClaimReturnVo; @@ -86,4 +87,11 @@ public interface EbikeBikeOrderService extends IService { * @param changeVo 更换信息 */ void batteryChange(EbikeBatteryChangeVo changeVo); + + /** + * 获取车辆详情 + * @param bikeCode 车辆编号 + * @return 详情 + */ + EbikeOrderBikeInfoDto bikeInfo(String bikeCode); } diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java index 7ebcb69..15dd945 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeOrderServiceImpl.java @@ -7,6 +7,7 @@ import com.cdzy.common.model.dto.ResGPSDto; import com.cdzy.operations.enums.*; import com.cdzy.operations.mapper.*; import com.cdzy.operations.model.dto.EbikeBikeOrderInfoDto; +import com.cdzy.operations.model.dto.EbikeOrderBikeInfoDto; import com.cdzy.operations.model.entity.*; import com.cdzy.operations.model.vo.EbikeBatteryChangeVo; import com.cdzy.operations.model.vo.EbikeBatteryClaimReturnVo; @@ -369,6 +370,11 @@ public class EbikeBikeOrderServiceImpl extends ServiceImplstandard_address + //private final static String ADDRESS_KEY = "formatted_addresses"; + private final static String ADDRESS_KEY = "formatted_address"; + private final static String STANDARD_ADDRESS_KEY = "standard_address"; + // 位置键 高德地图webservice 为location,腾讯地图webservice为location + private final static String LOCATION_KEY = "location"; + // 地址详情键 高德地图webservice 为addressComponent,腾讯地图webservice为ad_info + private final static String ADDRESS_COMPONENT_KEY = "addressComponent"; + private final static String DISTRICT_KEY = "district"; + private final static String ADCODE_KEY = "adcode"; + private final static String MSG_KEY = "message"; + + private final String url; + private final String accessKey; + private final OkHttpClient client; + private final ObjectMapper objectMapper; + + /** + * 地理编码工具类构造函数。 + * 目前实现的腾讯地图webservice + * + * @param apiUrl + * @param accessKey + */ + public GeoCodingUtil(String apiUrl, String accessKey) { + this.url = apiUrl; + this.accessKey = accessKey; + this.client = new OkHttpClient(); + this.objectMapper = new ObjectMapper(); + } + + /** + * 输入经纬度,返回地址。 + * + * @param location 经纬度 + * @return 地址 + */ + public String getLocationToAddress(JsonNode location) { + //String locationStr = String.format("%f,%f", location.getDouble(LATITUDE_KEY), location.getDouble(LONGITUDE_KEY)); + String locationStr = String.format("%f,%f", location.get(LONGITUDE_KEY).asDouble(), location.get(LATITUDE_KEY).asDouble()); + Request request = new Request.Builder() + .url(url + "/"+LOCATION_TO_ADDRESS + "?"+"location=" + locationStr + "&key=" + accessKey) + .build(); + try(Response response = client.newCall(request).execute()) { + if(response.isSuccessful()) { + if (response.body()!= null) { + String result = response.body().string(); + JsonNode jsonObject = objectMapper.readTree(result); + if (jsonObject.get(STATUS_KEY).asInt() == CODE_STATUS_SUCCESS) { + //return jsonObject.getJSONObject(RESULT_KEY).getJSONObject(ADDRESS_KEY).getString(STANDARD_ADDRESS_KEY); + return jsonObject.get(ADDRESS_RESULT_KEY).get(ADDRESS_KEY).asText(); + } + logError("地址解析失败==>{}", jsonObject.get(MSG_KEY).asText()); + return null; + } + logError("地址解析失败==>{}", response.message()); + return null; + } + logError("地址解析失败==>{}", response.message()); + return null; + } catch (Exception e) { + logError("地址解析失败==>{}", e.getMessage() + Arrays.toString(e.getStackTrace())); + return null; + } + } + + /** + * 输入经纬度,返回地址明细(含区域ID、县区名)。 + * + * @param location 经纬度 + * @return 地址 + */ + public JsonNode getLocationToAddressDetails(JsonNode location) { + //String locationStr = String.format("%f,%f", location.getDouble(LATITUDE_KEY), location.getDouble(LONGITUDE_KEY)); + String locationStr = String.format("%f,%f", location.get(LONGITUDE_KEY).asDouble(), location.get(LATITUDE_KEY).asDouble()); + Request request = new Request.Builder() + .url(url + "/"+LOCATION_TO_ADDRESS + "?location=" + locationStr + "&key=" + accessKey) + .build(); + try(Response response = client.newCall(request).execute()) { + if(response.isSuccessful()) { + if (response.body()!= null) { + String result = response.body().string(); + JsonNode jsonObject = objectMapper.readTree(result); + if (jsonObject.get(STATUS_KEY).asInt() == CODE_STATUS_SUCCESS) { + JsonNode address = objectMapper.createObjectNode(); + //String detail = jsonObject.getJSONObject(ADDRESS_RESULT_KEY).getJSONObject(ADDRESS_KEY).getString(STANDARD_ADDRESS_KEY); + String detail = jsonObject.get(ADDRESS_RESULT_KEY).get(ADDRESS_KEY).asText(); + ((com.fasterxml.jackson.databind.node.ObjectNode) address).put("detail", detail); + //String district = jsonObject.getJSONObject(ADDRESS_RESULT_KEY).getJSONObject(ADDRESS_COMPONENT_KEY).getString(DISTRICT_KEY); + String district = jsonObject.get(ADDRESS_RESULT_KEY).get(ADDRESS_COMPONENT_KEY).get(DISTRICT_KEY).asText(); + ((com.fasterxml.jackson.databind.node.ObjectNode) address).put("district", district); + //String adcode = jsonObject.getJSONObject(ADDRESS_RESULT_KEY).getJSONObject(ADDRESS_COMPONENT_KEY).getString(ADCODE_KEY); + String adcode = jsonObject.get(ADDRESS_RESULT_KEY).get(ADDRESS_COMPONENT_KEY).get(ADCODE_KEY).asText(); + ((com.fasterxml.jackson.databind.node.ObjectNode) address).put("adcode", adcode); + return address; + } + logError("地址解析失败==>{}", jsonObject.get(MSG_KEY).asText()); + return null; + } + logError("地址解析失败==>{}", response.message()); + return null; + } + logError("地址解析失败==>{}", response.message()); + return null; + } catch (Exception e) { + logError("地址解析失败==>{}", e.getMessage() + Arrays.toString(e.getStackTrace())); + return null; + } + } + + /** + * 输入地址,返回经纬度(GCJ02)。 + * + * @param address 地址 + * @return 经纬度 + */ + public JsonNode getAddressToLocation(String address) { + Request request = new Request.Builder() + .url(url + "/"+ADDRESS_TO_LOCATION + "?address=" + address + "&key=" + accessKey) + .build(); + try(Response response = client.newCall(request).execute()) { + if(response.isSuccessful()) { + if (response.body() != null) { + String result = response.body().string(); + JsonNode jsonObject = objectMapper.readTree(result); + if (jsonObject.get(STATUS_KEY).asInt() == CODE_STATUS_SUCCESS) { + // 腾讯地图webservice的位置是 JSONObject {"lat": 39.9042, "lng": 116.4074} + //return jsonObject.getJSONObject(LOCATION_RESULT_KEY).getJSONObject(LOCATION_KEY); + String loc = jsonObject.get(LOCATION_RESULT_KEY).get(0).get(LOCATION_KEY).asText(); + String[] locArr = loc.split(","); + ObjectNode location = objectMapper.createObjectNode(); + location.put("lng", Double.valueOf(locArr[0])); + location.put("lat", Double.valueOf(locArr[1])); + return location; + }else{ + logError("位置解析失败==>{}", jsonObject.get(MSG_KEY).asText()); + return null; + } + }else{ + logError("位置解析失败==>{}", response.message()); + return null; + } + }else{ + logError("位置解析失败==>{}", response.message()); + return null; + } + } catch (Exception e) { + logError("位置解析失败==>{}", e.getMessage() + Arrays.toString(e.getStackTrace())); + return null; + } + } + + + private void logError(String errDesc, String errorMessage) { + log.error(errDesc, errorMessage); + } +} \ No newline at end of file