first commit
This commit is contained in:
147
pages/appointment/index.js
Normal file
147
pages/appointment/index.js
Normal file
@@ -0,0 +1,147 @@
|
||||
// pages/appointment/index.js
|
||||
Page({
|
||||
data: {
|
||||
appointmentList: [],
|
||||
services: [
|
||||
{ id: 1, name: '面部护理', duration: 60, price: 298 },
|
||||
{ id: 2, name: '身体按摩', duration: 90, price: 398 },
|
||||
{ id: 3, name: '美甲服务', duration: 45, price: 158 },
|
||||
{ id: 4, name: '美发造型', duration: 120, price: 258 }
|
||||
],
|
||||
selectedDate: '',
|
||||
selectedTime: '',
|
||||
selectedService: null,
|
||||
timeSlots: ['09:00', '10:00', '11:00', '13:00', '14:00', '15:00', '16:00', '17:00'],
|
||||
currentDate: '',
|
||||
dateList: []
|
||||
},
|
||||
|
||||
onLoad: function (options) {
|
||||
this.generateDateList();
|
||||
this.setData({
|
||||
selectedDate: this.data.dateList[0].date,
|
||||
currentDate: this.data.dateList[0].date
|
||||
});
|
||||
|
||||
// 从本地存储获取预约列表
|
||||
const appointmentList = wx.getStorageSync('appointmentList') || [];
|
||||
this.setData({ appointmentList });
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().init();
|
||||
}
|
||||
|
||||
// 刷新预约列表
|
||||
const appointmentList = wx.getStorageSync('appointmentList') || [];
|
||||
this.setData({ appointmentList });
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh: function() {
|
||||
// 刷新预约列表
|
||||
const appointmentList = wx.getStorageSync('appointmentList') || [];
|
||||
this.setData({ appointmentList }, () => {
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
// 生成未来7天的日期列表
|
||||
generateDateList: function() {
|
||||
const dateList = [];
|
||||
const today = new Date();
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const date = new Date(today);
|
||||
date.setDate(today.getDate() + i);
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()];
|
||||
|
||||
dateList.push({
|
||||
date: `${year}-${month}-${day}`,
|
||||
day: day,
|
||||
weekday: weekday
|
||||
});
|
||||
}
|
||||
|
||||
this.setData({ dateList });
|
||||
},
|
||||
|
||||
// 选择日期
|
||||
selectDate: function(e) {
|
||||
const date = e.currentTarget.dataset.date;
|
||||
this.setData({ selectedDate: date });
|
||||
},
|
||||
|
||||
// 选择时间
|
||||
selectTime: function(e) {
|
||||
const time = e.currentTarget.dataset.time;
|
||||
this.setData({ selectedTime: time });
|
||||
},
|
||||
|
||||
// 选择服务
|
||||
selectService: function(e) {
|
||||
const serviceId = e.currentTarget.dataset.id;
|
||||
const service = this.data.services.find(item => item.id === serviceId);
|
||||
this.setData({ selectedService: service });
|
||||
},
|
||||
|
||||
// 提交预约
|
||||
submitAppointment: function() {
|
||||
const { selectedDate, selectedTime, selectedService } = this.data;
|
||||
|
||||
if (!selectedDate || !selectedTime || !selectedService) {
|
||||
wx.showToast({
|
||||
title: '请完成所有选择',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新预约
|
||||
const newAppointment = {
|
||||
id: Date.now(),
|
||||
date: selectedDate,
|
||||
time: selectedTime,
|
||||
service: selectedService,
|
||||
status: '待确认'
|
||||
};
|
||||
|
||||
// 更新预约列表
|
||||
const appointmentList = [...this.data.appointmentList, newAppointment];
|
||||
|
||||
// 保存到本地存储
|
||||
wx.setStorageSync('appointmentList', appointmentList);
|
||||
|
||||
this.setData({
|
||||
appointmentList,
|
||||
selectedTime: '',
|
||||
selectedService: null
|
||||
});
|
||||
|
||||
wx.showToast({
|
||||
title: '预约成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
|
||||
// 取消预约
|
||||
cancelAppointment: function(e) {
|
||||
const id = e.currentTarget.dataset.id;
|
||||
const appointmentList = this.data.appointmentList.filter(item => item.id !== id);
|
||||
|
||||
// 更新本地存储
|
||||
wx.setStorageSync('appointmentList', appointmentList);
|
||||
|
||||
this.setData({ appointmentList });
|
||||
|
||||
wx.showToast({
|
||||
title: '已取消预约',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
})
|
||||
9
pages/appointment/index.json
Normal file
9
pages/appointment/index.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"t-button": "tdesign-miniprogram/button/button",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-empty": "tdesign-miniprogram/empty/empty",
|
||||
"navigation-bar": "/components/navigation-bar/navigation-bar"
|
||||
},
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
92
pages/appointment/index.wxml
Normal file
92
pages/appointment/index.wxml
Normal file
@@ -0,0 +1,92 @@
|
||||
<!--pages/appointment/index.wxml-->
|
||||
<navigation-bar title="预约服务" back="{{false}}" color="black" background="#FFF"></navigation-bar>
|
||||
|
||||
<view class="appointment-container">
|
||||
<!-- 日期选择 -->
|
||||
<view class="section date-section">
|
||||
<view class="section-title">选择日期</view>
|
||||
<scroll-view scroll-x class="date-scroll">
|
||||
<view class="date-list">
|
||||
<view
|
||||
wx:for="{{dateList}}"
|
||||
wx:key="date"
|
||||
class="date-item {{selectedDate === item.date ? 'active' : ''}}"
|
||||
bindtap="selectDate"
|
||||
data-date="{{item.date}}"
|
||||
>
|
||||
<view class="date-weekday">{{item.weekday}}</view>
|
||||
<view class="date-day">{{item.day}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 时间选择 -->
|
||||
<view class="section time-section">
|
||||
<view class="section-title">选择时间</view>
|
||||
<view class="time-list">
|
||||
<view
|
||||
wx:for="{{timeSlots}}"
|
||||
wx:key="*this"
|
||||
class="time-item {{selectedTime === item ? 'active' : ''}}"
|
||||
bindtap="selectTime"
|
||||
data-time="{{item}}"
|
||||
>
|
||||
{{item}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务选择 -->
|
||||
<view class="section service-section">
|
||||
<view class="section-title">选择服务</view>
|
||||
<view class="service-list">
|
||||
<view
|
||||
wx:for="{{services}}"
|
||||
wx:key="id"
|
||||
class="service-item {{selectedService.id === item.id ? 'active' : ''}}"
|
||||
bindtap="selectService"
|
||||
data-id="{{item.id}}"
|
||||
>
|
||||
<view class="service-name">{{item.name}}</view>
|
||||
<view class="service-info">
|
||||
<text class="service-duration">{{item.duration}}分钟</text>
|
||||
<text class="service-price">¥{{item.price}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<t-button theme="primary" size="large" block bindtap="submitAppointment">提交预约</t-button>
|
||||
</view>
|
||||
|
||||
<!-- 我的预约列表 -->
|
||||
<view class="section my-appointments" wx:if="{{appointmentList.length > 0}}">
|
||||
<view class="section-title">我的预约</view>
|
||||
<view class="appointment-list">
|
||||
<view wx:for="{{appointmentList}}" wx:key="id" class="appointment-card">
|
||||
<view class="appointment-header">
|
||||
<view class="appointment-service">{{item.service.name}}</view>
|
||||
<view class="appointment-status {{item.status === '已确认' ? 'confirmed' : ''}}">{{item.status}}</view>
|
||||
</view>
|
||||
<view class="appointment-info">
|
||||
<view class="appointment-time">
|
||||
<t-icon name="time" size="40rpx" />
|
||||
<text>{{item.date}} {{item.time}}</text>
|
||||
</view>
|
||||
<view class="appointment-price">¥{{item.service.price}}</view>
|
||||
</view>
|
||||
<view class="appointment-actions">
|
||||
<t-button size="small" variant="outline" bindtap="cancelAppointment" data-id="{{item.id}}">取消预约</t-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 无预约提示 -->
|
||||
<view class="empty-appointments" wx:if="{{appointmentList.length === 0}}">
|
||||
<t-empty icon="info-circle-filled" description="暂无预约记录" />
|
||||
</view>
|
||||
</view>
|
||||
196
pages/appointment/index.wxss
Normal file
196
pages/appointment/index.wxss
Normal file
@@ -0,0 +1,196 @@
|
||||
/* pages/appointment/index.wxss */
|
||||
.appointment-container {
|
||||
padding: 30rpx;
|
||||
padding-bottom: 130rpx !important; /* 为底部标签栏留出空间 */
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 日期选择样式 */
|
||||
.date-scroll {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date-list {
|
||||
display: flex;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.date-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
margin-right: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f8f8f8;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.date-item.active {
|
||||
background-color: #FF5F15;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.date-weekday {
|
||||
font-size: 24rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.date-day {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 时间选择样式 */
|
||||
.time-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.time-item {
|
||||
width: 150rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
text-align: center;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.time-item.active {
|
||||
background-color: #FF5F15;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 服务选择样式 */
|
||||
.service-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.service-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f8f8f8;
|
||||
margin-bottom: 20rpx;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.service-item.active {
|
||||
background-color: #FFF0E6;
|
||||
border: 2rpx solid #FF5F15;
|
||||
}
|
||||
|
||||
.service-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.service-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.service-price {
|
||||
color: #FF5F15;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 提交按钮样式 */
|
||||
.submit-section {
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
|
||||
/* 预约列表样式 */
|
||||
.appointment-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.appointment-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.appointment-service {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.appointment-status {
|
||||
font-size: 24rpx;
|
||||
color: #FF9500;
|
||||
background-color: #FFF5E5;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.appointment-status.confirmed {
|
||||
color: #07C160;
|
||||
background-color: #E8F8F0;
|
||||
}
|
||||
|
||||
.appointment-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.appointment-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.appointment-time text {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.appointment-price {
|
||||
font-size: 32rpx;
|
||||
color: #FF5F15;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.appointment-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
.empty-appointments {
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
Reference in New Issue
Block a user