家政服务小程序设计与实现
一、系统设计
(一)系统架构设计
本家政服务系统基于微信小程序云开发,采用前后端分离的架构。前端是微信小程序,负责与用户进行交互,展示各种功能界面,如首页、服务详情页、预约表单页、订单列表页等。后端依托微信云开发提供的云函数、云数据库和云存储等服务。云函数用于处理业务逻辑,如订单生成、服务人员调度等;云数据库用于存储用户信息、服务信息、订单信息等数据;云存储用于存储服务人员头像、用户上传的图片等文件。
(二)功能模块设计
-
用户管理模块:包括用户注册登录、个人信息管理。用户可以通过微信授权快速注册登录,登录后可修改昵称、联系方式、地址等个人信息。
-
服务展示模块:展示各类家政服务,如保洁、家电清洗、月嫂等。每个服务有详细介绍,包括服务内容、价格、服务时长、服务人员技能要求等。同时,展示热门服务推荐,方便用户选择。
-
预约下单模块:用户选择服务项目、服务时间、服务人员(可选),填写预约地址等信息后提交订单。系统会验证服务时间是否冲突、地址是否合法等。
-
**[订单管理模块
-
服务人员管理模块:管理员可对服务人员进行管理,添加、删除、修改服务人员信息,设置其技能、服务区域、工作时间等。
-
评价管理模块:用户对完成的服务进行评价,评价内容包括服务质量、态度、效率等。评价信息对其他用户和服务人员公开,作为选择和改进服务的参考。
(三)数据库设计
- 用户表(users):存储用户信息,包括用户ID、昵称、微信openid、联系方式、地址等。
- 服务人员表(service_providers):存储服务人员信息,如服务人员ID、姓名、性别、联系方式、技能、服务区域、工作时间、头像等。
- 服务项目表(services):存储家政服务项目信息,包括服务项目ID、服务名称、服务内容、价格、服务时长等。
- 订单表(orders):存储订单信息,如订单ID、用户ID、服务项目ID、服务人员ID(可为空,下单时未指定)、服务时间、预约地址、订单状态、支付状态等。
- 评价表(reviews):存储用户对服务的评价信息,包括评价ID、订单ID、用户ID、服务人员ID、评分、评价内容等。
(四)接口设计
- 用户接口:提供微信授权登录、获取用户信息、更新用户信息等接口。
- 服务接口:获取服务项目列表、服务项目详情等接口。
- 预约接口:提交预约订单、获取预约表单信息等接口。
- 订单接口:获取订单列表、支付订单、取消订单、评价订单等接口。
- 服务人员接口:获取服务人员列表、服务人员详情等接口。
二、系统实现
(一)开发环境与技术选型
- 开发环境:微信开发者工具用于小程序前端开发和调试,云开发控制台用于后端云函数、数据库和存储的管理。
- 技术选型:
-
前端:微信小程序框架,使用WXML、WXSS和JavaScript进行页面结构和样式、逻辑的编写。
-
后端:微信云开发,利用云函数处理业务逻辑,云数据库进行数据存储和查询,云存储存储文件。
(二)关键功能实现
1、微信授权登录:
-
前端:在小程序页面中调用
wx.login()获取临时登录凭证(code),然后调用wx.getUserInfo()获取用户信息,将code和用户信息发送到后端云函数。 -
后端:云函数接收code和用户信息,通过微信提供的接口用code换取openid和session_key,将用户信息存储到用户表中,返回用户ID和登录态给前端。
2、预约下单:
-
前端:用户在预约表单页选择服务项目、服务时间、服务人员(可选)等信息,点击提交按钮后,将预约信息发送到后端云函数。
-
后端:云函数验证服务时间是否冲突、预约地址是否合法等,若验证通过,生成订单并存储到订单表中,同时通知相应的服务人员(可通过消息推送等方式)。
3、订单支付:
-
前端:在订单详情页点击支付按钮,调用微信支付接口,将支付信息发送到微信支付服务器。
-
后端:接收微信支付服务器返回的支付结果通知,更新订单的支付状态。
4、服务人员调度:
-
后端:云函数根据用户的预约信息和服务人员的排班情况,采用一定的算法(如贪心算法)进行服务人员调度,将调度结果通知服务人员。
(三)关键代码实现
1、首页(展示家政服务分类、热门推荐等)
pages/home/home.wxml
<view class="container">
<!-- 服务分类 -->
<view class="service-category">
<text class="title">服务分类</text>
<view class="category-list">
<block wx:for="{{serviceCategories}}" wx:key="index">
<view class="category-item">{{item}}</view>
</block>
</view>
</view>
<!-- 热门推荐 -->
<view class="hot-recommend">
<text class="title">热门推荐</text>
<view class="recommend-list">
<block wx:for="{{hotRecommendations}}" wx:key="index">
<view class="recommend-item">{{item}}</view>
</block>
</view>
</view>
</view>
pages/home/home.js
Page({
data: {
serviceCategories: [],
hotRecommendations: []
},
onLoad: function () {
this.loadServiceCategories();
this.loadHotRecommendations();
},
loadServiceCategories: function () {
// 这里调用云函数获取服务分类数据
this.setData({
serviceCategories: ["保洁", "家电维修", "月嫂"]
});
},
loadHotRecommendations: function () {
// 热门推荐数据
this.setData({
hotRecommendations: ["深度保洁", "空调清洗", "月嫂服务"]
});
}
});
后端云函数 - getServiceCategories
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
// 云函数入口函数
exports.main = async (event, context) => {
return {
serviceCategories: ["保洁", "家电维修", "月嫂"]
};
};
后端云函数 - getHotRecommendations
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
// 云函数入口函数
exports.main = async (event, context) => {
return {
hotRecommendations: ["深度保洁", "空调清洗", "月嫂服务"]
};
};
2、家政服务详情页(展示服务价格、服务内容等)
pages/serviceDetail/serviceDetail.wxml
<view class="container">
<view class="service-info">
<text class="service-name">{{serviceDetail.name}}</text>
<text class="service-price">价格:¥{{serviceDetail.price}}</text>
<text class="service-content">{{serviceDetail.content}}</text>
</view>
<button bindtap="makeAppointment">立即预约</button>
</view>
pages/serviceDetail/serviceDetail.js
Page({
data: {
serviceDetail: {}
},
onLoad: function (options) {
const serviceId = options.serviceId;
this.loadServiceDetail(serviceId);
},
loadServiceDetail: function (serviceId) {
// 这里调用云函数获取服务详情数据
let detail;
switch (serviceId) {
case "1":
detail = {
name: "深度保洁",
price: 199,
content: "包含客厅、卧室、厨房、卫生间全面清洁"
};
break;
// 其他服务详情...
}
this.setData({
serviceDetail: detail
});
},
makeAppointment: function () {
wx.navigateTo({
url: `/pages/appointmentForm/appointmentForm?serviceId=${this.data.serviceDetail.id}`
});
}
});
后端云函数 - getServiceDetail
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
// 云函数入口函数
exports.main = async (event, context) => {
const serviceId = event.serviceId;
let detail;
switch (serviceId) {
case "1":
detail = {
name: "深度保洁",
price: 199,
content: "包含客厅、卧室、厨房、卫生间全面清洁"
};
break;
// 其他服务详情...
}
return {
serviceDetail: detail
};
};
3、预约表单页(填写服务地址、选择服务时间等)
pages/appointmentForm/appointmentForm.wxml
<view class="container">
<view class="form-item">
<text>服务地址</text>
<input placeholder="请输入服务地址" bindinput="inputAddress" />
</view>
<view class="form-item">
<text>服务时间</text>
<picker mode="date" bindchange="selectDate">
<view>{{selectedDate || '请选择日期'}}</view>
</picker>
<picker mode="time" bindchange="selectTime">
<view>{{selectedTime || '请选择时间'}}</view>
</picker>
</view>
<button bindtap="submitAppointment">提交预约</button>
</view>
pages/appointmentForm/appointmentForm.js
Page({
data: {
serviceId: "",
address: "",
selectedDate: "",
selectedTime: ""
},
onLoad: function (options) {
this.setData({
serviceId: options.serviceId
});
},
inputAddress: function (e) {
this.setData({
address: e.detail.value
});
},
selectDate: function (e) {
this.setData({
selectedDate: e.detail.value
});
},
selectTime: function (e) {
this.setData({
selectedTime: e.detail.value
});
},
submitAppointment: function () {
const { serviceId, address, selectedDate, selectedTime } = this.data;
if (!address ||!selectedDate ||!selectedTime) {
wx.showToast({
title: '请填写完整信息',
icon: 'none'
});
return;
}
wx.cloud.callFunction({
name: 'submitAppointment',
data: {
serviceId,
address,
selectedDate,
selectedTime
},
success: res => {
wx.showToast({
title: '预约成功',
icon: 'success'
});
wx.navigateBack();
},
fail: err => {
wx.showToast({
title: '预约失败,请重试',
icon: 'none'
});
}
});
}
});
后端云函数 - submitAppointment
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
const { serviceId, address, selectedDate, selectedTime } = event;
// 这里可以进行服务时间冲突验证、地址合法性验证等
// 生成订单并存储到数据库
try {
await db.collection('orders').add({
data: {
serviceId,
address,
appointmentTime: `${selectedDate} ${selectedTime}`,
status: '待支付'
}
});
return {
success: true
};
} catch (error) {
return {
success: false,
error
};
}
};
4、订单列表页(展示用户订单状态等)
pages/orderList/orderList.wxml
<view class="container">
<view class="order-item" wx:for="{{orderList}}" wx:key="index">
<view class="order-info">
<text class="service-name">{{item.serviceName}}</text>
<text class="order-status">{{item.status}}</text>
</view>
<view class="order-actions">
<button wx:if="{{item.status === '待支付'}}" bindtap="payOrder" data-order-id="{{item._id}}">支付</button>
<button wx:if="{{item.status === '待评价'}}" bindtap="evaluateOrder" data-order-id="{{item._id}}">评价</button>
</view>
</view>
</view>
pages/orderList/orderList.js
Page({
data: {
orderList: []
},
onLoad: function () {
this.loadOrderList();
},
loadOrderList: function () {
wx.cloud.callFunction({
name: 'getOrderList',
success: res => {
this.setData({
orderList: res.result.orderList
});
},
fail: err => {
wx.showToast({
title: '加载订单失败',
icon: 'none'
});
}
});
},
payOrder: function (e) {
const orderId = e.currentTarget.dataset.orderId;
// 调用微信支付接口等逻辑
},
evaluateOrder: function (e) {
const orderId = e.currentTarget.dataset.orderId;
wx.navigateTo({
url: `/pages/evaluateOrder/evaluateOrder?orderId=${orderId}`
});
}
});
后端云函数 - getOrderList
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
try {
const orderList = await db.collection('orders').get();
return {
orderList: orderList.data
};
} catch (error) {
return {
error
};
}
};
5、评价页(用户对服务进行评价)
pages/evaluateOrder/evaluateOrder.wxml
<view class="container">
<view class="rating">
<text>评分</text>
<slider min="1" max="5" show-value bindchange="changeRating" />
</view>
<view class="comment">
<text>评价内容</text>
<textarea placeholder="请输入您的评价" bindinput="inputComment"></textarea>
</view>
<button bindtap="submitEvaluate">提交评价</button>
</view>
pages/evaluateOrder/evaluateOrder.js
Page({
data: {
orderId: "",
rating: 3,
comment: ""
},
onLoad: function (options) {
this.setData({
orderId: options.orderId
});
},
changeRating: function (e) {
this.setData({
rating: e.detail.value
});
},
inputComment: function (e) {
this.setData({
comment: e.detail.value
});
},
submitEvaluate: function () {
const { orderId, rating, comment } = this.data;
wx.cloud.callFunction({
name: 'submitEvaluate',
data: {
orderId,
rating,
comment
},
success: res => {
wx.showToast({
title: '评价成功',
icon: 'success'
});
wx.navigateBack();
},
fail: err => {
wx.showToast({
title: '评价失败,请重试',
icon: 'none'
});
}
});
}
});
后端云函数 - submitEvaluate
// 云函数入口文件
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
const { orderId, rating, comment } = event;
try {
await db.collection('reviews').add({
data: {
orderId,
rating,
comment
}
});
await db.collection('orders').doc(orderId).update({
data: {
status: '已完成'
}
});
return {
success: true
};
} catch (error) {
return {
success: false,
error
};
}
};