@cqsjjb/jjb-react-admin-component 3.3.0-beta.3 → 3.3.0-beta.4

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 (2) hide show
  1. package/AMap/index.js +238 -113
  2. package/package.json +1 -1
package/AMap/index.js CHANGED
@@ -1,22 +1,21 @@
1
1
  import React, { useEffect, useRef, useState, useCallback } from 'react';
2
2
  import { Button, Col, message, Modal, Result, Row } from 'antd';
3
- import './index.less';
4
3
  const _A_MAP_SEARCH_ = '_A_MAP_SEARCH_';
5
4
  const _A_MAP_DEFAULT_POINT_ = {
6
5
  lng: 116.397437,
7
6
  lat: 39.909148
8
7
  };
9
- const AMap = ({
8
+ export default function AMap({
10
9
  lng: propLng,
11
10
  lat: propLat,
12
11
  title = '高德地图',
13
12
  width = 700,
14
13
  onOk,
15
14
  onCancel
16
- }) => {
15
+ }) {
17
16
  const [lng, setLng] = useState(_A_MAP_DEFAULT_POINT_.lng);
18
17
  const [lat, setLat] = useState(_A_MAP_DEFAULT_POINT_.lat);
19
- const GL = useRef(null); // 地图容器,沿用你原来的名字
18
+ const GL = useRef(null);
20
19
  const mapRef = useRef(null);
21
20
  const markerRef = useRef(null);
22
21
  const autoRef = useRef(null);
@@ -26,78 +25,136 @@ const AMap = ({
26
25
  message.error('未导入高德地图文件,生成地图失败!').then(() => null);
27
26
  return;
28
27
  }
29
- const initLng = propLng || _A_MAP_DEFAULT_POINT_.lng;
30
- const initLat = propLat || _A_MAP_DEFAULT_POINT_.lat;
31
- setLng(initLng);
32
- setLat(initLat);
28
+ let mounted = true;
33
29
 
34
- // 创建地图
35
- const map = new window.AMap.Map(GL.current, {
36
- center: [initLng, initLat],
37
- zoom: 18,
38
- viewMode: '3D'
39
- });
40
- mapRef.current = map;
30
+ // 保证传入的初始值是 number(避免 NaN)
31
+ const initLng = Number(propLng) || _A_MAP_DEFAULT_POINT_.lng;
32
+ const initLat = Number(propLat) || _A_MAP_DEFAULT_POINT_.lat;
41
33
 
42
- // 通过 plugin 先加载需要的插件(保证控件类存在)
43
- window.AMap.plugin(['AMap.Scale', 'AMap.ToolBar', 'AMap.Geolocation', 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder'], () => {
44
- // 比例尺
45
- try {
46
- const scale = new window.AMap.Scale();
47
- map.addControl(scale);
48
- } catch (e) {
49
- // 某些按需构建或旧环境可能报错,容错处理
50
- // console.warn('AMap.Scale plugin not available', e);
34
+ // 等待容器可见且尺寸非 0(Modal 动画或隐藏态时常为 0)
35
+ const waitForVisible = (el, timeout = 3000) => new Promise(resolve => {
36
+ const start = Date.now();
37
+ function check() {
38
+ if (!el) return resolve(false);
39
+ const r = el.getBoundingClientRect();
40
+ if (r.width > 0 && r.height > 0) return resolve(true);
41
+ if (Date.now() - start > timeout) return resolve(false);
42
+ requestAnimationFrame(check);
43
+ }
44
+ check();
45
+ });
46
+ async function init() {
47
+ if (!GL.current) {
48
+ console.warn('AMap container ref not ready');
49
+ return;
50
+ }
51
+ const visible = await waitForVisible(GL.current, 3000);
52
+ if (!visible) {
53
+ // 继续也可,但记录一下。多数情况下等待后再 init 能解决 Pixel(NaN, 0)
54
+ console.warn('AMap container still not visible before init (proceeding anyway).');
51
55
  }
52
-
53
- // 工具条(放大缩小)
54
- try {
55
- map.addControl(new window.AMap.ToolBar({
56
- position: 'RT'
57
- }));
58
- } catch (e) {}
59
-
60
- // 定位控件
61
56
  try {
62
- const geolocation = new window.AMap.Geolocation({
63
- position: 'BT',
64
- offset: new window.AMap.Pixel(20, 20),
65
- showCircle: false,
66
- showButton: true
57
+ const map = new window.AMap.Map(GL.current, {
58
+ center: [initLng, initLat],
59
+ zoom: 18,
60
+ viewMode: '3D'
67
61
  });
68
- map.addControl(geolocation);
69
- geolocation.getCurrentPosition(status => {
70
- if (status !== 'complete') {
71
- message.error('未知原因,定位失败!');
62
+ mapRef.current = map;
63
+
64
+ // 保证 state 与实际中心一致
65
+ setLng(initLng);
66
+ setLat(initLat);
67
+
68
+ // 插件加载、控件创建都做容错
69
+ window.AMap.plugin(['AMap.Scale', 'AMap.ToolBar', 'AMap.Geolocation', 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder'], () => {
70
+ try {
71
+ map.addControl(new window.AMap.Scale());
72
+ } catch (e) {
73
+ // 某些构建/版本中可能不存在
74
+ console.warn('Scale control failed', e);
72
75
  }
73
- });
74
- } catch (e) {}
76
+ try {
77
+ map.addControl(new window.AMap.ToolBar({
78
+ position: 'RT'
79
+ }));
80
+ } catch (e) {
81
+ console.warn('ToolBar control failed', e);
82
+ }
83
+ try {
84
+ // 使用合法角落(RB/RT/LB/LT),不要自定义 'BT'
85
+ const geolocation = new window.AMap.Geolocation({
86
+ position: 'RB',
87
+ offset: new window.AMap.Pixel(Number(20), Number(20)),
88
+ showCircle: false,
89
+ showButton: true
90
+ });
91
+ map.addControl(geolocation);
75
92
 
76
- // 初始 marker
77
- markerRef.current = new window.AMap.Marker({
78
- position: [initLng, initLat],
79
- map
80
- });
93
+ // 正确的回调签名 (status, result)
94
+ geolocation.getCurrentPosition((status, result) => {
95
+ if (status !== 'complete') {
96
+ // 不做致命处理,但提示
97
+ message.error('未知原因,定位失败!');
98
+ } else {
99
+ // 如果需要可以从 result.position 取值
100
+ try {
101
+ const pos = result && result.position;
102
+ if (pos) {
103
+ const px = typeof pos.getLng === 'function' ? pos.getLng() : pos.lng;
104
+ const py = typeof pos.getLat === 'function' ? pos.getLat() : pos.lat;
105
+ if (!Number.isNaN(Number(px)) && !Number.isNaN(Number(py))) {
106
+ setLng(Number(px));
107
+ setLat(Number(py));
108
+ map.setCenter([Number(px), Number(py)]);
109
+ }
110
+ }
111
+ } catch (e) {
112
+ // 忽略
113
+ }
114
+ }
115
+ });
116
+ } catch (e) {
117
+ console.warn('Geolocation init failed', e);
118
+ }
81
119
 
82
- // 自动完成 + 地点搜索
83
- try {
84
- placeSearchRef.current = new window.AMap.PlaceSearch({
85
- map
86
- });
87
- autoRef.current = new window.AMap.AutoComplete({
88
- input: document.getElementById(_A_MAP_SEARCH_)
89
- });
90
- autoRef.current.on && autoRef.current.on('select', e => {
91
- // e.poi 里通常包含 name / location / adcode 等信息
92
- const name = e?.poi && (e.poi.name || e.poi.address) || e?.info || e?.name;
93
- // if (!name) return;
94
- placeSearchRef.current.search(name, (status, result) => {
95
- if (status === 'complete' && result && result.poiList && result.poiList.pois && result.poiList.pois.length > 0) {
96
- const poi = result.poiList.pois[0];
97
- const loc = poi.location || poi.lnglat;
98
- const foundLng = loc && (loc.lng || Array.isArray(loc) && loc[0]) || null;
99
- const foundLat = loc && (loc.lat || Array.isArray(loc) && loc[1]) || null;
100
- if (foundLng != null && foundLat != null) {
120
+ // 初始 marker 放置
121
+ try {
122
+ markerRef.current = new window.AMap.Marker({
123
+ position: [initLng, initLat],
124
+ map
125
+ });
126
+ } catch (e) {
127
+ console.warn('Marker init failed', e);
128
+ }
129
+
130
+ // AutoComplete + PlaceSearch
131
+ try {
132
+ placeSearchRef.current = new window.AMap.PlaceSearch({
133
+ map
134
+ });
135
+ autoRef.current = new window.AMap.AutoComplete({
136
+ input: document.getElementById(_A_MAP_SEARCH_)
137
+ });
138
+ autoRef.current.on && autoRef.current.on('select', e => {
139
+ // e.poi 里可能是 AMap.LngLat 实例 / 对象 / 数组,做兼容处理
140
+ const poi = e && e.poi ? e.poi : null;
141
+ let loc = poi && (poi.location || poi.lnglat) || e && (e.location || e.lnglat) || null;
142
+ let foundLng = null;
143
+ let foundLat = null;
144
+ if (loc) {
145
+ if (typeof loc.getLng === 'function' && typeof loc.getLat === 'function') {
146
+ // AMap.LngLat 实例
147
+ foundLng = Number(loc.getLng());
148
+ foundLat = Number(loc.getLat());
149
+ } else if (typeof loc.lng === 'number' && typeof loc.lat === 'number') {
150
+ foundLng = Number(loc.lng);
151
+ foundLat = Number(loc.lat);
152
+ } else if (Array.isArray(loc)) {
153
+ foundLng = Number(loc[0]);
154
+ foundLat = Number(loc[1]);
155
+ }
156
+ }
157
+ if (foundLng != null && foundLat != null && !Number.isNaN(foundLng) && !Number.isNaN(foundLat)) {
101
158
  setLng(foundLng);
102
159
  setLat(foundLat);
103
160
  map.setCenter([foundLng, foundLat]);
@@ -109,86 +166,155 @@ const AMap = ({
109
166
  map
110
167
  });
111
168
  }
169
+ } else {
170
+ // 兜底:用 placeSearch 搜索 name(如果有)
171
+ const name = poi && (poi.name || poi.address) || e && (e.info || e.name);
172
+ if (name && placeSearchRef.current && placeSearchRef.current.search) {
173
+ placeSearchRef.current.search(name, (status, result) => {
174
+ // placeSearch 回调再处理,这里保持原有逻辑或按需增强
175
+ if (status === 'complete' && result && result.poiList && result.poiList.pois && result.poiList.pois.length > 0) {
176
+ const p = result.poiList.pois[0];
177
+ const loc2 = p.location || p.lnglat;
178
+ let x = null,
179
+ y = null;
180
+ if (loc2) {
181
+ if (typeof loc2.getLng === 'function') {
182
+ x = Number(loc2.getLng());
183
+ y = Number(loc2.getLat());
184
+ } else if (typeof loc2.lng === 'number') {
185
+ x = Number(loc2.lng);
186
+ y = Number(loc2.lat);
187
+ } else if (Array.isArray(loc2)) {
188
+ x = Number(loc2[0]);
189
+ y = Number(loc2[1]);
190
+ }
191
+ }
192
+ if (!Number.isNaN(x) && !Number.isNaN(y)) {
193
+ setLng(x);
194
+ setLat(y);
195
+ map.setCenter([x, y]);
196
+ if (markerRef.current) markerRef.current.setPosition([x, y]);else markerRef.current = new window.AMap.Marker({
197
+ position: [x, y],
198
+ map
199
+ });
200
+ }
201
+ }
202
+ });
203
+ }
112
204
  }
113
- }
114
- });
115
- });
116
- } catch (e) {}
205
+ });
206
+ } catch (e) {
207
+ console.warn('AutoComplete / PlaceSearch init failed', e);
208
+ }
117
209
 
118
- // 地图点击选点
119
- map.on && map.on('click', e => {
120
- const {
121
- lng: clickLng,
122
- lat: clickLat
123
- } = e.lnglat || {};
124
- if (clickLng == null || clickLat == null) return;
125
- setLng(clickLng);
126
- setLat(clickLat);
127
- if (markerRef.current) {
128
- markerRef.current.setPosition([clickLng, clickLat]);
129
- } else {
130
- markerRef.current = new window.AMap.Marker({
131
- position: [clickLng, clickLat],
132
- map
133
- });
134
- }
135
- });
136
- });
210
+ // 点击选点
211
+ try {
212
+ map.on && map.on('click', e => {
213
+ const lnglat = e && e.lnglat;
214
+ if (!lnglat) return;
215
+ let clickLng = null;
216
+ let clickLat = null;
217
+ if (typeof lnglat.getLng === 'function') {
218
+ clickLng = Number(lnglat.getLng());
219
+ clickLat = Number(lnglat.getLat());
220
+ } else {
221
+ clickLng = Number(lnglat.lng || Array.isArray(lnglat) && lnglat[0]);
222
+ clickLat = Number(lnglat.lat || Array.isArray(lnglat) && lnglat[1]);
223
+ }
224
+ if (Number.isNaN(clickLng) || Number.isNaN(clickLat)) return;
225
+ setLng(clickLng);
226
+ setLat(clickLat);
227
+ if (markerRef.current) {
228
+ markerRef.current.setPosition([clickLng, clickLat]);
229
+ } else {
230
+ markerRef.current = new window.AMap.Marker({
231
+ position: [clickLng, clickLat],
232
+ map
233
+ });
234
+ }
235
+ });
236
+ } catch (e) {
237
+ console.warn('map.on click failed', e);
238
+ }
239
+ });
240
+ } catch (err) {
241
+ console.error('AMap init error', err);
242
+ }
243
+ }
244
+ init();
137
245
 
138
246
  // cleanup
139
247
  return () => {
248
+ mounted = false;
140
249
  try {
141
250
  if (mapRef.current) {
142
251
  mapRef.current.destroy();
143
252
  mapRef.current = null;
144
253
  }
145
- } catch (e) {}
254
+ } catch (e) {
255
+ // ignore
256
+ }
146
257
  markerRef.current = null;
147
258
  autoRef.current = null;
148
259
  placeSearchRef.current = null;
149
260
  };
150
261
  }, [propLng, propLat]);
151
262
 
152
- /** 重置地图 */
263
+ // 重置、确认等操作(同样做 number guard)
153
264
  const onResetMap = useCallback(() => {
154
265
  const map = mapRef.current;
155
266
  if (!map) return;
156
- setLng(_A_MAP_DEFAULT_POINT_.lng);
157
- setLat(_A_MAP_DEFAULT_POINT_.lat);
158
- map.setCenter([_A_MAP_DEFAULT_POINT_.lng, _A_MAP_DEFAULT_POINT_.lat]);
159
- if (markerRef.current) {
160
- markerRef.current.setPosition([_A_MAP_DEFAULT_POINT_.lng, _A_MAP_DEFAULT_POINT_.lat]);
161
- } else {
162
- markerRef.current = new window.AMap.Marker({
163
- position: [_A_MAP_DEFAULT_POINT_.lng, _A_MAP_DEFAULT_POINT_.lat],
164
- map
165
- });
267
+ const x = Number(_A_MAP_DEFAULT_POINT_.lng);
268
+ const y = Number(_A_MAP_DEFAULT_POINT_.lat);
269
+ setLng(x);
270
+ setLat(y);
271
+ try {
272
+ map.setCenter([x, y]);
273
+ if (markerRef.current) {
274
+ markerRef.current.setPosition([x, y]);
275
+ } else {
276
+ markerRef.current = new window.AMap.Marker({
277
+ position: [x, y],
278
+ map
279
+ });
280
+ }
281
+ } catch (e) {
282
+ console.warn('reset map failed', e);
166
283
  }
167
284
  }, []);
168
-
169
- /** 确认操作(逆地理编码) */
170
285
  const handleOk = useCallback(() => {
171
286
  if (!mapRef.current) return;
172
- // 确保 Geocoder 可用
287
+ // 确保 lng/lat 是 number
288
+ const x = Number(lng);
289
+ const y = Number(lat);
290
+ if (Number.isNaN(x) || Number.isNaN(y)) {
291
+ onOk && onOk({
292
+ lng,
293
+ lat,
294
+ comp: undefined,
295
+ compText: undefined
296
+ });
297
+ return;
298
+ }
173
299
  window.AMap.plugin('AMap.Geocoder', () => {
174
300
  try {
175
301
  const geocoder = new window.AMap.Geocoder();
176
- geocoder.getAddress([lng, lat], (status, result) => {
302
+ geocoder.getAddress([x, y], (status, result) => {
177
303
  let comp;
178
304
  if (status === 'complete' && result && result.regeocode) {
179
305
  comp = result.regeocode.addressComponent;
180
306
  }
181
307
  onOk && onOk({
182
- lng,
183
- lat,
308
+ lng: x,
309
+ lat: y,
184
310
  comp,
185
311
  compText: comp && [comp.province, comp.city, comp.district, comp.township, comp.street, comp.streetNumber].filter(Boolean).join('') || undefined
186
312
  });
187
313
  });
188
314
  } catch (e) {
189
315
  onOk && onOk({
190
- lng,
191
- lat,
316
+ lng: x,
317
+ lat: y,
192
318
  comp: undefined,
193
319
  compText: undefined
194
320
  });
@@ -242,5 +368,4 @@ const AMap = ({
242
368
  status: "error",
243
369
  title: "\u52A0\u8F7D\u5730\u56FE\u5931\u8D25\uFF0C\u7F3A\u5C11\u5FC5\u8981\u7684\u6587\u4EF6\uFF01"
244
370
  }));
245
- };
246
- export default AMap;
371
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cqsjjb/jjb-react-admin-component",
3
- "version": "3.3.0-beta.3",
3
+ "version": "3.3.0-beta.4",
4
4
  "description": "jjb-react-admin-组件库@new",
5
5
  "main": "index.js",
6
6
  "author": "jjb-front-team",