@conecli/cone-render 0.10.1-shop3.126 → 0.10.1-shop3.127

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.
@@ -1 +1 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
1
  getQualityImage,
3
2
  isH5AndJdShopView,
4
3
  isChartH5,
5
4
  isH5AndJdShopViewH5Scroll,
6
5
  isAppStowShop,
7
6
  getSgmCustomCode,
8
7
  isImageOptimizeEnable,
9
8
  getAvifSupport,
10
9
  getWebpSupport,
11
10
  draBusinessCustomReport,
12
11
  getNativePageScrollRes,
13
12
  latestFromNativeMsgStorage,
14
13
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFAAAAp3o92gAAAAF0Uk5TAEDm2GYAAAAKSURBVHicY2QAAAAEAAIhZK1qAAAAAElFTkSuQmCC';
15
14
  'https://img14.360buyimg.com/imagetools/jfs/t1/222907/25/7012/5824/61c4797cEbcd17c7f/6c76fc71e4fdb5a5.png';
16
15
  const styleSheets = document.styleSheets;
17
16
  const internalStyleSheets = [];
18
17
  for (let i = 0; i < styleSheets.length; i++) {
19
18
  const sheet = styleSheets[i];
20
19
  const ownerNode = sheet.ownerNode;
21
20
  if (ownerNode && ownerNode.nodeName === 'STYLE') {
22
21
  internalStyleSheets.push(sheet);
23
22
  }
24
23
  }
25
24
  console.warn('🚗 ~~ file: index.h5.tsx:47 ~~ getRuleBySelector() ~~ selector:', selector);
26
25
  for (let i = 0; i < internalStyleSheets.length; i++) {
27
26
  try {
28
27
  const sheet = internalStyleSheets[i];
29
28
  const rules = sheet.cssRules || sheet.rules;
30
29
  for (const rule of rules) {
31
30
  if (rule?.selectorText?.match(new RegExp(selector + '$'))) {
32
31
  return rule;
33
32
  }
34
33
  }
35
34
  } catch (e) {
36
35
  console.warn('因安全限制无法访问样式表:', e);
37
36
  }
38
37
  }
39
38
  return null;
40
39
  const {
41
40
  src = null,
42
41
  lazyLoad = true,
43
42
  imagRenderingSet = true,
44
43
  width = null,
45
44
  height = null,
46
45
  className = null,
47
46
  isSkuImage = false,
48
47
  hideErrorImage = false,
49
48
  style = null,
50
49
  backgroundColor = null,
51
50
  errorSrc = null,
52
51
  onLoad = null,
53
52
  onError = null,
54
53
  sizeScale = 1,
55
54
  loadType = undefined,
56
55
  ...otherOption
57
56
  } = props;
58
57
  getNetWorkType === NetWorkTypeQuality.default &&
59
58
  (getNetWorkType = global.info.sysInfo.netWorkType);
60
59
  const [loadSuccess, setLoadSuccess] = useState(false);
61
60
  const [imageErrState, setImageErrState] = useState(false);
62
61
  const [componentShowState, setComponentShowState] = useState(false);
63
62
  const measureRef = useRef<HTMLElement | null>(null);
64
63
  const [measureComplete, setMeasureComplete] = useState(false);
65
64
  const [imgSrc, setImgSrc] = useState(src);
66
65
  const [hasRetrySuccess, setHasRetrySuccess] = useState(false);
67
66
  const hasRetryRef = useRef(false);
68
67
  const componentShowStateRef = useRef(false);
69
68
  const requestSrcRef = useRef(src);
70
69
  const needShowHighVersion =
71
70
  isH5AndJdShopViewH5Scroll &&
72
71
  !(global.info.queryInfo?.downgraded && global.info.queryInfo.downgraded === 'true');
73
72
  const enableAvifOptimize = isImageOptimizeEnable();
74
73
  const isVipShop = global?.info?.pageInfo?.isVipShop;
75
74
  const avifSupport = getAvifSupport();
76
75
  const webpSupport = getWebpSupport();
77
76
  const nativeImgFlag = useRef('');
78
77
 
79
78
  const getRequestSrc = useCallback(
80
79
  (src) => {
81
80
  let requestSrc = getQualityImage(imgSrc, {
82
81
  isSkuImage,
83
82
  size: measureRef?.current?.getBoundingClientRect()?.width,
84
83
  sizeScale,
85
84
  });
86
85
  requestSrcRef.current = requestSrc;
87
86
  if (loadType === LoadType.hybrid) {
88
87
  requestSrc = requestSrc
89
88
  .replace('http://', 'hybridimg://')
90
89
  .replace('https://', 'hybridimg://');
91
90
  nativeImgFlag.current = requestSrc;
92
91
  }
93
92
  return requestSrc;
94
93
  },
95
94
  [src],
96
95
  );
97
96
 
98
97
  const imageErrorRetry = (src) => {
99
98
  return new Promise((resolve, reject) => {
100
99
  if (fetch && window && window.Image) {
101
100
  fetch(src)
102
101
  .then((response) => {
103
102
  const { ok, status } = response;
104
103
  if (ok) {
105
104
  const originUrl = src.replace(/\.(jpe?g|png).*/, '.$1');
106
105
  response
107
106
  .blob()
108
107
  .then((blob) => {
109
108
  if (URL) {
110
109
  const url = URL.createObjectURL(blob);
111
110
  const img = new window.Image();
112
111
  img.src = url;
113
112
  img.onload = () => {
114
113
  reportSGM({
115
114
  status,
116
115
  text: '再次请求并且onload了',
117
116
  type: 'retryAndOnload',
118
117
  requestSrc: src,
119
118
  resolveUrl: url,
120
119
  });
121
120
  resolve({
122
121
  ok: true,
123
122
  url,
124
123
  });
125
124
  setTimeout(() => {
126
125
  URL.revokeObjectURL(url);
127
126
  }, 2000);
128
127
  };
129
128
  img.onerror = () => {
130
129
  reportSGM({
131
130
  status,
132
131
  text: '图片解析异常',
133
132
  type: 'imageParseError',
134
133
  requestSrc: src,
135
134
  });
136
135
  URL.revokeObjectURL(url);
137
136
  resolve({
138
137
  ok: true,
139
138
  url: originUrl,
140
139
  });
141
140
  };
142
141
  } else {
143
142
  resolve({
144
143
  ok: true,
145
144
  url: originUrl,
146
145
  });
147
146
  }
148
147
  })
149
148
  .catch((error) => {
150
149
  resolve({
151
150
  ok: true,
152
151
  url: originUrl,
153
152
  });
154
153
  console.error('LazyLoadImage imageErrorRetry() error:', error);
155
154
  });
156
155
  } else {
157
156
  if (status === 404) {
158
157
  resolve({
159
158
  ok: false,
160
159
  text: '访问图片不存在',
161
160
  type: 'noSuchUrlImage',
162
161
  });
163
162
  } else {
164
163
  resolve({
165
164
  ok: false,
166
165
  status: status,
167
166
  text: '其它图片问题',
168
167
  type: 'otherImageError',
169
168
  });
170
169
  }
171
170
  }
172
171
  })
173
172
  .catch((error) => {
174
173
  resolve({
175
174
  ok: false,
176
175
  text: '网络异常',
177
176
  type: 'networkError',
178
177
  });
179
178
  console.error('LazyLoadImage imageErrorRetry() error:', error);
180
179
  });
181
180
  } else {
182
181
  resolve({
183
182
  ok: false,
184
183
  text: '不支持重试',
185
184
  type: 'notSupportRetry',
186
185
  });
187
186
  }
188
187
  });
189
188
  };
190
189
 
191
190
  const reportSGM = ({ status, text, type, requestSrc = imgSrc, resolveUrl = '' }) => {
192
191
  const { shopId, venderId } = global.info.queryInfo || {};
193
192
  draBusinessCustomReport({
194
193
  eventName: 'business',
195
194
  errorName: getSgmCustomCode(`${SgmCustomCode.IMAGE_LOAD}_${type}`),
196
195
  errorMessage: '图片加载失败异常',
197
196
  extraData: JSON.stringify({
198
197
  avifSupport,
199
198
  webpSupport,
200
199
  shopId,
201
200
  venderId,
202
201
  originSrc: src,
203
202
  requestSrc,
204
203
  resolveUrl,
205
204
  status,
206
205
  text,
207
206
  }),
208
207
  });
209
208
  };
210
209
  const imageErrorHandle = useCallback(
211
210
  (e) => {
212
211
  console.log(' ==============> 图片加载错误', e);
213
212
  if (nativeImgFlag.current) {
214
213
  draBusinessCustomReport({
215
214
  eventName: 'business',
216
215
  errorName: 'jdapp_initCheckNativeImg_ImgLoad_catch_err',
217
216
  errorMessage: '松果app内图片原生加载过程catch异常, 触发https请求重试不阻塞页面',
218
217
  extraData: JSON.stringify({
219
218
  e,
220
219
  currentSrc: nativeImgFlag.current,
221
220
  }),
222
221
  });
223
222
  }
224
223
  if (!hasRetryRef.current) {
225
224
  hasRetryRef.current = true;
226
225
  if (src) {
227
226
  try {
228
227
  imageErrorRetry(requestSrcRef.current).then((result) => {
229
228
  const { status, ok, text, type, url } = result || {};
230
229
  if (ok) {
231
230
  setImgSrc(url);
232
231
  setHasRetrySuccess(true);
233
232
  } else {
234
233
  errorSrc && setImgSrc(errorSrc);
235
234
  hideErrorImage && setImageErrState(true);
236
235
  typeof onError === 'function' && onError(e, src, props);
237
236
  reportSGM({
238
237
  status,
239
238
  text,
240
239
  type,
241
240
  requestSrc: requestSrcRef.current,
242
241
  });
243
242
  }
244
243
  });
245
244
  } catch (e) {
246
245
  console.error('LazyLoadImage imageErrorHandle() error:', e);
247
246
  errorSrc && setImgSrc(errorSrc);
248
247
  hideErrorImage && setImageErrState(true);
249
248
  typeof onError === 'function' && onError(e, src, props);
250
249
  }
251
250
  }
252
251
  } else {
253
252
  reportSGM({
254
253
  status: '',
255
254
  text: '渲染原始图片渲染异常',
256
255
  type: 'renderOriginImageError',
257
256
  });
258
257
  if (imgSrc.includes('blob:')) {
259
258
  reportSGM({
260
259
  status: '',
261
260
  text: '渲染本地blob图片异常',
262
261
  type: 'renderBlobImageError',
263
262
  });
264
263
  } else {
265
264
  reportSGM({
266
265
  status: '',
267
266
  text: '渲染本地非blob图片异常',
268
267
  type: 'renderNoBlobImageError',
269
268
  });
270
269
  }
271
270
  }
272
271
  },
273
272
  [src, hasRetryRef.current],
274
273
  );
275
274
 
276
275
  const imageLoad = useCallback(
277
276
  (_src, event) => {
278
277
  setLoadSuccess(true);
279
278
  typeof onLoad === 'function' && onLoad(event, src, props);
280
279
  },
281
280
  [src],
282
281
  );
283
282
 
284
283
  const changeStyleIncludeWidthAndHeightAndBgColor = () => {
285
284
  const changeStyle = {};
286
285
  width && (changeStyle['width'] = width);
287
286
  height && (changeStyle['height'] = height);
288
287
  backgroundColor && (changeStyle['backgroundColor'] = backgroundColor);
289
288
  return changeStyle;
290
289
  };
291
290
  useEffect(() => {
292
291
  try {
293
292
  const { mode } = otherOption;
294
293
  if (mode && mode === 'heightFix') {
295
294
  className?.split(/\s/)?.forEach((item) => {
296
295
  const userDefinedClass = getRuleBySelector('.' + item);
297
296
  const userDefinedHeight = userDefinedClass?.style?.height;
298
297
  if (userDefinedHeight === '' || userDefinedHeight === 'auto') {
299
298
  console.warn(
300
299
  "🚗 ~~ 发现一例用户使用图片组件设置了 mode='heightFix' 并且没有定义一个具体高度:",
301
300
  userDefinedHeight,
302
301
  {
303
302
  code: getSgmCustomCode(`imageUsageCheck`),
304
303
  msg: {
305
304
  userDefinedClass: item,
306
305
  userDefinedHeight,
307
306
  },
308
307
  },
309
308
  );
310
309
  draBusinessCustomReport({
311
310
  eventName: 'business',
312
311
  errorName: getSgmCustomCode(`imageUsageCheck`),
313
312
  errorMessage: JSON.stringify({
314
313
  userDefinedClass: item,
315
314
  userDefinedHeight,
316
315
  }),
317
316
  });
318
317
  }
319
318
  });
320
319
  }
321
320
  } catch (e) {
322
321
  console.warn('imageUsageCheck error:', e);
323
322
  }
324
323
  setMeasureComplete(true);
325
324
  if (needShowHighVersion) return;
326
325
  const latestRes = latestFromNativeMsgStorage[TaroEventType.PAGE_SCROLL] || {};
327
326
  !componentShowStateRef.current && dealPageScrollInfo(latestRes);
328
327
  Taro.eventCenter.on(TaroEventType.PAGE_SCROLL, (res) => {
329
328
  !componentShowStateRef.current && dealPageScrollInfo(res);
330
329
  });
331
330
  }, []);
332
331
 
333
332
  const dealPageScrollInfo = (res) => {
334
333
  const { displayHeight, offSetY } = getNativePageScrollRes(res) || {};
335
334
  if (typeof displayHeight === 'undefined' || typeof offSetY === 'undefined') return;
336
335
  if (measureRef.current) {
337
336
  const eleClientRect = measureRef.current.getBoundingClientRect();
338
337
  const getContainerHeightOffSetY = displayHeight * 1.5 + offSetY;
339
338
  const eleOffsetTop = Math.ceil(eleClientRect.top);
340
339
  const eleOffsetHeight = Math.ceil(eleClientRect.height);
341
340
  if (!componentShowStateRef.current) {
342
341
  if (getContainerHeightOffSetY > eleOffsetTop) {
343
342
  componentShowStateRef.current = true;
344
343
  setComponentShowState(true);
345
344
  }
346
345
  }
347
346
  }
348
347
  };
349
348
  return isH5AndJdShopView &&
350
349
  global?.config?.needImageLazy !== false &&
351
350
  !needShowHighVersion &&
352
351
  !isAppStowShop ? (
353
352
  <View
354
353
  ref={measureRef}
355
354
  className={classNames(
356
355
  imageStyle['d-app-lazy-image'],
357
356
  {
358
357
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
359
358
  },
360
359
  {
361
360
  [imageStyle['d-hide-image-error']]: imageErrState,
362
361
  },
363
362
  {
364
363
  [imageStyle['d-load-completed']]: loadSuccess,
365
364
  },
366
365
  {
367
366
  'd-imag-rendering-crisp-edges': !isVipShop && imagRenderingSet,
368
367
  },
369
368
  'J_html5ImageBg',
370
369
  className,
371
370
  )}
372
371
  style={{
373
372
  ...style,
374
373
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
375
374
  }}
376
375
  {...otherOption}
377
376
  >
378
377
  {(componentShowState || lazyLoad === false) && (
379
378
  <img
380
379
  src={getQualityImage(
381
380
  imgSrc,
382
381
  isVipShop ? NetWorkTypeQuality['perfect'] : NetWorkTypeQuality[getNetWorkType],
383
382
  )}
384
383
  onLoad={imageLoad.bind(this, imgSrc)}
385
384
  onError={imageErrorHandle}
386
385
  />
387
386
  )}
388
387
  </View>
389
388
  ) : enableAvifOptimize ? (
390
389
  [
391
390
  measureComplete ? (
392
391
  <Image
393
392
  key={hasRetrySuccess ? 'realImageRetry' : 'realImage'}
394
393
  style={{
395
394
  ...style,
396
395
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
397
396
  }}
398
397
  className={classNames(
399
398
  imageStyle['d-lazy-image'],
400
399
  {
401
400
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
402
401
  },
403
402
  {
404
403
  [imageStyle['d-hide-image-error']]: imageErrState,
405
404
  },
406
405
  {
407
406
  [imageStyle['d-load-completed']]: loadSuccess,
408
407
  },
409
408
  {
410
409
  'd-imag-rendering-crisp-edges': imagRenderingSet,
411
410
  },
412
411
  {
413
412
  [imageStyle['d-no-jd-dog']]: isVipShop && !isSkuImage,
414
413
  },
415
414
  className,
416
415
  )}
417
416
  src={hasRetrySuccess ? imgSrc : getRequestSrc(imgSrc)}
418
417
  lazyLoad={isChartH5 ? false : lazyLoad}
419
418
  onError={imageErrorHandle}
420
419
  onLoad={imageLoad.bind(this, imgSrc)}
421
420
  {...otherOption}
422
421
  />
423
422
  ) : (
424
423
  <Image
425
424
  key="defaultImage"
426
425
  style={{
427
426
  ...style,
428
427
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
429
428
  }}
430
429
  className={classNames(
431
430
  imageStyle['d-lazy-image'],
432
431
  {
433
432
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
434
433
  },
435
434
  {
436
435
  [imageStyle['d-hide-image-error']]: imageErrState,
437
436
  },
438
437
  {
439
438
  [imageStyle['d-load-completed']]: loadSuccess,
440
439
  },
441
440
  {
442
441
  'd-imag-rendering-crisp-edges': imagRenderingSet,
443
442
  },
444
443
  {
445
444
  [imageStyle['d-no-jd-dog']]: isVipShop && !isSkuImage,
446
445
  },
447
446
  className,
448
447
  )}
449
448
  src={isSkuImage ? DEFAULT_SKU_SRC : DEFAULT_SRC}
450
449
  />
451
450
  ),
452
451
  loadSuccess ? null : <View key="measureRef" ref={measureRef}></View>,
453
452
  ]
454
453
  ) : (
455
454
  <Image
456
455
  style={{
457
456
  ...style,
458
457
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
459
458
  }}
460
459
  className={classNames(
461
460
  imageStyle['d-lazy-image'],
462
461
  {
463
462
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
464
463
  },
465
464
  {
466
465
  [imageStyle['d-hide-image-error']]: imageErrState,
467
466
  },
468
467
  {
469
468
  [imageStyle['d-load-completed']]: loadSuccess,
470
469
  },
471
470
  {
472
471
  'd-imag-rendering-crisp-edges': imagRenderingSet,
473
472
  },
474
473
  className,
475
474
  )}
476
475
  src={getQualityImage(imgSrc, NetWorkTypeQuality[getNetWorkType])}
477
476
  lazyLoad={isChartH5 ? false : lazyLoad}
478
477
  onError={imageErrorHandle}
479
478
  onLoad={imageLoad.bind(this, imgSrc)}
480
479
  {...otherOption}
481
480
  />
482
481
  );
482
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
483
483
  getQualityImage,
484
484
  isH5AndJdShopView,
485
485
  isChartH5,
486
486
  isH5AndJdShopViewH5Scroll,
487
487
  isAppStowShop,
488
488
  getSgmCustomCode,
489
489
  isImageOptimizeEnable,
490
490
  getAvifSupport,
491
491
  getWebpSupport,
492
492
  draBusinessCustomReport,
493
493
  draBusinessCustomLogReport,
494
494
  getNativePageScrollRes,
495
495
  latestFromNativeMsgStorage,
496
496
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFAAAAp3o92gAAAAF0Uk5TAEDm2GYAAAAKSURBVHicY2QAAAAEAAIhZK1qAAAAAElFTkSuQmCC';
497
497
  'https://img14.360buyimg.com/imagetools/jfs/t1/222907/25/7012/5824/61c4797cEbcd17c7f/6c76fc71e4fdb5a5.png';
498
498
  const styleSheets = document.styleSheets;
499
499
  const internalStyleSheets = [];
500
500
  for (let i = 0; i < styleSheets.length; i++) {
501
501
  const sheet = styleSheets[i];
502
502
  const ownerNode = sheet.ownerNode;
503
503
  if (ownerNode && ownerNode.nodeName === 'STYLE') {
504
504
  internalStyleSheets.push(sheet);
505
505
  }
506
506
  }
507
507
  console.warn('🚗 ~~ file: index.h5.tsx:47 ~~ getRuleBySelector() ~~ selector:', selector);
508
508
  for (let i = 0; i < internalStyleSheets.length; i++) {
509
509
  try {
510
510
  const sheet = internalStyleSheets[i];
511
511
  const rules = sheet.cssRules || sheet.rules;
512
512
  for (const rule of rules) {
513
513
  if (rule?.selectorText?.match(new RegExp(selector + '$'))) {
514
514
  return rule;
515
515
  }
516
516
  }
517
517
  } catch (e) {
518
518
  console.warn('因安全限制无法访问样式表:', e);
519
519
  }
520
520
  }
521
521
  return null;
522
522
  const {
523
523
  src = null,
524
524
  lazyLoad = true,
525
525
  imagRenderingSet = true,
526
526
  width = null,
527
527
  height = null,
528
528
  className = null,
529
529
  isSkuImage = false,
530
530
  hideErrorImage = false,
531
531
  style = null,
532
532
  backgroundColor = null,
533
533
  errorSrc = null,
534
534
  onLoad = null,
535
535
  onError = null,
536
536
  sizeScale = 1,
537
537
  loadType = undefined,
538
538
  ...otherOption
539
539
  } = props;
540
540
  getNetWorkType === NetWorkTypeQuality.default &&
541
541
  (getNetWorkType = global.info.sysInfo.netWorkType);
542
542
  const [loadSuccess, setLoadSuccess] = useState(false);
543
543
  const [imageErrState, setImageErrState] = useState(false);
544
544
  const [componentShowState, setComponentShowState] = useState(false);
545
545
  const measureRef = useRef<HTMLElement | null>(null);
546
546
  const [measureComplete, setMeasureComplete] = useState(false);
547
547
  const [imgSrc, setImgSrc] = useState(src);
548
548
  const [hasRetrySuccess, setHasRetrySuccess] = useState(false);
549
549
  const hasRetryRef = useRef(false);
550
550
  const componentShowStateRef = useRef(false);
551
551
  const requestSrcRef = useRef(src);
552
552
  const needShowHighVersion =
553
553
  isH5AndJdShopViewH5Scroll &&
554
554
  !(global.info.queryInfo?.downgraded && global.info.queryInfo.downgraded === 'true');
555
555
  const enableAvifOptimize = isImageOptimizeEnable();
556
556
  const isVipShop = global?.info?.pageInfo?.isVipShop;
557
557
  const avifSupport = getAvifSupport();
558
558
  const webpSupport = getWebpSupport();
559
559
  const nativeImgFlag = useRef('');
560
560
 
561
561
  const getRequestSrc = useCallback(
562
562
  (src) => {
563
563
  let requestSrc = getQualityImage(imgSrc, {
564
564
  isSkuImage,
565
565
  size: measureRef?.current?.getBoundingClientRect()?.width,
566
566
  sizeScale,
567
567
  });
568
568
  requestSrcRef.current = requestSrc;
569
569
  if (loadType === LoadType.hybrid) {
570
570
  requestSrc = requestSrc
571
571
  .replace('http://', 'hybridimg://')
572
572
  .replace('https://', 'hybridimg://');
573
573
  nativeImgFlag.current = requestSrc;
574
574
  }
575
575
  return requestSrc;
576
576
  },
577
577
  [src],
578
578
  );
579
579
 
580
580
  const imageErrorRetry = (src) => {
581
581
  return new Promise((resolve, reject) => {
582
582
  if (fetch && window && window.Image) {
583
583
  fetch(src)
584
584
  .then((response) => {
585
585
  const { ok, status } = response;
586
586
  if (ok) {
587
587
  const originUrl = src.replace(/\.(jpe?g|png).*/, '.$1');
588
588
  response
589
589
  .blob()
590
590
  .then((blob) => {
591
591
  if (URL) {
592
592
  const url = URL.createObjectURL(blob);
593
593
  const img = new window.Image();
594
594
  img.src = url;
595
595
  img.onload = () => {
596
596
  reportSGM({
597
597
  status,
598
598
  text: '再次请求并且onload了',
599
599
  type: 'retryAndOnload',
600
600
  requestSrc: src,
601
601
  resolveUrl: url,
602
602
  });
603
603
  resolve({
604
604
  ok: true,
605
605
  url,
606
606
  });
607
607
  setTimeout(() => {
608
608
  URL.revokeObjectURL(url);
609
609
  }, 2000);
610
610
  };
611
611
  img.onerror = () => {
612
612
  reportSGM({
613
613
  status,
614
614
  text: '图片解析异常',
615
615
  type: 'imageParseError',
616
616
  requestSrc: src,
617
617
  });
618
618
  URL.revokeObjectURL(url);
619
619
  resolve({
620
620
  ok: true,
621
621
  url: originUrl,
622
622
  });
623
623
  };
624
624
  } else {
625
625
  resolve({
626
626
  ok: true,
627
627
  url: originUrl,
628
628
  });
629
629
  }
630
630
  })
631
631
  .catch((error) => {
632
632
  resolve({
633
633
  ok: true,
634
634
  url: originUrl,
635
635
  });
636
636
  console.error('LazyLoadImage imageErrorRetry() error:', error);
637
637
  });
638
638
  } else {
639
639
  if (status === 404) {
640
640
  resolve({
641
641
  ok: false,
642
642
  text: '访问图片不存在',
643
643
  type: 'noSuchUrlImage',
644
644
  });
645
645
  } else {
646
646
  resolve({
647
647
  ok: false,
648
648
  status: status,
649
649
  text: '其它图片问题',
650
650
  type: 'otherImageError',
651
651
  });
652
652
  }
653
653
  }
654
654
  })
655
655
  .catch((error) => {
656
656
  resolve({
657
657
  ok: false,
658
658
  text: '网络异常',
659
659
  type: 'networkError',
660
660
  });
661
661
  console.error('LazyLoadImage imageErrorRetry() error:', error);
662
662
  });
663
663
  } else {
664
664
  resolve({
665
665
  ok: false,
666
666
  text: '不支持重试',
667
667
  type: 'notSupportRetry',
668
668
  });
669
669
  }
670
670
  });
671
671
  };
672
672
 
673
673
  const reportSGM = ({ status, text, type, requestSrc = imgSrc, resolveUrl = '' }) => {
674
674
  const { shopId, venderId } = global.info.queryInfo || {};
675
675
  draBusinessCustomReport({
676
676
  eventName: 'business',
677
677
  errorName: getSgmCustomCode(`${SgmCustomCode.IMAGE_LOAD}_${type}`),
678
678
  errorMessage: '图片加载失败异常',
679
679
  extraData: JSON.stringify({
680
680
  avifSupport,
681
681
  webpSupport,
682
682
  shopId,
683
683
  venderId,
684
684
  originSrc: src,
685
685
  requestSrc,
686
686
  resolveUrl,
687
687
  status,
688
688
  text,
689
689
  }),
690
690
  });
691
691
  };
692
692
  const imageErrorHandle = useCallback(
693
693
  (e) => {
694
694
  console.log(' ==============> 图片加载错误', e);
695
695
  if (nativeImgFlag.current) {
696
696
  draBusinessCustomReport({
697
697
  eventName: 'business',
698
698
  errorName: 'jdapp_initCheckNativeImg_ImgLoad_catch_err',
699
699
  errorMessage: '松果app内图片原生加载过程catch异常, 触发https请求重试不阻塞页面',
700
700
  extraData: JSON.stringify({
701
701
  e,
702
702
  currentSrc: nativeImgFlag.current,
703
703
  }),
704
704
  });
705
705
  }
706
706
  if (!hasRetryRef.current) {
707
707
  hasRetryRef.current = true;
708
708
  if (src) {
709
709
  try {
710
710
  imageErrorRetry(requestSrcRef.current).then((result) => {
711
711
  const { status, ok, text, type, url } = result || {};
712
712
  if (ok) {
713
713
  setImgSrc(url);
714
714
  setHasRetrySuccess(true);
715
715
  } else {
716
716
  errorSrc && setImgSrc(errorSrc);
717
717
  hideErrorImage && setImageErrState(true);
718
718
  typeof onError === 'function' && onError(e, src, props);
719
719
  reportSGM({
720
720
  status,
721
721
  text,
722
722
  type,
723
723
  requestSrc: requestSrcRef.current,
724
724
  });
725
725
  }
726
726
  });
727
727
  } catch (e) {
728
728
  console.error('LazyLoadImage imageErrorHandle() error:', e);
729
729
  errorSrc && setImgSrc(errorSrc);
730
730
  hideErrorImage && setImageErrState(true);
731
731
  typeof onError === 'function' && onError(e, src, props);
732
732
  }
733
733
  }
734
734
  } else {
735
735
  reportSGM({
736
736
  status: '',
737
737
  text: '渲染原始图片渲染异常',
738
738
  type: 'renderOriginImageError',
739
739
  });
740
740
  if (imgSrc.includes('blob:')) {
741
741
  reportSGM({
742
742
  status: '',
743
743
  text: '渲染本地blob图片异常',
744
744
  type: 'renderBlobImageError',
745
745
  });
746
746
  } else {
747
747
  reportSGM({
748
748
  status: '',
749
749
  text: '渲染本地非blob图片异常',
750
750
  type: 'renderNoBlobImageError',
751
751
  });
752
752
  }
753
753
  }
754
754
  },
755
755
  [src, hasRetryRef.current],
756
756
  );
757
757
 
758
758
  const imageLoad = useCallback(
759
759
  (_src, event) => {
760
760
  setLoadSuccess(true);
761
761
  typeof onLoad === 'function' && onLoad(event, src, props);
762
762
  if (nativeImgFlag.current && window?.PAGE_DATA?.businessData?.nativeImgConfig?.successLog) {
763
763
  draBusinessCustomLogReport(
764
764
  `APP店铺initCheckNativeImg安卓图片原生加载成功:${nativeImgFlag.current}`,
765
765
  );
766
766
  }
767
767
  },
768
768
  [src],
769
769
  );
770
770
 
771
771
  const changeStyleIncludeWidthAndHeightAndBgColor = () => {
772
772
  const changeStyle = {};
773
773
  width && (changeStyle['width'] = width);
774
774
  height && (changeStyle['height'] = height);
775
775
  backgroundColor && (changeStyle['backgroundColor'] = backgroundColor);
776
776
  return changeStyle;
777
777
  };
778
778
  useEffect(() => {
779
779
  try {
780
780
  const { mode } = otherOption;
781
781
  if (mode && mode === 'heightFix') {
782
782
  className?.split(/\s/)?.forEach((item) => {
783
783
  const userDefinedClass = getRuleBySelector('.' + item);
784
784
  const userDefinedHeight = userDefinedClass?.style?.height;
785
785
  if (userDefinedHeight === '' || userDefinedHeight === 'auto') {
786
786
  console.warn(
787
787
  "🚗 ~~ 发现一例用户使用图片组件设置了 mode='heightFix' 并且没有定义一个具体高度:",
788
788
  userDefinedHeight,
789
789
  {
790
790
  code: getSgmCustomCode(`imageUsageCheck`),
791
791
  msg: {
792
792
  userDefinedClass: item,
793
793
  userDefinedHeight,
794
794
  },
795
795
  },
796
796
  );
797
797
  draBusinessCustomReport({
798
798
  eventName: 'business',
799
799
  errorName: getSgmCustomCode(`imageUsageCheck`),
800
800
  errorMessage: JSON.stringify({
801
801
  userDefinedClass: item,
802
802
  userDefinedHeight,
803
803
  }),
804
804
  });
805
805
  }
806
806
  });
807
807
  }
808
808
  } catch (e) {
809
809
  console.warn('imageUsageCheck error:', e);
810
810
  }
811
811
  setMeasureComplete(true);
812
812
  if (needShowHighVersion) return;
813
813
  const latestRes = latestFromNativeMsgStorage[TaroEventType.PAGE_SCROLL] || {};
814
814
  !componentShowStateRef.current && dealPageScrollInfo(latestRes);
815
815
  Taro.eventCenter.on(TaroEventType.PAGE_SCROLL, (res) => {
816
816
  !componentShowStateRef.current && dealPageScrollInfo(res);
817
817
  });
818
818
  }, []);
819
819
 
820
820
  const dealPageScrollInfo = (res) => {
821
821
  const { displayHeight, offSetY } = getNativePageScrollRes(res) || {};
822
822
  if (typeof displayHeight === 'undefined' || typeof offSetY === 'undefined') return;
823
823
  if (measureRef.current) {
824
824
  const eleClientRect = measureRef.current.getBoundingClientRect();
825
825
  const getContainerHeightOffSetY = displayHeight * 1.5 + offSetY;
826
826
  const eleOffsetTop = Math.ceil(eleClientRect.top);
827
827
  const eleOffsetHeight = Math.ceil(eleClientRect.height);
828
828
  if (!componentShowStateRef.current) {
829
829
  if (getContainerHeightOffSetY > eleOffsetTop) {
830
830
  componentShowStateRef.current = true;
831
831
  setComponentShowState(true);
832
832
  }
833
833
  }
834
834
  }
835
835
  };
836
836
  return isH5AndJdShopView &&
837
837
  global?.config?.needImageLazy !== false &&
838
838
  !needShowHighVersion &&
839
839
  !isAppStowShop ? (
840
840
  <View
841
841
  ref={measureRef}
842
842
  className={classNames(
843
843
  imageStyle['d-app-lazy-image'],
844
844
  {
845
845
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
846
846
  },
847
847
  {
848
848
  [imageStyle['d-hide-image-error']]: imageErrState,
849
849
  },
850
850
  {
851
851
  [imageStyle['d-load-completed']]: loadSuccess,
852
852
  },
853
853
  {
854
854
  'd-imag-rendering-crisp-edges': !isVipShop && imagRenderingSet,
855
855
  },
856
856
  'J_html5ImageBg',
857
857
  className,
858
858
  )}
859
859
  style={{
860
860
  ...style,
861
861
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
862
862
  }}
863
863
  {...otherOption}
864
864
  >
865
865
  {(componentShowState || lazyLoad === false) && (
866
866
  <img
867
867
  src={getQualityImage(
868
868
  imgSrc,
869
869
  isVipShop ? NetWorkTypeQuality['perfect'] : NetWorkTypeQuality[getNetWorkType],
870
870
  )}
871
871
  onLoad={imageLoad.bind(this, imgSrc)}
872
872
  onError={imageErrorHandle}
873
873
  />
874
874
  )}
875
875
  </View>
876
876
  ) : enableAvifOptimize ? (
877
877
  [
878
878
  measureComplete ? (
879
879
  <Image
880
880
  key={hasRetrySuccess ? 'realImageRetry' : 'realImage'}
881
881
  style={{
882
882
  ...style,
883
883
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
884
884
  }}
885
885
  className={classNames(
886
886
  imageStyle['d-lazy-image'],
887
887
  {
888
888
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
889
889
  },
890
890
  {
891
891
  [imageStyle['d-hide-image-error']]: imageErrState,
892
892
  },
893
893
  {
894
894
  [imageStyle['d-load-completed']]: loadSuccess,
895
895
  },
896
896
  {
897
897
  'd-imag-rendering-crisp-edges': imagRenderingSet,
898
898
  },
899
899
  {
900
900
  [imageStyle['d-no-jd-dog']]: isVipShop && !isSkuImage,
901
901
  },
902
902
  className,
903
903
  )}
904
904
  src={hasRetrySuccess ? imgSrc : getRequestSrc(imgSrc)}
905
905
  lazyLoad={isChartH5 ? false : lazyLoad}
906
906
  onError={imageErrorHandle}
907
907
  onLoad={imageLoad.bind(this, imgSrc)}
908
908
  {...otherOption}
909
909
  />
910
910
  ) : (
911
911
  <Image
912
912
  key="defaultImage"
913
913
  style={{
914
914
  ...style,
915
915
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
916
916
  }}
917
917
  className={classNames(
918
918
  imageStyle['d-lazy-image'],
919
919
  {
920
920
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
921
921
  },
922
922
  {
923
923
  [imageStyle['d-hide-image-error']]: imageErrState,
924
924
  },
925
925
  {
926
926
  [imageStyle['d-load-completed']]: loadSuccess,
927
927
  },
928
928
  {
929
929
  'd-imag-rendering-crisp-edges': imagRenderingSet,
930
930
  },
931
931
  {
932
932
  [imageStyle['d-no-jd-dog']]: isVipShop && !isSkuImage,
933
933
  },
934
934
  className,
935
935
  )}
936
936
  src={isSkuImage ? DEFAULT_SKU_SRC : DEFAULT_SRC}
937
937
  />
938
938
  ),
939
939
  loadSuccess ? null : <View key="measureRef" ref={measureRef}></View>,
940
940
  ]
941
941
  ) : (
942
942
  <Image
943
943
  style={{
944
944
  ...style,
945
945
  ...changeStyleIncludeWidthAndHeightAndBgColor(),
946
946
  }}
947
947
  className={classNames(
948
948
  imageStyle['d-lazy-image'],
949
949
  {
950
950
  [imageStyle['d-lazy-sku-image']]: isSkuImage,
951
951
  },
952
952
  {
953
953
  [imageStyle['d-hide-image-error']]: imageErrState,
954
954
  },
955
955
  {
956
956
  [imageStyle['d-load-completed']]: loadSuccess,
957
957
  },
958
958
  {
959
959
  'd-imag-rendering-crisp-edges': imagRenderingSet,
960
960
  },
961
961
  className,
962
962
  )}
963
963
  src={getQualityImage(imgSrc, NetWorkTypeQuality[getNetWorkType])}
964
964
  lazyLoad={isChartH5 ? false : lazyLoad}
965
965
  onError={imageErrorHandle}
966
966
  onLoad={imageLoad.bind(this, imgSrc)}
967
967
  {...otherOption}
968
968
  />
969
969
  );