开发背景
在当代“瘦身热”的带动下,到健身房运动和瘦身的人员也在不断增加,一定程度上加大了健身房的管理难度,因此,开发一款属于健身房预约的小程序这时候正好可以派上用场
概要设计
本项目分为用户端,教练端,后台端3个组成部分:
- 预约管理:开始/截止时间/人数均可灵活设置,可以自定义客户预约填写的数据项
- 预约凭证:支持线下到场后校验签到/核销/二维码自助签到等多种方式
- 详尽的预约数据:支持预约名单数据导出Excel,打印
技术选型
- 本项目使用微信小程序平台进行开发。
- 使用腾讯专门的小程序云开发技术,云资源包含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。
- 小程序本身的即用即走,适合小工具的使用场景,也适合快速开发迭代。
- 云开发技术采用腾讯内部链路,节省防火墙费用,安全性高且免维护。
- 资源承载力可根据业务发展需要随时弹性扩展。
数据库设计
_pid: 'string|true',
MEET_ID: 'string|true',
MEET_ADMIN_ID: 'string|true|comment=添加的管理员',
MEET_TITLE: 'string|true|comment=标题',
MEET_JOIN_FORMS: 'array|true|default=[]|comment=表单字段设置',
MEET_DAYS: 'array|true|default=[]|comment=最近一次修改保存的可用日期',
MEET_CATE_ID: 'string|true|comment=分类编号',
MEET_CATE_NAME: 'string|true|comment=分类冗余',
MEET_FORMS: 'array|true|default=[]',
MEET_OBJ: 'object|true|default={}',
MEET_CANCEL_SET: 'int|true|default=1|comment=取消设置 0=不允,1=允许,2=仅开始前可取消',
MEET_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=使用中,9=停止预约,10=已关闭',
MEET_ORDER: 'int|true|default=9999',
MEET_VOUCH: 'int|true|default=0',
MEET_QR: 'string|false',
MEET_PHONE: 'string|false|comment=登录手机',
MEET_PASSWORD: 'string|false|comment=登录密码',
MEET_TOKEN: 'string|false|comment=当前登录token',
MEET_TOKEN_TIME: 'int|true|default=0|comment=当前登录token time',
MEET_MINI_OPENID: 'string|false|comment=小程序openid',
MEET_LOGIN_CNT: 'int|true|default=0|comment=登陆次数',
MEET_LOGIN_TIME: 'int|false|comment=最近登录时间',
MEET_ADD_TIME: 'int|true',
MEET_EDIT_TIME: 'int|true',
MEET_ADD_IP: 'string|false',
MEET_EDIT_IP: 'string|false',
技术难点
// 用户预约逻辑
async join(userId, meetId, timeMark, formsList) {
// 预约时段是否存在
let meetWhere = {
_id: meetId
};
let day = this.getDayByTimeMark(timeMark);
let meet = await this.getMeetOneDay(meetId, day, meetWhere);
if (!meet) {
this.AppError('预约时段选择错误1,请重新选择');
}
let daySet = this.getDaySetByTimeMark(meet, timeMark);
if (!daySet)
this.AppError('预约时段选择错误2,请重新选择');
let timeSet = this.getTimeSetByTimeMark(meet, timeMark);
if (!timeSet)
this.AppError('预约时段选择错误3,请重新选择');
// 规则校验
await this.checkMeetRules(userId, meetId, timeMark, formsList);
let data = {};
data.JOIN_USER_ID = userId;
data.JOIN_MEET_ID = meetId;
data.JOIN_MEET_CATE_ID = meet.MEET_CATE_ID;
data.JOIN_MEET_CATE_NAME = meet.MEET_CATE_NAME;
data.JOIN_MEET_TITLE = meet.MEET_TITLE;
data.JOIN_MEET_DAY = daySet.day;
data.JOIN_MEET_TIME_START = timeSet.start;
data.JOIN_MEET_TIME_END = timeSet.end;
data.JOIN_MEET_TIME_MARK = timeMark;
data.JOIN_START_TIME = timeUtil.time2Timestamp(daySet.day + ' ' + timeSet.start + ':00');
data.JOIN_STATUS = JoinModel.STATUS.SUCC;
data.JOIN_COMPLETE_END_TIME = daySet.day + ' ' + timeSet.end;
// 入库
for (let k = 0; k < formsList.length; k++) {
let forms = formsList[k];
data.JOIN_FORMS = forms;
data.JOIN_OBJ = dataUtil.dbForms2Obj(forms);
data.JOIN_CODE = dataUtil.genRandomIntString(15);
await JoinModel.insert(data);
}
// 统计
this.statJoinCnt(meetId, timeMark);
return {
result: 'ok',
}
}
UI设计(用户端)
教练端截图
后台管理系统截图
git
git源码