尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
基于SpringBoot+Vue3的船舶维保管理系统设计与实现
做管理系统这些年我接触过仓储、设备、物业好几个行业船舶维保是其中最考验人的一个。原因很简单船是移动资产一条船几个月在海上漂维保工作必须按计划刚性执行可传统纸质记录和散落的Excel表格又实在无法追溯——上次主机保养是哪天做的、下次滑油更换还剩多少运行小时全靠老师傅脑子记风险不小。去年帮某船务公司梳理内部系统时我落地了一套船舶维保管理系统技术栈就是标题里写的 Java SpringBoot Vue3 MyBatis数据库用 MySQL前后端分离。系统规模不大但把船舶档案、维保计划、工单流转、备件库存、统计报表这些核心业务覆盖全了。这几天我把源码整理出来分享给同行顺手把设计和实现过程写成这篇文章。想了解真实业务系统怎么落地的后端朋友、想看看 Vue3 在项目中实际怎么用的前端同学或是正在做船舶信息化选型的人都可以参考。1. 项目整体设计与选型思路1.1 场景痛点与系统定位船舶维保这个场景和普通企业设备管理有一个很大的不同数据产生地点和使用地点经常分离。机务主管在岸基办公室制定计划轮机员在船上执行工单船长要看整体维保进度备件管理员则关心库存够不够。每个角色关心的是同一批数据的不同侧面这就要求系统从一开始就要把“流程”和“数据一致性”放在首位而不是简单做个增删改查。传统管理方式的核心痛点有几个。第一维保计划靠人工盯什么设备该保养了、什么时候到期稍有疏忽就会出现漏保养影响船舶安全。第二工单执行结果记录在纸上回到岸基再录入电脑信息滞后还容易丢失。第三备件领用和库存对不上经常出现账上有、库里没的情况紧急采购又赶不上船期。第四管理层想看的统计报表全靠人工汇总工作量巨大。这套系统的定位就是针对这些痛点做一套轻量级解决方案。不追求大而全重点把计划、执行、库存三个环节打通计划自动生成工单工单执行关联备件领用备件消耗自动扣库存报表从这些数据里实时聚合出来。这样一个闭环下来机务主管打开工作台就能看到各船维保完成情况轮机员在平板上就能接收工单、填写结果备件管理员实时掌握库存变化管理层要数据随时能看。1.2 为什么是前后端分离架构选前后端分离不是跟风完全是这个项目的实际需要。船舶行业的用户分散在岸基、船端和港口未来很可能要做小程序或者对接船岸通讯系统前后端分离之后后端只要提供统一的 API任何终端都可以接入。尤其是船端网络不稳定将来做离线模式或者数据同步的时候后端接口独立于前端页面改起来省事得多。从团队协作角度说前后端分离也清晰。后端同事专注 SpringBoot 接口开发、MyBatis SQL 调优前端同事专注 Vue3 组件和交互两边用接口文档作为契约并行推进效率明显高于传统的服务端渲染模板开发。而且这套系统的页面以表格、表单、图表为主页面状态复杂用 Vue 这类现代前端框架来管理界面状态体验比 JSP 时代强太多了。再说技术选型。SpringBoot MyBatis 是 Java 后端在中小企业项目里非常成熟的组合SpringBoot 把配置简化到极致MyBatis 则把 SQL 控制权完全还给开发者。这套源码里我故意用原生 MyBatis 的 XML 写法没有引入 MyBatis-Plus主要是考虑到教学场景原生 SQL 看得见摸得着业务逻辑复杂的时候不会被自动生成的 SQL 坑到。实际商业项目里用 MyBatis-Plus 提效没问题但理解底层原理还是原生写法最实在。1.3 核心表结构与数据模型拆解数据库我用 MySQL 8.xInnoDB 引擎字符集选 utf8mb4。这个细节看起来不起眼实际上很关键——船舶维保数据里大量英文缩写、特殊符号以及中文生僻字utf8mb4 才能完整支持否则存储时会出现乱码或者字符丢失。整个库的表结构可以分成四大类。基础档案类船舶信息表、设备信息表、备件信息表负责把管理对象建立起来。计划执行类维保计划表、维保工单表、工单执行记录表负责把流程跑起来。库存采购类备件库存表、备件出入库记录表、采购申请单表负责把物资管起来。权限类用户表、角色表、菜单权限表负责把入口控制住。拿核心的维保工单表举例字段设计上除了常规的工单编号、关联设备、计划完成时间、指派人、工单状态之外还有一个“来源计划ID”字段。这个字段特别重要它把工单和生成它的维保计划关联起来这样任何时候都能从工单反查是哪个计划触发的报表统计完成率时也从这里拿数据。类似的隐藏关联逻辑在备件出库单里也有体现出库单不仅记录备件数量和领用人还要关联工单ID这样分析“哪个设备最耗备件”就非常容易了。2. 后端核心模块实现要点2.1 RBAC权限模型与接口鉴权管理系统最先要解决的问题就是权限。这套系统用的是经典的 RBAC 模型五张表用户表、角色表、菜单表、用户角色关系表、角色菜单关系表。用户的权限不是直接挂在用户身上而是通过角色间接关联这样新增一个岗位只需要配置角色和菜单的关系不用一个个改用户维护成本低很多。有一次一个朋友问我前端把菜单隐藏掉用户不就看不到按钮了吗后端加鉴权是不是多此一举我说这是最典型的误区。前端隐藏菜单只是体验优化接口不校验才是真正的安全漏洞。有人抓包拿到接口地址直接构造请求就能操作数据后果非常严重。所以这套系统里前端负责看不见后端负责动不了。后端权限拦截的实现思路很直接。登录成功后在 Redis 里缓存用户的权限标识集合每次请求经过一个拦截器拦截器解析 Token 拿到用户ID再查 Redis 里的权限集合判断该请求对应的接口是否需要权限。没有权限直接返回 403不会进入 Controller。这里有一个细节容易踩坑修改角色权限后必须删掉该角色下所有用户的缓存否则旧权限会一直生效。我在系统里是用一个权限变更版本号来解决的每次变更角色权限版本号加一拦截器比较版本号不一致就强制刷新缓存。2.2 维保计划与工单状态机维保计划是整个业务核心的起点。计划分为两种类型一种是周期型比如某型柴油机每运行 500 小时更换滑油系统根据设备运行小时数自动判断是否到期生成工单另一种是日历型比如年检、特检这类按日期固定的项目到点自动提醒。这两种计划在数据库里用一个计划类型字段区分触发逻辑不一样但生成的工单结构是统一的。工单流转是这里最值得讲的部分。我用状态机来管理工单状态六个状态待派工、已派工、执行中、待验收、已完成、已取消。每个状态定义了允许的流转方向和操作角色待派工只能由机务主管操作派工已派工可以由轮机员确认开始执行执行中填写完维保结果后提交待验收验收人确认通过后变为已完成。非法操作在代码层直接拦截比如已完成的工单不允许再修改更不允许改回执行中。状态机的好处不只是防呆还有流程追溯价值。工单表里有一个状态变更记录表每次状态变化都插一条记录包括操作人、操作时间、旧状态、新状态、备注。这样出了问题能查到完整的流转链路是哪个环节、哪个人、什么时间做了什么操作一清二楚。这个设计最初是船务公司提出的需求实际上做下来发现对任何流程类系统都有很强的借鉴意义。2.3 备件库存与采购联动逻辑船舶备件管理和普通仓库管理有个明显区别备件种类杂、计量单位不统一有的按“个”、有的按“桶”、还有按“公斤”的而且部分关键备件必须随船携带、不能断供。这套系统在设计库存表时用统一的备件编码做主键单位字段独立出来避免出现换算混乱。工单执行过程有一个领用备件操作前端选择备件、填写数量后后端在一个事务里完成三件事扣减库存表的可用数量、插入一条出库记录、如果库存低于安全阈值则自动生成一条采购申请记录。这三个操作必须在一个事务里任何一个环节失败都不能写入数据库否则就会出现库存扣了但出库单没生成这种数据不一致的问题。我在这块代码里加了事务注解并且把扣减库存的 SQL 写成了乐观锁更新先查当前库存再带条件更新affectedRows 为 0 说明有人并发改了数据直接报业务异常提示刷新重试这种处理方式在多人同时操作的场景下非常可靠。备件采购这块采购申请单生成后有一个简单审批流程机务主管审批通过后流转到采购员采购员录入到货信息后系统自动做入库操作并更新库存。整条链路设计下来备件从进船到消耗的全生命周期都有据可查。2.4 报表统计的SQL聚合思路报表模块往往是管理系统的点睛之笔。系统里统计了几个核心指标各船维保计划完成率、设备故障率、近六个月的备件消耗趋势、工单按时完成率。这些指标在数据库层面用分组聚合可以轻松算出来不需要折腾复杂的大数据组件。以计划完成率为例思路是这样的从工单表按船舶分组统计已完成数量再从工单表按船舶分组统计总数量两个结果集按船舶关联后计算比率。关键点在于SQL的where条件要处理好时间范围比如按月统计就按工单创建时间过滤既能查看趋势又不会把全量历史数据都捞出来影响性能。我特别想提醒一句话这类管理系统的报表能用SQL聚合解决的千万别在前端做。见过不少项目把明细数据全部拉到前端再用JavaScript循环统计数据量小的时候看不出问题但超过几千条页面就卡得不能忍。数据库做了几百万行数据的聚合也就几十毫秒网络传输的数据量还小这才是一个管理系统的正确打开方式。3. 前端Vue3实现与交互细节3.1 路由守卫与动态菜单Vue3 前端这部分我用了组合式API风格配合 Pinia 做全局状态管理。整个前端最核心的交互逻辑就是动态菜单和路由守卫。用户在登录页输入账号密码后端校验通过后返回一个 Token 和该用户的菜单树前端把菜单树存进 Pinia然后通过 Vue Router 的 addRoute 方法动态注册路由。动态路由有一个容易踩的坑页面刷新后 Pinia 内存里的数据丢失导致路由表变成空页面白屏。解决思路是在路由守卫里做一层检查发现 Store 里没有菜单数据时重新调用后端接口获取用户信息和菜单再动态添加路由。这样不管怎么刷新只要 Token 没过期系统都能自己恢复状态。路由守卫的另一个职责是登录状态检查。我在 beforeEach 里判断没有 Token 直接重定向到登录页有 Token 但没有用户信息时先拉取用户信息再放行。这里要注意接口并发请求的顺序问题如果页面里多个组件同时发起接口请求登录态未初始化时容易被误判为未登录所以守卫里的初始化过程要加一个 Promise 串行化处理简单说就是第一个请求拉取用户信息时后续请求等它完成再走。3.2 表格页面通用封装管理系统里最不缺的就是表格页面每个业务模块都是列表、搜索、分页、新增、编辑、删除这套流程。如果每个页面都单独写请求逻辑和分页逻辑代码量会爆炸。我用组合式函数封装了一个 useTable把“加载数据、搜索条件、分页参数、刷新列表”这套逻辑全部抽进去。具体用法是每个页面调用 useTable 时传入一个接口地址和默认查询参数返回一个响应式对象和一组方法模板里直接绑定表格的 data 属性、分页组件的数据源按钮点击时调用对应的方法。这样每个页面只需要写自己特有的搜索表单和表格列定义通用逻辑全部复用后续加字段只改一处。这套封装做完之后新增一个列表页从原来的两百行代码直接缩减到六七十行效率提升是肉眼可见的。分页交互上有一个小细节用户操作完翻页后回到列表时最好保持之前的页码和搜索条件而不是回到第一页。这个功能我用一个页面级的状态缓存实现离开页面时把分页参数存到 sessionStorage进入页面时恢复。虽然功能不大但使用体验差别很明显。3.3 数据可视化与弱网适配报表页面用 ECharts 做数据可视化折线图看备件消耗趋势柱状图看各船维保完成率对比饼图看故障类型分布。用 ECharts 要注意一个资源管理问题图表组件在创建时初始化实例在组件卸载时必须调用 dispose 销毁否则内存泄漏来回切换页面几次后浏览器会明显变卡。容器尺寸变化导致的图表变形也是一个常见问题。浏览器窗口被拖拽后图表宽度不会自动适配解决方案是监听容器大小变化用 ResizeObserver 触发 chart.resize()。这个适配逻辑我封装在一个 BaseChart 组件里所有图表页面共用。弱网适配方面船舶场景下用户可能通过卫星网络访问系统带宽小、延迟高。前端在请求库里的配置要注意超时时间不能按局域网标准设置我设了 15 秒超时加载和提交过程给出明确的 loading 状态避免用户以为请求卡死了反复点击造成重复数据。相关操作按钮在请求期间要禁用掉这是一个小交互细节但没有它用户会重复提交工单产生一堆脏数据。4. 从源码到运行的完整实操4.1 环境准备与版本选择想把这套系统跑起来环境要求不复杂。后端需要 JDK 1.8 或 11、Maven 3.6 以上版本前端需要 Node.js 16 以上数据库用 MySQL 8.xRedis 作为缓存和 Token 存储版本 5.0 以上即可。版本选择上我多说两句。JDK 11 是目前企业项目兼容性和性能比较平衡的选择新项目可以上 17但这套源码在 JDK 8 下也能编译运行照顾了大部分老项目的环境。Node 版本建议不要低于 16Vite 对 Node 版本有要求版本太低启动时会直接报错。MySQL 8.x 和 5.7 有一部分语法差异比如 8.0 默认字符集是 utf8mb45.7 默认是 latin1所以统一用 8.x 最能减少环境差异带来的问题。4.2 后端启动五步走后端启动流程很简单核心就五步。第一步创建一个 MySQL 数据库名字随意但建议和配置一致然后执行源码里提供的 init.sql 脚本这个脚本会创建所有表结构并插入演示数据。第二步修改 application.yml 配置文件把数据库地址、用户名、密码改成自己环境的。第三步启动 Redis确保端口 6379 可用。第四步在项目根目录执行 mvn spring-boot:run 或打成 jar 包后运行。第五步启动成功后访问后端接口地址看到登录接口返回正常响应就说明环境通了。application.yml 里最关键的配置是数据源和 Redis其他配置项比如文件上传路径我用了一个相对路径部署时要注意目录存在且有写权限。如果修改了 Redis 密码配置文件里也要同步改否则启动时不会报错但登录功能会异常——Token 存不进缓存每次请求都是未登录状态这类问题排查起来还挺费时间的。4.3 前端构建与联调配置前端启动前先执行 npm install 安装依赖。如果网络环境不好可以配置镜像源这个不多说。依赖安装完成后执行 npm run dev 启动开发服务器默认端口是 5173。开发环境的跨域问题我用 Vite 的 proxy 配置解决而不是在后端开启 CORS。原理是让前端开发服务器把 /api 开头的请求转发到后端的 8080 端口这样浏览器看到的请求是同源的自然不存在跨域问题。配置如下// vite.config.js 核心配置 server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }生产部署时简单的做法是后端打 jar 包、前端构建静态文件后用 Nginx 托管再把 /api 路径代理到后端服务。这样一套架构下来前端和后端在访问路径上统一也没有跨域问题维护起来最省心。4.4 演示数据与角色说明系统内置了一套演示数据包含三条演示船舶、若干设备类型和备件信息维保计划也有几种典型配置方便快速体验完整业务流程。用户账号分为三个角色管理员、机务主管、轮机员。管理员的权限覆盖全部功能包括数据字典维护和用户管理机务主管拥有维保计划、工单派工、报表查看的权限轮机员负责接收工单、填写维保结果和领用备件。建议第一次登录后修改默认密码系统里也做了这个逻辑——默认密码登录后强制进入修改密码页面。演示数据还有一个作用就是跑一遍流程后马上能看出数据之间的关系执行一个工单、领用几个备件、再去库存页面看数量变化、去报表页面看指标统计整个链路在十几分钟内可以全部体验完。实际上我自己测试时也是这么干的走通主流程后再去改代码定位问题会快很多。5. 常见问题与排查技巧实录5.1 数据库连接与中文乱码中文乱码是管理系统里最高频的问题几乎每个人都有深刻教训。常见的原因是创建数据库时字符集没指定好MySQL 在某些版本下默认字符集不支持中文。解决方法是建库时明确指定字符集和排序规则CREATE DATABASE ship_maintenance DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;另一个容易忽略的地方是 JDBC 连接串。在 application.yml 的数据源配置里URL 末尾一定要加 useUnicodetrue 和 characterEncodingutf8否则即使数据库字符集正确连接层依然可能乱码。还有一个细节MySQL 8.x 的驱动类和 5.x 不一样配置 driver-class-name 时要注意对应版本。这类问题一般有几个特征数据库命令行查出来正常、但页面显示乱码说明问题出在连接层而数据库里存进去时就已经乱码则多半是建库字符集问题。分清楚这两条线排查方向就不会错。5.2 跨域与登录失效问题跨域问题在前后端分离项目里不可避免。开发环境用 Vite proxy 解决后一般不会遇到但有时候改了后端地址忘了同步改 proxy 配置也会导致请求打到了别的服务上表现就是页面能打开但数据全部请求失败。排查时先看浏览器 Network 面板请求是否真的发到了目标地址再确认响应状态码。登录失效是另一个高频问题。Token 过期后请求返回 401前端要有一个全局的响应拦截遇到 401 时清空本地登录状态并跳转到登录页。但这里有个场景容易忽视用户正在填写一个很长的维保工单突然登录失效填了一半的数据全丢了。我的处理方案是在拦截器里弹一个友好的提示并且把当前路由和页面数据暂存到 sessionStorage重新登录后提示用户恢复。这个功能用户评价特别好减少了不少抱怨。5.3 查询慢与索引设计随着维保工单数据积累工单表的行数增长很快如果不加索引联表查询会越跑越慢。我在这套系统里给工单表建了组合索引索引字段是船舶ID计划完成时间这样按船舶查工单列表、按时间范围统计完成率都能命中索引性能提升非常明显。注意组合索引的顺序有讲究最常用的等值查询字段放前面范围查询字段放后面。排查慢查询时最直接的方法是打开 MySQL 的慢查询日志或者用 EXPLAIN 查看执行计划。看 key 字段是否命中索引看 rows 字段估算扫描行数如果扫描行数特别多就要考虑建索引。这里有一个反面经验曾经有个同事把所有查询字段都建了索引结果表插入数据变慢索引维护成本很高。索引不是越多越好要结合真实的查询场景来定高频查询字段加索引低频字段盲目加反而拖累写性能。5.4 权限漏配与数据越权权限这块最容易出现的问题不是权限拦截器写错了而是接口漏配。新增接口时忘了配置需要的权限标识结果任何登录用户都能调用这在验收测试时往往还测不出来因为测试只关注功能是否正常不会去验证越权场景。我的排查建议是做一个接口权限清单把每个 Controller 接口和所需的权限标识列出来和菜单配置对照检查。还有一个常见问题同一个接口被两个角色使用但操作的字段范围和按钮级别不一样最典型的是机务主管可以删除工单轮机员只能查看自己的工单。这类问题靠全局拦截器解决不了必须在业务层做数据范围的校验比如轮机员查询工单列表时SQL 里强制加上执行人等于当前用户ID的条件而不是把参数交给前端传入否则人家改一下请求参数就能看到别人的工单了。数据越权问题在船舶管理系统里尤其敏感因为工单里包含维修工时、故障详情、备件消耗这些都是船舶运营数据不能随便给无关的人看到。我在这套系统里给查询接口做了一个统一的用户上下文注入当前登录用户信息从 Token 解析出来塞进 ThreadLocalSQL 层根据角色自动拼接数据范围条件这样后端始终以服务端信息为准前端传什么参数都不能覆盖安全等级就上来了。说一个我实际项目里的体会。做这类管理系统技术本身没有什么高深的地方难的是对业务的理解和对数据一致性的敬畏。船舶维保这种场景设备漏保养可能直接带来安全隐患所以系统里每一个状态流转、每一次库存扣减我都要求有记录、可追溯、防并发。把这套思路想清楚再动手写代码的时候自然就稳了。源码整理出来之后有同行问我后续还能加什么功能我觉得下一步最值得做的是船端离线模式——把工单下载到本地、执行完再同步回岸基这需要在现有接口结构上加一层同步机制好在当初接口设计时返回值全部做了统一封装改造起来不会伤筋动骨。希望这套系统的设计思路能给做同类项目的朋友一些参考少走几步我曾经踩过的弯路。
RELATED

相关推荐

open-code-review:代码评审的工程化规则引擎与实践指南

open-code-review:代码评审的工程化规则引擎与实践指南

代码评审这件事,我见过太多团队把它做成一种仪式感极强、实际效果为零的流程。PR/MR 一发出来,评审人扫一眼绿叉就点 Approve,连 diff 都没完整看过;稍微认真的团队,评审时也只盯着变量命名是不是少了个空格、注释有没…

📅 2026/10/20 6:39:32
煤矿双重预防管理信息系统建设实践:从风险模型到隐患闭环

煤矿双重预防管理信息系统建设实践:从风险模型到隐患闭环

1. 为什么“双重预防”在煤矿现场总是流于形式1.1 风险辨识清单往往是“一次性”的在煤矿干过安全管理的人都有体会,每年年初做风险辨识,通常就是技术科牵头、组织几个老专家和科室负责人开半天会,最后生成一份几十页的《年度风险辨识评估报告…

📅 2026/10/20 6:34:32
webpack入口配置全解析:从单页到多页的构建演进路径

webpack入口配置全解析:从单页到多页的构建演进路径

聊webpack配置,很多人第一反应是去逐条背module.rules和plugins,可真正决定打包流程走向的,往往是那个看起来不起眼的entry字段。它就像一张依赖地图的起始坐标:webpack拿到它,顺着import递归展开整棵依赖树&#xff0…

📅 2026/10/20 6:34:32
MORE NEWS

更多资讯

📰

Ingress Nginx 高性能调优:从内核参数到 10 万 QPS 的完整实践

1. 为什么你的 Ingress Nginx 跑不到 10 万 QPS先把话说在前面:Ingress Nginx 单机 10 万 QPS,这个目标不是玄学,但也绝不是把worker_processes改成auto、把内存调大就能碰到的。我原先帮某电商中台调过一版 Nginx Ingress,业务高…

📰

dart_scope鸿蒙适配实战:作用域驱动Flutter依赖生命周期治理

开头一个 Flutter 应用跑在鸿蒙设备上,界面渲染没问题了,但业务状态却乱成一锅粥——页面 A 创建的服务在页面 B 里串用了,退出页面后定时器还在跑,全局单例越攒越多却没人清理。这种场景,做过多端适配的团队多少都经历…

📰

扩散语言模型技术全解析:并行生成、可控性与工程实践

直接从一个技术圈的老话题切入吧——早就听人争论“语言生成到底还要不要按顺序一个字一个字往外蹦”,直到这轮“数亿元”级别的融资砸下来,全球扩散语言模型这个赛道才算真正被重新定价。说实话,当看到手机生态的头部玩家和智能终端领域的巨…

📰

YOLO11双模态改进源码解析:红外与RGB特征融合的目标检测实践

简介:一套YOLOv11多模态输入检测项目资源,面向毕业设计及科研场景,核心解决红外(IR)与RGB可见光图像共同识别问题,通过融合不同光谱信息,提升夜间、低照度、烟雾等复杂环境下的目标检测精度与鲁…

📰

Ray 分布式对象溢出调优:应对千万级长上下文的跨存储治理

在以 Ray 为分布式底层引擎构建的企业级大模型(LLM)推理、微调与长文档复杂 Agent 评测平台中,内存是整座系统最昂贵、也最容易猝死的核心战略资源。随着 GPT-6、DeepSeek-V4 等架构全面迈入 128K 乃至 1M Token 的超长上下文(Lon…

📰

基于Python的网络小说分析系统:爬虫、文本挖掘与可视化实战

最近这几年,“基于Python的网络小说分析系统”这类题目在课程设计和毕业设计里出现的频率非常高。回想我当年带学生选题的时候,每届都有好几个小组选类似的题目,原因很简单:它既有技术深度——爬虫、数据库、文本挖掘、可视化一应…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬