1. 项目概述与背景
企业内部网络管理系统是现代企业数字化转型的基础设施。我在实际开发中发现,很多中小型企业仍在使用Excel表格或纸质文档管理员工、部门和任务信息,这种模式存在数据孤岛、版本混乱、协作效率低下等问题。基于SpringBoot+Vue的技术栈,我们开发了一套轻量级但功能完备的内部管理系统,特别适合50-200人规模的企业使用。
这套系统最核心的价值在于解决了三个痛点:一是通过统一平台整合了分散的人力资源数据;二是实现了任务流转的可视化跟踪;三是为管理层提供了实时数据看板。技术选型上,后端采用SpringBoot 2.7 + MyBatis-Plus的组合,前端使用Vue 3 + Element Plus,这种组合既保证了开发效率,又能满足企业级应用对稳定性的要求。
2. 系统架构设计
2.1 技术栈选型考量
后端选择SpringBoot主要基于以下考虑:
- 自动配置特性大幅减少XML配置(相比传统SSM框架配置量减少约60%)
- 内嵌Tomcat服务器简化部署流程
- 丰富的Starter依赖(如spring-boot-starter-security用于权限控制)
前端选用Vue.js+Element Plus的组合是因为:
- 响应式编程模型更符合现代Web开发范式
- 组件库提供了丰富的企业级UI组件(如表格、表单、图表等)
- 与后端SpringBoot天然适配的RESTful通信方式
数据库选用MySQL 8.0主要考虑:
- 事务支持完善(ACID特性)
- 对JSON数据类型的原生支持(用于存储动态表单数据)
- 良好的社区支持和完善的文档
2.2 系统模块划分
系统采用经典的三层架构:
code复制├── 表现层(Vue前端)
│ ├── 员工管理模块
│ ├── 部门管理模块
│ ├── 任务管理模块
│ └── 数据统计模块
├── 业务逻辑层(SpringBoot)
│ ├── 权限控制服务
│ ├── 业务规则引擎
│ └── 数据校验服务
└── 数据访问层(MyBatis-Plus)
├── 实体关系映射
├── 动态SQL生成
└── 多数据源支持
3. 核心功能实现细节
3.1 员工信息管理模块
3.1.1 数据库设计优化
员工表(staff_info)的设计有几个关键点需要注意:
sql复制CREATE TABLE `staff_info` (
`staff_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '雪花算法ID',
`staff_name` VARCHAR(50) NOT NULL COMMENT '姓名+索引',
`staff_dept` VARCHAR(30) NOT NULL COMMENT '关联部门表',
`staff_position` VARCHAR(30) NOT NULL DEFAULT '员工' COMMENT '职位',
`staff_phone` VARCHAR(20) UNIQUE COMMENT '手机号加密存储',
`staff_email` VARCHAR(50) UNIQUE COMMENT '邮箱',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`staff_id`),
INDEX `idx_dept` (`staff_dept`),
INDEX `idx_name` (`staff_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
实际开发中我们遇到了两个典型问题:
- 手机号等敏感信息存储:采用AES对称加密后再存入数据库
- 姓名字段模糊查询:添加了前缀索引(idx_name)提升LIKE查询性能
3.1.2 前后端交互实现
前端采用Element Plus的表格组件:
vue复制<el-table
:data="staffList"
border
stripe
@row-click="handleRowClick">
<el-table-column prop="staffName" label="姓名" width="120" />
<el-table-column prop="staffDept" label="部门" width="150" />
<el-table-column prop="staffPosition" label="职位" />
</el-table>
后端接口设计遵循RESTful规范:
java复制@RestController
@RequestMapping("/api/staff")
public class StaffController {
@Autowired
private StaffService staffService;
@GetMapping
public Result<List<StaffVO>> listStaff(
@RequestParam(required = false) String dept,
@RequestParam(required = false) String name) {
// 分页查询逻辑
}
@PostMapping
public Result<Long> addStaff(@Valid @RequestBody StaffDTO dto) {
// 参数校验和业务处理
}
}
3.2 权限控制系统
3.2.1 RBAC模型实现
我们基于Spring Security实现了标准的RBAC(基于角色的访问控制)模型:
code复制用户(user) -> 角色(role) -> 权限(permission)
数据库关系设计:
sql复制CREATE TABLE `sys_role` (
`role_id` BIGINT PRIMARY KEY,
`role_name` VARCHAR(50) UNIQUE NOT NULL,
`role_desc` VARCHAR(200)
);
CREATE TABLE `sys_permission` (
`perm_id` BIGINT PRIMARY KEY,
`perm_name` VARCHAR(50) NOT NULL,
`perm_key` VARCHAR(100) UNIQUE NOT NULL COMMENT '如staff:add'
);
CREATE TABLE `sys_user_role` (
`user_id` BIGINT NOT NULL,
`role_id` BIGINT NOT NULL,
PRIMARY KEY (`user_id`, `role_id`)
);
CREATE TABLE `sys_role_perm` (
`role_id` BIGINT NOT NULL,
`perm_id` BIGINT NOT NULL,
PRIMARY KEY (`role_id`, `perm_id`)
);
3.2.2 动态权限控制
通过实现Spring Security的FilterInvocationSecurityMetadataSource接口,实现从数据库动态加载权限配置:
java复制@Override
public Collection<ConfigAttribute> getAttributes(Object object) {
String requestUrl = ((FilterInvocation) object).getRequestUrl();
// 从缓存查询URL对应的权限标识
List<String> permKeys = permissionService.getPermKeysByUrl(requestUrl);
return SecurityConfig.createList(permKeys.toArray(new String[0]));
}
前端配合实现动态路由:
javascript复制// 过滤有权限的路由
const filterRoutes = (routes, permissions) => {
return routes.filter(route => {
if (route.meta && route.meta.perms) {
return permissions.some(perm => route.meta.perms.includes(perm));
}
return true;
});
};
4. 典型问题解决方案
4.1 跨域问题处理
在前后端分离架构下,跨域是必遇问题。我们的解决方案:
后端配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
前端axios配置:
javascript复制const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000,
withCredentials: true // 允许携带cookie
});
4.2 文件导出性能优化
当导出大量员工数据时(如5000+条记录),我们采用以下优化方案:
- 服务端分页查询+流式写入:
java复制@GetMapping("/export")
public void exportStaff(HttpServletResponse response) {
response.setContentType("application/vnd.ms-excel");
try (OutputStream out = response.getOutputStream();
ExcelWriter writer = EasyExcel.write(out).build()) {
int pageSize = 500;
int pageNo = 1;
do {
Page<Staff> page = staffService.page(new Page<>(pageNo, pageSize));
writer.write(page.getRecords(),
EasyExcel.writerSheet("员工数据").head(Staff.class).build());
if (!page.hasNext()) break;
pageNo++;
} while (true);
}
}
- 前端采用Web Worker防止界面卡顿:
javascript复制const worker = new Worker('/static/export.worker.js');
worker.postMessage({ type: 'start_export' });
worker.onmessage = (e) => {
if (e.data.progress) {
updateProgress(e.data.progress);
}
};
5. 部署与运维实践
5.1 生产环境部署方案
推荐使用Docker Compose进行容器化部署:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
ports:
- "3306:3306"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/company?useSSL=false
frontend:
build: ./frontend
ports:
- "80:80"
5.2 性能监控配置
集成Spring Boot Actuator + Prometheus + Grafana监控体系:
- 添加依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
- 配置application.yml:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: ${spring.application.name}
- Grafana仪表盘关键指标:
- JVM内存使用率
- 数据库连接池活跃连接数
- HTTP请求成功率
- 接口响应时间P99
6. 项目扩展方向
在实际使用中,我们发现系统还可以在以下方面进行增强:
- 集成企业微信/钉钉对接:
java复制// 企业微信消息推送示例
public void sendWechatAlert(String userId, String content) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send";
Map<String, Object> body = new HashMap<>();
body.put("touser", userId);
body.put("msgtype", "text");
body.put("agentid", wechatAgentId);
body.put("text", Map.of("content", content));
restTemplate.postForObject(url, body, String.class);
}
- 添加审计日志功能:
java复制@Aspect
@Component
public class AuditLogAspect {
@Autowired
private AuditLogService logService;
@Around("@annotation(auditLog)")
public Object around(ProceedingJoinPoint pjp, AuditLog auditLog) throws Throwable {
long start = System.currentTimeMillis();
try {
Object result = pjp.proceed();
logService.saveLog(
getOperator(),
auditLog.value(),
System.currentTimeMillis() - start,
true);
return result;
} catch (Exception e) {
logService.saveLog(/*...*/);
throw e;
}
}
}
- 引入工作流引擎:
对于复杂的审批流程,可以集成Activiti或Flowable引擎,实现可视化流程设计。