buddhism/pages/index/index.vue

830 lines
19 KiB
Vue
Raw Normal View History

2025-07-28 10:53:56 +08:00
<template>
2025-08-14 11:22:53 +08:00
<view class="page">
<!-- 加载状态指示器 -->
<view v-if="loading" class="loading-overlay">
<view class="loading-content">
<text>正在加载配置...</text>
</view>
</view>
<!-- 背景图 -->
2025-08-15 15:26:13 +08:00
<image :src="templeData.imgUrl" class="bj" mode="aspectFill"></image>
2025-08-14 11:22:53 +08:00
<!-- 音频与VR图标 -->
<view class="tubiao">
<view class="audio-controls">
<image
2025-09-05 18:06:19 +08:00
v-if="isAudioPlaying"
2025-08-14 11:22:53 +08:00
:src="pageConfig.topIcons.leftIcon.img"
mode=""
2025-09-05 18:06:19 +08:00
@click="toggleAudio"
2025-08-14 11:22:53 +08:00
></image>
<image
2025-09-05 18:06:19 +08:00
v-if="!isAudioPlaying"
2025-08-14 11:22:53 +08:00
:src="pageConfig.topIcons.rightIcon.img"
mode=""
2025-09-05 18:06:19 +08:00
@click="toggleAudio"
2025-08-14 11:22:53 +08:00
></image>
</view>
<view class="tubiao-item">
<!-- <view class="tubiao-item" @click="goToVR">-->
<!-- <image :src="pageConfig.topIcons.bottomIcon.img" mode=""></image>-->
2025-08-14 11:22:53 +08:00
</view>
</view>
<!-- 底部 -->
<view class="bot">
<view class="name">
<image :src="bottomSection.openingTime.decorationImg" mode=""></image>
<text>{{ bottomSection.openingTime.title }}</text>
<image :src="bottomSection.openingTime.decorationImg" mode=""></image>
</view>
2025-08-15 15:26:13 +08:00
<view class="time">
{{ templeData.startTime }} - {{ templeData.endTime }}
</view>
<!-- 公告 -->
<view class="announcement">
<image :src="pageConfig.announcement.icon" class="ggimg" mode="" />
<view class="marquee-wrap">
<view
:style="{ transform: `translateX(${marqueeX}rpx)` }"
class="marquee"
>
{{ templeData.bulletinContent }}
</view>
</view>
</view>
2025-08-14 11:22:53 +08:00
<view class="hua">
<image
mode=""
2025-08-15 15:26:13 +08:00
src="https://api.ccttiot.com/smartmeter/img/static/uyz1LDPTjPqeOzBMjLZ7"
2025-08-14 11:22:53 +08:00
></image>
</view>
2025-08-04 16:17:43 +08:00
<view class="list-scroll">
2025-08-14 11:22:53 +08:00
<view class="list">
<!-- 导航项目列表 -->
<view
v-for="(item, index) in navigationItems"
:key="index"
2025-08-15 15:26:13 +08:00
class="li"
2025-08-14 11:22:53 +08:00
@click="navigateToPage(item, index)"
>
<image :src="item.img" mode=""></image>
<view class="da">
{{ item.title }}
</view>
<view class="xiao">
{{ item.subtitle }}
</view>
</view>
<!-- 空状态提示 -->
2025-08-15 15:26:13 +08:00
<view
v-if="!loading && navigationItems.length === 0"
class="empty-state"
>
2025-08-14 11:22:53 +08:00
<text>暂无功能项目</text>
</view>
</view>
</view>
<view
2025-08-15 15:26:13 +08:00
v-if="
bottomSection.prayerSection &&
bottomSection.prayerSection.backgroundImg
"
2025-08-14 11:22:53 +08:00
class="bottom"
>
2025-08-15 15:26:13 +08:00
<image
:src="bottomSection.prayerSection.backgroundImg"
mode=""
@click="goToPersonalCenter"
></image>
2025-09-19 10:56:19 +08:00
<!-- <view class="rixing">-->
<!-- {{ bottomSection.prayerSection.title }}-->
<!-- </view>-->
2025-08-14 11:22:53 +08:00
<view class="qifu" @click="goToPray">
2025-08-15 15:26:13 +08:00
<image
:src="bottomSection.prayerSection.prayerButton.icon"
mode=""
></image>
2025-08-14 11:22:53 +08:00
<view class="zaixian">
<view class="da">
{{ bottomSection.prayerSection.prayerButton.title }}
2025-08-06 12:04:17 +08:00
</view>
2025-08-14 11:22:53 +08:00
<view class="xiao">
{{ bottomSection.prayerSection.prayerButton.subtitle }}
</view>
</view>
</view>
</view>
</view>
</view>
2025-07-28 10:53:56 +08:00
</template>
<script>
2025-08-15 15:26:13 +08:00
import { navigateToPage } from "../../utils/router.js";
import { getHomeConfig, getTempleIndex } from "../../api/index/index.js";
import { getArticleById } from "../../api/article/article.js";
export default {
data() {
return {
marqueeX: "", // 初始位置和marquee-wrap宽度一致
timer: null,
loading: true, // 默认为true等待API数据加载
// 页面配置数据完全依赖API
pageConfig: {
background: { img: "" },
announcement: { icon: "", text: "" },
topIcons: {
leftIcon: { hidden: false, img: "" },
rightIcon: { img: "" },
bottomIcon: { img: "" },
2025-08-14 11:22:53 +08:00
},
2025-08-15 15:26:13 +08:00
},
navigationItems: [],
bottomSection: {
openingTime: {
title: "",
time: "",
decorationImg: "",
2025-08-14 11:22:53 +08:00
},
},
2025-08-15 15:26:13 +08:00
templeData: {
imgUrl: "",
bulletinContent: "",
startTime: "",
endTime: "",
audioUrl: "",
2025-08-14 11:22:53 +08:00
},
2025-09-05 18:06:19 +08:00
isAudioPlaying: true, // 改为默认开启
2025-08-15 15:26:13 +08:00
audioContext: null,
};
},
onLoad() {
// 页面加载时获取配置
this.loadHomeConfig();
// 获取寺庙数据
this.loadTempleData();
},
// 添加下拉刷新支持
onPullDownRefresh() {
console.log("用户触发下拉刷新");
Promise.all([this.loadHomeConfig(), this.loadTempleData()]).finally(() => {
uni.stopPullDownRefresh();
});
},
onShow() {
// 启动跑马灯(方法内部会检查是否有文本)
this.startMarquee();
},
onUnload() {
this.stopMarquee();
// 停止音频播放
this.stopAudio();
},
methods: {
/**
* 获取首页配置
*/
async loadHomeConfig() {
console.log("开始获取首页配置...");
this.loading = true;
// 重试机制
const maxRetries = 3;
let retryCount = 0;
while (retryCount < maxRetries) {
2025-08-14 11:22:53 +08:00
try {
2025-08-15 15:26:13 +08:00
console.log(`${retryCount + 1} 次尝试获取配置...`);
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
const response = await getHomeConfig();
console.log("API响应:", response);
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 简化验证:只检查关键字段
if (response?.code === 200 && response?.data?.[0]?.body) {
const parsedConfig = JSON.parse(response.data[0].body);
// 更新页面配置
this.updatePageConfig(parsedConfig);
2025-08-14 11:22:53 +08:00
// 重新启动跑马灯
2025-08-15 15:26:13 +08:00
this.stopMarquee();
this.startMarquee();
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
console.log("配置加载成功");
break;
2025-08-14 11:22:53 +08:00
} else {
2025-08-15 15:26:13 +08:00
throw new Error("API响应数据无效");
2025-08-14 11:22:53 +08:00
}
} catch (error) {
2025-08-15 15:26:13 +08:00
retryCount++;
console.error(`${retryCount} 次尝试失败:`, error.message);
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
if (retryCount >= maxRetries) {
console.error("所有重试都失败了");
this.useDefaultConfig();
break;
} else {
await new Promise((resolve) =>
setTimeout(resolve, retryCount * 1000),
);
}
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
}
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
this.loading = false;
console.log("配置加载完成");
},
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
/**
* 处理配置加载失败
*/
useDefaultConfig() {
console.log("API获取失败无法加载配置");
// 不设置任何默认配置,保持初始化的空状态
// 数据保持为初始化时的空结构
// 显示提示信息
uni.showModal({
title: "加载失败",
content: "无法获取页面配置,请检查网络连接后重试",
showCancel: true,
cancelText: "取消",
confirmText: "重试",
success: (res) => {
if (res.confirm) {
this.loadHomeConfig();
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
},
});
},
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
/**
* 更新页面配置
*/
updatePageConfig(parsedConfig) {
// 直接更新配置使用默认值防止undefined
this.pageConfig = parsedConfig.pageConfig || this.pageConfig;
this.navigationItems = parsedConfig.navigationItems || [];
this.bottomSection = parsedConfig.bottomSection || this.bottomSection;
console.log("配置更新完成");
},
/**
* 获取寺庙数据
*/
async loadTempleData() {
try {
console.log("开始获取寺庙数据...");
const response = await getTempleIndex();
console.log("寺庙数据API响应:", response);
if (response?.code === 200 && response?.data) {
this.templeData = {
imgUrl: response.data.imgUrl || "",
bulletinContent: response.data.bulletinContent || "",
startTime: response.data.startTime || "",
endTime: response.data.endTime || "",
audioUrl: response.data.audioUrl || "",
};
uni.setStorageSync("abbotId", response.data.abbotId);
// 重新启动跑马灯
this.stopMarquee();
this.startMarquee();
2025-09-05 18:06:19 +08:00
// 自动播放音频
if (this.templeData.audioUrl) {
this.playAudio();
}
2025-08-15 15:26:13 +08:00
console.log("寺庙数据加载成功");
} else {
throw new Error("寺庙数据API响应无效");
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
} catch (error) {
console.error("获取寺庙数据失败:", error);
uni.showToast({
title: "获取寺庙数据失败",
icon: "none",
});
}
},
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
startMarquee() {
// 简单检查公告文本是否存在
const announcementText =
this.templeData?.bulletinContent || this.pageConfig?.announcement?.text;
if (!announcementText) {
return;
}
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 停止之前的定时器
this.stopMarquee();
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 估算文字宽度每个字24rpx
const textWidth = announcementText.length * 24;
this.timer = setInterval(() => {
this.marqueeX--;
if (this.marqueeX < -textWidth) {
this.marqueeX = 600;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
}, 16);
},
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
stopMarquee() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 兼容两种跳转方式page路由跳转 或 aid文章详情跳转
async navigateToPage(item, index) {
try {
console.log("导航项信息:", item);
console.log("导航项索引:", index);
// 优先使用page字段进行路由跳转
if (item.page) {
console.log("使用page字段进行路由跳转:", item.page);
// 导入路由工具
const { navigateToPage: routerNavigate } = await import(
"../../utils/router.js"
);
routerNavigate(item.page);
return;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
// 如果没有page字段则使用aid进行文章详情跳转
if (item.aid) {
console.log("使用aid字段获取文章详情:", item.aid);
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 显示加载提示
uni.showLoading({
title: "加载中...",
mask: true,
});
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
// 调用API获取文章详情
const response = await getArticleById(item.aid);
// 隐藏加载提示
uni.hideLoading();
if (response.code === 200 && response.data) {
console.log("获取文章详情成功:", response.data);
// 将文章数据存储到本地,供目标页面使用
uni.setStorageSync("currentArticle", response.data);
// 直接跳转到文章详情页面
uni.navigateTo({
url: "/pages/article/article-detail",
fail: (err) => {
console.error("跳转到文章详情页面失败:", err);
uni.showToast({
title: "页面跳转失败",
icon: "none",
});
},
});
} else {
console.error("获取文章详情失败:", response);
2025-08-14 11:22:53 +08:00
uni.showToast({
2025-08-15 15:26:13 +08:00
title: "获取内容失败",
icon: "none",
});
}
} else {
console.error("导航项既没有page字段也没有aid字段:", item);
2025-08-14 11:22:53 +08:00
uni.showToast({
2025-08-15 15:26:13 +08:00
title: "配置错误",
icon: "none",
});
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
} catch (error) {
// 隐藏加载提示
uni.hideLoading();
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
console.error("导航跳转出错:", error);
2025-08-14 11:22:53 +08:00
uni.showToast({
2025-08-15 15:26:13 +08:00
title: "网络错误",
icon: "none",
});
}
2025-08-14 11:22:53 +08:00
},
2025-07-28 10:53:56 +08:00
2025-08-15 15:26:13 +08:00
/**
* 跳转到祈福页面
*/
goToPray() {
try {
console.log("跳转到祈福页面");
// 使用navigateToPage方法传入参数pray
navigateToPage("pray");
} catch (error) {
console.error("跳转到祈福页面失败:", error);
uni.showToast({
title: "页面跳转失败",
icon: "none",
});
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
},
goToPersonalCenter() {
try {
console.log("跳转到个人中心页面");
navigateToPage("pc");
} catch (error) {
console.error("跳转到祈福页面失败:", error);
uni.showToast({
title: "页面跳转失败",
icon: "none",
});
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
},
2025-09-18 10:47:28 +08:00
goToVR() {
let id = "15";
uni.navigateTo({
url: "/page_user/webViewVR/webViewVR?id=" + id,
});
},
2025-09-05 18:06:19 +08:00
/**
* 切换音频播放状态
*/
toggleAudio() {
if (this.isAudioPlaying) {
this.stopAudio();
} else {
this.playAudio();
}
},
2025-08-15 15:26:13 +08:00
/**
* 播放音频
*/
playAudio() {
if (!this.templeData.audioUrl) {
uni.showToast({
title: "暂无音频资源",
icon: "none",
});
return;
}
try {
// 如果已经在播放,先停止
if (this.audioContext) {
this.stopAudio();
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
// 创建音频上下文
this.audioContext = uni.createInnerAudioContext();
this.audioContext.src = this.templeData.audioUrl;
this.audioContext.loop = true; // 循环播放
// 监听播放状态
this.audioContext.onPlay(() => {
console.log("音频开始播放");
this.isAudioPlaying = true;
2025-09-19 17:40:36 +08:00
// uni.showToast({
// title: "音频已开启",
// icon: "none",
// });
2025-08-15 15:26:13 +08:00
});
this.audioContext.onError((err) => {
console.error("音频播放错误:", err);
this.isAudioPlaying = false;
uni.showToast({
title: "音频播放失败",
icon: "none",
});
});
this.audioContext.onEnded(() => {
console.log("音频播放结束");
this.isAudioPlaying = false;
});
// 开始播放
this.audioContext.play();
} catch (error) {
console.error("音频播放失败:", error);
this.isAudioPlaying = false;
uni.showToast({
title: "音频播放失败",
icon: "none",
});
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
},
/**
* 停止音频
*/
stopAudio() {
if (this.audioContext) {
this.audioContext.stop();
this.audioContext.destroy();
this.audioContext = null;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
this.isAudioPlaying = false;
2025-09-19 17:40:36 +08:00
// uni.showToast({
// title: "音频已关闭",
// icon: "none",
// });
2025-08-15 15:26:13 +08:00
},
},
};
</script>
<style lang="scss">
page {
background-color: #fff;
}
.bot {
position: fixed;
left: 50%;
transform: translateX(-50%);
bottom: 56rpx;
width: 100%;
max-width: 750rpx;
/* 确保不会限制子元素的滚动 */
overflow: visible;
.bottom {
margin-top: 64rpx;
display: flex;
padding: 0 118rpx;
box-sizing: border-box;
2025-09-19 10:56:19 +08:00
justify-content: center;
gap: 20rpx;
2025-08-15 15:26:13 +08:00
image {
width: 64rpx;
height: 64rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
.rixing {
width: 206rpx;
height: 64rpx;
background: #522510;
border-radius: 45rpx 45rpx 45rpx 45rpx;
text-align: center;
line-height: 64rpx;
font-weight: 600;
font-size: 24rpx;
color: #ffffff;
border-radius: 50rpx;
margin-left: 26rpx;
margin-right: 26rpx;
}
.qifu {
width: 194rpx;
height: 64rpx;
border-radius: 41rpx 41rpx 41rpx 41rpx;
border: 1rpx solid #522510;
2025-08-14 11:22:53 +08:00
display: flex;
2025-08-15 15:26:13 +08:00
align-items: center;
justify-content: center;
image {
width: 32rpx;
height: 32rpx;
}
.zaixian {
margin-left: 12rpx;
2025-08-14 11:22:53 +08:00
.da {
font-size: 24rpx;
color: #522510;
2025-08-15 15:26:13 +08:00
font-weight: 600;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
2025-08-14 11:22:53 +08:00
.xiao {
font-size: 12rpx;
color: #522510;
}
}
2025-08-15 15:26:13 +08:00
}
}
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
.list-scroll {
width: 100%;
margin-top: 20rpx;
2025-09-19 17:40:36 +08:00
2025-08-15 15:26:13 +08:00
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
/* 确保滚动容器不被父元素限制 */
position: relative;
z-index: 1;
/* 隐藏滚动条 */
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
}
.list {
display: flex;
width: 1400rpx; /* 更大的宽度确保滚动 */
2025-08-15 15:26:13 +08:00
padding: 0 20rpx;
box-sizing: border-box;
/* 确保内容不被压缩 */
flex-shrink: 0;
.li {
width: 150rpx;
flex: 0 0 150rpx;
2025-08-14 11:22:53 +08:00
text-align: center;
2025-08-15 15:26:13 +08:00
margin-right: 20rpx;
2025-08-14 11:22:53 +08:00
image {
2025-08-15 15:26:13 +08:00
width: 56rpx;
height: 56rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
.da {
font-size: 24rpx;
2025-08-14 11:22:53 +08:00
color: #522510;
2025-08-15 15:26:13 +08:00
margin-top: 8rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
.xiao {
font-size: 12rpx;
color: #522510;
2025-08-14 11:22:53 +08:00
}
}
2025-08-15 15:26:13 +08:00
.empty-state {
width: 100%;
text-align: center;
padding: 40rpx;
color: #999;
font-size: 28rpx;
}
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
.hua {
2025-08-14 11:22:53 +08:00
width: 100%;
2025-08-15 15:26:13 +08:00
text-align: center;
//margin-top: 30rpx;
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
image {
width: 656rpx;
height: 108rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
}
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
.time {
font-weight: 600;
font-size: 32rpx;
color: #522510;
margin-top: 8rpx;
width: 100%;
text-align: center;
}
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
.name {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
2025-08-14 11:22:53 +08:00
2025-08-15 15:26:13 +08:00
text {
font-weight: 600;
font-size: 32rpx;
color: #522510;
margin-left: 24rpx;
margin-right: 24rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
image {
width: 12rpx;
height: 12rpx;
2025-08-14 11:22:53 +08:00
}
}
2025-08-15 15:26:13 +08:00
}
.tubiao {
margin-top: 184rpx;
2025-08-15 15:26:13 +08:00
width: 100%;
display: flex;
padding: 0 40rpx;
box-sizing: border-box;
justify-content: space-between;
.audio-controls {
2025-08-14 11:22:53 +08:00
display: flex;
align-items: center;
2025-08-15 15:26:13 +08:00
gap: 26rpx;
}
image {
width: 82rpx;
height: 82rpx;
display: block;
margin-top: 50rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.9);
opacity: 0.8;
2025-08-14 11:22:53 +08:00
}
}
2025-08-15 15:26:13 +08:00
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.announcement {
width: 100%;
//margin-top: 184rpx;
padding: 20rpx 48rpx;
2025-08-15 15:26:13 +08:00
box-sizing: border-box;
display: flex;
align-items: center;
white-space: nowrap;
.ggimg {
width: 32rpx;
height: 32rpx;
margin-right: 14rpx;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
.marquee-wrap {
width: 600rpx;
overflow: hidden;
position: relative;
height: 32rpx;
2025-08-14 11:22:53 +08:00
display: flex;
align-items: center;
}
2025-08-15 15:26:13 +08:00
.marquee {
white-space: nowrap;
position: absolute;
left: 0;
top: 0;
font-size: 24rpx;
color: #522510;
2025-08-14 11:22:53 +08:00
}
2025-08-15 15:26:13 +08:00
}
.bj {
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
/* 加载状态指示器样式 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-content {
background-color: rgba(255, 255, 255, 0.9);
padding: 40rpx 60rpx;
border-radius: 20rpx;
text-align: center;
}
.loading-content text {
font-size: 28rpx;
color: #333;
}
2025-08-14 11:22:53 +08:00
</style>