Files
ShaFaFanXin/前端/pages/index/index.uvue

437 lines
9.4 KiB
Plaintext
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">
<!-- 自定义导航栏 -->
<nav-bar title="优艺家沙发翻新"></nav-bar>
<scroll-view class="page-content" scroll-y>
<!-- 轮播图 -->
<view class="banner-section">
<swiper
class="banner-swiper"
circular
autoplay
indicator-dots
indicator-color="rgba(255,255,255,0.5)"
indicator-active-color="#ffffff"
>
<swiper-item v-for="item in bannerList" :key="item.id">
<image
class="banner-image"
:src="item.image"
mode="aspectFill"
@click="handleBannerClick(item)"
></image>
</swiper-item>
</swiper>
</view>
<!-- 服务入口 -->
<view class="service-section">
<view class="service-grid">
<service-card
v-for="item in serviceTypes"
:key="item.id"
:id="item.id"
:name="item.name"
:icon="item.icon"
@click="handleServiceClick"
></service-card>
</view>
</view>
<!-- 公司优势 -->
<view class="advantage-section">
<view class="advantage-list">
<view class="advantage-item" v-for="item in advantages" :key="item.title">
<text class="advantage-icon">{{ item.icon }}</text>
<view class="advantage-info">
<text class="advantage-title">{{ item.title }}</text>
<text class="advantage-desc">{{ item.desc }}</text>
</view>
</view>
</view>
</view>
<!-- 热门案例 -->
<view class="case-section">
<section-header
title="热门案例"
:showMore="true"
@more="goToCaseList"
></section-header>
<view class="case-list">
<case-card
v-for="item in hotCases"
:key="item.id"
:caseData="item"
@click="goToCaseDetail"
></case-card>
</view>
</view>
<!-- 预约入口 -->
<view class="booking-section" @click="goToBooking">
<view class="booking-content">
<view class="booking-left">
<text class="booking-title">免费上门评估</text>
<text class="booking-desc">专业师傅免费上门,为您的沙发量身定制翻新方案</text>
</view>
<view class="booking-btn">
<text class="booking-btn-text">立即预约</text>
</view>
</view>
</view>
<!-- 底部间距 -->
<view class="bottom-space"></view>
</scroll-view>
</view>
</template>
<script setup lang="uts">
import { getBanners, getHotCases, getActiveServices } from '@/api/index.uts'
import { getServiceTypeName } from '@/utils/config.uts'
// 轮播图类型
type BannerItem = {
id : string
image : string
title : string
link : string
}
// 案例类型
type CaseItem = {
id : string
title : string
category : string
categoryName : string
coverImage : string
material : string
duration : string
price : string
views : number
likes : number
}
// 服务类型
type ServiceType = {
id : string
name : string
icon : string
}
// 优势类型
type AdvantageItem = {
icon : string
title : string
desc : string
}
// 轮播图数据
const bannerList = ref<BannerItem[]>([])
// 服务类型
const serviceTypes = ref<ServiceType[]>([])
// 热门案例
const hotCases = ref<CaseItem[]>([])
// 公司优势
const advantages = ref<AdvantageItem[]>([
{ icon: '👨‍🔧', title: '专业团队', desc: '10年+经验' },
{ icon: '✅', title: '品质保证', desc: '质保2年' },
{ icon: '🚗', title: '上门服务', desc: '免费评估' },
{ icon: '💰', title: '价格透明', desc: '无隐形消费' }
])
// 获取服务类型
const fetchServiceTypes = async () => {
try {
const res = await getActiveServices()
if (res.code === 0 && res.data != null) {
const data = res.data as UTSJSONObject
const list = data['list'] as UTSJSONObject[] || []
serviceTypes.value = list.map((item) : ServiceType => {
return {
id: String(item['id']),
name: item['name'] as string,
icon: item['icon'] as string || '/static/icons/default.png'
} as ServiceType
})
}
} catch (e) {
console.error('获取服务类型失败', e)
// 失败时使用默认数据
serviceTypes.value = [
{ id: 'repair', name: '局部修复', icon: '/static/icons/repair.png' },
{ id: 'refurbish', name: '整体翻新', icon: '/static/icons/refurbish.png' }
] as ServiceType[]
}
}
// 获取轮播图
const fetchBanners = async () => {
try {
const res = await getBanners()
if (res.code === 0 && res.data != null) {
const data = res.data as UTSJSONObject[]
bannerList.value = data.map((item) : BannerItem => {
return {
id: item['id'] as string,
image: item['image'] as string,
title: item['title'] as string,
link: item['link'] as string
} as BannerItem
})
}
} catch (e) {
console.error('获取轮播图失败', e)
}
}
// 获取热门案例
const fetchHotCases = async () => {
try {
const res = await getHotCases()
if (res.code == 0 && res.data != null) {
const data = res.data as UTSJSONObject
// 适应后端返回格式:{ list: [], total: 0 }
const list = data['list'] as UTSJSONObject[] || []
hotCases.value = list.map((item) : CaseItem => {
// 优先使用images其次afterImages最后beforeImages
const images = item['images'] as string[] || []
const afterImages = item['afterImages'] as string[] || []
const beforeImages = item['beforeImages'] as string[] || []
const coverImage = images.length > 0 ? images[0] : (afterImages.length > 0 ? afterImages[0] : (beforeImages.length > 0 ? beforeImages[0] : ''))
return {
id: String(item['id']),
title: item['title'] as string,
category: item['serviceType'] as string || '',
categoryName: getServiceTypeName(item['serviceType'] as string),
coverImage: coverImage,
material: item['materials'] as string || '暂无',
duration: (item['duration'] as number || 0) + '天',
price: item['price'] != null ? '¥' + item['price'] : '面议',
views: item['views'] as number || 0,
likes: item['likes'] as number || 0
} as CaseItem
})
}
} catch (e) {
console.error('获取热门案例失败', e)
}
}
// 轮播图点击
const handleBannerClick = (item : BannerItem) => {
if (item.link != '') {
uni.navigateTo({
url: item.link,
fail: () => {
uni.switchTab({
url: item.link
})
}
})
}
}
// 服务点击
const handleServiceClick = (id : string) => {
uni.switchTab({
url: '/pages/service/index'
})
}
// 查看更多案例
const goToCaseList = () => {
uni.switchTab({
url: '/pages/cases/list'
})
}
// 查看案例详情
const goToCaseDetail = (id : string) => {
uni.navigateTo({
url: `/pages/cases/detail?id=${id}`
})
}
// 去预约
const goToBooking = () => {
uni.navigateTo({
url: '/pages/booking/index'
})
}
// API测试方法
const testAPI = async () => {
try {
console.log('开始API对接测试...')
const bannerRes = await getBanners()
console.log('轮播图API响应:', bannerRes)
const caseRes = await getCaseList()
console.log('案例列表API响应:', caseRes)
uni.showToast({
title: 'API测试完成请查看控制台',
icon: 'success'
})
} catch (error) {
console.error('API测试失败:', error)
uni.showToast({
title: 'API测试失败',
icon: 'error'
})
}
}
onLoad(() => {
fetchServiceTypes()
fetchBanners()
fetchHotCases()
// 开发环境下自动进行API测试
// testAPI()
})
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f5f5f5;
}
.page-content {
flex: 1;
}
/* 轮播图 */
.banner-section {
padding: 24rpx;
}
.banner-swiper {
height: 320rpx;
border-radius: 16rpx;
overflow: hidden;
}
.banner-image {
width: 100%;
height: 100%;
}
/* 服务入口 */
.service-section {
padding: 0 24rpx 24rpx;
}
.service-grid {
flex-direction: row;
justify-content: space-between;
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx 16rpx;
}
/* 公司优势 */
.advantage-section {
padding: 0 24rpx 24rpx;
}
.advantage-list {
flex-direction: row;
flex-wrap: wrap;
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
}
.advantage-item {
width: 50%;
flex-direction: row;
align-items: center;
padding: 16rpx 0;
}
.advantage-icon {
font-size: 48rpx;
margin-right: 16rpx;
}
.advantage-info {
flex: 1;
}
.advantage-title {
font-size: 28rpx;
font-weight: 600;
color: #333333;
margin-bottom: 4rpx;
}
.advantage-desc {
font-size: 24rpx;
color: #909399;
}
/* 热门案例 */
.case-section {
padding: 0 24rpx;
}
.case-list {
padding-bottom: 24rpx;
}
/* 预约入口 */
.booking-section {
margin: 0 24rpx 24rpx;
background: linear-gradient(135deg, #D4A574 0%, #B8895A 100%);
border-radius: 16rpx;
padding: 32rpx;
}
.booking-content {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.booking-left {
flex: 1;
}
.booking-title {
font-size: 34rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 8rpx;
}
.booking-desc {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
.booking-btn {
background-color: #ffffff;
padding: 16rpx 32rpx;
border-radius: 999rpx;
margin-left: 24rpx;
}
.booking-btn-text {
font-size: 28rpx;
font-weight: 600;
color: #D4A574;
}
/* 底部间距 */
.bottom-space {
height: 120rpx;
}
</style>