项目编号:BS-GX-057
前言:
新媒体时代“移动”已经成为很多人的生活习惯和生活方式,而新的移动媒体使传播进入了一个新的阶段。大学生作为最容易接受新鲜事物的代表群体,数字技术、无线技术、网络技术高度集中的移动设备已经成为他们不可或缺的工具,如手机、平板、笔记本电脑等这些移动媒介和设备对大学生的生活方式产生了深刻的影响[1]。作为当代大学生中的一员,更能了解当代大学生在大学生活方面的所想所需,并对大学生的生活现状做了深刻的剖析,来以此开发出符合当代大学生的生活方式的校园互助平台,该项目围绕PC端进行开发,为大学生提供更加适合且便捷的大学校园生活。
本平台采用B/S架构模式进行设计,为提高前端页面精致、交互流畅高、响应快等特点,使用Vue、Element-UI及脚手架进行快速开发,后端运用当前最热门的Java语言进行开发,基于Springboot框架实现整体架构,保障系统的高可用、高性能、高并发,对于数据的建立和维护必须满足数据一致性、完整性、原子性等特点,且在考虑成本的条件下选择MySQL作为数据库。而开发工具上前后端使用VSCode、IntelliJ IDEA,实现开发上也能做到前后端分离,避免代码臃肿,数据库上使用DataGrip工具来满足数据可视化。
平台主要分为前台用户界面和后台管理员界面。前台面向的用户为当代大学生,根据大学生的大学生活方式进行设计并开发功能,共有七个模块;后台是管理端,由管理员对用户们在该平台留下的信息进行管理,共有八个模块。本文主要从开发该平台的目的,系统分析、系统设计、系统实现几个方面进行论述。
一,项目简介
校园互助平台分为前台与后台。
前台主要面向的用户是在校大学生,分为七个模块,分别为搜索模块、学习交流模快、生活分享模块、校园活动模块、失物招领模块、通知模块与个人中心模块。
搜索模块包括的功能有,搜索内容;学习交流模块包括的功能有,浏览文章内容、发布文章内容、修改文章内容、删除文章;生活分享模块包括的功能有,浏览分享内容、发布分享内容、修改分享内容、删除分享内容;校园活动模块包括的功能有,查看活动内容、发布活动、修改活动内容、删除活动;失物招领模块包括的功能有,查看发布的物品信息、发布丢失或捡到的物品信息、修改发布的信息、删除发布的信息,搜索、物品状态显示;通知模块包括的功能有,查看已发布的的通知;个人中心模块包括的功能有,查看个人信息、修改个人信息。校园互助平台前台功能结构图如图1-1所示:
后台主要由管理员进行操作,分为六个模块,分别为,用户管理模块、文章管理模块、生活分享管理模块、失物招领管理模块、活动管理模块、通知管理模块。
用户管理模块包括的功能有,搜索用户、查看用户信息、删除用户;文章管理模块即为学习交流管理模块,包括的功能主要有,查看文章信息、删除文章;生活分享管理模块包括的功能有,查看生活分享的内容、删除分享;失物招领管理模块包括的功能有,查看发布的失物或招领内容、发布失物招领信息、修改发布的信息内容、删除发布的失物招领;活动管理模块包括的功能有,查看发布的活动内容、发布活动、修改发布的活动内容、删除发布的活动;通知管理模块包括的功能有,发布通知、查看通知内容、修改通知内容、删除通知。校园互助平台后台功能结构图如图3-2所示:
图3-2 后台功能结构图
校园互助平台主要有两个角色,普通用户和管理员,普通用户主要对前台进行操作,管理员主要对后台管理端进行操作,用例图如3-3所示:
图3-3 校园互助平台用例图
二,环境介绍
语言环境:Java: jdk1.8
数据库:Mysql: mysql5.7
应用服务器:Tomcat: tomcat8.5.31
开发工具:IDEA或eclipse
后台服务框架:springboot+mybaits
前端框架技术:Vue
三,系统展示
5.1 后端管理模块
5.1.1 登录
管理员访问后台管理系统,输入对应的账号密码,点击登录按钮,触发校验事件,对管理员输入的账号与密码进行校验,待校验成功后执行登录操作,发送/admin/user/login请求,后端再次对数据校验,将提交的账号与加密后的密码从数据库中匹配,倘若失败则返回错误消息,反之,查出管理员的基本信息,通过JWT工具将管理员的信息以某种规则生成Token,将生成好的Token做为键,管理员ID为值,存储至Redis中,最后将Token返回给前端,前端会将返回的Token存储至浏览器的localStorage中,之后的每一次请求都会将Token放置请求头中并发送给后端,拦截器会从请求头中取出Token从Redis匹配,存在则放行此次请求,失败则跳转至登录页面。界面实现效果如图5-1所示。
图5-1 后台登录界面
5.1.2 用户管理模块
管理员点击用户管理模块默认跳转至用户列表页面,页面渲染时,后台会发送/admin/user/listForConditions请求,默认查询第一页10条数据,后端接收到请求并查询数据库,通过PageHelper插件对查出的数据进行分页,再以Stream流的方式遍历查询出的数据集合,调用Spring提供的copyProperties方法将一个个Entity转换成VO,接着将封装好的数据进行过滤,返回给页面展示,前端会将返回的数据以双向绑定的方式,进行数据渲染,将数据在页面上展现出来。界面实现效果如图5-2所示。
管理员点击添加用户,跳转至添加页面,输入用户的基本信息,添加时前端会动态的监听数据,校验数据是否无误,待数据校验无误后,管理员点击创建用户发送/admin/user/insert请求,后端对数据再次校验,将数据存储至数据库中,并返回添加成功的提示消息。界面实现效果如图5-3所示。
图5-2 用户信息界面
图5-3 添加用户界面
5.1.3 文章模块
管理员点击文章管理模块默认跳转至文章列表页面,页面渲染时,后台会发送/admin/article/listForConditions请求,后端接收到请求并从数据库查询数据,通过PageHelper插件对查出的数据进行分页,再以Stream流的方式遍历查询出的数据集合,调用Spring提供的copyProperties方法将一个个Entity转换成VO,接着将封装好的数据进行过滤,返回给页面展示,前端会将返回的数据以双向绑定的方式,进行数据渲染。界面实现效果如图5-4所示。
图5-4 文章信息显示页面
5.1.4 失物招领模块
图5-5 失物招领页面
图5-6 失物招领添加页面
5.1.5 通知管理模块
管理员点击通知管理模块默认跳转至通知信息列表页面,页面渲染时,后台会发送/admin/announcement/listForConditions请求,默认查询第一页10条数据无条件,后端接收到请求并查询数据库,通过PagHelper插件对查出的数据进行分页,再以Stream流的方式遍历查询出的数据集合,调用Spring提供的copyProperties方法将一个个Entity转换成VO,接着将封装好的数据进行过滤,返回给页面展示,前端会将返回的数据以双向绑定的方式,进行数据渲染。界面实现效果如图5-7所示。
管理员点击添加通知,跳转至添加页面,输入通知的内容,添加时前端会动态的监听数据,校验数据格式是否无误,待数据校验无误后,管理员点击创建用户发送/admin/announcement/insert请求,后端对数据再次校验将数据存储至数据库中,并返回添加成功的提示消息。界面实现效果如图5-8所示。
图5-7 通知显示页面
图5-8 通知添加页面
5.2前台用户模块
5.2.1 收藏功能
图5-9 收藏页面
5.2.2 点赞与踩一踩功能
当用户执行点赞操作,首先前端会取反点赞按钮的状态值与Class样式,若该条数据为未点赞数据,会判断该条数据是否存在于踩集合中,若存在,则将该条数据移除于踩集合,添加至点赞集合,发送/api/like请求,后端接收请求中的数据ID与Token并解析出Token中的用户ID,判断数据ID与用户ID在Redis中的踩Set中是否存在,若存在则移除该数据,接着判断在点赞Set中是否存在,若存在,则移除该数据,若不存在则添加至点赞Set集合中,操作完Redis后,系统会拿着该数据ID访问数据库,对该数据的点赞进行+1操作。当用户执行踩操作,首先前端会取反踩按钮的状态值与Class样式,若该条数据为未踩数据,会判断该条数据是否存在于点赞集合中,若存在,则将该条数据移除于点赞集合,添加至踩集合,发送/api/unLike请求,后端接收请求中的数据ID与Token并解析出Token中的用户ID,判断数据ID与用户ID在Redis中的点赞Set中是否存在,若存在则移除该数据,与此同时判断在踩Set中是否存在,若存在,则移除该数据,若不存在则添加至踩Set集合中,操作完Redis后,系统会拿着该数据ID访问数据库,对该数据的踩数进行+1操作。界面实现效果如图5-10所示。
图5-10 点赞与踩一踩界面
四,核心代码展示
package com.baobaoting.schoolhelp.controller.admin; import com.baobaoting.schoolhelp.common.R; import com.baobaoting.schoolhelp.service.IUserActivityService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * 前端控制器 * </p> * * @author * @since 2022-09-02 */ @Api("用户活动中间表") @RestController @RequestMapping("/admin/userActivity") public class AdminUserActivityController { @Autowired private IUserActivityService userActivityService; @ApiOperation("根据ID删除") @DeleteMapping(path = "/deleteById/{userActivityId}") public R deleteById(@PathVariable("userActivityId")Long userActivityId){ int result = userActivityService.deleteById(userActivityId); if (result != 0){ return R.ok().message("删除成功!"); } return R.error().message("删除失败,系统异常!"); } }
package com.baobaoting.schoolhelp.controller.admin; import com.baobaoting.schoolhelp.common.Assert; import com.baobaoting.schoolhelp.common.R; import com.baobaoting.schoolhelp.entity.dto.LostFoundDTO; import com.baobaoting.schoolhelp.entity.vo.LostFoundVO; import com.baobaoting.schoolhelp.service.ILostFoundService; import com.baobaoting.schoolhelp.valid.LostFoundDataValid; 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.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; /** * <p> * 前端控制器 * </p> * * @since 2022-09-02 */ @Api("失物招领") @RestController @RequestMapping("/admin/lostfound") public class AdminLostFoundController { @Autowired private ILostFoundService lostFoundService; @ApiOperation("根据条件查询失物与招领") @PostMapping(path = "/listForConditions") public R listForConditions(@RequestParam(name = "page",defaultValue = "1")Integer page, @RequestParam(name = "limit",defaultValue = "10")Integer limit,@RequestBody LostFoundDTO lostFoundDTO){ PageInfo<LostFoundVO> lostFoundVOPageInfo = lostFoundService.listForConditions(page,limit,lostFoundDTO); return R.ok().data("data",lostFoundVOPageInfo); } @ApiOperation("根据ID查询") @GetMapping(path = "/getByIdForAdmin") public R getById(@RequestParam(name = "lostFoundId")Long lostFoundId){ LostFoundVO lostFoundVO = lostFoundService.getByIdForAdmin(lostFoundId); return R.ok().data("data",lostFoundVO); } @ApiOperation("添加丢失招领信息") @PostMapping(path = "/insert") public R insert(@RequestBody @Validated({LostFoundDataValid.class}) LostFoundDTO lostFoundDTO, BindingResult bindingResult,@RequestHeader(name = "X-Token")String token){ Assert.validResult(bindingResult); lostFoundDTO.setToken(token); int result = lostFoundService.insert(lostFoundDTO, token); if (result != 0){ return R.ok().message("添加成功!"); } return R.error().message("添加失败,请稍后再试!"); } @ApiOperation("根据ID删除丢失招领") @DeleteMapping(path = "/deleteById/{lostFoundId}") public R deleteById(@PathVariable("lostFoundId")Long lostFoundId){ int result = lostFoundService.deleteById(lostFoundId); if (result != 0){ return R.ok().message("删除成功!"); } return R.error().message("删除失败,系统异常"); } @ApiOperation("根据ID修改丢失招领信息") @PutMapping(path = "/updateById") public R updateById(@RequestBody LostFoundDTO lostFoundDTO){ int result = lostFoundService.updateById(lostFoundDTO); if (result != 0){ return R.ok().message("修改成功!"); } return R.error().message("修改失败!"); } }
package com.baobaoting.schoolhelp.controller.admin; import com.baobaoting.schoolhelp.common.R; import com.baobaoting.schoolhelp.entity.dto.LifeShareDTO; import com.baobaoting.schoolhelp.entity.vo.LifeShareVO; import com.baobaoting.schoolhelp.service.ILifeShareService; 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.*; /** * <p> * 前端控制器 * </p> * * @since 2022-09-02 */ @Api("生活分享") @RestController @RequestMapping("/admin/lifeshare") public class AdminLifeShareController { @Autowired private ILifeShareService lifeShareService; @ApiOperation("分页查询生活分享") @PostMapping(path = "/listForConditions") public R listForConditions(@RequestParam(name = "page", defaultValue = "1") Integer page, @RequestParam(name = "limit", defaultValue = "10") Integer limit, @RequestBody(required = false) LifeShareDTO lifeShareDTO){ PageInfo<LifeShareVO> lifeShareVOPageInfo = lifeShareService.listForConditions(page,limit,lifeShareDTO); return R.ok().data("data",lifeShareVOPageInfo); } @ApiOperation("根据ID查询") @GetMapping(path = "/getByIdForAdmin") public R getByIdForAdmin(@RequestParam(name = "lifeShareId")Long lifeShareId){ LifeShareVO lifeShareVO = lifeShareService.getByIdForAdmin(lifeShareId); return R.ok().data("data",lifeShareVO); } @ApiOperation("根据ID删除") @DeleteMapping(path = "/deleteById/{lifeShareId}") public R deleteById(@PathVariable("lifeShareId")Long lifeShareId){ int result = lifeShareService.deleteById(lifeShareId); if (result != 0) { return R.ok().message("删除成功!"); } return R.error().message("删除失败,系统异常!"); } }
package com.baobaoting.schoolhelp.controller.admin; import com.baobaoting.schoolhelp.common.R; import com.baobaoting.schoolhelp.entity.UserEntity; import com.baobaoting.schoolhelp.entity.dto.UserDTO; import com.baobaoting.schoolhelp.entity.vo.UserVO; import com.baobaoting.schoolhelp.service.IUserService; 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.*; /** * <p> * 前端控制器 * </p> * @since 2022-09-02 */ @Api("用户管理") @RestController @RequestMapping("/admin/user") public class AdminUserController { @Autowired private IUserService userService; @ApiOperation("根据条件查询用户") @PostMapping(path = "/listForConditions") public R listForConditions(@RequestParam(name = "page",defaultValue = "1") Integer page, @RequestParam(name = "limit",defaultValue = "10") Integer limit, @RequestBody(required = false) UserDTO userDTO) { PageInfo<UserVO> userVOPageInfo = userService.listForConditions(page, limit, userDTO); return R.ok().data("data", userVOPageInfo); } @ApiOperation("根据ID查询用户") @GetMapping(path = "/getByIdForAdmin") public R getById(@RequestParam(name = "userId")Long userId){ UserVO userVO = userService.getByIdForAdmin(userId); return R.ok().data("data",userVO); } @ApiOperation("根据用户ID删除") @DeleteMapping(path = "/deleteById/{userId}") public R deleteById(@PathVariable("userId")Long userId){ int result = userService.deleteById(userId); if (result != 0){ return R.ok().message("删除成功!"); } return R.error().message("删除失败!"); } @ApiOperation("根据ID修改用户信息") @PutMapping(path = "/updateById") public R updateById(@RequestBody UserDTO userDTO){ int result = userService.updateById(userDTO); if (result != 0){ return R.ok().message("修改成功!"); } return R.error().message("修改失败!"); } @ApiOperation("添加用户") @PostMapping(path = "/insert") public R insert(@RequestBody UserDTO userDTO){ int result = userService.insert(userDTO); if (result != 0){ return R.ok().message("添加成功!"); } return R.error().message("添加失败!"); } }
五,项目总结
互助平台研究的内容包括,为在校大学生提供学习交流的氛围和校园日常生活的分享、学校相关活动的介绍以及失物招领和寻物启事。
在当下校园环境中,一个人能够认识的交流的人是有限的,但在平台上,用户包括了所在学校几乎所有的大学生,能够保证自己的想法能被更多的校友知晓,甚至找到志同道合的校友。还可以让大学生在该平台上分享自己日常生活有趣的部分,不仅仅局限在朋友圈,在同一校园也会更有话题可聊,通过他人的分享,更能体会到校园生活的乐趣。在活动界面,学生可以更全面的了解到学校或者社团最近举办的所有活动,并能积极呼吁学生报名参加。在失物寻物界面,大学生可对自己在校园内捡到的物品上传,为失主提供寻找的途径。学生也可发布自己丢失的物品信息,让捡到的学生有机会归还给,该模块为大学生提供了为失物找失主、失主找丢失的物品的渠道。
互助平台主要面向在校大学生,旨在为在校大学生提供校园生活服务,丰富学时光的校园生活。