Flutter+springboot实现考勤码+gps考勤签到功能

    • 实现步骤和思路:
  • 设计
    • 发布考勤任务
    • 签到考勤
  • 环境准备
    • 后端步骤:
    • 1.教师发布考勤任务接口
    • 2.rabbitmq收到教师发布考勤执行的步骤代码接口
    • 3.考勤过期后,rabbitmq执行的代码
    • 4.websocket推送,以及离线消息缓存,上线取出发送,删除缓存
    • 5.学生考勤接口
    • 前端flutter app
    • 需要用到的插件
    • 2. 发布成功,通过provide更新UI,把考勤记录记入本地换成,并且利用计时器倒计时
    • websocket接收考勤消息推送和处理
    • 1.websocket接收数据
    • 2.websocket处理解析数据
    • 3. 利用NotificationsUtil通知用户,并使用EventBus消息总线将处理好的数据推送到相关的UI界面
    • 4. 要显示跟新的UI界面监听消息总线通道,取出收到的数据写入本地并通过provide刷新UI
    • 效果预览图
  • 总结

本人正在做一个智慧课堂辅助app的毕设作品,刚好有一个功能是考勤签到,正好实现了,分享一下经验。
主要实现有 1.app教师用户发布数字或gps考勤任务,gps考勤可以设置考勤地点和距离范围内有效,并且能设置考勤失效时间。后端将考勤任务通过websocket推送到该课程的所有学生,学生收到后在指定时间地点内输入考勤码完成签到,过期不签到的同学将被系统设置为旷课。利用redis做离线消息缓存七天,离线用户的将消息存储到redis中,用户上线后取出redis离线消息推送。

实现步骤和思路:

后端springboot:
1.教师通过restful风格接口创建考勤任务,生成数据库记录
2. 在该创建考勤接口中使用rabbitmq来执行三个步骤:

1.生成需要签到的学生名单记录到数据库,赋默认状态值-1,表示需要签到;2.将需要考勤的消息通过websocket推送给前端app,3.使用redis把教师创建的考勤任务记入,并设置过期时间为教师设置的有效时间。

3.在创建考勤接口最后一步使用rabbitmq的消息延迟队列去跟新数据库状态为-1(需要考勤)的记录修改为缺勤的状态,并把缺勤的记录通过websocket推送到学生前端。 消息延迟队列时间为考勤有效时间
4. 利用redis做离线消息缓存

前端flutter:
1.教师使用高德地图插件定位获取考勤位置,设置考勤距离和有效时间,通过http请求发送到后端;
3. 成功通过Timer计时器来显示剩余时间,并且使用provide状态管理来保持时间显示;
4. 考勤期间收到完成考勤的学生数据,使用provide插入本地并更新名单记录;
5. 考勤结束收到后端websocket推送的学生缺勤名单,provide更新数据;

学生:1.收到教师发布的考勤任务,前往考勤页面点击考勤,完成考勤更新UI,如果失败,也跟新UI界面

使用到的工具和框架有:

springboot
spring-data-jpa
mysql
redis
rabbitmq
rabbitmq消息延迟队列插件

设计

发布考勤任务

课堂创建者可以发布考勤任务让学生用户在指定的时间内完成考勤。发布的考勤主要分两种方式,第一种是数字考勤,学生只需要在指定的时间内通过考勤码完成考勤任务即可;第二种为GPS考勤,是在第一种考勤的方式上,设置指定考勤的地点范围,只有在指定的地点范围内完成考勤,才算成功,否则系统视为缺勤。该功能主要涉及的工具和技术有Reids非关系型数据库、RabbitMQ消息中间件、消息延时队列、Websocket。服务端具体的设计过程如下:

(1) 客户端通过请求Restful风格接口创建考勤任务,生成数据库记录;

(2) 在该创建考勤任务接口中利用RabbitMQ消息中间件来异步完成三个步骤:

①生成需要签到的学生名单(userId)批量写入到数据库,考勤状态(status)赋默认状态值-1,表示需要完成签到任务;

②将考勤消息通过websocket推送给需要完成考勤任务的所有用户App客户 端;

③把教师用户创建的考勤任务记录写入Redis,并设置过期时间为教师用户指 定的时间(expireTime)。

(3) 利用RabbitMQ的延时队列去修改学生考勤记录状态(status)为-1的记录统一修改为状态为0,表示学生缺勤,未能在指定时间内完成考勤任务,并用Websocket推送缺勤名单给考勤任务创建者;

(4) 需要完成考勤的学生用户在考勤有效时间内完成考勤,数据库学生考勤状态(status)为-1的修改为1,表示出勤, 并用Websocket推送缺勤名单给考勤任务创建者。

Flutter
App客户端Gps考勤使用到高德地图的定位接口,主要分为以下几个步骤:

(1)在Flutter的pubspec.yaml文件中引入高德地图插件:

amap_location_fluttify: 0.8.11+481e45c #高德地图

(2) 到高德地图开放平台(https://lbs.amap.com/)注册开发者,并创建应用;

(3) 在Android的AndroidManifest.xml文件下添加高德地图创建应用生成的Key

(4) 在调用高德地图接口插件前,调用以下代码,初始化接口:

WidgetsFlutterBinding.ensureInitialized();

Await AmapCore.init(‘21f35eb097c0cd048f7668194525ba7a’);

发布考勤任务功能的流程如图。

签到考勤

学生用户在收到教师用户发布的考勤任务后,将收到系统提示的考勤消息。在相应的课堂考勤列表中出现需要完成的考勤记录,如果发布的是数字考勤,通过教师告诉学生的考勤码完成签到,如果是GPS考勤,则需要手机定位后在输入考勤码签到。如果考勤任务时间过期,或者考勤用户的定位地点不在指定地点范围内将直接视为缺勤,无法再签到。具体实现流程如图所示。

环境准备

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>25.1-jre</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>

后端步骤:

1.教师发布考勤任务接口

2.rabbitmq收到教师发布考勤执行的步骤代码接口

3.考勤过期后,rabbitmq执行的代码

4.websocket推送,以及离线消息缓存,上线取出发送,删除缓存


用户上线后,websocket取出redis离线消息推送,并且清除离线缓存的数据
@OnPen接口

5.学生考勤接口

///学生考勤
@RequestMapping(value = "AttendanceStudentCheck", method = {RequestMethod.GET, RequestMethod.POST})
public BaseResult AttendanceStudentCheck(@Valid @RequestBody AttendanceStudentDto attendanceStudentDto,HttpServletRequest request) {String key = RedisKeyUtil.Attendance.getAttendanceExpireKey(attendanceStudentDto.getAttendanceId());Attendance attendance = (Attendance) redisService.get(key);String studentId = (String) request.getAttribute("X-AUTH-ID");if (attendance == null) {//考勤失败,缺勤attendanceStudentService.updateStudentStatus(studentId, attendanceStudentDto, 3, 0);return BaseResult.ok(3);}boolean isSuccess = false;double d = 0;if (attendance.getAttendCode().equals(attendanceStudentDto.getAttendCode())) {if (attendanceStudentDto.getType() == 0) {//数字考勤//考勤成功isSuccess = true;} else {//gpsBigDecimal lat = attendance.getLatitude();BigDecimal lon = attendance.getLongitude();double distance = attendance.getDistance();attendanceStudentDto.getLatitude();attendanceStudentDto.getLongitude();d = DistanceUtil.earthDis(lat.doubleValue(), lon.doubleValue(),attendanceStudentDto.getLatitude().doubleValue(),attendanceStudentDto.getLongitude().doubleValue());System.out.println("distance: " + d);if (d <= distance) {isSuccess = true;}}}if (isSuccess) {AttendanceStudent attendanceStudent =attendanceStudentService.updateStudentStatus(studentId, attendanceStudentDto, 0, d);Map<String, Object> map = new HashMap<>();map.put("method", "teacher/createAttendance");map.put("publisherId", attendance.getPublisherId());try {redisRabbitProvider.websocketSend(attendanceStudent, map);} catch (IOException e) {e.printStackTrace();}return BaseResult.ok(0);} else {return BaseResult.ok(-1);}}

前端flutter app

需要用到的插件

 dio: ^3.0.8provide: ^1.0.2     #状态管理shared_preferences: ^0.5.1flutter_local_notifications: ^1.1.5+1 #permission_handler: ^4.2.0+hotfix.3 #权限库amap_location_fluttify: 0.8.6+356f11c #高德地图flutter_event_bus: ^0.0.2

主要思路
教师通过dio 发送http请求创建考勤任务,
经过封装的发布考勤接口,

2. 发布成功,通过provide更新UI,把考勤记录记入本地换成,并且利用计时器倒计时

自定义的provide+计时器工具类

class TimeExpire{int expire=0;double minutes = 0;int second = 0;}///倒计时器
class ExpireTimerProvide with ChangeNotifier{Map<int, Timer> timerMap = Map();Map<int, TimeExpire>  timeExpire=Map();///void init(){timerMap.clear();timeExpire.clear();}//开始计时方法startCountdownTimer(Duration d, int id) {int counterTime = d.inSeconds;print('进来 ${counterTime}');TimeExpire expireT=TimeExpire();expireT.expire=counterTime;expireT.minutes= counterTime / 60;expireT.second = counterTime % 60;timeExpire.putIfAbsent(id, ()=>expireT);var oneMinuute = Duration(seconds: 1);var callback = (Timer timer) async {// print(timer.tick);if (timeExpire[id].expire < 1) {timerMap[id].cancel();if (timerMap.containsKey(id)) {timerMap.remove(id);}print('remove :${timerMap}');} else {int temp=timeExpire[id].expire;timeExpire[id].expire =temp- 1;timeExpire[id].minutes = temp / 60;timeExpire[id].second = temp % 60;}notifyListeners();};timerMap.putIfAbsent(id, ()=>Timer.periodic(oneMinuute, callback));}}

显示计时UI代码

websocket接收考勤消息推送和处理

1.websocket接收数据

2.websocket处理解析数据

3. 利用NotificationsUtil通知用户,并使用EventBus消息总线将处理好的数据推送到相关的UI界面

推送总线消息

Application.eventBus.publish(要推送的数据);

4. 要显示跟新的UI界面监听消息总线通道,取出收到的数据写入本地并通过provide刷新UI

完整代码已经上传到github项目,做为项目的某部分,项目将继续完善
github:coureapp源码

效果预览图





总结

最终圆满完成考勤功能,推送消息没有问题。本人做后端的,不擅长前端,UI做的太丑了,求手下留情!

智慧课堂app(一)Flutter+springboot 实现考勤码+gps考勤签到功能相关推荐

  1. 智慧农场app定制开发是否需要源码交付

    随着移动互联网的发展,越来越多的人开始使用智慧农场app进行农业生产活动.对于开发者来说,开发一款智慧农场app需要考虑很多因素. 1:智慧农场app定制开发需要源码交付吗 智慧农场app定制开发需要 ...

  2. 职教云计算机网络基础题库,智慧职教云课堂APP计算机组装与维护章节测试答案...

    智慧职教云课堂APP计算机组装与维护章节测试答案 更多相关问题 早餐摄入的能量应占全天总能量的25%,午餐占50%,晚餐占25%.() 边远地区和交通不便地区的企业库存现金可多于5天,但最多不能超过( ...

  3. Flutter智慧城市App

    前言 下面将是我使用Flutter对智慧城市APP的实现过程,尽管过程有点繁琐,但这终究只是我的一片记录学习过程的文章,如果有错误的地方,望在评论区留言,给广大的朋友们指条明路- 要求 任务 1:引导 ...

  4. 搜题计算机组装与维修教程,智慧职教云课堂APP计算机组装与维护(长沙环境保护职业技术学院)答案大全...

    智慧职教云课堂APP计算机组装与维护(长沙环境保护职业技术学院)答案大全 更多相关问题 下列关于实验现象的描写正确的是()A.红磷在氧气中燃烧,产生大量白雾B.硫在空气中燃烧--蓝紫色火焰,生成有 关 ...

  5. 智慧工地无线覆盖重点产品人员定位和移动考勤

    智慧工地无线覆盖重点产品[人员定位]-产品功能 智慧工地无线覆盖重点产品人员定位和移动考勤 智慧工地无线覆盖重点产品:移动考勤 产品简介:移动考勤以移动互联网应用模式,基于综合定位,为建筑施工企业员工 ...

  6. 【互联网+“创新创业大赛”】智慧课堂项目计划书

    文章目录 项目简介 项目背景 课堂教育发展痛点与现状分析 教育硬件设备的普及率有限 教育软件平台标准不一 教学内容制作的水平参差不齐 产品技术和服务 硬件设备 软件应用 智能化服务 市场分析 市场规模 ...

  7. 计算机毕业设计ssm面向智慧课堂的教学过程管理系统evi14系统+程序+源码+lw+远程部署

    计算机毕业设计ssm面向智慧课堂的教学过程管理系统evi14系统+程序+源码+lw+远程部署 计算机毕业设计ssm面向智慧课堂的教学过程管理系统evi14系统+程序+源码+lw+远程部署 本源码技术栈 ...

  8. 【附源码】计算机毕业设计SSM面向智慧课堂的教学过程管理系统

    项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...

  9. 【附源码】Python计算机毕业设计面向智慧课堂的教学过程管理系统

    项目运行 环境配置: Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+Navicat11+Django+nodejs. 项目技术: dj ...

最新文章

  1. 自己实现一个最简单的数据库
  2. DelphiX教程系列 4 - 滚动背景 part 1
  3. angular 动态取到的html片段 在页面的展示
  4. Android Intent基本使用
  5. 网络体系结构(OSI模型和TCP/IP协议 功能)
  6. simplified build configuration
  7. Java多线程学习十七:读锁应该插队吗?什么是读写锁的升降级?
  8. 如何在Timeline中使用Cinemachine?
  9. 拖拽动态生成网页-VvvebJs
  10. 汽车+辐射测试软件,汽车EMC辐射发射的一些所见所闻和思考
  11. swoft使用redis
  12. Atitit 非结构化数据管理法 目录 1. 什么是非结构化数据? 1 2. 对非结构化数据也即对全文数据的搜索主要有两种方法: 2 2.1. 顺序扫描法(Serial Scanning): 2 2
  13. 基于SpringCloud Alibaba实现的论坛
  14. css中引入下载字体的方法
  15. 微信小程序实现图片上传
  16. java从本地下载pdf文件_java下载PDF文件
  17. Stellarium 0.19.0 发布,开源 3D 天象模拟软件
  18. java ckfinder_java 使用ckfinder
  19. Elasticsearch:如何在聚合时选择所需要的 bucket 并进行可视化
  20. Typora常用快捷键(详细)

热门文章

  1. 手掌是人体健康的晴雨表
  2. python抢火车票成功率_用Python抢火车票
  3. 公司发的月饼出虫了~~~~
  4. flutter应用安卓商店合规化处理
  5. 基于java-web的公园景区导游网站系统jsp版本---计算机毕业设计
  6. 【制作多媒体演示文稿软件】Focusky教程 | 六个高效演示文稿综合制作技巧
  7. h710阵列卡支持最大硬盘_DELL服务器RAID磁盘阵列级别迁移 (RLM)(以H710P阵列卡为例)...
  8. 关于使用UIWebView加载HTTPS站点出现NSURLErrorDomain code=-1202
  9. 计算机专业英语+贾任,网络环境下的高职英语教学_网络与高职英语教学的整合_贾泽军...
  10. 电工的恶魔果实-布线-PCB系列教程1-13