yl-frontend/src/views/ServiceView.vue

597 lines
14 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>
<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>