buddhism/pages/article/article-detail.vue

229 lines
4.9 KiB
Vue
Raw Normal View History

<template>
<view class="page">
<!-- 自定义导航栏 -->
<custom-navbar :title="articleData.title || '文章详情'" />
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<view class="loading-content">
<text>加载中...</text>
</view>
</view>
<!-- 文章内容 -->
<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>
<!-- 文章封面图 -->
<view v-if="articleData.coverUrl" class="article-cover">
<image :src="articleData.coverUrl" mode="aspectFill" />
</view>
<!-- 文章内容 -->
<view class="article-content">
<rich-text :nodes="articleData.content"></rich-text>
</view>
<!-- 文章信息 -->
<view class="article-info">
<text class="info-item">发布时间{{ formatTime(articleData.createTime) }}</text>
<text v-if="articleData.templeName" class="info-item">寺庙{{ articleData.templeName }}</text>
</view>
</view>
<!-- 错误状态 -->
<view v-else class="error-container">
<view class="error-content">
<text>内容加载失败</text>
<button class="retry-btn" @click="loadArticleData">重新加载</button>
</view>
</view>
</view>
</template>
<script>
import CustomNavbar from "../../components/custom-navbar/custom-navbar.vue";
export default {
components: {
CustomNavbar
},
data() {
return {
loading: true,
articleData: null,
articleId: null
}
},
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 {
this.loading = false;
uni.showToast({
title: '文章数据不存在',
icon: 'none'
});
}
}
},
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>
.page {
min-height: 100vh;
background-color: #f5f5f5;
}
.loading-container,
.error-container {
display: flex;
justify-content: center;
align-items: center;
height: 60vh;
}
.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;
}
.article-container {
padding: 30rpx;
background-color: white;
margin: 20rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}
.article-header {
margin-bottom: 30rpx;
}
.article-title {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #333;
line-height: 1.4;
margin-bottom: 10rpx;
}
.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>