1. 项目背景与核心需求
学生宿舍作为高校生活的重要场所,其设施维护效率直接影响学生的居住体验。传统纸质报修流程存在响应慢、进度不透明、统计困难等痛点。这套基于SpringBoot3+Vue3的报修系统,正是为解决以下核心问题而设计:
- 流程数字化:将报修申请、工单分配、维修反馈全流程线上化,告别纸质登记本
- 实时状态追踪:学生可随时查看报修进度,维修人员能即时接收新任务提醒
- 数据可视化:自动生成设备故障统计报表,辅助后勤部门优化资源配置
技术选型上,前端采用Vue3组合式API开发,后端使用SpringBoot3构建RESTful接口,数据库选用MySQL 8.0。这套技术栈既能满足高校场景的高并发需求(如开学季集中报修),又便于后续功能扩展(如接入微信小程序)。
实际部署中发现:移动端访问占比高达85%,因此在Vue3项目中特别优化了移动端表单输入体验,例如增加防误触设计和离线缓存功能。
2. 系统架构设计
2.1 技术栈全景图
code复制前端层:Vue3 + Pinia + Vant UI + Axios
网关层:Nginx反向代理 + HTTPS加密
后端层:SpringBoot3 + Spring Security + MyBatis-Plus
数据层:MySQL8.0 + Redis缓存
运维层:Docker容器化 + Prometheus监控
2.2 前后端分离架构
采用经典的B/S架构模式:
- 前端SPA应用通过80端口提供服务
- 后端API服务运行在8080端口
- 通过Nginx配置跨域和请求转发
这种架构的优势在于:
- 前端可独立部署,不影响后端服务
- 利用浏览器缓存机制提升加载速度
- 便于后期扩展多终端接入(如小程序、APP)
2.3 数据库ER图设计
主要实体关系包括:
- 学生(Student) ↔ 报修单(RepairOrder):一对多
- 维修工(Maintainer) ↔ 报修单:一对多
- 宿舍楼(DormBuilding) ↔ 宿舍房间(Room):一对多
关键字段设计示例:
sql复制CREATE TABLE `repair_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`student_id` varchar(20) NOT NULL COMMENT '学号',
`fault_type` tinyint NOT NULL COMMENT '1水电/2家具/3网络',
`description` varchar(500) DEFAULT NULL,
`status` tinyint DEFAULT '0' COMMENT '0待接单/1处理中/2已完成',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`images` json DEFAULT NULL COMMENT '报修图片URL数组',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 前端关键实现
3.1 Vue3组合式API实践
使用setup语法糖简化代码结构:
javascript复制// 报修表单组件
<script setup>
const formState = reactive({
building: '',
room: '',
faultType: null,
desc: ''
})
const onSubmit = async () => {
try {
await axios.post('/api/repair', formState)
showToast('提交成功')
} catch (e) {
console.error('提交失败', e)
}
}
</script>
3.2 移动端适配方案
- 视口配置:
html复制<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
- CSS适配:
css复制/* 使用vw单位 */
.submit-btn {
width: 90vw;
margin: 0 auto;
}
/* 防止iOS输入框缩放 */
input, textarea {
font-size: 16px !important;
}
- 手势优化:
javascript复制// 防止快速重复点击
const debounceSubmit = _.debounce(onSubmit, 1000)
3.3 状态管理设计
采用Pinia管理全局状态:
javascript复制// stores/repair.js
export const useRepairStore = defineStore('repair', {
state: () => ({
historyOrders: []
}),
actions: {
async fetchHistory() {
this.historyOrders = await getRepairHistory()
}
}
})
4. 后端核心功能实现
4.1 SpringBoot3新特性应用
- 记录操作日志(利用AOP):
java复制@Aspect
@Component
public class LogAspect {
@AfterReturning("execution(* com..controller.*.*(..))")
public void logMethodAccess(JoinPoint jp) {
String method = jp.getSignature().getName();
log.info("执行方法: " + method);
}
}
- 参数校验:
java复制@PostMapping("/repair")
public Result submitRepair(@Valid @RequestBody RepairDTO dto) {
// ...
}
@Data
public class RepairDTO {
@NotNull(message = "故障类型不能为空")
private Integer faultType;
@Size(max = 500, message = "描述不超过500字")
private String description;
}
4.2 工单状态机设计
使用枚举定义状态流转:
java复制public enum RepairStatus {
PENDING(0) {
@Override
public RepairStatus nextStatus() {
return PROCESSING;
}
},
PROCESSING(1) {
// ...其他状态转换逻辑
};
private final int code;
public abstract RepairStatus nextStatus();
}
4.3 定时任务设计
每天凌晨统计昨日工单:
java复制@Scheduled(cron = "0 0 0 * * ?")
public void generateDailyReport() {
LocalDate yesterday = LocalDate.now().minusDays(1);
List<RepairOrder> orders = orderMapper.selectByDate(yesterday);
// 生成Excel报表并邮件发送
}
5. 系统安全方案
5.1 认证授权设计
采用JWT+Spring Security方案:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthFilter(authenticationManager()));
return http.build();
}
}
5.2 敏感数据保护
- 密码加密存储:
java复制BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encodedPwd = encoder.encode(rawPassword);
- 日志脱敏处理:
java复制public String desensitizePhone(String phone) {
if(StringUtils.isEmpty(phone)) return "";
return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
}
6. 部署与运维实践
6.1 Docker化部署
后端Dockerfile示例:
dockerfile复制FROM openjdk:17
COPY target/repair-system.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
前端Nginx配置:
nginx复制server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
}
}
6.2 性能优化措施
- 接口缓存:
java复制@Cacheable(value = "buildings", key = "#root.methodName")
public List<Building> getAllBuildings() {
return buildingMapper.selectList(null);
}
- SQL优化:
sql复制-- 添加复合索引提升查询效率
ALTER TABLE repair_order
ADD INDEX idx_status_created (status, create_time);
7. 典型问题解决方案
7.1 图片上传限制
解决方案:
- 前端限制文件类型和大小
javascript复制const beforeUpload = (file) => {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) alert('仅支持JPEG格式')
if (!isLt2M) alert('图片大小不超过2MB')
return isJPG && isLt2M
}
- 后端使用OSS存储
java复制public String uploadToOSS(MultipartFile file) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);
ossClient.putObject(bucketName, objectName, file.getInputStream());
return "https://" + bucketName + "." + endpoint + "/" + objectName;
}
7.2 高并发报修提交
应对策略:
- 使用Redis分布式锁
java复制public boolean submitWithLock(RepairDTO dto) {
String lockKey = "repair_submit:" + dto.getStudentId();
try {
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (locked) {
return repairService.createOrder(dto);
}
throw new BusinessException("操作过于频繁");
} finally {
redisTemplate.delete(lockKey);
}
}
- 数据库连接池配置
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
8. 扩展功能展望
- 微信小程序接入:
- 利用uni-app编译到小程序平台
- 集成微信支付功能(维修押金场景)
- 智能派单算法:
java复制public Maintainer assignBestMaintainer(RepairOrder order) {
// 基于维修工技能匹配度、当前位置、当前工单量等维度计算
return maintainerService.list()
.stream()
.min(Comparator.comparing(m -> calculateScore(m, order)))
.orElse(null);
}
- 物联网设备对接:
- 水电表异常自动触发报修工单
- 门禁系统数据关联晚归报修
这套系统在某高校实际运行后,报修平均响应时间从原来的48小时缩短至4小时,学生满意度提升35%。关键成功因素在于:
- 移动端友好的操作体验
- 实时推送的进度通知
- 维修人员的绩效考核挂钩
对于想二次开发的同行,建议重点关注:
- 报修分类体系的扩展性设计
- 状态流转的自定义配置能力
- 与现有校园系统的单点登录集成
