mrr.sj.front/pages/notice/detail.vue

359 lines
8.4 KiB
Vue

<template>
<view class="notice-detail-page">
<!-- 自定义顶部导航组件 -->
<custom-navbar
title="公告通知详情"
:showBack="true"
backgroundColor="linear-gradient(180deg, #E6ECFB 0%, #FFFFFF 100%)"
:showHeadle="true"
borderBottom="none"
headleSrc="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/51ebca5d-95c5-4fb8-8aa3-560a79100d25.png"
@onHeadleClick="handleShare"
/>
<!-- 页面主要内容 -->
<view class="page-content">
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-icon"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 详情内容 -->
<view v-else-if="detailData.id" class="detail-card">
<!-- 标题 -->
<text class="detail-title">{{ detailData.title }}</text>
<!-- 发布时间 -->
<view class="detail-time">
<text class="time-text">时间:{{ formatTime(detailData.create_time) }}</text>
<text class="browse-text"> <image class="browse-icon" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/6133cbef-5861-40f8-80f5-d8a86477c94f.png" mode="aspectFit"></image> {{ detailData.browse_num }}</text>
</view>
<!-- 富文本内容 -->
<view class="detail-content">
<rich-text :nodes="detailData.content"></rich-text>
</view>
</view>
<!-- 空状态或错误 -->
<view v-else-if="!loading && !detailData.id" class="empty-container">
<image class="empty-img" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/8c5e7b2a-3d4f-4b1e-9a7c-6e8f2d1b4a5c.png" mode="aspectFit"></image>
<text class="empty-text">公告不存在或已删除</text>
</view>
</view>
</view>
</template>
<script>
import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue';
import request from '@/utils/request';
export default {
components: {
CustomNavbar
},
data() {
return {
loading: false, // 加载状态
detailData: { // 公告详情数据
id: null,
title: '',
create_time: '',
content: ''
}
};
},
onLoad(options) {
const id = options.id;
if (id) {
this.fetchNoticeDetail(id);
} else {
uni.showToast({
title: '参数错误',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
},
methods: {
// 获取公告详情
fetchNoticeDetail(id) {
this.loading = true;
request.post('/sj/notice/details', { id: id })
.then(res => {
if (res.code === 200 && res.data) {
this.detailData = res.data;
// 动态设置页面标题(可选)
uni.setNavigationBarTitle({
title: this.detailData.title || '公告详情'
});
} else {
uni.showToast({
title: res.msg || '获取详情失败',
icon: 'none'
});
}
})
.catch(err => {
console.error('获取公告详情失败:', err);
uni.showToast({
title: '网络异常,请稍后重试',
icon: 'none'
});
})
.finally(() => {
this.loading = false;
});
},
formatTime(timeStr) {
if (!timeStr) return '--:--:--';
let formatted = timeStr;
if (timeStr.includes('.') && !timeStr.includes('-')) {
const match = timeStr.match(/(\d{4})\.(\d{2})\.(\d{2})(\d{2}:\d{2}:\d{2})/);
if (match) {
formatted = `${match[1]}-${match[2]}-${match[3]} ${match[4]}`;
} else {
formatted = timeStr.replace(/\./g, '-');
}
}
// 如果是标准格式直接返回,否则返回原字符串
if (formatted.includes('-') && formatted.includes(':')) {
// 转换回点分隔显示,以匹配设计图风格: 2026.05.08 15:00:00
const datePart = formatted.split(' ')[0];
const timePart = formatted.split(' ')[1] || '';
if (datePart && datePart.includes('-')) {
const dotDate = datePart.replace(/-/g, '.');
return `${dotDate} ${timePart}`.trim();
}
return formatted;
}
return timeStr;
},
}
};
</script>
<style lang="scss" scoped>
.notice-detail-page {
min-height: 100vh;
background-color: #fff;
}
.page-content {
// padding: 20rpx 24rpx 60rpx;
}
// 加载状态
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.loading-icon {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #e0e0e0;
border-top-color: #FF4767;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-bottom: 20rpx;
}
.loading-text {
font-size: 26rpx;
color: #999;
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
// 详情卡片
.detail-card {
background: #ffffff;
border-radius: 24rpx;
padding: 20rpx 30rpx;
margin-bottom: 30rpx;
.detail-title {
display: block;
margin-bottom: 14rpx;
font-weight: 500;
font-size: 40rpx;
color: #333333;
line-height: 56rpx;
}
.detail-time {
display: flex;
align-items: center;
margin-bottom: 30rpx;
justify-content: space-between; // 两端对齐
// border-bottom: 1rpx solid #f0f0f0;
.time-icon {
width: 28rpx;
height: 28rpx;
margin-right: 10rpx;
opacity: 0.6;
}
.time-text {
font-weight: 400;
font-size: 28rpx;
color: #B6B6B6;
line-height: 40rpx;
}
.browse-icon {
width: 38rpx;
height: 22rpx;
// margin-right: 10rpx;
}
.browse-text {
margin-right: 10rpx;
font-weight: 400;
font-size: 28rpx;
color: #B08463;
line-height: 40rpx;
}
}
.detail-content {
font-weight: 400;
font-size: 28rpx;
color: #2A2A2A;
line-height: 40rpx;
overflow-x: hidden;
// 对rich-text内部样式进行补充
::v-deep img {
max-width: 100%;
height: auto;
display: block;
margin: 30rpx 0;
}
::v-deep p {
margin-bottom: 20rpx; // 重置外边距,避免多余间距
padding: 0;
}
// 在需要分段的地方手动创建间距
::v-deep br {
display: block; // 让 <br> 标签表现正常
margin-bottom: 30rpx; // 控制段落间距
}
}
}
// 空状态
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 150rpx 0;
.empty-img {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
opacity: 0.6;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
// 底部会员营销卡片(根据设计图样式)
.member-card {
background: linear-gradient(135deg, #FFE6E8 0%, #FFF0E6 100%);
border-radius: 24rpx;
padding: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
.member-info {
flex: 1;
.member-price {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #FF4767;
line-height: 44rpx;
margin-bottom: 8rpx;
}
.member-desc {
display: block;
font-size: 24rpx;
color: #333;
line-height: 34rpx;
margin-bottom: 12rpx;
}
.member-tag {
display: flex;
align-items: center;
.tag-text, .tag-gift {
font-size: 20rpx;
background: rgba(255, 71, 103, 0.15);
padding: 4rpx 12rpx;
border-radius: 20rpx;
color: #FF4767;
margin-right: 12rpx;
}
.tag-gift {
background: rgba(255, 193, 7, 0.2);
color: #E6A100;
}
}
}
.member-btn {
background: linear-gradient(135deg, #FF4767, #FF6B8A);
border-radius: 48rpx;
padding: 14rpx 28rpx;
text-align: center;
min-width: 160rpx;
box-shadow: 0 4rpx 12rpx rgba(255, 71, 103, 0.3);
.btn-text {
display: block;
font-size: 26rpx;
font-weight: 600;
color: #FFFFFF;
line-height: 36rpx;
}
.btn-sub {
display: block;
font-size: 20rpx;
color: rgba(255, 255, 255, 0.9);
line-height: 28rpx;
}
}
}
::v-deep .icon-headle {
width: 32rpx !important;
height: 32rpx !important;
}
</style>