280 lines
7.7 KiB
Vue
280 lines
7.7 KiB
Vue
<template>
|
||
<view class="content">
|
||
<swiper class="swiper" autoplay interval="3000" duration="500" circular v-if="bannerList.length > 0">
|
||
<swiper-item v-for="(item,index) in bannerList" :key="item.id">
|
||
<image class="swiper-img" :src="item.image_url" mode="aspectFill"></image>
|
||
</swiper-item>
|
||
</swiper>
|
||
<view v-else class="swiper center" style="background-color: #f5f5f5;">
|
||
<text style="color: #999;">暂无Banner</text>
|
||
</view>
|
||
|
||
<view class="column"
|
||
style="width: 100%; background-color: white; border-radius: 27rpx; margin-top: -32rpx; z-index: 999; box-shadow: 0 15rpx 15rpx -3rpx rgba(0, 0, 0, 0.1); ">
|
||
|
||
<view class="hot-services-title" style="margin-top: 21rpx; margin-left: 25rpx;">
|
||
<text style="font-size: 32rpx; font-weight: bold; color: #333;">{{ $t('home.hotServices') }}</text>
|
||
</view>
|
||
|
||
<view class="" style="display: flex; flex-wrap: wrap; margin-top: 22rpx; margin-left: 11rpx;">
|
||
|
||
<view class="column" v-for="(item, index) in hotList" :key="item.id"
|
||
style="margin-left: 22rpx; width: 331.12rpx; margin-bottom: 25rpx;" @click="toDetails(item)">
|
||
<image :src="item.image_url || '/static/placeholder.png'"
|
||
style="width: 331.12rpx; height: 159.57rpx; border-radius: 16rpx; background-color: #f5f5f5; box-shadow: 0 0 10rpx 5rpx rgba(0, 0, 0, 0.1);"
|
||
mode="aspectFill"></image>
|
||
|
||
<view class="service-text">{{ item.name }}</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<view class="about-title" style="margin-top: 22rpx; margin-left: 28rpx;">
|
||
<text style="font-size: 32rpx; font-weight: bold; color: #333;">{{ $t('home.aboutMe') }}</text>
|
||
</view>
|
||
|
||
<image :src="aboutUsImage" v-if="aboutUsImage"
|
||
style="width: 100%; height: 759.97rpx; box-shadow: 0 0 10rpx 5rpx rgba(0, 0, 0, 0.1); margin-top: 26rpx; margin-bottom: 30rpx; border-radius: 28rpx; background-color: white;"
|
||
mode="aspectFill" @error="handleImageError" @load="handleImageLoad">
|
||
</image>
|
||
<view v-else
|
||
style="width: 100%; height: 759.97rpx; box-shadow: 0 0 10rpx 5rpx rgba(0, 0, 0, 0.1); margin-top: 26rpx; margin-bottom: 30rpx; border-radius: 28rpx; background-color: white; display: flex; align-items: center; justify-content: center;">
|
||
<text style="color: #999;">{{ $t('home.aboutMe') }}</text>
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
updateTabBarI18n
|
||
} from '@/utils/tabbar-i18n.js'
|
||
import {
|
||
requireAuth,
|
||
isLoggedIn
|
||
} from '@/utils/auth.js'
|
||
import Config from '@/modules/Config.js'
|
||
import {
|
||
AppServer
|
||
} from '@/modules/api/AppServer.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
bannerList: [],
|
||
hotList: [],
|
||
aboutUsImage: '', // 关于我们图片
|
||
appLogo: '', // 应用Logo
|
||
appName: '' // 应用名称
|
||
}
|
||
},
|
||
onLoad() {
|
||
// 不在首页检查登录状态,允许游客浏览
|
||
this.loadConfig()
|
||
this.loadBanners()
|
||
this.loadHotServices()
|
||
},
|
||
onShow() {
|
||
updateTabBarI18n(this)
|
||
this.checkUnreadNotifications()
|
||
},
|
||
methods: {
|
||
/**
|
||
* 加载配置
|
||
*/
|
||
async loadConfig() {
|
||
try {
|
||
console.log('开始加载配置...')
|
||
const config = await Config.getPublicConfig()
|
||
console.log('获取到的配置:', JSON.stringify(config))
|
||
console.log('配置类型:', typeof config)
|
||
console.log('about_us_image值:', config.about_us_image)
|
||
|
||
// 更新关于我们图片
|
||
if (config.about_us_image) {
|
||
this.aboutUsImage = Config.getImageUrl(config.about_us_image)
|
||
console.log('关于我们图片URL:', this.aboutUsImage)
|
||
} else {
|
||
console.log('配置中没有about_us_image')
|
||
}
|
||
|
||
// 更新应用Logo
|
||
if (config.app_logo) {
|
||
this.appLogo = Config.getImageUrl(config.app_logo)
|
||
console.log('应用Logo URL:', this.appLogo)
|
||
}
|
||
|
||
// 更新应用名称
|
||
if (config.app_name) {
|
||
this.appName = config.app_name
|
||
}
|
||
} catch (error) {
|
||
console.error('加载配置失败:', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载Banner列表
|
||
*/
|
||
async loadBanners() {
|
||
try {
|
||
console.log('开始加载Banner...')
|
||
console.log('API URL:', Config.API_BASE_URL + '/api/v1/home/banners')
|
||
|
||
uni.request({
|
||
url: Config.API_BASE_URL + '/api/v1/home/banners',
|
||
method: 'GET',
|
||
success: (res) => {
|
||
console.log('Banner请求成功 - res:', res)
|
||
if (res.statusCode === 200 && res.data.code === 0) {
|
||
this.bannerList = res.data.data.map(banner => ({
|
||
...banner,
|
||
image_url: Config.getImageUrl(banner.image_url)
|
||
}))
|
||
console.log('Banner列表:', this.bannerList)
|
||
console.log('Banner数量:', this.bannerList.length)
|
||
} else {
|
||
console.log('Banner加载条件不满足')
|
||
console.log('statusCode:', res.statusCode)
|
||
console.log('code:', res.data?.code)
|
||
}
|
||
},
|
||
fail: (error) => {
|
||
console.error('Banner请求失败:', error)
|
||
}
|
||
})
|
||
} catch (error) {
|
||
console.error('加载Banner失败:', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载热门服务列表
|
||
*/
|
||
async loadHotServices() {
|
||
try {
|
||
uni.request({
|
||
url: Config.API_BASE_URL + '/api/v1/home/hot-services',
|
||
method: 'GET',
|
||
header: {
|
||
'Accept-Language': this.$i18n.locale || 'zh'
|
||
},
|
||
success: (res) => {
|
||
if (res.statusCode === 200 && res.data.code === 0) {
|
||
this.hotList = res.data.data.map(service => ({
|
||
...service,
|
||
image_url: service.image_url ? Config.getImageUrl(service
|
||
.image_url) : null
|
||
}))
|
||
console.log('热门服务列表:', this.hotList)
|
||
}
|
||
},
|
||
fail: (error) => {
|
||
console.error('加载热门服务失败:', error)
|
||
}
|
||
})
|
||
} catch (error) {
|
||
console.error('加载热门服务失败:', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 图片加载成功
|
||
*/
|
||
handleImageLoad(e) {
|
||
console.log('图片加载成功:', e)
|
||
},
|
||
|
||
/**
|
||
* 图片加载失败 - 清空图片URL显示占位符
|
||
*/
|
||
handleImageError(e) {
|
||
console.error('图片加载失败:', e)
|
||
console.error('图片URL:', this.aboutUsImage)
|
||
// 图片加载失败时清空URL,显示占位符
|
||
this.aboutUsImage = ''
|
||
},
|
||
|
||
/**
|
||
* 检查未读通知并更新TabBar红点
|
||
*/
|
||
async checkUnreadNotifications() {
|
||
if (!isLoggedIn()) {
|
||
// 未登录,移除红点
|
||
uni.removeTabBarBadge({ index: 2 })
|
||
return
|
||
}
|
||
try {
|
||
const appserver = new AppServer()
|
||
const response = await appserver.GetNotificationUnreadCount()
|
||
if (response.code === 0 && response.data) {
|
||
const unreadCount = response.data.all || 0
|
||
if (unreadCount > 0) {
|
||
uni.setTabBarBadge({
|
||
index: 2,
|
||
text: unreadCount > 99 ? '99+' : String(unreadCount)
|
||
})
|
||
} else {
|
||
uni.removeTabBarBadge({ index: 2 })
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('检查未读通知失败:', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 跳转到详情页(需要登录)
|
||
*/
|
||
toDetails(item) {
|
||
// 检查登录状态,未登录则跳转到登录页
|
||
if (!requireAuth(true)) {
|
||
return
|
||
}
|
||
|
||
// 已登录,跳转到详情页
|
||
uni.navigateTo({
|
||
url: '/pages/index/reserve-details-page?id=' + item.id + '&title=' + encodeURIComponent(item
|
||
.name) + '&serviceType=' + encodeURIComponent(item.service_type)
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.content {
|
||
display: flex;
|
||
min-height: 100vh;
|
||
background-color: #F3F4F8;
|
||
flex-direction: column;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.swiper {
|
||
width: 100%;
|
||
height: 398.94rpx;
|
||
}
|
||
|
||
.swiper-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.service-text {
|
||
font-size: 25.93rpx;
|
||
margin-top: 8rpx;
|
||
font-weight: 500;
|
||
width: 100%;
|
||
text-align: center;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
line-height: 1.4;
|
||
}
|
||
</style> |