项目编号:BS-XX-184
一,环境介绍
语言环境:Java: jdk1.8
数据库:Mysql: mysql5.7
应用服务器:Tomcat: tomcat8.5.31
开发工具:IDEA或eclipse
开发技术:Springboot+Vue 前后端分离
二,项目简介
本课题研究的主是关于驾校预约管理系统的开发与实现。选个这个课题主要是基于目前国内汽车数量逐年增长,家庭拥有汽车数量也在不断增加,成人驾考热度持续上升的大背景。随着驾考人数的不断递增,各个驾校的生意可以说是十分红火,但传统的驾校报名和管理方式,使得客户的体验很差,据调查统计,80%的人对于驾校的管理和练车服务都不是很满意,觉得有很大需要提升的空间,反映最大的就是练车排队,浪费大量个人时间的问题。那么如何利用信息化技术手段,来帮助这些驾校开发实现一个预约练车的管理系统,让学员可以通过此系统提前在线预约,实现有效合理的练车安排,是本系统着重要研究的问题。
本课题主要使用信息化软件开发技术,开发实现一个练车预约管理系统,使得学员可以在线进行预约练车,教练可以在线查看练车信息,给学员进行打分,并可以通过学员的练车记录得分,估算出学生预约练车的通过率,同时可以完成在线汽车维修信息的管理,学员、教练、课程、汽车等基本信息的管理,可以通过本系统完成一个对驾校的综合性信息管理的功能,有效的提升学员练车的体验,并提升驾校本身的管理系统。
本次系统的的开发设计要技术上主要运用JAVA后台开发技术和VUE前端开发技术共同开发实现,采用前后端分离的方式来开发实现。系统提供了供前端用户答题使用的前端操作界面,以及提供后台管理员使用的后台管理界面,后台服务接口采用Springboot框架技术开发实现,同时集成Mybatis-plus 持久层框架完成数据持久化,业务数据存储采用MYSQL5.7进行数据存储。
本课题是驾校预约练车系统,由于本人也有在驾校考驾照的经历,经历了排队练车的煎熬过程,同时走访大量的驾考人员,阅读大量文献并参考同类的驾考平台,来分析系统的基本功能性需求。经过分析确定系统的用户主要分为学员用户、教练用户和后台管理用户两类,学员的主要功能有:用户在线注册与登陆、在线课程浏览、查看教练详情、车辆信息查看、在线预约练车的实现以及个人中心管理。后台管理用户的主要功能包含有:用户信息管理模块、个人信息管理模块、车辆信息管理、教练信息管理、预约数据管理、学员信息管理、车辆维修管理、课程管理等。教练的主要功能有:课程管理、学员管理、车辆管理、维修上报管理、学员预约记录管理等功能。
驾校预约练车系统具体的系统功能结构图如下图1所示:
图1系统功能架构
三,系统展示
本章节主要展示一下驾校预约练车系统系统相关核心功能的实现,主要通过功能模块界面和代码的方式来展示系统模块是如何实现的,下面将系统的学员用户和后台管理员的主要业务功能模块儿做一下统一的展示。
3.1学员功能模块实现
3.1.1 用户注册登陆
驾校预约练车系统的学员用户可以在系统平台提供的注册页面进行会员用户注册操作,用户注册后可以进行相应的登陆,登陆认证通过后可以在线进行进行相应的操作,用户注册如图3.1所示:
图3.1 用户注册
学员用户登陆的界面展示如下图3.2所示,用户输入账户和密码后,选择自己的身份,提交信息到后台服务接口,管理员、学员和教练登陆使用的是同一个界面,具体展示界面如下图3.2所示。
图3.2 用户登陆界面
3.1.2个人中心
学员登陆系统后可以在个人中心模块管理自己的个人信息,并可以在线修改密码,具体功能实现如下图3.3、3.4所示。
图3.3 个人信息管理
图3.4 个人密码管理
3.1.3 车辆信息查看
学员登陆系统后,可以在车辆管理模块查看目前驾校所拥有的车辆信息,具体如下图3.5所示:
图3.5 车辆查看
3.1.4 教练查看模块
学员登陆系统后,可以在教练管理模块查看目前驾校所拥有的教练信息,具体如下图4.6所示:
图3.6 教练管理
3.1.5 课程管理模块
学员登陆系统后,可以在课程管理模块查看目前驾校所设置的课程信息,具体如下图3.7所示:
图3.7 课程管理
3.1.6 在线预约模块
学员登陆系统后,可以在在线预约管理模块实现在线预约,完成预约添加和信息查看,具体如下图3.8所示:
图3.8 预约管理
图4.9 在线预约
3.2 教练功能模块(略)
3.3 管理员功能模块(略)
四,核心代码展示
package com.controller; import java.util.Arrays; import java.util.Map; import javax.servlet.http.HttpServletRequest; import com.service.UsersService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.annotation.IgnoreAuth; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.entity.UsersEntity; import com.service.TokenService; import com.utils.MPUtil; import com.utils.PageUtils; import com.utils.R; /** * 登录相关 */ @RequestMapping("users") @RestController public class UsersController { @Autowired private UsersService usersService; @Autowired private TokenService tokenService; /** * 登录 */ @IgnoreAuth @PostMapping(value = "/login") public R login(String username, String password, String captcha, HttpServletRequest request) { UsersEntity user = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username)); if(user==null || !user.getPassword().equals(password)) { return R.error("账号或密码不正确"); } String token = tokenService.generateToken(user.getId(),username, "users", user.getRole()); R r = R.ok(); r.put("token", token); r.put("role",user.getRole()); r.put("userId",user.getId()); return r; } /** * 注册 */ @IgnoreAuth @PostMapping(value = "/register") public R register(@RequestBody UsersEntity user){ // ValidatorUtils.validateEntity(user); if(usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", user.getUsername())) !=null) { return R.error("用户已存在"); } usersService.insert(user); return R.ok(); } /** * 退出 */ @GetMapping(value = "logout") public R logout(HttpServletRequest request) { request.getSession().invalidate(); return R.ok("退出成功"); } /** * 密码重置 */ @IgnoreAuth @RequestMapping(value = "/resetPass") public R resetPass(String username, HttpServletRequest request){ UsersEntity user = usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username)); if(user==null) { return R.error("账号不存在"); } user.setPassword("123456"); usersService.update(user,null); return R.ok("密码已重置为:123456"); } /** * 列表 */ @RequestMapping("/page") public R page(@RequestParam Map<String, Object> params,UsersEntity user){ EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>(); PageUtils page = usersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params)); return R.ok().put("data", page); } /** * 列表 */ @RequestMapping("/list") public R list( UsersEntity user){ EntityWrapper<UsersEntity> ew = new EntityWrapper<UsersEntity>(); ew.allEq(MPUtil.allEQMapPre( user, "user")); return R.ok().put("data", usersService.selectListView(ew)); } /** * 信息 */ @RequestMapping("/info/{id}") public R info(@PathVariable("id") String id){ UsersEntity user = usersService.selectById(id); return R.ok().put("data", user); } /** * 获取用户的session用户信息 */ @RequestMapping("/session") public R getCurrUser(HttpServletRequest request){ Integer id = (Integer)request.getSession().getAttribute("userId"); UsersEntity user = usersService.selectById(id); return R.ok().put("data", user); } /** * 保存 */ @PostMapping("/save") public R save(@RequestBody UsersEntity user){ // ValidatorUtils.validateEntity(user); if(usersService.selectOne(new EntityWrapper<UsersEntity>().eq("username", user.getUsername())) !=null) { return R.error("用户已存在"); } usersService.insert(user); return R.ok(); } /** * 修改 */ @RequestMapping("/update") public R update(@RequestBody UsersEntity user){ // ValidatorUtils.validateEntity(user); usersService.updateById(user);//全部更新 return R.ok(); } /** * 删除 */ @RequestMapping("/delete") public R delete(@RequestBody Long[] ids){ usersService.deleteBatchIds(Arrays.asList(ids)); return R.ok(); } }
package com.controller; import java.io.File; import java.math.BigDecimal; import java.net.URL; import java.text.SimpleDateFormat; import com.alibaba.fastjson.JSONObject; import java.util.*; import org.springframework.beans.BeanUtils; import javax.servlet.http.HttpServletRequest; import org.springframework.web.context.ContextLoader; import javax.servlet.ServletContext; import com.service.TokenService; import com.utils.*; import java.lang.reflect.InvocationTargetException; import com.service.DictionaryService; import org.apache.commons.lang3.StringUtils; import com.annotation.IgnoreAuth; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.entity.*; import com.entity.view.*; import com.service.*; import com.utils.PageUtils; import com.utils.R; import com.alibaba.fastjson.*; /** * 练车记录 * 后端接口 * @author * @email */ @RestController @Controller @RequestMapping("/lianchejilu") public class LianchejiluController { private static final Logger logger = LoggerFactory.getLogger(LianchejiluController.class); private static final String TABLE_NAME = "lianchejilu"; @Autowired private LianchejiluService lianchejiluService; @Autowired private TokenService tokenService; @Autowired private CheliangService cheliangService;//车辆 @Autowired private CheliangWeixiuService cheliangWeixiuService;//车辆维修 @Autowired private DictionaryService dictionaryService;//字典 @Autowired private JiaolianService jiaolianService;//教练 @Autowired private KechengService kechengService;//课程 @Autowired private KechengBaomingService kechengBaomingService;//练车预约 @Autowired private YonghuService yonghuService;//学员 @Autowired private UsersService usersService;//管理员 /** * 后端列表 */ @RequestMapping("/page") public R page(@RequestParam Map<String, Object> params, HttpServletRequest request){ logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); String role = String.valueOf(request.getSession().getAttribute("role")); if(false) return R.error(511,"永不会进入"); else if("学员".equals(role)) params.put("yonghuId",request.getSession().getAttribute("userId")); else if("教练".equals(role)) params.put("jiaolianId",request.getSession().getAttribute("userId")); CommonUtil.checkMap(params); PageUtils page = lianchejiluService.queryPage(params); //字典表数据转换 List<LianchejiluView> list =(List<LianchejiluView>)page.getList(); for(LianchejiluView c:list){ //修改对应字典表字段 dictionaryService.dictionaryConvert(c, request); } return R.ok().put("data", page); } /** * 后端详情 */ @RequestMapping("/info/{id}") public R info(@PathVariable("id") Long id, HttpServletRequest request){ logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); LianchejiluEntity lianchejilu = lianchejiluService.selectById(id); if(lianchejilu !=null){ //entity转view LianchejiluView view = new LianchejiluView(); BeanUtils.copyProperties( lianchejilu , view );//把实体数据重构到view中 //级联表 车辆 //级联表 CheliangEntity cheliang = cheliangService.selectById(lianchejilu.getCheliangId()); if(cheliang != null){ BeanUtils.copyProperties( cheliang , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "jiaolianId" , "yonghuId"});//把级联的数据添加到view中,并排除id和创建时间字段,当前表的级联注册表 view.setCheliangId(cheliang.getId()); } //级联表 学员 //级联表 YonghuEntity yonghu = yonghuService.selectById(lianchejilu.getYonghuId()); if(yonghu != null){ BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "jiaolianId" , "yonghuId"});//把级联的数据添加到view中,并排除id和创建时间字段,当前表的级联注册表 view.setYonghuId(yonghu.getId()); } //级联表 教练 //级联表 JiaolianEntity jiaolian = jiaolianService.selectById(lianchejilu.getJiaolianId()); if(jiaolian != null){ BeanUtils.copyProperties( jiaolian , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "jiaolianId" , "yonghuId"});//把级联的数据添加到view中,并排除id和创建时间字段,当前表的级联注册表 view.setJiaolianId(jiaolian.getId()); } //修改对应字典表字段 dictionaryService.dictionaryConvert(view, request); return R.ok().put("data", view); }else { return R.error(511,"查不到数据"); } } /** * 后端保存 */ @RequestMapping("/save") public R save(@RequestBody LianchejiluEntity lianchejilu, HttpServletRequest request){ logger.debug("save方法:,,Controller:{},,lianchejilu:{}",this.getClass().getName(),lianchejilu.toString()); String role = String.valueOf(request.getSession().getAttribute("role")); if(false) return R.error(511,"永远不会进入"); else if("教练".equals(role)) lianchejilu.setJiaolianId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); else if("学员".equals(role)) lianchejilu.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); List<LianchejiluEntity> lianchejiluEntities = lianchejiluService.selectList(new EntityWrapper<LianchejiluEntity>() .eq("yonghu_id", lianchejilu.getYonghuId()) .eq("kemu_types", lianchejilu.getKemuTypes()) ); //添加练车记录时,会根据得分来计算平均分,平均分-30得到通过率(自己可以改算法) if(lianchejiluEntities.size()>0){ BigDecimal zongfen = new BigDecimal(0.0); for(LianchejiluEntity l:lianchejiluEntities){ zongfen=zongfen.add(new BigDecimal(l.getLianchejiluDefen())); } //计算平均分,来测试通过率 BigDecimal pingjunfen = zongfen.divide(new BigDecimal(lianchejiluEntities.size())); if(lianchejiluEntities.size()<10 && pingjunfen.doubleValue()>35){ pingjunfen=pingjunfen.subtract(new BigDecimal(30)); } YonghuEntity yonghuEntity = yonghuService.selectById(lianchejilu.getYonghuId()); if(yonghuEntity != null){ //设置科目2的通过率 if(lianchejilu.getKemuTypes() ==1) yonghuEntity.setErTongguolv(pingjunfen.doubleValue()); //设置科目3的通过率 if(lianchejilu.getKemuTypes() ==2) yonghuEntity.setSanTongguolv(pingjunfen.doubleValue()); yonghuService.updateById(yonghuEntity); } } //根据分类来判断练车结果 if(lianchejilu.getLianchejiluDefen()>90) lianchejilu.setLianchejiluTypes(4); else if(lianchejilu.getLianchejiluDefen()>80) lianchejilu.setLianchejiluTypes(3); else if(lianchejilu.getLianchejiluDefen()>60) lianchejilu.setLianchejiluTypes(2); else lianchejilu.setLianchejiluTypes(1); lianchejilu.setCreateTime(new Date()); lianchejiluService.insert(lianchejilu); return R.ok(); } /** * 后端修改 */ @RequestMapping("/update") public R update(@RequestBody LianchejiluEntity lianchejilu, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { logger.debug("update方法:,,Controller:{},,lianchejilu:{}",this.getClass().getName(),lianchejilu.toString()); LianchejiluEntity oldLianchejiluEntity = lianchejiluService.selectById(lianchejilu.getId());//查询原先数据 String role = String.valueOf(request.getSession().getAttribute("role")); // if(false) // return R.error(511,"永远不会进入"); // else if("教练".equals(role)) // lianchejilu.setJiaolianId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // else if("学员".equals(role)) // lianchejilu.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); //根据分类来判断练车结果 if(lianchejilu.getLianchejiluDefen()>90) lianchejilu.setLianchejiluTypes(4); else if(lianchejilu.getLianchejiluDefen()>80) lianchejilu.setLianchejiluTypes(3); else if(lianchejilu.getLianchejiluDefen()>60) lianchejilu.setLianchejiluTypes(2); else lianchejilu.setLianchejiluTypes(1); lianchejiluService.updateById(lianchejilu);//根据id更新 return R.ok(); } /** * 删除 */ @RequestMapping("/delete") public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); List<LianchejiluEntity> oldLianchejiluList =lianchejiluService.selectBatchIds(Arrays.asList(ids));//要删除的数据 lianchejiluService.deleteBatchIds(Arrays.asList(ids)); return R.ok(); } /** * 批量上传 */ @RequestMapping("/batchInsert") public R save( String fileName, HttpServletRequest request){ logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { List<LianchejiluEntity> lianchejiluList = new ArrayList<>();//上传的东西 Map<String, List<String>> seachFields= new HashMap<>();//要查询的字段 Date date = new Date(); int lastIndexOf = fileName.lastIndexOf("."); if(lastIndexOf == -1){ return R.error(511,"该文件没有后缀"); }else{ String suffix = fileName.substring(lastIndexOf); if(!".xls".equals(suffix)){ return R.error(511,"只支持后缀为xls的excel文件"); }else{ URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName);//获取文件路径 File file = new File(resource.getFile()); if(!file.exists()){ return R.error(511,"找不到上传文件,请联系管理员"); }else{ List<List<String>> dataList = PoiUtil.poiImport(file.getPath());//读取xls文件 dataList.remove(0);//删除第一行,因为第一行是提示 for(List<String> data:dataList){ //循环 LianchejiluEntity lianchejiluEntity = new LianchejiluEntity(); lianchejiluEntity.setYonghuId(Integer.valueOf(data.get(0))); //学员 要改的 lianchejiluEntity.setCheliangId(Integer.valueOf(data.get(0))); //车辆 要改的 lianchejiluEntity.setJiaolianId(Integer.valueOf(data.get(0))); //教练 要改的 lianchejiluEntity.setKemuTypes(Integer.valueOf(data.get(0))); //所属科目 要改的 lianchejiluEntity.setLianchejiluKaishiTime(sdf.parse(data.get(0))); //练车开始时间 要改的 lianchejiluEntity.setLianchejiluShichang(Integer.valueOf(data.get(0))); //练车时长 要改的 lianchejiluEntity.setLianchejiluDefen(Double.parseDouble(data.get(0))); //本次成绩 要改的 lianchejiluEntity.setLianchejiluTypes(Integer.valueOf(data.get(0))); //练车成果 要改的 lianchejiluEntity.setLianchejiluContent("");//详情和图片 lianchejiluEntity.setCreateTime(date);//时间 lianchejiluList.add(lianchejiluEntity); //把要查询是否重复的字段放入map中 } //查询是否重复 lianchejiluService.insertBatch(lianchejiluList); return R.ok(); } } } }catch (Exception e){ e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); } } }
五,相关作品展示
基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目
基于Nodejs、Vue等前端技术开发的前端实战项目
基于微信小程序和安卓APP应用开发的相关作品
基于51单片机等嵌入式物联网开发应用
基于各类算法实现的AI智能应用
基于大数据实现的各类数据管理和推荐系统