✨作者主页:IT研究室✨
个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。
☑文末获取源码☑
精彩专栏推荐⬇⬇⬇
Java项目
Python项目
安卓项目
微信小程序项目
一、前言
随着经济的发展和城市化进程的加快,越来越多的家庭拥有车辆,而城市内的停车位也因此变得紧张。在这种情况下,智能停车计费系统应运而生。该系统利用物联网技术,对停车场的停车位进行实时监控,对车辆的进出进行自动化管理,以此提高停车效率,减少人力成本,同时为车主提供方便、快捷的停车服务。
然而,尽管智能停车计费系统在一定程度上解决了城市停车难的问题,但在实际应用中仍然存在一些问题。例如,现有的系统通常只关注车辆的进出管理,而忽视了车位信息的实时更新和停车行为的监管,这可能导致车主在寻找停车位时浪费时间和精力。另外,系统的自动化管理也可能导致一些违规行为无法及时发现和处理。因此,为了更好地解决这些问题,我们提出了一个更加完善的智能停车计费系统。
当前,很多停车场都采用了智能停车计费系统,但这些系统普遍存在一些问题。首先,它们无法实时更新车位信息,导致车主在寻找停车位时浪费时间和精力。其次,这些系统对车辆的进出管理虽然实现了自动化,但缺乏对停车行为的监管,容易滋生违规行为。此外,现有的系统通常只提供基础的论坛交流和公告功能,而缺乏对用户投诉建议的及时响应和处理,无法满足用户的需求。因此,我们需要一个更加完善、更加智能的停车计费系统来解决这些问题。
本课题的研究目的是开发一个更加完善的智能停车计费系统,该系统能够实时更新车位信息,对车辆的进出和停车行为进行全面监管,同时提供更加丰富、实用的服务功能,如论坛交流、公告、投诉建议处理等。通过实现这些功能,我们的研究旨在提高停车效率、减少人力成本、方便车主停车的同时,也能够提高停车场的管理效率和质量。
智能停车计费系统的研究对于解决城市停车难的问题具有重要意义。首先,该系统能够实时监控车位信息,帮助车主快速找到合适的停车位,节省时间和精力。其次,系统的自动化管理能够提高停车场的运行效率和管理质量,减少人力成本。此外,通过对停车行为的监管和对违规行为的及时处理,能够维护停车场的秩序和安全。最后,系统的投诉建议处理和论坛交流功能能够提高用户满意度和参与度,促进停车场与用户之间的互动和沟通。因此,智能停车计费系统的研究对于提高城市交通效率、改善城市环境、提升用户体验等方面都具有重要的意义。
二、开发环境
- 开发语言:Java
- 数据库:MySQL
- 系统架构:B/S
- 后端:SpringBoot
- 前端:Vue
三、系统功能模块
- 角色:用户、管理员
- 功能:
用户:
车位信息、论坛交流、公告、投诉建议、在线交流、车辆进场管理、车辆离场管理 、违规处罚管理;
管理员:
用户管理、车位分类管理、车位信息管理、车辆进场管理、车辆离场管理 、违规处罚管理、投诉建议管理、论坛管理、在线交流、公告管理。
四、系统界面展示
- 智能停车计费系统-界面展示:
五、部分代码设计
- Java项目实战-代码参考:
/**
* 判断用户是否还有未完成订单
* @return 用户未完成的预约订单VO 或 null
*/
@GetMapping("getLastAppointmentOrder")
@ApiOperation(value = "获取未完成订单",notes = "获取用户未完成的预约或续约订单")
private Result getLastAppointmentOrder(){
ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
Long uid = activeUser.getUid();
//从redis获取用户最后一条预约订单或续约订单
AppointmentOrder lastOrder = null;
AppointmentOrder appointmentOrder = (AppointmentOrder) redisTemplate.opsForValue().get("last_appOrder_uid:" + uid);
AppointmentOrder renewalOrder = (AppointmentOrder) redisTemplate.opsForValue().get("last_renOrder_uid:" + uid);
//如果续约不是空 就用续约 是空 就用预约 如果预约不是空 就用预约 是空 就查数据库(应该不用查数据库)
if (renewalOrder != null){
lastOrder = renewalOrder;
}else if (appointmentOrder != null){
lastOrder = appointmentOrder;
}
//如果lastOrder为null 返回null
if (lastOrder == null){
return Result.ok("没有未完成订单",null);
}
//验证订单是否在预约时间内
if (!DelayQueueUtil.isSave(lastOrder.getAoOrderNum())){
return Result.ok("没有未完成订单",null);
}
//返回预约订单信息VO
AppointmentOrderVO appointmentOrderVO = new AppointmentOrderVO();
BeanUtils.copyProperties(lastOrder,appointmentOrderVO);
return Result.ok("查询成功",appointmentOrderVO);
}
/**
* 获取停车场信息VO
* @param pid 停车场id
* @return 停车场信息VO
*/
@GetMapping("getParkLotInfo")
@ApiOperation(value = "获取停车场信息",notes = "获取用户选择的停车场信息")
private Result getParkLotInfo(Long pid) {
ParkLotVO parkLotVO = new ParkLotVO();
ParkLot parkLot = getParkingLotInfo(pid);
if (parkLot == null){
return Result.error("停车场信息错误");
}
//返回停车场信息VO
BeanUtils.copyProperties(parkLot,parkLotVO);
return Result.ok("查询成功", parkLotVO);
}
/**
* 获取停车场信息
* @param pid 停车场id
* @return 停车场信息
*/
private ParkLot getParkingLotInfo(Long pid) {
ParkLot parkLot = appointmentService.selectParkLotInfoByPid(pid);
//如果为null 返回null
if (parkLot == null) {
return null;
}
//更新redis中停车场空闲车位数量 此处为实时更新
redisTemplate.opsForValue().set("free_parkSpace_pid:" + pid, parkLot.getMaxSpace() - parkLot.getNowSpace());
return parkLot;
}
/**
* 获取用户的默认车牌号
* @return 默认车牌号
*/
@GetMapping("getCarNumber")
@ApiOperation(value = "获取默认车牌",notes = "获取用户默认车牌号,没有就需要输入")
private Result getCarNumber(){
ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
Long uid = activeUser.getUid();
//从redis获取用户的默认车牌号
Licenseplate licensePlate = (Licenseplate) redisTemplate.opsForValue().get("default_license_uid:" + uid);
//如果为null 从数据库获取
if (licensePlate == null){
licensePlate = appointmentService.selectCarNumberByUid(uid);
}
//如果为null 返回null
if (licensePlate == null){
return Result.ok("没有绑定车牌",null);
}
//如果有数据 放进redis
redisTemplate.opsForValue().set("default_license_uid:" + uid,licensePlate,5, TimeUnit.MINUTES);
//返回默认车牌号
return Result.ok("查询成功",licensePlate.getCarNum());
}
/**
* 用户确认下订单(停车场预约)
* @param appointmentDTO 预约信息DTO
* @return 预约订单确认信息VO
*/
@PostMapping("sureAppointmentOrder")
@ApiOperation(value = "确认下预约订单",notes = "生成预约订单存入数据,返回订单信息")
private Result sureAppointmentOrder(@RequestBody AppointmentDTO appointmentDTO){
ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
AppointmentOrder appointmentOrder = null;
//获取用户信誉分
Integer creditPoint = appointmentService.selectCreditPointByUid(activeUser.getUid());
//查询停车场信息 更新free_parkSpace
ParkLot parkingLotInfo = getParkingLotInfo(appointmentDTO.getPid());
//创建预约订单
try {
appointmentOrder = createAppointmentOrder(appointmentDTO,creditPoint);
} catch (RuntimeException e){
log.info("RuntimeException 错误信息{}",e.getMessage());
return Result.error(e.getMessage());
} catch (Exception e){
//将保持信息放到日志中
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(byteArrayOS));
String exception = byteArrayOS.toString();
log.info("Exception 错误信息{}",exception);
return Result.error(e.getMessage()+"请通知管理员");
}
//预约订单放进数据库
boolean isSuccess = appointmentService.insertAppointmentOrder(appointmentOrder);
//插入成功 返回预约订单确认信息VO 插入失败 提示重新操作 其实可以程序内部再次插入
if (!isSuccess){
return Result.error("预约失败,请重新操作");
}
//预约成功放进redis 预约支付时间为5分钟
redisTemplate.opsForValue().set("last_appOrder_uid:" + activeUser.getUid(), appointmentOrder, 5, TimeUnit.MINUTES);
//放入队列中
DelayQueueUtil.inputOrder(appointmentOrder.getAoOrderNum(),5);
//返回预约订单确认信息VO
AppointmentOrderVO appointmentOrderVO = new AppointmentOrderVO();
BeanUtils.copyProperties(appointmentOrder,appointmentOrderVO);
appointmentOrderVO.setCreditPoint(creditPoint);
return Result.ok("预约订单生成成功",appointmentOrderVO);
}
/**
* 生成停车场预约订单
* @param appointmentDTO 预约信息DTO
* @return 预约订单
*/
private AppointmentOrder createAppointmentOrder(AppointmentDTO appointmentDTO, Integer creditPoint){
ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
Integer appointmentDuration = appointmentDTO.getAppointmentDuration();
//判断信誉分给出金额系数 如果信誉分过低就禁止预约 之后还需要提醒用户
double coefficient_money = 0.3;
if (creditPoint < 60){
throw new RuntimeException("信誉分过低,禁止预约");
}else if (creditPoint < 80){
coefficient_money = 0.4;
}
//修改停车场现在占用数量 修改失败抛出异常 修改redis中的数据 redis中线程安全 需求每天定时往redis中更新数据
updateFreeParkSpace(appointmentDTO.getPid(),-1);
//获取停车场停车单价
ParkLot parkLot = getParkingLotInfo(appointmentDTO.getPid());
if (parkLot == null){
throw new RuntimeException("停车场信息错误,请通知管理员");
}
BigDecimal parkPrice = parkLot.getParkPrice();
//获取时长系数
double coefficient_time = 1;
if (appointmentDuration == 30){
coefficient_time = 0.5;
}
//计算金额 时长*单价*系数
BigDecimal money = parkPrice.multiply(BigDecimal.valueOf(coefficient_money)).multiply(BigDecimal.valueOf(coefficient_time));
//计算时间
Date startTime = new Date();
Date endTime = new Date(startTime.getTime() + appointmentDuration * 60 * 1000);
//创建要返回的订单
String orderNum = SnowFlake.getOrderNum();
AppointmentOrder appointmentOrder = new AppointmentOrder();
appointmentOrder.setUid(activeUser.getUid());
appointmentOrder.setPid(appointmentDTO.getPid());
appointmentOrder.setCarNum(appointmentDTO.getCarNum());
appointmentOrder.setAoOrderNum(orderNum);
appointmentOrder.setMoney(money);
appointmentOrder.setAppointmentTime(startTime);
appointmentOrder.setAppointmentDuration(appointmentDuration);
appointmentOrder.setEndTime(endTime);
appointmentOrder.setState((byte) 0);//数据库有默认信息
return appointmentOrder;
}
/**
* 修改停车场剩余停车位
* @param pid 停车场id
* @param num 修改数量
*/
private void updateFreeParkSpace(Long pid, Integer num){
Integer freeParkingSpace = (Integer) redisTemplate.opsForValue().get("free_parkSpace_pid:" + pid);
if (freeParkingSpace == null || freeParkingSpace < 0){
throw new RuntimeException("停车场信息错误,请通知管理员");
}
//防止加数量的时候抛异常
if (freeParkingSpace + num <= -1){
throw new RuntimeException("车位暂无");
}
//停车场还有空位 操作空位数量
redisTemplate.opsForValue().set("free_parkSpace_pid:" + pid,freeParkingSpace + num);
//修改数据库 做到同步
boolean isSuccess = appointmentService.updateNowSpaceByPid(pid, num);
if (!isSuccess){
throw new RuntimeException("同步数据错误");
}
}
/**
* 主动取消订单 支付成功后不支持取消
* @param orderNum 订单号
* @return 是否取消成功
*/
@GetMapping("cancelAppointmentOrder")
@ApiOperation(value = "取消订单",notes = "订单生成5分钟内未支付,可以主动取消订单,五分钟后自动取消")
private Result cancelAppointmentOrder(String orderNum){
if (timeoutHandler(orderNum)){
if (DelayQueueUtil.outputOrder(orderNum)){
return Result.ok("取消成功");
}
}
return Result.error("取消失败");
}
/**
* 超时处理
* @param orderNum 订单号
* @return 处理结果
*/
public boolean timeoutHandler(String orderNum) {
//获取要取消的订单信息
AppointmentOrder appointmentOrder = appointmentService.selectAppointmentOrderByOrderNum(orderNum);
if (appointmentOrder == null) {
return false;
}
//从redis中去掉
if (appointmentOrder.getRenewalDuration() != null){
redisTemplate.delete("last_renOrder_uid:" + appointmentOrder.getUid());
}else {
redisTemplate.delete("last_appOrder_uid:" + appointmentOrder.getUid());
}
if (appointmentOrder.getState() == 0){
//订单超时 自动取消 修改订单状态为2 预约订单才恢复停车场空闲车位数量
try {
if (appointmentOrder.getAppointmentDuration() != null){
updateFreeParkSpace(appointmentOrder.getPid(),1);
}
} catch (RuntimeException e){
log.info("RuntimeException 错误信息{}",e.getMessage());
return false;
} catch (Exception e){
//将保持信息放到日志中
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(byteArrayOS));
String exception = byteArrayOS.toString();
log.info("Exception 错误信息{}",exception);
return false;
}
return appointmentService.updateAppointmentOrder(appointmentOrder.getAoid(),(byte) 2);
}else if (appointmentOrder.getState() == 1){
//订单超时 扣除信誉分
return appointmentService.updateCreditPointByUid(appointmentOrder.getUid(),-10);
}
return false;
}
/**
* 支付成功后的变动
* @param payStatusDTO 支付回调
* @return
*/
@PostMapping("callBack")
@ApiOperation(value = "支付回调接口",notes = "回调支付状态,更新数据信息,返回更新结果")
private Result callBack(@RequestBody PayStatusDTO payStatusDTO){
if ("支付成功".equals(payStatusDTO.getState())){
//获取订单信息
AppointmentOrder appointmentOrder = appointmentService.selectAppointmentOrderByOrderNum(payStatusDTO.getOrderNum());
if (appointmentOrder != null){
boolean b = appointmentService.updateAppointmentOrder(appointmentOrder.getAoid(), (byte) 1);
if (b){
//从队列中取出订单信息 重新存入
DelayQueueUtil.outputOrder(payStatusDTO.getOrderNum());
if (appointmentOrder.getRenewalDuration() != null){
DelayQueueUtil.inputOrder(payStatusDTO.getOrderNum(),appointmentOrder.getRenewalDuration());
appointmentOrder.setState((byte) 1);//因为改了数据库没有再查询 所以就直接给赋值了
redisTemplate.opsForValue().set("last_renOrder_uid:" + appointmentOrder.getUid(), appointmentOrder, appointmentOrder.getRenewalDuration(), TimeUnit.MINUTES);
//把预约订单的redis和队列都取出
AppointmentOrder o = (AppointmentOrder) redisTemplate.opsForValue().get("last_appOrder_uid:" + appointmentOrder.getUid());
if (o == null){
//throw new RuntimeException("应该不会有问题 要是抛这个异常 redis有问题");
return Result.error("redis服务器错误");
}
DelayQueueUtil.outputOrder(o.getAoOrderNum());
redisTemplate.delete("last_appOrder_uid:" + appointmentOrder.getUid());
}else {
DelayQueueUtil.inputOrder(payStatusDTO.getOrderNum(),appointmentOrder.getAppointmentDuration());
appointmentOrder.setState((byte) 1);//因为改了数据库没有再查询 所以就直接给赋值了
redisTemplate.opsForValue().set("last_appOrder_uid:" + appointmentOrder.getUid(), appointmentOrder, appointmentOrder.getAppointmentDuration(), TimeUnit.MINUTES);
}
return Result.ok("状态变更成功");
}
}
}
return Result.error("状态变更失败");
}
/**
* 续约
* @return 续约订单信息
*/
@GetMapping("sureRenewalOrder")
@ApiOperation(value = "确认下续约订单",notes = "生成续约订单存入数据,返回订单信息")
private Result sureRenewalOrder(){
ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
Long uid = activeUser.getUid();
//从redis获取用户最后一条预约订单
AppointmentOrder appointmentOrder = (AppointmentOrder) redisTemplate.opsForValue().get("last_appOrder_uid:" + uid);
//如果为null 从数据库获取最后一条订单
if (appointmentOrder == null){
appointmentOrder = appointmentService.getLastAppointmentOrderByUid(activeUser.getUid());
}
//如果为null 返回null
if (appointmentOrder == null || !DelayQueueUtil.isSave(appointmentOrder.getAoOrderNum())){
return Result.error("没有预约信息");
}
//验证订单是否在预约时间内
boolean save = DelayQueueUtil.isSave(appointmentOrder.getAoOrderNum());
//判断能否续约
if (!save || appointmentOrder.getRenewalDuration() != null || appointmentOrder.getState() != 1){
return Result.error("不能重复续约");
}
//能续约 续30分钟
AppointmentOrder renewalOrder = createRenewalOrder(appointmentOrder);
//预约订单放进数据库
boolean isSuccess = appointmentService.insertAppointmentOrder(renewalOrder);
//插入成功 返回预约订单确认信息VO 插入失败 提示重新操作 其实可以程序内部再次插入
if (!isSuccess){
return Result.error("续约失败");
}
//redis存入续约单
redisTemplate.opsForValue().set("last_renOrder_uid:" + renewalOrder.getUid(), renewalOrder, 5, TimeUnit.MINUTES);
//放入队列中
DelayQueueUtil.inputOrder(renewalOrder.getAoOrderNum(),5);
//返回预约订单确认信息VO
AppointmentOrderVO appointmentOrderVO = new AppointmentOrderVO();
BeanUtils.copyProperties(renewalOrder,appointmentOrderVO);
return Result.ok("续约订单生成成功",appointmentOrderVO);
}
/**
* 生成续约订单
* @param appointmentOrder 预约订单
* @return 续约订单
*/
private AppointmentOrder createRenewalOrder(AppointmentOrder appointmentOrder){
//计算时间
Date startTime = new Date();
Date endTime = new Date(startTime.getTime() + 30 * 60 * 1000);
//计算价格
BigDecimal money = appointmentOrder.getMoney();
if (appointmentOrder.getAppointmentDuration() == 60){
money = appointmentOrder.getMoney().divide(BigDecimal.valueOf(2),2, RoundingMode.UNNECESSARY);
}
//创建要返回的订单
String orderNum = SnowFlake.getOrderNum();
AppointmentOrder renewalOrder = new AppointmentOrder();
renewalOrder.setUid(appointmentOrder.getUid());
renewalOrder.setPid(appointmentOrder.getPid());
renewalOrder.setCarNum(appointmentOrder.getCarNum());
renewalOrder.setAoOrderNum(orderNum);
renewalOrder.setMoney(money);
renewalOrder.setRenewalTime(startTime);
renewalOrder.setRenewalDuration(30);
renewalOrder.setEndTime(endTime);
renewalOrder.setState((byte) 0);//数据库有默认信息
return renewalOrder;
}
/*//测试专用方法
@GetMapping("selectQueue")
private void selectQueue(){
System.out.println(DelayQueueUtil.selectQueue());
}
@GetMapping("test")
private void test() throws InterruptedException {
DelayQueueUtil.inputOrder("123",2);
Thread.sleep(2000);
boolean b = DelayQueueUtil.outputOrder("123");
System.out.println(b);
}
六、论文参考
- 计算机毕业设计选题推荐-智能停车计费系统-论文参考:
七、系统视频
智能停车计费系统-项目视频:
基于SpringBoot的智能停车计费系统
结语
计算机毕业设计选题推荐-智能停车计费系统-Java项目实战
大家可以帮忙点赞、收藏、关注、评论啦~
源码获取:私信我