1. 项目概述:疫情下的高校人员管理平台
去年帮学弟调试这个毕设项目时,我意识到这类管理系统在特殊时期的价值。这个基于SpringBoot+Vue的高校人员管理平台,核心要解决三个痛点:教职工健康信息实时采集、学生行程动态追踪、校内区域出入管控。不同于常规OA系统,疫情管理对数据时效性和统计维度有更高要求。
平台采用经典的前后端分离架构,后端SpringBoot提供RESTful API,前端Vue实现动态交互,MySQL作为数据存储。这种技术栈组合既能满足毕业设计的教学要求,又符合当前企业主流开发模式。我在实际部署时发现,系统对并发要求不高但数据一致性要求严格,比如同一个教职工的晨午检记录不允许重复提交。
2. 技术架构解析
2.1 后端SpringBoot设计要点
采用多模块Maven项目结构,主要分为:
system-core(核心工具类)system-admin(管理后台接口)system-api(移动端接口)system-task(定时任务)
特别注意在application.yml中配置了多环境profiles,这是很多初学者容易忽略的。数据库连接池使用HikariCP而非默认的Tomcat pool,实测在低配云服务器上性能提升约30%:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
2.2 前端Vue工程优化
使用Vue CLI 4.x脚手架初始化项目时,建议关闭ESLint校验(新手容易因此卡壳)。通过vue.config.js实现三项关键配置:
- 代理设置解决跨域
- 打包路径修改
- 开启Gzip压缩
javascript复制module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
configureWebpack: {
plugins: [
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$/
})
]
}
}
3. 核心功能实现
3.1 健康打卡模块
数据库设计采用纵向表结构(health_report),包含字段:
- user_id(关联用户表)
- report_date(打卡日期)
- temperature(体温)
- health_status(下拉选择)
- location(GPS坐标)
后端采用策略模式处理不同用户类型的打卡规则。比如教职工每天一次,住校生需要晨午两次打卡。核心校验逻辑:
java复制public class HealthCheckStrategy {
public boolean validate(HealthReport report) {
// 规则1:体温范围校验
if(report.getTemperature() < 35 || report.getTemperature() > 42) {
throw new BizException("体温数据异常");
}
// 规则2:当日是否已提交
Integer count = healthMapper.selectCount(
new QueryWrapper<HealthReport>()
.eq("user_id", report.getUserId())
.eq("report_date", LocalDate.now())
);
return count == 0;
}
}
3.2 出入审批流程
使用状态机模式管理审批状态流转:
mermaid复制stateDiagram
[*] --> PENDING
PENDING --> APPROVED: 管理员通过
PENDING --> REJECTED: 管理员拒绝
APPROVED --> USED: 扫码核销
USED --> [*]
前端实现基于Element UI的时间选择器+地图选址组件组合。特别注意要缓存最近三次的出入记录,提升用户体验:
vue复制<template>
<el-form>
<el-date-picker
v-model="form.dateRange"
type="daterange"
:disabled-date="disabledDate">
</el-date-picker>
<location-picker
@change="handleLocationChange"
:history="locationHistory">
</location-picker>
</el-form>
</template>
4. 数据库设计与优化
4.1 关键表结构
sql复制CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`user_type` tinyint COMMENT '1教职工 2学生 3访客',
`college_id` int COMMENT '学院ID',
`username` varchar(50) NOT NULL,
`id_card` varchar(18) NOT NULL,
`phone` varchar(11) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_idcard` (`id_card`),
KEY `idx_college` (`college_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 查询优化方案
- 人员统计报表使用物化视图:
sql复制CREATE MATERIALIZED VIEW mv_daily_health
REFRESH COMPLETE ON DEMAND
AS
SELECT
report_date,
college_id,
COUNT(CASE WHEN health_status=1 THEN 1 END) as normal_count,
COUNT(CASE WHEN health_status=2 THEN 1 END) as fever_count
FROM health_report hr
JOIN sys_user u ON hr.user_id = u.user_id
GROUP BY report_date, college_id;
- 对于行程追踪的时空查询,使用R树索引优化:
sql复制ALTER TABLE travel_record
ADD SPATIAL INDEX(`location_path`);
5. 典型问题排查实录
5.1 跨域问题深度解决
除了基础的@CrossOrigin注解,还需要注意:
- 当使用Spring Security时,需额外配置:
java复制@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);
return config;
});
}
- 前端axios实例需要设置withCredentials:
javascript复制const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000,
withCredentials: true
})
5.2 批量导入性能优化
原始方案逐条插入导致1000条数据需要8秒,改进方案:
- 使用MyBatis的批量插入语法:
xml复制<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO health_report
(user_id, report_date, temperature)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.reportDate}, #{item.temperature})
</foreach>
</insert>
- 开启rewriteBatchedStatements参数:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/covid?rewriteBatchedStatements=true
实测性能提升至0.8秒完成1000条记录插入。
6. 部署实战经验
6.1 后端打包注意事项
- 排除测试依赖:
xml复制<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
- 指定启动类:
xml复制<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.covid.CovidApplication</mainClass>
</configuration>
</plugin>
6.2 前端部署踩坑记录
- 路由模式问题:使用history模式需要Nginx额外配置
nginx复制location / {
try_files $uri $uri/ /index.html;
}
- 静态资源404问题:修改publicPath为相对路径
javascript复制// vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
}
- 接口地址动态配置:通过window._env_注入
html复制<!-- public/index.html -->
<script>
window._env_ = {
API_URL: 'https://your.domain.com'
}
</script>
7. 毕设答辩加分技巧
- 系统亮点提炼:
- 采用Redis缓存热点数据(如各学院健康统计)
- 使用WebSocket实现异常情况实时告警
- 导出Excel使用EasyExcel避免OOM
- 性能对比数据准备:
- 优化前后查询响应时间对比表
- 不同并发下的系统吞吐量统计
- 扩展性问题:
- 如何扩展支持多校区管理
- 与现有教务系统对接方案
- 移动端小程序适配思路
我在指导答辩时发现,能清晰说明技术选型原因(比如为什么用Vue不用React)的学员通常能获得更高分数。建议准备一份技术对比矩阵:
| 技术选项 | 优势 | 适用场景 | 选型理由 |
|---|---|---|---|
| Vue.js | 学习曲线平缓 | 中小型管理后台 | 符合团队技术储备 |
| Element UI | 组件丰富 | 快速开发 | 与Vue生态契合度高 |
| MyBatis | SQL可控 | 复杂业务查询 | 需要精细优化查询 |
