@conecli/cone-render 0.10.1-shop3.123 → 0.10.1-shop3.124

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