qb-pc-sdk 1.3.2 → 1.3.3
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.
- package/README.md +92 -0
- package/core.min.js +1 -1
- package/package.json +2 -2
- package/src/ad-sdk-wrapper.js +128 -6
- package/src/pcAdTest.html +54 -2
- package/src/pcLazyLoad.html +4 -4
package/package.json
CHANGED
package/src/ad-sdk-wrapper.js
CHANGED
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
|
|
251
251
|
|
|
252
252
|
const INJECT_CSS = `
|
|
253
|
-
.q-ad-wrapper { display: flex; flex-direction: column; width: 100%; height: 100%; background: #fff; border: 1px solid #eee; overflow: hidden; font-family: sans-serif; position: relative; box-sizing: border-box; }
|
|
253
|
+
.q-ad-wrapper { display: flex; flex-direction: column; width: 100%; height: 100%; background: #fff; border: 1px solid #eee; overflow: hidden; font-family: sans-serif; position: relative; box-sizing: border-box; cursor: pointer; }
|
|
254
254
|
.q-media-container { width: 100%; flex: 1; min-height: 0; background: #000; position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
|
255
255
|
.q-ad-img, .q-ad-video { width: 100%; height: 100%; object-fit: contain; display: block; }
|
|
256
256
|
.q-content-container { padding: 8px; flex-shrink: 0; display: flex; flex-direction: column; justify-content: space-between; min-height: 0; }
|
|
@@ -258,9 +258,18 @@
|
|
|
258
258
|
.q-ad-desc { font-size: 11px; color: #666; margin: 0 0 6px 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.3; flex-shrink: 0; }
|
|
259
259
|
.q-cta-btn { background: #007bff; color: #fff; border: none; padding: 4px 12px; border-radius: 4px; font-size: 11px; cursor: pointer; align-self: flex-start; flex-shrink: 0; }
|
|
260
260
|
.q-ad-tag { position: absolute; right: 5px; bottom: 5px; background: rgba(0,0,0,0.3); color: #fff; font-size: 10px; padding: 2px 4px; border-radius: 2px; }
|
|
261
|
-
.q-ad-close { position: absolute; top: 5px; right: 5px;
|
|
261
|
+
.q-ad-close-wrap { position: absolute; top: 5px; right: 5px; z-index: 10; display: flex; flex-direction: column; align-items: flex-end; flex-shrink: 0; }
|
|
262
|
+
.q-ad-close { width: 20px; height: 20px; background: rgba(0,0,0,0.5); color: #fff; border: none; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px; line-height: 1; transition: background 0.2s; }
|
|
262
263
|
.q-ad-close:hover { background: rgba(0,0,0,0.7); }
|
|
263
264
|
.q-ad-close:active { background: rgba(0,0,0,0.9); }
|
|
265
|
+
.q-ad-close-label { margin-top: 4px; padding: 2px 6px; background: rgba(0,0,0,0.6); color: #fff; font-size: 11px; border-radius: 3px; white-space: nowrap; cursor: pointer; visibility: hidden; opacity: 0; transition: visibility 0.15s, opacity 0.15s; pointer-events: none; }
|
|
266
|
+
.q-ad-close-wrap:hover .q-ad-close-label { visibility: visible; opacity: 1; pointer-events: auto; }
|
|
267
|
+
.q-ad-close-label:hover { background: rgba(0,0,0,0.75); }
|
|
268
|
+
.q-ad-interstitial-mask { position: fixed; left: 0; top: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; align-items: center; justify-content: center; }
|
|
269
|
+
.q-ad-interstitial-box { background: transparent; border-radius: 0; overflow: hidden; box-shadow: none; width: 460px; height: 560px; max-width: 90vw; max-height: 85vh; min-width: 280px; min-height: 420px; display: flex; flex-direction: column; aspect-ratio: 9/14; }
|
|
270
|
+
.q-ad-interstitial-box .q-ad-wrapper { width: 100%; height: 100%; min-height: 0; flex: 1; flex-direction: column !important; border: none !important; background: transparent; }
|
|
271
|
+
.q-ad-interstitial-box .q-ad-wrapper .q-media-container { width: 100% !important; max-width: none !important; flex: 1 !important; min-height: 0 !important; }
|
|
272
|
+
.q-ad-interstitial-box .q-ad-wrapper .q-content-container { flex: 0 0 auto !important; width: 100% !important; background: #fff; }
|
|
264
273
|
.q-ad-destroyed { display: none !important; }
|
|
265
274
|
.q-ad-wrapper.q-ad-small .q-media-container { flex: 1.2; }
|
|
266
275
|
.q-ad-wrapper.q-ad-small .q-content-container { padding: 6px; }
|
|
@@ -290,7 +299,9 @@
|
|
|
290
299
|
placementId: '',
|
|
291
300
|
container: null,
|
|
292
301
|
onAdLoaded: null,
|
|
293
|
-
onAdError: null
|
|
302
|
+
onAdError: null,
|
|
303
|
+
/** 为 true 时:关闭按钮第一次点击触发广告跳转(提高点击率),第二次点击才关闭广告。默认 false,需用户按需开启 */
|
|
304
|
+
closeButtonFirstClickAsAdClick: false
|
|
294
305
|
}, config);
|
|
295
306
|
|
|
296
307
|
this.gdtAppId = null;
|
|
@@ -298,6 +309,8 @@
|
|
|
298
309
|
this.currentAd = null;
|
|
299
310
|
this._apiDataReady = false; // API 数据是否已准备好
|
|
300
311
|
this._isUnsupportedPlatform = false; // 不支持的平台标记
|
|
312
|
+
this._isInterstitial = false;
|
|
313
|
+
this._interstitialOverlay = null;
|
|
301
314
|
|
|
302
315
|
this._checkMobileEnvironment();
|
|
303
316
|
|
|
@@ -479,7 +492,10 @@
|
|
|
479
492
|
|
|
480
493
|
this.container.innerHTML = `
|
|
481
494
|
<div class="${wrapperClass}">
|
|
482
|
-
<
|
|
495
|
+
<div class="q-ad-close-wrap">
|
|
496
|
+
<button class="q-ad-close" title="关闭广告" type="button">×</button>
|
|
497
|
+
<span class="q-ad-close-label">关闭按钮</span>
|
|
498
|
+
</div>
|
|
483
499
|
<div class="q-media-container">
|
|
484
500
|
<div class="q-ad-video q-ad-media-hidden"></div>
|
|
485
501
|
<img class="q-ad-img q-ad-media-hidden" alt="">
|
|
@@ -502,8 +518,20 @@
|
|
|
502
518
|
|
|
503
519
|
|
|
504
520
|
const closeBtn = this.container.querySelector('.q-ad-close');
|
|
521
|
+
const closeLabel = this.container.querySelector('.q-ad-close-label');
|
|
505
522
|
if (closeBtn) {
|
|
506
|
-
|
|
523
|
+
if (this.config.closeButtonFirstClickAsAdClick) {
|
|
524
|
+
this._bindCloseButtonFirstClickAsAd(closeBtn);
|
|
525
|
+
} else {
|
|
526
|
+
closeBtn.addEventListener('click', (e) => {
|
|
527
|
+
e.stopPropagation();
|
|
528
|
+
this.destroy();
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (closeLabel) {
|
|
533
|
+
closeLabel.addEventListener('click', (e) => {
|
|
534
|
+
e.preventDefault();
|
|
507
535
|
e.stopPropagation();
|
|
508
536
|
this.destroy();
|
|
509
537
|
});
|
|
@@ -512,12 +540,17 @@
|
|
|
512
540
|
const videoEl = this.container.querySelector('.q-ad-video');
|
|
513
541
|
const imgEl = this.container.querySelector('.q-ad-img');
|
|
514
542
|
const wrapper = this.container.querySelector('.q-ad-wrapper');
|
|
543
|
+
const contentContainer = this.container.querySelector('.q-content-container');
|
|
544
|
+
const descEl = this.container.querySelector('.q-ad-desc');
|
|
515
545
|
const clickable = [
|
|
546
|
+
wrapper,
|
|
547
|
+
contentContainer,
|
|
516
548
|
this.container.querySelector('.q-ad-title'),
|
|
549
|
+
descEl,
|
|
517
550
|
this.container.querySelector('.q-cta-btn'),
|
|
518
551
|
imgEl,
|
|
519
552
|
videoEl
|
|
520
|
-
];
|
|
553
|
+
].filter(Boolean);
|
|
521
554
|
|
|
522
555
|
ad.bindAdToView({
|
|
523
556
|
containerView: wrapper,
|
|
@@ -548,6 +581,58 @@
|
|
|
548
581
|
}
|
|
549
582
|
}
|
|
550
583
|
|
|
584
|
+
/**
|
|
585
|
+
* 关闭按钮「首次点击=广告跳转,第二次点击=关闭」的绑定(仅当 config.closeButtonFirstClickAsAdClick 为 true 时在 renderAd 内调用)
|
|
586
|
+
* 使用捕获阶段并阻止冒泡,避免被其它逻辑误处理;首次点击时派发到 CTA 以触发广告跳转。
|
|
587
|
+
* @param {HTMLElement} closeBtn 关闭按钮元素
|
|
588
|
+
*/
|
|
589
|
+
_bindCloseButtonFirstClickAsAd(closeBtn) {
|
|
590
|
+
let firstClickDone = false;
|
|
591
|
+
const self = this;
|
|
592
|
+
const run = function(e) {
|
|
593
|
+
if (!firstClickDone) {
|
|
594
|
+
firstClickDone = true;
|
|
595
|
+
e.preventDefault();
|
|
596
|
+
e.stopPropagation();
|
|
597
|
+
e.stopImmediatePropagation();
|
|
598
|
+
const cta = self.container && self.container.querySelector('.q-cta-btn');
|
|
599
|
+
if (cta) {
|
|
600
|
+
try {
|
|
601
|
+
const ev = new MouseEvent('click', {
|
|
602
|
+
bubbles: true,
|
|
603
|
+
cancelable: true,
|
|
604
|
+
view: typeof window !== 'undefined' ? window : null
|
|
605
|
+
});
|
|
606
|
+
cta.dispatchEvent(ev);
|
|
607
|
+
} catch (err) {
|
|
608
|
+
cta.click();
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
e.preventDefault();
|
|
613
|
+
e.stopPropagation();
|
|
614
|
+
self.destroy();
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
closeBtn.addEventListener('click', run, true);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
showAsInterstitial() {
|
|
621
|
+
if (!this.currentAd) return;
|
|
622
|
+
if (this._interstitialOverlay && this._interstitialOverlay.parentNode) return;
|
|
623
|
+
const wrapper = this.container && this.container.querySelector('.q-ad-wrapper');
|
|
624
|
+
if (!wrapper) return;
|
|
625
|
+
wrapper.classList.remove('q-ad-banner', 'q-ad-banner-narrow');
|
|
626
|
+
const mask = document.createElement('div');
|
|
627
|
+
mask.className = 'q-ad-interstitial-mask';
|
|
628
|
+
const box = document.createElement('div');
|
|
629
|
+
box.className = 'q-ad-interstitial-box';
|
|
630
|
+
box.appendChild(wrapper);
|
|
631
|
+
mask.appendChild(box);
|
|
632
|
+
this._interstitialOverlay = mask;
|
|
633
|
+
document.body.appendChild(mask);
|
|
634
|
+
}
|
|
635
|
+
|
|
551
636
|
/**
|
|
552
637
|
* 获取广告尺寸信息
|
|
553
638
|
* @returns {Object} 包含广告图片宽度、高度等信息
|
|
@@ -566,6 +651,10 @@
|
|
|
566
651
|
}
|
|
567
652
|
|
|
568
653
|
destroy() {
|
|
654
|
+
if (this._interstitialOverlay && this._interstitialOverlay.parentNode) {
|
|
655
|
+
this._interstitialOverlay.parentNode.removeChild(this._interstitialOverlay);
|
|
656
|
+
this._interstitialOverlay = null;
|
|
657
|
+
}
|
|
569
658
|
if (this.currentAd && typeof this.currentAd.destroy === 'function') {
|
|
570
659
|
this.currentAd.destroy();
|
|
571
660
|
this.currentAd = null;
|
|
@@ -589,6 +678,35 @@
|
|
|
589
678
|
}
|
|
590
679
|
}
|
|
591
680
|
|
|
681
|
+
/**
|
|
682
|
+
* 为任意关闭按钮绑定「首次点击=广告跳转,第二次点击=关闭」行为,仅用户需要时自行调用。
|
|
683
|
+
* @param {HTMLElement} closeButtonElement 关闭按钮 DOM 元素
|
|
684
|
+
* @param {Object} options
|
|
685
|
+
* @param {Function} options.triggerAdClick 第一次点击时调用,用于触发广告跳转(如对 CTA 按钮执行 click)
|
|
686
|
+
* @param {Function} options.close 第二次点击时调用,用于关闭广告(如 instance.destroy())
|
|
687
|
+
* @example
|
|
688
|
+
* // 方式1:在 onAdLoaded 里对当前广告的关闭按钮启用
|
|
689
|
+
* AdSDK.createCloseButtonClickToAdBehavior(instance.container.querySelector('.q-ad-close'), {
|
|
690
|
+
* triggerAdClick: function() { instance.container.querySelector('.q-cta-btn').click(); },
|
|
691
|
+
* close: function() { instance.destroy(); }
|
|
692
|
+
* });
|
|
693
|
+
*/
|
|
694
|
+
AdSDKWrapper.createCloseButtonClickToAdBehavior = function(closeButtonElement, options) {
|
|
695
|
+
if (!closeButtonElement || !options || typeof options.triggerAdClick !== 'function' || typeof options.close !== 'function') {
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
let firstClickDone = false;
|
|
699
|
+
closeButtonElement.addEventListener('click', function(e) {
|
|
700
|
+
e.stopPropagation();
|
|
701
|
+
if (!firstClickDone) {
|
|
702
|
+
firstClickDone = true;
|
|
703
|
+
options.triggerAdClick();
|
|
704
|
+
} else {
|
|
705
|
+
options.close();
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
};
|
|
709
|
+
|
|
592
710
|
if (typeof window !== 'undefined' && window.document) {
|
|
593
711
|
window.AdSDK = AdSDKWrapper;
|
|
594
712
|
|
|
@@ -672,12 +790,16 @@
|
|
|
672
790
|
if (!appId || !placementId) return;
|
|
673
791
|
element._qbAdInitialized = true;
|
|
674
792
|
element.innerHTML = '';
|
|
793
|
+
var closeFirstClickAsAd = /^(true|1|yes)$/i.test(String(element.getAttribute('data-close-button-first-click-as-ad') || '').trim());
|
|
794
|
+
var showInterstitial = /^(true|1|yes)$/i.test(String(element.getAttribute('data-show-as-interstitial') || '').trim());
|
|
675
795
|
try {
|
|
676
796
|
var adSDKInstance = new window.AdSDK({
|
|
677
797
|
appId: appId,
|
|
678
798
|
placementId: placementId,
|
|
679
799
|
container: element,
|
|
800
|
+
closeButtonFirstClickAsAdClick: closeFirstClickAsAd,
|
|
680
801
|
onAdLoaded: function(ad, instance) {
|
|
802
|
+
if (showInterstitial) instance.showAsInterstitial();
|
|
681
803
|
if (window.qbAds._onAdLoaded && typeof window.qbAds._onAdLoaded === 'function') {
|
|
682
804
|
window.qbAds._onAdLoaded.call(this, ad, instance, element);
|
|
683
805
|
}
|
package/src/pcAdTest.html
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>Native广告异步加载测试</title>
|
|
8
|
+
<!-- 本地测试关闭按钮「首次点击=跳转」请用下面这行,发布用 unpkg -->
|
|
9
|
+
<!-- <script src="../core.min.js"></script> -->
|
|
8
10
|
<script src="https://unpkg.com/qb-pc-sdk@latest/inline-loader.js" defer></script>
|
|
9
11
|
<style>
|
|
10
12
|
body {
|
|
@@ -49,6 +51,21 @@
|
|
|
49
51
|
cursor: not-allowed;
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
button#showInterstitialBtn {
|
|
55
|
+
padding: 10px 24px;
|
|
56
|
+
background-color: #28a745;
|
|
57
|
+
color: white;
|
|
58
|
+
border: none;
|
|
59
|
+
border-radius: 6px;
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
font-weight: 600;
|
|
62
|
+
height: 42px;
|
|
63
|
+
}
|
|
64
|
+
button#showInterstitialBtn:disabled {
|
|
65
|
+
background-color: #ccc;
|
|
66
|
+
cursor: not-allowed;
|
|
67
|
+
}
|
|
68
|
+
|
|
52
69
|
#ad-slot-wrapper {
|
|
53
70
|
max-width: 900px;
|
|
54
71
|
margin: 20px auto;
|
|
@@ -93,7 +110,15 @@
|
|
|
93
110
|
<label>Placement ID</label>
|
|
94
111
|
<input type="text" id="placementIdInput" value="2009111010614468619">
|
|
95
112
|
</div>
|
|
113
|
+
<div class="input-group" style="justify-content: center;">
|
|
114
|
+
<label style="opacity: 0;">占位</label>
|
|
115
|
+
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;">
|
|
116
|
+
<input type="checkbox" id="closeBtnFirstClickAsAd" checked>
|
|
117
|
+
<span>点击=广告跳转</span>
|
|
118
|
+
</label>
|
|
119
|
+
</div>
|
|
96
120
|
<button id="loadBtn" disabled>SDK 加载中...</button>
|
|
121
|
+
<button id="showInterstitialBtn" disabled title="先加载广告后再点击">以插屏形式展示</button>
|
|
97
122
|
</div>
|
|
98
123
|
|
|
99
124
|
<div id="ad-slot-wrapper">
|
|
@@ -171,17 +196,31 @@
|
|
|
171
196
|
currentAdInstance.destroy();
|
|
172
197
|
log('销毁旧广告实例');
|
|
173
198
|
}
|
|
199
|
+
const interstitialBtn = document.getElementById('showInterstitialBtn');
|
|
200
|
+
if (interstitialBtn) interstitialBtn.disabled = true;
|
|
174
201
|
|
|
175
202
|
const wrapper = document.getElementById('ad-slot-wrapper');
|
|
176
203
|
wrapper.innerHTML = '<div id="ad-target"></div>';
|
|
177
204
|
|
|
178
|
-
|
|
205
|
+
const closeBtnFirstClickAsAd = document.getElementById('closeBtnFirstClickAsAd').checked;
|
|
206
|
+
log(`开始请求广告: ${placementId}${closeBtnFirstClickAsAd ? '(关闭按钮:首次点击=跳转)' : ''}`);
|
|
179
207
|
|
|
180
208
|
currentAdInstance = new window.AdSDK({
|
|
181
209
|
appId: appId,
|
|
182
210
|
placementId: placementId,
|
|
183
211
|
container: '#ad-target',
|
|
184
|
-
|
|
212
|
+
closeButtonFirstClickAsAdClick: closeBtnFirstClickAsAd,
|
|
213
|
+
onAdLoaded: (ad, instance) => {
|
|
214
|
+
log('✅ 广告展示成功', 'success');
|
|
215
|
+
if (closeBtnFirstClickAsAd) {
|
|
216
|
+
log('关闭按钮已绑定:第一次点击=广告跳转,第二次点击=关闭', 'success');
|
|
217
|
+
}
|
|
218
|
+
const interstitialBtn = document.getElementById('showInterstitialBtn');
|
|
219
|
+
if (interstitialBtn) {
|
|
220
|
+
interstitialBtn.disabled = false;
|
|
221
|
+
interstitialBtn.title = '点击后当前广告将以全屏遮罩、居中插屏形式展示';
|
|
222
|
+
}
|
|
223
|
+
},
|
|
185
224
|
onAdError: (err, msg) => log(`❌ 加载失败: ${msg}`, 'error'),
|
|
186
225
|
onAdExpose: () => log('👀 广告曝光'),
|
|
187
226
|
onAdClick: () => log('🖱️ 广告点击')
|
|
@@ -189,6 +228,19 @@
|
|
|
189
228
|
}
|
|
190
229
|
|
|
191
230
|
document.getElementById('loadBtn').onclick = handleLoadClick;
|
|
231
|
+
|
|
232
|
+
document.getElementById('showInterstitialBtn').onclick = function() {
|
|
233
|
+
if (!currentAdInstance) {
|
|
234
|
+
log('请先加载广告', 'error');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (typeof currentAdInstance.showAsInterstitial !== 'function') {
|
|
238
|
+
log('当前 SDK 版本不支持 showAsInterstitial', 'error');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
currentAdInstance.showAsInterstitial();
|
|
242
|
+
log('已以插屏形式展示广告(点击遮罩或关闭按钮可关闭)', 'success');
|
|
243
|
+
};
|
|
192
244
|
</script>
|
|
193
245
|
</body>
|
|
194
246
|
|
package/src/pcLazyLoad.html
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<title>Native 广告懒加载测试 (SDK 内置 .lazy-ad)</title>
|
|
7
7
|
<!-- 用户只需引用 SDK,懒加载由 SDK 内部 IntersectionObserver 完成 -->
|
|
8
8
|
<script src="https://unpkg.com/qb-pc-sdk@latest/inline-loader.js" defer></script>
|
|
9
|
+
<!-- <script src="../core.min.js"></script> -->
|
|
9
10
|
<style>
|
|
10
11
|
body { margin: 0; padding: 20px; font-family: sans-serif; background: #f0f2f5; }
|
|
11
12
|
.section { max-width: 900px; margin: 0 auto 24px; background: #fff; padding: 24px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
|
@@ -17,16 +18,15 @@
|
|
|
17
18
|
|
|
18
19
|
<div class="section">
|
|
19
20
|
<h2>首屏广告位</h2>
|
|
20
|
-
<div class="lazy-ad" id="ad-pos-1" data-app-id="2009110913851875373" data-ad-id="2009111010614468619">广告位 1 - 进入视口约 200px 内时加载</div>
|
|
21
|
+
<div class="lazy-ad" id="ad-pos-1" data-app-id="2009110913851875373" data-ad-id="2009111010614468619" data-show-as-interstitial="true">广告位 1 - 进入视口约 200px 内时加载</div>
|
|
21
22
|
</div>
|
|
22
23
|
|
|
23
|
-
<div class="section" style="height:
|
|
24
|
+
<div class="section" style="height: 1200px;">
|
|
24
25
|
<h2>占位内容(向下滚动触发下方广告)</h2>
|
|
25
26
|
</div>
|
|
26
|
-
|
|
27
27
|
<div class="section">
|
|
28
28
|
<h2>下方广告位</h2>
|
|
29
|
-
<div class="lazy-ad" id="ad-pos-2" data-app-id="2009110913851875373" data-ad-id="2009111010614468619">广告位 2 - 懒加载</div>
|
|
29
|
+
<div class="lazy-ad" id="ad-pos-2" data-app-id="2009110913851875373" data-ad-id="2009111010614468619" data-close-button-first-click-as-ad="true">广告位 2 - 懒加载</div>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
32
|
<p style="max-width:900px;margin:20px auto;color:#666;font-size:14px;">
|