From 2c2e4a52b40a27313cc1dde758f1cc92ba6cae35 Mon Sep 17 00:00:00 2001
From: zlwu <704541015@qq.com>
Date: Sat, 16 Aug 2025 23:02:25 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/application-dev.yml | 7 +
backend/ruoyi-modules/ruoyi-system/pom.xml | 11 +-
.../controller/SysRegionController.java | 17 ++
.../system/domain/bo/GeocodingRequestBo.java | 47 +++
.../system/domain/vo/GeocodingResponseVo.java | 268 ++++++++++++++++++
.../dromara/system/service/IAmapService.java | 21 ++
.../system/service/impl/AmapServiceImpl.java | 80 ++++++
docs/开发文档/API/API文档总览.md | 3 +
docs/开发文档/API/逆地理编码API.md | 226 +++++++++++++++
docs/开发文档/逆地理编码功能使用说明.md | 242 ++++++++++++++++
10 files changed, 920 insertions(+), 2 deletions(-)
create mode 100644 backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/GeocodingRequestBo.java
create mode 100644 backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/GeocodingResponseVo.java
create mode 100644 backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAmapService.java
create mode 100644 backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AmapServiceImpl.java
create mode 100644 docs/开发文档/API/逆地理编码API.md
create mode 100644 docs/开发文档/逆地理编码功能使用说明.md
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