buddhism/pages/nearbystores/index.vue
2025-08-05 17:40:15 +08:00

598 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- 加载状态指示器 -->
<view v-if="loading" class="loading-overlay">
<view class="loading-content">
<text>正在加载配置...</text>
</view>
</view>
<!-- 背景图 -->
<image class="bj" :src="pageConfig.background.img" mode="aspectFill"></image>
<!-- 公告 -->
<view class="announcement">
<image class="ggimg" :src="pageConfig.announcement.icon" mode="" />
<view class="marquee-wrap">
<view class="marquee" :style="{ transform: `translateX(${marqueeX}rpx)` }">
{{ pageConfig.announcement.text }}
</view>
</view>
</view>
<!-- 右侧图标 -->
<view class="tubiao">
<view class="">
<image v-if="pageConfig.topIcons.leftIcon.hidden" :src="pageConfig.topIcons.leftIcon.img" mode=""></image>
<image :src="pageConfig.topIcons.rightIcon.img" mode=""></image>
</view>
<view class="tubiao-item">
<image :src="pageConfig.topIcons.bottomIcon.img" mode=""></image>
</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>
<view class="time">
{{ bottomSection.openingTime.time }}
</view>
<view class="hua">
<image src="https://api.ccttiot.com/smartmeter/img/static/uyz1LDPTjPqeOzBMjLZ7" mode=""></image>
</view>
<view class="list-scroll">
<view class="list">
<view
class="li"
v-for="(item, index) in navigationItems"
:key="item.aid"
@click="navigateToPage(item, index)"
>
<image :src="item.img" mode=""></image>
<view class="da">
{{ item.title }}
</view>
<view class="xiao">
{{ item.subtitle }}
</view>
</view>
</view>
</view>
<view class="bottom">
<!-- <image :src="bottomSection.prayerSection.backgroundImg" mode=""></image>-->
<!-- <view class="rixing">-->
<!-- {{ bottomSection.prayerSection.title }}-->
<!-- </view>-->
<!-- <view class="qifu">-->
<!-- <image :src="bottomSection.prayerSection.prayerButton.icon" mode=""></image>-->
<!-- <view class="zaixian">-->
<!-- <view class="da">-->
<!-- {{ bottomSection.prayerSection.prayerButton.title }}-->
<!-- </view>-->
<!-- <view class="xiao">-->
<!-- {{ bottomSection.prayerSection.prayerButton.subtitle }}-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
</view>
</view>
</view>
</template>
<script>
import navigationData from "../../enum/navigationData.json";
import { navigateToPage } from "../../utils/router.js";
import { getHomeConfig } from "../../api/index/index.js";
import { getArticleById } from "../../api/article/article.js";
export default {
data() {
return {
marqueeX: '', // 初始位置和marquee-wrap宽度一致
timer: null,
loading: false,
// 默认配置如果API获取失败则使用本地配置
pageConfig: navigationData.pageConfig,
navigationItems: navigationData.navigationItems,
bottomSection: navigationData.bottomSection
}
},
onLoad() {
// 页面加载时获取配置
this.loadHomeConfig();
},
onShow() {
// 如果配置已加载,启动跑马灯
if (this.pageConfig && this.pageConfig.announcement) {
this.startMarquee();
}
},
onUnload() {
this.stopMarquee();
},
methods: {
/**
* 获取首页配置
*/
async loadHomeConfig() {
// 添加调试信息
console.log('=== 开始获取首页配置 ===');
console.log('当前时间:', new Date().toISOString());
console.log('页面路径:', this.$mp?.page?.route || 'unknown');
this.loading = true;
console.log('开始获取首页配置...');
// 重试机制
const maxRetries = 3;
let retryCount = 0;
while (retryCount < maxRetries) {
try {
console.log(`第 ${retryCount + 1} 次尝试获取配置...`);
// 检查网络状态
const isNetworkAvailable = await this.checkNetworkStatus();
if (!isNetworkAvailable) {
console.error('网络不可用,使用默认配置');
this.useDefaultConfig();
return;
}
console.log('网络状态正常开始请求API...');
const response = await getHomeConfig();
console.log('API响应:', response);
// 检查响应状态
if (!response) {
console.error('API响应为空');
this.useDefaultConfig();
return;
}
// 检查响应码
if (response.code !== 200) {
console.error('API响应码错误:', response.code, response.msg);
this.useDefaultConfig();
return;
}
// 检查数据是否存在
if (!response.data) {
console.error('API响应数据为空');
this.useDefaultConfig();
return;
}
// 检查数据是否为数组且有内容
if (!Array.isArray(response.data) || response.data.length === 0) {
console.error('API响应数据格式错误或为空数组');
this.useDefaultConfig();
return;
}
// 获取第一条配置数据
const configData = response.data[0];
console.log('配置数据:', configData);
// 检查body字段是否存在
if (!configData.body) {
console.error('配置数据缺少body字段');
this.useDefaultConfig();
return;
}
// 解析JSON配置
try {
const parsedConfig = JSON.parse(configData.body);
console.log('解析后的配置数据:', parsedConfig);
// 验证配置数据完整性
if (!this.validateConfig(parsedConfig)) {
console.error('配置数据验证失败');
this.useDefaultConfig();
return;
}
// 更新页面配置
this.updatePageConfig(parsedConfig);
// 重新启动跑马灯
this.stopMarquee();
this.startMarquee();
console.log('配置加载成功');
} catch (parseError) {
console.error('解析配置JSON失败:', parseError);
console.log('原始body数据:', configData.body);
this.useDefaultConfig();
}
// 如果成功获取到数据,跳出重试循环
break;
} catch (error) {
retryCount++;
console.error(`第 ${retryCount} 次尝试失败:`, error);
console.error('错误详情:', {
message: error.message,
stack: error.stack,
name: error.name
});
if (retryCount >= maxRetries) {
console.error('所有重试都失败了,使用默认配置');
this.useDefaultConfig();
break;
} else {
console.log(`等待 ${retryCount * 1000}ms 后重试...`);
await new Promise(resolve => setTimeout(resolve, retryCount * 1000));
}
}
}
this.loading = false;
console.log('配置加载完成loading状态:', this.loading);
},
/**
* 使用默认配置
*/
useDefaultConfig() {
console.log('使用默认配置数据');
// 确保默认配置可用
if (!this.pageConfig || !this.pageConfig.announcement) {
console.error('默认配置数据不完整');
uni.showToast({
title: '配置数据异常',
icon: 'none',
duration: 2000
});
return;
}
// 启动跑马灯
this.stopMarquee();
this.startMarquee();
// 显示提示信息
uni.showToast({
title: '使用本地配置',
icon: 'none',
duration: 1500
});
},
/**
* 验证配置数据完整性
*/
validateConfig(config) {
if (!config) {
console.error('配置对象为空');
return false;
}
// 检查必需的配置项
const requiredFields = ['pageConfig', 'navigationItems', 'bottomSection'];
for (const field of requiredFields) {
if (!config[field]) {
console.error(`配置缺少必需字段: ${field}`);
return false;
}
}
// 检查pageConfig的必需子字段
const requiredPageConfigFields = ['background', 'announcement', 'topIcons'];
for (const field of requiredPageConfigFields) {
if (!config.pageConfig[field]) {
console.error(`pageConfig缺少必需字段: ${field}`);
return false;
}
}
// 检查announcement的必需子字段
if (!config.pageConfig.announcement.text) {
console.error('announcement缺少text字段');
return false;
}
console.log('配置数据验证通过');
return true;
},
/**
* 更新页面配置
*/
updatePageConfig(parsedConfig) {
if (parsedConfig.pageConfig) {
this.pageConfig = parsedConfig.pageConfig;
console.log('更新pageConfig成功');
}
if (parsedConfig.navigationItems) {
this.navigationItems = parsedConfig.navigationItems;
console.log('更新navigationItems成功');
}
if (parsedConfig.bottomSection) {
this.bottomSection = parsedConfig.bottomSection;
console.log('更新bottomSection成功');
}
},
/**
* 检查网络状态
*/
checkNetworkStatus() {
return new Promise((resolve) => {
uni.getNetworkType({
success: (res) => {
console.log('网络类型:', res.networkType);
if (res.networkType === 'none') {
console.error('网络连接不可用');
resolve(false);
} else {
resolve(true);
}
},
fail: () => {
console.error('获取网络状态失败');
resolve(false);
}
});
});
},
startMarquee() {
// 确保配置数据存在
if (!this.pageConfig || !this.pageConfig.announcement || !this.pageConfig.announcement.text) {
console.warn('配置数据不完整,无法启动跑马灯');
return;
}
// 停止之前的定时器
this.stopMarquee();
// 估算文字宽度每个字24rpx可根据实际字体大小调整
const textWidth = this.pageConfig.announcement.text.length * 24;
this.timer = setInterval(() => {
this.marqueeX--;
if (this.marqueeX < -textWidth) {
this.marqueeX = 600;
}
}, 16); // 约60帧
},
stopMarquee() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
// 页面跳转方法 - 使用路由仓库
navigateToPage(pageType) {
navigateToPage(pageType);
}
}
}
</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;
image{
width: 64rpx;
height: 64rpx;
}
.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;
display: flex;
align-items: center;
justify-content: center;
image{
width: 32rpx;
height: 32rpx;
}
.zaixian{
margin-left: 12rpx;
.da{
font-size: 24rpx;
color: #522510;
font-weight: 600;
}
.xiao{
font-size: 12rpx;
color: #522510;
}
}
}
}
.list-scroll {
width: 100%;
margin-top: 20rpx;
height: 120rpx;
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;
}
}
.list{
display: flex;
width: 1600rpx; /* 更大的宽度确保滚动 */
padding: 0 20rpx;
box-sizing: border-box;
/* 确保内容不被压缩 */
flex-shrink: 0;
.li{
width: 150rpx;
flex: 0 0 150rpx;
text-align: center;
margin-right: 20rpx;
image{
width: 56rpx;
height: 56rpx;
}
.da{
font-size: 24rpx;
color: #522510;
margin-top: 8rpx;
}
.xiao{
font-size: 12rpx;
color: #522510;
}
}
}
.hua{
width: 100%;
text-align: center;
margin-top: 30rpx;
image{
width: 656rpx;
height: 108rpx;
}
}
.time{
font-weight: 600;
font-size: 32rpx;
color: #522510;
margin-top: 8rpx;
width: 100%;
text-align: center;
}
.name{
display: flex;
align-items: center;
width: 100%;
justify-content: center;
text{
font-weight: 600;
font-size: 32rpx;
color: #522510;
margin-left: 24rpx;
margin-right: 24rpx;
}
image{
width: 12rpx;
height: 12rpx;
}
}
}
.tubiao{
width: 100%;
display: flex;
padding: 0 30rpx;
box-sizing: border-box;
justify-content: space-between;
image{
width: 82rpx;
height: 82rpx;
display: block;
margin-top: 50rpx;
}
}
.announcement {
width: 100%;
margin-top: 184rpx;
padding: 0 48rpx;
box-sizing: border-box;
display: flex;
align-items: center;
white-space: nowrap;
.ggimg {
width: 32rpx;
height: 32rpx;
margin-right: 14rpx;
}
.marquee-wrap {
width: 600rpx;
overflow: hidden;
position: relative;
height: 32rpx;
display: flex;
align-items: center;
}
.marquee {
white-space: nowrap;
position: absolute;
left: 0;
top: 0;
font-size: 24rpx;
color: #522510;
}
}
.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;
}
</style>