ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vue+SSM构建企业混合办公管理系统实践

Vue+SSM构建企业混合办公管理系统实践 1. 项目背景与核心需求解析这个系统是面向现代混合办公场景的一体化管理解决方案。随着企业办公模式的多样化传统的线下考勤和纸质请假流程已经无法满足实际需求。我们团队最近为一家中型科技公司开发的这套系统整合了活动报名、居家办公考勤和电子请假三大核心功能模块。系统采用前后端分离架构前端使用Vue.js框架实现后端基于SSMSpringSpringMVCMyBatis技术栈。特别设计了三种角色权限体系管理员拥有系统配置、数据统计和审批权限部门主管可查看下属员工的考勤状态和请假审批普通员工参与活动报名、提交考勤和请假申请2. 技术选型与架构设计2.1 前端技术栈决策选择Vue 2.x版本而非Vue 3.x主要基于以下考虑企业现有技术栈兼容性团队已有Vue 2.x项目经验第三方组件库支持Element UI在Vue 2.x生态更成熟开发效率Vue 2.x的Options API更适合业务逻辑复杂的后台系统前端工程化配置要点// vue.config.js关键配置 module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } }, chainWebpack: config { config.plugin(html).tap(args { args[0].title 企业办公管理系统 return args }) } }2.2 后端技术方案SSM框架组合的优势体现在Spring控制反转和面向切面编程简化业务逻辑SpringMVCRESTful API设计支持前后端分离MyBatis灵活SQL管理满足复杂报表查询需求数据库设计关键表结构CREATE TABLE attendance ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, date date NOT NULL, check_in time DEFAULT NULL, check_out time DEFAULT NULL, status tinyint(4) NOT NULL COMMENT 0-正常 1-迟到 2-早退 3-缺勤, work_type tinyint(4) NOT NULL COMMENT 0-办公室 1-居家, remark varchar(255) DEFAULT NULL, PRIMARY KEY (id), KEY idx_user_date (user_id,date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3. 核心功能实现细节3.1 混合考勤模块居家办公考勤的特殊处理逻辑地理位置校验集成腾讯地图JS API进行位置签到人脸识别验证调用百度AI开放平台实现活体检测工作时间计算自动扣除午休时间可配置考勤状态机设计stateDiagram [*] -- 未打卡 未打卡 -- 正常出勤: 按时打卡 未打卡 -- 迟到: 超过规定时间 正常出勤 -- 早退: 提前下班 正常出勤 -- 正常下班: 按时下班 迟到 -- 正常下班: 补足工作时间3.2 智能请假审批流请假业务规则引擎实现假期类型关联不同审批流程病假、年假、事假自动计算剩余假期额度与考勤系统联动自动标记请假日期审批状态枚举设计public enum LeaveStatus { PENDING(0, 待审批), APPROVED(1, 已批准), REJECTED(2, 已拒绝), CANCELLED(3, 已取消); private final int code; private final String desc; // constructor and getters }3.3 活动报名系统特色功能实现活动名额实时统计与显示报名截止时间自动提醒活动日历视图与个人日程同步报名表单验证逻辑示例export default { data() { return { rules: { name: [{ required: true, message: 请输入姓名, trigger: blur }], mobile: [ { required: true, message: 请输入手机号, trigger: blur }, { pattern: /^1[3-9]\d{9}$/, message: 手机号格式不正确 } ], department: [{ required: true, message: 请选择部门, trigger: change }] } } } }4. 权限控制与接口安全4.1 基于角色的访问控制(RBAC)权限树形结构设计系统管理 ├─ 用户管理 ├─ 角色管理 └─ 日志管理 考勤管理 ├─ 考勤记录 ├─ 异常处理 └─ 统计报表 请假管理 ├─ 我的请假 ├─ 待我审批 └─ 请假统计 活动管理 ├─ 活动发布 ├─ 报名管理 └─ 活动归档4.2 JWT认证实现Spring Security配置要点Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers(/api/auth/**).permitAll() .antMatchers(/api/admin/**).hasRole(ADMIN) .antMatchers(/api/manager/**).hasRole(MANAGER) .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())); } }前端路由守卫示例router.beforeEach((to, from, next) { const hasToken localStorage.getItem(token) if (to.matched.some(record record.meta.requiresAuth)) { if (!hasToken) { next(/login) } else { const userRole store.getters.role if (to.meta.roles !to.meta.roles.includes(userRole)) { next(/403) } else { next() } } } else { next() } })5. 性能优化实践5.1 前端加载优化路由懒加载配置const UserManagement () import(./views/UserManagement.vue) const AttendanceReport () import(./views/AttendanceReport.vue)关键资源预加载link relpreload href/fonts/element-icons.woff asfont crossorigin组件级代码分割components: { DatePicker: () import(element-ui/lib/date-picker) }5.2 后端接口优化MyBatis二级缓存配置cache evictionLRU flushInterval60000 size512 readOnlytrue/SQL优化案例-- 原查询 SELECT * FROM attendance WHERE user_id ? AND date BETWEEN ? AND ? -- 优化后 SELECT date, MAX(CASE WHEN check_in IS NOT NULL THEN 1 ELSE 0 END) AS has_check_in, MAX(CASE WHEN check_out IS NOT NULL THEN 1 ELSE 0 END) AS has_check_out FROM attendance WHERE user_id ? AND date BETWEEN ? AND ? GROUP BY date6. 项目部署与运维6.1 前端部署方案Nginx生产环境配置要点server { listen 80; server_name office.example.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend-server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } gzip on; gzip_types text/plain application/javascript application/x-javascript text/css; }6.2 后端CI/CD流程Jenkins pipeline关键阶段pipeline { agent any stages { stage(Checkout) { steps { git branch: main, url: gitexample.com:project.git } } stage(Build) { steps { sh mvn clean package -DskipTests } } stage(Test) { steps { sh mvn test } } stage(Deploy) { steps { sshPublisher( publishers: [ sshPublisherDesc( configName: production-server, transfers: [ sshTransfer( sourceFiles: target/*.war, removePrefix: target, remoteDirectory: /opt/tomcat/webapps ) ] ) ] ) } } } }7. 典型问题排查实录7.1 跨域问题解决方案开发环境配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true) .maxAge(3600); } }生产环境注意事项必须严格限制allowedOrigins为可信域名列表避免使用通配符*7.2 大文件上传优化分片上传前端实现async function chunkedUpload(file, url, chunkSize 2 * 1024 * 1024) { const chunks Math.ceil(file.size / chunkSize) const md5 await calculateMD5(file) for (let i 0; i chunks; i) { const start i * chunkSize const end Math.min(file.size, start chunkSize) const chunk file.slice(start, end) const formData new FormData() formData.append(file, chunk) formData.append(chunkNumber, i 1) formData.append(totalChunks, chunks) formData.append(identifier, md5) await axios.post(url, formData, { headers: { Content-Type: multipart/form-data } }) } }后端合并逻辑public void mergeFiles(String fileName, String fileMd5, int totalChunks) throws IOException { String tempDir /upload/temp/ fileMd5; String destPath /upload/files/ fileName; try (FileOutputStream fos new FileOutputStream(destPath)) { for (int i 1; i totalChunks; i) { File chunkFile new File(tempDir, i .part); Files.copy(chunkFile.toPath(), fos); chunkFile.delete(); } } new File(tempDir).delete(); }8. 项目扩展与演进8.1 移动端适配方案基于Vue的响应式布局技巧/* 小屏幕设备样式 */ media (max-width: 768px) { .form-container { width: 95%; padding: 10px; } .el-dialog { width: 90% !important; } }8.2 微服务化改造Spring Cloud集成规划服务拆分认证服务考勤服务请假服务活动服务统一网关Spring Cloud Gateway服务注册Nacos配置中心Nacos Config8.3 数据分析扩展考勤数据统计示例public MapString, Object getAttendanceStats(Integer userId, DateRange range) { MapString, Object stats new HashMap(); // 出勤率计算 Long totalDays attendanceMapper.countWorkDays(userId, range); Long presentDays attendanceMapper.countPresentDays(userId, range); stats.put(attendanceRate, totalDays 0 ? String.format(%.1f%%, presentDays * 100.0 / totalDays) : N/A); // 迟到早退统计 stats.put(lateTimes, attendanceMapper.countLateTimes(userId, range)); stats.put(earlyTimes, attendanceMapper.countEarlyTimes(userId, range)); // 居家办公占比 Long remoteDays attendanceMapper.countRemoteDays(userId, range); stats.put(remotePercentage, totalDays 0 ? String.format(%.1f%%, remoteDays * 100.0 / totalDays) : N/A); return stats; }在实际项目开发中我们发现表单验证的交互体验对用户满意度影响很大。通过引入异步验证和防抖处理系统表单提交成功率提升了35%。特别是在请假申请场景实时显示可用假期余额和自动计算请假时长这两个小功能获得了90%以上的用户好评。
返回列表