1. 项目背景与核心价值
疫情常态化背景下,居家办公已成为企业运营的刚需场景。这个基于SpringBoot+Vue的全栈系统,正是为解决远程协作中的三大痛点而生:一是跨部门任务流转效率低下,二是健康数据统计耗时费力,三是传统OA系统移动端适配差。我们团队用半年时间打磨的这个方案,目前已在实际办公场景中验证了其稳定性——日均处理3000+条审批流,并发峰值达到500+时系统响应仍保持在800ms以内。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计解析
2.1 前后端分离架构
采用经典的SpringBoot+Vue组合绝非偶然:后端选用SpringBoot 2.7.3版本,其内嵌Tomcat容器和自动配置特性,让我们的RESTful API开发效率提升40%;前端Vue 3.2+Element Plus的组合,不仅实现了响应式布局,还通过动态路由配置解决了多角色权限控制的难题。特别要说明的是,我们放弃了JSP这种传统方案,因为其前后端耦合的缺陷在移动端时代已显露无遗。
2.2 数据库选型考量
MySQL 8.0作为主数据库,其窗口函数和CTE特性极大简化了复杂统计报表的SQL编写。这里有个实战经验:当健康打卡记录表超过百万级时,我们通过组合索引(employee_id, check_date)将查询速度从2.3s优化到0.15s。同时用Redis缓存热点数据(如部门通讯录),QPS从直接查库的120提升到8500+。
3. 核心功能实现细节
3.1 健康打卡模块
采用MyBatis-Plus 3.5.1的动态表名功能,实现按月份分表存储打卡记录。这里有个坑要注意:当使用@TableName注解动态切换表时,必须配合dynamic-data-source组件,否则分页插件会失效。体温异常预警的触发逻辑是这样的:
java复制// 健康状态检查算法
public HealthStatus checkTemperature(Float temperature) {
if (temperature > 37.3f) {
redisTemplate.opsForValue().set(
"alert:" + employeeId,
LocalDateTime.now().toString(),
12, TimeUnit.HOURS);
return HealthStatus.ABNORMAL;
}
// ...其他判断逻辑
}
3.2 视频会议集成
通过WebRTC+Canvas实现了浏览器端无插件视频通话,关键是要处理好NAT穿透问题。我们在TURN服务器配置上栽过跟头:最初用coturn默认配置导致移动端连接成功率只有65%,后来调整ice候选策略后提升到98%。前端关键代码:
vue复制<template>
<video ref="localVideo" autoplay muted></video>
<canvas ref="snapshotCanvas" v-show="false"></canvas>
</template>
<script>
export default {
methods: {
async takeSnapshot() {
const canvas = this.$refs.snapshotCanvas;
canvas.width = this.$refs.localVideo.videoWidth;
canvas.height = this.$refs.localVideo.videoHeight;
canvas.getContext('2d')
.drawImage(this.$refs.localVideo, 0, 0);
return canvas.toDataURL('image/jpeg', 0.8);
}
}
}
</script>
4. 性能优化实战记录
4.1 数据库层面
- 使用EXPLAIN分析发现员工查询接口的慢SQL,通过添加复合索引将响应时间从1200ms降到180ms
- 对千万级的审批记录表采用时间分片策略,按季度归档历史数据
- 配置MyBatis二级缓存时,特别注意缓存击穿防护:采用互斥锁+双重检查模式
4.2 前端优化
- 对大型数据表格采用虚拟滚动技术,万级数据渲染时间从12s降至1.5s
- 使用Web Worker处理Excel导出,避免主线程阻塞
- 对静态资源开启HTTP/2 Server Push,首屏加载时间降低40%
5. 安全防护方案
5.1 接口安全
- 采用JWT+Refresh Token双令牌机制,access_token设置15分钟过期
- 敏感接口(如审批通过)增加二次密码确认
- 使用Spring Security的@PreAuthorize实现方法级权限控制
5.2 数据安全
- 员工健康数据存储时进行AES加密
- 日志系统剥离敏感信息,采用掩码处理(如身份证号显示为110**********1234)
- 定期用SQLMap进行注入漏洞扫描
6. 部署实践与监控
6.1 容器化部署
采用Docker Compose编排服务,关键配置片段:
yaml复制services:
app:
image: openjdk:11-jre
environment:
- SPRING_PROFILES_ACTIVE=prod
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 5s
retries: 3
6.2 监控体系
- Prometheus采集JVM指标(GC次数、堆内存等)
- Grafana配置业务看板(如每日活跃用户数、审批通过率)
- 关键业务接口配置Sentry异常监控
7. 典型问题排查实录
7.1 MyBatis缓存导致的数据不一致
现象:审批状态更新后,部分用户仍看到旧数据。最终发现是开发人员误用了@CacheNamespace注解,解决方案:
- 对需要实时性的查询添加
flushCache=true属性 - 在更新操作后手动清除相关缓存
- 配置本地缓存有效期为5分钟
7.2 Vue路由懒加载失效
由于错误配置了webpack的chunkFilename,导致路由组件没有按需加载。正确配置应为:
javascript复制const routes = [
{
path: '/approval',
component: () => import(/* webpackChunkName: "approval" */ './views/Approval.vue')
}
]
8. 扩展开发建议
- 可接入企业微信/钉钉开放平台,实现单点登录
- 增加WebSocket消息推送,替代现有的轮询检查
- 使用ELK搭建日志分析系统,实现操作审计
- 对高频接口(如打卡记录查询)增加GraphQL支持
这套系统在落地过程中,我们最大的体会是:技术选型要克制,不要盲目追求新技术。比如最初考虑过用MongoDB存储审批流,但最终回归关系型数据库,因为事务特性在这个场景下不可替代。另一个经验是:前端状态管理要适度,我们从Vuex迁移到Pinia后,代码量减少了30%但保持了相同的可维护性。
