buddhism/pages/ancient/ancientTourById.vue

408 lines
9.7 KiB
Vue
Raw Normal View History

2025-08-12 12:02:20 +08:00
<template>
<view class="page">
<!-- 使用自定义导航栏组件 -->
2025-08-14 11:22:53 +08:00
<custom-navbar ref="customNavbar" :title="tourDetail.title || '古刹巡礼'" />
<tile-grid />
2025-08-14 10:50:12 +08:00
<!-- 主要内容区域 -->
<view class="content-container">
<!-- 文章头部信息 -->
<view class="article-header">
2025-08-14 11:22:53 +08:00
<text class="article-title">{{ tourDetail.title || "加载中..." }}</text>
<text class="article-time"
>{{ formatTime(tourDetail.createTime) }}
</text>
2025-08-14 10:50:12 +08:00
</view>
<!-- 封面图片 -->
2025-08-14 11:22:53 +08:00
<view v-if="tourDetail.coverUrl" class="cover-image-container">
<image
:src="tourDetail.coverUrl"
class="cover-image"
mode="aspectFill"
@error="handleImageError"
>
2025-08-14 10:50:12 +08:00
</image>
</view>
<!-- 文章内容 -->
2025-08-14 11:22:53 +08:00
<view v-if="tourDetail.content" class="article-content">
2025-08-14 10:50:12 +08:00
<rich-text :nodes="processedContent"></rich-text>
</view>
<!-- 加载状态 -->
2025-08-14 11:22:53 +08:00
<view v-if="loading" class="loading-container">
2025-08-14 10:50:12 +08:00
<text class="loading-text">加载中...</text>
2025-08-12 12:02:20 +08:00
</view>
2025-08-14 10:50:12 +08:00
<!-- 相关阅读区域 -->
2025-08-14 11:22:53 +08:00
<view v-if="relevantArticles.length > 0" class="relevant-section">
2025-08-14 10:50:12 +08:00
<view class="section-title">
<text class="title-text">相关阅读</text>
2025-08-12 12:02:20 +08:00
</view>
2025-08-14 10:50:12 +08:00
<view class="relevant-list">
2025-08-14 11:22:53 +08:00
<view
v-for="(item, index) in relevantArticles"
:key="index"
class="relevant-item"
@click="goToArticle(item)"
>
2025-08-14 10:50:12 +08:00
<view class="item-content">
2025-08-14 12:02:30 +08:00
<view class="title-row">
2025-08-14 13:56:46 +08:00
<text class="item-title">古刹巡礼</text>
<text v-if="item.title" class="item-subtitle"
>{{ item.title }}
2025-08-14 12:02:30 +08:00
</text>
</view>
2025-08-14 10:50:12 +08:00
<view class="item-meta">
<text class="item-time">{{ formatTime(item.createTime) }}</text>
</view>
</view>
</view>
2025-08-12 12:02:20 +08:00
</view>
</view>
</view>
</view>
</template>
<script>
2025-08-14 11:22:53 +08:00
import { CommonEnum } from "@/enum/common.js";
import { getRelevantArticles, getTourById } from "@/api/article/article.js";
2025-08-12 12:02:20 +08:00
import CustomNavbar from "../../components/custom-navbar/custom-navbar.vue";
export default {
components: {
2025-08-14 11:22:53 +08:00
CustomNavbar,
2025-08-12 12:02:20 +08:00
},
data() {
return {
CommonEnum,
2025-08-14 11:22:53 +08:00
tourId: "24", // 巡礼ID默认为24
2025-08-14 10:50:12 +08:00
tourDetail: {
2025-08-14 11:22:53 +08:00
title: "",
content: "",
createTime: "",
coverUrl: "",
2025-08-12 12:02:20 +08:00
},
2025-08-14 10:50:12 +08:00
relevantArticles: [], // 相关文章列表
2025-08-14 11:22:53 +08:00
loading: false,
};
2025-08-12 12:02:20 +08:00
},
2025-08-14 10:50:12 +08:00
computed: {
// 处理文章内容确保HTML正确显示
processedContent() {
2025-08-14 11:22:53 +08:00
if (!this.tourDetail.content) return "";
2025-08-14 10:50:12 +08:00
// 处理HTML内容确保样式正确
let content = this.tourDetail.content;
2025-08-14 11:22:53 +08:00
2025-08-14 10:50:12 +08:00
// 添加基本样式
content = `<div style="
2025-08-14 11:58:05 +08:00
font-size: 28rpx;
line-height: 1.8;
color: #333;
word-wrap: break-word;
2025-08-14 10:50:12 +08:00
word-break: break-all;
padding: 20rpx 0;
">${content}</div>`;
2025-08-14 11:22:53 +08:00
2025-08-14 10:50:12 +08:00
return content;
2025-08-14 11:22:53 +08:00
},
2025-08-14 10:50:12 +08:00
},
onLoad(options) {
// 获取传递的参数如果没有则使用默认值24
if (options.id) {
this.tourId = options.id;
}
// 无论是否有参数都加载数据
this.fetchTourDetail();
this.fetchRelevantArticles();
2025-08-12 12:02:20 +08:00
},
methods: {
2025-08-14 10:50:12 +08:00
// 获取巡礼详情
async fetchTourDetail() {
2025-08-12 12:02:20 +08:00
try {
2025-08-14 10:50:12 +08:00
this.loading = true;
const res = await getTourById(this.tourId);
2025-08-14 11:22:53 +08:00
2025-08-12 12:02:20 +08:00
if (res.code === 200 && res.data) {
2025-08-14 10:50:12 +08:00
this.tourDetail = {
2025-08-14 11:22:53 +08:00
title: res.data.title || "",
content: res.data.content || "",
createTime: res.data.createTime || "",
coverUrl: res.data.coverUrl || "",
2025-08-14 10:50:12 +08:00
};
2025-08-12 12:02:20 +08:00
} else {
uni.showToast({
2025-08-14 11:22:53 +08:00
title: res.msg || "获取文章详情失败",
icon: "none",
2025-08-14 10:50:12 +08:00
});
2025-08-12 12:02:20 +08:00
}
2025-08-14 10:50:12 +08:00
} catch (error) {
2025-08-14 11:22:53 +08:00
console.error("获取文章详情失败:", error);
2025-08-12 12:02:20 +08:00
uni.showToast({
2025-08-14 11:22:53 +08:00
title: "网络错误",
icon: "none",
2025-08-14 10:50:12 +08:00
});
2025-08-12 12:02:20 +08:00
} finally {
2025-08-14 10:50:12 +08:00
this.loading = false;
2025-08-12 12:02:20 +08:00
}
},
2025-08-14 10:50:12 +08:00
// 获取相关文章
async fetchRelevantArticles() {
try {
const res = await getRelevantArticles(this.tourId);
2025-08-14 11:22:53 +08:00
2025-08-14 10:50:12 +08:00
if (res.code === 200 && res.data) {
2025-08-14 11:22:53 +08:00
this.relevantArticles = res.data.map((item) => ({
2025-08-14 10:58:36 +08:00
id: item.id || item.articleId, // 兼容不同的ID字段名
2025-08-14 11:22:53 +08:00
title: item.title || "",
2025-08-14 13:48:12 +08:00
createTime: item.createTime || null, // 保持原始值,让 formatTime 方法处理
2025-08-14 10:50:12 +08:00
}));
}
} catch (error) {
2025-08-14 11:22:53 +08:00
console.error("获取相关文章失败:", error);
2025-08-14 10:50:12 +08:00
// 相关文章获取失败不影响主页面显示
2025-08-12 12:02:20 +08:00
}
},
2025-08-14 10:50:12 +08:00
// 格式化时间
formatTime(timeStr) {
2025-08-14 13:48:12 +08:00
// 如果时间为空、null 或 undefined返回"不详"
2025-08-14 13:56:46 +08:00
if (!timeStr || timeStr === "") {
2025-08-14 13:48:12 +08:00
return "不详";
}
2025-08-14 11:22:53 +08:00
2025-08-14 10:50:12 +08:00
try {
const date = new Date(timeStr);
2025-08-14 13:48:12 +08:00
// 检查日期是否有效
if (isNaN(date.getTime())) {
return "不详";
}
2025-08-14 10:50:12 +08:00
const year = date.getFullYear();
2025-08-14 11:22:53 +08:00
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
2025-08-14 10:50:12 +08:00
return `${year}-${month}-${day} ${hours}:${minutes}`;
} catch (error) {
2025-08-14 13:48:12 +08:00
console.error("时间格式化错误:", error, "原始时间:", timeStr);
return "不详";
2025-08-12 12:02:20 +08:00
}
},
2025-08-14 11:22:53 +08:00
// 跳转到相关文章
goToArticle(article) {
console.log("点击相关文章:", article);
if (article && article.id) {
console.log("跳转到文章ID:", article.id);
uni.navigateTo({
url: `/pages/ancient/ancientTourById?id=${article.id}`,
success: () => {
console.log("跳转成功");
},
fail: (error) => {
console.error("跳转失败:", error);
uni.showToast({
title: "跳转失败",
icon: "none",
});
},
});
} else {
console.warn("文章ID不存在:", article);
uni.showToast({
title: "文章信息不完整",
icon: "none",
});
}
},
// 处理图片加载错误
handleImageError() {
console.log("封面图片加载失败");
// 可以设置默认图片或隐藏图片容器
},
},
};
2025-08-12 12:02:20 +08:00
</script>
<style lang="scss">
2025-08-14 11:58:05 +08:00
// 页面基础样式
2025-08-12 12:02:20 +08:00
.page {
2025-08-14 11:22:53 +08:00
background: #f6f1e7;
2025-08-12 12:02:20 +08:00
width: 100%;
min-height: 100vh;
flex-direction: column;
align-items: center;
}
2025-08-14 11:58:05 +08:00
// 内容容器
2025-08-14 10:50:12 +08:00
.content-container {
width: 100%;
2025-08-14 11:58:05 +08:00
padding: 0 52rpx;
2025-08-14 10:50:12 +08:00
box-sizing: border-box;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
background: #fff;
2025-08-14 10:50:12 +08:00
}
2025-08-14 11:58:05 +08:00
// 文章头部区域
2025-08-14 10:50:12 +08:00
.article-header {
2025-08-14 11:58:05 +08:00
display: flex;
justify-content: space-between;
align-items: center;
2025-08-14 10:50:12 +08:00
background: #fff;
2025-08-14 11:58:05 +08:00
padding: 32rpx 30rpx;
2025-08-14 10:50:12 +08:00
border-radius: 16rpx;
2025-08-14 13:56:46 +08:00
//box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
.article-title {
font-weight: 500;
font-size: 44rpx;
color: #3d3d3d;
line-height: 60rpx;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
}
.article-time {
display: block;
font-weight: 400;
font-size: 24rpx;
color: #808080;
line-height: 32rpx;
}
2025-08-12 12:02:20 +08:00
}
2025-08-14 11:58:05 +08:00
// 封面图片区域
2025-08-14 10:50:12 +08:00
.cover-image-container {
background: #fff;
2025-08-14 11:58:05 +08:00
margin-bottom: 32rpx;
2025-08-14 10:50:12 +08:00
overflow: hidden;
2025-08-14 13:56:46 +08:00
//box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
//border: red solid 1px;
2025-08-12 12:02:20 +08:00
2025-08-14 11:58:05 +08:00
.cover-image {
width: 100%;
2025-08-14 13:48:12 +08:00
height: 340rpx;
2025-08-14 11:58:05 +08:00
display: block;
}
2025-08-12 12:02:20 +08:00
}
2025-08-14 11:58:05 +08:00
// 文章内容区域
2025-08-14 10:50:12 +08:00
.article-content {
background: #fff;
2025-08-14 11:58:05 +08:00
2025-08-12 12:02:20 +08:00
border-radius: 16rpx;
2025-08-14 11:58:05 +08:00
margin-bottom: 32rpx;
2025-08-14 13:56:46 +08:00
//box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
2025-08-14 10:50:12 +08:00
min-height: 200rpx;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 10:50:12 +08:00
}
2025-08-14 11:58:05 +08:00
// 加载状态区域
2025-08-14 10:50:12 +08:00
.loading-container {
background: #fff;
padding: 60rpx 30rpx;
border-radius: 16rpx;
text-align: center;
margin-bottom: 20rpx;
2025-08-14 11:58:05 +08:00
.loading-text {
font-size: 28rpx;
color: #999;
}
2025-08-14 10:50:12 +08:00
}
2025-08-14 11:58:05 +08:00
// 相关阅读区域
2025-08-14 10:50:12 +08:00
.relevant-section {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
2025-08-14 13:56:46 +08:00
//box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
2025-08-14 11:58:05 +08:00
.section-title {
.title-text {
font-weight: 400;
font-size: 36rpx;
color: #695347;
line-height: 50rpx;
border-bottom: 2rpx solid #a24242;
}
}
.relevant-list {
padding: 0;
}
.relevant-item {
display: flex;
align-items: center;
2025-08-14 14:08:05 +08:00
padding: 30rpx 0;
2025-08-14 11:58:05 +08:00
border-bottom: 1rpx solid #f0f0f0;
transition: background-color 0.3s ease;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
&:last-child {
border-bottom: none;
}
2025-08-14 10:58:36 +08:00
2025-08-14 11:58:05 +08:00
&:active {
background-color: #f5f5f5;
}
2025-08-14 10:50:12 +08:00
2025-08-14 11:58:05 +08:00
.item-content {
flex: 1;
margin-right: 20rpx;
2025-08-14 12:02:30 +08:00
.title-row {
.item-title {
font-weight: 400;
font-size: 32rpx;
color: #522510;
line-height: 44rpx;
2025-08-14 13:39:25 +08:00
padding-right: 10rpx;
border-right: 4rpx solid #522510;
2025-08-14 12:02:30 +08:00
}
2025-08-14 10:50:12 +08:00
2025-08-14 12:02:30 +08:00
.item-subtitle {
2025-08-14 13:39:25 +08:00
padding-left: 10rpx;
2025-08-14 12:02:30 +08:00
font-weight: 400;
font-size: 32rpx;
color: #522510;
line-height: 44rpx;
}
2025-08-14 11:58:05 +08:00
}
2025-08-14 10:50:12 +08:00
2025-08-14 11:58:05 +08:00
.item-meta {
2025-08-14 13:56:46 +08:00
padding-top: 22rpx;
2025-08-14 11:58:05 +08:00
display: flex;
align-items: center;
justify-content: space-between;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
.item-time {
font-size: 22rpx;
color: #999;
flex-shrink: 0;
2025-08-14 13:56:46 +08:00
//border: red solid 1px;
2025-08-14 11:58:05 +08:00
}
2025-08-14 13:48:12 +08:00
.debug-time {
font-size: 18rpx;
color: #ccc;
margin-left: 10rpx;
flex-shrink: 0;
}
2025-08-14 11:58:05 +08:00
}
}
}
2025-08-12 12:02:20 +08:00
}
2025-08-14 11:22:53 +08:00
</style>