fjrcloud-community-app/pages/sub/community/dynamics-detail.vue

226 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!-- 社区动态详情页 -->
<template>
<s-layout title="社区动态" color="#333333">
<view class="detail-page">
<!-- 渐变背景 -->
<view class="gradient-bg"></view>
<!-- 固定头部区域标题+发布信息 -->
<view class="detail-header" :style="{ top: navbarHeight + 'px' }">
<view class="header-inner">
<!-- 标题 -->
<view class="detail-title">
<text class="title-text">{{ detailInfo.title }}</text>
</view>
<!-- 发布信息 -->
<view class="publish-info">
<text class="community-name">{{ detailInfo.communityName }}</text>
<text class="publish-date">{{ detailInfo.publishDate ? sheep.$helper.timeFormat(detailInfo.publishDate, 'yyyy年mm月dd日 hh:MM') : '' }}</text>
</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 class="bottom-placeholder"></view>
</scroll-view>
</view>
</s-layout>
</template>
<script setup>
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import DynamicsApi from '@/sheep/api/community/dynamics';
import sheep from '@/sheep';
// 详情数据
const detailInfo = ref({
title: '',
communityName: '',
publishDate: '',
content: '',
});
// 滚动区域高度
const scrollHeight = ref(0);
// 滚动区域距离顶部距离
const scrollTop = ref(0);
// 导航栏高度px用于固定头部避开导航栏
const navbarHeight = sheep.$platform.navbar;
// 页面加载
onLoad((options) => {
if (options.id) {
loadDetail(options.id);
}
});
// 计算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.topfixed 元素在不同平台表现不一致)
scrollTop.value = navbarHeight + headerRect.height;
scrollHeight.value = sysInfo.windowHeight - scrollTop.value - safeBottom;
}
});
});
};
onMounted(() => {
calcScrollHeight();
});
// 加载详情
async function loadDetail(id) {
const { code, data } = await DynamicsApi.getDetail(id);
if (code === 0 && data) {
const communityName = data.author || '';
detailInfo.value = {
title: data.title || '',
communityName,
publishDate: data.publishTime || '',
content: data.content || '',
};
// 等 Vue DOM 更新完成后再计算高度,避免网络延迟导致拿到旧尺寸
nextTick(() => {
calcScrollHeight();
});
}
}
</script>
<style lang="scss" scoped>
/* 页面容器 */
.detail-page {
position: relative;
z-index: 1;
}
/* 渐变背景 */
.gradient-bg {
position: absolute;
top: 0;
left: 0;
width: 750rpx;
height: 660rpx;
background: linear-gradient(180deg, #F8EDE8 0%, #F5F5F5 50%);
z-index: 0;
pointer-events: none;
}
/* 固定头部区域 */
.detail-header {
position: fixed;
left: 0;
width: 100%;
z-index: 10;
background: transparent;
}
.header-inner {
padding: 0 32rpx;
}
/* 文章标题 */
.detail-title {
padding: 32rpx 0 24rpx;
.title-text {
font-size: 40rpx;
font-weight: 600;
color: #333333;
line-height: 1.5;
font-family: 'PingFang SC', sans-serif;
}
}
/* 发布信息 */
.publish-info {
display: flex;
align-items: center;
gap: 16rpx;
padding-bottom: 24rpx;
justify-content: space-between;
.community-name {
font-size: 28rpx;
color: #666666;
font-family: 'PingFang SC', sans-serif;
}
.publish-date {
font-size: 26rpx;
color: #999999;
font-family: 'PingFang SC', sans-serif;
}
}
/* 分割线 */
.divider {
height: 1rpx;
background-color: #E5E5E5;
margin-bottom: 32rpx;
}
/* 内容滚动区域 - 固定定位 */
.content-scroll {
position: fixed;
left: 0;
width: 100%;
z-index: 5;
}
/* 内容卡片 */
.content-card {
border-radius: 24rpx;
padding: 32rpx;
}
/* 富文本内容 */
.content-inner {
:deep(p) {
font-size: 30rpx;
color: #333333;
line-height: 1.8;
margin-bottom: 24rpx;
font-family: 'PingFang SC', sans-serif;
}
:deep(img) {
width: 100%;
border-radius: 16rpx;
margin: 16rpx 0;
}
}
/* 底部占位 */
.bottom-placeholder {
height: 40rpx;
}
</style>