Browse Source

feat: 添加广告位功能并优化tab-bar显示逻辑

- 实现瀑布流布局中的广告位展示
- 添加完整卡片广告(full_card)和半高图片广告(half_image)两种样式
- 修复筛选逻辑确保广告位正常显示
- 优化tab-bar默认显示,移除动态隐藏逻辑
- 添加广告点击事件处理
- 创建统一的广告配置管理
pull/1/head
徐飞洋 2 months ago
parent
commit
9ac82f8557
  1. 23
      custom-tab-bar/index.js
  2. BIN
      images/轮播图1.jpg
  3. BIN
      images/轮播图2.jpg
  4. 102
      pages/index/index.js
  5. 32
      pages/index/index.wxml
  6. 48
      pages/index/index.wxss
  7. 38
      utils/ad-config.js

23
custom-tab-bar/index.js

@ -10,12 +10,11 @@ Component({
*/
data: {
selected: 'index',
show: true, // 控制tab-bar显示状态
badges: {}, // 存储各tab的未读标记
// 记录tabBar数据,用于匹配
show: true,
badges: {},
tabBarItems: [
{ key: 'index', route: 'pages/index/index' },
{ key: 'chat', route: 'pages/chat/index', badgeKey: 'chat' }, // 消息中心
{ key: 'chat', route: 'pages/chat/index', badgeKey: 'chat' },
{ key: 'settlement', route: 'pages/settlement/index' },
{ key: 'profile', route: 'pages/profile/index' }
]
@ -261,31 +260,17 @@ Component({
}
},
// 开始监听全局tab-bar显示状态变化
startTabBarStatusListener() {
// 使用定时器定期检查全局状态
this.tabBarStatusTimer = setInterval(() => {
try {
const app = getApp()
if (app && app.globalData) {
// 检查显示状态
if (typeof app.globalData.showTabBar !== 'undefined') {
const showTabBar = app.globalData.showTabBar
if (this.data.show !== showTabBar) {
this.setData({
show: showTabBar
})
console.log('tab-bar显示状态更新:', showTabBar)
}
}
// 更新未读标记
this.updateBadges()
}
} catch (e) {
console.error('监听tab-bar状态失败:', e)
}
}, 100) // 每100ms检查一次,确保响应迅速
}, 100)
}
},

BIN
images/轮播图1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/轮播图2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

102
pages/index/index.js

@ -308,6 +308,10 @@ Page({
newGoods = newGoods.filter(item => (item.status || '').toLowerCase() !== 'hidden')
if (!isLoadMore && newGoods.length > 0) {
newGoods = this.insertAdSlots(newGoods)
}
let updatedGoods = []
if (isLoadMore) {
const existingIds = new Set(this.data.goods.map(item => item.id));
@ -318,7 +322,15 @@ Page({
}
const filteredGoods = this.applyFilters(updatedGoods)
console.log('filteredGoods 数量:', filteredGoods.length)
console.log('filteredGoods[0]:', filteredGoods[0])
console.log('filteredGoods[1]:', filteredGoods[1])
const { leftColumnGoods, rightColumnGoods } = this.distributeToColumns(filteredGoods)
console.log('leftColumnGoods 数量:', leftColumnGoods.length)
console.log('rightColumnGoods 数量:', rightColumnGoods.length)
console.log('leftColumnGoods[0]:', leftColumnGoods[0])
console.log('rightColumnGoods[0]:', rightColumnGoods[0])
this.setData({
goods: updatedGoods,
@ -331,24 +343,62 @@ Page({
})
},
// 瀑布流布局:将商品分配到左右两列实现真正的高度自适应
distributeToColumns: function(goods) {
if (!goods || goods.length === 0) {
return { leftColumnGoods: [], rightColumnGoods: [] }
// 插入广告位数据
insertAdSlots: function(goods) {
if (!goods || goods.length === 0) return goods
console.log('insertAdSlots 被调用,商品数量:', goods.length)
const adSlot1 = {
id: 'ad_slot_1',
name: '广告位1',
imageUrls: ['/images/轮播图1.jpg'],
price: 0,
adType: 'full_card',
isAd: true
}
const leftColumn = []
const rightColumn = []
const adSlot2 = {
id: 'ad_slot_2',
name: '广告位2',
imageUrls: ['/images/轮播图1.jpg'],
price: 0,
adType: 'half_image',
isAd: true
}
for (let i = 0; i < goods.length; i++) {
if (i % 2 === 0) {
leftColumn.push(goods[i])
} else {
rightColumn.push(goods[i])
const result = [adSlot1, adSlot2, ...goods]
console.log('插入广告后的商品数量:', result.length)
console.log('第一个商品:', result[0])
console.log('第二个商品:', result[1])
return result
},
// 广告点击事件处理
onAdClick: function(e) {
const adData = e.currentTarget.dataset.ad
console.log('广告被点击, 广告ID:', adData ? adData.id : 'unknown')
if (adData && adData.adType) {
wx.showToast({
title: '广告位: ' + adData.adType,
icon: 'none',
duration: 2000
})
if (adData.adType === 'full_card') {
console.log('完整卡片广告被点击')
} else if (adData.adType === 'half_image') {
console.log('半高图片广告被点击')
}
} else {
wx.showToast({
title: '广告加载中',
icon: 'loading',
duration: 1500
})
}
return { leftColumnGoods: leftColumn, rightColumnGoods: rightColumn }
},
// 加载商品数据 - 淘宝风格优化
@ -419,19 +469,20 @@ Page({
else if (category === '红壳') keyword = '红'
else if (category === '白壳') keyword = '白'
filtered = filtered.filter(item => (item.name || '').includes(keyword))
filtered = filtered.filter(item => item.isAd || (item.name || '').includes(keyword))
}
if (this.data.searchKeyword) {
const keyword = this.data.searchKeyword.toLowerCase()
filtered = filtered.filter(item =>
item.isAd ||
(item.name || '').toLowerCase().includes(keyword) ||
(item.region || '').toLowerCase().includes(keyword)
)
}
if (this.data.selectedRegion !== '全国') {
filtered = filtered.filter(item => item.region === this.data.selectedRegion)
filtered = filtered.filter(item => item.isAd || item.region === this.data.selectedRegion)
}
filtered.sort((a, b) => {
@ -475,10 +526,6 @@ Page({
return { leftColumnGoods: leftColumn, rightColumnGoods: rightColumn }
},
})
return filtered
},
// 分组商品用于交错布局(左长右短,左短右长交替)
groupGoodsForStaggeredLayout: function(goods) {
@ -725,36 +772,21 @@ Page({
// 滚动事件处理
onScroll: function(e) {
// 获取滚动信息
const { scrollTop, scrollHeight, clientHeight } = e.detail;
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
// 获取全局状态
const app = getApp();
if (!app || !app.globalData) {
return;
}
// 当滚动到底部且没有更多数据时,隐藏tabBar
if (distanceToBottom < 100 && !this.data.hasMoreData) {
app.globalData.showTabBar = false;
}
// 当往上滚动不在底部时,立即重新显示tabBar
else {
app.globalData.showTabBar = true;
}
app.globalData.showTabBar = true;
},
// 上拉加载更多
onReachBottom: function() {
if (this.data.hasMoreData && !this.data.loadingMore) {
this.loadGoods(true)
} else if (!this.data.hasMoreData) {
// 没有更多数据时,隐藏tabBar
const app = getApp();
if (app && app.globalData) {
app.globalData.showTabBar = false;
}
}
},

32
pages/index/index.wxml

@ -170,12 +170,28 @@
<view class="waterfall-container">
<!-- 左列 -->
<view class="waterfall-column left-column">
<!-- 广告位1:完整卡片广告 (始终显示) -->
<view class="waterfall-item">
<view class="ad-card ad-full-card">
<image
class="ad-image"
src="/images/轮播图1.jpg"
mode="aspectFill"
bindtap="onAdClick"
data-ad="ad_slot_1"
></image>
<view class="ad-badge">广告</view>
</view>
</view>
<!-- 正常商品列表 -->
<view
class="waterfall-item"
wx:for="{{leftColumnGoods}}"
wx:key="id"
data-item="{{item}}"
bindtap="viewGoodsDetail"
wx:if="{{!item.isAd}}"
>
<view class="product-card">
<view class="product-image-wrapper">
@ -215,12 +231,28 @@
<!-- 右列 -->
<view class="waterfall-column right-column">
<!-- 广告位2:半高图片广告 (始终显示) -->
<view class="waterfall-item">
<view class="ad-card ad-half-image">
<image
class="ad-image-half"
src="/images/轮播图1.jpg"
mode="aspectFill"
bindtap="onAdClick"
data-ad="ad_slot_2"
></image>
<view class="ad-badge">广告</view>
</view>
</view>
<!-- 正常商品列表 -->
<view
class="waterfall-item"
wx:for="{{rightColumnGoods}}"
wx:key="id"
data-item="{{item}}"
bindtap="viewGoodsDetail"
wx:if="{{!item.isAd}}"
>
<view class="product-card">
<view class="product-image-wrapper">

48
pages/index/index.wxss

@ -1228,6 +1228,54 @@ page {
right: 25%;
}
/* 广告位样式 */
.ad-card {
position: relative;
border-radius: 16rpx;
overflow: hidden;
background: #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
/* 完整卡片广告 */
.ad-full-card {
width: 100%;
height: 400rpx;
}
.ad-image {
width: 100%;
height: 400rpx;
}
/* 半高图片广告 */
.ad-half-image {
width: 100%;
height: 200rpx;
}
.ad-image-half {
width: 100%;
height: 200rpx;
}
/* 广告标签 */
.ad-badge {
position: absolute;
top: 16rpx;
right: 16rpx;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 6rpx;
}
/* 广告点击效果 */
.ad-card:active {
opacity: 0.85;
}
/* 空商品状态 */
.empty-goods {
display: flex;

38
utils/ad-config.js

@ -0,0 +1,38 @@
const adConfig = {
ads: [
{
id: 'ad_slot_1',
name: '广告位1',
type: 'full_card',
imageUrl: '/images/轮播图1.jpg',
link: '',
show: true
},
{
id: 'ad_slot_2',
name: '广告位2',
type: 'half_image',
imageUrl: '/images/轮播图1.jpg',
link: '',
show: true
}
],
getAdById(id) {
return this.ads.find(ad => ad.id === id && ad.show)
},
getFullCardAd() {
return this.ads.find(ad => ad.type === 'full_card' && ad.show)
},
getHalfImageAd() {
return this.ads.find(ad => ad.type === 'half_image' && ad.show)
},
getAllAds() {
return this.ads.filter(ad => ad.show)
}
}
module.exports = adConfig
Loading…
Cancel
Save