437 lines
9.4 KiB
Plaintext
437 lines
9.4 KiB
Plaintext
<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> |