refactor(community): 重构动态详情页布局
parent
856b7224c1
commit
203fd7a1a6
|
|
@ -5,41 +5,41 @@
|
||||||
<!-- 渐变背景 -->
|
<!-- 渐变背景 -->
|
||||||
<view class="gradient-bg"></view>
|
<view class="gradient-bg"></view>
|
||||||
|
|
||||||
<!-- 固定头部区域(标题+发布信息) -->
|
<!-- 头部区域(标题+发布信息)-->
|
||||||
<view class="detail-header" :style="{ top: navbarHeight + 'px' }">
|
<view class="detail-header">
|
||||||
<view class="header-inner">
|
<view class="header-inner">
|
||||||
<!-- 标题 -->
|
<!-- 标题 -->
|
||||||
<view class="detail-title">
|
<view class="detail-title">
|
||||||
<text class="title-text">{{ detailInfo.title }}</text>
|
<text class="title-text">{{ detailInfo.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 发布信息 -->
|
<!-- 发布信息 -->
|
||||||
<view class="publish-info">
|
<view class="publish-info">
|
||||||
<text class="community-name">{{ detailInfo.communityName }}</text>
|
<text class="community-name">{{ detailInfo.communityName }}</text>
|
||||||
<text class="publish-date">{{ detailInfo.publishDate ? sheep.$helper.timeFormat(detailInfo.publishDate, 'yyyy年mm月dd日 hh:MM') : '' }}</text>
|
<text class="publish-date">{{ detailInfo.publishDate ? sheep.$helper.timeFormat(detailInfo.publishDate, 'yyyy年mm月dd日 hh:MM') : '' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 分割线 -->
|
<!-- 分割线 -->
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 富文本内容 - 固定滚动区域 -->
|
|
||||||
<scroll-view class="content-scroll" scroll-y :style="{ height: scrollHeight + 'px', top: scrollTop + 'px' }">
|
|
||||||
<view class="content-card">
|
|
||||||
<view class="content-inner">
|
|
||||||
<mp-html :content="detailInfo.content"></mp-html>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 底部占位 -->
|
|
||||||
<view class="bottom-placeholder"></view>
|
<!-- 富文本内容 - calc 计算高度滚动区域 -->
|
||||||
</scroll-view>
|
<scroll-view class="content-scroll" scroll-y>
|
||||||
|
<view class="content-card">
|
||||||
|
<view class="content-inner">
|
||||||
|
<mp-html :content="detailInfo.content+detailInfo.content"></mp-html>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 底部占位 -->
|
||||||
|
<view class="bottom-placeholder"></view>
|
||||||
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</s-layout>
|
</s-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
import DynamicsApi from '@/sheep/api/community/dynamics';
|
import DynamicsApi from '@/sheep/api/community/dynamics';
|
||||||
import sheep from '@/sheep';
|
import sheep from '@/sheep';
|
||||||
|
|
@ -52,14 +52,6 @@ const detailInfo = ref({
|
||||||
content: '',
|
content: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 滚动区域高度
|
|
||||||
const scrollHeight = ref(0);
|
|
||||||
// 滚动区域距离顶部距离
|
|
||||||
const scrollTop = ref(0);
|
|
||||||
|
|
||||||
// 导航栏高度(px),用于固定头部避开导航栏
|
|
||||||
const navbarHeight = sheep.$platform.navbar;
|
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
|
|
@ -67,31 +59,6 @@ onLoad((options) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算scroll-view高度和位置
|
|
||||||
const calcScrollHeight = () => {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
nextTick(() => {
|
|
||||||
const sysInfo = uni.getSystemInfoSync();
|
|
||||||
const query = uni.createSelectorQuery().in(instance);
|
|
||||||
|
|
||||||
// 获取头部区域高度
|
|
||||||
query.select('.detail-header').boundingClientRect();
|
|
||||||
query.exec((res) => {
|
|
||||||
const headerRect = res[0];
|
|
||||||
if (headerRect) {
|
|
||||||
const safeBottom = sysInfo.safeAreaInsets?.bottom || 0;
|
|
||||||
// scroll-view 顶部 = 导航栏高度 + 头部高度,不再依赖 headerRect.top(fixed 元素在不同平台表现不一致)
|
|
||||||
scrollTop.value = navbarHeight + headerRect.height;
|
|
||||||
scrollHeight.value = sysInfo.windowHeight - scrollTop.value - safeBottom;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
calcScrollHeight();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 加载详情
|
// 加载详情
|
||||||
async function loadDetail(id) {
|
async function loadDetail(id) {
|
||||||
const { code, data } = await DynamicsApi.getDetail(id);
|
const { code, data } = await DynamicsApi.getDetail(id);
|
||||||
|
|
@ -104,20 +71,18 @@ async function loadDetail(id) {
|
||||||
publishDate: data.publishTime || '',
|
publishDate: data.publishTime || '',
|
||||||
content: data.content || '',
|
content: data.content || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 等 Vue DOM 更新完成后再计算高度,避免网络延迟导致拿到旧尺寸
|
|
||||||
nextTick(() => {
|
|
||||||
calcScrollHeight();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* 页面容器 */
|
/* 页面容器:纵向 flex 布局,减去导航栏高度 176rpx */
|
||||||
.detail-page {
|
.detail-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: calc(100vh - 176rpx);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 渐变背景 */
|
/* 渐变背景 */
|
||||||
|
|
@ -132,13 +97,11 @@ async function loadDetail(id) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 固定头部区域 */
|
/* 头部区域:正常文档流,不参与滚动 */
|
||||||
.detail-header {
|
.detail-header {
|
||||||
position: fixed;
|
position: relative;
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
background: transparent;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-inner {
|
.header-inner {
|
||||||
|
|
@ -187,12 +150,12 @@ async function loadDetail(id) {
|
||||||
margin-bottom: 32rpx;
|
margin-bottom: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 内容滚动区域 - 固定定位 */
|
/* 内容滚动区域:flex:1 占满头部剩余空间,height:0 是小程序 scroll-view 配合 flex 的关键 */
|
||||||
.content-scroll {
|
.content-scroll {
|
||||||
position: fixed;
|
position: relative;
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
flex: 1;
|
||||||
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 内容卡片 */
|
/* 内容卡片 */
|
||||||
|
|
@ -218,8 +181,8 @@ async function loadDetail(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部占位 */
|
/* 底部占位:40rpx 基础间距 + 安全区域 */
|
||||||
.bottom-placeholder {
|
.bottom-placeholder {
|
||||||
height: 40rpx;
|
height: calc(40rpx + env(safe-area-inset-bottom));
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue