fix(square): use ref-binding for scrollTop reset; add bottom safety margin
This commit is contained in:
parent
751bd68bf1
commit
b0290456bb
@ -24,96 +24,104 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 骨架屏 -->
|
<!-- 内容区域: 内部 scroll -->
|
||||||
<view v-if="loading" class="grid-skeleton">
|
<scroll-view
|
||||||
<view v-for="i in 11" :key="i" class="skeleton-card">
|
class="content-scroll"
|
||||||
<view class="skeleton-image"></view>
|
scroll-y
|
||||||
<view class="skeleton-info">
|
:show-scrollbar="false"
|
||||||
<view class="skeleton-avatar"></view>
|
:bounce="false"
|
||||||
<view class="skeleton-name"></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>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 内容网格 -->
|
<!-- 内容网格 -->
|
||||||
<view v-else class="items-grid">
|
<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
|
<view
|
||||||
class="wf-like-wave wf-like-wave-outer"
|
v-for="(item, index) in items"
|
||||||
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
|
:key="item.id || index"
|
||||||
/>
|
class="grid-card"
|
||||||
<view
|
:class="{
|
||||||
class="wf-like-wave wf-like-wave-inner"
|
[`grid-card-top-${index + 1}`]: index < 5,
|
||||||
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
|
'grid-card-top-other': index >= 5,
|
||||||
/>
|
}"
|
||||||
|
@click="handleCardClick(item)"
|
||||||
<!-- 单行布局:藏品图片 + 头像 + 点赞数 + 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>
|
|
||||||
<view
|
<view
|
||||||
class="like-info"
|
class="wf-like-wave wf-like-wave-outer"
|
||||||
:class="{ [`like-info-top-${index + 1}`]: index < 3 }"
|
:class="{ 'wf-like-wave-active': likingMap[item.id] }"
|
||||||
>
|
/>
|
||||||
<view class="like-row">
|
<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
|
<image
|
||||||
class="like-icon"
|
class="card-image"
|
||||||
:src="
|
:src="item.cover_url || item.cover_image || ''"
|
||||||
item.is_liked
|
mode="aspectFill"
|
||||||
? '/static/icon/heart-icon.png'
|
/>
|
||||||
: '/static/icon/heart-icon-false.png'
|
<!-- 前 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"
|
mode="aspectFit"
|
||||||
/>
|
/>
|
||||||
<text class="like-count">{{ formatCount(item.like_count) }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
<text class="user-name">{{
|
<view
|
||||||
item.owner_nickname || item.creator_name || item.name || ""
|
class="like-info"
|
||||||
}}</text>
|
:class="{ [`like-info-top-${index + 1}`]: index < 3 }"
|
||||||
<text class="user-number">No.{{ item.owner_uid || "" }}</text>
|
>
|
||||||
</view>
|
<view class="like-row">
|
||||||
<view v-if="index >= 3" class="top-badge">
|
<image
|
||||||
<view class="badge-rank">
|
class="like-icon"
|
||||||
<image
|
:src="
|
||||||
class="badge-rank-icon"
|
item.is_liked
|
||||||
src="/static/square/top/top.png"
|
? '/static/icon/heart-icon.png'
|
||||||
mode="aspectFit"
|
: '/static/icon/heart-icon-false.png'
|
||||||
/>
|
"
|
||||||
<text class="badge-rank-number">{{ index + 1 }}</text>
|
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>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -305,11 +313,21 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.hot-category-block {
|
.hot-category-block {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
padding: 0 9.5rpx;
|
padding: 0 9.5rpx;
|
||||||
border-radius: 24rpx;
|
border-radius: 24rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-scroll {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0; /* flex 子项需要 min-height: 0 才能正确伸缩 */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tab 栏 —— 与 Figma Rectangle 90 (83:268) 一一对应 */
|
/* Tab 栏 —— 与 Figma Rectangle 90 (83:268) 一一对应 */
|
||||||
.ranking-tabs {
|
.ranking-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -480,7 +498,11 @@ onUnmounted(() => {
|
|||||||
border-bottom-right-radius: 12px;
|
border-bottom-right-radius: 12px;
|
||||||
border-bottom-left-radius: 12px;
|
border-bottom-left-radius: 12px;
|
||||||
opacity: 0.8; /* 与 Figma 一致 */
|
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;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
<scroll-view
|
<scroll-view
|
||||||
class="content-wrapper"
|
class="content-wrapper"
|
||||||
:scroll-y="activeContentTab === 'guangchang'"
|
:scroll-y="activeContentTab === 'guangchang'"
|
||||||
|
:scroll-top="outerScrollTop"
|
||||||
:show-scrollbar="false"
|
:show-scrollbar="false"
|
||||||
:bounce="false"
|
:bounce="false"
|
||||||
@scroll="onScroll"
|
@scroll="onScroll"
|
||||||
@ -120,11 +121,14 @@ const showRankingModal = ref(false);
|
|||||||
const creationGridRef = ref(null);
|
const creationGridRef = ref(null);
|
||||||
const cardTapTimers = {};
|
const cardTapTimers = {};
|
||||||
const likingMap = ref({});
|
const likingMap = ref({});
|
||||||
|
// 外层 scroll-view 的 scrollTop 受控值:通过 ref 绑定实现程序化重置
|
||||||
|
// (uni.pageScrollTo 操作的是 page 滚动条,不会作用于 <scroll-view>)
|
||||||
|
const outerScrollTop = ref(0);
|
||||||
|
|
||||||
// 切 tab 时重置外层 scroll-view 的 scrollTop,避免残留滚动位置
|
// 切 tab 时重置外层 scroll-view 的 scrollTop,避免残留滚动位置
|
||||||
watch(activeContentTab, () => {
|
watch(activeContentTab, () => {
|
||||||
// 星河/星榜 时 scroll-y=false,但 scrollTop 残留可能导致显示异常
|
// 星河/星榜 时 scroll-y=false,但 scrollTop 残留可能导致显示异常
|
||||||
uni.pageScrollTo({ scrollTop: 0, duration: 0 });
|
outerScrollTop.value = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 统一 scroll 处理:驱动 CreationGrid 切 fixed
|
// 统一 scroll 处理:驱动 CreationGrid 切 fixed
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user