Files
xdd-uniapp-new/pkg_product/views/housekeeperDetail.vue
T
2025-10-30 18:40:13 +08:00

1406 lines
33 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="housekeeper-detail">
<!-- 导航栏 -->
<hx-navbar
:fixed="true"
:background-color="[0,[0,0,0,0],[0,0,0,0]]"
:pageScroll.sync="scrollData"
statusBarFontColor="#ffffff"
barPlaceholder="hidden"
transparent="auto"
color='#ffffff'
title="管家详情"
/>
<!-- 管家基本信息区 -->
<view class="housekeeper-header">
<view class="header-bg">
<image
:src="housekeeperInfo.backgroundImage || defaultBg"
class="bg-image"
mode="aspectFill"
/>
<view class="bg-overlay"></view>
</view>
<view class="header-content">
<!-- 专业标签 -->
<view class="tags-section">
<view class="section-title">TA能帮你</view>
<view class="tags-grid">
<view
v-for="(tag, index) in housekeeperInfo.tags || defaultTags"
:key="index"
class="tag-item"
>
<image :src="tag.icon" class="tag-icon" />
<text class="tag-text">{{ tag.text }}</text>
</view>
</view>
</view>
<!-- 金牌管家认证 -->
<view class="certification-section" v-if="housekeeperInfo.isGoldHousekeeper">
<view class="cert-header">
<image src="/static/images/gold-badge.png" class="cert-icon" />
<text class="cert-title">金牌管家</text>
</view>
<view class="cert-content">
<text class="cert-desc">高品质服务助力顺畅沟通</text>
<view class="cert-features">
<text class="feature">安全守护·接急应证</text>
<text class="feature">皮对突发装况</text>
</view>
</view>
<view class="cert-stats">
<text class="stat">出行天数C1驾照(5年驾龄)提供途径改变或小众自驾路线规划</text>
</view>
</view>
</view>
</view>
<!-- 服务项目列表 -->
<view class="services-section">
<view class="section-header">
<text class="section-title">服务项目</text>
<text class="section-subtitle">精选优质服务满足您的需求</text>
</view>
<view class="services-list">
<view
v-for="(service, index) in serviceList"
:key="index"
class="service-item"
@click="selectService(service)"
>
<view class="service-content">
<view class="service-header">
<text class="service-name">{{ service.name }}</text>
<view class="service-price">
<text class="price-symbol"></text>
<text class="price-amount">{{ service.price }}</text>
<text class="price-unit">/{{ service.unit }}</text>
</view>
</view>
<view class="service-desc">{{ service.description }}</view>
<view class="service-features">
<view
v-for="(feature, fIndex) in service.features"
:key="fIndex"
class="feature-tag"
>
{{ feature }}
</view>
</view>
<view class="service-meta">
<text class="duration">服务时长{{ service.duration }}</text>
<text class="booking-count">已预约{{ service.bookingCount }}</text>
</view>
</view>
<view class="service-action">
<view class="book-btn" @click.stop="bookService(service)">
立即预约
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'HousekeeperDetail',
data() {
return {
scrollData: {
scrollTop: 0,
lastScrollTop: 0,
showBackToTop: false,
navbarVisible: true
},
// 性能优化相关
reviewsLoading: false,
hasMoreReviews: true,
housekeeperId: '',
// 默认数据
defaultBg: '/static/images/housekeeper-bg.jpg',
defaultAvatar: '/static/images/default-avatar.png',
defaultTags: [
{ icon: '/static/images/tag-schedule.png', text: '设计行程' },
{ icon: '/static/images/tag-food.png', text: '推荐美食' },
{ icon: '/static/images/tag-guide.png', text: '游玩向导' },
{ icon: '/static/images/tag-custom.png', text: '预定门票' },
{ icon: '/static/images/tag-recommend.png', text: '特色推荐' },
{ icon: '/static/images/tag-culture.png', text: '文化讲解' },
{ icon: '/static/images/tag-private.png', text: '私人定制' },
{ icon: '/static/images/tag-memory.png', text: '记忆保存' }
],
// 管家信息
housekeeperInfo: {
id: 1,
name: '甄美丽',
title: '旅居管家',
avatar: '/static/images/housekeeper-avatar.jpg',
backgroundImage: '/static/images/housekeeper-bg.jpg',
rating: 5.0,
serviceYears: 3,
isOnline: true,
isGoldHousekeeper: true,
isFavorite: false,
description: '擅长行程规划,专注带来深度体验乡村旅游,农耕体验、古村探秘、山野徒步、农家美食,量身规划沉浸式乡村旅程。',
tags: [
{ icon: '/static/images/tag-schedule.png', text: '设计行程' },
{ icon: '/static/images/tag-food.png', text: '推荐美食' },
{ icon: '/static/images/tag-guide.png', text: '游玩向导' },
{ icon: '/static/images/tag-custom.png', text: '预定门票' }
]
},
// 服务列表
serviceList: [
{
id: 1,
name: '一日游规划',
price: 299,
unit: '天',
duration: '8小时',
bookingCount: 128,
description: '专业定制一日游行程,包含景点推荐、路线规划、美食指南',
features: ['个性化定制', '全程陪同', '拍照服务']
},
{
id: 2,
name: '多日游策划',
price: 199,
unit: '天',
duration: '全天',
bookingCount: 86,
description: '深度多日游策划,涵盖住宿、交通、景点的全方位安排',
features: ['行程规划', '住宿推荐', '交通安排']
},
{
id: 3,
name: '美食探店',
price: 158,
unit: '次',
duration: '3小时',
bookingCount: 203,
description: '带您探索当地特色美食,品尝地道农家菜和特色小吃',
features: ['美食推荐', '预约订座', '文化讲解']
}
],
// 评价列表
reviewsList: [
{
id: 1,
username: '张**',
userAvatar: '/static/images/user1.jpg',
rating: 5,
date: '2024-01-15',
content: '甄美丽管家服务非常专业,行程安排得很合理,带我们体验了很多当地特色,强烈推荐!',
images: ['/static/images/review1.jpg', '/static/images/review2.jpg']
},
{
id: 2,
username: '李**',
userAvatar: '/static/images/user2.jpg',
rating: 5,
date: '2024-01-10',
content: '第一次体验管家服务,超出预期!美丽很贴心,帮我们安排了很多有趣的活动。',
images: []
},
{
id: 3,
username: '王**',
userAvatar: '/static/images/user3.jpg',
rating: 4,
date: '2024-01-08',
content: '服务态度很好,对当地很熟悉,推荐的美食都很棒,下次还会选择她的服务。',
images: ['/static/images/review3.jpg']
}
],
// 预约表单
showBookingForm: false,
showDatePicker: false,
selectedService: {},
bookingForm: {
date: '',
time: '',
phone: '',
requirements: ''
},
formErrors: {
date: '',
time: '',
phone: ''
},
availableTimeSlots: [
{ label: '09:00', value: '09:00', disabled: false },
{ label: '10:00', value: '10:00', disabled: false },
{ label: '11:00', value: '11:00', disabled: false },
{ label: '14:00', value: '14:00', disabled: false },
{ label: '15:00', value: '15:00', disabled: false },
{ label: '16:00', value: '16:00', disabled: false },
{ label: '17:00', value: '17:00', disabled: false },
{ label: '18:00', value: '18:00', disabled: false }
]
}
},
computed: {
displayReviews() {
return this.reviewsList.slice(0, 3)
},
// 表单是否有效
isFormValid() {
return this.bookingForm.date &&
this.bookingForm.time &&
this.bookingForm.phone &&
this.isValidPhone(this.bookingForm.phone) &&
!this.formErrors.date &&
!this.formErrors.time &&
!this.formErrors.phone
},
// 最小日期(今天)
minDate() {
return new Date().toISOString().split('T')[0]
},
// 最大日期(30天后)
maxDate() {
const date = new Date()
date.setDate(date.getDate() + 30)
return date.toISOString().split('T')[0]
}
},
onLoad(options) {
this.housekeeperId = options.id || '1'
this.loadHousekeeperDetail()
// 预加载关键资源
this.$nextTick(() => {
this.preloadResources()
})
},
onUnload() {
// 移除事件监听
uni.$off('openBooking')
},
onPageScroll(e) {
// 使用优化的滚动处理
// this.optimizedScrollHandler()(e)
},
onReachBottom() {
// 触底加载更多评价
this.loadMoreReviews()
},
methods: {
// 加载管家详情
async loadHousekeeperDetail() {
try {
uni.showLoading({ title: '加载中...' })
// 这里调用API获取管家详情
// const res = await getHousekeeperDetail(this.housekeeperId)
// this.housekeeperInfo = res.data
// this.serviceList = res.data.services
// this.reviewsList = res.data.reviews
} catch (error) {
uni.showToast({ title: '加载失败', icon: 'error' })
} finally {
uni.hideLoading()
}
},
// 选择服务
selectService(service) {
this.selectedService = service
this.showBookingForm = true
},
// 预约服务
bookService(service) {
this.selectService(service)
},
// 快速预约
quickBook() {
if (this.serviceList.length > 0) {
this.selectService(this.serviceList[0])
}
},
// 关闭预约表单
closeBookingForm() {
this.showBookingForm = false
this.resetBookingForm()
},
// 重置预约表单
resetBookingForm() {
this.bookingForm = {
date: '',
time: '',
phone: '',
requirements: ''
}
this.formErrors = {
date: '',
time: '',
phone: ''
}
},
// 弹窗状态变化
onPopupChange(e) {
if (!e.show) {
this.closeBookingForm()
}
},
// 日期变化
onDateChange(value) {
this.bookingForm.date = value
this.formErrors.date = ''
this.showDatePicker = false
this.updateAvailableTimeSlots()
},
// 选择时间段
selectTimeSlot(slot) {
if (slot.disabled) return
this.bookingForm.time = slot.value
this.formErrors.time = ''
},
// 更新可用时间段
updateAvailableTimeSlots() {
const selectedDate = new Date(this.bookingForm.date)
const today = new Date()
const isToday = selectedDate.toDateString() === today.toDateString()
if (isToday) {
const currentHour = today.getHours()
this.availableTimeSlots.forEach(slot => {
const slotHour = parseInt(slot.value.split(':')[0])
slot.disabled = slotHour <= currentHour
})
} else {
this.availableTimeSlots.forEach(slot => {
slot.disabled = false
})
}
},
// 验证手机号
validatePhone() {
if (!this.bookingForm.phone) {
this.formErrors.phone = '请输入联系电话'
} else if (!this.isValidPhone(this.bookingForm.phone)) {
this.formErrors.phone = '请输入正确的手机号'
} else {
this.formErrors.phone = ''
}
},
// 检查手机号格式
isValidPhone(phone) {
return /^1[3-9]\d{9}$/.test(phone)
},
// 提交预约
async submitBooking() {
// 如果表单无效,不允许提交
if (!this.isFormValid) {
this.validateForm()
return
}
try {
uni.showLoading({ title: '提交中...' })
const bookingData = {
housekeeperId: this.housekeeperId,
serviceId: this.selectedService.id,
serviceName: this.selectedService.name,
date: this.bookingForm.date,
time: this.bookingForm.time,
phone: this.bookingForm.phone,
requirements: this.bookingForm.requirements,
totalPrice: this.selectedService.price
}
// 调用预约API
// const result = await this.$api.housekeeper.submitBooking(bookingData)
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000))
uni.showToast({ title: '预约成功', icon: 'success' })
this.closeBookingForm()
// 跳转到订单页面
setTimeout(() => {
uni.navigateTo({ url: '/pages/order/MyOrder/index' })
}, 1500)
} catch (error) {
console.error('预约失败:', error)
uni.showToast({ title: '预约失败,请重试', icon: 'error' })
} finally {
uni.hideLoading()
}
},
// 验证整个表单
validateForm() {
let hasError = false
if (!this.bookingForm.date) {
this.formErrors.date = '请选择预约日期'
hasError = true
}
if (!this.bookingForm.time) {
this.formErrors.time = '请选择预约时间'
hasError = true
}
if (!this.bookingForm.phone) {
this.formErrors.phone = '请输入联系电话'
hasError = true
} else if (!this.isValidPhone(this.bookingForm.phone)) {
this.formErrors.phone = '请输入正确的手机号'
hasError = true
}
if (hasError) {
uni.showToast({ title: '请完善表单信息', icon: 'none' })
}
return !hasError
},
// 联系管家
contactHousekeeper() {
// 跳转到聊天页面或拨打电话
uni.navigateTo({
url: `/pages/chat/index?housekeeperId=${this.housekeeperId}`
})
},
// 收藏管家
async favoriteHousekeeper() {
try {
// 调用收藏API
// await toggleFavoriteHousekeeper(this.housekeeperId)
this.housekeeperInfo.isFavorite = !this.housekeeperInfo.isFavorite
const message = this.housekeeperInfo.isFavorite ? '收藏成功' : '取消收藏'
uni.showToast({ title: message, icon: 'success' })
} catch (error) {
uni.showToast({ title: '操作失败', icon: 'error' })
}
},
// 查看更多评价
viewMoreReviews() {
uni.navigateTo({
url: `/pages/reviews/index?housekeeperId=${this.housekeeperId}`
})
},
// 预览图片
previewImage(images, current) {
uni.previewImage({
urls: images,
current: current
})
},
// 图片懒加载
onImageLoad(e) {
// 图片加载成功后的处理
console.log('图片加载成功:', e)
},
onImageError(e) {
// 图片加载失败的处理
console.log('图片加载失败:', e)
// 可以设置默认图片
},
// 节流函数 - 用于滚动事件优化
throttle(func, delay) {
let timeoutId
let lastExecTime = 0
return function (...args) {
const currentTime = Date.now()
if (currentTime - lastExecTime > delay) {
func.apply(this, args)
lastExecTime = currentTime
} else {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
func.apply(this, args)
lastExecTime = Date.now()
}, delay - (currentTime - lastExecTime))
}
}
},
// 防抖函数 - 用于搜索等输入优化
debounce(func, delay) {
let timeoutId
return function (...args) {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => func.apply(this, args), delay)
}
},
// 优化的滚动处理
optimizedScrollHandler() {
return this.throttle((e) => {
this.scrollData.scrollTop = e.detail.scrollTop
// 当滚动到一定位置时显示返回顶部按钮
this.scrollData.showBackToTop = e.detail.scrollTop > 500
// 滚动时隐藏/显示导航栏
if (e.detail.scrollTop > this.scrollData.lastScrollTop) {
// 向下滚动
this.scrollData.navbarVisible = false
} else {
// 向上滚动
this.scrollData.navbarVisible = true
}
this.scrollData.lastScrollTop = e.detail.scrollTop
}, 16) // 约60fps
},
// 返回顶部
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: 300
})
},
// 预加载关键资源
preloadResources() {
// 预加载管家头像
if (this.housekeeperInfo.avatar) {
const img = new Image()
img.src = this.housekeeperInfo.avatar
}
// 预加载服务图片
this.serviceList.forEach(service => {
if (service.image) {
const img = new Image()
img.src = service.image
}
})
},
// 数据分页加载
async loadMoreReviews() {
if (this.reviewsLoading || !this.hasMoreReviews) return
this.reviewsLoading = true
try {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000))
const newReviews = [
// 模拟新的评价数据
{
id: Date.now(),
user: {
name: '新用户',
avatar: '/static/images/default-avatar.png'
},
rating: 5,
content: '新加载的评价内容...',
date: '2024-01-20',
images: []
}
]
this.reviewsList.push(...newReviews)
// 检查是否还有更多数据
this.hasMoreReviews = this.reviewsList.length < 50 // 假设最多50条评价
} catch (error) {
console.error('加载更多评价失败:', error)
uni.showToast({ title: '加载失败', icon: 'error' })
} finally {
this.reviewsLoading = false
}
}
}
}
</script>
<style lang="less" scoped>
.housekeeper-detail {
background: #f5f5f5;
min-height: 100vh;
padding-bottom: 120rpx;
}
// 管家头部信息区
.housekeeper-header {
position: relative;
background: #fff;
.header-bg {
position: relative;
overflow: hidden;
height: 791rpx;
border-radius: 0 0 200rpx 200rpx;
.bg-image {
width: 100%;
height: 100%;
}
.bg-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(180deg, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.6) 100%);
}
}
.header-content {
position: relative;
margin-top: -120rpx;
padding: 0 32rpx 40rpx;
z-index: 2;
}
}
// 管家基本信息
.housekeeper-info {
display: flex;
margin-bottom: 40rpx;
.avatar-section {
position: relative;
margin-right: 24rpx;
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.15);
}
.online-status {
position: absolute;
bottom: 8rpx;
right: 8rpx;
width: 24rpx;
height: 24rpx;
background: #fff;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
.status-dot {
width: 12rpx;
height: 12rpx;
background: #52c41a;
border-radius: 6rpx;
}
}
}
.info-section {
flex: 1;
.name-row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.name {
font-size: 36rpx;
font-weight: bold;
color: #fff;
margin-right: 16rpx;
}
.title-badge {
background: rgba(255,255,255,0.9);
padding: 6rpx 16rpx;
border-radius: 20rpx;
.title {
font-size: 24rpx;
color: #333;
}
}
}
.rating-row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.stars {
display: flex;
margin-right: 12rpx;
.star {
font-size: 28rpx;
color: #ddd;
&.active {
color: #ffd700;
}
}
}
.rating-text {
font-size: 28rpx;
color: #fff;
margin-right: 16rpx;
}
.service-years {
font-size: 24rpx;
color: rgba(255,255,255,0.8);
}
}
.description {
font-size: 28rpx;
line-height: 40rpx;
color: rgba(255,255,255,0.9);
}
}
}
// 专业标签区
.tags-section {
margin-bottom: 40rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
}
.tags-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24rpx;
.tag-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
.tag-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 12rpx;
}
.tag-text {
font-size: 24rpx;
color: #333;
text-align: center;
}
}
}
}
// 金牌管家认证
.certification-section {
background: linear-gradient(135deg, #fff8e1 0%, #fff3c4 100%);
border-radius: 20rpx;
padding: 24rpx;
border: 2rpx solid #ffd700;
.cert-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.cert-icon {
width: 32rpx;
height: 32rpx;
margin-right: 12rpx;
}
.cert-title {
font-size: 28rpx;
font-weight: bold;
color: #d4a017;
}
}
.cert-content {
margin-bottom: 16rpx;
.cert-desc {
font-size: 26rpx;
color: #666;
margin-bottom: 12rpx;
}
.cert-features {
display: flex;
gap: 16rpx;
.feature {
font-size: 24rpx;
color: #999;
}
}
}
.cert-stats {
.stat {
font-size: 24rpx;
color: #666;
line-height: 32rpx;
}
}
}
// 服务项目区
.services-section {
margin: 24rpx 32rpx;
.section-header {
margin-bottom: 24rpx;
.section-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.section-subtitle {
font-size: 26rpx;
color: #666;
}
}
.services-list {
.service-item {
background: #fff;
border-radius: 20rpx;
padding: 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
.service-content {
.service-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16rpx;
.service-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.service-price {
display: flex;
align-items: baseline;
color: #ff4757;
.price-symbol {
font-size: 24rpx;
}
.price-amount {
font-size: 36rpx;
font-weight: bold;
}
.price-unit {
font-size: 24rpx;
margin-left: 4rpx;
}
}
}
.service-desc {
font-size: 28rpx;
color: #666;
line-height: 40rpx;
margin-bottom: 16rpx;
}
.service-features {
display: flex;
gap: 12rpx;
margin-bottom: 16rpx;
.feature-tag {
background: #f0f9ff;
color: #0ea5e9;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
}
}
.service-meta {
display: flex;
justify-content: space-between;
font-size: 24rpx;
color: #999;
}
}
.service-action {
margin-top: 24rpx;
.book-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
text-align: center;
padding: 20rpx;
border-radius: 50rpx;
font-size: 28rpx;
font-weight: bold;
}
}
}
}
}
// 用户评价区
.reviews-section {
margin: 24rpx 32rpx;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.section-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.view-more {
display: flex;
align-items: center;
color: #666;
font-size: 26rpx;
.arrow {
margin-left: 8rpx;
font-size: 20rpx;
}
}
}
.reviews-list {
.review-item {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 16rpx;
.review-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
.user-avatar {
width: 60rpx;
height: 60rpx;
border-radius: 30rpx;
margin-right: 16rpx;
}
.user-info {
flex: 1;
.username {
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
}
.review-rating {
display: flex;
.star {
font-size: 20rpx;
color: #ddd;
&.active {
color: #ffd700;
}
}
}
}
.review-date {
font-size: 24rpx;
color: #999;
}
}
.review-content {
font-size: 28rpx;
line-height: 40rpx;
color: #333;
margin-bottom: 16rpx;
}
.review-images {
display: flex;
gap: 12rpx;
.review-img {
width: 120rpx;
height: 120rpx;
border-radius: 8rpx;
}
}
}
}
}
// 预约表单
.booking-form {
background: #fff;
border-radius: 20rpx 20rpx 0 0;
max-height: 80vh;
.form-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
border-bottom: 1rpx solid #f0f0f0;
.form-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.close-btn {
font-size: 48rpx;
color: #999;
line-height: 1;
}
}
.form-content {
padding: 32rpx;
max-height: 60vh;
overflow-y: auto;
.selected-service {
background: #f8f9fa;
padding: 24rpx;
border-radius: 16rpx;
margin-bottom: 32rpx;
.service-name {
font-size: 28rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.service-price {
font-size: 32rpx;
color: #ff4757;
font-weight: bold;
}
}
.form-group {
margin-bottom: 32rpx;
.label {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 16rpx;
}
.input-field {
width: 100%;
padding: 24rpx;
border: 1rpx solid #e0e0e0;
border-radius: 12rpx;
font-size: 28rpx;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
&.error {
border-color: #ff4757;
}
.arrow {
color: #999;
}
}
.textarea-field {
width: 100%;
min-height: 120rpx;
padding: 24rpx;
border: 1rpx solid #e0e0e0;
border-radius: 12rpx;
font-size: 28rpx;
background: #fff;
resize: none;
&.error {
border-color: #ff4757;
}
}
.error-message {
color: #ff4757;
font-size: 24rpx;
margin-top: 8rpx;
}
.char-counter {
text-align: right;
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
// 时间选择器
.time-slots {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16rpx;
margin-top: 16rpx;
.time-slot {
padding: 20rpx;
border: 1rpx solid #e0e0e0;
border-radius: 12rpx;
text-align: center;
font-size: 26rpx;
color: #333;
background: #fff;
transition: all 0.3s;
&.selected {
background: #667eea;
color: #fff;
border-color: #667eea;
}
&.disabled {
background: #f5f5f5;
color: #ccc;
border-color: #f0f0f0;
}
}
}
// 总价显示
.total-price {
background: #f8f9fa;
padding: 24rpx;
border-radius: 12rpx;
margin-top: 16rpx;
.price-label {
font-size: 26rpx;
color: #666;
margin-bottom: 8rpx;
}
.price-amount {
font-size: 36rpx;
font-weight: bold;
color: #ff4757;
}
}
}
}
.form-footer {
padding: 32rpx;
border-top: 1rpx solid #f0f0f0;
.submit-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
text-align: center;
padding: 24rpx;
border-radius: 50rpx;
font-size: 32rpx;
font-weight: bold;
transition: all 0.3s;
&.disabled {
background: #f0f0f0;
color: #ccc;
cursor: not-allowed;
}
}
}
}
// 返回顶部按钮
.back-to-top {
position: fixed;
right: 30rpx;
bottom: 200rpx;
width: 80rpx;
height: 80rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
transition: all 0.3s ease;
.back-icon {
color: #ffffff;
font-size: 32rpx;
font-weight: bold;
}
&:active {
transform: scale(0.9);
}
}
// 加载更多样式
.loading-more,
.load-more,
.no-more {
padding: 40rpx 0;
text-align: center;
.loading-text,
.load-more-text,
.no-more-text {
font-size: 28rpx;
color: #999999;
}
}
.load-more {
cursor: pointer;
.load-more-text {
color: #007AFF;
}
&:active {
opacity: 0.7;
}
}
// 底部操作栏
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #fff;
padding: 20rpx 32rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
border-top: 1rpx solid #f0f0f0;
display: flex;
align-items: center;
gap: 24rpx;
z-index: 100;
.action-item {
display: flex;
flex-direction: column;
align-items: center;
.action-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 8rpx;
}
.action-text {
font-size: 24rpx;
color: #666;
}
}
.primary-action {
flex: 1;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
text-align: center;
padding: 24rpx;
border-radius: 50rpx;
font-size: 32rpx;
font-weight: bold;
}
}
// 响应式适配
@media screen and (min-width: 768px) {
.housekeeper-detail {
max-width: 750rpx;
margin: 0 auto;
}
.tags-grid {
grid-template-columns: repeat(8, 1fr);
}
}
</style>