# 支付宝小程序商品预约功能实现 下面是一个完整的支付宝小程序商品预约功能的实现代码,包含前端页面和后端逻辑。 ## 1. 前端页面 (pages/reserve/reserve.axml) ```xml <view class="container"> <view class="product-info"> <image src="{{product.image}}" mode="aspectFill" class="product-image"></image> <view class="product-detail"> <text class="product-name">{{product.name}}</text> <text class="product-price">¥{{product.price}}</text> </view> </view> <view class="form-container"> <view class="form-item"> <text class="label">预约日期</text> <picker mode="date" start="{{minDate}}" end="{{maxDate}}" value="{{reserveDate}}" onChange="onDateChange"> <view class="picker">{{reserveDate || '请选择预约日期'}}</view> </picker> </view> <view class="form-item"> <text class="label">预约时间</text> <picker mode="time" value="{{reserveTime}}" onChange="onTimeChange"> <view class="picker">{{reserveTime || '请选择预约时间'}}</view> </picker> </view> <view class="form-item"> <text class="label">联系人</text> <input class="input" placeholder="请输入联系人姓名" value="{{contactName}}" onInput="onContactNameChange" /> </view> <view class="form-item"> <text class="label">联系电话</text> <input class="input" type="number" placeholder="请输入联系电话" value="{{contactPhone}}" onInput="onContactPhoneChange" /> </view> <view class="form-item"> <text class="label">备注</text> <textarea class="textarea" placeholder="请输入备注信息" value="{{remark}}" onInput="onRemarkChange"></textarea> </view> </view> <button type="primary" class="submit-btn" onTap="submitReservation">提交预约</button> </view> ``` ## 2. 前端样式 (pages/reserve/reserve.acss) ```css .container { padding: 20rpx; } .product-info { display: flex; margin-bottom: 30rpx; padding: 20rpx; background: #fff; border-radius: 10rpx; } .product-image { width: 200rpx; height: 200rpx; border-radius: 10rpx; } .product-detail { margin-left: 20rpx; display: flex; flex-direction: column; justify-content: space-between; } .product-name { font-size: 32rpx; font-weight: bold; } .product-price { font-size: 36rpx; color: #ff5000; } .form-container { background: #fff; padding: 20rpx; border-radius: 10rpx; } .form-item { margin-bottom: 30rpx; } .label { display: block; margin-bottom: 10rpx; font-size: 28rpx; color: #666; } .picker, .input, .textarea { width: 100%; padding: 20rpx; border: 1rpx solid #eee; border-radius: 8rpx; font-size: 28rpx; } .textarea { height: 200rpx; } .submit-btn { margin-top: 40rpx; width: 100%; } ``` ## 3. 前端逻辑 (pages/reserve/reserve.js) ```javascript Page({ data: { product: { id: '123', // 商品ID,实际应从路由参数获取 name: '示例商品', // 商品名称 price: '199.00', // 商品价格 image: 'https://example.com/product.jpg' // 商品图片 }, minDate: new Date().getTime(), // 最小可选日期,今天 maxDate: new Date(new Date().setMonth(new Date().getMonth() + 3)).getTime(), // 最大可选日期,3个月后 reserveDate: '', // 预约日期 reserveTime: '', // 预约时间 contactName: '', // 联系人 contactPhone: '', // 联系电话 remark: '' // 备注 }, onLoad(options) { // 从路由参数获取商品ID const productId = options.id; // 这里应该调用API获取商品详情 // this.getProductDetail(productId); }, // 日期选择变化 onDateChange(e) { this.setData({ reserveDate: e.detail.value }); }, // 时间选择变化 onTimeChange(e) { this.setData({ reserveTime: e.detail.value }); }, // 联系人输入变化 onContactNameChange(e) { this.setData({ contactName: e.detail.value }); }, // 联系电话输入变化 onContactPhoneChange(e) { this.setData({ contactPhone: e.detail.value }); }, // 备注输入变化 onRemarkChange(e) { this.setData({ remark: e.detail.value }); }, // 提交预约 submitReservation() { const { product, reserveDate, reserveTime, contactName, contactPhone } = this.data; // 简单验证 if (!reserveDate) { my.showToast({ content: '请选择预约日期', type: 'none' }); return; } if (!reserveTime) { my.showToast({ content: '请选择预约时间', type: 'none' }); return; } if (!contactName) { my.showToast({ content: '请输入联系人姓名', type: 'none' }); return; } if (!contactPhone) { my.showToast({ content: '请输入联系电话', type: 'none' }); return; } // 组装预约数据 const reservationData = { productId: product.id, reserveDate, reserveTime, contactName, contactPhone, remark: this.data.remark }; // 调用API提交预约 this.submitReservationToServer(reservationData); }, // 提交预约到服务器 submitReservationToServer(data) { my.showLoading({ content: '提交中...' }); my.request({ url: 'https://your-server.com/api/reservation', // 替换为你的API地址 method: 'POST', data, success: (res) => { my.hideLoading(); if (res.data.success) { my.showToast({ content: '预约成功', type: 'success' }); // 预约成功后跳转 setTimeout(() => { my.redirectTo({ url: '/pages/reservationSuccess/reservationSuccess' }); }, 1500); } else { my.showToast({ content: res.data.message || '预约失败', type: 'fail' }); } }, fail: () => { my.hideLoading(); my.showToast({ content: '网络错误,请重试', type: 'fail' }); } }); } }); ``` ## 4. 后端API示例 (Node.js) ```javascript const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // 预约数据存储 let reservations = []; // 预约API app.post('/api/reservation', (req, res) => { const { productId, reserveDate, reserveTime, contactName, contactPhone, remark } = req.body; // 验证数据 if (!productId || !reserveDate || !reserveTime || !contactName || !contactPhone) { return res.status(400).json({ success: false, message: '缺少必要参数' }); } // 验证手机号格式 if (!/^1[3-9]\d{9}$/.test(contactPhone)) { return res.status(400).json({ success: false, message: '手机号格式不正确' }); } // 创建预约记录 const reservation = { id: Date.now().toString(), productId, reserveDate, reserveTime, contactName, contactPhone, remark, createTime: new Date().toISOString(), status: 'pending' // 预约状态:pending/confirmed/canceled }; // 存储预约记录 reservations.push(reservation); // 返回成功响应 res.json({ success: true, data: reservation }); }); // 获取预约列表API app.get('/api/reservations', (req, res) => { res.json({ success: true, data: reservations }); }); // 启动服务器 const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); ``` ## 5. 数据库设计 (MySQL示例) ```sql CREATE TABLE `products` ( `id` varchar(32) NOT NULL COMMENT '商品ID', `name` varchar(100) NOT NULL COMMENT '商品名称', `price` decimal(10,2) NOT NULL COMMENT '商品价格', `image` varchar(255) DEFAULT NULL COMMENT '商品图片', `description` text COMMENT '商品描述', `status` tinyint(1) DEFAULT '1' COMMENT '商品状态:1-上架 0-下架', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; CREATE TABLE `reservations` ( `id` varchar(32) NOT NULL COMMENT '预约ID', `product_id` varchar(32) NOT NULL COMMENT '商品ID', `user_id` varchar(32) DEFAULT NULL COMMENT '用户ID', `reserve_date` date NOT NULL COMMENT '预约日期', `reserve_time` time NOT NULL COMMENT '预约时间', `contact_name` varchar(50) NOT NULL COMMENT '联系人', `contact_phone` varchar(20) NOT NULL COMMENT '联系电话', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `status` tinyint(1) DEFAULT '0' COMMENT '状态:0-待确认 1-已确认 2-已取消', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_product_id` (`product_id`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品预约表'; ``` ## 注意事项 1. 在实际项目中,前端应该从路由参数获取商品ID,然后调用API获取商品详情,而不是使用硬编码的数据。 2. 后端API应该添加身份验证和权限控制,确保只有登录用户才能提交预约,并且只能查看和管理自己的预约记录。 3. 预约时间冲突检查是重要功能,后端应该验证同一商品在同一时间的预约是否已满,避免超额预约。 [2025-03-26 02:24:39 | AI写代码神器 | 2568点数解答]