1. 项目概述
船舶维保管理系统是针对航运企业、修船厂等机构设计的专业信息化解决方案。这个基于SpringBoot+Vue的前后端分离系统,通过整合MyBatis和MySQL数据库,实现了船舶设备全生命周期管理的数字化和智能化。
我在实际开发中发现,传统船舶维保管理普遍存在纸质记录易丢失、维修历史难追溯、备件库存不透明等问题。这套系统通过以下几个核心模块解决了这些痛点:
- 设备档案管理:记录船舶各类设备的基础信息和技术参数
- 维修工单流转:实现从报修到验收的全流程电子化跟踪
- 预防性维护计划:基于设备运行小时数或日历周期的自动提醒
- 备件库存管理:实时监控备件库存状态和采购需求
- 数据分析看板:可视化展示设备故障率、维修成本等关键指标
2. 技术架构解析
2.1 后端技术栈
SpringBoot 2.7作为后端框架,其自动配置特性大幅简化了项目初始化工作。我在pom.xml中主要配置了这些关键依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>MyBatis的XML映射文件采用了动态SQL写法,这是处理船舶设备复杂查询条件的关键:
<select id="selectEquipmentList" resultMap="EquipmentResult"> SELECT * FROM ship_equipment <where> <if test="shipId != null">AND ship_id = #{shipId}</if> <if test="equipmentType != null">AND equipment_type = #{equipmentType}</if> <if test="status != null">AND status = #{status}</if> </where> ORDER BY create_time DESC </select>2.2 前端技术栈
Vue 3组合式API大幅提升了代码组织效率。这个典型设备列表组件展示了前后端交互方式:
<script setup> import { ref, onMounted } from 'vue' import { getEquipmentList } from '@/api/equipment' const equipmentList = ref([]) const loading = ref(true) onMounted(async () => { try { const res = await getEquipmentList() equipmentList.value = res.data } finally { loading.value = false } }) </script>3. 核心功能实现
3.1 维修工单状态机
船舶维修涉及多状态流转,我们采用状态模式实现工单生命周期管理:
public interface MaintenanceOrderState { void submit(OrderContext context); void approve(OrderContext context); void reject(OrderContext context); void complete(OrderContext context); } // 具体状态实现 public class DraftState implements MaintenanceOrderState { @Override public void submit(OrderContext context) { context.setState(new PendingReviewState()); // 发送通知给审批人 notificationService.sendReviewNotice(context.getOrder()); } }3.2 预防性维护提醒
基于Quartz实现两种维保触发机制:
- 固定周期提醒(如每3个月)
- 运行小时数提醒(如每500小时)
配置示例:
@Scheduled(cron = "0 0 8 * * ?") // 每天8点检查 public void checkPreventiveMaintenance() { // 查询即将到期的设备 List<Equipment> dueSoon = equipmentMapper.selectDueSoonEquipment(); dueSoon.forEach(equip -> { // 生成维保工单 MaintenanceOrder order = new MaintenanceOrder(); order.setEquipmentId(equip.getId()); // 发送微信/邮件提醒 remindService.sendMaintenanceReminder(equip.getResponsiblePerson()); }); }4. 数据库设计要点
4.1 关键表结构
CREATE TABLE `ship_equipment` ( `id` bigint NOT NULL AUTO_INCREMENT, `ship_id` bigint NOT NULL COMMENT '所属船舶', `name` varchar(100) NOT NULL COMMENT '设备名称', `type_code` varchar(50) NOT NULL COMMENT '设备类型编码', `manufacturer` varchar(100) DEFAULT NULL COMMENT '制造商', `model` varchar(100) DEFAULT NULL COMMENT '型号', `install_date` date DEFAULT NULL COMMENT '安装日期', `last_maintenance_date` date DEFAULT NULL COMMENT '上次维保日期', `running_hours` int DEFAULT '0' COMMENT '运行小时数', `status` tinyint DEFAULT '1' COMMENT '状态(1-正常 2-维修中 3-报废)', PRIMARY KEY (`id`), KEY `idx_ship` (`ship_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;4.2 查询优化实践
针对船舶维保特有的跨表查询场景,我们采用这些优化策略:
- 为高频查询字段添加复合索引
- 使用MyBatis二级缓存处理静态数据
- 对大文本字段(如维修记录)单独建表
5. 部署与运维
5.1 多环境配置
通过Spring Profile实现环境隔离:
# application-dev.yml spring: datasource: url: jdbc:mysql://dev-db:3306/ship_maintenance?useSSL=false username: devuser password: dev123 # application-prod.yml spring: datasource: url: jdbc:mysql://prod-db:3306/ship_maintenance?useSSL=true username: produser password: ${DB_PASSWORD} # 从环境变量读取5.2 前端部署方案
Vue项目通过nginx配置实现高效部署:
server { listen 80; server_name maintenance.yourdomain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }6. 踩坑与解决方案
6.1 时区问题处理
船舶经常跨时区航行,我们在系统中统一采用UTC时间存储,前端按用户时区显示:
@Configuration public class TimeConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { return builder -> builder.timeZone(TimeZone.getTimeZone("UTC")); } }6.2 大文件上传优化
对于船舶图纸等大文件,采用分片上传方案:
- 前端使用vue-simple-uploader组件
- 后端实现分片合并接口
- 文件存储采用MinIO对象存储
核心代码片段:
@PostMapping("/merge") public Result mergeChunks(@RequestParam String md5, @RequestParam String fileName) { // 合并临时分片文件 FileMergeUtil.merge(md5, fileName); // 保存文件元信息 attachmentService.saveFileInfo(md5, fileName); return Result.success(); }7. 扩展功能建议
根据实际船舶管理需求,后续可以考虑集成:
- 物联网设备数据采集(通过MQTT协议)
- 基于历史数据的故障预测(机器学习模型)
- 移动端小程序(微信/钉钉)
- 电子签名验收功能
- 多语言支持(针对国际航运公司)
在船舶设备详情页,我们添加了二维码生成功能,方便现场扫码查看设备信息。这个功能使用qrcode.js实现:
generateQRCode(equipmentId) { const qrCodeUrl = `${location.origin}/equipment/detail/${equipmentId}` QRCode.toCanvas(document.getElementById('qrcode'), qrCodeUrl, { width: 120, margin: 1 }) }