|
|
@@ -1,13 +1,24 @@
|
|
|
package com.ylx.massage.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.ylx.common.config.AmapConfig;
|
|
|
+import com.ylx.common.core.domain.R;
|
|
|
+import com.ylx.common.exception.ServiceException;
|
|
|
+import com.ylx.common.utils.http.HttpUtils;
|
|
|
import com.ylx.massage.domain.Area;
|
|
|
-import com.ylx.massage.domain.vo.AreaTreeNode;
|
|
|
+import com.ylx.massage.domain.dto.CoordinateDTO;
|
|
|
+import com.ylx.massage.domain.vo.*;
|
|
|
import com.ylx.massage.mapper.AreaMapper;
|
|
|
import com.ylx.massage.service.AreaService;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
@@ -16,6 +27,17 @@ import java.util.stream.Collectors;
|
|
|
@Service("areaService")
|
|
|
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {
|
|
|
|
|
|
+ @Resource
|
|
|
+ private AmapConfig amapConfig;
|
|
|
+
|
|
|
+ private static final String AMAP_URL_PATTERN = "https://restapi.amap.com/v3/geocode/regeo?key=%s&location=%s,%s";
|
|
|
+
|
|
|
+ private static final String AMAP_SUCCESS_STATUS = "1";
|
|
|
+ private static final String ERROR_MSG_API_KEY_MISSING = "配置文件中未找到或 app.amap-api-key 为空";
|
|
|
+ private static final String ERROR_MSG_LOCATION_FAILED = "获取地理位置异常";
|
|
|
+ private static final String ERROR_MSG_CITY_NOT_FOUND = "城市数据不存在";
|
|
|
+ private static final int MAX_QUERY_RESULTS = 1;
|
|
|
+
|
|
|
/**
|
|
|
* 一次性查询所有区域,内存构建树形结构
|
|
|
*/
|
|
|
@@ -58,4 +80,79 @@ public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements Ar
|
|
|
.filter(node -> "0".equals(node.getParentCode()))
|
|
|
.collect(Collectors.toList());
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CityInfoVo getCityInfoByCoordinates(CoordinateDTO dto) {
|
|
|
+ // 参数验证
|
|
|
+ validateCoordinates(dto);
|
|
|
+
|
|
|
+ // 获取API Key
|
|
|
+ String amapKey = amapConfig.getApiKey();
|
|
|
+ if (StrUtil.isEmpty(amapKey)) {
|
|
|
+ log.error(ERROR_MSG_API_KEY_MISSING);
|
|
|
+ throw new ServiceException(ERROR_MSG_API_KEY_MISSING);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 调用高德API
|
|
|
+ String url = String.format(AMAP_URL_PATTERN, amapKey, dto.getLongitude(), dto.getLatitude());
|
|
|
+ String response = HttpUtils.sendGet(url);
|
|
|
+
|
|
|
+ // 解析响应
|
|
|
+ AmapRegeoVo amapResponse = parseAmapResponse(response);
|
|
|
+
|
|
|
+ // 获取城市信息
|
|
|
+ return getCityInfo(amapResponse);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取城市信息失败", e);
|
|
|
+ throw new ServiceException(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateCoordinates(CoordinateDTO dto) {
|
|
|
+ if (dto == null) {
|
|
|
+ throw new IllegalArgumentException("坐标信息不能为空");
|
|
|
+ }
|
|
|
+ if (dto.getLongitude() < -180 || dto.getLongitude() > 180) {
|
|
|
+ throw new IllegalArgumentException("经度必须在-180到180之间");
|
|
|
+ }
|
|
|
+ if (dto.getLatitude() < -90 || dto.getLatitude() > 90) {
|
|
|
+ throw new IllegalArgumentException("纬度必须在-90到90之间");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AmapRegeoVo parseAmapResponse(String response) {
|
|
|
+ if (StrUtil.isEmpty(response)) {
|
|
|
+ throw new ServiceException(ERROR_MSG_LOCATION_FAILED);
|
|
|
+ }
|
|
|
+
|
|
|
+ AmapRegeoVo vo = JSONObject.parseObject(response, AmapRegeoVo.class);
|
|
|
+ if (vo == null || !AMAP_SUCCESS_STATUS.equals(vo.getStatus())) {
|
|
|
+ throw new ServiceException(ERROR_MSG_LOCATION_FAILED);
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private CityInfoVo getCityInfo(AmapRegeoVo amapResponse) {
|
|
|
+ if (amapResponse == null || amapResponse.getRegeocode() == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ AddressComponent addressComponent = amapResponse.getRegeocode().getAddressComponent();
|
|
|
+ if (addressComponent == null || StrUtil.isEmpty(addressComponent.getCity())) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优化查询,只取第一条记录
|
|
|
+ LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(Area::getName, addressComponent.getCity())
|
|
|
+ .last("LIMIT " + MAX_QUERY_RESULTS);
|
|
|
+
|
|
|
+ Area area = this.getOne(queryWrapper);
|
|
|
+ if (area == null) {
|
|
|
+ throw new ServiceException(ERROR_MSG_CITY_NOT_FOUND);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new CityInfoVo(area.getName(), area.getCode());
|
|
|
+ }
|
|
|
}
|