229 lines
4.9 KiB
Vue
229 lines
4.9 KiB
Vue
<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> |