expo-gaode-map-search 1.3.1-next.0 → 1.3.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -7
- package/android/src/main/java/expo/modules/gaodemap/search/ExpoGaodeMapSearchModule.kt +411 -67
- package/build/ExpoGaodeMapSearch.types.d.ts +158 -1
- package/build/ExpoGaodeMapSearch.types.js +2 -0
- package/build/ExpoGaodeMapSearchModule.d.ts +12 -1
- package/build/index.d.ts +32 -2
- package/build/index.js +36 -0
- package/ios/ExpoGaodeMapSearchModule.swift +292 -14
- package/package.json +4 -5
- package/src/ExpoGaodeMapSearch.types.ts +164 -0
- package/src/ExpoGaodeMapSearchModule.ts +27 -2
- package/src/index.ts +48 -0
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
package expo.modules.gaodemap.search
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
|
|
4
5
|
import com.amap.api.services.core.LatLonPoint
|
|
5
6
|
import com.amap.api.services.core.PoiItem
|
|
7
|
+
import com.amap.api.services.core.PoiItemV2
|
|
8
|
+
|
|
9
|
+
import com.amap.api.services.geocoder.GeocodeResult
|
|
10
|
+
import com.amap.api.services.geocoder.GeocodeSearch
|
|
11
|
+
import com.amap.api.services.geocoder.RegeocodeQuery
|
|
12
|
+
import com.amap.api.services.geocoder.RegeocodeResult
|
|
6
13
|
import com.amap.api.services.help.Inputtips
|
|
7
14
|
import com.amap.api.services.help.InputtipsQuery
|
|
8
15
|
import com.amap.api.services.help.Tip
|
|
9
|
-
import com.amap.api.services.poisearch.
|
|
10
|
-
import com.amap.api.services.poisearch.
|
|
11
|
-
|
|
16
|
+
import com.amap.api.services.poisearch.PoiResultV2
|
|
17
|
+
import com.amap.api.services.poisearch.PoiSearchV2
|
|
18
|
+
|
|
12
19
|
import com.amap.api.services.routepoisearch.RoutePOISearch
|
|
13
20
|
import com.amap.api.services.routepoisearch.RoutePOISearchQuery
|
|
14
21
|
import com.amap.api.services.routepoisearch.RoutePOISearchResult
|
|
15
22
|
import expo.modules.kotlin.Promise
|
|
16
23
|
import expo.modules.kotlin.modules.Module
|
|
17
24
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
25
|
+
import kotlin.collections.mapOf
|
|
18
26
|
|
|
19
27
|
class ExpoGaodeMapSearchModule : Module() {
|
|
20
28
|
private val context: Context
|
|
@@ -23,10 +31,18 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
23
31
|
override fun definition() = ModuleDefinition {
|
|
24
32
|
Name("ExpoGaodeMapSearch")
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* 手动初始化搜索模块(可选)
|
|
36
|
+
*/
|
|
37
|
+
Function("initSearch") {
|
|
38
|
+
ensureAPIKeyIsSet()
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
/**
|
|
27
42
|
* POI 搜索
|
|
28
43
|
*/
|
|
29
44
|
AsyncFunction("searchPOI") { options: Map<String, Any?>, promise: Promise ->
|
|
45
|
+
ensureAPIKeyIsSet()
|
|
30
46
|
try {
|
|
31
47
|
val keyword = options["keyword"] as? String
|
|
32
48
|
?: throw Exception("keyword is required")
|
|
@@ -36,14 +52,15 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
36
52
|
val pageSize = (options["pageSize"] as? Number)?.toInt() ?: 20
|
|
37
53
|
val pageNum = (options["pageNum"] as? Number)?.toInt() ?: 1
|
|
38
54
|
|
|
39
|
-
val query =
|
|
55
|
+
val query = PoiSearchV2.Query(keyword, types, city)
|
|
40
56
|
query.pageSize = pageSize
|
|
41
57
|
query.pageNum = pageNum - 1 // 高德 SDK 从 0 开始
|
|
58
|
+
query.showFields = PoiSearchV2.ShowFields(PoiSearchV2.ShowFields.ALL)
|
|
42
59
|
|
|
43
|
-
val poiSearch =
|
|
60
|
+
val poiSearch = PoiSearchV2(context, query)
|
|
44
61
|
|
|
45
|
-
poiSearch.setOnPoiSearchListener(object :
|
|
46
|
-
override fun onPoiSearched(result:
|
|
62
|
+
poiSearch.setOnPoiSearchListener(object : PoiSearchV2.OnPoiSearchListener {
|
|
63
|
+
override fun onPoiSearched(result: PoiResultV2?, rCode: Int) {
|
|
47
64
|
if (rCode == 1000) {
|
|
48
65
|
promise.resolve(convertPoiResult(result))
|
|
49
66
|
} else {
|
|
@@ -51,7 +68,7 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
51
68
|
}
|
|
52
69
|
}
|
|
53
70
|
|
|
54
|
-
override fun onPoiItemSearched(item:
|
|
71
|
+
override fun onPoiItemSearched(item: PoiItemV2?, rCode: Int) {
|
|
55
72
|
// 不使用单个 POI 搜索
|
|
56
73
|
}
|
|
57
74
|
})
|
|
@@ -66,10 +83,12 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
66
83
|
* 周边搜索
|
|
67
84
|
*/
|
|
68
85
|
AsyncFunction("searchNearby") { options: Map<String, Any?>, promise: Promise ->
|
|
86
|
+
ensureAPIKeyIsSet()
|
|
69
87
|
try {
|
|
70
88
|
val keyword = options["keyword"] as? String
|
|
71
89
|
?: throw Exception("keyword is required")
|
|
72
90
|
|
|
91
|
+
@Suppress("UNCHECKED_CAST")
|
|
73
92
|
val center = options["center"] as? Map<String, Any?>
|
|
74
93
|
?: throw Exception("center is required")
|
|
75
94
|
|
|
@@ -83,25 +102,27 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
83
102
|
val pageSize = (options["pageSize"] as? Number)?.toInt() ?: 20
|
|
84
103
|
val pageNum = (options["pageNum"] as? Number)?.toInt() ?: 1
|
|
85
104
|
|
|
86
|
-
val query =
|
|
105
|
+
val query = PoiSearchV2.Query(keyword, types)
|
|
87
106
|
query.pageSize = pageSize
|
|
88
107
|
query.pageNum = pageNum - 1
|
|
108
|
+
query.showFields = PoiSearchV2.ShowFields(PoiSearchV2.ShowFields.ALL)
|
|
89
109
|
|
|
90
|
-
val poiSearch =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
val poiSearch = PoiSearchV2(context, query)
|
|
111
|
+
val centerPoint = LatLonPoint(latitude, longitude)
|
|
112
|
+
poiSearch.bound = PoiSearchV2.SearchBound(
|
|
113
|
+
centerPoint, radius
|
|
114
|
+
)
|
|
94
115
|
|
|
95
|
-
poiSearch.setOnPoiSearchListener(object :
|
|
96
|
-
override fun onPoiSearched(result:
|
|
116
|
+
poiSearch.setOnPoiSearchListener(object : PoiSearchV2.OnPoiSearchListener {
|
|
117
|
+
override fun onPoiSearched(result: PoiResultV2?, rCode: Int) {
|
|
97
118
|
if (rCode == 1000) {
|
|
98
|
-
promise.resolve(convertPoiResult(result))
|
|
119
|
+
promise.resolve(convertPoiResult(result, centerPoint))
|
|
99
120
|
} else {
|
|
100
121
|
promise.reject("SEARCH_ERROR", "Search failed with code: $rCode", null)
|
|
101
122
|
}
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
override fun onPoiItemSearched(item:
|
|
125
|
+
override fun onPoiItemSearched(item: PoiItemV2?, rCode: Int) {}
|
|
105
126
|
})
|
|
106
127
|
|
|
107
128
|
poiSearch.searchPOIAsyn()
|
|
@@ -114,10 +135,12 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
114
135
|
* 沿途搜索
|
|
115
136
|
*/
|
|
116
137
|
AsyncFunction("searchAlong") { options: Map<String, Any?>, promise: Promise ->
|
|
138
|
+
ensureAPIKeyIsSet()
|
|
117
139
|
try {
|
|
118
140
|
val keyword = options["keyword"] as? String
|
|
119
141
|
?: throw Exception("keyword is required")
|
|
120
142
|
|
|
143
|
+
@Suppress("UNCHECKED_CAST")
|
|
121
144
|
val polyline = options["polyline"] as? List<Map<String, Any?>>
|
|
122
145
|
?: throw Exception("polyline is required")
|
|
123
146
|
|
|
@@ -151,17 +174,15 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
151
174
|
|
|
152
175
|
val routePOISearch = RoutePOISearch(context, query)
|
|
153
176
|
|
|
154
|
-
routePOISearch.setPoiSearchListener
|
|
155
|
-
override fun onRoutePoiSearched(result: RoutePOISearchResult?, rCode: Int) {
|
|
177
|
+
routePOISearch.setPoiSearchListener { result, rCode ->
|
|
156
178
|
if (rCode == 1000 && result != null) {
|
|
157
|
-
|
|
179
|
+
promise.resolve(convertRoutePOIResult(result))
|
|
158
180
|
} else {
|
|
159
|
-
|
|
181
|
+
promise.reject("SEARCH_ERROR", "Route search failed with code: $rCode", null)
|
|
160
182
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
routePOISearch.searchRoutePOIAsyn()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
routePOISearch.searchRoutePOIAsyn()
|
|
165
186
|
} catch (e: Exception) {
|
|
166
187
|
promise.reject("SEARCH_ERROR", e.message, e)
|
|
167
188
|
}
|
|
@@ -171,10 +192,11 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
171
192
|
* 多边形搜索(使用矩形范围代替)
|
|
172
193
|
*/
|
|
173
194
|
AsyncFunction("searchPolygon") { options: Map<String, Any?>, promise: Promise ->
|
|
195
|
+
ensureAPIKeyIsSet()
|
|
174
196
|
try {
|
|
175
197
|
val keyword = options["keyword"] as? String
|
|
176
198
|
?: throw Exception("keyword is required")
|
|
177
|
-
|
|
199
|
+
@Suppress("UNCHECKED_CAST")
|
|
178
200
|
val polygon = options["polygon"] as? List<Map<String, Any?>>
|
|
179
201
|
?: throw Exception("polygon is required")
|
|
180
202
|
|
|
@@ -191,32 +213,65 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
191
213
|
LatLonPoint(lat, lng)
|
|
192
214
|
}
|
|
193
215
|
|
|
194
|
-
|
|
195
|
-
val maxLat = points.maxOf { it.latitude }
|
|
196
|
-
val minLng = points.minOf { it.longitude }
|
|
197
|
-
val maxLng = points.maxOf { it.longitude }
|
|
216
|
+
|
|
198
217
|
|
|
199
|
-
val query =
|
|
200
|
-
|
|
218
|
+
val query = PoiSearchV2.Query(keyword, types)
|
|
219
|
+
// 策略调整:为了解决 SDK 多边形搜索实为矩形搜索导致过滤后数据量过少的问题
|
|
220
|
+
// 我们强制请求最大数量 (50),然后在客户端过滤
|
|
221
|
+
// 注意:这会破坏精确的分页对应关系,但在多边形搜索场景下,优先保证返回有效数据更重要
|
|
222
|
+
val sdkPageSize = 50
|
|
223
|
+
query.pageSize = sdkPageSize
|
|
201
224
|
query.pageNum = pageNum - 1
|
|
225
|
+
query.showFields = PoiSearchV2.ShowFields(PoiSearchV2.ShowFields.ALL)
|
|
226
|
+
|
|
227
|
+
val poiSearch = PoiSearchV2(context, query)
|
|
202
228
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
poiSearch.setBound(PoiSearch.SearchBound(
|
|
206
|
-
LatLonPoint(minLat, minLng),
|
|
207
|
-
LatLonPoint(maxLat, maxLng)
|
|
208
|
-
))
|
|
229
|
+
// 使用 SDK 原生多边形搜索
|
|
230
|
+
poiSearch.bound = PoiSearchV2.SearchBound(points)
|
|
209
231
|
|
|
210
|
-
poiSearch.setOnPoiSearchListener(object :
|
|
211
|
-
override fun onPoiSearched(result:
|
|
232
|
+
poiSearch.setOnPoiSearchListener(object : PoiSearchV2.OnPoiSearchListener {
|
|
233
|
+
override fun onPoiSearched(result: PoiResultV2?, rCode: Int) {
|
|
212
234
|
if (rCode == 1000) {
|
|
213
|
-
|
|
235
|
+
val convertedResult = convertPoiResult(result).toMutableMap()
|
|
236
|
+
val pois = convertedResult["pois"] as? List<Map<String, Any?>>
|
|
237
|
+
|
|
238
|
+
if (pois != null) {
|
|
239
|
+
// 1. 客户端过滤:只保留在多边形内的点
|
|
240
|
+
val filteredPois = pois.filter { poi ->
|
|
241
|
+
val location = poi["location"] as? Map<String, Any?>
|
|
242
|
+
val lat = (location?.get("latitude") as? Number)?.toDouble()
|
|
243
|
+
val lng = (location?.get("longitude") as? Number)?.toDouble()
|
|
244
|
+
|
|
245
|
+
if (lat != null && lng != null) {
|
|
246
|
+
isPointInPolygon(LatLonPoint(lat, lng), points)
|
|
247
|
+
} else {
|
|
248
|
+
false
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 2. 处理分页截断 (恢复用户请求的 pageSize)
|
|
253
|
+
// 如果过滤后的数量多于用户请求的 pageSize,进行截断
|
|
254
|
+
// 注意:由于我们在 SDK 层请求了 50 条,这里尽量返回给用户填满 pageSize 的数据
|
|
255
|
+
val userPageSize = pageSize
|
|
256
|
+
val finalPois = if (filteredPois.size > userPageSize) {
|
|
257
|
+
filteredPois.subList(0, userPageSize)
|
|
258
|
+
} else {
|
|
259
|
+
filteredPois
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
convertedResult["pois"] = finalPois
|
|
263
|
+
// 更新统计信息,反映过滤后的实际情况
|
|
264
|
+
convertedResult["pageSize"] = userPageSize
|
|
265
|
+
// total 仍然是 SDK 返回的矩形区域总数,无法精确修正,保持原样或不返回
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
promise.resolve(convertedResult)
|
|
214
269
|
} else {
|
|
215
270
|
promise.reject("SEARCH_ERROR", "Search failed with code: $rCode", null)
|
|
216
271
|
}
|
|
217
272
|
}
|
|
218
273
|
|
|
219
|
-
override fun onPoiItemSearched(item:
|
|
274
|
+
override fun onPoiItemSearched(item: PoiItemV2?, rCode: Int) {}
|
|
220
275
|
})
|
|
221
276
|
|
|
222
277
|
poiSearch.searchPOIAsyn()
|
|
@@ -229,6 +284,7 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
229
284
|
* 输入提示
|
|
230
285
|
*/
|
|
231
286
|
AsyncFunction("getInputTips") { options: Map<String, Any?>, promise: Promise ->
|
|
287
|
+
ensureAPIKeyIsSet()
|
|
232
288
|
try {
|
|
233
289
|
val keyword = options["keyword"] as? String
|
|
234
290
|
?: throw Exception("keyword is required")
|
|
@@ -256,49 +312,242 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
256
312
|
promise.reject("TIPS_ERROR", e.message, e)
|
|
257
313
|
}
|
|
258
314
|
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* 逆地理编码(坐标转地址)
|
|
318
|
+
*/
|
|
319
|
+
AsyncFunction("reGeocode") { options: Map<String, Any?>, promise: Promise ->
|
|
320
|
+
ensureAPIKeyIsSet()
|
|
321
|
+
try {
|
|
322
|
+
@Suppress("UNCHECKED_CAST")
|
|
323
|
+
val location = options["location"] as? Map<String, Any?>
|
|
324
|
+
?: throw Exception("location is required")
|
|
325
|
+
|
|
326
|
+
val latitude = (location["latitude"] as? Number)?.toDouble()
|
|
327
|
+
?: throw Exception("location.latitude is required")
|
|
328
|
+
val longitude = (location["longitude"] as? Number)?.toDouble()
|
|
329
|
+
?: throw Exception("location.longitude is required")
|
|
330
|
+
|
|
331
|
+
val radius = (options["radius"] as? Number)?.toFloat() ?: 1000f
|
|
332
|
+
|
|
333
|
+
val geocodeSearch = GeocodeSearch(context)
|
|
334
|
+
geocodeSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener {
|
|
335
|
+
override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) {
|
|
336
|
+
if (rCode == 1000 && result != null) {
|
|
337
|
+
promise.resolve(convertRegeocodeResult(result))
|
|
338
|
+
} else {
|
|
339
|
+
promise.reject("SEARCH_ERROR", "ReGeocode failed with code: $rCode", null)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) {
|
|
344
|
+
// Not used
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
val point = LatLonPoint(latitude, longitude)
|
|
349
|
+
val query = RegeocodeQuery(point, radius, GeocodeSearch.AMAP)
|
|
350
|
+
query.extensions = "all"
|
|
351
|
+
|
|
352
|
+
geocodeSearch.getFromLocationAsyn(query)
|
|
353
|
+
} catch (e: Exception) {
|
|
354
|
+
promise.reject("SEARCH_ERROR", e.message, e)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* POI ID 搜索(详情查询)
|
|
360
|
+
*/
|
|
361
|
+
AsyncFunction("getPoiDetail") { id: String, promise: Promise ->
|
|
362
|
+
ensureAPIKeyIsSet()
|
|
363
|
+
try {
|
|
364
|
+
if (id.isEmpty()) {
|
|
365
|
+
throw Exception("id is required")
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
val poiSearch = PoiSearchV2(context, null)
|
|
369
|
+
poiSearch.setOnPoiSearchListener(object : PoiSearchV2.OnPoiSearchListener {
|
|
370
|
+
override fun onPoiSearched(result: PoiResultV2?, rCode: Int) {
|
|
371
|
+
// Not used
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
override fun onPoiItemSearched(item: PoiItemV2?, rCode: Int) {
|
|
375
|
+
if (rCode == 1000 && item != null) {
|
|
376
|
+
promise.resolve(convertPoiItem(item))
|
|
377
|
+
} else {
|
|
378
|
+
promise.reject("SEARCH_ERROR", "Get POI detail failed with code: $rCode", null)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
poiSearch.searchPOIIdAsyn(id)
|
|
384
|
+
} catch (e: Exception) {
|
|
385
|
+
promise.reject("SEARCH_ERROR", e.message, e)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
259
388
|
}
|
|
260
389
|
|
|
390
|
+
// MARK: - Private Methods
|
|
391
|
+
|
|
261
392
|
/**
|
|
262
|
-
*
|
|
393
|
+
* 判断点是否在多边形内 (Ray Casting 算法)
|
|
263
394
|
*/
|
|
264
|
-
private fun
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
395
|
+
private fun isPointInPolygon(point: LatLonPoint, vertices: List<LatLonPoint>): Boolean {
|
|
396
|
+
var inside = false
|
|
397
|
+
var j = vertices.size - 1
|
|
398
|
+
for (i in vertices.indices) {
|
|
399
|
+
if (((vertices[i].latitude > point.latitude) != (vertices[j].latitude > point.latitude)) &&
|
|
400
|
+
(point.longitude < (vertices[j].longitude - vertices[i].longitude) * (point.latitude - vertices[i].latitude) / (vertices[j].latitude - vertices[i].latitude) + vertices[i].longitude)
|
|
401
|
+
) {
|
|
402
|
+
inside = !inside
|
|
403
|
+
}
|
|
404
|
+
j = i
|
|
273
405
|
}
|
|
406
|
+
return inside
|
|
407
|
+
}
|
|
274
408
|
|
|
275
|
-
|
|
276
|
-
|
|
409
|
+
/**
|
|
410
|
+
* 确保 API Key 已设置
|
|
411
|
+
* 优先级:已设置 > AndroidManifest.xml
|
|
412
|
+
*/
|
|
413
|
+
private fun ensureAPIKeyIsSet() {
|
|
414
|
+
try {
|
|
415
|
+
|
|
416
|
+
// 1. 尝试从 AndroidManifest.xml 读取
|
|
417
|
+
// 尝试从 AndroidManifest.xml 读取并设置 API Key
|
|
418
|
+
val apiKey = context.packageManager
|
|
419
|
+
.getApplicationInfo(context.packageName, android.content.pm.PackageManager.GET_META_DATA)
|
|
420
|
+
.metaData?.getString("com.amap.api.v2.apikey")
|
|
421
|
+
|
|
422
|
+
if (apiKey.isNullOrEmpty()) {
|
|
423
|
+
throw Exception("API Key is not set")
|
|
424
|
+
}
|
|
425
|
+
} catch (_: Exception) {
|
|
426
|
+
// Ignore errors, let the SDK handle it or fail later
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* 转换单个 POI Item
|
|
432
|
+
*/
|
|
433
|
+
private fun convertPoiItem(poi: PoiItemV2, center: LatLonPoint? = null): Map<String, Any?> {
|
|
434
|
+
var distance = -1
|
|
435
|
+
if (center != null && poi.latLonPoint != null) {
|
|
436
|
+
val results = FloatArray(1)
|
|
437
|
+
android.location.Location.distanceBetween(
|
|
438
|
+
center.latitude, center.longitude,
|
|
439
|
+
poi.latLonPoint.latitude, poi.latLonPoint.longitude,
|
|
440
|
+
results
|
|
441
|
+
)
|
|
442
|
+
distance = results[0].toInt()
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// 获取深度信息
|
|
446
|
+
val business = poi.business
|
|
447
|
+
val indoor = poi.indoorData
|
|
448
|
+
val photos = poi.photos
|
|
449
|
+
|
|
450
|
+
return mapOf<String, Any?>(
|
|
277
451
|
"id" to poi.poiId,
|
|
278
452
|
"name" to poi.title,
|
|
279
453
|
"address" to poi.snippet,
|
|
280
|
-
"location" to mapOf(
|
|
454
|
+
"location" to mapOf<String, Any?>(
|
|
281
455
|
"latitude" to poi.latLonPoint?.latitude,
|
|
282
456
|
"longitude" to poi.latLonPoint?.longitude
|
|
283
457
|
),
|
|
284
458
|
"typeCode" to poi.typeCode,
|
|
285
459
|
"typeDes" to poi.typeDes,
|
|
286
|
-
"tel" to
|
|
287
|
-
"distance" to
|
|
460
|
+
"tel" to "", // V2 SDK 移除了 tel 字段,即使 ShowFields.ALL 也不包含
|
|
461
|
+
"distance" to distance,
|
|
288
462
|
"cityName" to poi.cityName,
|
|
289
463
|
"cityCode" to poi.cityCode,
|
|
290
464
|
"provinceName" to poi.provinceName,
|
|
291
465
|
"adName" to poi.adName,
|
|
292
|
-
"adCode" to poi.adCode
|
|
466
|
+
"adCode" to poi.adCode,
|
|
467
|
+
// 添加深度信息字段映射
|
|
468
|
+
"business" to if (business != null) mapOf<String, Any?>(
|
|
469
|
+
"opentime" to business.opentimeWeek,
|
|
470
|
+
"opentimeToday" to business.opentimeToday,
|
|
471
|
+
"rating" to business.getmRating(),
|
|
472
|
+
"cost" to business.cost,
|
|
473
|
+
"parkingType" to business.parkingType,
|
|
474
|
+
"tag" to business.tag,
|
|
475
|
+
"tel" to business.tel,
|
|
476
|
+
"alias" to business.alias,
|
|
477
|
+
"businessArea" to business.businessArea
|
|
478
|
+
) else null,
|
|
479
|
+
"photos" to photos?.map { photo ->
|
|
480
|
+
mapOf<String, Any?>(
|
|
481
|
+
"title" to photo.title,
|
|
482
|
+
"url" to photo.url
|
|
483
|
+
)
|
|
484
|
+
},
|
|
485
|
+
"indoor" to if (indoor != null) mapOf<String, Any?>(
|
|
486
|
+
"floor" to indoor.floor,
|
|
487
|
+
"floorName" to indoor.floorName,
|
|
488
|
+
"poiId" to indoor.poiId,
|
|
489
|
+
"hasIndoorMap" to indoor.isIndoorMap
|
|
490
|
+
) else null
|
|
293
491
|
)
|
|
294
|
-
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* 转换单个 Legacy POI Item (用于逆地理编码)
|
|
496
|
+
*/
|
|
497
|
+
private fun convertLegacyPoiItem(poi: PoiItem): Map<String, Any?> {
|
|
498
|
+
return mapOf<String, Any?>(
|
|
499
|
+
"id" to poi.poiId,
|
|
500
|
+
"name" to poi.title,
|
|
501
|
+
"address" to poi.snippet,
|
|
502
|
+
"location" to mapOf<String, Any?>(
|
|
503
|
+
"latitude" to poi.latLonPoint?.latitude,
|
|
504
|
+
"longitude" to poi.latLonPoint?.longitude
|
|
505
|
+
),
|
|
506
|
+
"typeCode" to poi.typeCode,
|
|
507
|
+
"typeDes" to poi.typeDes,
|
|
508
|
+
"tel" to poi.tel,
|
|
509
|
+
"distance" to poi.distance,
|
|
510
|
+
"cityName" to poi.cityName,
|
|
511
|
+
"cityCode" to poi.cityCode,
|
|
512
|
+
"provinceName" to poi.provinceName,
|
|
513
|
+
"adName" to poi.adName,
|
|
514
|
+
"adCode" to poi.adCode,
|
|
515
|
+
"website" to poi.website,
|
|
516
|
+
"email" to poi.email,
|
|
517
|
+
"postcode" to poi.postcode,
|
|
518
|
+
"direction" to poi.direction,
|
|
519
|
+
"hasIndoorMap" to poi.isIndoorMap,
|
|
520
|
+
"businessArea" to poi.businessArea,
|
|
521
|
+
"parkingType" to poi.parkingType
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* 转换 POI 搜索结果
|
|
527
|
+
*/
|
|
528
|
+
private fun convertPoiResult(result: PoiResultV2?, center: LatLonPoint? = null): Map<String, Any?> {
|
|
529
|
+
if (result == null) {
|
|
530
|
+
return mapOf(
|
|
531
|
+
"pois" to emptyList<Map<String, Any?>>(),
|
|
532
|
+
"total" to 0,
|
|
533
|
+
"pageNum" to 1,
|
|
534
|
+
"pageSize" to 20,
|
|
535
|
+
"pageCount" to 0
|
|
536
|
+
)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
val pois = result.pois?.map { convertPoiItem(it, center) } ?: emptyList()
|
|
540
|
+
|
|
541
|
+
val totalCount = result.count
|
|
542
|
+
val pageSize = result.query.pageSize
|
|
543
|
+
val pageCount = if (pageSize > 0) (totalCount + pageSize - 1) / pageSize else 0
|
|
295
544
|
|
|
296
545
|
return mapOf(
|
|
297
546
|
"pois" to pois,
|
|
298
|
-
"total" to
|
|
547
|
+
"total" to totalCount,
|
|
299
548
|
"pageNum" to (result.query.pageNum + 1),
|
|
300
|
-
"pageSize" to
|
|
301
|
-
"pageCount" to
|
|
549
|
+
"pageSize" to pageSize,
|
|
550
|
+
"pageCount" to pageCount
|
|
302
551
|
)
|
|
303
552
|
}
|
|
304
553
|
|
|
@@ -312,7 +561,7 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
312
561
|
"name" to tip.name,
|
|
313
562
|
"address" to tip.address,
|
|
314
563
|
"location" to tip.point?.let {
|
|
315
|
-
mapOf(
|
|
564
|
+
mapOf<String, Any?>(
|
|
316
565
|
"latitude" to it.latitude,
|
|
317
566
|
"longitude" to it.longitude
|
|
318
567
|
)
|
|
@@ -331,11 +580,11 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
331
580
|
*/
|
|
332
581
|
private fun convertRoutePOIResult(result: RoutePOISearchResult): Map<String, Any?> {
|
|
333
582
|
val pois = result.routePois?.map { poi ->
|
|
334
|
-
mapOf(
|
|
583
|
+
mapOf<String, Any?>(
|
|
335
584
|
"id" to poi.id,
|
|
336
585
|
"name" to poi.title,
|
|
337
|
-
"address" to "",
|
|
338
|
-
"location" to mapOf(
|
|
586
|
+
"address" to "", // RoutePOIItem 确实没有 address/snippet 字段
|
|
587
|
+
"location" to mapOf<String, Any?>(
|
|
339
588
|
"latitude" to poi.point?.latitude,
|
|
340
589
|
"longitude" to poi.point?.longitude
|
|
341
590
|
),
|
|
@@ -351,4 +600,99 @@ class ExpoGaodeMapSearchModule : Module() {
|
|
|
351
600
|
"pageCount" to 1
|
|
352
601
|
)
|
|
353
602
|
}
|
|
354
|
-
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* 转换逆地理编码结果
|
|
606
|
+
*/
|
|
607
|
+
private fun convertRegeocodeResult(result: RegeocodeResult): Map<String, Any?> {
|
|
608
|
+
val address = result.regeocodeAddress ?: return emptyMap<String, Any?>()
|
|
609
|
+
|
|
610
|
+
val addressComponent = mapOf<String, Any?>(
|
|
611
|
+
"province" to address.province,
|
|
612
|
+
"city" to address.city,
|
|
613
|
+
"district" to address.district,
|
|
614
|
+
"township" to address.township,
|
|
615
|
+
"towncode" to address.towncode,
|
|
616
|
+
"neighborhood" to address.neighborhood,
|
|
617
|
+
"building" to address.building,
|
|
618
|
+
"cityCode" to address.cityCode,
|
|
619
|
+
"adCode" to address.adCode,
|
|
620
|
+
"country" to address.country,
|
|
621
|
+
"countryCode" to address.countryCode,
|
|
622
|
+
"streetNumber" to (address.streetNumber?.let {
|
|
623
|
+
mapOf<String, Any?>(
|
|
624
|
+
"street" to it.street,
|
|
625
|
+
"number" to it.number,
|
|
626
|
+
"direction" to it.direction,
|
|
627
|
+
"distance" to it.distance
|
|
628
|
+
)
|
|
629
|
+
} ?: mapOf<String, Any?>(
|
|
630
|
+
"street" to "",
|
|
631
|
+
"number" to "",
|
|
632
|
+
"direction" to "",
|
|
633
|
+
"distance" to 0f
|
|
634
|
+
)),
|
|
635
|
+
"businessAreas" to (address.businessAreas?.map { area ->
|
|
636
|
+
mapOf<String, Any?>(
|
|
637
|
+
"name" to area.name,
|
|
638
|
+
"location" to mapOf<String, Any?>(
|
|
639
|
+
"latitude" to area.centerPoint?.latitude,
|
|
640
|
+
"longitude" to area.centerPoint?.longitude
|
|
641
|
+
)
|
|
642
|
+
)
|
|
643
|
+
} ?: emptyList())
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
val pois = address.pois?.map { convertLegacyPoiItem(it) } ?: emptyList()
|
|
647
|
+
|
|
648
|
+
val aois = address.aois?.map { aoi ->
|
|
649
|
+
mapOf<String, Any?>(
|
|
650
|
+
"id" to aoi.aoiId,
|
|
651
|
+
"name" to aoi.aoiName,
|
|
652
|
+
"adCode" to aoi.adCode,
|
|
653
|
+
"location" to mapOf<String, Any?>(
|
|
654
|
+
"latitude" to aoi.aoiCenterPoint?.latitude,
|
|
655
|
+
"longitude" to aoi.aoiCenterPoint?.longitude
|
|
656
|
+
),
|
|
657
|
+
"area" to aoi.aoiArea
|
|
658
|
+
)
|
|
659
|
+
} ?: emptyList()
|
|
660
|
+
|
|
661
|
+
val roads = address.roads?.map { road ->
|
|
662
|
+
mapOf<String, Any?>(
|
|
663
|
+
"id" to road.id,
|
|
664
|
+
"name" to road.name,
|
|
665
|
+
"distance" to road.distance,
|
|
666
|
+
"direction" to road.direction,
|
|
667
|
+
"location" to mapOf<String, Any?>(
|
|
668
|
+
"latitude" to road.latLngPoint?.latitude,
|
|
669
|
+
"longitude" to road.latLngPoint?.longitude
|
|
670
|
+
)
|
|
671
|
+
)
|
|
672
|
+
} ?: emptyList()
|
|
673
|
+
|
|
674
|
+
val roadCrosses = address.crossroads?.map { cross ->
|
|
675
|
+
mapOf<String, Any?>(
|
|
676
|
+
"distance" to cross.distance,
|
|
677
|
+
"direction" to cross.direction,
|
|
678
|
+
"location" to mapOf<String, Any?>(
|
|
679
|
+
"latitude" to cross.centerPoint?.latitude,
|
|
680
|
+
"longitude" to cross.centerPoint?.longitude
|
|
681
|
+
),
|
|
682
|
+
"firstId" to cross.firstRoadId,
|
|
683
|
+
"firstName" to cross.firstRoadName,
|
|
684
|
+
"secondId" to cross.secondRoadId,
|
|
685
|
+
"secondName" to cross.secondRoadName
|
|
686
|
+
)
|
|
687
|
+
} ?: emptyList()
|
|
688
|
+
|
|
689
|
+
return mapOf(
|
|
690
|
+
"formattedAddress" to address.formatAddress,
|
|
691
|
+
"addressComponent" to addressComponent,
|
|
692
|
+
"pois" to pois,
|
|
693
|
+
"aois" to aois,
|
|
694
|
+
"roads" to roads,
|
|
695
|
+
"roadCrosses" to roadCrosses
|
|
696
|
+
)
|
|
697
|
+
}
|
|
698
|
+
}
|