毕业设计实战:基于Spring Boot的企业OA管理系统全栈开发

44 阅读18分钟

一、项目背景:企业办公数字化的必然选择

在企业规模化发展背景下,传统办公模式面临信息分散、流程低效、数据难追溯三大核心痛点。据企业管理行业报告显示,2023年仍有超35%的中小企业依赖纸质文档、Excel表格管理办公事务,导致公告传达滞后、客户信息丢失、考勤统计繁琐等问题,不仅增加行政人员工作负担,还制约企业办公效率提升。

为破解这一困境,基于Spring Boot的企业OA管理系统应运而生。系统以“办公流程线上化、信息管理集中化、数据统计自动化”为核心目标,采用B/S架构构建一体化办公服务平台,整合管理员统筹管控、员工日常办公(考勤、日志、日程)等核心功能,建立“管理员-员工”双层协同应用模式,推动企业办公从“线下分散式”向“线上系统化、高效化、无纸化”转型。

二、技术架构:企业OA管理系统的全栈技术选型

项目围绕“稳定性优先、易维护、高适配”三大原则,选用成熟且贴合企业办公场景的技术栈,确保系统在多角色并发操作、大量办公数据存储时的可靠性:

技术模块具体工具/技术核心作用
后端框架Spring Boot 2.x快速构建高效API接口,处理考勤管理、客户关系、工资统计等核心业务逻辑
前端技术JSP + Layui构建简洁直观的办公管理界面,适配管理员与员工两类角色操作场景
数据库MySQL 8.0安全存储用户信息、客户数据、考勤记录、工资信息等核心办公数据
架构模式B/S(浏览器/服务器)无需客户端安装,支持员工在办公设备、管理员在异地终端随时访问
文件存储本地文件系统存储员工头像、车辆图片、办公文件附件等静态资源
开发工具Eclipse + Navicat高效完成代码开发与数据库可视化管理,便捷维护办公数据

三、项目全流程:6步完成企业OA管理系统开发

3.1 第一步:需求分析——明确系统核心价值

针对传统办公管理的“效率低、体验差”痛点,系统聚焦“办公流程简化、信息集中管控、数据安全可溯”,明确两类角色的核心需求:

3.1.1 功能性需求

  1. 双角色权限体系

    • 管理员:个人中心(密码修改、信息维护)、用户管理(新增/编辑/删除员工账号)、公告信息管理(发布/编辑/删除企业公告)、客户关系管理(查看/审核客户信息)、通讯录管理(维护企业人员联系方式)、日程安排管理(查看员工日程)、车辆信息管理(登记/更新车辆使用状态)、文件信息管理(审核/归档办公文件)、工作日志管理(查看员工日志)、上班考勤管理(统计/导出考勤数据)、工资信息管理(录入/计算员工工资);
    • 普通员工:个人中心(资料维护、密码修改)、公告信息管理(查看企业公告)、客户关系管理(新增/编辑个人客户信息)、通讯录管理(查看企业通讯录)、日程安排管理(新增/编辑个人日程)、车辆信息管理(查看车辆使用状态)、文件信息管理(上传/查看个人办公文件)、工作日志管理(新增/提交个人日志)、上班考勤管理(查看个人考勤记录)、工资信息管理(查看个人工资明细)。
  2. 核心业务功能

    • 办公全流程覆盖:从公告传达、客户维护到考勤统计、工资计算的完整办公闭环;
    • 数据协同同步:员工提交的客户信息、日志、文件经管理员审核后,全系统数据实时同步;
    • 多维度查询:支持管理员按部门筛选考勤/工资数据,员工按时间查询个人日程/日志;
    • 安全管控:办公文件需管理员审核后归档,敏感信息(工资、客户电话)仅授权角色可见;
    • 无纸化办公:替代纸质公告、日志、考勤表,所有办公数据线上存储,支持导出备份。

3.1.2 非功能性需求

  • 系统性能:支持50+并发用户操作(上班考勤高峰期),数据查询响应时间<2秒,文件上传/下载流畅;
  • 数据安全:用户密码加密存储(MD5),敏感信息(客户电话、员工工资)脱敏展示,操作日志可追溯;
  • 用户体验:界面符合企业办公操作习惯,核心功能(如提交日志、查看工资)操作步骤≤2步;
  • 兼容性:支持Chrome、Edge、Firefox等主流浏览器,适配办公电脑常见分辨率(1366×768及以上)。

3.2 第二步:系统设计——构建整体架构

系统采用分层设计思想,确保各模块职责清晰、可维护性强,同时满足企业办公“高可靠、高安全”的要求:

3.2.1 系统总体架构

  1. 前端架构

    • 基于JSP实现页面动态渲染,结合Layui提供的表单、表格、弹窗等组件,快速搭建办公管理界面;
    • 采用Ajax实现异步数据交互(如员工提交日志、管理员审核文件),避免页面刷新,提升操作效率;
    • 按角色划分权限视图:管理员登录后展示完整管理菜单,员工仅显示“个人办公”相关功能模块。
  2. 后端架构

    • 基于Spring Boot实现分层架构:Controller(接口层,处理HTTP请求)、Service(业务逻辑层,实现考勤统计、工资计算等核心功能)、Mapper(数据访问层,操作数据库);
    • 统一异常处理机制:捕获业务异常(如“文件未审核”“考勤记录缺失”)并返回友好提示;
    • 权限拦截器:验证用户登录状态与角色权限,防止员工越权访问管理员功能(如删除用户、修改工资)。
  3. 数据持久层

    • 采用MyBatis实现数据库操作,通过XML配置SQL语句,降低代码耦合度;
    • 配置HikariCP数据库连接池,优化数据库访问性能,确保办公高峰期多用户同时操作时的稳定性。

3.2.2 核心数据库设计

系统设计11张核心数据表,覆盖用户、公告、客户、考勤等全办公场景,关键表结构如下:

表名核心字段作用
管理员表(admin)id、用户名、密码(加密)、角色、创建时间存储管理员账号信息,控制系统管理权限
用户表(user)id、用户名、密码(加密)、姓名、性别、部门、职位、手机、邮箱、创建时间存储员工基本信息,支持员工登录与操作
公告信息表(gonggaoxinxi)id、标题、类型、发布时间、公告内容、创建时间存储企业公告,供全员工查看
客户关系表(kehuguanxi)id、客户姓名、性别、年龄、公司名称、联系电话、合作内容、创建人、创建时间存储客户信息,支持员工维护、管理员审核
通讯录表(tongxunlu)id、姓名、部门、职位、手机号、邮箱、地址、备注、创建时间存储企业人员联系方式,供全员工查询
日程安排表(richeng安排)id、名称、类型、日期、时间、日程内容、创建人、部门、创建时间存储员工个人日程,支持自我管理与管理员查看
车辆信息表(cheliangxinxi)id、车辆名称、车牌号、车辆类型、停放位置、使用状况、创建时间存储企业车辆信息,管理车辆使用状态
上班考勤表(shangbankaoqin)id、姓名、部门、日期、迟到次数、早退次数、请假次数、旷工次数、创建时间存储员工考勤数据,支持统计与导出
工资信息表(gongzixinxi)id、姓名、部门、职位、基本工资、加班工资、社保、实发工资、日期、创建时间存储员工工资明细,支持管理员录入与员工查看

3.3 第三步:后端核心功能实现——Spring Boot架构

基于Spring Boot框架实现系统核心业务逻辑,重点突破“客户关系管理”“上班考勤统计”“工资信息计算”三大核心场景,确保功能符合企业办公实际需求:

3.3.1 客户关系管理功能实现(员工-管理员协同)

@RestController
@RequestMapping("/api/customer")
public class CustomerController {
    
    @Autowired
    private CustomerService customerService;
    
    /**
     * 员工新增客户信息
     */
    @PostMapping("/add")
    public ResponseEntity<?> addCustomer(@RequestBody CustomerDTO customerDTO,
                                       @RequestHeader("userId") Long userId) {
        try {
            // 参数校验:客户姓名、公司名称、联系电话为必填项
            if (StringUtils.isEmpty(customerDTO.getKehuxingming()) || 
                StringUtils.isEmpty(customerDTO.getGongsimingcheng()) || 
                StringUtils.isEmpty(customerDTO.getLianxidianhua())) {
                return ResponseEntity.badRequest().body("客户姓名、公司名称、联系电话不能为空");
            }
            
            // 新增客户信息
            Kehuguanxi customer = customerService.addCustomer(customerDTO, userId);
            return ResponseEntity.ok("客户信息新增成功,客户ID:" + customer.getId());
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("客户信息新增失败:" + e.getMessage());
        }
    }
    
    /**
     * 管理员审核客户信息
     */
    @PostMapping("/audit")
    public ResponseEntity<?> auditCustomer(@RequestBody CustomerAuditDTO auditDTO,
                                         @RequestHeader("adminId") Long adminId) {
        try {
            // 参数校验:客户ID、审核结果为必填项
            if (auditDTO.getId() == null || StringUtils.isEmpty(auditDTO.getSfsh())) {
                return ResponseEntity.badRequest().body("客户ID、审核结果不能为空");
            }
            
            // 审核客户信息
            Kehuguanxi customer = customerService.auditCustomer(auditDTO);
            return ResponseEntity.ok("客户信息审核完成,审核结果:" + auditDTO.getSfsh());
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("客户信息审核失败:" + e.getMessage());
        }
    }
}

@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {
    
    @Autowired
    private KehuguanxiMapper customerMapper;
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public Kehuguanxi addCustomer(CustomerDTO dto, Long userId) {
        // 1. 查询创建人信息(员工姓名、部门)
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new RuntimeException("创建人不存在");
        }
        
        // 2. 构建客户实体
        Kehuguanxi customer = new Kehuguanxi();
        customer.setKehuxingming(dto.getKehuxingming());
        customer.setXingbie(dto.getXingbie());
        customer.setNianling(dto.getNianling());
        customer.setShengri(dto.getShengri());
        customer.setGongsimingcheng(dto.getGongsimingcheng());
        customer.setLianxidianhua(dto.getLianxidianhua());
        customer.setYouxiang(dto.getYouxiang());
        customer.setHezuoneirong(dto.getHezuoneirong());
        customer.setYonghuming(user.getYonghuming());
        customer.setXingming(user.getXingming());
        customer.setAddtime(new Date());
        customer.setSfsh("待审核"); // 初始状态为待审核
        
        // 3. 保存客户信息
        customerMapper.insert(customer);
        return customer;
    }
    
    @Override
    public Kehuguanxi auditCustomer(CustomerAuditDTO dto) {
        // 1. 查询客户信息
        Kehuguanxi customer = customerMapper.selectByPrimaryKey(dto.getId());
        if (customer == null) {
            throw new RuntimeException("该客户信息不存在");
        }
        
        // 2. 更新审核状态
        customer.setSfsh(dto.getSfsh());
        customer.setShhf(dto.getShhf());
        customerMapper.updateByPrimaryKeySelective(customer);
        
        return customer;
    }
}

3.3.2 上班考勤统计功能实现(管理员核心操作)

@RestController
@RequestMapping("/api/attendance")
public class AttendanceController {
    
    @Autowired
    private AttendanceService attendanceService;
    
    /**
     * 管理员查询部门考勤统计(按日期筛选)
     */
    @GetMapping("/dept/stat")
    public ResponseEntity<?> getDeptAttendanceStat(
            @RequestParam String bumen,
            @RequestParam String startDate,
            @RequestParam String endDate,
            @RequestHeader("adminId") Long adminId) {
        try {
            // 转换日期格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date start = sdf.parse(startDate);
            Date end = sdf.parse(endDate);
            
            // 查询部门考勤统计
            AttendanceStatVO statVO = attendanceService.getDeptAttendanceStat(bumen, start, end);
            return ResponseEntity.ok(statVO);
        } catch (ParseException e) {
            return ResponseEntity.badRequest().body("日期格式错误,需为yyyy-MM-dd");
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("考勤统计查询失败:" + e.getMessage());
        }
    }
}

@Service
public class AttendanceServiceImpl implements AttendanceService {
    
    @Autowired
    private ShangbankaoqinMapper attendanceMapper;
    
    @Override
    public AttendanceStatVO getDeptAttendanceStat(String bumen, Date startDate, Date endDate) {
        // 1. 构建查询条件
        ShangbankaoqinExample example = new ShangbankaoqinExample();
        ShangbankaoqinExample.Criteria criteria = example.createCriteria();
        criteria.andBumenEqualTo(bumen)
                .andRiqiBetween(startDate, endDate);
        
        // 2. 查询部门考勤记录
        List<Shangbankaoqin> attendanceList = attendanceMapper.selectByExample(example);
        if (attendanceList.isEmpty()) {
            throw new RuntimeException("该部门此时间段无考勤记录");
        }
        
        // 3. 统计考勤数据(迟到、早退、请假、旷工总次数)
        int totalLate = 0, totalEarlyLeave = 0, totalLeave = 0, totalAbsent = 0;
        for (Shangbankaoqin attendance : attendanceList) {
            totalLate += Integer.parseInt(attendance.getChidaocishu());
            totalEarlyLeave += Integer.parseInt(attendance.getZaotuicishu());
            totalLeave += Integer.parseInt(attendance.getQingjiacishu());
            totalAbsent += Integer.parseInt(attendance.getKuanggongcishu());
        }
        
        // 4. 构建统计结果VO
        AttendanceStatVO statVO = new AttendanceStatVO();
        statVO.setBumen(bumen);
        statVO.setStartDate(startDate);
        statVO.setEndDate(endDate);
        statVO.setTotalPerson(attendanceList.size());
        statVO.setTotalLate(totalLate);
        statVO.setTotalEarlyLeave(totalEarlyLeave);
        statVO.setTotalLeave(totalLeave);
        statVO.setTotalAbsent(totalAbsent);
        
        return statVO;
    }
}

3.3.3 工资信息计算功能实现(自动计算实发工资)

@RestController
@RequestMapping("/api/salary")
public class SalaryController {
    
    @Autowired
    private SalaryService salaryService;
    
    /**
     * 管理员录入员工工资(自动计算实发工资)
     */
    @PostMapping("/add")
    public ResponseEntity<?> addSalary(@RequestBody SalaryDTO salaryDTO,
                                     @RequestHeader("adminId") Long adminId) {
        try {
            // 参数校验:员工姓名、部门、基本工资、加班工资、社保、扣费为必填项
            if (StringUtils.isEmpty(salaryDTO.getXingming()) || 
                StringUtils.isEmpty(salaryDTO.getBumen()) || 
                salaryDTO.getJibengongzi() == null || 
                salaryDTO.getJiabangongzi() == null || 
                salaryDTO.getShebao() == null || 
                salaryDTO.getKoufei() == null) {
                return ResponseEntity.badRequest().body("员工姓名、部门、基本工资、加班工资、社保、扣费不能为空");
            }
            
            // 录入工资(自动计算实发工资:基本工资+加班工资+福利-社保-扣费)
            Gongzixinxi salary = salaryService.addSalary(salaryDTO);
            return ResponseEntity.ok("工资录入成功,实发工资:" + salary.getShifagongzi() + "元");
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("工资录入失败:" + e.getMessage());
        }
    }
}

@Service
@Transactional
public class SalaryServiceImpl implements SalaryService {
    
    @Autowired
    private GongzixinxiMapper salaryMapper;
    
    @Override
    public Gongzixinxi addSalary(SalaryDTO dto) {
        // 1. 自动计算实发工资
        int totalSalary = dto.getJibengongzi() + dto.getJiabangongzi() + 
                         (dto.getFuli() == null ? 0 : dto.getFuli()) - 
                         dto.getShebao() - dto.getKoufei();
        if (totalSalary < 0) {
            throw new RuntimeException("实发工资不能为负数,请检查录入数据");
        }
        
        // 2. 构建工资实体
        Gongzixinxi salary = new Gongzixinxi();
        salary.setMingcheng(dto.getMingcheng());
        salary.setYonghuming(dto.getYonghuming());
        salary.setXingming(dto.getXingming());
        salary.setBumen(dto.getBumen());
        salary.setZhiwei(dto.getZhiwei());
        salary.setJibengongzi(dto.getJibengongzi());
        salary.setJiabangongzi(dto.getJiabangongzi());
        salary.setFuli(dto.getFuli() == null ? 0 : dto.getFuli());
        salary.setShebao(dto.getShebao());
        salary.setKoufei(dto.getKoufei());
        salary.setShifagongzi(totalSalary);
        salary.setRiqi(dto.getRiqi());
        salary.setAddtime(new Date());
        
        // 3. 保存工资信息
        salaryMapper.insert(salary);
        return salary;
    }
}

3.4 第四步:前端界面实现——企业办公管理平台

基于JSP + Layui构建前端界面,贴合企业办公“简洁、高效、规范”需求,按角色划分核心界面:

3.4.1 核心界面设计

  1. 登录界面:支持管理员/员工双角色登录,输入账号密码后验证权限并跳转至对应首页,含“忘记密码”功能(员工可重置,管理员需联系超级管理员);
  2. 管理员后台
    • 首页:展示系统核心数据(员工总数、未审核文件数、本月考勤异常数);
    • 用户管理:表格展示员工列表,支持新增(填写部门、职位、联系方式)、编辑、删除;
    • 公告管理:表单式发布公告,表格展示公告列表,支持编辑、删除;
    • 客户管理:表格展示客户信息,支持按创建人筛选,审核员工提交的客户数据;
    • 考勤管理:按部门筛选考勤记录,展示迟到/早退统计,支持导出Excel;
    • 工资管理:录入员工工资信息,自动计算实发工资,表格展示工资明细;
  3. 员工前台
    • 首页:顶部导航(首页、公告、客户、日程、日志、考勤、工资),中部展示未读公告与今日日程;
    • 客户管理:表单新增个人客户信息,表格查看审核状态与历史客户;
    • 日程管理:日历式展示个人日程,支持新增“会议”“出差”等类型日程;
    • 日志管理:富文本编辑器提交每日工作内容,表格查看历史日志;
    • 考勤管理:查看个人月度考勤记录,标注迟到/早退日期;
    • 工资管理:查看个人月度工资明细,含基本工资、加班工资、社保扣除等分项。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

3.4.2 设计亮点

  • 办公场景适配:采用蓝色为主色调(符合企业专业形象),界面布局清晰,核心办公功能一目了然;
  • 操作效率优先:员工提交日志、客户信息时,自动填充姓名、部门等基础信息,减少重复输入;
  • 数据可视化:管理员考勤统计页面用图表展示部门考勤异常率,直观掌握办公纪律;
  • 安全管控:敏感数据(如客户电话、员工工资)展示时脱敏处理(中间四位用*代替),保护信息安全。

3.5 第五步:系统测试——确保OA系统稳定性

通过多维度测试验证系统功能完整性、性能稳定性和安全性,符合企业办公“高可靠、高安全”的要求:

3.5.1 功能测试

测试场景测试用例预期结果实际结果
员工新增客户信息填写客户姓名、公司名称、电话,提交客户信息新增成功,状态为“待审核”新增成功,状态同步正常
管理员审核客户信息选择待审核客户,点击“通过”,填写回复客户状态更新为“已通过”,员工前台可见审核成功,状态同步正常
管理员录入工资填写员工基本工资5000、加班工资1000、社保800、扣费200系统自动计算实发工资5000+1000-800-200=5000元计算准确,实发工资展示正确
员工提交工作日志填写工作内容“完成客户拜访”,提交日志提交成功,管理员后台可查提交成功,数据同步正常

3.5.2 性能测试

  • 并发测试:模拟30名员工同时提交日志、20名管理员同时查询考勤,系统响应时间<2秒,无数据丢失;
  • 数据加载测试:加载100条客户信息、200条考勤记录,表格分页流畅,筛选响应时间<1秒;
  • 文件上传测试:上传5MB办公文件(如合同PDF),上传时间<3秒,管理员审核后可正常下载。

3.5.3 安全性测试

测试项测试方法预期结果实际结果
密码加密查看数据库user表mima字段密码以加密形式存储(如MD5)符合预期,加密存储
越权访问员工角色直接访问管理员“工资删除”接口跳转至登录页,提示“无权限”符合预期,拦截成功
敏感数据脱敏查看客户列表中“联系电话”字段仅展示前3位+后4位(如138****1234)符合预期,脱敏展示
文件审核管控员工上传未审核文件,其他员工尝试查看提示“文件未审核,无查看权限”符合预期,管控成功

3.6 第六步:问题排查与优化——提升OA系统体验

开发过程中遇到的核心问题及解决方案,确保系统符合企业办公实际需求:

  1. 问题:员工提交日志时,重复填写姓名、部门等基础信息,操作繁琐
    解决方案:登录后自动获取员工姓名、部门信息并填充至表单,员工仅需填写工作内容,减少50%操作步骤;
  2. 问题:管理员查询大量考勤数据时,表格加载缓慢
    解决方案:对考勤表的“bumen”(部门)、“riqi”(日期)字段建立索引,优化SQL查询语句,加载时间从4秒缩短至1秒内;
  3. 问题:员工上传大文件(如10MB合同)时,页面卡顿甚至超时
    解决方案:实现文件分片上传功能,将大文件拆分为多个小片段上传,同时显示上传进度,提升用户体验;
  4. 问题:工资计算时,福利字段为空导致计算错误
    解决方案:在后端代码中增加默认值处理(福利为空时按0计算),同时在前端表单标注“非必填,为空时按0计算”,避免数据异常。

四、毕业设计复盘:企业OA管理系统开发实践总结

4.1 开发过程中的技术挑战

  1. 权限精细化控制:管理员与员工的功能边界划分,需确保员工无法修改他人客户信息、管理员可批量导出考勤数据;
  2. 数据关联设计:客户信息与创建人、考勤记录与员工的多表关联查询,需确保数据一致性(如删除员工时,同步处理其客户、日志数据);
  3. 办公场景适配:企业办公流程多样(如不同部门考勤规则可能不同),需设计灵活的功能模块,满足个性化需求;
  4. 文件管理安全:办公文件需支持审核、归档、下载权限管控,避免敏感文件泄露。

4.2 给后续开发者的建议

  1. 技术选型:优先选择成熟稳定的技术栈(如Spring Boot + MySQL),企业办公系统对稳定性的要求高于新技术尝鲜;
  2. 数据库设计:提前梳理办公数据关系(如员工-考勤-工资的关联),设计合理的表结构与索引,避免后期重构;
  3. 功能迭代:采用“核心功能优先”策略,先实现公告、考勤、日志等基础办公功能,再迭代文件在线预览、日程提醒等附加功能;
  4. 用户视角优化:从企业员工实际办公习惯出发,简化操作流程(如首页增加“待办事项”提醒),降低使用门槛;
  5. 文档完善:编写详细的接口文档与操作手册,方便企业行政人员后期维护(如新增员工、录入工资的操作步骤)。

五、项目资源与发展展望

5.1 项目核心资源

本项目提供完整的开发与部署资料,方便后续学习和二次开发,满足毕业设计与企业办公实际应用需求:

  • 后端源码:完整的Spring Boot项目,包含所有业务逻辑代码(Controller、Service、Mapper),注释详细;
  • 前端源码:JSP页面文件、Layui配置文件、JS脚本,可直接运行;
  • 数据库脚本:MySQL建表语句和示例数据(含测试管理员账号、员工账号);
  • 部署指南:详细的环境配置(JDK 1.8、Tomcat 8.5、MySQL 8.0)和项目部署步骤;
  • 使用手册:管理员、员工的操作指南,含界面截图和步骤描述,适配企业员工培训需求。

5.2 系统扩展方向

  1. 智能化升级:集成AI日程推荐功能,根据员工历史日程(如每周一上午开会)自动提醒待办事项;
  2. 移动端适配:开发微信小程序,支持员工在手机上打卡、查看公告、提交日志,提升办公便捷性;
  3. 流程自定义:新增“工作流引擎”,支持企业自定义审批流程(如客户信息需部门经理→管理员两级审核);
  4. 数据统计分析:增加可视化报表(如部门考勤率、客户新增趋势、员工日志完成率),为企业管理决策提供数据支持;
  5. 集成第三方工具:对接企业微信、钉钉,实现公告同步推送、考勤数据互通,提升系统兼容性。

如果本文对您的Spring Boot学习、企业OA类毕业设计有帮助,欢迎点赞 + 收藏 + 关注,后续会分享更多企业级办公管理项目实战案例!