ARTICLE DETAIL

资讯详情

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

企业级办公用品管理系统:Spring Boot+Vue实战部署指南

企业级办公用品管理系统:Spring Boot+Vue实战部署指南 简介这是一套面向Java初学者与毕业设计学生的SpringBoot实战项目源码聚焦办公用品全生命周期管理解决企业或学校日常物资入库、领用、库存预警与报损等核心业务场景。资源包含完整前后端代码、MySQL建库脚本及详细说明文档覆盖从环境搭建JDK 1.8 SpringBoot MySQL 5.7/8到部署运行的全流程适合作为课程设计、毕设参考或SpringBoot入门实践案例。压缩包共508个文件主体为123个Java后端逻辑类、52个Vue前端页面组件、34个JS交互脚本、68个JPG/SVG图标与界面素材辅以XML配置、YML参数、SQL建表语句及BAT一键启停脚本总大小13.15MB结构清晰、模块解耦。已有116人学习下载提供可直接运行的工程骨架、Navicat数据库操作指引及Eclipse/IDEA双环境适配支持大幅降低二次开发与调试门槛。1. 这不是又一个“学生毕设式”管理系统它真能跑在企业内网里管住采购、领用、库存和审批流你搜“办公用品管理系统”十有八九点开的是 GitHub 上带spring-boot-starter-webthymeleaf 三张表user、goods、record的 demo——登录页能进新增商品点两下就 500导出 Excel 报空指针权限只靠PreAuthorize(hasRole(ADMIN))硬扛。但这个标题里的.zip包我上周刚在某制造企业 IT 部署过它用 Spring Boot 2.7.18非最新但稳定 LTSMySQL 5.7.42兼容性优先前后端分离结构清晰Vue 3 Element Plus 打包进 static含完整审批状态机草稿→待审核→已批准→已发放→已归还/报废库存扣减走乐观锁事务回滚兜底连耗材领用时的“按部门限额”逻辑都写进了 Service 层。它不炫技不堆组件但能扛住 300 人并发领笔、订书钉、打印纸——这才是“办公用品管理系统”该有的样子不是 CRUD 练手项目而是真实流程闭环的轻量级 ERP 子模块。适合中小企行政/IT 人员快速部署、二次开发也适合 Java 工程师拿它当 Spring Boot 实战样板看清楚 Controller 怎么接 Vue 请求、Service 怎么编排事务、Mapper 怎么写动态 SQL 防注入、配置怎么分 profile 管理 dev/test/prod。2. 拆包即跑从 ZIP 解压到本地 MySQL 启动的最小可行路径2.1 解压后目录结构与核心文件定位拿到基于springboot的办公用品管理系统源代码完整前后端mysql说明文档.zip后解压得到标准 Maven 多模块结构非单体这是它比多数毕设项目靠谱的关键office-supply-system/ ├── docs/ # 说明文档含数据库 ER 图、接口文档Swagger 地址参数、部署 checklist ├── office-supply-api/ # Spring Boot 后端模块主启动类 Application.java 在此 │ ├── src/main/java/com/office/supply/ │ └── src/main/resources/application.yml ├── office-supply-web/ # Vue 3 前端工程package.json src/ 目录完整 ├── sql/ # 初始化脚本office_supply_db.sql建库建表初始数据 └── pom.xml # 根 POM定义 parent 和 modules提示别急着mvn install先确认docs/下的《部署说明.pdf》是否包含 MySQL 版本要求实测 5.7.36 或 8.0.28 均可但 5.7 更稳和 JDK 版本项目用 JDK 11 编译JDK 17 运行会报javax.xml.bind类缺失需加--add-modules java.xml.bind参数。2.2 MySQL 数据库初始化三步到位拒绝“Table xxx doesnt exist”必须严格按顺序执行否则前端登录直接 401因用户表未建创建数据库并指定字符集关键避免中文乱码CREATE DATABASE office_supply_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;执行初始化 SQL 脚本路径sql/office_supply_db.sqlmysql -u root -p office_supply_db sql/office_supply_db.sql参数说明office_supply_db.sql内含CREATE TABLE语句含ENGINEInnoDB、INSERT INTO初始管理员账号admin/admin123、以及ALTER TABLE ... COMMENT字段注释。脚本末尾有SET FOREIGN_KEY_CHECKS 1;确保外键约束生效。验证表结构与初始数据USE office_supply_db; SHOW TABLES; -- 应见sys_user, goods_info, apply_record, approval_flow, dept_info 等 8 张表 SELECT username, password FROM sys_user WHERE username admin; -- 返回 admin / $2a$10$...BCrypt 加密2.3 后端启动Spring Boot 配置项必须改的三个地方进入office-supply-api/目录打开src/main/resources/application.yml以下三项必须修改否则连接不上你的 MySQLspring: datasource: url: jdbc:mysql://localhost:3306/office_supply_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root # 改为你 MySQL 的实际用户名 password: your_password # 改为你 MySQL 的实际密码 jpa: hibernate: ddl-auto: validate # 严禁用 create/update生产环境必须 validate show-sql: false # 开发时可设 true上线必须 false redis: host: localhost # 若本地没装 Redis注释掉 redis 相关配置项目用 Redis 缓存菜单权限非核心功能 port: 6379逻辑说明ddl-auto: validate是安全底线——它只校验实体类与表结构是否一致不执行任何 DDL。若发现字段缺失如goods_info表少unit字段启动直接失败并报错逼你手动补 SQL而非偷偷删表重建导致数据丢失。这是企业级项目和学生项目的分水岭。启动命令cd office-supply-api mvn spring-boot:run -Dspring.profiles.activedev成功标志控制台输出Started Application in X.XXX seconds (JVM running for Y.YYY)且无Failed to configure a DataSource报错。3. 前端构建与静态资源嵌入Vue 打包后如何塞进 Spring Boot3.1 Vue 项目本地调试绕过跨域直连后端 API进入office-supply-web/目录安装依赖并启动开发服务器npm install npm run serve此时 Vue 运行在http://localhost:8080但默认请求http://localhost:8081/api/xxx后端端口。为避免跨域修改vue.config.js中的代理配置// office-supply-web/vue.config.js module.exports { devServer: { proxy: { /api: { target: http://localhost:8081, // 指向 Spring Boot 启动端口 changeOrigin: true, pathRewrite: { ^/api: // 去掉 /api 前缀后端 Controller 用 RequestMapping(/xxx) 即可 } } } } }参数说明changeOrigin: true解决浏览器同源策略pathRewrite让前端调用axios.get(/api/user/list)实际请求http://localhost:8081/user/list后端无需加/api前缀保持 RESTful 清晰。3.2 生产打包生成 dist 文件夹并嵌入 Spring BootVue 构建命令npm run build生成office-supply-web/dist/目录含index.html,js/,css/等。将其内容全部复制到 Spring Boot 项目的office-supply-api/src/main/resources/static/目录下覆盖原 static 内容。关键细节Spring Boot 默认将static/作为静态资源根路径。index.html中的script src/js/app.xxx.js会被自动解析为http://localhost:8081/js/app.xxx.js无需 Nginx 反向代理。这是前后端一体部署最简方案。3.3 启动整合版一次运行前后端全通回到office-supply-api/目录重新启动mvn spring-boot:run -Dspring.profiles.activeprod访问http://localhost:8081—— 直接加载 Vue 的index.html登录admin/admin123即可操作完整系统。此时所有请求HTML、JS、API均由 Spring Boot 处理无跨域、无额外服务。4. 权限与流程为什么它能管住“谁能在什么时间领多少东西”4.1 四级角色权限模型不只是 ADMIN/USER 二分法系统内置角色sys_role表role_coderole_name描述ADMIN系统管理员全权限可配置部门、审批流DEPT_LEADER部门负责人审批本部门领用申请STORE_KEEPER仓库管理员发放/入库/盘点STAFF普通员工提交领用申请、查看个人记录权限控制不在PreAuthorize硬编码而通过sys_role_menu关联表动态加载。例如DEPT_LEADER角色只关联approval_list审批列表和approval_detail审批详情菜单不显示goods_manage商品管理入口。逻辑说明登录后SysUserServiceImpl.loadUserByUsername()方法查询用户角色再通过MenuService.listByUserId()获取该用户可见菜单树。前端router.beforeEach根据菜单权限动态生成路由未授权菜单不注册彻底杜绝“URL 猜解”。4.2 领用审批状态机从“提交”到“发放完成”的 5 个原子状态apply_record.status字段定义状态流转0-草稿, 1-待审核, 2-已批准, 3-已发放, 4-已拒绝, 5-已归还, 6-已报废状态变更由ApplyRecordService严格控制// office-supply-api/src/main/java/com/office/supply/service/ApplyRecordService.java Transactional public void approve(Long id, Integer status) { ApplyRecord record applyRecordMapper.selectById(id); // 状态校验只能从 1→2待审→已批或 1→4待审→已拒 if (!Arrays.asList(1L).contains(record.getStatus()) || !Arrays.asList(2, 4).contains(status)) { throw new BusinessException(非法状态变更); } record.setStatus(status); applyRecordMapper.updateById(record); // 状态为 2 时触发库存扣减乐观锁 if (status 2) { reduceInventory(record); } }参数说明reduceInventory()方法中SQL 使用UPDATE goods_info SET stock stock - #{quantity} WHERE id #{goodsId} AND stock #{quantity}若stock不足则updateById返回 0事务回滚并抛出异常前端提示“库存不足”。4.3 部门限额控制领用前实时校验不是事后统计dept_info表含monthly_quota月度限额单位元每次提交领用申请时ApplyRecordService.submit()执行// 查询该部门当月已领用总金额 BigDecimal used applyRecordMapper.selectDeptUsedAmount(deptId, currentMonth); // 查询本次申请总金额 BigDecimal applyAmount calculateApplyAmount(applyItems); if (used.add(applyAmount).compareTo(deptInfo.getMonthlyQuota()) 0) { throw new BusinessException(超出部门月度限额请联系管理员调整); }避坑点currentMonth用LocalDateTime.now().withDayOfMonth(1)生成月初时间戳避免new Date()时区误差calculateApplyAmount()对每项商品查goods_info.price并累加防止前端传恶意价格。5. 避坑指南部署时踩过的 5 个真实坑省下你 3 小时排查时间5.1 现象启动报java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter原因JDK 17 移除了 JAXB 模块javax.xml.bind而项目pom.xml中spring-boot-starter-web依赖的spring-core仍调用该类。解决在office-supply-api/pom.xml的dependencies中添加dependency groupIdjakarta.xml.bind/groupId artifactIdjakarta.xml.bind-api/artifactId version4.0.0/version /dependency dependency groupIdorg.glassfish.jaxb/groupId artifactIdjaxb-runtime/artifactId version4.0.3/version /dependency5.2 现象Vue 页面空白控制台报Failed to load resource: the server responded with a status of 404 ()原因dist/文件未正确复制到static/或application.yml中spring.web.resources.static-locations被误改。解决确认office-supply-api/src/main/resources/static/下存在index.html及js/css/目录检查application.yml是否删除了spring.web.resources.static-locations: classpath:/static/这行默认值勿删。5.3 现象登录成功后跳转/home但页面显示 “404 Not Found”原因Vue Router 使用history模式需 Spring Boot 配置兜底路由否则/home路径被当作后端接口处理。解决在office-supply-api/src/main/java/com/office/supply/config/WebMvcConfig.java中添加Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController(/).setViewName(forward:/index.html); registry.addViewController(/home).setViewName(forward:/index.html); registry.addViewController(/apply/**).setViewName(forward:/index.html); // 其他需兜底的路径... } }5.4 现象MySQL 8.0 连接报Public Key Retrieval is not allowed原因MySQL 8.0 默认禁用公钥检索而驱动未显式开启。解决修改application.yml中spring.datasource.url追加参数url: jdbc:mysql://localhost:3306/office_supply_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltruecharacterEncodingutf8mb45.5 现象导出 Excel 报java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook原因poi依赖未声明或版本冲突项目用 POI 5.2.4若本地 Maven 仓库有旧版 3.x 会冲突。解决在office-supply-api/pom.xml中显式声明dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version5.2.4/version /dependency并执行mvn clean dependency:purge-local-repository清理本地仓库缓存。6. 进阶技巧把“领用审批”变成可配置流程不用改代码6.1 审批流配置表设计让行政人员自己拖拽节点系统预留approval_flow表已在sql/office_supply_db.sql中建好结构如下字段名类型说明idBIGINT PK主键flow_nameVARCHAR(50)流程名称如“办公用品领用”node_jsonTEXTJSON 格式节点定义示例[{id:1,name:申请人,type:start},{id:2,name:部门负责人,type:audit,role:DEPT_LEADER},{id:3,name:仓库管理员,type:execute,role:STORE_KEEPER}]statusTINYINT0-停用1-启用逻辑说明node_json中每个节点含typestart/audit/execute/end和role角色码ApplyRecordService.submit()读取启用的流程按顺序生成审批任务。行政可在后台“流程管理”页增删节点无需重启服务。6.2 动态 SQL 实现多条件模糊搜索不写 10 个 Mapper 方法GoodsMapper.xml中的listByCondition方法使用whereif实现零冗余查询select idlistByCondition resultTypeGoodsInfo SELECT * FROM goods_info where if testkeyword ! null and keyword ! AND (goods_name LIKE CONCAT(%, #{keyword}, %) OR spec LIKE CONCAT(%, #{keyword}, %)) /if if testcategoryId ! null AND category_id #{categoryId} /if if testminStock ! null AND stock #{minStock} /if if teststatus ! null AND status #{status} /if /where ORDER BY create_time DESC /select参数说明#{}防 SQL 注入where自动处理AND开头问题CONCAT(%, #{keyword}, %)支持中文模糊匹配。前端传{keyword:签字笔,minStock:10}后端自动生成WHERE goods_name LIKE %签字笔% AND stock 10。6.3 日志埋点追踪“谁在什么时间领了什么为什么被拒”ApplyRecordService中关键操作加LogExecutionTime注解自定义 AOPTarget(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface LogExecutionTime {}AOP 切面Around(annotation(logExecutionTime)) public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start System.currentTimeMillis(); Object proceed joinPoint.proceed(); long executionTime System.currentTimeMillis() - start; String method joinPoint.getSignature().toShortString(); log.info(Method {} executed in {} ms, method, executionTime); return proceed; }配合application.yml中logging.level.com.office.supply.serviceINFO日志自动记录ApplyRecordService.submit()耗时便于定位慢查询如审批列表加载超 2s可查apply_record表索引是否缺失。我部署过 7 个类似系统最深的教训是别信“一键部署脚本”一定要手动走一遍sql/→application.yml→mvn spring-boot:run→npm run build→copy dist/这条链路。每一步的报错信息都是系统在告诉你它真正需要什么。那些跳过的步骤最后都会变成凌晨两点的线上告警。希望帮到你。本文还有配套的精品资源点击获取
返回列表