buddhism/pages/nearbystores/index.vue
2025-08-06 12:04:17 +08:00

693 lines
17 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="index"
@click="navigateToPage(item, index)"
>
<image :src="item.img" mode=""></image>
<view class="da">
{{ item.title }}
</view>
<view class="xiao">
{{ item.subtitle }}
</view>
</view>
<!-- 空状态提示 -->
<view v-if="!loading && navigationItems.length === 0" class="empty-state">
<text>暂无功能项目</text>
</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 { 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: true, // 默认为true等待API数据加载
// 页面配置数据完全依赖API
pageConfig: {
background: { img: '' },
announcement: { icon: '', text: '' },
topIcons: {
leftIcon: { hidden: false, img: '' },
rightIcon: { img: '' },
bottomIcon: { img: '' }
}
},
navigationItems: [],
bottomSection: {
openingTime: {
title: '',
time: '',
decorationImg: ''
}
}
}
},
onLoad() {
// 页面加载时获取配置
this.loadHomeConfig();
},
// 添加下拉刷新支持
onPullDownRefresh() {
console.log('用户触发下拉刷新');
this.loadHomeConfig().finally(() => {
uni.stopPullDownRefresh();
});
},
onShow() {
// 如果配置已加载,启动跑马灯
if (this.pageConfig && this.pageConfig.announcement && this.pageConfig.announcement.text) {
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();
this.loading = false;
return;
}
console.log('网络状态正常开始请求API...');
const response = await getHomeConfig();
console.log('API响应:', response);
// 检查响应状态
if (!response) {
console.error('API响应为空');
throw new Error('API响应为空');
}
// 检查响应码
if (response.code !== 200) {
console.error('API响应码错误:', response.code, response.msg);
throw new Error(`API响应码错误: ${response.code}`);
}
// 检查数据是否存在
if (!response.data) {
console.error('API响应数据为空');
throw new Error('API响应数据为空');
}
// 检查数据是否为数组且有内容
if (!Array.isArray(response.data) || response.data.length === 0) {
console.error('API响应数据格式错误或为空数组');
throw new Error('API响应数据格式错误');
}
// 获取第一条配置数据
const configData = response.data[0];
console.log('配置数据:', configData);
// 检查body字段是否存在
if (!configData.body) {
console.error('配置数据缺少body字段');
throw new Error('配置数据缺少body字段');
}
// 解析JSON配置
try {
const parsedConfig = JSON.parse(configData.body);
console.log('解析后的配置数据:', parsedConfig);
// 验证配置数据完整性
if (!this.validateConfig(parsedConfig)) {
console.error('配置数据验证失败');
throw new Error('配置数据验证失败');
}
// 更新页面配置
this.updatePageConfig(parsedConfig);
// 重新启动跑马灯
this.stopMarquee();
this.startMarquee();
console.log('配置加载成功');
} catch (parseError) {
console.error('解析配置JSON失败:', parseError);
console.log('原始body数据:', configData.body);
throw new Error('解析配置JSON失败: ' + parseError.message);
}
// 如果成功获取到数据,跳出重试循环
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('API获取失败无法加载配置');
// 不设置任何默认配置,保持初始化的空状态
// 数据保持为初始化时的空结构
// 显示提示信息
uni.showModal({
title: '加载失败',
content: '无法获取页面配置,请检查网络连接后重试',
showCancel: true,
cancelText: '取消',
confirmText: '重试',
success: (res) => {
if (res.confirm) {
this.loadHomeConfig();
}
}
});
},
/**
* 验证配置数据完整性
*/
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;
}
},
// 兼容两种跳转方式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;
}
// 如果没有page字段则使用aid进行文章详情跳转
if (item.aid) {
console.log('使用aid字段获取文章详情:', item.aid);
// 显示加载提示
uni.showLoading({
title: '加载中...',
mask: true
});
// 调用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);
uni.showToast({
title: '获取内容失败',
icon: 'none'
});
}
} else {
console.error('导航项既没有page字段也没有aid字段:', item);
uni.showToast({
title: '配置错误',
icon: 'none'
});
}
} catch (error) {
// 隐藏加载提示
uni.hideLoading();
console.error('导航跳转出错:', error);
uni.showToast({
title: '网络错误',
icon: 'none'
});
}
}
}
}
</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;
}
}
.empty-state {
width: 100%;
text-align: center;
padding: 40rpx;
color: #999;
font-size: 28rpx;
}
}
.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>