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

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