项目编号:BS-XX-179
前言:
随着我国计算机与互联网的迅速发展和普及,为解决存在疫情蔓延的高风险社区的管理和统计、“零”接触等诸多问题,开发一款与疫情相关的社区管理系统已是迫在眉睫,通过对周边社区的走访调查与研究发现大多数社区依旧是采用人工的方式进行管理,但人工管理模式在现如今的疫情大背景下就显得格外的“漏洞百出”,而待社区疫情管理系统开发出来之后,会使得社区的管理变得更快、更便捷、更行之有效,由过去的人工管理方式转变为更智能化的计算机方式,由效率低,数据冗余大的纸质统计转变为检索迅速、查找便捷、信息存储量大以及实时化的数据统计,最重要的是解决了“零”接触的问题,避免了社区交叉感染,这些系统所带来的优点,能够极大的提高社区的管理与安全性[1]。
本系统采用B/S架构模式进行设计,使页面更为精致、交互流畅度更高、响应更快等特点,使用Vue、Element-UI及脚手架进行快速开发,后端运用当前最热门的Java语言进行开发,基于SpringCloudAlibaba+MybatisPlus框架实现整体架构,保障系统的高可用、高性能、高并发,对于数据的建立和维护必须满足数据一致性、完整性、原子性等特点,且在考虑成本的条件下选择MySQL作为数据库。而开发工具上前后端使用VSCode、IntelliJ IDEA,实现开发上也能做到前后端分离,避免代码臃肿,数据库上使用DataGrip工具来满足数据可视化。
社区疫情管理平台属于微服务,即每个模块拆分出来作为一个服务,降低代码的冗余度,提供更高的灵活与扩展性,权限上,本系统吸收权限管理的特点,将用户分为三类角色,即居民、门卫、管理员,每个角色都拥有独特的功能模块,登录上实现第三方接口采用短信验证码的方式登录,功能上,管理员可以选择延时与实时两种方式发布健康打卡,允许管理员根据小区的不同需求,自定义打卡信息,在打卡的最后半小时,系统会自动筛选出未打卡的用户通过发送短信的方式提醒,解决用户忘记打卡的问题,用户根据管理员发布的健康打卡上传行程码、健康码、定位信息等等,每次打卡信息都会被统计,管理员可以根据某个时间段及条件检索打卡的详情信息,查看打卡与未打卡用户。允许管理员修改小区及用户信息,管理员可以在用户模块查看、添加、修改用户信息,而楼栋模块通过导入Excel文档初始化整个小区信息,为小区分配具体的用户,解决添加操作所带来的一系列繁琐问题。居民可以在个人中心模块修改信息,也可以在生活模块中购买生活必需品,解决突发隔离所带来的“囤货”不足的情况。
一,项目简介
本系统提供了三个角色:普通用户(居民)、普通用户(门卫)和系统管理员。普通用户可以通过手机验证码的方式登录本系统,可使用系统提供的健康打卡,对管理员定义的打卡问卷信息进行填写,上传健康码、行程码以及定位信息,浏览管理员发布的公告信息,本系统还为用户提供物资购买的功能,用户可以登录系统前台,购买生活用品,修改个人信息,发起进出入申请等等。
(1)普通用户(居民)功能
该系统的居民功能模块图如图3-1所示。
图3-1居民功能模块图
(2)普通用户(门卫)功能
该系统的保安功能模块图如图3-2所示。
图3-2保安功能模块图
(3)系统管理员功能
系统管理员可以在数据面板中查看注册的用户、及当天当卡、未打卡的用户总数;对用户的基本信息进行管理,可以查看用户的详细信息,提供条件查询,管理员可以根据用户名、手机号、邮箱及时间区间等条件检索用户;也能添加、删除、修改用户,初始化社区信息,根据系统提供的模板,将社区名、社区单元及每单元房号汇总成EXCEL文件,导入上传至项目,初始化社区的基本信息,分配和移除用户;管理员可以编写打卡问卷,发布签到,选择小区及打卡时间段,系统会发送手机短息给位于当前社区的所有居民,通知居民进行打卡。
该系统的管理员功能模块图如图3-3所示。
图3-3管理员功能模块图
未登录的用户仅只能浏览本网站的商品信息模块,其他功能必须登录后才能使用,如:购买商品的下单功能,健康打卡功能,发起进出入申请,修改个人信息,用例图如图3-4所示。
图3-4 居民功能用例图
保安可以使用如下功能:查看所在社区公告,修改及查看个人信息,登记及检索进出入人员信息,用例图如图3-5所示。
图3-5 保安功能用例图
管理员通过账号密码登录本系统,管理员可以使用如下功能:查看数据面板、用户管理、社区管理、公告管理、问卷管理、健康打卡管理、商品管理、商品分类管理、进出入管理、订单管理等。管理员功能用例图如图3-6所示。
图3-6 管理员用例图
二,环境介绍
语言环境:Java: jdk1.8
数据库:Mysql: mysql5.7
应用服务器:Tomcat: tomcat8.5.31
开发工具:IDEA或eclipse
后台开发技术:SpringCloudAlibaba+Springboot+Mybatis-plus+网关
前以开发技:Vue+ElementUI
三,系统展示
登录模块
公告管理模块
健康打卡模块
社区管理模块
用户管理模块
进出入管理模块
商品管理模块
问卷管理模块
居民打卡模块
四,核心代码展示
package com.baobaokai.epidemic.core.controller; import com.baobaokai.epidemic.common.OssModuleEnum; import com.baobaokai.epidemic.core.client.IOssService; import com.baobaokai.epidemic.exception.BusinessException; import com.baobaokai.epidemic.result.R; import com.baobaokai.epidemic.result.ResponseEnum; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @RestController @RequestMapping(path = "/api/core/file") public class FileController { @Resource private IOssService ossService; @PostMapping(path = "/uploadHeadImg") public R uploadHeadImg(@RequestParam(name = "file") MultipartFile file) { if (file.isEmpty()) { throw new BusinessException(ResponseEnum.FILE_NULL_ERROR); } //调用上传图片模块 R r = ossService.uploadImg(file, OssModuleEnum.USER_AVATAR.getModuleName()); return R.ok().data("data", r.getData().get("data")); } @PostMapping(path = "/uploadCommodityImg") public R uploadCommodityImg(@RequestParam(name = "file") MultipartFile file) { if (file.isEmpty()) { throw new BusinessException(ResponseEnum.FILE_NULL_ERROR); } //调用上传图片模块 R r = ossService.uploadImg(file, OssModuleEnum.COMMODITY_IMG.getModuleName()); return R.ok().data("data", r.getData().get("data")); } @PostMapping(path = "/upload") public R upload(@RequestParam(name = "file") MultipartFile file,@RequestParam(name = "moduleName")String moduleName) { if (file.isEmpty()) { throw new BusinessException(ResponseEnum.FILE_NULL_ERROR); } //调用上传图片模块 R r = ossService.uploadImg(file, moduleName); return R.ok().data("data", r.getData().get("data")); } }
package com.baobaokai.epidemic.core.controller.admin; import com.baobaokai.epidemic.core.entity.dto.SignTimeDTO; import com.baobaokai.epidemic.core.entity.vo.SignTimeVO; import com.baobaokai.epidemic.core.service.ISignTimeService; import com.baobaokai.epidemic.result.R; import com.github.pagehelper.PageInfo; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Map; /** * 发布签到 */ @RestController @RequestMapping(path = "/admin/core/signtime") public class AdminSignTimeController { @Autowired private ISignTimeService signTimeService; /** * 分页查询 * @return */ @ApiOperation("分页查询") @PostMapping(path = "/pageListForConditions") public R pageListForConditions(@RequestParam(name = "page",defaultValue = "1")Integer page, @RequestParam(name = "limit",defaultValue = "10")Integer limit,@RequestBody(required = false)Map<String,Object> conditions){ PageInfo<SignTimeVO> info = signTimeService.pageListForConditions(page,limit,conditions); return R.ok().data("data",info); } @ApiOperation("添加打卡时间") @PostMapping(path = "/insertSignTime") public R insertSignTime(@RequestBody SignTimeDTO signTimeDTO){ int result = signTimeService.insertTime(signTimeDTO); if (result != 0){ return R.ok().message("发布成功!"); } return R.error().message("发布失败!"); } @ApiOperation("修改打卡消息状态") @PutMapping(path = "/updateStatusById") public R updateCancelStatus(@RequestParam("id")Long id){ int result = signTimeService.updateCancelStatus(id); if (result != 0 ){ return R.ok().message("操作成功!"); } return R.ok().message("操作失败!"); } @ApiOperation("根据ID删除打卡") @DeleteMapping(path = "/deleteById/{id}") public R deleteById(@PathVariable("id")Long id){ int result = signTimeService.deleteById(id); if (result > 0 ) { return R.ok().message("撤销成功!"); } return R.error().message("撤销失败!"); } }
package com.baobaokai.epidemic.core.controller.admin; import cn.hutool.core.util.StrUtil; import com.baobaokai.epidemic.core.entity.dto.ResidentBuildingDTO; import com.baobaokai.epidemic.core.entity.vo.ResidentBuildingVO; import com.baobaokai.epidemic.core.entity.vo.UserVO; import com.baobaokai.epidemic.core.service.IResidentBuildingService; import com.baobaokai.epidemic.exception.BusinessException; import com.baobaokai.epidemic.result.R; import com.baobaokai.epidemic.result.ResponseEnum; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; /** * <p> * 前端控制器 * </p> * */ @RestController @RequestMapping("/admin/core/residentBuilding") public class AdminResidentBuildingController { @Autowired private IResidentBuildingService residentBuildingService; /** * 未分配房间 * @return */ @PostMapping(path = "/selectUnDistribution") public R selectUnDistribution(@RequestParam(name = "page",defaultValue = "1")Integer page, @RequestParam(name = "limit",defaultValue = "5")Integer limit, @RequestBody(required = false)Map<String,Object> conditions){ PageInfo<UserVO> info = residentBuildingService.selectUnDistribution(page,limit,conditions); return R.ok().data("data",info); } /** * 根据房间ID查询房间中的所有居民 * @return */ @GetMapping(path = "/selectResidentByBuildingId") public R selectResidentByBuildingId(@RequestParam(name = "buildingId") Integer buildingId) { List<ResidentBuildingVO> residentBuildingVoList = residentBuildingService.selectResidentByBuildingId(buildingId); return R.ok().data("data", residentBuildingVoList); } /** * 根据房间号查询房间所在居民 * @return */ @GetMapping(path = "/selectResidentByBuildingName") public R selectResidentByBuildingName(@RequestParam(name = "buildingName")String buildingName){ List<ResidentBuildingVO> residentBuildingVos = residentBuildingService.selectResidentByBuildingName(buildingName); return R.ok().data("data",residentBuildingVos); } /** * 根据用户ID删除所在记录 * * @return */ @DeleteMapping(path = "/deleteByUserAndBuildingId/{userId}/{buildingId}") public R deleteByUserId(@PathVariable("userId") String userId,@PathVariable("buildingId")Integer buildingId) { if (StrUtil.isEmpty(userId) || buildingId == null) { throw new BusinessException(ResponseEnum.REQUEST_DATA_ERROR); } residentBuildingService.deleteByUserId(userId,buildingId); return R.ok(); } /** * 添加记录 * * @return */ @PostMapping(path = "/insertResidentBuilding") public R insertResidentBuilding(@RequestBody ResidentBuildingDTO residentBuildingDto) { int result = residentBuildingService.insertResidentBuilding(residentBuildingDto); if (result != 0) { return R.ok().message("添加成功!"); } return R.error().message("添加失败!"); } }
package com.baobaokai.epidemic.core.controller.admin; import com.baobaokai.epidemic.core.entity.dto.QuestionnaireDTO; import com.baobaokai.epidemic.core.entity.vo.QuestionnaireVO; import com.baobaokai.epidemic.core.service.IQuestionnaireService; import com.baobaokai.epidemic.result.R; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @Api(tags = "管理员问卷管理") @RestController @RequestMapping(path = "/admin/core/questionnaire") public class AdminQuestionnaireController { @Autowired private IQuestionnaireService questionnaireService; @ApiOperation("分页查询问卷") @PostMapping(path = "/pageListForConditions") public R pageListForConditions(@RequestParam(name = "page", defaultValue = "1") Integer page, @RequestParam(name = "limit", defaultValue = "10") Integer limit, @RequestBody(required = false) Map<String, Object> conditions) { PageInfo<QuestionnaireVO> info = questionnaireService.pageListForConditions(page, limit, conditions); return R.ok().data("data", info); } @ApiOperation("查询所有问卷") @GetMapping(path = "/listAllQuestionnaire") public R listAllQuestionnaire(){ List<QuestionnaireVO> data = questionnaireService.listAllQuestionnaire(); return R.ok().data("data",data); } @ApiOperation("通过ID获取子节点") @GetMapping(path = "/selectChildrenById") public R selectChildrenById(@RequestParam(name = "id") Integer id) { List<QuestionnaireVO> questionnaireVOList = questionnaireService.selectChildrenById(id); return R.ok().data("data", questionnaireVOList); } @ApiOperation("新增问卷题目") @PostMapping(path = "/insertQuestionnaire") public R insertQuestionnaire(@RequestBody QuestionnaireDTO questionnaireDTO) { int result = questionnaireService.insertQuestionnaire(questionnaireDTO); if (result != 0) { return R.ok().data("data", result).message("添加成功!"); } return R.error().message("添加失败!"); } @ApiOperation("根据ID查询") @GetMapping(path = "/selectById") public R selectById(@RequestParam(name = "id") Integer id) { QuestionnaireVO questionnaireVO = questionnaireService.selectById(id); return R.ok().data("data", questionnaireVO); } @ApiOperation("根据ID修改") @PutMapping(path = "/updateById") public R updateById(@RequestBody QuestionnaireDTO questionnaireDTO) { int result = questionnaireService.updateById(questionnaireDTO); if (result != 0) { return R.ok().message("修改成功!"); } return R.error().message("修改失败!"); } @ApiOperation("根据ID删除") @DeleteMapping(path = "/deleteById/{id}") public R deleteById(@PathVariable("id") Integer id) { questionnaireService.deleteById(id); return R.ok().message("删除成功!"); } @ApiOperation("修改题目展示状态") @PutMapping(path = "/updateShowStatus") public R updateShowStatus(@RequestParam(name = "id") Integer id) { int i = questionnaireService.updateShowStatus(id); if (i > 0) { return R.ok().message("操作成功!"); } return R.error().message("操作失败!"); } }
五,项目总结
本课题以下几点对本系统的研究内容进行论述:
- 健康打卡
该模块为系统的核心模块,管理员只需要根据业主的行程码、健康码及打卡位置便能迅速的获取用户的健康信息与行踪轨迹,并通过条件对打卡信息进行检索。
- 增值功能
增值功能是研究本系统该有哪些增值功能,能更好的为居家隔离的业主提供更便捷的服务。
- 其他功能
研究疫情下可能带来的其他问题,从而根据核心功能模块衍生出其他功能,一、进出入模块,即疫情防控下严格审核人员进出入,防止不明外来人员随意进出社区,增加疫情风险;二、公告模块:及时了解社区的最新动态。
本系统意义是结合现如今疫情的大背景下进行研究来完成社区疫情管理平台的设计与实现。摒弃了传统的人工走访排查,充分利用互联网技术的优势,为社区实现优质高效的管理工作提供信息化技术支持,解决在面临疫情突发的场景下,能更好更快的采取行之有效的方式进行管控与信息采集;解决居民在家隔离期间所带来生活上的困扰等问题;解决社区管控期间对外来及人员进出等问题。