@@ -47,17 +47,19 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部CTA区域 - 橙色背景+图片叠加+二维码+文字 -->
|
||||
<!-- 底部CTA区域 - 图片底+橙色叠加层+内容层 -->
|
||||
<view class="cta-footer">
|
||||
<!-- 橙色背景层 -->
|
||||
<!-- 图片底层 - image_26原图 -->
|
||||
<image class="cta-overlay-img" src="/static/images/home/image_26_1496_1761.png" mode="widthFix"></image>
|
||||
<!-- 橙色叠加层 - 在图片上方, 高不透明度让橙色更亮更突出 -->
|
||||
<view class="cta-orange-bg"></view>
|
||||
<!-- 图片叠加层 -->
|
||||
<image
|
||||
class="cta-overlay-img"
|
||||
src="/static/images/home/image_26_1496_1761.png"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
<!-- 二维码 -->
|
||||
<!-- 内容层 -->
|
||||
<view class="cta-content">
|
||||
<!-- 长按识别 196×20px → 377×38rpx, 14px Medium white -->
|
||||
<text class="cta-tip">长按识别二维码,添加经理微信</text>
|
||||
<!-- 装饰箭头图标 19×10px → 37×19rpx -->
|
||||
<image class="cta-arrow" src="/static/icons/home/icon_arrow_down.png" mode="aspectFit"></image>
|
||||
<!-- 二维码 104×104px → 200×200rpx, 圆角10px → 19rpx -->
|
||||
<view class="qr-wrap">
|
||||
<image
|
||||
class="qr-img"
|
||||
@@ -65,14 +67,21 @@
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
</view>
|
||||
<!-- 联系我们文字图 -->
|
||||
<!-- 电话栏 200×45px → 385×87rpx, #000 0.1透明, 圆角10px → 19rpx -->
|
||||
<view class="phone-pill">
|
||||
<image class="phone-icon" src="/static/icons/home/icon_phone.svg" mode="aspectFit"></image>
|
||||
<text class="phone-text">15999928161</text>
|
||||
<image class="phone-icon" src="/static/icons/home/icon_wechat.svg" mode="aspectFit"></image>
|
||||
</view>
|
||||
<!-- 联系我们 - 用户提供的image.png -->
|
||||
<image
|
||||
class="cta-text-img"
|
||||
src="/static/images/home/image_28_1498_1767.png"
|
||||
src="/static/images/home/contact_us.png"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -238,61 +247,102 @@ export default {
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
/* 底部CTA - 橙色背景+图片叠加+二维码+文字 */
|
||||
/* 底部CTA - 橙色背景层+图片叠加层+内容层 */
|
||||
.cta-footer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
width: 750rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* 橙色背景层 - 391x200 */
|
||||
/* 图片底层 - image_26原图 */
|
||||
.cta-overlay-img {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
display: block;
|
||||
}
|
||||
/* 橙色叠加层 - 在图片上方, 0.8高不透明度让亮橙色突出 */
|
||||
.cta-orange-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
height: 100%;
|
||||
background: #ff6800;
|
||||
z-index: 0;
|
||||
}
|
||||
/* 图片叠加层 - 390x219 */
|
||||
.cta-overlay-img {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
opacity: 0.85;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
}
|
||||
/* 二维码 - 104x104 居中 圆角10px 白底 */
|
||||
.qr-wrap {
|
||||
/* 内容层 - absolute覆盖图片和橙色层, flex column 居中 */
|
||||
.cta-content {
|
||||
position: absolute;
|
||||
top: 54rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 208rpx;
|
||||
height: 208rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 33rpx; /* 17px → 33rpx */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* 长按识别 14px Medium white → 27rpx */
|
||||
.cta-tip {
|
||||
font-size: 27rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 38rpx;
|
||||
}
|
||||
/* 装饰箭头图标 19×10px → 37×19rpx */
|
||||
.cta-arrow {
|
||||
width: 37rpx;
|
||||
height: 19rpx;
|
||||
margin-top: 8rpx; /* 4px → 8rpx */
|
||||
}
|
||||
/* 二维码 104×104px → 200×200rpx, 圆角10px → 19rpx */
|
||||
.qr-wrap {
|
||||
margin-top: 13rpx; /* 7px → 13rpx */
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 19rpx;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.qr-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/* 联系我们文字图 - 236x78 居中 */
|
||||
/* 电话栏 200×45px → 385×87rpx, #000 0.1透明, 圆角10px → 19rpx */
|
||||
.phone-pill {
|
||||
margin-top: 23rpx; /* 12px → 23rpx */
|
||||
width: 385rpx;
|
||||
height: 87rpx;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 19rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.phone-icon {
|
||||
width: 35rpx; /* 18px → 35rpx */
|
||||
height: 35rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.phone-text {
|
||||
font-size: 23rpx; /* 12px → 23rpx */
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
/* 联系我们 - 用户提供的image.png */
|
||||
.cta-text-img {
|
||||
position: absolute;
|
||||
top: 256rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 472rpx;
|
||||
z-index: 3;
|
||||
margin-top: 19rpx; /* 10px → 19rpx */
|
||||
width: 569rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,7 +18,33 @@ export default {
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 首次测量(可能为 0,因为 v-if 可能为 false)
|
||||
this.$nextTick(() => this.emitHeight())
|
||||
},
|
||||
watch: {
|
||||
// 筛选标签增减 → 高度变化 → 重新测量
|
||||
'list.length'() {
|
||||
this.$nextTick(() => this.emitHeight())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emitHeight() {
|
||||
// v-if 为 false 时 #activeFilters 不存在,返回 0
|
||||
if (!this.list || this.list.length === 0) {
|
||||
this.$emit('height-change', 0)
|
||||
return
|
||||
}
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
query.select('#activeFilters').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res && res[0]) {
|
||||
this.$emit('height-change', res[0].height)
|
||||
} else {
|
||||
this.$emit('height-change', 0)
|
||||
}
|
||||
})
|
||||
},
|
||||
onRemove(key) {
|
||||
this.$emit('remove', key)
|
||||
},
|
||||
|
||||
@@ -30,7 +30,26 @@ export default {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 首次测量
|
||||
this.$nextTick(() => this.emitHeight())
|
||||
},
|
||||
watch: {
|
||||
// 国家列表变化 → 换行行数可能变化 → 重新测量
|
||||
'list.length'() {
|
||||
this.$nextTick(() => this.emitHeight())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emitHeight() {
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
query.select('#countryBar').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res && res[0]) {
|
||||
this.$emit('height-change', res[0].height)
|
||||
}
|
||||
})
|
||||
},
|
||||
selectItem(item) {
|
||||
this.$emit('select', item.id)
|
||||
}
|
||||
|
||||
@@ -81,7 +81,33 @@ export default {
|
||||
// 商品滚动区固定高度(px),由父组件动态计算传入
|
||||
scrollHeight: { type: Number, default: 400 }
|
||||
},
|
||||
mounted() {
|
||||
// 首次测量子分类高度
|
||||
this.$nextTick(() => this.emitSubHeight())
|
||||
},
|
||||
watch: {
|
||||
// 子分类列表变化 → 重新测量
|
||||
'subCategories.length'() {
|
||||
this.$nextTick(() => this.emitSubHeight())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emitSubHeight() {
|
||||
// v-if 为 false 时 #subCategories 不存在,返回 0
|
||||
if (!this.subCategories || this.subCategories.length === 0) {
|
||||
this.$emit('sub-height-change', 0)
|
||||
return
|
||||
}
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
query.select('#subCategories').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res && res[0]) {
|
||||
this.$emit('sub-height-change', res[0].height)
|
||||
} else {
|
||||
this.$emit('sub-height-change', 0)
|
||||
}
|
||||
})
|
||||
},
|
||||
selectSub(id) { this.$emit('sub-select', id) },
|
||||
onTapProduct(item) { this.$emit('product-click', item) },
|
||||
onScrollToLower() { this.$emit('scroll-to-lower') }
|
||||
|
||||
@@ -41,7 +41,20 @@ export default {
|
||||
this.statusBarHeight = 20
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 测量自身高度并 emit 给父组件(小程序端无法跨组件查询 DOM,必须自测量)
|
||||
this.$nextTick(() => this.emitHeight())
|
||||
},
|
||||
methods: {
|
||||
emitHeight() {
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
query.select('#searchBar').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res && res[0]) {
|
||||
this.$emit('height-change', res[0].height)
|
||||
}
|
||||
})
|
||||
},
|
||||
onInput(e) {
|
||||
this.$emit('input', e.detail.value)
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
@input="onSearchInput"
|
||||
@blur="onSearchBlur"
|
||||
@filter="toggleFilter"
|
||||
@height-change="onSearchBarHeight"
|
||||
/>
|
||||
|
||||
<!-- 国家选择条 -->
|
||||
@@ -14,6 +15,7 @@
|
||||
:list="countries"
|
||||
:selected-id="selectedCountry"
|
||||
@select="selectCountry"
|
||||
@height-change="onCountryBarHeight"
|
||||
/>
|
||||
|
||||
<!-- 主体内容:左侧分类侧边栏(固定宽度) + 右侧内容区(自动剩余宽度) -->
|
||||
@@ -32,6 +34,7 @@
|
||||
:list="activeFilters"
|
||||
@remove="removeFilter"
|
||||
@clear-all="clearAllFilters"
|
||||
@height-change="onActiveFiltersHeight"
|
||||
/>
|
||||
|
||||
<!-- 产品列表(内含子分类条件+滚动商品) -->
|
||||
@@ -46,6 +49,7 @@
|
||||
@sub-select="selectSubCategory"
|
||||
@product-click="goDetail"
|
||||
@scroll-to-lower="onScrollToLower"
|
||||
@sub-height-change="onSubCategoriesHeight"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
@@ -83,6 +87,16 @@ export default {
|
||||
ProductGrid,
|
||||
FilterDrawer
|
||||
},
|
||||
watch: {
|
||||
// 筛选标签增减 → 子组件会自测量并 emit,父组件这里不需要 watch
|
||||
// 保留一个兜底:activeFilters.length 变化时主动触发一次重算
|
||||
'activeFilters.length'() {
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
'subCategories.length'() {
|
||||
this.recomputeScrollHeight()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchKeyword: '',
|
||||
@@ -110,25 +124,33 @@ export default {
|
||||
products: [],
|
||||
windowHeight: 667,
|
||||
scrollTopVal: 0,
|
||||
productScrollHeight: 400 // 商品滚动区高度(px),动态计算
|
||||
productScrollHeight: 400, // 商品滚动区高度(px),由子组件测量后动态计算
|
||||
// 各子组件上报的高度(px),默认 0
|
||||
_searchBarH: 0,
|
||||
_countryBarH: 0,
|
||||
_activeFiltersH: 0,
|
||||
_subCategoriesH: 0
|
||||
}
|
||||
},
|
||||
async onLoad() {
|
||||
try {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
// windowHeight 已自动扣除 uni-app 默认导航栏 & TabBar 高度
|
||||
// 当前页是 navigationStyle:custom + TabBar 页,正好匹配可视区
|
||||
this.windowHeight = sysInfo.windowHeight || 667
|
||||
// tabBar 页 + navigationStyle:custom 时,windowHeight 在不同平台/版本可能不扣 tabBar
|
||||
// 改用 screenHeight - tabBarHeight 计算,确保可视区高度正确
|
||||
const tabBarHeight = sysInfo.tabBarHeight || 50
|
||||
this.windowHeight = (sysInfo.screenHeight || 750) - tabBarHeight
|
||||
console.log('[onLoad] screenHeight=' + sysInfo.screenHeight +
|
||||
', tabBarHeight=' + tabBarHeight +
|
||||
' → windowHeight=' + this.windowHeight)
|
||||
} catch (e) {
|
||||
this.windowHeight = 667
|
||||
}
|
||||
await this.initData()
|
||||
this.loadSubCategories('all')
|
||||
await this.loadGoods(1)
|
||||
// 首屏数据渲染完成后计算滚动区高度
|
||||
this.$nextTick(() => {
|
||||
this.calcScrollHeight()
|
||||
})
|
||||
// 首屏数据渲染完成后,子组件会通过 mounted 自行测量并 emit 高度
|
||||
// 这里兜底触发一次重算(防止某些端 mounted 比父组件 onLoad 晚)
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
methods: {
|
||||
async initData() {
|
||||
@@ -259,10 +281,8 @@ export default {
|
||||
this.hasMore = this.products.length < total
|
||||
this.loadingMore = false
|
||||
|
||||
// 数据变更后重算滚动区高度(筛选标签/子分类数量变化会影响上方占位高度)
|
||||
this.$nextTick(() => {
|
||||
this.calcScrollHeight()
|
||||
})
|
||||
// 数据变更后兜底重算滚动区高度(子组件会自行 emit,这里兜底)
|
||||
this.recomputeScrollHeight()
|
||||
|
||||
console.log(
|
||||
'[loadGoods] total=' + total +
|
||||
@@ -364,38 +384,46 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* 动态计算商品滚动区高度(px)。
|
||||
* 用 createSelectorQuery 测量 SearchBar / CountryBar / ActiveFilters / subCategories 的实际高度,
|
||||
* 用 windowHeight 依次减去,得到 scroll-view 可用的固定高度。
|
||||
* 子组件高度上报回调 —— 每个子组件在 mounted / 内容变化时自行测量 DOM 高度,
|
||||
* 通过 @height-change 事件上报给父组件。父组件汇总后重算滚动区高度。
|
||||
*
|
||||
* 这种方式解决了 uni-app 小程序端 createSelectorQuery 无法跨组件查询 DOM 的问题:
|
||||
* H5 端 DOM 全局可查,但小程序每个组件有独立节点树,页面级 select 选不到子组件内部的节点。
|
||||
*/
|
||||
onSearchBarHeight(h) {
|
||||
this._searchBarH = h
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
onCountryBarHeight(h) {
|
||||
this._countryBarH = h
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
onActiveFiltersHeight(h) {
|
||||
this._activeFiltersH = h
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
onSubCategoriesHeight(h) {
|
||||
this._subCategoriesH = h
|
||||
this.recomputeScrollHeight()
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据 4 个子组件上报的高度,计算 scroll-view 可用的固定高度。
|
||||
* —— 完全符合 uni-app / 微信小程序官方文档「scroll-y 需给固定 height」的要求。
|
||||
*/
|
||||
calcScrollHeight() {
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
// 分别测量 4 个元素的 boundingClientRect
|
||||
query.select('#searchBar').boundingClientRect()
|
||||
query.select('#countryBar').boundingClientRect()
|
||||
query.select('#activeFilters').boundingClientRect()
|
||||
query.select('#subCategories').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
// res[0]=searchBar, res[1]=countryBar, res[2]=activeFilters, res[3]=subCategories
|
||||
// 注意:v-if 为 false 时 res[i] 可能为 null
|
||||
const searchBarH = res[0] ? res[0].height : 0
|
||||
const countryBarH = res[1] ? res[1].height : 0
|
||||
const activeFiltersH = res[2] ? res[2].height : 0
|
||||
const subCategoriesH = res[3] ? res[3].height : 0
|
||||
|
||||
const totalUsed = searchBarH + countryBarH + activeFiltersH + subCategoriesH
|
||||
recomputeScrollHeight() {
|
||||
const totalUsed = this._searchBarH + this._countryBarH +
|
||||
this._activeFiltersH + this._subCategoriesH
|
||||
let h = this.windowHeight - totalUsed
|
||||
// 最小值保护:至少 200px,避免极端情况
|
||||
if (h < 200) h = 200
|
||||
if (h > this.windowHeight) h = this.windowHeight
|
||||
|
||||
this.productScrollHeight = Math.round(h)
|
||||
console.log('[calcScrollHeight] windowHeight=' + this.windowHeight +
|
||||
', searchBar=' + searchBarH + ', countryBar=' + countryBarH +
|
||||
', activeFilters=' + activeFiltersH + ', subCategories=' + subCategoriesH +
|
||||
console.log('[recomputeScrollHeight] windowHeight=' + this.windowHeight +
|
||||
', searchBar=' + this._searchBarH + ', countryBar=' + this._countryBarH +
|
||||
', activeFilters=' + this._activeFiltersH + ', subCategories=' + this._subCategoriesH +
|
||||
' → scrollHeight=' + this.productScrollHeight)
|
||||
})
|
||||
},
|
||||
|
||||
async selectCountry(id) {
|
||||
|
||||
|
After Width: | Height: | Size: 944 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.898 16.875H12.8215C11.0215 16.7805 8.59034 14.9985 6.31559 12.1117L5.47634 11.052C3.20159 8.16525 2.01021 5.34487 2.29034 3.51113C2.48609 2.21738 4.31871 1.125 5.36609 1.125C5.88134 1.125 6.06921 1.39388 6.13671 1.55588C6.72509 2.664 7.45859 4.58663 7.46421 5.27625V5.32463L7.44734 5.37075C7.31571 5.733 7.02434 5.90625 6.76559 6.06038C6.42471 6.26288 6.23234 6.3945 6.20759 6.77587C6.20196 6.89062 6.29646 7.41825 7.79608 9.35775L8.43734 10.1711C9.94258 12.0364 10.4151 12.2366 10.5242 12.2524C10.8876 12.3075 11.0608 12.1444 11.3207 11.8418C11.5187 11.6089 11.7437 11.3512 12.1138 11.295L12.1633 11.286L12.2083 11.3017C12.8653 11.4424 14.5371 12.5764 15.4933 13.4201C15.6283 13.5146 15.868 13.8004 15.679 14.427C15.382 15.4114 14.0848 16.875 12.898 16.875Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 890 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.898 16.875H12.8215C11.0215 16.7805 8.59034 14.9985 6.31559 12.1117L5.47634 11.052C3.20159 8.16525 2.01021 5.34487 2.29034 3.51113C2.48609 2.21738 4.31871 1.125 5.36609 1.125C5.88134 1.125 6.06921 1.39388 6.13671 1.55588C6.72509 2.664 7.45859 4.58663 7.46421 5.27625V5.32463L7.44734 5.37075C7.31571 5.733 7.02434 5.90625 6.76559 6.06038C6.42471 6.26288 6.23234 6.3945 6.20759 6.77587C6.20196 6.89062 6.29646 7.41825 7.79608 9.35775L8.43734 10.1711C9.94258 12.0364 10.4151 12.2366 10.5242 12.2524C10.8876 12.3075 11.0608 12.1444 11.3207 11.8418C11.5187 11.6089 11.7437 11.3512 12.1138 11.295L12.1633 11.286L12.2083 11.3017C12.8653 11.4424 14.5371 12.5764 15.4933 13.4201C15.6283 13.5146 15.868 13.8004 15.679 14.427C15.382 15.4114 14.0848 16.875 12.898 16.875Z" fill="#333333"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 892 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.24985 4.5V2.25C5.24985 1.83579 5.58564 1.5 5.99985 1.5H14.9998C15.4141 1.5 15.7498 1.83579 15.7498 2.25V12.75C15.7498 13.1642 15.4141 13.5 14.9998 13.5H12.7498V15.7493C12.7498 16.1639 12.4124 16.5 11.9948 16.5H3.00499C2.58794 16.5 2.25 16.1665 2.25 15.7493L2.25195 5.25065C2.25202 4.83608 2.58948 4.5 3.00706 4.5H5.24985ZM3.75181 6L3.75014 15H11.2498V6H3.75181ZM6.74985 4.5H12.7498V12H14.2498V3H6.74985V4.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 538 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.24985 4.5V2.25C5.24985 1.83579 5.58564 1.5 5.99985 1.5H14.9998C15.4141 1.5 15.7498 1.83579 15.7498 2.25V12.75C15.7498 13.1642 15.4141 13.5 14.9998 13.5H12.7498V15.7493C12.7498 16.1639 12.4124 16.5 11.9948 16.5H3.00499C2.58794 16.5 2.25 16.1665 2.25 15.7493L2.25195 5.25065C2.25202 4.83608 2.58948 4.5 3.00706 4.5H5.24985ZM3.75181 6L3.75014 15H11.2498V6H3.75181ZM6.74985 4.5H12.7498V12H14.2498V3H6.74985V4.5Z" fill="#333333"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 540 B |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 486 KiB After Width: | Height: | Size: 3.5 MiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 616 KiB |
@@ -188,6 +188,16 @@ var _default = {
|
||||
ProductGrid: ProductGrid,
|
||||
FilterDrawer: FilterDrawer
|
||||
},
|
||||
watch: {
|
||||
// 筛选标签增减 → 子组件会自测量并 emit,父组件这里不需要 watch
|
||||
// 保留一个兜底:activeFilters.length 变化时主动触发一次重算
|
||||
'activeFilters.length': function activeFiltersLength() {
|
||||
this.recomputeScrollHeight();
|
||||
},
|
||||
'subCategories.length': function subCategoriesLength() {
|
||||
this.recomputeScrollHeight();
|
||||
}
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
searchKeyword: '',
|
||||
@@ -213,21 +223,29 @@ var _default = {
|
||||
products: [],
|
||||
windowHeight: 667,
|
||||
scrollTopVal: 0,
|
||||
productScrollHeight: 400 // 商品滚动区高度(px),动态计算
|
||||
productScrollHeight: 400,
|
||||
// 商品滚动区高度(px),由子组件测量后动态计算
|
||||
// 各子组件上报的高度(px),默认 0
|
||||
_searchBarH: 0,
|
||||
_countryBarH: 0,
|
||||
_activeFiltersH: 0,
|
||||
_subCategoriesH: 0
|
||||
};
|
||||
},
|
||||
onLoad: function onLoad() {
|
||||
var _this = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
||||
var sysInfo;
|
||||
var sysInfo, tabBarHeight;
|
||||
return _regenerator.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
try {
|
||||
sysInfo = uni.getSystemInfoSync(); // windowHeight 已自动扣除 uni-app 默认导航栏 & TabBar 高度
|
||||
// 当前页是 navigationStyle:custom + TabBar 页,正好匹配可视区
|
||||
_this.windowHeight = sysInfo.windowHeight || 667;
|
||||
sysInfo = uni.getSystemInfoSync(); // tabBar 页 + navigationStyle:custom 时,windowHeight 在不同平台/版本可能不扣 tabBar
|
||||
// 改用 screenHeight - tabBarHeight 计算,确保可视区高度正确
|
||||
tabBarHeight = sysInfo.tabBarHeight || 50;
|
||||
_this.windowHeight = (sysInfo.screenHeight || 750) - tabBarHeight;
|
||||
console.log('[onLoad] screenHeight=' + sysInfo.screenHeight + ', tabBarHeight=' + tabBarHeight + ' → windowHeight=' + _this.windowHeight);
|
||||
} catch (e) {
|
||||
_this.windowHeight = 667;
|
||||
}
|
||||
@@ -238,10 +256,9 @@ var _default = {
|
||||
_context.next = 6;
|
||||
return _this.loadGoods(1);
|
||||
case 6:
|
||||
// 首屏数据渲染完成后计算滚动区高度
|
||||
_this.$nextTick(function () {
|
||||
_this.calcScrollHeight();
|
||||
});
|
||||
// 首屏数据渲染完成后,子组件会通过 mounted 自行测量并 emit 高度
|
||||
// 这里兜底触发一次重算(防止某些端 mounted 比父组件 onLoad 晚)
|
||||
_this.recomputeScrollHeight();
|
||||
case 7:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
@@ -432,10 +449,8 @@ var _default = {
|
||||
_this4.hasMore = _this4.products.length < total;
|
||||
_this4.loadingMore = false;
|
||||
|
||||
// 数据变更后重算滚动区高度(筛选标签/子分类数量变化会影响上方占位高度)
|
||||
_this4.$nextTick(function () {
|
||||
_this4.calcScrollHeight();
|
||||
});
|
||||
// 数据变更后兜底重算滚动区高度(子组件会自行 emit,这里兜底)
|
||||
_this4.recomputeScrollHeight();
|
||||
console.log('[loadGoods] total=' + total + ', page=' + currentPage + ', items=' + products.length + ', loaded=' + _this4.products.length + ', hasMore=' + _this4.hasMore);
|
||||
_context4.next = 25;
|
||||
break;
|
||||
@@ -542,64 +557,70 @@ var _default = {
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 动态计算商品滚动区高度(px)。
|
||||
* 用 createSelectorQuery 测量 SearchBar / CountryBar / ActiveFilters / subCategories 的实际高度,
|
||||
* 用 windowHeight 依次减去,得到 scroll-view 可用的固定高度。
|
||||
* 子组件高度上报回调 —— 每个子组件在 mounted / 内容变化时自行测量 DOM 高度,
|
||||
* 通过 @height-change 事件上报给父组件。父组件汇总后重算滚动区高度。
|
||||
*
|
||||
* 这种方式解决了 uni-app 小程序端 createSelectorQuery 无法跨组件查询 DOM 的问题:
|
||||
* H5 端 DOM 全局可查,但小程序每个组件有独立节点树,页面级 select 选不到子组件内部的节点。
|
||||
*/
|
||||
onSearchBarHeight: function onSearchBarHeight(h) {
|
||||
this._searchBarH = h;
|
||||
this.recomputeScrollHeight();
|
||||
},
|
||||
onCountryBarHeight: function onCountryBarHeight(h) {
|
||||
this._countryBarH = h;
|
||||
this.recomputeScrollHeight();
|
||||
},
|
||||
onActiveFiltersHeight: function onActiveFiltersHeight(h) {
|
||||
this._activeFiltersH = h;
|
||||
this.recomputeScrollHeight();
|
||||
},
|
||||
onSubCategoriesHeight: function onSubCategoriesHeight(h) {
|
||||
this._subCategoriesH = h;
|
||||
this.recomputeScrollHeight();
|
||||
},
|
||||
/**
|
||||
* 根据 4 个子组件上报的高度,计算 scroll-view 可用的固定高度。
|
||||
* —— 完全符合 uni-app / 微信小程序官方文档「scroll-y 需给固定 height」的要求。
|
||||
*/
|
||||
calcScrollHeight: function calcScrollHeight() {
|
||||
var _this6 = this;
|
||||
var query = uni.createSelectorQuery().in(this);
|
||||
// 分别测量 4 个元素的 boundingClientRect
|
||||
query.select('#searchBar').boundingClientRect();
|
||||
query.select('#countryBar').boundingClientRect();
|
||||
query.select('#activeFilters').boundingClientRect();
|
||||
query.select('#subCategories').boundingClientRect();
|
||||
query.exec(function (res) {
|
||||
// res[0]=searchBar, res[1]=countryBar, res[2]=activeFilters, res[3]=subCategories
|
||||
// 注意:v-if 为 false 时 res[i] 可能为 null
|
||||
var searchBarH = res[0] ? res[0].height : 0;
|
||||
var countryBarH = res[1] ? res[1].height : 0;
|
||||
var activeFiltersH = res[2] ? res[2].height : 0;
|
||||
var subCategoriesH = res[3] ? res[3].height : 0;
|
||||
var totalUsed = searchBarH + countryBarH + activeFiltersH + subCategoriesH;
|
||||
var h = _this6.windowHeight - totalUsed;
|
||||
recomputeScrollHeight: function recomputeScrollHeight() {
|
||||
var totalUsed = this._searchBarH + this._countryBarH + this._activeFiltersH + this._subCategoriesH;
|
||||
var h = this.windowHeight - totalUsed;
|
||||
// 最小值保护:至少 200px,避免极端情况
|
||||
if (h < 200) h = 200;
|
||||
if (h > _this6.windowHeight) h = _this6.windowHeight;
|
||||
_this6.productScrollHeight = Math.round(h);
|
||||
console.log('[calcScrollHeight] windowHeight=' + _this6.windowHeight + ', searchBar=' + searchBarH + ', countryBar=' + countryBarH + ', activeFilters=' + activeFiltersH + ', subCategories=' + subCategoriesH + ' → scrollHeight=' + _this6.productScrollHeight);
|
||||
});
|
||||
if (h > this.windowHeight) h = this.windowHeight;
|
||||
this.productScrollHeight = Math.round(h);
|
||||
console.log('[recomputeScrollHeight] windowHeight=' + this.windowHeight + ', searchBar=' + this._searchBarH + ', countryBar=' + this._countryBarH + ', activeFilters=' + this._activeFiltersH + ', subCategories=' + this._subCategoriesH + ' → scrollHeight=' + this.productScrollHeight);
|
||||
},
|
||||
selectCountry: function selectCountry(id) {
|
||||
var _this7 = this;
|
||||
var _this6 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5() {
|
||||
var country, filters;
|
||||
return _regenerator.default.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
if (!(_this7.selectedCountry === id)) {
|
||||
if (!(_this6.selectedCountry === id)) {
|
||||
_context5.next = 8;
|
||||
break;
|
||||
}
|
||||
_this7.selectedCountry = '';
|
||||
_this7.activeFilters = _this7.activeFilters.filter(function (f) {
|
||||
_this6.selectedCountry = '';
|
||||
_this6.activeFilters = _this6.activeFilters.filter(function (f) {
|
||||
return f.key !== 'country';
|
||||
});
|
||||
_context5.next = 5;
|
||||
return _this7.loadCategoryData('');
|
||||
return _this6.loadCategoryData('');
|
||||
case 5:
|
||||
_context5.next = 7;
|
||||
return _this7.loadGoods(1);
|
||||
return _this6.loadGoods(1);
|
||||
case 7:
|
||||
return _context5.abrupt("return");
|
||||
case 8:
|
||||
// 选中新国家
|
||||
country = _this7.countries.find(function (c) {
|
||||
country = _this6.countries.find(function (c) {
|
||||
return c.id === id;
|
||||
});
|
||||
filters = _this7.activeFilters.filter(function (f) {
|
||||
filters = _this6.activeFilters.filter(function (f) {
|
||||
return f.key !== 'country';
|
||||
});
|
||||
if (country) {
|
||||
@@ -608,13 +629,13 @@ var _default = {
|
||||
label: country.name
|
||||
});
|
||||
}
|
||||
_this7.selectedCountry = id;
|
||||
_this7.activeFilters = filters;
|
||||
_this6.selectedCountry = id;
|
||||
_this6.activeFilters = filters;
|
||||
_context5.next = 15;
|
||||
return _this7.loadCategoryData(id);
|
||||
return _this6.loadCategoryData(id);
|
||||
case 15:
|
||||
_context5.next = 17;
|
||||
return _this7.loadGoods(1);
|
||||
return _this6.loadGoods(1);
|
||||
case 17:
|
||||
case "end":
|
||||
return _context5.stop();
|
||||
@@ -624,16 +645,16 @@ var _default = {
|
||||
}))();
|
||||
},
|
||||
selectCategory: function selectCategory(id) {
|
||||
var _this8 = this;
|
||||
var _this7 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6() {
|
||||
return _regenerator.default.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
_this8.activeCategory = id;
|
||||
_this8.loadSubCategories(id);
|
||||
_this7.activeCategory = id;
|
||||
_this7.loadSubCategories(id);
|
||||
_context6.next = 4;
|
||||
return _this8.loadGoods(1);
|
||||
return _this7.loadGoods(1);
|
||||
case 4:
|
||||
case "end":
|
||||
return _context6.stop();
|
||||
@@ -643,15 +664,15 @@ var _default = {
|
||||
}))();
|
||||
},
|
||||
selectSubCategory: function selectSubCategory(id) {
|
||||
var _this9 = this;
|
||||
var _this8 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7() {
|
||||
return _regenerator.default.wrap(function _callee7$(_context7) {
|
||||
while (1) {
|
||||
switch (_context7.prev = _context7.next) {
|
||||
case 0:
|
||||
_this9.activeSubCategory = id;
|
||||
_this8.activeSubCategory = id;
|
||||
_context7.next = 3;
|
||||
return _this9.loadGoods(1);
|
||||
return _this8.loadGoods(1);
|
||||
case 3:
|
||||
case "end":
|
||||
return _context7.stop();
|
||||
@@ -683,27 +704,27 @@ var _default = {
|
||||
this.filterGroups = groups;
|
||||
},
|
||||
removeFilter: function removeFilter(key) {
|
||||
var _this10 = this;
|
||||
var _this9 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8() {
|
||||
var filters, groupId, groups;
|
||||
return _regenerator.default.wrap(function _callee8$(_context8) {
|
||||
while (1) {
|
||||
switch (_context8.prev = _context8.next) {
|
||||
case 0:
|
||||
filters = _this10.activeFilters.filter(function (f) {
|
||||
filters = _this9.activeFilters.filter(function (f) {
|
||||
return f.key !== key;
|
||||
});
|
||||
if (!(key === 'country')) {
|
||||
_context8.next = 9;
|
||||
break;
|
||||
}
|
||||
_this10.selectedCountry = '';
|
||||
_this10.activeFilters = filters;
|
||||
_this9.selectedCountry = '';
|
||||
_this9.activeFilters = filters;
|
||||
_context8.next = 6;
|
||||
return _this10.loadCategoryData('');
|
||||
return _this9.loadCategoryData('');
|
||||
case 6:
|
||||
_context8.next = 8;
|
||||
return _this10.loadGoods(1);
|
||||
return _this9.loadGoods(1);
|
||||
case 8:
|
||||
return _context8.abrupt("return");
|
||||
case 9:
|
||||
@@ -712,7 +733,7 @@ var _default = {
|
||||
break;
|
||||
}
|
||||
groupId = key.replace('tag_', '');
|
||||
groups = _this10.filterGroups.map(function (g) {
|
||||
groups = _this9.filterGroups.map(function (g) {
|
||||
if (String(g.id) === String(groupId)) {
|
||||
return Object.assign({}, g, {
|
||||
selected: []
|
||||
@@ -720,14 +741,14 @@ var _default = {
|
||||
}
|
||||
return g;
|
||||
});
|
||||
_this10.activeFilters = filters;
|
||||
_this10.filterGroups = groups;
|
||||
_this9.activeFilters = filters;
|
||||
_this9.filterGroups = groups;
|
||||
_context8.next = 16;
|
||||
return _this10.loadGoods(1);
|
||||
return _this9.loadGoods(1);
|
||||
case 16:
|
||||
return _context8.abrupt("return");
|
||||
case 17:
|
||||
_this10.activeFilters = filters;
|
||||
_this9.activeFilters = filters;
|
||||
case 18:
|
||||
case "end":
|
||||
return _context8.stop();
|
||||
@@ -737,33 +758,33 @@ var _default = {
|
||||
}))();
|
||||
},
|
||||
clearAllFilters: function clearAllFilters() {
|
||||
var _this11 = this;
|
||||
var _this10 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9() {
|
||||
var hasCountry, groups;
|
||||
return _regenerator.default.wrap(function _callee9$(_context9) {
|
||||
while (1) {
|
||||
switch (_context9.prev = _context9.next) {
|
||||
case 0:
|
||||
hasCountry = _this11.activeFilters.some(function (f) {
|
||||
hasCountry = _this10.activeFilters.some(function (f) {
|
||||
return f.key === 'country';
|
||||
});
|
||||
_this11.activeFilters = [];
|
||||
if (!(hasCountry || _this11.selectedCountry)) {
|
||||
_this10.activeFilters = [];
|
||||
if (!(hasCountry || _this10.selectedCountry)) {
|
||||
_context9.next = 6;
|
||||
break;
|
||||
}
|
||||
_this11.selectedCountry = '';
|
||||
_this10.selectedCountry = '';
|
||||
_context9.next = 6;
|
||||
return _this11.loadCategoryData('');
|
||||
return _this10.loadCategoryData('');
|
||||
case 6:
|
||||
groups = _this11.filterGroups.map(function (g) {
|
||||
groups = _this10.filterGroups.map(function (g) {
|
||||
return Object.assign({}, g, {
|
||||
selected: []
|
||||
});
|
||||
});
|
||||
_this11.filterGroups = groups;
|
||||
_this10.filterGroups = groups;
|
||||
_context9.next = 10;
|
||||
return _this11.loadGoods(1);
|
||||
return _this10.loadGoods(1);
|
||||
case 10:
|
||||
case "end":
|
||||
return _context9.stop();
|
||||
@@ -781,7 +802,7 @@ var _default = {
|
||||
this.filterGroups = groups;
|
||||
},
|
||||
confirmFilters: function confirmFilters() {
|
||||
var _this12 = this;
|
||||
var _this11 = this;
|
||||
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee10() {
|
||||
var filters, countryFilter;
|
||||
return _regenerator.default.wrap(function _callee10$(_context10) {
|
||||
@@ -789,11 +810,11 @@ var _default = {
|
||||
switch (_context10.prev = _context10.next) {
|
||||
case 0:
|
||||
filters = [];
|
||||
countryFilter = _this12.activeFilters.find(function (f) {
|
||||
countryFilter = _this11.activeFilters.find(function (f) {
|
||||
return f.key === 'country';
|
||||
});
|
||||
if (countryFilter) filters.push(countryFilter);
|
||||
_this12.filterGroups.forEach(function (group) {
|
||||
_this11.filterGroups.forEach(function (group) {
|
||||
if (group.selected.length > 0) {
|
||||
var labels = group.tags.filter(function (t) {
|
||||
return group.selected.indexOf(t.id) > -1;
|
||||
@@ -808,10 +829,10 @@ var _default = {
|
||||
}
|
||||
}
|
||||
});
|
||||
_this12.activeFilters = filters;
|
||||
_this12.showFilter = false;
|
||||
_this11.activeFilters = filters;
|
||||
_this11.showFilter = false;
|
||||
_context10.next = 8;
|
||||
return _this12.loadGoods(1);
|
||||
return _this11.loadGoods(1);
|
||||
case 8:
|
||||
case "end":
|
||||
return _context10.stop();
|
||||
|
||||
@@ -1 +1 @@
|
||||
<view class="products-page" style="{{'height:'+(windowHeight+'px')+';'}}"><search-bar vue-id="08007ac0-1" keyword="{{searchKeyword}}" data-event-opts="{{[['^input',[['onSearchInput']]],['^blur',[['onSearchBlur']]],['^filter',[['toggleFilter']]]]}}" bind:input="__e" bind:blur="__e" bind:filter="__e" bind:__l="__l"></search-bar><country-bar vue-id="08007ac0-2" list="{{countries}}" selected-id="{{selectedCountry}}" data-event-opts="{{[['^select',[['selectCountry']]]]}}" bind:select="__e" bind:__l="__l"></country-bar><view class="content-body"><category-sidebar vue-id="08007ac0-3" list="{{categories}}" active-id="{{activeCategory}}" data-event-opts="{{[['^select',[['selectCategory']]]]}}" bind:select="__e" bind:__l="__l"></category-sidebar><view class="right-wrap"><active-filters vue-id="08007ac0-4" list="{{activeFilters}}" data-event-opts="{{[['^remove',[['removeFilter']]],['^clearAll',[['clearAllFilters']]]]}}" bind:remove="__e" bind:clearAll="__e" bind:__l="__l"></active-filters><product-grid vue-id="08007ac0-5" list="{{products}}" sub-categories="{{subCategories}}" active-sub-id="{{activeSubCategory}}" has-more="{{hasMore}}" loading="{{loadingMore}}" scroll-top-val="{{scrollTopVal}}" scroll-height="{{productScrollHeight}}" data-event-opts="{{[['^subSelect',[['selectSubCategory']]],['^productClick',[['goDetail']]],['^scrollToLower',[['onScrollToLower']]]]}}" bind:subSelect="__e" bind:productClick="__e" bind:scrollToLower="__e" bind:__l="__l"></product-grid></view></view><filter-drawer vue-id="08007ac0-6" visible="{{showFilter}}" groups="{{filterGroups}}" data-event-opts="{{[['^close',[['closeFilter']]],['^toggleTag',[['toggleFilterTag']]],['^reset',[['resetFilters']]],['^confirm',[['confirmFilters']]]]}}" bind:close="__e" bind:toggleTag="__e" bind:reset="__e" bind:confirm="__e" bind:__l="__l"></filter-drawer></view>
|
||||
<view class="products-page" style="{{'height:'+(windowHeight+'px')+';'}}"><search-bar vue-id="08007ac0-1" keyword="{{searchKeyword}}" data-event-opts="{{[['^input',[['onSearchInput']]],['^blur',[['onSearchBlur']]],['^filter',[['toggleFilter']]],['^heightChange',[['onSearchBarHeight']]]]}}" bind:input="__e" bind:blur="__e" bind:filter="__e" bind:heightChange="__e" bind:__l="__l"></search-bar><country-bar vue-id="08007ac0-2" list="{{countries}}" selected-id="{{selectedCountry}}" data-event-opts="{{[['^select',[['selectCountry']]],['^heightChange',[['onCountryBarHeight']]]]}}" bind:select="__e" bind:heightChange="__e" bind:__l="__l"></country-bar><view class="content-body"><category-sidebar vue-id="08007ac0-3" list="{{categories}}" active-id="{{activeCategory}}" data-event-opts="{{[['^select',[['selectCategory']]]]}}" bind:select="__e" bind:__l="__l"></category-sidebar><view class="right-wrap"><active-filters vue-id="08007ac0-4" list="{{activeFilters}}" data-event-opts="{{[['^remove',[['removeFilter']]],['^clearAll',[['clearAllFilters']]],['^heightChange',[['onActiveFiltersHeight']]]]}}" bind:remove="__e" bind:clearAll="__e" bind:heightChange="__e" bind:__l="__l"></active-filters><product-grid vue-id="08007ac0-5" list="{{products}}" sub-categories="{{subCategories}}" active-sub-id="{{activeSubCategory}}" has-more="{{hasMore}}" loading="{{loadingMore}}" scroll-top-val="{{scrollTopVal}}" scroll-height="{{productScrollHeight}}" data-event-opts="{{[['^subSelect',[['selectSubCategory']]],['^productClick',[['goDetail']]],['^scrollToLower',[['onScrollToLower']]],['^subHeightChange',[['onSubCategoriesHeight']]]]}}" bind:subSelect="__e" bind:productClick="__e" bind:scrollToLower="__e" bind:subHeightChange="__e" bind:__l="__l"></product-grid></view></view><filter-drawer vue-id="08007ac0-6" visible="{{showFilter}}" groups="{{filterGroups}}" data-event-opts="{{[['^close',[['closeFilter']]],['^toggleTag',[['toggleFilterTag']]],['^reset',[['resetFilters']]],['^confirm',[['confirmFilters']]]]}}" bind:close="__e" bind:toggleTag="__e" bind:reset="__e" bind:confirm="__e" bind:__l="__l"></filter-drawer></view>
|
||||