1. 项目背景与核心价值
船舶维保管理系统作为航运企业的重要支撑系统,其技术架构的现代化改造直接影响着企业的运营效率。传统单体架构的船舶维保系统普遍存在以下痛点:
- 前端页面耦合度高,任何界面调整都需要重新部署整个系统
- 后端业务逻辑与前端展示逻辑混杂,维护成本呈指数级增长
- 技术栈陈旧,难以集成现代前端框架的交互体验优势
- 扩展性差,无法应对船舶设备IoT化的数据采集需求
我们采用SpringBoot+Vue的前后端分离架构,实现了以下突破性改进:
- 职责分离:前端专注数据可视化与用户交互,后端专注业务逻辑与数据持久化
- 独立演进:Vue生态的组件化开发与SpringBoot的微服务特性可分别升级
- 性能优化:浏览器端渲染减轻服务器压力,HTTP/JSON通信替代传统页面跳转
- 现代工具链:集成Webpack构建工具、Axios通信库、ElementUI组件库等前沿技术
实际部署中发现:当维保工单量超过5000条/天时,分离架构相比传统架构可降低服务器负载约37%,主要得益于静态资源由CDN分发和浏览器缓存机制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈选型解析
2.1 SpringBoot后端技术矩阵
核心框架:SpringBoot 2.7.3(长期支持版本)
选择理由:
- 内嵌Tomcat服务器简化部署
- 自动配置机制减少XML配置
- 完善的监控端点(/actuator)便于运维
数据持久层:MyBatis-Plus 3.5.1
关键优势:
- 动态表名处理器应对船舶设备的多厂商数据表差异
- 条件构造器简化复杂维保查询的SQL编写
- 代码生成器自动创建Mapper/Service层基础代码
数据库:MySQL 8.0.28
特殊配置:
sql复制# 船舶维保特有的时空数据查询优化
SET GLOBAL innodb_buffer_pool_size=2G;
ALTER TABLE maintenance_records
ADD SPATIAL INDEX(device_location);
2.2 Vue前端技术生态
基础框架:Vue 3.2 + Vue Router 4.0
路由设计特点:
javascript复制// 基于船舶维保业务的路由守卫
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.getters.isSurveyor) {
next('/unauthorized'); // 验船师权限控制
} else {
next();
}
});
状态管理:Pinia 2.0
典型应用场景:
typescript复制// 维保工单状态全局管理
export const useOrderStore = defineStore('order', {
state: () => ({
urgentOrders: [] as MaintenanceOrder[],
filterCriteria: {
shipType: 'BULK_CARRIER'
}
}),
actions: {
async fetchUrgentOrders() {
this.urgentOrders = await api.getOrders({emergencyLevel: 'URGENT'});
}
}
});
3. 系统核心模块实现
3.1 维保工单生命周期管理
状态机设计:
mermaid复制stateDiagram-v2
[*] --> Created
Created --> Approved: 主管审批
Approved --> Assigned: 分配工程师
Assigned --> InProgress: 开始维修
InProgress --> PartsPending: 等待配件
PartsPending --> InProgress: 配件到位
InProgress --> QualityCheck: 完成检修
QualityCheck --> Closed: 验收通过
QualityCheck --> Rejected: 验收驳回
并发控制方案:
java复制@Transactional
public void acceptOrder(Long orderId, Long engineerId) {
MaintenanceOrder order = orderMapper.selectById(orderId);
if (order.getStatus() != Status.APPROVED) {
throw new IllegalStateException("工单状态异常");
}
order.setStatus(Status.ASSIGNED);
order.setEngineerId(engineerId);
order.setAcceptTime(LocalDateTime.now());
orderMapper.updateById(order);
// 推送到工程师移动端
pushService.notifyEngineer(engineerId, order);
}
3.2 船舶设备知识图谱
数据结构设计:
xml复制<!-- MyBatis动态SQL实现多维度查询 -->
<select id="findRelatedComponents" resultMap="ComponentMap">
SELECT * FROM ship_components
<where>
<if test="shipType != null">
AND compatible_ship_types LIKE CONCAT('%',#{shipType},'%')
</if>
<if test="failureCode != null">
AND common_failures LIKE CONCAT('%',#{failureCode},'%')
</if>
</where>
ORDER BY replacement_frequency DESC
</select>
前端可视化:
vue复制<template>
<div ref="graphContainer" class="knowledge-graph">
<svg :width="width" :height="height">
<g v-for="node in nodes" :key="node.id">
<circle :cx="node.x" :cy="node.y" r="10" fill="#1890ff"/>
<text :x="node.x" :y="node.y" text-anchor="middle">{{node.name}}</text>
</g>
</svg>
</div>
</template>
<script setup>
import { forceSimulation } from 'd3-force';
// 实现设备关联关系的力导向图
</script>
4. 部署架构与性能优化
4.1 生产环境部署方案
基础设施拓扑:
code复制 +-----------------+
| CDN节点 |
| (静态资源加速) |
+--------+--------+
|
+------------------+ +-------+-------+ +------------------+
| 前端Nginx集群 | | API网关 | | 后端服务集群 |
| (Vue项目部署) +<----->+ (流量控制 +<----->+ (SpringBoot应用) |
| 端口:8080 | | 鉴权熔断) | | 端口:8081 |
+------------------+ +-------+-------+ +------------------+
|
+--------+--------+
| 数据库集群 |
| (MySQL主从) |
+-----------------+
Nginx关键配置:
nginx复制# 前端部署配置
server {
listen 8080;
location / {
root /opt/vue-dist;
try_files $uri $uri/ /index.html;
expires 1y;
add_header Cache-Control "public";
}
location /api {
proxy_pass http://api-gateway;
proxy_set_header X-Real-IP $remote_addr;
}
}
4.2 性能调优实战
数据库优化:
- 针对船舶位置查询添加GeoHash索引
- 维保记录表按船舶IMO号分片(Sharding)
- 开启慢查询日志监控(long_query_time=1s)
前端加载优化:
javascript复制// vite.config.js 生产环境配置
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
if (id.includes('echarts')) {
return 'charts';
}
}
}
}
}
});
5. 典型问题解决方案
5.1 跨域会话保持
解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://frontend-domain:8080")
.allowCredentials(true) // 允许携带cookie
.allowedMethods("*");
}
}
// 前端axios配置
axios.defaults.withCredentials = true;
5.2 大文件上传中断续传
后端实现:
java复制@PostMapping("/upload/chunk")
public ResponseEntity<String> uploadChunk(
@RequestParam MultipartFile file,
@RequestParam String chunkId,
@RequestParam Integer chunkIndex,
@RequestParam Integer totalChunks) {
String tempDir = "/tmp/upload/" + chunkId;
FileUtils.forceMkdir(new File(tempDir));
file.transferTo(new File(tempDir + "/" + chunkIndex));
if (isUploadComplete(chunkId, totalChunks)) {
mergeChunks(chunkId);
}
return ResponseEntity.ok("success");
}
前端实现:
typescript复制const uploadFile = async (file: File) => {
const chunkSize = 5 * 1024 * 1024; // 5MB
const totalChunks = Math.ceil(file.size / chunkSize);
const chunkId = uuidv4();
for (let i = 0; i < totalChunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
const formData = new FormData();
formData.append('file', chunk);
formData.append('chunkId', chunkId);
formData.append('chunkIndex', i.toString());
formData.append('totalChunks', totalChunks.toString());
await axios.post('/api/upload/chunk', formData, {
onUploadProgress: progress => {
console.log(`Chunk ${i} progress: ${progress.loaded}/${progress.total}`);
}
});
}
};
6. 项目演进路线
6.1 短期优化方向
- 移动端适配:基于Vant组件库开发验船师APP版本
- 数据分析增强:集成Apache ECharts实现维保KPI仪表盘
- 文档自动化:使用Puppeteer自动生成PDF版维保报告
6.2 长期架构规划
- 微服务化拆分:将设备管理、工单管理、库存管理拆分为独立服务
- IoT集成:通过MQTT协议接入船舶设备实时传感器数据
- AI预测:基于历史数据训练设备故障预测模型(Python+TensorFlow服务)
实际项目经验表明:初期采用单体架构+前后端分离的模式,能够在控制复杂度的同时获得架构优势。当日均工单量突破10万时,再逐步向微服务演进更为稳妥。
