<template> <div class="service-page"> <el-row :gutter="20"> <!-- 服务入口 --> <el-col :span="16"> <el-card class="service-grid"> <template #header> <div class="card-header"> <span>生活服务</span> </div> </template> <div class="grid-container"> <div v-for="service in services" :key="service.id" class="service-item" @click="handleService(service)" > <el-icon :size="40" :color="service.color"> <component :is="service.icon" /> </el-icon> <h3>{{ service.name }}</h3> <p>{{ service.description }}</p> </div> </div> </el-card> <!-- 社区团购 --> <el-card class="group-buy mt-20"> <template #header> <div class="card-header"> <span>社区团购</span> <el-radio-group v-model="groupBuyFilter" size="small"> <el-radio-button label="ongoing">进行中</el-radio-button> <el-radio-button label="upcoming">即将开始</el-radio-button> <el-radio-button label="ended">已结束</el-radio-button> </el-radio-group> </div> </template> <div class="group-buy-list"> <div v-for="item in filteredGroupBuyItems" :key="item.id" class="group-buy-item" > <el-image :src="item.image" fit="cover"> <template #error> <div class="image-slot"> <el-icon><Picture /></el-icon> </div> </template> </el-image> <div class="item-info"> <h4>{{ item.title }}</h4> <p class="description">{{ item.description }}</p> <div class="price-info"> <div class="price"> <span class="current">¥{{ item.groupPrice }}</span> <span class="original">¥{{ item.originalPrice }}</span> </div> <span class="participants">{{ item.participants }}人已参与</span> </div> <div class="progress-info"> <el-progress :percentage="(item.participants / item.target) * 100" :format="() => `${item.participants}/${item.target}人`" /> </div> <el-button type="primary" :disabled="item.status === 'ended'" @click="joinGroupBuy(item)" > {{ getGroupBuyButtonText(item.status) }} </el-button> </div> </div> </div> </el-card> </el-col> <!-- 服务记录 --> <el-col :span="8"> <!-- 进行中的服务 --> <el-card class="active-services"> <template #header> <div class="card-header"> <span>进行中的服务</span> </div> </template> <el-timeline> <el-timeline-item v-for="service in activeServices" :key="service.id" :type="service.status" :timestamp="service.time" > <h4>{{ service.title }}</h4> <p>{{ service.description }}</p> <div class="service-actions"> <el-button type="primary" link @click="contactService(service)" > 联系服务人员 </el-button> <el-button type="danger" link @click="cancelService(service)" > 取消服务 </el-button> </div> </el-timeline-item> </el-timeline> </el-card> <!-- 缴费提醒 --> <el-card class="payment-reminder mt-20"> <template #header> <div class="card-header"> <span>缴费提醒</span> <el-button type="primary" text @click="batchPayment"> 一键缴费 </el-button> </div> </template> <div class="payment-list"> <div v-for="bill in unpaidBills" :key="bill.id" class="payment-item" > <div class="bill-info"> <el-icon :color="bill.color"><component :is="bill.icon" /></el-icon> <div class="bill-details"> <h4>{{ bill.title }}</h4> <p>{{ bill.period }}</p> </div> </div> <div class="bill-amount"> <span class="amount">¥{{ bill.amount }}</span> <el-button type="primary" size="small" @click="payBill(bill)" > 立即缴费 </el-button> </div> </div> </div> </el-card> </el-col> </el-row> <!-- 家政服务预约对话框 --> <el-dialog v-model="serviceDialogVisible" :title="currentService?.name" width="50%" > <el-form :model="serviceForm" label-width="100px"> <el-form-item label="服务类型"> <el-select v-model="serviceForm.type" placeholder="请选择服务类型"> <el-option v-for="type in currentService?.types" :key="type.value" :label="type.label" :value="type.value" /> </el-select> </el-form-item> <el-form-item label="预约时间"> <el-date-picker v-model="serviceForm.date" type="datetime" placeholder="选择日期时间" /> </el-form-item> <el-form-item label="服务地址"> <el-input v-model="serviceForm.address" /> </el-form-item> <el-form-item label="备注说明"> <el-input v-model="serviceForm.notes" type="textarea" :rows="3" /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="serviceDialogVisible = false">取消</el-button> <el-button type="primary" @click="submitService">确认预约</el-button> </span> </template> </el-dialog> </div> </template> <script setup lang="ts"> import { ref, computed } from 'vue' import { Box, Van, Money, House, Tools, ShoppingCart, Picture, WaterMeter, Lightning, Connection } from '@element-plus/icons-vue' import { ElMessage, ElMessageBox } from 'element-plus' // 服务列表 const services = [ { id: 1, name: '家政服务', description: '专业保洁、护理等服务', icon: 'House', color: '#409EFF', types: [ { label: '日常保洁', value: 'cleaning' }, { label: '深度保洁', value: 'deep-cleaning' }, { label: '护理服务', value: 'care' } ] }, { id: 2, name: '快递代收', description: '快递代收和暂存服务', icon: 'Box', color: '#67C23A' }, { id: 3, name: '水电缴费', description: '水电费在线缴纳', icon: 'Money', color: '#E6A23C' }, { id: 4, name: '物业服务', description: '物业报修、投诉建议', icon: 'House', color: '#F56C6C' }, { id: 5, name: '维修服务', description: '家电维修、管道疏通', icon: 'Tools', color: '#909399' }, { id: 6, name: '社区团购', description: '团购优惠、便民服务', icon: 'ShoppingCart', color: '#9C27B0' } ] // 团购商品 const groupBuyFilter = ref('ongoing') const groupBuyItems = ref([ { id: 1, title: '新鲜水果礼盒', description: '精选时令水果,营养美味', image: 'https://example.com/fruits.jpg', groupPrice: 99, originalPrice: 199, participants: 35, target: 50, status: 'ongoing' }, // 添加更多团购商品... ]) // 进行中的服务 const activeServices = ref([ { id: 1, title: '家政保洁服务', description: '预约时间:2024-03-21 14:00', time: '2024-03-21 14:00', status: 'primary' }, // 添加更多服务记录... ]) // 未缴费账单 const unpaidBills = ref([ { id: 1, title: '水费', period: '2024年2月', amount: 85.5, icon: 'WaterMeter', color: '#409EFF' }, { id: 2, title: '电费', period: '2024年2月', amount: 156.8, icon: 'Lightning', color: '#E6A23C' }, { id: 3, title: '物业费', period: '2024年第一季度', amount: 450, icon: 'House', color: '#67C23A' } ]) // 服务预约表单 const serviceDialogVisible = ref(false) const currentService = ref<any>(null) const serviceForm = ref({ type: '', date: '', address: '', notes: '' }) // 计算属性 const filteredGroupBuyItems = computed(() => { return groupBuyItems.value.filter(item => item.status === groupBuyFilter.value) }) // 方法 const handleService = (service: any) => { currentService.value = service serviceDialogVisible.value = true } const submitService = () => { ElMessage.success('服务预约成功') serviceDialogVisible.value = false // 重置表单 serviceForm.value = { type: '', date: '', address: '', notes: '' } } const joinGroupBuy = (item: any) => { ElMessageBox.confirm( '确定参与该团购活动吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'info' } ).then(() => { ElMessage.success('参与成功') item.participants++ }) } const getGroupBuyButtonText = (status: string) => { const texts: Record<string, string> = { ongoing: '立即参与', upcoming: '即将开始', ended: '已结束' } return texts[status] || '立即参与' } const contactService = (service: any) => { ElMessage.success(`正在连接服务人员...`) } const cancelService = (service: any) => { ElMessageBox.confirm( '确定要取消该服务吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } ).then(() => { ElMessage.success('服务已取消') activeServices.value = activeServices.value.filter(s => s.id !== service.id) }) } const payBill = (bill: any) => { ElMessageBox.confirm( `确定支付${bill.title} ¥${bill.amount}吗?`, '提示', { confirmButtonText: '确定支付', cancelButtonText: '取消', type: 'info' } ).then(() => { ElMessage.success('支付成功') unpaidBills.value = unpaidBills.value.filter(b => b.id !== bill.id) }) } const batchPayment = () => { const total = unpaidBills.value.reduce((sum, bill) => sum + bill.amount, 0) ElMessageBox.confirm( `确定一键支付所有账单 ¥${total.toFixed(2)}吗?`, '提示', { confirmButtonText: '确定支付', cancelButtonText: '取消', type: 'info' } ).then(() => { ElMessage.success('批量支付成功') unpaidBills.value = [] }) } </script> <style scoped> .service-page { padding: 20px; } .mt-20 { margin-top: 20px; } .card-header { display: flex; justify-content: space-between; align-items: center; } /* 服务网格样式 */ .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; } .service-item { display: flex; flex-direction: column; align-items: center; padding: 20px; background: #f5f7fa; border-radius: 8px; cursor: pointer; transition: all 0.3s; } .service-item:hover { transform: translateY(-2px); box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1); } .service-item h3 { margin: 15px 0 5px; font-size: 18px; } .service-item p { margin: 0; color: #666; text-align: center; } /* 团购列表样式 */ .group-buy-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; } .group-buy-item { background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1); } .group-buy-item .el-image { width: 100%; height: 200px; } .item-info { padding: 15px; } .item-info h4 { margin: 0 0 10px 0; font-size: 16px; } .description { color: #666; margin: 0 0 10px 0; font-size: 14px; } .price-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .price .current { color: #f56c6c; font-size: 20px; font-weight: bold; margin-right: 8px; } .price .original { color: #999; text-decoration: line-through; font-size: 14px; } .participants { color: #666; font-size: 14px; } .progress-info { margin: 10px 0; } /* 服务记录样式 */ .service-actions { margin-top: 10px; } /* 缴费列表样式 */ .payment-list { display: flex; flex-direction: column; gap: 15px; } .payment-item { display: flex; justify-content: space-between; align-items: center; padding: 15px; background: #f5f7fa; border-radius: 8px; } .bill-info { display: flex; align-items: center; gap: 10px; } .bill-details h4 { margin: 0 0 5px 0; font-size: 16px; } .bill-details p { margin: 0; color: #666; font-size: 14px; } .bill-amount { text-align: right; } .amount { display: block; color: #f56c6c; font-size: 18px; font-weight: bold; margin-bottom: 5px; } </style>