fix(square): use ref-binding for scrollTop reset; add bottom safety margin

This commit is contained in:
zheng020 2026-06-11 12:43:09 +08:00
parent 751bd68bf1
commit b0290456bb
2 changed files with 105 additions and 79 deletions

View File

@ -24,96 +24,104 @@
</view>
</view>
<!-- 骨架屏 -->
<view v-if="loading" class="grid-skeleton">
<view v-for="i in 11" :key="i" class="skeleton-card">
<view class="skeleton-image"></view>
<view class="skeleton-info">
<view class="skeleton-avatar"></view>
<view class="skeleton-name"></view>
<!-- 内容区域: 内部 scroll -->
<scroll-view
class="content-scroll"
scroll-y
:show-scrollbar="false"
:bounce="false"
>
<!-- 骨架屏 -->
<view v-if="loading" class="grid-skeleton">
<view v-for="i in 11" :key="i" class="skeleton-card">
<view class="skeleton-image"></view>
<view class="skeleton-info">
<view class="skeleton-avatar"></view>
<view class="skeleton-name"></view>
</view>
</view>
</view>
</view>
<!-- 内容网格 -->
<view v-else class="items-grid">
<view
v-for="(item, index) in items"
:key="item.id || index"
class="grid-card"
:class="{
[`grid-card-top-${index + 1}`]: index < 5,
'grid-card-top-other': index >= 5,
}"
@click="handleCardClick(item)"
>
<!-- 点赞动效波纹 -->
<!-- 内容网格 -->
<view v-else class="items-grid">
<view
class="wf-like-wave wf-like-wave-outer"
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
/>
<view
class="wf-like-wave wf-like-wave-inner"
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
/>
<!-- 单行布局藏品图片 + 头像 + 点赞数 + TOP 标签 -->
<view class="card-row">
<view class="card-image-wrap">
<image
class="card-image"
:src="item.cover_url || item.cover_image || ''"
mode="aspectFill"
/>
<!-- 3 名专属包裹整个卡片的边框图 -->
<image
v-if="index < 3"
class="frame-image"
:src="TOP_FRAME_MAP[index]"
mode="scaleToFill"
/>
<!-- 3 名专属左上角奖牌装饰 -->
<image
v-if="index < 3"
class="card-medal"
:src="MEDAL_MAP[index]"
mode="aspectFit"
/>
</view>
v-for="(item, index) in items"
:key="item.id || index"
class="grid-card"
:class="{
[`grid-card-top-${index + 1}`]: index < 5,
'grid-card-top-other': index >= 5,
}"
@click="handleCardClick(item)"
>
<!-- 点赞动效波纹 -->
<view
class="like-info"
:class="{ [`like-info-top-${index + 1}`]: index < 3 }"
>
<view class="like-row">
class="wf-like-wave wf-like-wave-outer"
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
/>
<view
class="wf-like-wave wf-like-wave-inner"
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
/>
<!-- 单行布局藏品图片 + 头像 + 点赞数 + TOP 标签 -->
<view class="card-row">
<view class="card-image-wrap">
<image
class="like-icon"
:src="
item.is_liked
? '/static/icon/heart-icon.png'
: '/static/icon/heart-icon-false.png'
"
class="card-image"
:src="item.cover_url || item.cover_image || ''"
mode="aspectFill"
/>
<!-- 3 名专属包裹整个卡片的边框图 -->
<image
v-if="index < 3"
class="frame-image"
:src="TOP_FRAME_MAP[index]"
mode="scaleToFill"
/>
<!-- 3 名专属左上角奖牌装饰 -->
<image
v-if="index < 3"
class="card-medal"
:src="MEDAL_MAP[index]"
mode="aspectFit"
/>
<text class="like-count">{{ formatCount(item.like_count) }}</text>
</view>
<text class="user-name">{{
item.owner_nickname || item.creator_name || item.name || ""
}}</text>
<text class="user-number">No.{{ item.owner_uid || "" }}</text>
</view>
<view v-if="index >= 3" class="top-badge">
<view class="badge-rank">
<image
class="badge-rank-icon"
src="/static/square/top/top.png"
mode="aspectFit"
/>
<text class="badge-rank-number">{{ index + 1 }}</text>
<view
class="like-info"
:class="{ [`like-info-top-${index + 1}`]: index < 3 }"
>
<view class="like-row">
<image
class="like-icon"
:src="
item.is_liked
? '/static/icon/heart-icon.png'
: '/static/icon/heart-icon-false.png'
"
mode="aspectFit"
/>
<text class="like-count">{{ formatCount(item.like_count) }}</text>
</view>
<text class="user-name">{{
item.owner_nickname || item.creator_name || item.name || ""
}}</text>
<text class="user-number">No.{{ item.owner_uid || "" }}</text>
</view>
<view v-if="index >= 3" class="top-badge">
<view class="badge-rank">
<image
class="badge-rank-icon"
src="/static/square/top/top.png"
mode="aspectFit"
/>
<text class="badge-rank-number">{{ index + 1 }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
@ -305,11 +313,21 @@ onUnmounted(() => {
<style scoped lang="scss">
.hot-category-block {
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0 9.5rpx;
border-radius: 24rpx;
position: relative;
}
.content-scroll {
flex: 1;
min-height: 0; /* flex 子项需要 min-height: 0 才能正确伸缩 */
overflow: hidden;
}
/* Tab 栏 —— 与 Figma Rectangle 90 (83:268) 一一对应 */
.ranking-tabs {
display: flex;
@ -480,7 +498,11 @@ onUnmounted(() => {
border-bottom-right-radius: 12px;
border-bottom-left-radius: 12px;
opacity: 0.8; /* 与 Figma 一致 */
padding: 40rpx 20rpx 0;
/* padding: 40rpx 20rpx 0; */
/* 80rpx Task 2 .hot-category-wrapper height ,
重新加上 32rpx 底部 padding 保证最后一行卡片不会紧贴 scroll-view 底边
避免与 BottomNav fixed 区域视觉重叠 */
padding: 40rpx 20rpx 32rpx;
overflow: hidden;
}

View File

@ -46,6 +46,7 @@
<scroll-view
class="content-wrapper"
:scroll-y="activeContentTab === 'guangchang'"
:scroll-top="outerScrollTop"
:show-scrollbar="false"
:bounce="false"
@scroll="onScroll"
@ -120,11 +121,14 @@ const showRankingModal = ref(false);
const creationGridRef = ref(null);
const cardTapTimers = {};
const likingMap = ref({});
// scroll-view scrollTop ref
// uni.pageScrollTo page <scroll-view>
const outerScrollTop = ref(0);
// tab scroll-view scrollTop,
watch(activeContentTab, () => {
// / scroll-y=false, scrollTop
uni.pageScrollTo({ scrollTop: 0, duration: 0 });
outerScrollTop.value = 0;
});
// scroll CreationGrid fixed