高校健康上报系统设计与实现
0. 大作业讲解视频在根目录下
1. 项目介绍
在全国人民共同抗击新冠肺炎疫情的严峻形势下,为使高校师生健康信息及时汇报,便于了解健康状况,做好高校师生内部疫情防控和管理工作,特别设计开发高校健康上报系统。
2. 需求分析
2.1 前端界面功能模块
- 界面美观、简洁、主题统一;
- 调研国内相关系统界面的输入信息,设计前端各信息录入项目;
- 有防止用户重复提交的功能;
- 有加速渲染前端界面的设计。
2.2 后端管理端功能
-
使用
Vue + ElementUI
实现管理后台各个功能界面; - 界面简洁,主题统一;
- 管理员账号管理模块;
- 使用Spring Security安全框架实现认证、访问控制;
- 账号管理模块,可以锁定账号;
- 有解决系统高并发问题的设计;
- 提供大数据报表并导出Excel表格,相关人员通过报表可以一目了然查看相关信息;
- 所有列表可以进行综合查询,特别是时间字段,并可以排序;
- 所有列表可以导出excel文件或者pdf文件;
- 接入莞工中央认证
- 后台登录使用自定义图形验证码
3. 数据库设计
3.1 中央认证表
注:该表保存通过中央认证登录的用户信息【用于填写健康上报表单前的登录认证】
3.2 管理员表
3.3 健康上报表
4. 前端设计
使用技术栈:Vue + ElementUI + axios + VueX + Echart
4.1 健康上报表单设计
健康上报表单代码仓库:https://gitee.com/alizipeng/health-system-front
4.2 中台管理系统设计
中台管理系统代码仓库:https://gitee.com/alizipeng/health-system-middle
5. 后端设计
5.1 技术方案
(1)开发框架:Spring Boot、Mybatis-plus
(2)项目构建工具:Maven
(3)权限控制:Spring Security。用于对登录的用户认证授权,进行访问控制。
(4)数据缓存/NoSQL:Redis。用于缓存常用数据,如省份数据等;以及做一些NoSQL查询;使用Redis防止消息重复消费
(5)消息队列:RabbitMQ。用于异步导出查询数据,将数据导出与主业务进行 解耦 。可将数据导出模块单独部署,当数据量很大时,可以防止导出模块与主业务模块抢夺服务器资源。同时使用了 延时队列 来删除过期的导出文件。
(6)数据导出:利用MyBatis的动态SQL功能,首先传入参数生成完整SQL,再把SQL发送到队列中,等待消费者进行消费。
5.2 多模块项目结构
5.3 权限模块设计
5.3.1 中央认证安全配置
```java package com.health.central_authentication.config;
import com.health.central_authentication.filter.DGUTCheckTokenFilter; import com.health.central_authentication.handler.DGUTAccessDeniedHandler; import com.health.central_authentication.handler.DGUTAuthenticationEntryPoint; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
/* * 莞工中央认证安全配置 * @author: zipeng Li * 2021/6/14 19:53 / @Configuration @Order(99) public class DGUTSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private DGUTAccessDeniedHandler dgutAccessDeniedHandler; @Resource private DGUTAuthenticationEntryPoint dgutAuthenticationEntryPoint; @Resource private DGUTCheckTokenFilter dgutCheckTokenFilter;
/**
* 配置权限资源
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 只拦截检查'/api/user/**'的请求
.antMatcher("/api/user/**").authorizeRequests().anyRequest().hasAuthority("USER")
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(dgutAuthenticationEntryPoint)
.accessDeniedHandler(dgutAccessDeniedHandler);
http.addFilterBefore(dgutCheckTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
} ```
5.3.2 后台登录安全配置
```java package com.health.admin.config;
import com.health.admin.filter.CheckTokenFilter; import com.health.admin.handler.*; import com.health.security.impl.AdminDetailsService; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
/* * 后台管理系统安全配置 * @author: zipeng Li * 2021/6/13 12:58 / @Configuration @Order(100) public class AdminSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private AdminDetailsService adminDetailsService; @Resource private LoginSuccessHandler loginSuccessHandler; @Resource private LoginFailureHandler loginFailureHandler; @Resource private AdminAuthenticationEntryPoint adminAuthenticationEntryPoint; @Resource private AdminAccessDeniedHandler adminAccessDeniedHandler; @Resource private AdminLogoutSuccessHandler adminLogoutSuccessHandler; @Resource private CheckTokenFilter checkTokenFilter; @Value("${system.admin.login-url}") private String loginUrl; @Value("${system.admin.logout-url}") private String logoutUrl;
@Bean
public PasswordEncoder passwordEncoder() {
// 明文+随机盐值》加密存储
return new BCryptPasswordEncoder();
}
/**
* 配置权限资源
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 只拦截检查'/api/admin/**'的请求
.antMatcher("/api/admin/**").authorizeRequests()
.antMatchers(loginUrl, "/api/admin/image","/api/admin/testMq").permitAll()
.anyRequest().hasAuthority("ADMIN")
.and().formLogin()
.loginProcessingUrl(loginUrl)
// 自定义的登录验证成功或失败后的去向
.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler)
.and().logout()
.logoutUrl(logoutUrl)
.logoutSuccessHandler(adminLogoutSuccessHandler)
// 禁用csrf防御机制(跨域请求伪造),这么做在测试和开发会比较方便。
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(adminAuthenticationEntryPoint)
.accessDeniedHandler(adminAccessDeniedHandler);
http.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
/**
* 配置认证处理器
* 自定义的UserDetailsService
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(adminDetailsService);
}
} ```
5.4 数据导出模块设计
5.4.1 消息队列部分设计
分为两个消费者:
DataStatsTaskReceiver
的功能为
1. 执行SQL并导出Excel文件,然后把文件上传到七牛云中,再将任务状态更新为成功,客户端便可下载文件;
2. 成功导出文件后,会给文件设置一个有效期,过期之后将从七牛云删除。具体实现为发送延时消息到延迟队列中。
DelayTaskReceiver
为延迟队列的消费者,功能为接收
DataStatsTaskReceiver
发送过来的文件ID,等到有效期到达之后,会对文件进行删除。具体实现为使用了RabbitMQ延时队列插件。
DataStatsTaskReceiver
实现:
```java
@RabbitListener(queues = DataStatsTaskQueueConstants.STATS_TASK_QUEUE_NAME)
public void handler(Message message, Channel channel) throws IOException {
DataStatsTask dataStatsTask = (DataStatsTask) message.getPayload();
MessageHeaders headers = message.getHeaders();
Long tag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
String msgId = (String) headers.get("spring_returned_message_correlation");
logger.info("Received Task:{}",dataStatsTask.toString());
// 设置唯一消息id,防止重复消费
if (redisTemplate.opsForHash().entries("stats_task_log").containsKey(msgId)) {
//redis 中包含该 key,说明该消息已经被消费过
logger.info(msgId + ":消息已经被消费");
channel.basicAck(tag, false);//确认消息已消费
return;
}
String sql = dataStatsTask.getSql();
String key = dataStatsTask.getTaskId();
// 在redis中设置该任务的状态
redisTemplate.opsForHash().put("export_task",dataStatsTask.getTaskId(),"processing");
if(dbUtil.extractToExcel(sql,path,key)){
String local = path+key;
String url = QiNiuUtil.upload(local,key);
if(url==null){
redisTemplate.opsForHash().delete("export_task",dataStatsTask.getTaskId());
return;
}
redisTemplate.opsForHash().put("export_task",dataStatsTask.getTaskId(),url);
// 发送延时任务
sendDelayTask(key,dataStatsTask.getExpired());
}
}
/*
* 发送延时任务,msg为id,delayTime为文件有效期
/
public void sendDelayTask(String msg,Integer delayTime){
rabbitTemplate.convertAndSend(DelayDeleteQueueConstants.DELAY_DELETE_EXCHANGE_NAME,
DelayDeleteQueueConstants.DELAY_DELETE_ROUTING_KEY_NAME, msg, a ->{
a.getMessageProperties().setDelay(delayTime);
return a;
});
}
`DelayTaskReceiver`配置:
java
@Configuration
public class DelayedRabbitMQConfig {
@Bean
public Queue immediateQueue() {
return new Queue(DelayDeleteQueueConstants.DELAY_DELETE_QUEUE_NAME);
}
@Bean
public CustomExchange customExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
return new CustomExchange(DelayDeleteQueueConstants.DELAY_DELETE_EXCHANGE_NAME,
"x-delayed-message", true, false, args);
}
@Bean
public Binding bindingNotify(@Qualifier("immediateQueue") Queue queue,
@Qualifier("customExchange") CustomExchange customExchange) {
return BindingBuilder.bind(queue).to(customExchange)
.with(DelayDeleteQueueConstants.DELAY_DELETE_ROUTING_KEY_NAME).noargs();
}
}
`DelayTaskReceiver`实现:
java
@RabbitListener(queues = DelayDeleteQueueConstants.DELAY_DELETE_QUEUE_NAME)
public void handler(Message message, Channel channel) throws IOException {
String taskId = String.valueOf(message.getPayload());
logger.debug("delete expired task:{}",taskId);
QiNiuUtil.deleteFile(taskId);
redisTemplate.opsForHash().delete("export_task",taskId);
}
```
5.4.2 数据导出工具类
执行SQL,然后导出为Excel,会自动添加表头 ```java
public boolean extractToExcel(String sql,String path,String fileName){
try {
ResultSet resultSet = execute(sql);
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
List
> ret = new ArrayList<>();
List
}
return sql;
}
Controller调用代码:
java
@GetMapping("/stats/temperature")
public ResultVo getStatsTemperature(@RequestParam("temperature")float temperature,
@RequestParam("time")String time) {
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("stats-mybatis.xml"));
} catch (IOException e) {
e.printStackTrace();
return ResultUtils.error("Server error");
}
TemperStatsParam sParam = new TemperStatsParam();
sParam.setTemperature(temperature);
sParam.setTime(time);
String sql = MybatisSQLUtil.getMyBatisSql("StatsMapper.getTemperStats", sParam, sqlSessionFactory);
DataStatsTask dataStatsTask = new DataStatsTask(UUID.randomUUID().toString()+".xls",
sql,60000);
sendDataStatsTask(dataStatsTask);
return ResultUtils.success(dataStatsTask.getTaskId());
}
```
Mapper:
5.5 公共模块设计
5.6 实体类
5.7 DAO层
5.8 Service层
5.9 接口层
5.10 中央认证设计
```java package com.health.central_authentication;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.health.security.CentralAuthenticationToken; import com.health.security.Student; import com.health.security.StudentService; import com.health.util.JwtUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.json.JacksonJsonParser; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.WebAttributes; import org.springframework.util.LinkedMultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Map;
/* * @author: zipeng Li * 2021/6/14 16:42 / @Slf4j @RestController public class CentralAuthenticationController { private static final String appid = "javaee"; private static final String appSecret = "b3b52e43ccfd"; private static final RestTemplate rest = new RestTemplate(); private static final JacksonJsonParser jsonParser = new JacksonJsonParser(); private static final String GetAccessTokenURL = "https://cas.dgut.edu.cn/ssoapi/v2/checkToken"; private static final String GetInfoURL = "https://cas.dgut.edu.cn/oauth/getUserInfo";
@Resource
private StudentService studentService;
@GetMapping("/api/central/login")
public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 重定向到中央认证
response.sendRedirect("https://cas.dgut.edu.cn?appid=" + appid);
}
@GetMapping("/login/dgut")
public void callBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 新建未认证的 authentication
String token = request.getParameter("token");
CentralAuthenticationToken centralAuthenticationToken = new CentralAuthenticationToken(token);
try {
centralAuthenticationToken = authenticate(centralAuthenticationToken);
} catch (AuthenticationException e) {
// 如果校验失败providerManager会抛异常,在catch里作异常处理。
response.sendRedirect("https://cas.dgut.edu.cn?appid=" + appid);
return;
}
// 校验成功,执行后面的流程:
SecurityContextHolder.getContext().setAuthentication(centralAuthenticationToken);
// 移除之前认证时的错误信息
request.getSession().removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
// 生产token返回
JwtUtils jwtUtils = new JwtUtils();
String res = jwtUtils.generateTokenByCentralAuthenticationToken(centralAuthenticationToken);
log.info(res);
response.sendRedirect("http://localhost:8081?token=" + res);
}
private CentralAuthenticationToken authenticate(Authentication authentication) throws AuthenticationException {
// 1.强转 未认证的CentralAuthenticationToken
CentralAuthenticationToken authenticationToken = (CentralAuthenticationToken) authentication;
// 2.向中央认证服务器发送请求获取 openid 和 access_token
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("token", authenticationToken.getToken());
map.add("appid", appid);
map.add("appsecret", appSecret);
Map<String, Object> stringObjectMap = jsonParser.parseMap(rest.postForObject(GetAccessTokenURL, map, String.class));
String accessToken = (String) stringObjectMap.get("access_token");
String openid = (String) stringObjectMap.get("openid");
// 3.向中央认证服务器发送请求获取个人信息
map.clear();
map.add("access_token", accessToken);
map.add("openid", openid);
Map<String, Object> objectMap = jsonParser.parseMap(rest.postForObject(GetInfoURL, map, String.class));
// 4.认证成功,重新生产 authentication
Student student = new Student();
student.setUsername((String)objectMap.get("username"));
student.setName((String)objectMap.get("name"));
student.setWxOpenid((String)objectMap.get("wx_openid"));
student.setFacultyTitle((String)objectMap.get("faculty_title"));
student.setOpenid((String)objectMap.get("openid"));
// 5. 判断数据库是否已经存在该用户
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(Student::getUsername, student.getUsername());
studentService.saveOrUpdate(student, wrapper);
return new CentralAuthenticationToken(student, AuthorityUtils.createAuthorityList("USER"));
}
} ```
5.11 其他核心接口设计
5.11.1 后台管理相关
```java /* * 管理员控制器 * @author: zipeng Li * 2021/6/13 15:50 / @Slf4j @RestController @RequestMapping("/api/admin") public class AdminController { @Resource private DefaultKaptcha defaultKaptcha; @Resource private AdminService adminService; @Resource private StudentService studentService; @Resource private ReportFormService reportFormService; @Resource private PasswordEncoder passwordEncoder; @Autowired StringRedisTemplate redisTemplate;
@Autowired
RabbitTemplate rabbitTemplate;
@GetMapping("/stats/temperature")
public ResultVo getStatsTemperature(@RequestParam("temperature")float temperature,
@RequestParam("time")String time) {
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("stats-mybatis.xml"));
} catch (IOException e) {
e.printStackTrace();
return ResultUtils.error("Server error");
}
TemperStatsParam sParam = new TemperStatsParam();
sParam.setTemperature(temperature);
sParam.setTime(time);
String sql = MybatisSQLUtil.getMyBatisSql("StatsMapper.getTemperStats", sParam, sqlSessionFactory);
DataStatsTask dataStatsTask = new DataStatsTask(UUID.randomUUID().toString()+".xls",
sql,60000);
sendDataStatsTask(dataStatsTask);
return ResultUtils.success(dataStatsTask.getTaskId());
}
@GetMapping("/stats/region")
public ResultVo getStatsTemperature(@RequestParam("country")String country,
@RequestParam(value = "province",required = false)String province,
@RequestParam(value = "district",required = false)String district) {
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("stats-mybatis.xml"));
} catch (IOException e) {
e.printStackTrace();
return ResultUtils.error("Server error");
}
RegionStatsParam sParam = new RegionStatsParam();
sParam.setCountry(country);
sParam.setProvince(province);
sParam.setDistrict(district);
String sql = MybatisSQLUtil.getMyBatisSql("StatsMapper.getRegionStats", sParam, sqlSessionFactory);
DataStatsTask dataStatsTask = new DataStatsTask(UUID.randomUUID().toString()+".xls",
sql,60000);
sendDataStatsTask(dataStatsTask);
return ResultUtils.success(dataStatsTask.getTaskId());
}
@GetMapping("/stats/task")
public ResultVo getStatsFileId(@RequestParam("id")String id){
String url = String.valueOf(redisTemplate.opsForHash().get("export_task",id));
log.info(url);
if(url.equals("null"))
return ResultUtils.error("任务不存在");
else if(url.equals("process"))
return ResultUtils.error("任务导出中");
else
return ResultUtils.success("导出成功,请在10分钟内下载",url);
}
/**
* 后台登录,获取图形验证码
* @param request
* @param response
* @throws IOException
*/
@RequestMapping("image")
public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
//设置页面缓存方式 不缓存,不存储
response.setHeader("Cache-Control","no-store, no-cache");
//设置以图片的形式响应
response.setContentType("image/jpeg");
//1.获取验证码字符
String text = defaultKaptcha.createText();
log.info("获取验证码:" + text);
//2.存储到session中
request.getSession().setAttribute("code",text);
//3.生成验证码图片
BufferedImage image = defaultKaptcha.createImage(text);
//4.输出给前端
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image,"jpg",out);
if(out != null){
out.close();
}
}
/**
* 添加管理员
* @param admin
* @return
*/
@PostMapping("add-admin")
public ResultVo addAdmin(@RequestBody Admin admin){
// 检查权限
Admin principal =(Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(! "1".equals(principal.getIsAdmin())){
return ResultUtils.error("无此操作权限");
}
//查询用户是否存在
Admin one = adminService.getAdminByUserName(admin.getUsername());
if(one != null){
return ResultUtils.error("用户名已经存在!");
}
//加密用户密码
String pwd = passwordEncoder.encode(admin.getPassword());
admin.setPassword(pwd);
boolean b = adminService.save(admin);
if(b){
return ResultUtils.success("新增管理员成功");
}else{
return ResultUtils.error("新增管理员失败");
}
}
/**
* 管理员锁定
* @param lockAdmin
* @return
*/
@PostMapping("lock-admin")
public ResultVo LockAdmin(@RequestBody LockAdmin lockAdmin){
// 检查权限
Admin principal =(Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(! "1".equals(principal.getIsAdmin())){
return ResultUtils.error("无此操作权限", CodeStatus.NO_AUTH);
}
// 检查是否存在该用户
Admin admin = adminService.getById(lockAdmin.getId());
if (admin == null) {
return ResultUtils.error("不存在该用户", CodeStatus.ERROR_CODE);
}
// 锁定用户
admin.setAccountNonLocked(lockAdmin.isLock());
adminService.saveOrUpdate(admin);
return ResultUtils.success(lockAdmin.isLock()?"解锁成功":"锁定成功");
}
/**
* 管理员列表
* @param parm
* @return
*/
@PostMapping("list")
public ResultVo getList(@RequestBody ParmVo parm){
IPage<Admin> page = new Page<>();
page.setCurrent(parm.getStartIndex());
page.setSize(parm.getPageSize());
IPage<Admin> adminIPage = adminService.page(page);
return ResultUtils.success("查询成功", adminIPage);
}
/**
* 用户列表
* @param parm
* @return
*/
@PostMapping("student-list")
public ResultVo getStudentList(@RequestBody ParmVo parm){
IPage<Student> page = new Page<>();
page.setCurrent(parm.getStartIndex());
page.setSize(parm.getPageSize());
IPage<Student> adminIPage = studentService.page(page);
return ResultUtils.success("查询成功", adminIPage);
}
void sendDataStatsTask(DataStatsTask dataStatsTask) {
rabbitTemplate.convertAndSend(DataStatsTaskQueueConstants.STATS_TASK_EXCHANGE_NAME,
DataStatsTaskQueueConstants.STATS_TASK_ROUTING_KEY_NAME, dataStatsTask, a -> {
a.getMessageProperties().setCorrelationId(dataStatsTask.getTaskId());
return a;
});
}
/**
* 获取填报列表
* @param parmVo
* @return
*/
@PostMapping("report-list")
public ResultVo reportList(@RequestBody ParmVo parmVo){
IPage<ReportForm> page = new Page<>();
page.setCurrent(parmVo.getStartIndex());
page.setSize(parmVo.getPageSize());
IPage<ReportForm> adminIPage = reportFormService.page(page);
return ResultUtils.success("查询成功", adminIPage);
}
/**
* 获取表单详情
* @param id
* @return
*/
@GetMapping("report-detail")
public ResultVo reportDetail(@RequestParam Long id){
ReportForm reportForm = reportFormService.getById(id);
Student student = studentService.getById(reportForm.getCentralAuthenticationId());
HashMap<String, Object> map = new HashMap<>();
map.put("reportForm", reportForm);
map.put("student", student);
return ResultUtils.success("查询成功", map);
}
/**
* 获取统计数据
* @return
*/
@GetMapping("statistical-data")
public ResultVo reportDetail(){
// 获取用户人数
Integer studentNumber = studentService.list().size();
// 获取管理员人数
Integer adminNumber = adminService.list().size();
// 获取今日填报人数
Integer dayRecord = reportFormService.getDayRecords();
// 获取风险人数
Integer dangerNumber = reportFormService.getDangerNumber();
HashMap<Object, Object> map = new HashMap<>(4);
map.put("studentNumber", studentNumber);
map.put("adminNumber", adminNumber);
map.put("dayRecord", dayRecord);
map.put("dangerNumber", dangerNumber);
return ResultUtils.success("获取统计信息", map);
}
}
```
5.11.2 表单相关
```java /* * @author: zipeng Li * 2021/6/16 11:48 / @Slf4j @RestController @RequestMapping("/api/user") public class StudentController {
@GetMapping("student-info")
public ResultVo studentInfo(){
CentralAuthenticationToken authentication = (CentralAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return ResultUtils.success("获取用户信息成功", authentication.getStudent());
}
}
/* * @author: zipeng Li * 2021/6/20 16:53 / @Slf4j @RestController @RequestMapping("/api/user") public class reportController { @Resource private ReportFormService reportFormService;
/**
* 提交表单
* @param reportForm
* @return
*/
@PostMapping("report-form")
public ResultVo reportForm(@RequestBody ReportForm reportForm){
// 判断当前用户是否已经提交
CentralAuthenticationToken authentication = (CentralAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
Student student = authentication.getStudent();
ReportForm one = reportFormService.getDayRecord(student.getId());
if (one != null) return ResultUtils.error("当日已经打卡,勿重复提交");
// 保存数据库
reportForm.setCentralAuthenticationId(student.getId());
reportForm.setName(student.getName());
reportFormService.save(reportForm);
return ResultUtils.success("打卡成功");
}
/**
* 判断今天是否提交成功
* @return
*/
@PostMapping("check-report")
public ResultVo checkReport(){
// 判断当前用户是否已经提交
CentralAuthenticationToken authentication = (CentralAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
Student student = authentication.getStudent();
ReportForm one = reportFormService.getDayRecord(student.getId());
if (one != null) return ResultUtils.success("您今天已经提交成功啦", true);
return ResultUtils.success("您今天还没提交哦", false);
}
} ```
5.11.3
参考文献
- 基于Web的智能校园的研究和应用(武汉理工大学·刘玲)
- 基于微服务的健康管理平台的研究与设计(北京邮电大学·陈乾)
- 基于SSH技术的新生报到信息平台的设计与实现(大连海事大学·柴怡霖)
- 基于UML的教务管理系统分析与设计(南京理工大学·陈芬)
- 基于Java EE平台的个人健康信息管理系统设计与实现(南京邮电大学·贾顺贺)
- 基于Spring框架的短信通道系统的设计与实现(北京邮电大学·刘林华)
- 基于ssh2架构的科研管理系统研究与实现(电子科技大学·龚强)
- 在线学习过程管理系统软件设计与实现(北京邮电大学·王嘉康)
- 基于混合MVC框架的校园网单点登录系统的设计与实现(电子科技大学·张蓉)
- 基于微服务的校园应用门户网站的设计与实现(黑龙江大学·云岩)
- 基于Spring Boot的校园轻博客系统的设计与实现(华中科技大学·邓笑)
- 学生综合信息管理平台的设计与实现(吉林大学·刘铁刚)
- 基于SSH技术的新生报到信息平台的设计与实现(大连海事大学·柴怡霖)
- 基于微服务架构的校园网系统的设计与实现(安徽建筑大学·马红国)
- 基于微服务的健康管理平台的研究与设计(北京邮电大学·陈乾)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕设客栈 ,原文地址:https://bishedaima.com/yuanma/35681.html