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

564 lines
12 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">
<scroll-view class="page-scroll" scroll-y>
<!-- 顶部横幅 -->
<view class="banner">
<view class="banner-content">
<text class="banner-title">专业沙发翻新服务</text>
<text class="banner-desc">让旧沙发焕发新生</text>
</view>
</view>
<!-- 服务类型 -->
<view class="section">
<section-header title="服务类型"></section-header>
<view class="service-grid">
<view
class="service-item"
v-for="item in serviceTypes"
:key="item.id"
@click="handleServiceClick(item)"
>
<view class="service-icon-bg">
<text class="service-icon">{{ item.emoji }}</text>
</view>
<text class="service-name">{{ item.name }}</text>
<text class="service-desc">{{ item.desc }}</text>
</view>
</view>
</view>
<!-- 服务流程 -->
<view class="section">
<section-header title="服务流程"></section-header>
<view class="process-list">
<view class="process-item" v-for="(item, index) in processList" :key="item.step">
<view class="process-step">
<text class="step-num">{{ item.step }}</text>
</view>
<view class="process-content">
<text class="process-title">{{ item.title }}</text>
<text class="process-desc">{{ item.description }}</text>
</view>
<view class="process-line" v-if="index < processList.length - 1"></view>
</view>
</view>
</view>
<!-- 材质说明 -->
<view class="section">
<section-header title="材质说明"></section-header>
<view class="material-list">
<view class="material-item" v-for="item in materials" :key="item.name">
<view class="material-header">
<text class="material-name">{{ item.name }}</text>
<text class="material-price">{{ item.price }}</text>
</view>
<text class="material-desc">{{ item.desc }}</text>
<view class="material-tags">
<text class="material-tag" v-for="tag in item.tags" :key="tag">{{ tag }}</text>
</view>
</view>
</view>
</view>
<!-- 常见问题 -->
<view class="section">
<section-header title="常见问题"></section-header>
<view class="faq-list">
<view
class="faq-item"
v-for="(item, index) in faqList"
:key="index"
@click="toggleFaq(index)"
>
<view class="faq-header">
<text class="faq-question">{{ item.question }}</text>
<text class="faq-arrow">{{ item.expanded ? '' : '+' }}</text>
</view>
<view class="faq-answer" v-if="item.expanded">
<text class="faq-answer-text">{{ item.answer }}</text>
</view>
</view>
</view>
</view>
<!-- 底部间距 -->
<view class="bottom-space"></view>
</scroll-view>
<!-- 底部预约按钮 -->
<view class="bottom-bar">
<view class="bar-info">
<text class="bar-title">免费上门评估</text>
<text class="bar-desc">专业师傅为您量身定制方案</text>
</view>
<view class="bar-btn" @click="goToBooking">
<text class="bar-btn-text">立即预约</text>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { getServiceProcess, getActiveServices } from '@/api/index.uts'
// 服务类型
type ServiceType = {
id : number
name : string
desc : string
emoji : string
type : string
basePrice : number
}
// 流程类型
type ProcessItem = {
step : number
title : string
description : string
}
// 材质类型
type MaterialItem = {
name : string
price : string
desc : string
tags : string[]
}
// FAQ类型
type FaqItem = {
question : string
answer : string
expanded : boolean
}
// 服务类型数据
const serviceTypes = ref<ServiceType[]>([])
// 服务流程
const processList = ref<ProcessItem[]>([
{ step: 1, title: '在线预约', description: '填写信息,预约上门时间' },
{ step: 2, title: '上门评估', description: '专业师傅免费上门勘察' },
{ step: 3, title: '确认方案', description: '沟通翻新方案和价格' },
{ step: 4, title: '取件翻新', description: '取回沙发进行专业翻新' },
{ step: 5, title: '送货验收', description: '送货上门,满意付款' }
])
// 材质说明
const materials = ref<MaterialItem[]>([
{
name: '头层牛皮',
price: '¥800-1500/平',
desc: '采用进口头层牛皮,质地柔软,透气性好,使用寿命长',
tags: ['进口原料', '透气舒适', '耐用耐磨']
},
{
name: '二层牛皮',
price: '¥400-800/平',
desc: '经济实惠的选择,经过特殊处理后外观与头层相近',
tags: ['性价比高', '外观精美', '易打理']
},
{
name: '科技布',
price: '¥200-500/平',
desc: '新型环保面料,防水防污,清洁方便,触感舒适',
tags: ['防水防污', '易清洁', '环保健康']
},
{
name: '棉麻布艺',
price: '¥150-400/平',
desc: '天然面料,透气舒适,适合追求自然风格的客户',
tags: ['天然环保', '透气清爽', '风格多样']
}
])
// 常见问题
const faqList = ref<FaqItem[]>([
{
question: '翻新需要多长时间?',
answer: '根据沙发的大小和翻新程度不同一般需要3-10个工作日。局部修复1-3天整体翻新5-10天。',
expanded: false
},
{
question: '翻新后能保证多久?',
answer: '我们提供2年质保服务质保期内如有非人为损坏免费维修。头层牛皮正常使用可达10年以上。',
expanded: false
},
{
question: '可以上门取送吗?',
answer: '是的,我们提供免费上门取送服务(市区范围内),郊区会收取少量运输费用。',
expanded: false
},
{
question: '如何报价?',
answer: '我们提供免费上门评估服务,师傅会根据沙发的实际情况给出详细报价,价格透明无隐形消费。',
expanded: false
},
{
question: '定金和尾款如何支付?',
answer: '确认订单后支付30%定金,翻新完成验收满意后支付尾款。支持微信、支付宝、银行转账等多种方式。',
expanded: false
}
])
// 获取服务列表
const fetchServices = 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[] || []
// 服务类型emoji映射
const emojiMap = {
fabric: '🛋️',
leather: '💺',
cleaning: '✨',
repair: '🔧',
custom: '💎'
} as UTSJSONObject
serviceTypes.value = list.map((item) : ServiceType => {
const type = item['type'] as string
return {
id: item['id'] as number,
name: item['name'] as string,
desc: item['description'] as string,
emoji: emojiMap[type] as string || '🛋️',
type: type,
basePrice: item['basePrice'] as number
} as ServiceType
})
}
} catch (e) {
console.error('获取服务列表失败', e)
}
}
// 获取服务流程(暂时使用固定数据)
const fetchServiceProcess = async () => {
// 流程数据已在初始化时设置
}
// 切换FAQ展开
const toggleFaq = (index : number) => {
faqList.value[index].expanded = !faqList.value[index].expanded
}
// 服务点击
const handleServiceClick = (item : ServiceType) => {
uni.navigateTo({
url: '/pages/booking/index'
})
}
// 去预约
const goToBooking = () => {
uni.navigateTo({
url: '/pages/booking/index'
})
}
onLoad(() => {
fetchServices()
fetchServiceProcess()
})
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f5f5f5;
}
.page-scroll {
flex: 1;
}
/* 顶部横幅 */
.banner {
height: 280rpx;
background: linear-gradient(135deg, #D4A574 0%, #B8895A 100%);
justify-content: center;
align-items: center;
}
.banner-content {
align-items: center;
}
.banner-title {
font-size: 40rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 16rpx;
}
.banner-desc {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 通用section */
.section {
padding: 0 24rpx;
margin-bottom: 24rpx;
}
/* 服务类型 */
.service-grid {
flex-direction: row;
flex-wrap: wrap;
background-color: #ffffff;
border-radius: 16rpx;
padding: 16rpx;
}
.service-item {
width: 50%;
padding: 24rpx;
align-items: center;
}
.service-icon-bg {
width: 100rpx;
height: 100rpx;
background-color: #FDF6EE;
border-radius: 50%;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
}
.service-icon {
font-size: 48rpx;
}
.service-name {
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-bottom: 8rpx;
}
.service-desc {
font-size: 24rpx;
color: #909399;
}
/* 服务流程 */
.process-list {
background-color: #ffffff;
border-radius: 16rpx;
padding: 32rpx;
}
.process-item {
flex-direction: row;
position: relative;
padding-bottom: 32rpx;
}
.process-step {
width: 48rpx;
height: 48rpx;
background-color: #D4A574;
border-radius: 50%;
align-items: center;
justify-content: center;
margin-right: 24rpx;
z-index: 1;
}
.step-num {
font-size: 24rpx;
font-weight: 600;
color: #ffffff;
}
.process-content {
flex: 1;
}
.process-title {
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-bottom: 8rpx;
}
.process-desc {
font-size: 26rpx;
color: #909399;
}
.process-line {
position: absolute;
left: 22rpx;
top: 56rpx;
width: 4rpx;
height: 60rpx;
background-color: #E8C9A8;
}
/* 材质说明 */
.material-list {
background-color: #ffffff;
border-radius: 16rpx;
}
.material-item {
padding: 32rpx;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #EBEEF5;
}
.material-item:last-child {
border-bottom-width: 0;
}
.material-header {
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
}
.material-name {
font-size: 30rpx;
font-weight: 600;
color: #333333;
}
.material-price {
font-size: 28rpx;
color: #D4A574;
font-weight: 600;
}
.material-desc {
font-size: 26rpx;
color: #606266;
margin-bottom: 16rpx;
line-height: 40rpx;
}
.material-tags {
flex-direction: row;
flex-wrap: wrap;
}
.material-tag {
font-size: 22rpx;
color: #D4A574;
background-color: #FDF6EE;
padding: 8rpx 16rpx;
border-radius: 8rpx;
margin-right: 16rpx;
margin-bottom: 8rpx;
}
/* 常见问题 */
.faq-list {
background-color: #ffffff;
border-radius: 16rpx;
}
.faq-item {
padding: 32rpx;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #EBEEF5;
}
.faq-item:last-child {
border-bottom-width: 0;
}
.faq-header {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.faq-question {
font-size: 28rpx;
font-weight: 600;
color: #333333;
flex: 1;
}
.faq-arrow {
font-size: 36rpx;
color: #909399;
margin-left: 16rpx;
}
.faq-answer {
margin-top: 16rpx;
padding-top: 16rpx;
border-top-width: 1rpx;
border-top-style: dashed;
border-top-color: #EBEEF5;
}
.faq-answer-text {
font-size: 26rpx;
color: #606266;
line-height: 44rpx;
}
/* 底部间距 */
.bottom-space {
height: 160rpx;
}
/* 底部操作栏 */
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index:2;
flex-direction: row;
align-items: center;
justify-content: space-between;
background-color: #ffffff;
padding: 20rpx 32rpx;
padding-bottom: 40rpx;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.bar-info {
flex: 1;
}
.bar-title {
font-size: 30rpx;
font-weight: 600;
color: #333333;
}
.bar-desc {
font-size: 24rpx;
color: #909399;
margin-top: 4rpx;
}
.bar-btn {
background-color: #D4A574;
padding: 24rpx 56rpx;
border-radius: 999rpx;
}
.bar-btn-text {
font-size: 30rpx;
font-weight: 600;
color: #ffffff;
}
</style>