<template>
|
<div class="news-detail">
|
<el-card v-loading="loading">
|
<template #header>
|
<div class="news-header">
|
<h1 class="news-title">{{ news.title }}</h1>
|
<div class="news-meta">
|
<span class="author">作者:{{ news.author }}</span>
|
<span class="time">发布时间:{{ formatDate(news.createTime) }}</span>
|
<span class="views">浏览量:{{ news.viewCount }}</span>
|
</div>
|
</div>
|
</template>
|
|
<!-- 封面图片 -->
|
<div v-if="news.coverImage" class="cover-image-container">
|
<el-image
|
:src="news.coverImage"
|
class="cover-image"
|
fit="cover"
|
:preview-src-list="[news.coverImage]"
|
preview-teleported
|
/>
|
</div>
|
|
<div class="news-content" v-html="news.content"></div>
|
|
<div class="news-footer">
|
<el-button @click="goBack">返回列表</el-button>
|
</div>
|
</el-card>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, onMounted } from 'vue'
|
import { useRoute, useRouter } from 'vue-router'
|
import { ElMessage } from 'element-plus'
|
import { getPublishedNews } from '@/api/news'
|
|
const route = useRoute()
|
const router = useRouter()
|
|
const loading = ref(false)
|
const news = ref({
|
id: null,
|
title: '',
|
content: '',
|
summary: '',
|
coverImage: '',
|
author: '',
|
viewCount: 0,
|
state: 1,
|
createTime: '',
|
updateTime: ''
|
})
|
|
// 格式化日期
|
const formatDate = (dateString) => {
|
if (!dateString) return ''
|
const date = new Date(dateString)
|
return date.toLocaleString('zh-CN', {
|
year: 'numeric',
|
month: '2-digit',
|
day: '2-digit',
|
hour: '2-digit',
|
minute: '2-digit'
|
})
|
}
|
|
// 加载新闻数据
|
const loadNews = async () => {
|
try {
|
loading.value = true
|
const data = await getPublishedNews(route.params.id)
|
|
if (data) {
|
news.value = data
|
} else {
|
ElMessage.error('新闻不存在或已下架')
|
router.push('/news/list')
|
}
|
} catch (error) {
|
console.error('加载新闻失败:', error)
|
ElMessage.error('加载新闻失败')
|
router.push('/news/list')
|
} finally {
|
loading.value = false
|
}
|
}
|
|
// 返回
|
const goBack = () => {
|
router.go(-1)
|
}
|
|
onMounted(() => {
|
loadNews()
|
})
|
</script>
|
|
<style scoped>
|
.news-detail {
|
padding: 20px;
|
max-width: 800px;
|
margin: 0 auto;
|
}
|
|
.news-header {
|
text-align: center;
|
}
|
|
.news-title {
|
font-size: 24px;
|
font-weight: 600;
|
color: #333;
|
margin-bottom: 16px;
|
}
|
|
.news-meta {
|
display: flex;
|
justify-content: center;
|
gap: 20px;
|
font-size: 14px;
|
color: #666;
|
margin-bottom: 20px;
|
}
|
|
/* 封面图片样式 */
|
.cover-image-container {
|
text-align: center;
|
margin-bottom: 20px;
|
}
|
|
.cover-image {
|
max-width: 100%;
|
max-height: 400px;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.news-content {
|
line-height: 1.8;
|
font-size: 16px;
|
color: #333;
|
}
|
|
.news-content :deep(img) {
|
max-width: 100%;
|
height: auto;
|
display: block;
|
margin: 10px auto;
|
}
|
|
.news-content :deep(p) {
|
margin: 10px 0;
|
}
|
|
.news-footer {
|
margin-top: 30px;
|
text-align: center;
|
}
|
|
@media (max-width: 768px) {
|
.news-detail {
|
padding: 10px;
|
}
|
|
.news-meta {
|
flex-direction: column;
|
gap: 5px;
|
}
|
|
.news-title {
|
font-size: 20px;
|
}
|
|
.cover-image {
|
max-height: 200px;
|
}
|
}
|
</style>
|