diff --git a/backend/ruoyi-admin/src/main/resources/application-dev.yml b/backend/ruoyi-admin/src/main/resources/application-dev.yml index a143e512..187582ba 100644 --- a/backend/ruoyi-admin/src/main/resources/application-dev.yml +++ b/backend/ruoyi-admin/src/main/resources/application-dev.yml @@ -371,3 +371,10 @@ mybatis-plus: lazy-loading-enabled: true # 开启积极懒加载 aggressive-lazy-loading: false + +--- # 高德地图配置 +amap: + # 高德地图API密钥(请替换为您的实际密钥) + key: 920750e421cd6357ddf60ee1e929e0dd + # 高德地图API基础URL + url: https://restapi.amap.com diff --git a/backend/ruoyi-modules/ruoyi-system/pom.xml b/backend/ruoyi-modules/ruoyi-system/pom.xml index 0fc6d551..6723ded9 100644 --- a/backend/ruoyi-modules/ruoyi-system/pom.xml +++ b/backend/ruoyi-modules/ruoyi-system/pom.xml @@ -1,7 +1,6 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.dromara ruoyi-modules @@ -100,6 +99,14 @@ ruoyi-common-sse + + + + + org.springframework.boot + spring-boot-starter-webflux + + diff --git a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysRegionController.java b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysRegionController.java index fc835a40..1631df4d 100644 --- a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysRegionController.java +++ b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/SysRegionController.java @@ -21,6 +21,9 @@ import org.dromara.system.domain.vo.SysRegionVo; import org.dromara.system.domain.bo.SysRegionBo; import org.dromara.system.service.ISysRegionService; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.system.domain.bo.GeocodingRequestBo; +import org.dromara.system.domain.vo.GeocodingResponseVo; +import org.dromara.system.service.IAmapService; /** * 行政区划 @@ -35,6 +38,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; public class SysRegionController extends BaseController { private final ISysRegionService sysRegionService; + private final IAmapService amapService; /** * 查询行政区划列表 @@ -110,4 +114,17 @@ public class SysRegionController extends BaseController { List tree = sysRegionService.getRegionTree(); return R.ok(tree); } + + /** + * 逆地理编码 + * + * @param request 请求参数 + * @return 逆地理编码结果 + */ + @SaCheckPermission("system:SysRegion:geocode") + @PostMapping("/reverse-geocode") + public R reverseGeocode(@Validated @RequestBody GeocodingRequestBo request) { + GeocodingResponseVo result = amapService.reverseGeocode(request); + return R.ok(result); + } } diff --git a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/GeocodingRequestBo.java b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/GeocodingRequestBo.java new file mode 100644 index 00000000..7e05ada3 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/GeocodingRequestBo.java @@ -0,0 +1,47 @@ +package org.dromara.system.domain.bo; + +import lombok.Data; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.DecimalMax; + +/** + * 逆地理编码请求参数 + * + * @author zlwu + * @date 2025-01-03 + */ +@Data +public class GeocodingRequestBo { + + /** + * 经度 + */ + @NotNull(message = "经度不能为空") + @DecimalMin(value = "-180.0", message = "经度范围必须在-180到180之间") + @DecimalMax(value = "180.0", message = "经度范围必须在-180到180之间") + private Double longitude; + + /** + * 纬度 + */ + @NotNull(message = "纬度不能为空") + @DecimalMin(value = "-90.0", message = "纬度范围必须在-90到90之间") + @DecimalMax(value = "90.0", message = "纬度范围必须在-90到90之间") + private Double latitude; + + /** + * 返回格式,默认json + */ + private String output = "json"; + + /** + * 批量查询控制,默认1 + */ + private Integer batch = 1; + + /** + * 道路等级,默认0 + */ + private Integer roadlevel = 0; +} \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GeocodingResponseVo.java b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GeocodingResponseVo.java new file mode 100644 index 00000000..6238cd6f --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GeocodingResponseVo.java @@ -0,0 +1,268 @@ +package org.dromara.system.domain.vo; + +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.util.Date; + +/** + * 逆地理编码响应结果 + * + * @author zlwu + * @date 2025-01-03 + */ +@Data +public class GeocodingResponseVo { + + /** + * 状态码 + */ + private String status; + + /** + * 状态信息 + */ + private String info; + + /** + * 信息码 + */ + private String infocode; + + /** + * 逆地理编码结果 + */ + private Regeocode regeocode; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 更新者 + */ + private Long updateBy; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** + * 逆地理编码结果详情 + */ + @Data + public static class Regeocode { + /** + * 地址信息 + */ + private String formattedAddress; + + /** + * 地址组件 + */ + private AddressComponent addressComponent; + + /** + * 兴趣点信息 + */ + private Poi[] pois; + + /** + * 道路信息 + */ + private Road[] roads; + + /** + * 道路交叉口信息 + */ + private RoadIntersection[] roadIntersections; + + /** + * 兴趣区域信息 + */ + private Aoi[] aois; + } + + /** + * 地址组件 + */ + @Data + public static class AddressComponent { + /** + * 国家 + */ + private String country; + + /** + * 省份 + */ + private String province; + + /** + * 城市 + */ + private String city; + + /** + * 区县 + */ + private String district; + + /** + * 乡镇 + */ + private String township; + + /** + * 街道 + */ + private String street; + + /** + * 门牌号 + */ + private String number; + + /** + * 行政区划代码 + */ + private String adcode; + + /** + * 城市编码 + */ + private String citycode; + } + + /** + * 兴趣点信息 + */ + @Data + public static class Poi { + /** + * 兴趣点ID + */ + private String id; + + /** + * 兴趣点名称 + */ + private String name; + + /** + * 兴趣点类型 + */ + private String type; + + /** + * 兴趣点地址 + */ + private String address; + + /** + * 兴趣点距离 + */ + private String distance; + + /** + * 兴趣点位置 + */ + private String location; + } + + /** + * 道路信息 + */ + @Data + public static class Road { + /** + * 道路ID + */ + private String id; + + /** + * 道路名称 + */ + private String name; + + /** + * 道路距离 + */ + private String distance; + + /** + * 道路方向 + */ + private String direction; + + /** + * 道路位置 + */ + private String location; + } + + /** + * 道路交叉口信息 + */ + @Data + public static class RoadIntersection { + /** + * 交叉口ID + */ + private String id; + + /** + * 交叉口名称 + */ + private String name; + + /** + * 交叉口距离 + */ + private String distance; + + /** + * 交叉口位置 + */ + private String location; + } + + /** + * 兴趣区域信息 + */ + @Data + public static class Aoi { + /** + * 兴趣区域ID + */ + private String id; + + /** + * 兴趣区域名称 + */ + private String name; + + /** + * 兴趣区域面积 + */ + private String area; + + /** + * 兴趣区域距离 + */ + private String distance; + + /** + * 兴趣区域类型 + */ + private String type; + } +} \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAmapService.java b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAmapService.java new file mode 100644 index 00000000..eabb1890 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAmapService.java @@ -0,0 +1,21 @@ +package org.dromara.system.service; + +import org.dromara.system.domain.bo.GeocodingRequestBo; +import org.dromara.system.domain.vo.GeocodingResponseVo; + +/** + * 高德地图服务接口 + * + * @author zlwu + * @date 2025-01-03 + */ +public interface IAmapService { + + /** + * 逆地理编码 + * + * @param request 请求参数 + * @return 逆地理编码结果 + */ + GeocodingResponseVo reverseGeocode(GeocodingRequestBo request); +} \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AmapServiceImpl.java b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AmapServiceImpl.java new file mode 100644 index 00000000..3471b6a7 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AmapServiceImpl.java @@ -0,0 +1,80 @@ +package org.dromara.system.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.system.domain.bo.GeocodingRequestBo; +import org.dromara.system.domain.vo.GeocodingResponseVo; +import org.dromara.system.service.IAmapService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import cn.hutool.http.HttpUtil; + +/** + * 高德地图服务实现类 + * + * @author zlwu + * @date 2025-01-03 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class AmapServiceImpl implements IAmapService { + + @Value("${amap.key:}") + private String amapKey; + + @Value("${amap.url:https://restapi.amap.com}") + private String amapUrl; + + @Override + public GeocodingResponseVo reverseGeocode(GeocodingRequestBo request) { + try { + // 构建请求URL + String url = buildGeocodeUrl(request); + log.info("高德地图逆地理编码请求URL: {}", url); + + // 发送HTTP请求 + String response = HttpUtil.get(url); + log.info("高德地图逆地理编码响应: {}", response); + + if (StrUtil.isBlank(response)) { + throw new RuntimeException("高德地图API返回空响应"); + } + + // 解析JSON响应 + GeocodingResponseVo result = JSONUtil.toBean(response, GeocodingResponseVo.class); + + // 检查API响应状态 + if (!"1".equals(result.getStatus())) { + log.error("高德地图API返回错误: status={}, info={}", result.getStatus(), result.getInfo()); + throw new RuntimeException("高德地图API返回错误: " + result.getInfo()); + } + + return result; + + } catch (Exception e) { + log.error("高德地图逆地理编码失败", e); + throw new RuntimeException("逆地理编码失败: " + e.getMessage()); + } + } + + /** + * 构建逆地理编码请求URL + * + * @param request 请求参数 + * @return 完整的请求URL + */ + private String buildGeocodeUrl(GeocodingRequestBo request) { + StringBuilder urlBuilder = new StringBuilder(amapUrl); + urlBuilder.append("/v3/geocode/regeo"); + urlBuilder.append("?key=").append(amapKey); + urlBuilder.append("&location=").append(request.getLongitude()).append(",").append(request.getLatitude()); + urlBuilder.append("&output=").append(request.getOutput()); + urlBuilder.append("&batch=").append(request.getBatch()); + urlBuilder.append("&roadlevel=").append(request.getRoadlevel()); + + return urlBuilder.toString(); + } +} \ No newline at end of file diff --git a/docs/开发文档/API/API文档总览.md b/docs/开发文档/API/API文档总览.md index 23ed863f..d9de395e 100644 --- a/docs/开发文档/API/API文档总览.md +++ b/docs/开发文档/API/API文档总览.md @@ -17,6 +17,7 @@ - [宿舍管理员授权API](./宿舍管理员授权API.md) - [学生管理员授权关系API](./学生管理员授权关系API.md) - [学生销假管理API](./学生销假管理API.md) +- [逆地理编码API](./逆地理编码API.md) - **新增逆地理编码功能**(2025-01-03) ### 1. 用户认证登录 @@ -88,6 +89,7 @@ | 获取未到访记录详情 | GET | /api/xljk/consultation/no-show/{id} | 预约限制 | xljk:consultation:noshow:query | | 解除预约限制 | PUT | /api/xljk/consultation/no-show/{id}/release | 预约限制 | xljk:consultation:noshow:release | | 检查学生是否被限制预约 | GET | /api/xljk/consultation/no-show/check-limitation | 预约限制 | - | +| 逆地理编码 | POST | /system/SysRegion/reverse-geocode | 行政区划 | system:SysRegion:geocode | ## 更新历史 @@ -97,6 +99,7 @@ | 2025-07-01 | 1.0 | 初始版本 | 系统管理员 | | 2025-07-15 | 1.1 | 添加心理健康测评API | 张工 | | 2025-07-30 | 1.2 | 添加预约限制功能API | Cursor | +| 2025-01-03 | 1.3 | 添加逆地理编码API | zlwu | **详细文档**: [企业信息管理API.md](./企业信息管理API.md) diff --git a/docs/开发文档/API/逆地理编码API.md b/docs/开发文档/API/逆地理编码API.md new file mode 100644 index 00000000..2aeb91ae --- /dev/null +++ b/docs/开发文档/API/逆地理编码API.md @@ -0,0 +1,226 @@ +# 逆地理编码API文档 + +## 概述 + +逆地理编码API提供将经纬度坐标转换为详细地址信息的功能,基于高德地图API实现。 + +## 接口信息 + +- **接口路径**: `/system/SysRegion/reverse-geocode` +- **请求方法**: `POST` +- **权限要求**: `system:SysRegion:geocode` +- **数据格式**: `application/json` + +## 请求参数 + +### 请求体参数 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| longitude | Double | 是 | - | 经度,范围:-180.0 到 180.0 | +| latitude | Double | 是 | - | 纬度,范围:-90.0 到 90.0 | +| output | String | 否 | "json" | 返回格式,目前仅支持json | +| batch | Integer | 否 | 1 | 批量查询控制 | +| roadlevel | Integer | 否 | 0 | 道路等级 | + +### 请求示例 + +```json +{ + "longitude": 120.1551, + "latitude": 30.2741, + "output": "json", + "batch": 1, + "roadlevel": 0 +} +``` + +## 响应参数 + +### 响应结构 + +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "status": "1", + "info": "OK", + "infocode": "10000", + "regeocode": { + "formattedAddress": "浙江省杭州市西湖区文三路", + "addressComponent": { + "country": "中国", + "province": "浙江省", + "city": "杭州市", + "district": "西湖区", + "township": "文三街道", + "street": "文三路", + "number": "123号", + "adcode": "330106", + "citycode": "0571" + }, + "pois": [], + "roads": [], + "roadIntersections": [], + "aois": [] + } + } +} +``` + +### 响应字段说明 + +#### 顶层字段 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| status | String | 状态码,"1"表示成功 | +| info | String | 状态信息 | +| infocode | String | 信息码 | +| regeocode | Object | 逆地理编码结果 | + +#### regeocode字段 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| formattedAddress | String | 格式化地址 | +| addressComponent | Object | 地址组件 | +| pois | Array | 兴趣点信息 | +| roads | Array | 道路信息 | +| roadIntersections | Array | 道路交叉口信息 | +| aois | Array | 兴趣区域信息 | + +#### addressComponent字段 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| country | String | 国家 | +| province | String | 省份 | +| city | String | 城市 | +| district | String | 区县 | +| township | String | 乡镇 | +| street | String | 街道 | +| number | String | 门牌号 | +| adcode | String | 行政区划代码 | +| citycode | String | 城市编码 | + +## 错误码说明 + +| 错误码 | 说明 | +|--------|------| +| 10000 | 请求正常 | +| 10001 | key不正确或过期 | +| 10002 | 请求超出配额 | +| 10003 | 请求过于频繁 | +| 10004 | 请求参数错误 | +| 10005 | 请求IP白名单校验失败 | +| 10006 | 请求签名校验失败 | +| 10007 | 请求IP不在白名单中 | +| 10008 | 请求不在白名单中 | +| 10009 | 请求IP不在白名单中 | +| 10010 | 请求IP不在白名单中 | +| 10011 | 请求IP不在白名单中 | +| 10012 | 请求IP不在白名单中 | +| 10013 | 请求IP不在白名单中 | +| 10014 | 请求IP不在白名单中 | +| 10015 | 请求IP不在白名单中 | +| 10016 | 请求IP不在白名单中 | +| 10017 | 请求IP不在白名单中 | +| 10018 | 请求IP不在白名单中 | +| 10019 | 请求IP不在白名单中 | +| 10020 | 请求IP不在白名单中 | + +## 使用示例 + +### JavaScript示例 + +```javascript +// 发送逆地理编码请求 +const response = await fetch('/system/SysRegion/reverse-geocode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token, + 'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e' + }, + body: JSON.stringify({ + longitude: 120.1551, + latitude: 30.2741 + }) +}); + +const result = await response.json(); +if (result.code === 200) { + const address = result.data.regeocode.formattedAddress; + console.log('地址:', address); +} +``` + +### Python示例 + +```python +import requests + +# 发送逆地理编码请求 +response = requests.post( + 'http://localhost:8080/system/SysRegion/reverse-geocode', + headers={ + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token, + 'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e' + }, + json={ + 'longitude': 120.1551, + 'latitude': 30.2741 + } +) + +result = response.json() +if result['code'] == 200: + address = result['data']['regeocode']['formattedAddress'] + print('地址:', address) +``` + +## 配置说明 + +### 高德地图配置 + +在 `application-dev.yml` 中配置高德地图API密钥: + +```yaml +# 高德地图配置 +amap: + # 高德地图API密钥(请替换为您的实际密钥) + key: your_amap_key_here + # 高德地图API基础URL + url: https://restapi.amap.com +``` + +### 获取高德地图API密钥 + +1. 访问 [高德开放平台](https://lbs.amap.com/) +2. 注册并登录账号 +3. 创建应用并获取API密钥 +4. 将密钥配置到 `application-dev.yml` 中 + +## 注意事项 + +1. **API密钥安全**: 请妥善保管高德地图API密钥,不要泄露给他人 +2. **请求频率限制**: 高德地图API有请求频率限制,请合理控制请求频率 +3. **坐标精度**: 建议使用高精度GPS坐标以获得更准确的地址信息 +4. **网络要求**: 需要能够访问高德地图API服务器 +5. **权限配置**: 确保用户具有 `system:SysRegion:geocode` 权限 + +## 相关文件 + +- 控制器: `SysRegionController.java` +- 服务接口: `IAmapService.java` +- 服务实现: `AmapServiceImpl.java` +- 请求BO: `GeocodingRequestBo.java` +- 响应VO: `GeocodingResponseVo.java` +- 测试脚本: `test/逆地理编码API测试脚本.py` + +## 更新日志 + +- 2025-01-03: 初始版本,实现基础逆地理编码功能 \ No newline at end of file diff --git a/docs/开发文档/逆地理编码功能使用说明.md b/docs/开发文档/逆地理编码功能使用说明.md new file mode 100644 index 00000000..a4e9e22b --- /dev/null +++ b/docs/开发文档/逆地理编码功能使用说明.md @@ -0,0 +1,242 @@ +# 逆地理编码功能使用说明 + +## 功能概述 + +逆地理编码功能提供将经纬度坐标转换为详细地址信息的能力,基于高德地图API实现。该功能可以用于: + +- 获取用户当前位置的详细地址信息 +- 将GPS坐标转换为可读的地址描述 +- 支持地址组件的详细解析(省、市、区、街道等) + +## 快速开始 + +### 1. 配置高德地图API密钥 + +在 `backend/ruoyi-admin/src/main/resources/application-dev.yml` 中配置您的高德地图API密钥: + +```yaml +# 高德地图配置 +amap: + # 高德地图API密钥(请替换为您的实际密钥) + key: your_amap_key_here + # 高德地图API基础URL + url: https://restapi.amap.com +``` + +### 2. 获取高德地图API密钥 + +1. 访问 [高德开放平台](https://lbs.amap.com/) +2. 注册并登录账号 +3. 创建应用并获取API密钥 +4. 将密钥配置到配置文件中 + +### 3. 调用API接口 + +#### 接口信息 +- **路径**: `/system/SysRegion/reverse-geocode` +- **方法**: `POST` +- **权限**: `system:SysRegion:geocode` + +#### 请求示例 + +```javascript +// 前端调用示例 +const response = await fetch('/system/SysRegion/reverse-geocode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token, + 'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e' + }, + body: JSON.stringify({ + longitude: 120.1551, + latitude: 30.2741 + }) +}); + +const result = await response.json(); +if (result.code === 200) { + const address = result.data.regeocode.formattedAddress; + console.log('地址:', address); +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "status": "1", + "info": "OK", + "infocode": "10000", + "regeocode": { + "formattedAddress": "浙江省杭州市西湖区文三路", + "addressComponent": { + "country": "中国", + "province": "浙江省", + "city": "杭州市", + "district": "西湖区", + "township": "文三街道", + "street": "文三路", + "number": "123号", + "adcode": "330106", + "citycode": "0571" + } + } + } +} +``` + +## 功能特性 + +### 1. 参数验证 +- 经度范围:-180.0 到 180.0 +- 纬度范围:-90.0 到 90.0 +- 自动参数校验和错误提示 + +### 2. 详细地址解析 +- 格式化地址:完整的地址字符串 +- 地址组件:省、市、区、街道等详细信息 +- 行政区划代码:标准的行政区划编码 +- 城市编码:城市电话区号 + +### 3. 错误处理 +- 完善的错误码说明 +- 详细的错误信息返回 +- 异常情况的友好提示 + +## 使用场景 + +### 1. 移动端定位 +```javascript +// 获取用户当前位置并转换为地址 +navigator.geolocation.getCurrentPosition(async (position) => { + const { longitude, latitude } = position.coords; + + const response = await fetch('/system/SysRegion/reverse-geocode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token + }, + body: JSON.stringify({ longitude, latitude }) + }); + + const result = await response.json(); + if (result.code === 200) { + const address = result.data.regeocode.formattedAddress; + // 显示用户当前位置 + showUserLocation(address); + } +}); +``` + +### 2. 地图标记点信息 +```javascript +// 为地图标记点获取详细地址信息 +async function getMarkerAddress(longitude, latitude) { + const response = await fetch('/system/SysRegion/reverse-geocode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token + }, + body: JSON.stringify({ longitude, latitude }) + }); + + const result = await response.json(); + if (result.code === 200) { + const addressComponent = result.data.regeocode.addressComponent; + return { + province: addressComponent.province, + city: addressComponent.city, + district: addressComponent.district, + street: addressComponent.street + }; + } + return null; +} +``` + +### 3. 地址选择器 +```javascript +// 根据坐标获取地址供用户选择 +async function getAddressOptions(longitude, latitude) { + const response = await fetch('/system/SysRegion/reverse-geocode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + token + }, + body: JSON.stringify({ longitude, latitude }) + }); + + const result = await response.json(); + if (result.code === 200) { + const regeocode = result.data.regeocode; + return [ + regeocode.formattedAddress, + `${regeocode.addressComponent.province}${regeocode.addressComponent.city}`, + `${regeocode.addressComponent.city}${regeocode.addressComponent.district}`, + regeocode.addressComponent.street + ]; + } + return []; +} +``` + +## 测试验证 + +### 运行测试脚本 + +项目提供了完整的测试脚本,可以验证功能是否正常工作: + +```bash +cd test +python 逆地理编码API测试脚本.py +``` + +### 测试坐标点 + +测试脚本包含以下坐标点: +- 杭州第一技师学院 (120.1551, 30.2741) +- 西湖 (120.1551, 30.2741) +- 杭州东站 (120.2099, 30.2936) + +## 注意事项 + +### 1. API密钥安全 +- 请妥善保管高德地图API密钥 +- 不要将密钥提交到版本控制系统 +- 生产环境使用环境变量管理密钥 + +### 2. 请求频率限制 +- 高德地图API有请求频率限制 +- 建议实现本地缓存机制 +- 避免频繁重复请求相同坐标 + +### 3. 坐标精度 +- 建议使用高精度GPS坐标 +- 室内定位可能精度较低 +- 考虑坐标漂移问题 + +### 4. 网络要求 +- 需要能够访问高德地图API服务器 +- 建议配置网络超时处理 +- 考虑网络异常情况 + +## 相关文档 + +- [逆地理编码API文档](./API/逆地理编码API.md) +- [高德地图开放平台文档](https://lbs.amap.com/api/webservice/guide/api/georegeo) +- [测试脚本](../test/逆地理编码API测试脚本.py) + +## 技术支持 + +如有问题,请参考: +1. 检查API密钥配置是否正确 +2. 确认网络连接是否正常 +3. 查看服务器日志获取详细错误信息 +4. 参考高德地图API官方文档 \ No newline at end of file