背景
随着机动车逐渐走进寻常百姓家中,学车也随之被人们提上了日程,这使得汽车驾驶培训行业得到迅猛发展。移动互联网技术的广泛应用,使手机约车成为可能,如何合理地分配已有资源,提高资源利用率,增强驾校服务水平,己成为驾校越来越迫切的需求。驾校学车预约小程序使预约者只需拿起手机,就可以线上约车,可以做到“足不出户选教练”,这样能够有效减少学习者的等待时间,从而为学员提供更优质的服务。 本系统包含学员端,教练端,管理端三方,不前后端完整,包括公告,驾校教练预约,科目培训预约,后台管理,用户管理,预约名单管理,预约记录管理与导出,我的预约,历史浏览,我的收藏等模块,采用腾讯提供的小程序云开发解决方案,无须服务器和域名。
概要设计
本项目分为学员端,驾校教练端,后台端3个组成部分:
- 后台端:可以添加和设定教练的基本信息,账号,登陆密码等。
- 驾校教练端:可以编辑自己的个人资料(头像,简介,星级等),设定预约时段排期(可预约时段,各时段人数限定), 在现场核销用户的预约码。
- 学员端:选择自己需要的教练和时段,下单预约,预约成功后到健身房出示预约码给教练或者工作人员核销
数据库设计
MeetModel.DB_STRUCTURE = {
_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',
};
技术运用
- 本项目使用微信小程序平台进行开发。
- 使用腾讯专门的小程序云开发技术,云资源包含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。
- 小程序本身的即用即走,适合小工具的使用场景,也适合快速开发迭代。
- 云开发技术采用腾讯内部链路,没有被黑客攻击的风险,不会 DDOS攻击,节省防火墙费用,安全性高且免维护。
- 资源承载力可根据业务发展需要随时弹性扩展。
难点实现
/** 获取日期设置 */
async getDaysSet(meetId, startDay, endDay = null) {
let where = {
DAY_MEET_ID: meetId
}
if (startDay && endDay && endDay == startDay)
where.day = startDay;
else if (startDay && endDay)
where.day = ['between', startDay, endDay];
else if (!startDay && endDay)
where.day = ['<=', endDay];
else if (startDay && !endDay)
where.day = ['>=', startDay];
let orderBy = {
'day': 'asc'
}
let list = await DayModel.getAllBig(where, 'day,dayDesc,times', orderBy, 1000);
for (let k = 0; k < list.length; k++) {
delete list[k]._id;
}
return list;
}
// 按时段统计某时段报名情况
async statJoinCnt(meetId, timeMark) {
let whereDay = {
DAY_MEET_ID: meetId,
day: this.getDayByTimeMark(timeMark)
};
let day = await DayModel.getOne(whereDay, 'times');
if (!day) return;
let whereJoin = {
JOIN_MEET_TIME_MARK: timeMark,
JOIN_MEET_ID: meetId
};
let ret = await JoinModel.groupCount(whereJoin, 'JOIN_STATUS');
let stat = { //统计数据
succCnt: ret['JOIN_STATUS_1'] || 0, //1=预约成功,
cancelCnt: ret['JOIN_STATUS_10'] || 0, //10=已取消,
adminCancelCnt: ret['JOIN_STATUS_99'] || 0, //99=后台取消
};
let times = day.times;
for (let j in times) {
if (times[j].mark === timeMark) {
let data = {
['times.' + j + '.stat']: stat
}
await DayModel.edit(whereDay, data);
return;
}
}
}
学员端UI设计
教练端UI设计
后台管理UI设计