mrr.sj.front/pages/yuyue/yuyue.vue

336 lines
8.5 KiB
Vue

<template>
<view class="appointment-page">
<!-- 服务选择 -->
<view class="section">
<text class="section-title">选择服务</text>
<radio-group @change="handleServiceChange">
<label v-for="item in services" :key="item.id" class="radio-item">
<radio :value="item.name" :checked="selectedService === item.name" />
<text>{{ item.name }} ({{ item.duration }}分钟)</text>
</label>
</radio-group>
</view>
<!-- 日期选择 -->
<view class="section">
<text class="section-title">选择日期</text>
<picker
mode="date"
:value="selectedDate"
:start="startDate"
:end="endDate"
@change="handleDateChange"
>
<view class="picker">
{{ selectedDate }} ({{ selectedDay }})
</view>
</picker>
</view>
<!-- 时间选择 -->
<view class="section" v-if="timeSlots.length > 0">
<text class="section-title">选择时间</text>
<view class="time-slots">
<view
v-for="(slot, index) in timeSlots"
:key="index"
class="time-slot"
:class="{ selected: selectedTime === slot[0] }"
@click="selectTime(slot)"
>
{{ slot[0] }} - {{ slot[1] }}
</view>
</view>
</view>
<view v-else class="no-slots">
当前没有可预约时段
</view>
<!-- 提交按钮 -->
<button
type="primary"
class="submit-btn"
:disabled="!selectedService || !selectedTime"
@click="submitAppointment"
>
确认预约
</button>
</view>
</template>
<script>
import { ServiceManager } from '../../utils/service'
export default {
data() {
return {
serviceManager: new ServiceManager(),
services: [
{ id: 1, name: '剪发', duration: 30 },
{ id: 2, name: '染发', duration: 90 },
{ id: 3, name: '护理', duration: 60 }
],
selectedService: '',
selectedDate: '',
selectedDay: '',
selectedTime: '',
timeSlots: [],
existingAppointments: {
// 示例数据: 已有预约
'2023-06-15': [['10:00', '10:30'], ['14:00', '15:00']],
'2023-06-16': [['09:30', '10:30']]
}
}
},
computed: {
startDate() {
return this.getDateStr(0)
},
endDate() {
return this.getDateStr(30) // 可预约未来30天
}
},
created() {
this.initServiceManager()
this.selectedDate = this.getDateStr(0)
this.updateDayName()
},
methods: {
// 生成时间段选项
generateTimeSlots(date) {
if (!this.selected_date) {
this.timeOptions = [];
return;
}
const slots = [];
let workTime;
let startWorkTime;
let endWorkTime;
if(this.service.server_kind == 1) {
workTime = this.syrorsjInfo.default_times.split('-');
startWorkTime = workTime[0].split(':');
endWorkTime = workTime[1].split(':');
}else if(this.service.server_kind == 2) {
workTime = this.syrorsjInfo.business_time.split('-');
startWorkTime = workTime[0].split(':');
endWorkTime = workTime[1].split(':');
}
const now = new Date();
let startHour;
if(this.selectedDateIndex == 0) {
startHour = now.getHours();
if(startHour > parseInt(startWorkTime[0])) {
const startMinute = now.getMinutes();
let beginTime = new Date();
if (startMinute >= 30) {
startHour = startHour+1;
}
}else {
startHour = parseInt(startWorkTime[0]);
}
}else {
startHour = parseInt(startWorkTime[0]);
}
const endHour = parseInt(endWorkTime[0]); // 结束时间 18:00
// const bookedTimes = this.bookedSlots[this.date] || [];
for (let hour = startHour; hour < endHour; hour++) {
for (let minute = 0; minute < 60; minute += 30) {
const timeStr = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
// 跳过已预约的时间
// if (!bookedTimes.includes(timeStr)) {
slots.push({
label: timeStr,
value: timeStr
});
// }
}
}
this.timeOptions = slots;
// 如果没有可用时间段,显示提示
if (slots.length === 0) {
this.timeOptions = [{ label: '该日期无可用时间段', value: '' }];
}
},
// 初始化服务管理器
initServiceManager() {
const sm = this.serviceManager
// 设置工作日时间 (9:00-17:00)
const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
weekdays.forEach(day => {
sm.setWorkingHours(day, '09:00', '12:00')
sm.setWorkingHours(day, '13:00', '17:00')
})
// 周末时间 (10:00-16:00)
sm.setWorkingHours('Saturday', '10:00', '16:00')
sm.setWorkingHours('Sunday', '10:00', '16:00')
// 设置午休时间
weekdays.forEach(day => {
sm.addBlockedTime(day, '12:00', '13:00')
})
// 添加服务
this.services.forEach(service => {
sm.addService(service.name, service.duration)
})
},
// 获取日期字符串
getDateStr(daysAfterToday) {
const date = new Date()
date.setDate(date.getDate() + daysAfterToday)
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`
},
// 更新星期几显示
updateDayName() {
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
const date = new Date(this.selectedDate)
this.selectedDay = days[date.getDay()]
},
// 服务选择变化
handleServiceChange(e) {
this.selectedService = e.detail.value
this.updateTimeSlots()
},
// 日期选择变化
handleDateChange(e) {
this.selectedDate = e.detail.value
this.updateDayName()
this.updateTimeSlots()
},
// 更新时间段列表
updateTimeSlots() {
if (!this.selectedService) return
const day = this.selectedDay
const appointments = this.existingAppointments[this.selectedDate] || []
try {
this.timeSlots = this.serviceManager.getAvailableSlots(day, this.selectedService, appointments)
this.selectedTime = ''
} catch (e) {
uni.showToast({
title: e.message,
icon: 'none'
})
this.timeSlots = []
}
},
// 选择时间段
selectTime(slot) {
this.selectedTime = slot[0]
},
// 提交预约
submitAppointment() {
if (!this.selectedService || !this.selectedTime) return
const duration = this.services.find(s => s.name === this.selectedService).duration
const endTime = this.addMinutes(this.selectedTime, duration)
uni.showModal({
title: '确认预约',
content: `确认预约 ${this.selectedService} 服务\n时间: ${this.selectedDate} ${this.selectedTime}-${endTime}`,
success: (res) => {
if (res.confirm) {
// 这里应该调用API保存预约
uni.showToast({
title: '预约成功',
icon: 'success'
})
// 添加到已有预约
if (!this.existingAppointments[this.selectedDate]) {
this.existingAppointments[this.selectedDate] = []
}
this.existingAppointments[this.selectedDate].push([this.selectedTime, endTime])
// 重置选择
this.selectedTime = ''
this.updateTimeSlots()
}
}
})
},
// 时间加减
addMinutes(time, minutes) {
const [hours, mins] = time.split(':').map(Number)
let totalMins = hours * 60 + mins + minutes
const newHours = Math.floor(totalMins / 60)
const newMins = totalMins % 60
return `${newHours.toString().padStart(2, '0')}:${newMins.toString().padStart(2, '0')}`
}
}
}
</script>
<style>
.appointment-page {
padding: 20px;
}
.section {
margin-bottom: 30px;
}
.section-title {
display: block;
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.radio-item {
display: flex;
align-items: center;
margin: 10px 0;
}
.picker {
padding: 10px;
border: 1px solid #eee;
border-radius: 4px;
}
.time-slots {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.time-slot {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
}
.time-slot.selected {
background-color: #007aff;
color: white;
border-color: #007aff;
}
.no-slots {
color: #999;
text-align: center;
padding: 20px;
}
.submit-btn {
margin-top: 30px;
}
</style>