expo-gaode-map-search 1.2.0-beta.0 → 1.3.0

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.
Files changed (53) hide show
  1. package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
  2. package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
  3. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  4. package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
  5. package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-expo-gaode-map-search.jar +0 -0
  6. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  7. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  8. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  9. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  10. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  11. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  12. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  13. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  14. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  15. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  16. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  17. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  18. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  19. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  20. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  21. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  22. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  23. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  24. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  25. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  26. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  27. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  28. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  29. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  41. package/android/build/outputs/aar/expo-gaode-map-search-debug.aar +0 -0
  42. package/android/build/outputs/logs/manifest-merger-debug-report.txt +9 -9
  43. package/android/build.gradle +4 -3
  44. package/android/src/main/java/expo/modules/gaodemap/search/ExpoGaodeMapSearchModule.kt +354 -0
  45. package/build/ExpoGaodeMapSearchModule.js +33 -0
  46. package/ios/ExpoGaodeMapSearchModule.swift +415 -0
  47. package/package.json +16 -9
  48. package/src/ExpoGaodeMapSearch.types.ts +179 -0
  49. package/src/ExpoGaodeMapSearchModule.ts +46 -0
  50. package/src/index.ts +170 -0
  51. package/.eslintrc.js +0 -2
  52. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  53. package/package.json.backup +0 -54
@@ -0,0 +1,415 @@
1
+ import ExpoModulesCore
2
+ import AMapSearchKit
3
+ import AMapFoundationKit
4
+
5
+ public class ExpoGaodeMapSearchModule: Module {
6
+ private var searchAPI: AMapSearchAPI!
7
+ private var searchDelegate: SearchDelegate!
8
+
9
+ public func definition() -> ModuleDefinition {
10
+ Name("ExpoGaodeMapSearch")
11
+
12
+ // 不在 OnCreate 中初始化,改为延迟初始化
13
+
14
+ /**
15
+ * 手动初始化搜索模块(可选)
16
+ * 如果 API Key 已经设置,则直接初始化
17
+ * 如果未设置,会尝试从 Info.plist 读取
18
+ */
19
+ Function("initSearch") {
20
+ self.initSearchAPI()
21
+ }
22
+
23
+ /**
24
+ * POI 搜索
25
+ */
26
+ AsyncFunction("searchPOI") { (options: [String: Any], promise: Promise) in
27
+ // 延迟初始化:在首次使用时才初始化
28
+ self.initSearchAPI()
29
+
30
+ guard let keyword = options["keyword"] as? String else {
31
+ promise.reject("SEARCH_ERROR", "keyword is required")
32
+ return
33
+ }
34
+
35
+ let city = options["city"] as? String ?? ""
36
+ let types = options["types"] as? String ?? ""
37
+ let pageSize = options["pageSize"] as? Int ?? 20
38
+ let pageNum = options["pageNum"] as? Int ?? 1
39
+
40
+ let request = AMapPOIKeywordsSearchRequest()
41
+ request.keywords = keyword
42
+ request.city = city
43
+ request.types = types
44
+ request.page = pageNum
45
+ request.offset = pageSize
46
+
47
+ self.searchDelegate.currentPromise = promise
48
+ self.searchAPI.aMapPOIKeywordsSearch(request)
49
+ }
50
+
51
+ /**
52
+ * 周边搜索
53
+ */
54
+ AsyncFunction("searchNearby") { (options: [String: Any], promise: Promise) in
55
+ self.initSearchAPI()
56
+
57
+ guard let keyword = options["keyword"] as? String else {
58
+ promise.reject("SEARCH_ERROR", "keyword is required")
59
+ return
60
+ }
61
+
62
+ guard let center = options["center"] as? [String: Any],
63
+ let latitude = center["latitude"] as? Double,
64
+ let longitude = center["longitude"] as? Double else {
65
+ promise.reject("SEARCH_ERROR", "center is required")
66
+ return
67
+ }
68
+
69
+ let radius = options["radius"] as? Int ?? 1000
70
+ let types = options["types"] as? String ?? ""
71
+ let pageSize = options["pageSize"] as? Int ?? 20
72
+ let pageNum = options["pageNum"] as? Int ?? 1
73
+
74
+ let request = AMapPOIAroundSearchRequest()
75
+ request.keywords = keyword
76
+ request.location = AMapGeoPoint.location(
77
+ withLatitude: CGFloat(latitude),
78
+ longitude: CGFloat(longitude)
79
+ )
80
+ request.radius = radius
81
+ request.types = types
82
+ request.page = pageNum
83
+ request.offset = pageSize
84
+
85
+ self.searchDelegate.currentPromise = promise
86
+ self.searchAPI.aMapPOIAroundSearch(request)
87
+ }
88
+
89
+ /**
90
+ * 沿途搜索
91
+ * iOS SDK 支持的沿途搜索类型:加油站、ATM、汽修、厕所
92
+ */
93
+ AsyncFunction("searchAlong") { (options: [String: Any], promise: Promise) in
94
+ self.initSearchAPI()
95
+
96
+ guard let keyword = options["keyword"] as? String else {
97
+ promise.reject("SEARCH_ERROR", "keyword is required")
98
+ return
99
+ }
100
+
101
+ guard let polyline = options["polyline"] as? [[String: Any]] else {
102
+ promise.reject("SEARCH_ERROR", "polyline is required")
103
+ return
104
+ }
105
+
106
+ guard polyline.count >= 2 else {
107
+ promise.reject("SEARCH_ERROR", "polyline must have at least 2 points")
108
+ return
109
+ }
110
+
111
+ // 转换路线点
112
+ var points: [AMapGeoPoint] = []
113
+ for point in polyline {
114
+ if let lat = point["latitude"] as? Double,
115
+ let lng = point["longitude"] as? Double {
116
+ points.append(AMapGeoPoint.location(
117
+ withLatitude: CGFloat(lat),
118
+ longitude: CGFloat(lng)
119
+ ))
120
+ }
121
+ }
122
+
123
+ guard let startPoint = points.first,
124
+ let endPoint = points.last else {
125
+ promise.reject("SEARCH_ERROR", "Invalid polyline points")
126
+ return
127
+ }
128
+
129
+ // 根据关键词确定搜索类型
130
+ let lowercaseKeyword = keyword.lowercased()
131
+ var searchType: AMapRoutePOISearchType = .gasStation
132
+ if lowercaseKeyword.contains("加油") || lowercaseKeyword == "加油站" {
133
+ searchType = .gasStation
134
+ } else if lowercaseKeyword.contains("atm") || lowercaseKeyword.contains("银行") {
135
+ searchType = .ATM
136
+ } else if lowercaseKeyword.contains("汽修") || lowercaseKeyword.contains("维修") {
137
+ searchType = .maintenanceStation
138
+ } else if lowercaseKeyword.contains("厕所") || lowercaseKeyword.contains("卫生间") {
139
+ searchType = .toilet
140
+ }
141
+
142
+ let request = AMapRoutePOISearchRequest()
143
+ request.origin = startPoint
144
+ request.destination = endPoint
145
+ request.searchType = searchType
146
+ request.range = 250
147
+ request.strategy = 0
148
+
149
+ self.searchDelegate.currentPromise = promise
150
+ self.searchAPI.aMapRoutePOISearch(request)
151
+ }
152
+
153
+ /**
154
+ * 多边形搜索
155
+ */
156
+ AsyncFunction("searchPolygon") { (options: [String: Any], promise: Promise) in
157
+ self.initSearchAPI()
158
+
159
+ guard let keyword = options["keyword"] as? String else {
160
+ promise.reject("SEARCH_ERROR", "keyword is required")
161
+ return
162
+ }
163
+
164
+ guard let polygon = options["polygon"] as? [[String: Any]] else {
165
+ promise.reject("SEARCH_ERROR", "polygon is required")
166
+ return
167
+ }
168
+
169
+ let types = options["types"] as? String ?? ""
170
+ let pageSize = options["pageSize"] as? Int ?? 20
171
+ let pageNum = options["pageNum"] as? Int ?? 1
172
+
173
+ var points: [AMapGeoPoint] = []
174
+ for point in polygon {
175
+ if let lat = point["latitude"] as? Double,
176
+ let lng = point["longitude"] as? Double {
177
+ points.append(AMapGeoPoint.location(
178
+ withLatitude: CGFloat(lat),
179
+ longitude: CGFloat(lng)
180
+ ))
181
+ }
182
+ }
183
+
184
+ let request = AMapPOIPolygonSearchRequest()
185
+ request.keywords = keyword
186
+ request.polygon = AMapGeoPolygon(points: points)
187
+ request.types = types
188
+ request.page = pageNum
189
+ request.offset = pageSize
190
+
191
+ self.searchDelegate.currentPromise = promise
192
+ self.searchAPI.aMapPOIPolygonSearch(request)
193
+ }
194
+
195
+ /**
196
+ * 输入提示
197
+ */
198
+ AsyncFunction("getInputTips") { (options: [String: Any], promise: Promise) in
199
+ self.initSearchAPI()
200
+
201
+ guard let keyword = options["keyword"] as? String else {
202
+ promise.reject("TIPS_ERROR", "keyword is required")
203
+ return
204
+ }
205
+
206
+ let city = options["city"] as? String ?? ""
207
+ let types = options["types"] as? String ?? ""
208
+
209
+ let request = AMapInputTipsSearchRequest()
210
+ request.keywords = keyword
211
+ request.city = city
212
+ request.types = types
213
+
214
+ self.searchDelegate.currentPromise = promise
215
+ self.searchAPI.aMapInputTipsSearch(request)
216
+ }
217
+ }
218
+
219
+ // MARK: - Private Methods
220
+
221
+ /**
222
+ * 初始化搜索 API(延迟初始化)
223
+ */
224
+ private func initSearchAPI() {
225
+ if searchAPI == nil {
226
+ // 确保 API Key 已设置
227
+ self.ensureAPIKeyIsSet()
228
+
229
+ searchDelegate = SearchDelegate()
230
+ searchAPI = AMapSearchAPI()
231
+ searchAPI.delegate = searchDelegate
232
+
233
+ let apiKey = AMapServices.shared().apiKey
234
+ print("[ExpoGaodeMapSearch] 搜索 API 已初始化,API Key: \(apiKey ?? "未设置")")
235
+ }
236
+ }
237
+
238
+ /**
239
+ * 确保 API Key 已设置
240
+ * 优先级:已设置 > Info.plist > 提示错误
241
+ */
242
+ private func ensureAPIKeyIsSet() {
243
+ // 1. 检查是否已经设置(通过 initSDK 或 AppDelegate)
244
+ if let existingKey = AMapServices.shared().apiKey, !existingKey.isEmpty {
245
+ print("[ExpoGaodeMapSearch] ✓ API Key 已设置")
246
+ return
247
+ }
248
+
249
+ // 2. 尝试从 Info.plist 读取(Config Plugin 会写入)
250
+ if let apiKey = Bundle.main.object(forInfoDictionaryKey: "AMapApiKey") as? String, !apiKey.isEmpty {
251
+ AMapServices.shared().apiKey = apiKey
252
+ AMapServices.shared().enableHTTPS = true
253
+ print("[ExpoGaodeMapSearch] ✓ 从 Info.plist 读取并设置 API Key")
254
+ return
255
+ }
256
+
257
+ // 3. 都没有,提示错误
258
+ print("[ExpoGaodeMapSearch] ✗ 错误: API Key 未设置!")
259
+ print("[ExpoGaodeMapSearch] 请通过以下任一方式设置:")
260
+ print("[ExpoGaodeMapSearch] 1. 在 app.json 的 plugins 中配置 iosApiKey(推荐)")
261
+ print("[ExpoGaodeMapSearch] 2. 调用 ExpoGaodeMap.initSDK({ iosKey: 'your-key' })")
262
+ print("[ExpoGaodeMapSearch] 3. 在 AppDelegate 中调用 [AMapServices sharedServices].apiKey = @\"your-key\"")
263
+ }
264
+ }
265
+
266
+ // MARK: - Search Delegate
267
+ class SearchDelegate: NSObject, AMapSearchDelegate {
268
+ var currentPromise: Promise?
269
+
270
+ /**
271
+ * POI 搜索回调
272
+ */
273
+ func onPOISearchDone(_ request: AMapPOISearchBaseRequest!, response: AMapPOISearchResponse!) {
274
+ guard let promise = currentPromise else { return }
275
+
276
+ if let response = response {
277
+ promise.resolve(convertPOISearchResponse(response))
278
+ } else {
279
+ promise.reject("SEARCH_ERROR", "Search failed")
280
+ }
281
+
282
+ currentPromise = nil
283
+ }
284
+
285
+ /**
286
+ * 沿途搜索回调
287
+ */
288
+ func onRoutePOISearchDone(_ request: AMapRoutePOISearchRequest!, response: AMapRoutePOISearchResponse!) {
289
+ guard let promise = currentPromise else { return }
290
+
291
+ if let response = response {
292
+ promise.resolve(convertRoutePOISearchResponse(response))
293
+ } else {
294
+ promise.reject("SEARCH_ERROR", "Route search failed")
295
+ }
296
+
297
+ currentPromise = nil
298
+ }
299
+
300
+ /**
301
+ * 输入提示回调
302
+ */
303
+ func onInputTipsSearchDone(_ request: AMapInputTipsSearchRequest!, response: AMapInputTipsSearchResponse!) {
304
+ guard let promise = currentPromise else { return }
305
+
306
+ if let response = response {
307
+ promise.resolve(convertInputTipsResponse(response))
308
+ } else {
309
+ promise.reject("TIPS_ERROR", "Input tips failed")
310
+ }
311
+
312
+ currentPromise = nil
313
+ }
314
+
315
+ /**
316
+ * 搜索失败回调
317
+ */
318
+ func aMapSearchRequest(_ request: Any!, didFailWithError error: Error!) {
319
+ guard let promise = currentPromise else { return }
320
+
321
+ let errorMessage = error?.localizedDescription ?? "Unknown error"
322
+ promise.reject("SEARCH_ERROR", errorMessage)
323
+ currentPromise = nil
324
+ }
325
+
326
+ // MARK: - 转换方法
327
+
328
+ /**
329
+ * 转换 POI 搜索结果
330
+ */
331
+ private func convertPOISearchResponse(_ response: AMapPOISearchResponse) -> [String: Any] {
332
+ let pois = response.pois?.map { poi -> [String: Any] in
333
+ var result: [String: Any] = [
334
+ "id": poi.uid ?? "",
335
+ "name": poi.name ?? "",
336
+ "address": poi.address ?? "",
337
+ "location": [
338
+ "latitude": poi.location?.latitude ?? 0,
339
+ "longitude": poi.location?.longitude ?? 0
340
+ ],
341
+ "typeCode": poi.typecode ?? "",
342
+ "typeDes": poi.type ?? "",
343
+ "tel": poi.tel ?? "",
344
+ "distance": poi.distance,
345
+ "cityName": poi.city ?? "",
346
+ "provinceName": poi.province ?? "",
347
+ "adName": poi.district ?? "",
348
+ "adCode": poi.adcode ?? ""
349
+ ]
350
+ return result
351
+ } ?? []
352
+
353
+ return [
354
+ "pois": pois,
355
+ "total": response.count,
356
+ "pageNum": response.pois?.first?.uid != nil ? 1 : 0,
357
+ "pageSize": response.pois?.count ?? 0,
358
+ "pageCount": (response.count + 19) / 20
359
+ ]
360
+ }
361
+
362
+ /**
363
+ * 转换输入提示结果
364
+ */
365
+ private func convertInputTipsResponse(_ response: AMapInputTipsSearchResponse) -> [String: Any] {
366
+ let tips = response.tips?.map { tip -> [String: Any] in
367
+ var result: [String: Any] = [
368
+ "id": tip.uid ?? "",
369
+ "name": tip.name ?? "",
370
+ "address": tip.address ?? "",
371
+ "typeCode": tip.typecode ?? "",
372
+ "cityName": tip.district ?? "",
373
+ "adName": tip.district ?? ""
374
+ ]
375
+
376
+ if let location = tip.location {
377
+ result["location"] = [
378
+ "latitude": location.latitude,
379
+ "longitude": location.longitude
380
+ ]
381
+ }
382
+
383
+ return result
384
+ } ?? []
385
+
386
+ return ["tips": tips]
387
+ }
388
+
389
+ /**
390
+ * 转换沿途 POI 搜索结果
391
+ */
392
+ private func convertRoutePOISearchResponse(_ response: AMapRoutePOISearchResponse) -> [String: Any] {
393
+ let pois = response.pois?.map { poi -> [String: Any] in
394
+ var result: [String: Any] = [
395
+ "id": poi.uid ?? "",
396
+ "name": poi.name ?? "",
397
+ "address": "",
398
+ "location": [
399
+ "latitude": poi.location?.latitude ?? 0,
400
+ "longitude": poi.location?.longitude ?? 0
401
+ ],
402
+ "distance": poi.distance
403
+ ]
404
+ return result
405
+ } ?? []
406
+
407
+ return [
408
+ "pois": pois,
409
+ "total": pois.count,
410
+ "pageNum": 1,
411
+ "pageSize": pois.count,
412
+ "pageCount": 1
413
+ ]
414
+ }
415
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-gaode-map-search",
3
- "version": "1.2.0-beta.0",
3
+ "version": "1.3.0",
4
4
  "description": "高德地图搜索功能模块 - POI搜索、关键词搜索、周边搜索,需先安装expo-gaode-map",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -21,8 +21,17 @@
21
21
  "author": "尚博信_王强 <wangqiang03@sunboxsoft.com> (https://github.com/TomWq)",
22
22
  "license": "MIT",
23
23
  "homepage": "https://github.com/TomWq/expo-gaode-map#readme",
24
- "dependencies": {
25
- "expo-gaode-map": "^2.2.0-beta.0"
24
+ "files": [
25
+ "build/**/*",
26
+ "src/**/*",
27
+ "android/**/*",
28
+ "ios/**/*",
29
+ "expo-module.config.json",
30
+ "README.md",
31
+ "package.json"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
26
35
  },
27
36
  "devDependencies": {
28
37
  "@types/react": "~19.1.0",
@@ -33,20 +42,18 @@
33
42
  },
34
43
  "peerDependencies": {
35
44
  "expo": "*",
36
- "expo-gaode-map": ">=2.0.0",
37
45
  "react": "*",
38
46
  "react-native": "*"
39
47
  },
40
- "peerDependenciesMeta": {
41
- "expo-gaode-map": {
42
- "optional": false
43
- }
48
+ "dependencies": {
49
+ "expo-gaode-map": "^2.2.0"
44
50
  },
45
51
  "scripts": {
46
52
  "build": "expo-module build",
47
53
  "clean": "expo-module clean",
48
54
  "lint": "expo-module lint",
49
55
  "test": "expo-module test",
50
- "expo-module": "expo-module"
56
+ "expo-module": "expo-module",
57
+ "postinstall": "node -e \"try{require.resolve('expo-gaode-map');process.exit(0)}catch(e1){try{require.resolve('expo-gaode-map-navigation');process.exit(0)}catch(e2){console.error('[expo-gaode-map-search] 需要安装基础地图组件:expo-gaode-map 或 expo-gaode-map-navigation 中的任意一个。\\n请执行:pnpm add expo-gaode-map 或 pnpm add expo-gaode-map-navigation');process.exit(1)}}\""
51
58
  }
52
59
  }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * 搜索类型
3
+ */
4
+ export enum SearchType {
5
+ /** POI 搜索 */
6
+ POI = 'poi',
7
+ /** 周边搜索 */
8
+ NEARBY = 'nearby',
9
+ /** 沿途搜索 */
10
+ ALONG = 'along',
11
+ /** 多边形搜索 */
12
+ POLYGON = 'polygon',
13
+ /** 输入提示 */
14
+ INPUT_TIPS = 'inputTips',
15
+ }
16
+
17
+ /**
18
+ * 坐标点
19
+ */
20
+ export interface Coordinates {
21
+ latitude: number;
22
+ longitude: number;
23
+ }
24
+
25
+ /**
26
+ * POI 信息
27
+ */
28
+ export interface POI {
29
+ /** POI ID */
30
+ id: string;
31
+ /** 名称 */
32
+ name: string;
33
+ /** 地址 */
34
+ address: string;
35
+ /** 坐标 */
36
+ location: Coordinates;
37
+ /** 类型编码 */
38
+ typeCode: string;
39
+ /** 类型描述 */
40
+ typeDes: string;
41
+ /** 电话 */
42
+ tel?: string;
43
+ /** 距离(米),仅周边搜索返回 */
44
+ distance?: number;
45
+ /** 城市名称 */
46
+ cityName?: string;
47
+ /** 城市编码 */
48
+ cityCode?: string;
49
+ /** 省份名称 */
50
+ provinceName?: string;
51
+ /** 区域名称 */
52
+ adName?: string;
53
+ /** 区域编码 */
54
+ adCode?: string;
55
+ }
56
+
57
+ /**
58
+ * POI 搜索选项
59
+ */
60
+ export interface POISearchOptions {
61
+ /** 搜索关键词 */
62
+ keyword: string;
63
+ /** 城市名称或城市编码(可选) */
64
+ city?: string;
65
+ /** POI 类型(可选),多个类型用 | 分隔 */
66
+ types?: string;
67
+ /** 每页记录数,默认 20,最大 50 */
68
+ pageSize?: number;
69
+ /** 当前页码,从 1 开始,默认 1 */
70
+ pageNum?: number;
71
+ /** 是否按照距离排序,需要设置中心点 */
72
+ sortByDistance?: boolean;
73
+ /** 中心点坐标,用于距离排序或周边搜索 */
74
+ center?: Coordinates;
75
+ }
76
+
77
+ /**
78
+ * 周边搜索选项
79
+ */
80
+ export interface NearbySearchOptions {
81
+ /** 搜索关键词 */
82
+ keyword: string;
83
+ /** 中心点坐标 */
84
+ center: Coordinates;
85
+ /** 搜索半径,单位:米,默认 1000,最大 50000 */
86
+ radius?: number;
87
+ /** POI 类型(可选),多个类型用 | 分隔 */
88
+ types?: string;
89
+ /** 每页记录数,默认 20,最大 50 */
90
+ pageSize?: number;
91
+ /** 当前页码,从 1 开始,默认 1 */
92
+ pageNum?: number;
93
+ }
94
+
95
+ /**
96
+ * 沿途搜索选项
97
+ */
98
+ export interface AlongSearchOptions {
99
+ /** 搜索关键词 */
100
+ keyword: string;
101
+ /** 路线坐标点数组 */
102
+ polyline: Coordinates[];
103
+ /** 搜索范围,单位:米,默认 500,最大 1000 */
104
+ range?: number;
105
+ /** POI 类型(可选),多个类型用 | 分隔 */
106
+ types?: string;
107
+ }
108
+
109
+ /**
110
+ * 多边形搜索选项
111
+ */
112
+ export interface PolygonSearchOptions {
113
+ /** 搜索关键词 */
114
+ keyword: string;
115
+ /** 多边形顶点坐标数组 */
116
+ polygon: Coordinates[];
117
+ /** POI 类型(可选),多个类型用 | 分隔 */
118
+ types?: string;
119
+ /** 每页记录数,默认 20,最大 50 */
120
+ pageSize?: number;
121
+ /** 当前页码,从 1 开始,默认 1 */
122
+ pageNum?: number;
123
+ }
124
+
125
+ /**
126
+ * 输入提示选项
127
+ */
128
+ export interface InputTipsOptions {
129
+ /** 关键词 */
130
+ keyword: string;
131
+ /** 城市名称或城市编码(可选) */
132
+ city?: string;
133
+ /** POI 类型(可选),多个类型用 | 分隔 */
134
+ types?: string;
135
+ }
136
+
137
+ /**
138
+ * 输入提示结果
139
+ */
140
+ export interface InputTip {
141
+ /** 提示 ID */
142
+ id: string;
143
+ /** 名称 */
144
+ name: string;
145
+ /** 地址 */
146
+ address: string;
147
+ /** 坐标(可能为空) */
148
+ location?: Coordinates;
149
+ /** 类型编码 */
150
+ typeCode?: string;
151
+ /** 城市名称 */
152
+ cityName?: string;
153
+ /** 区域名称 */
154
+ adName?: string;
155
+ }
156
+
157
+ /**
158
+ * 搜索结果
159
+ */
160
+ export interface SearchResult {
161
+ /** POI 列表 */
162
+ pois: POI[];
163
+ /** 总记录数 */
164
+ total: number;
165
+ /** 当前页码 */
166
+ pageNum: number;
167
+ /** 每页记录数 */
168
+ pageSize: number;
169
+ /** 总页数 */
170
+ pageCount: number;
171
+ }
172
+
173
+ /**
174
+ * 输入提示结果
175
+ */
176
+ export interface InputTipsResult {
177
+ /** 提示列表 */
178
+ tips: InputTip[];
179
+ }
@@ -0,0 +1,46 @@
1
+
2
+ import { requireNativeModule } from 'expo-modules-core';
3
+
4
+ /**
5
+ * 在加载原生搜索模块前,强制校验基础地图组件是否已安装。
6
+ * 支持两种“基础地图提供者”:expo-gaode-map 或 expo-gaode-map-navigation(导航内置地图)。
7
+ * 这样可避免导航与核心包的 SDK 冲突时无法使用搜索模块的问题。
8
+ */
9
+ function ensureBaseInstalled() {
10
+ let installed = false;
11
+ try {
12
+ // 优先检测核心地图包
13
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
14
+ require('expo-gaode-map');
15
+ installed = true;
16
+ } catch (_) {
17
+ // 再尝试导航包(内置地图能力)
18
+ try {
19
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
20
+ require('expo-gaode-map-navigation');
21
+ installed = true;
22
+ } catch (_) {
23
+ installed = false;
24
+ }
25
+ }
26
+
27
+ if (!installed) {
28
+ const msg =
29
+ '[expo-gaode-map-search] 需要先安装基础地图组件,支持以下任一包:\n' +
30
+ ' - expo-gaode-map(核心地图包),或\n' +
31
+ ' - expo-gaode-map-navigation(导航包,内置地图能力)\n' +
32
+ '请先安装并完成原生配置后再重试。';
33
+ throw new Error(msg);
34
+ }
35
+ }
36
+
37
+ ensureBaseInstalled();
38
+
39
+ /**
40
+ * 高德地图搜索模块
41
+ *
42
+ * 提供 POI 搜索、周边搜索、沿途搜索、多边形搜索和输入提示功能
43
+ */
44
+ const ExpoGaodeMapSearchModule = requireNativeModule('ExpoGaodeMapSearch');
45
+
46
+ export default ExpoGaodeMapSearchModule;