1. 项目背景与核心需求
铝塑门窗制造行业作为传统制造业的重要组成部分,长期以来面临着生产效率低下、生产计划混乱、设备利用率不高等问题。我在实地调研某中型铝塑门窗生产企业时发现,他们的生产调度仍采用纸质工单流转方式,设备状态靠人工记录,工序衔接经常出现延误。车间主任每周要花2-3天时间手工排产,遇到紧急插单时整个生产计划都要推倒重来。
这个基于SSM+Vue的生产管理系统正是为解决这些痛点而设计。系统需要实现的核心功能包括:
- 实时监控设备运行状态和产能利用率
- 自动化的智能排产调度
- 标准化的工序流程管理
- 从订单到交付的全流程跟踪
- 可视化的生产数据看板
2. 技术选型与架构设计
2.1 技术栈选择考量
选择SSM(Spring+SpringMVC+MyBatis)作为后端框架主要基于以下考虑:
- Spring框架的IoC和AOP特性非常适合企业级应用开发,其声明式事务管理对生产调度这类业务场景尤为重要
- MyBatis在复杂SQL查询和性能优化方面比Hibernate更灵活,适合处理生产数据多表关联查询
- SpringMVC的RESTful支持为前后端分离提供了良好基础
前端选择Vue.js主要因为:
- 响应式数据绑定特别适合实时展示生产状态变化
- 组件化开发便于构建复杂的生产看板界面
- 相比React更轻量,学习曲线平缓,适合学生团队开发
2.2 系统架构设计
系统采用典型的三层架构:
code复制表示层(Vue.js) → 业务逻辑层(Spring) → 数据访问层(MyBatis)
↓ ↓
浏览器缓存 Redis缓存
关键设计决策:
- 使用WebSocket实现设备状态实时推送
- 采用Redis缓存热点数据(如当前工单、设备状态)
- 数据库设计遵循第三范式,同时为报表查询保留适当冗余
3. 核心功能模块实现
3.1 智能调度算法实现
调度模块是系统的核心,我们设计了一个混合调度策略:
java复制// 伪代码示例:调度核心算法
public class Scheduler {
public ScheduleResult generateSchedule(Order[] orders, Machine[] machines) {
// 第一阶段:基于规则的初步调度
List<Task> tasks = ruleBasedScheduling(orders);
// 第二阶段:遗传算法优化
GeneticAlgorithm ga = new GeneticAlgorithm(tasks, machines);
ScheduleResult result = ga.optimize();
// 第三阶段:人工调整接口
return allowManualAdjust(result);
}
private List<Task> ruleBasedScheduling(Order[] orders) {
// 实现SPT(最短加工时间优先)、EDD(最早交货期优先)等规则
}
}
算法考虑的关键因素:
- 设备能力约束(门窗切割机最大加工尺寸)
- 工序先后约束(必须先切割后组装)
- 订单优先级(VIP客户插单处理)
- 换模时间(不同型材切换需要的准备时间)
3.2 设备状态监控实现
通过Modbus TCP协议与PLC控制器通信获取实时数据:
java复制public class EquipmentMonitor {
@Scheduled(fixedRate = 5000)
public void updateMachineStatus() {
ModbusMaster master = getModbusConnection();
byte[] data = master.readHoldingRegisters(slaveId, address, length);
MachineStatus status = parseData(data);
redisTemplate.opsForValue().set("machine:"+machineId, status);
// WebSocket推送更新
simpMessagingTemplate.convertAndSend("/topic/machine-status", status);
}
}
监控的关键指标:
- 运行状态(运行/待机/故障)
- 当前加工任务
- 累计运行时长
- 实时产量计数
4. 数据库设计要点
4.1 核心表结构设计
sql复制CREATE TABLE `work_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL COMMENT '工单编号',
`product_id` bigint(20) NOT NULL COMMENT '产品ID',
`quantity` int(11) NOT NULL COMMENT '数量',
`priority` tinyint(4) DEFAULT 2 COMMENT '优先级1-5',
`status` tinyint(4) DEFAULT 0 COMMENT '0未开始 1进行中 2已完成',
`plan_start` datetime DEFAULT NULL COMMENT '计划开始时间',
`plan_end` datetime DEFAULT NULL COMMENT '计划完成时间',
PRIMARY KEY (`id`),
KEY `idx_status` (`status`),
KEY `idx_plan_time` (`plan_start`,`plan_end`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 优化实践
- 为高频查询字段建立复合索引:
sql复制ALTER TABLE `process_record` ADD INDEX `idx_machine_process` (`machine_id`, `process_id`);
- 使用冗余字段减少联表查询:
sql复制ALTER TABLE `work_order` ADD COLUMN `product_name` VARCHAR(100) COMMENT '产品名称冗余';
5. 前端关键技术实现
5.1 生产看板实现
使用Vue+ECharts构建实时看板:
vue复制<template>
<div class="dashboard">
<el-row :gutter="20">
<el-col :span="8">
<echart :option="outputChartOption" auto-resize/>
</el-col>
<el-col :span="8">
<machine-status-panel :data="machineData"/>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
machineData: [],
socket: null
}
},
mounted() {
this.initWebSocket();
},
methods: {
initWebSocket() {
this.socket = new WebSocket(`ws://${location.host}/api/ws`);
this.socket.onmessage = (event) => {
this.machineData = JSON.parse(event.data);
}
}
}
}
</script>
5.2 甘特图组件封装
基于vue-gantt-elastic定制生产排程视图:
javascript复制import GanttElastic from 'vue-gantt-elastic';
export default {
components: { GanttElastic },
data() {
return {
tasks: {
data: [
{
id: 1,
label: '工单A',
user: '切割工序',
start: '2024-03-01',
end: '2024-03-03',
percent: 50,
style: { backgroundColor: '#FFA500' }
}
]
}
}
}
}
6. 系统部署与性能优化
6.1 部署架构
code复制 +-----------------+
| Nginx |
| (负载均衡+静态资源) |
+--------+--------+
|
+----------------+-----------------+
| | |
+----------+-------+ +------+--------+ +------+--------+
| Tomcat节点1 | | Tomcat节点2 | | Tomcat节点3 |
| (JVM调优) | | (JVM调优) | | (JVM调优) |
+------------------+ +---------------+ +---------------+
| | |
+----------------+-----------------+
|
+--------+--------+
| MySQL |
| (主从复制) |
+--------+--------+
|
+--------+--------+
| Redis |
| (缓存+会话共享) |
+-----------------+
6.2 JVM调优参数
bash复制# Tomcat的setenv.sh配置
JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m -XX:+UseG1GC
-XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4"
7. 开发中的典型问题与解决方案
7.1 并发调度冲突问题
问题现象:
当多个管理员同时调整排产计划时,出现调度冲突和数据不一致。
解决方案:
- 采用乐观锁机制:
java复制@Transactional
public boolean updateSchedule(Schedule schedule) {
Schedule old = scheduleMapper.selectById(schedule.getId());
if (old.getVersion() != schedule.getVersion()) {
throw new OptimisticLockException("版本不一致");
}
schedule.setVersion(schedule.getVersion() + 1);
return scheduleMapper.updateById(schedule) > 0;
}
- 关键操作加入分布式锁:
java复制public void dispatchTask(Task task) {
String lockKey = "dispatch:" + task.getMachineId();
try {
boolean locked = redisLock.tryLock(lockKey, 10, TimeUnit.SECONDS);
if (locked) {
// 执行派工逻辑
}
} finally {
redisLock.unlock(lockKey);
}
}
7.2 大数据量报表查询优化
问题现象:
生产历史报表查询速度慢,超过5秒。
优化措施:
- 建立汇总表定时预计算
sql复制CREATE TABLE `prod_daily_summary` (
`summary_date` date NOT NULL,
`machine_id` bigint(20) NOT NULL,
`output_qty` int(11) DEFAULT 0,
`run_time` int(11) DEFAULT 0 COMMENT '分钟',
PRIMARY KEY (`summary_date`, `machine_id`)
);
- 使用MyBatis二级缓存
xml复制<cache eviction="LRU" flushInterval="3600000"
size="512" readOnly="true"/>
8. 项目心得与建议
经过这个项目的完整开发周期,我总结了以下几点经验:
-
领域建模要准确
初期对铝塑门窗生产工艺理解不足,导致工序模型修改了3版。建议先花2周时间深入车间学习实际生产流程。 -
性能测试要尽早
调度算法在模拟数据下运行很快,但实际部署后大数据量时出现性能瓶颈。应在开发中期就进行压力测试。 -
前端状态管理要谨慎
生产状态涉及多组件联动,最初用事件总线实现导致难以维护。改用Vuex后代码更清晰。 -
异常处理要全面
实际运行中发现设备断线、数据异常等情况比预期多。应建立完善的异常处理机制和日志记录。
对于想开发类似系统的同学,我建议:
- 先聚焦核心调度功能,再扩展其他模块
- 使用Swagger规范API接口,减少前后端联调问题
- 生产环境一定要配置完善的监控告警系统