buddhism/pages/article/article-detail.vue

236 lines
5.2 KiB
Vue
Raw Permalink Normal View History

<template>
<view class="page">
<!-- 自定义导航栏 -->
<custom-navbar :title="articleData.title || '文章详情'" />
2025-08-14 11:22:53 +08:00
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-content">
<text>加载中...</text>
</view>
</view>
2025-08-14 11:22:53 +08:00
<!-- 文章内容 -->
<view v-else-if="articleData" class="article-container">
<!-- 文章标题 -->
<view class="article-header">
<text class="article-title">{{ articleData.title }}</text>
<text v-if="articleData.subtitle" class="article-subtitle">{{ articleData.subtitle }}</text>
</view>
2025-08-14 11:22:53 +08:00
<!-- 文章封面图 -->
<view v-if="articleData.coverUrl" class="article-cover">
<image :src="articleData.coverUrl" mode="aspectFill" />
</view>
2025-08-14 11:22:53 +08:00
<!-- 文章内容 -->
<view class="article-content">
<rich-text :nodes="articleData.content"></rich-text>
</view>
2025-08-14 11:22:53 +08:00
<!-- 文章信息 -->
<view class="article-info">
<text class="info-item">发布时间{{ formatTime(articleData.createTime) }}</text>
2025-08-14 11:22:53 +08:00
<text v-if="articleData.templeName" class="info-item"
>寺庙{{ articleData.templeName }}</text
>
</view>
</view>
2025-08-14 11:22:53 +08:00
<!-- 错误状态 -->
<view v-else class="error-container">
<view class="error-content">
<text>内容加载失败</text>
<button class="retry-btn" @click="loadArticleData">重新加载</button>
</view>
</view>
</view>
</template>
<script>
2025-08-14 11:22:53 +08:00
import CustomNavbar from '../../components/custom-navbar/custom-navbar.vue'
export default {
components: {
CustomNavbar,
},
data() {
return {
loading: true,
articleData: null,
articleId: null,
}
2025-08-14 11:22:53 +08:00
},
onLoad(options) {
// 从页面参数或本地存储获取文章数据
if (options.id) {
this.articleId = options.id
this.loadArticleData()
} else {
// 从本地存储获取文章数据
const storedArticle = uni.getStorageSync('currentArticle')
if (storedArticle) {
this.articleData = storedArticle
this.loading = false
// 清除本地存储
uni.removeStorageSync('currentArticle')
} else {
2025-08-14 11:22:53 +08:00
this.loading = false
uni.showToast({
2025-08-14 11:22:53 +08:00
title: '文章数据不存在',
icon: 'none',
})
}
}
},
2025-08-14 11:22:53 +08:00
methods: {
// 加载文章数据
async loadArticleData() {
if (!this.articleId) {
this.loading = false
return
}
this.loading = true
try {
const { getArticleById } = await import('@/api/article/article.js')
const response = await getArticleById(this.articleId)
if (response.code === 200 && response.data) {
this.articleData = response.data
} else {
uni.showToast({
title: response.msg || '获取文章失败',
icon: 'none',
})
}
} catch (error) {
console.error('获取文章详情失败:', error)
uni.showToast({
title: '网络错误',
icon: 'none',
})
} finally {
this.loading = false
}
},
// 格式化时间
formatTime(timeStr) {
if (!timeStr) return ''
const date = new Date(timeStr)
return (
date.toLocaleDateString('zh-CN') +
' ' +
date.toLocaleTimeString('zh-CN', { hour12: false })
)
},
},
}
</script>
<style lang="scss" scoped>
2025-08-14 11:22:53 +08:00
.page {
min-height: 100vh;
background-color: #f5f5f5;
}
.loading-container,
.error-container {
display: flex;
justify-content: center;
align-items: center;
height: 60vh;
}
2025-08-14 11:22:53 +08:00
.loading-content,
.error-content {
text-align: center;
color: #666;
font-size: 28rpx;
}
.retry-btn {
margin-top: 20rpx;
padding: 20rpx 40rpx;
background-color: #4c97e7;
color: white;
border: none;
border-radius: 10rpx;
font-size: 28rpx;
}
2025-08-14 11:22:53 +08:00
.article-container {
padding: 30rpx;
background-color: white;
margin: 20rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}
2025-08-14 11:22:53 +08:00
.article-header {
margin-bottom: 30rpx;
}
2025-08-14 11:22:53 +08:00
.article-title {
display: block;
2025-08-14 11:22:53 +08:00
font-size: 36rpx;
font-weight: bold;
color: #333;
line-height: 1.4;
margin-bottom: 10rpx;
}
2025-08-14 11:22:53 +08:00
.article-subtitle {
display: block;
font-size: 28rpx;
color: #666;
line-height: 1.3;
}
.article-cover {
margin-bottom: 30rpx;
border-radius: 15rpx;
overflow: hidden;
image {
width: 100%;
height: 400rpx;
}
}
.article-content {
margin-bottom: 30rpx;
line-height: 1.8;
font-size: 30rpx;
color: #333;
:deep(p) {
margin-bottom: 20rpx;
}
:deep(a) {
color: #4c97e7;
text-decoration: underline;
}
:deep(img) {
max-width: 100%;
height: auto;
margin: 20rpx 0;
}
}
.article-info {
padding-top: 30rpx;
border-top: 1rpx solid #eee;
.info-item {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 10rpx;
}
}
</style>