<template>
|
<view class="detail-page">
|
<!-- 加载状态 -->
|
<view v-if="loading" class="loading-container">
|
<u-loading mode="circle" size="48"></u-loading>
|
<text class="loading-text">加载中...</text>
|
</view>
|
|
<!-- 内容区域 -->
|
<template v-else>
|
<!-- 标题区 -->
|
<view class="header">
|
<text class="title">{{ detailData.title }}</text>
|
<text class="meta">
|
<text class="date">{{ formatDate(detailData.publishDate) }}</text>
|
</text>
|
</view>
|
|
<!-- 富文本内容 -->
|
<scroll-view scroll-y class="content-wrapper">
|
<rich-text
|
:nodes="formatContent(detailData.content)"
|
class="content"
|
></rich-text>
|
</scroll-view>
|
</template>
|
|
<!-- 错误提示 -->
|
<u-toast ref="uToast"></u-toast>
|
</view>
|
</template>
|
|
<script>
|
import { detail } from '@/api/news.js'
|
|
export default {
|
data() {
|
return {
|
detailId: '',
|
loading: true,
|
detailData: {
|
title: '',
|
content: '',
|
publishDate: ''
|
}
|
}
|
},
|
onLoad(options) {
|
if (options.id) {
|
this.detailId = options.id
|
this.loadDetailData()
|
}
|
},
|
methods: {
|
async loadDetailData() {
|
this.loading = true
|
try {
|
const res = await detail(this.detailId)
|
if (res.statusCode === 200) {
|
this.detailData = {
|
title: res.data.data.title || '无标题',
|
content: res.data.data.content || '',
|
publishDate: res.data.data.publishDate || ''
|
}
|
} else {
|
this.showError('加载失败: ' + (res.message || '未知错误'))
|
}
|
} catch (error) {
|
console.error('加载详情出错:', error)
|
this.showError('网络请求失败')
|
} finally {
|
this.loading = false
|
}
|
},
|
|
formatDate(dateString) {
|
if (!dateString) return '未知时间'
|
|
try {
|
const date = new Date(dateString)
|
if (isNaN(date.getTime())) return dateString
|
|
const year = date.getFullYear()
|
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
const day = date.getDate().toString().padStart(2, '0')
|
const hours = date.getHours().toString().padStart(2, '0')
|
const minutes = date.getMinutes().toString().padStart(2, '0')
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
} catch (e) {
|
console.error('日期格式化错误:', e)
|
return dateString
|
}
|
},
|
|
formatContent(content) {
|
if (!content) return ''
|
|
// 基础处理:确保图片自适应
|
const processedContent = content
|
.replace(/<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:20rpx auto;"')
|
.replace(/<table/gi, '<table style="width:100%;border-collapse:collapse;"')
|
.replace(/<td/gi, '<td style="border:1px solid #ddd;padding:8px;"')
|
|
return processedContent
|
},
|
|
showError(message) {
|
this.$refs.uToast.show({
|
type: 'error',
|
message: message,
|
duration: 2000
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.detail-page {
|
padding: 30rpx;
|
min-height: 100vh;
|
background-color: #f8f8f8;
|
}
|
|
.loading-container {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
height: 60vh;
|
|
.loading-text {
|
margin-top: 20rpx;
|
font-size: 28rpx;
|
color: #999;
|
}
|
}
|
|
.header {
|
background-color: #fff;
|
border-radius: 16rpx;
|
padding: 30rpx;
|
margin-bottom: 30rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
.title {
|
display: block;
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
line-height: 1.5;
|
margin-bottom: 20rpx;
|
}
|
|
.meta {
|
display: flex;
|
justify-content: flex-end;
|
font-size: 24rpx;
|
color: #999;
|
|
.date {
|
margin-left: 15rpx;
|
}
|
}
|
}
|
|
.content-wrapper {
|
background-color: #fff;
|
border-radius: 16rpx;
|
padding: 30rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
height: calc(100vh - 300rpx);
|
|
.content {
|
font-size: 30rpx;
|
line-height: 1.8;
|
color: #333;
|
|
// 覆盖rich-text内部元素样式
|
/deep/ p {
|
margin-bottom: 20rpx;
|
}
|
|
/deep/ h1, /deep/ h2, /deep/ h3 {
|
margin: 40rpx 0 20rpx;
|
font-weight: bold;
|
}
|
|
/deep/ ul, /deep/ ol {
|
padding-left: 40rpx;
|
margin-bottom: 20rpx;
|
}
|
|
/deep/ li {
|
margin-bottom: 10rpx;
|
}
|
|
/deep/ a {
|
color: #007aff;
|
word-break: break-all;
|
}
|
|
/deep/ blockquote {
|
border-left: 4rpx solid #ddd;
|
padding-left: 20rpx;
|
color: #666;
|
margin: 20rpx 0;
|
}
|
}
|
}
|
</style>
|