公司动态
基于Spring Boot构建工业生产计划管理系统:从核心流程到技术实现
这类系统最值得先看的不是功能列表而是能不能把生产计划、物料、订单、排程这些核心流程串起来并且在实际部署时稳定运行。很多团队在选型或自研时容易陷入两个误区要么过度追求大而全引入了大量用不上的复杂模块导致维护成本飙升要么只做了简单的增删改查业务逻辑散落在各个角落一旦计划调整或插单整个系统就乱了套。一个真正能用的工业生产计划管理系统核心价值在于流程闭环和数据驱动。它需要把销售订单、物料清单BOM、库存、设备产能、工时、交货期这些原本分散在Excel、邮件甚至纸质单据里的信息通过一个统一的逻辑串联起来让计划员能基于实时数据做决策而不是靠经验“拍脑袋”。对于正在评估或准备动手开发的团队来说最该关注的是系统如何定义“计划”这个核心对象排程算法是简单的先到先得还是能考虑优先级、换线时间、设备约束当紧急订单插入时系统是推倒重来还是能局部调整并给出影响评估下面我会以一个从零开始构建的视角拆解基于Spring Boot实现这样一个系统的关键环节、技术选型考量以及那些只有踩过坑才知道的细节。文章会避开空泛的概念直接聚焦于环境搭建、核心表设计、排程逻辑实现、前后端协作以及生产环境部署中的具体问题。1. 先明确系统边界它到底管什么不管什么在动手写第一行代码之前必须把系统的边界画清楚。一个“工业生产计划管理系统”听起来包罗万象但如果试图一次性解决所有问题项目大概率会失败。1.1 核心管理对象从销售订单到生产工单的转化链系统管理的起点通常是销售订单或预测订单。终点是下达给车间执行的生产工单。中间的核心转化逻辑是这套系统的灵魂。你需要明确以下几个实体及其关系销售订单客户要什么、要多少、何时要。产品最终要交付的成品。物料清单一个成品由哪些子部件或原材料构成BOM以及构成的数量关系。这是计划分解的基石。物料具体的原材料、半成品、零部件需要有库存信息。工作中心可以是一台设备、一条生产线或一个班组是执行生产任务的基本单位需要有产能如小时/天和日历工作日、休息日信息。工艺路线一个产品在哪些工作中心上经过哪些工序每个工序的标准工时是多少。生产工单最终下达的指令包含产品、数量、计划开始/结束时间、所需物料、工序步骤等。很多新手系统只做到了“工单管理”即手工创建工单并分配这只是一个高级版的记事本。真正的计划系统应该能根据销售订单结合BOM和库存自动计算出需要生产或采购的物料需求即MRP核心思想再根据工艺路线和工作中心产能将生产任务在时间轴上排列开来即排程。1.2 功能边界划分第一期做什么后续迭代什么对于第一期MVP我建议聚焦以下核心闭环基础数据管理产品、BOM、物料、工作中心、工艺路线的维护。销售订单录入。MRP运算根据订单和现有库存计算物料净需求。这一步可以暂时简化例如只考虑单层BOM不考虑在途、安全库存等复杂因素。简单排程根据物料齐套情况和工作中心产能为生产任务分配一个建议的开始时间。初期可以采用无限产能排程即假设产能无限只按顺序排先跑通流程。工单下达与状态跟踪工单创建后可以下发并更新状态待生产、生产中、已完成。暂时不要做复杂的有限产能优化算法。完整的供应链管理供应商、采购订单。车间现场数据采集。复杂的成本核算。先让核心流程跑起来数据能流转再基于实际使用反馈进行迭代。这个边界意识能帮你节省大量初期开发时间避免陷入技术细节而忘了业务目标。2. 技术栈选型与项目初始化不只是Spring Boot虽然标题是“基于Spring Boot”但一个可用的系统远不止一个框架。技术选型需要平衡开发效率、团队技能和后期维护成本。2.1 后端技术栈稳健为主预留扩展Spring Boot毫无疑问是基石。版本选择上不必追求最新。Spring Boot 2.7.x 或 3.x 的LTS版本都是稳妥的选择。新项目可以从3.x开始注意其最低要求JDK 17。持久层ORM框架MyBatis-Plus。它比纯JPA更贴近国内开发者的SQL习惯代码生成器能极大提升基础CRUD的开发速度对于管理类系统非常友好。数据库MySQL 8.0 或 PostgreSQL。生产环境务必做好主从分离和备份策略的规划。缓存Redis。用于存储会话、热点数据如产品信息、以及简单的排程队列状态。Spring Boot缓存技术可以很方便地通过注解集成但要注意缓存一致性问题。消息队列可选但建议预留。当工单状态变更、计划更新需要通知其他系统如MES、WMS时消息队列是解耦利器。RabbitMQ或RocketMQ都是常见选择。SpringBoot整合ActiveMQ也是一种方案但ActiveMQ在吞吐量和社区活跃度上相对弱一些。任务调度计划系统本身可能就有定时任务需求如每天凌晨自动运行MRP计算。Spring自带的Scheduled注解适合简单场景更复杂的分布式调度可以考虑XXL-JOB或Quartz集成。API文档Swagger。用SpringBoot增加Swagger依赖并简单配置可以自动生成API文档前后端协作效率倍增。工具包Hutool、Lombok等能减少很多样板代码。2.2 前端技术栈分离部署快速迭代推荐前后端分离架构。后端提供RESTful API前端独立部署。Vue 3 Element Plus是目前管理后台类项目非常主流和高效的选择。组件丰富生态成熟。构建工具Vite开发热更新速度极快。2.3 项目初始化与关键配置使用IDEA的Spring Initializr或阿里云的 start.aliyun.com 快速生成项目骨架。pom.xml文件是依赖管理的核心初期不必引入所有功能。按需添加例如dependencies !-- Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 数据库 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version最新版本/version /dependency !-- 缓存 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- 文档 -- dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version2.x/version /dependency !-- 工具 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependenciesapplication.yml配置要点server: port: 8080 servlet: context-path: /api # 建议统一API前缀 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/prod_plan?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: your_password redis: host: localhost port: 6379 database: 0 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发阶段开启SQL日志 global-config: db-config: logic-delete-field: deleted # 逻辑删除字段 logic-delete-value: 1 logic-not-delete-value: 0 # Swagger/OpenAPI 配置 springdoc: api-docs: path: /v3/api-docs swagger-ui: path: /swagger-ui.html注意生产环境务必移除SQL日志打印并妥善保管数据库密码。3. 核心数据库设计与领域建模数据库设计直接决定了系统的扩展性和性能。不要一上来就对着界面画表要先理解业务实体和它们之间的关系。3.1 核心表结构设计简化版以下是最核心的几张表用于支撑第一节描述的闭环产品表 (product)CREATE TABLE product ( id bigint NOT NULL COMMENT 主键, code varchar(64) NOT NULL COMMENT 产品编码, name varchar(255) NOT NULL COMMENT 产品名称, spec varchar(500) DEFAULT NULL COMMENT 规格型号, unit varchar(20) DEFAULT NULL COMMENT 单位, type tinyint DEFAULT NULL COMMENT 类型1-成品2-半成品3-原材料, PRIMARY KEY (id), UNIQUE KEY uk_code (code) ) COMMENT产品表;物料清单表 (bom)CREATE TABLE bom ( id bigint NOT NULL, parent_product_id bigint NOT NULL COMMENT 父产品ID, component_product_id bigint NOT NULL COMMENT 子件/原材料产品ID, quantity decimal(12,4) NOT NULL COMMENT 单台用量, loss_rate decimal(5,4) DEFAULT 0.0000 COMMENT 损耗率, PRIMARY KEY (id), KEY idx_parent (parent_product_id) ) COMMENT物料清单表;一个成品parent对应多条BOM记录。type字段可以区分替代料、虚拟件等初期可省略。销售订单表 (sales_order)CREATE TABLE sales_order ( id bigint NOT NULL, order_no varchar(64) NOT NULL COMMENT 订单号, customer_name varchar(255) DEFAULT NULL COMMENT 客户, product_id bigint NOT NULL COMMENT 产品ID, quantity decimal(12,4) NOT NULL COMMENT 订单数量, delivery_date date NOT NULL COMMENT 要求交货日期, status tinyint DEFAULT 1 COMMENT 状态1-待处理2-已计划3-已关闭, PRIMARY KEY (id) ) COMMENT销售订单表;物料库存表 (material_stock)CREATE TABLE material_stock ( id bigint NOT NULL, product_id bigint NOT NULL COMMENT 物料产品ID, warehouse varchar(100) DEFAULT NULL COMMENT 仓库, location varchar(100) DEFAULT NULL COMMENT 库位, quantity decimal(12,4) NOT NULL DEFAULT 0.0000 COMMENT 当前库存数量, locked_quantity decimal(12,4) DEFAULT 0.0000 COMMENT 已锁定数量已分配未出库, PRIMARY KEY (id), UNIQUE KEY uk_product_warehouse (product_id,warehouse) ) COMMENT物料库存表;locked_quantity用于实现简单的库存预留防止超卖。工作中心表 (work_center)CREATE TABLE work_center ( id bigint NOT NULL, code varchar(64) NOT NULL COMMENT 工作中心编码, name varchar(255) NOT NULL COMMENT 名称, daily_capacity decimal(10,2) DEFAULT NULL COMMENT 日产能小时, efficiency decimal(5,4) DEFAULT 1.0000 COMMENT 效率系数, calendar_id bigint DEFAULT NULL COMMENT 关联日历ID, PRIMARY KEY (id) ) COMMENT工作中心表;工艺路线表 (process_route) 与 工序表 (process_step)-- 工艺路线头 CREATE TABLE process_route ( id bigint NOT NULL, product_id bigint NOT NULL COMMENT 产品ID, version varchar(20) DEFAULT A COMMENT 版本, PRIMARY KEY (id), UNIQUE KEY uk_product_version (product_id,version) ) COMMENT工艺路线表; -- 工艺路线明细工序 CREATE TABLE process_step ( id bigint NOT NULL, route_id bigint NOT NULL COMMENT 工艺路线ID, step_no int NOT NULL COMMENT 工序序号, work_center_id bigint NOT NULL COMMENT 工作中心ID, setup_time decimal(8,2) DEFAULT 0.00 COMMENT 准备时间小时, process_time decimal(8,4) NOT NULL COMMENT 单件加工时间小时/件, description varchar(500) DEFAULT NULL COMMENT 工序描述, PRIMARY KEY (id), KEY idx_route (route_id) ) COMMENT工序表;生产工单表 (work_order)CREATE TABLE work_order ( id bigint NOT NULL, order_no varchar(64) NOT NULL COMMENT 工单号, product_id bigint NOT NULL COMMENT 产品ID, plan_quantity decimal(12,4) NOT NULL COMMENT 计划数量, status tinyint NOT NULL DEFAULT 1 COMMENT 状态1-已创建2-已排程3-已下达4-生产中5-已完成6-已关闭, plan_start_time datetime DEFAULT NULL COMMENT 计划开始时间, plan_end_time datetime DEFAULT NULL COMMENT 计划结束时间, actual_start_time datetime DEFAULT NULL, actual_end_time datetime DEFAULT NULL, priority int DEFAULT 10 COMMENT 优先级数字越小优先级越高, source_order_id bigint DEFAULT NULL COMMENT 来源销售订单ID, PRIMARY KEY (id) ) COMMENT生产工单表;3.2 领域模型与Service层设计有了表结构在Java中需要建立对应的实体类。使用MyBatis-Plus可以配合Lombok简化代码。Data TableName(work_order) public class WorkOrder { TableId(type IdType.ASSIGN_ID) // 使用雪花算法ID private Long id; private String orderNo; private Long productId; private BigDecimal planQuantity; private Integer status; private LocalDateTime planStartTime; private LocalDateTime planEndTime; private Integer priority; private Long sourceOrderId; // 其他字段... }业务逻辑集中在Service层。例如WorkOrderService中会包含创建工单、排程、状态变更等方法。这里的关键是事务管理。例如创建工单并扣减物料库存必须在一个事务内完成否则会导致数据不一致。Service Transactional(rollbackFor Exception.class) public class WorkOrderServiceImpl extends ServiceImplWorkOrderMapper, WorkOrder implements WorkOrderService { Autowired private MaterialStockService stockService; Override public boolean createAndAllocate(WorkOrder workOrder, ListMaterialRequirement requirements) { // 1. 保存工单 this.save(workOrder); // 2. 为工单分配物料锁定库存 for (MaterialRequirement req : requirements) { stockService.lockStock(req.getProductId(), req.getWarehouse(), req.getQuantity()); } // 如果任何一步失败整个事务回滚 return true; } }4. 核心业务逻辑实现MRP与排程这是系统的“大脑”。初期可以简化但逻辑必须清晰。4.1 简化的MRP计算服务MRP的核心是需求分解和净需求计算。我们实现一个最简单的版本只考虑一层BOM不考虑在途、安全库存和批量政策。Service public class MrpService { Autowired private SalesOrderService salesOrderService; Autowired private BomService bomService; Autowired private MaterialStockService stockService; /** * 为指定销售订单计算物料需求 * param orderId 销售订单ID * return 物料需求清单 */ public ListMaterialRequirement calculateRequirement(Long orderId) { SalesOrder order salesOrderService.getById(orderId); ListMaterialRequirement result new ArrayList(); // 1. 获取订单产品 Product finishedProduct productService.getById(order.getProductId()); // 2. 获取该产品的BOM ListBom bomList bomService.listByParentProductId(finishedProduct.getId()); for (Bom bom : bomList) { MaterialRequirement req new MaterialRequirement(); req.setProductId(bom.getComponentProductId()); // 3. 计算毛需求 订单数量 * BOM用量 * (1 损耗率) BigDecimal grossReq order.getQuantity() .multiply(bom.getQuantity()) .multiply(BigDecimal.ONE.add(bom.getLossRate())); // 4. 查询当前可用库存 (当前库存 - 已锁定库存) BigDecimal availableStock stockService.getAvailableStock(bom.getComponentProductId()); // 5. 计算净需求 毛需求 - 可用库存 (如果为负则取0) BigDecimal netReq grossReq.subtract(availableStock); if (netReq.compareTo(BigDecimal.ZERO) 0) { netReq BigDecimal.ZERO; } req.setQuantity(netReq); if (netReq.compareTo(BigDecimal.ZERO) 0) { result.add(req); } } return result; } }这个计算结果是“需要多少物料”。实际项目中净需求还会触发采购建议或生产建议对于半成品。4.2 基于有限产能的后向排程排程算法极其复杂工业级APS高级计划排程系统是另一个专业领域。我们实现一个最基本的后向排程从交货日期倒推考虑每个工序的标准工时和工作中心产能。假设条件工作中心每天工作8小时。工序之间没有等待时间。排程时暂时忽略其他已排产任务即无限产能假设。Service public class SchedulingService { Autowired private ProcessRouteService routeService; Autowired private WorkCenterService workCenterService; /** * 为工单计算计划开始和结束时间后向排程 * param workOrder 工单 * param deliveryDate 要求完工日期 * return 排程结果 */ public ScheduleResult backwardSchedule(WorkOrder workOrder, LocalDate deliveryDate) { ScheduleResult result new ScheduleResult(); // 1. 获取产品的工艺路线 ProcessRoute route routeService.getByProductId(workOrder.getProductId()); ListProcessStep steps routeService.getStepsByRouteId(route.getId()); // 假设最后一道工序在交货日下班前完成 LocalDateTime currentEndTime deliveryDate.atTime(17, 0); // 下午5点下班 ListStepSchedule stepSchedules new ArrayList(); // 2. 倒序计算每道工序 for (int i steps.size() - 1; i 0; i--) { ProcessStep step steps.get(i); StepSchedule ss new StepSchedule(); ss.setStep(step); // 计算该工序总工时 准备时间 (单件时间 * 工单数量) BigDecimal totalHours step.getSetupTime() .add(step.getProcessTime().multiply(workOrder.getPlanQuantity())); // 将工时转换为工作日简化按8小时/天 double daysNeeded totalHours.doubleValue() / 8.0; // 计算计划开始时间从结束时间往前推 LocalDateTime planStart calculateStartTime(currentEndTime, daysNeeded); ss.setPlanStartTime(planStart); ss.setPlanEndTime(currentEndTime); stepSchedules.add(0, ss); // 按正序插入列表 // 当前工序的开始时间是上一道工序在循环中的结束时间 currentEndTime planStart; } result.setStepSchedules(stepSchedules); if (!stepSchedules.isEmpty()) { result.setPlanStartTime(stepSchedules.get(0).getPlanStartTime()); result.setPlanEndTime(stepSchedules.get(stepSchedules.size() - 1).getPlanEndTime()); } // 3. 将最终的计划时间更新到工单 workOrder.setPlanStartTime(result.getPlanStartTime()); workOrder.setPlanEndTime(result.getPlanEndTime()); workOrder.setStatus(2); // 状态更新为“已排程” // ... 保存工单 return result; } private LocalDateTime calculateStartTime(LocalDateTime endTime, double daysNeeded) { // 简化计算不考虑节假日直接减去所需天数 long hoursToSubtract (long) (daysNeeded * 8); return endTime.minusHours(hoursToSubtract); } }这个算法非常初级但足以演示排程的核心思想时间推算和产能占用。真实的排程还需要考虑有限产能检查工作中心在计划时间段内是否已被占用。工序重叠某些工序可以并行。换模时间产品切换带来的设备准备时间。优先级规则紧急订单插单处理。对于初期系统可以先使用这个简化算法让计划员能看到一个初步的时间线然后再手动调整。这比完全没有排程要前进一大步。5. 前端界面与API交互让数据流动起来后端逻辑完成后需要通过清晰的界面和稳定的API暴露给用户。5.1 RESTful API设计要点遵循RESTful风格保持接口语义清晰。GET /api/work-orders获取工单列表可分页、过滤、排序。GET /api/work-orders/{id}获取单个工单详情。POST /api/work-orders创建新工单。PUT /api/work-orders/{id}更新工单信息。POST /api/work-orders/{id}/schedule为指定工单执行排程。POST /api/mrp/calculate?orderIdxxx触发MRP计算。使用SpringBoot常用注解简化开发RestController RequestMapping(/api/work-orders) Api(tags 生产工单管理) public class WorkOrderController { Autowired private WorkOrderService workOrderService; GetMapping ApiOperation(分页查询工单列表) public RPageWorkOrderVO list(RequestParam(required false) Integer status, RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize) { PageWorkOrder page new Page(pageNum, pageSize); LambdaQueryWrapperWorkOrder queryWrapper new LambdaQueryWrapper(); if (status ! null) { queryWrapper.eq(WorkOrder::getStatus, status); } queryWrapper.orderByDesc(WorkOrder::getId); PageWorkOrder resultPage workOrderService.page(page, queryWrapper); // 转换为VO对象... return R.ok(voPage); } PostMapping(/{id}/schedule) ApiOperation(为工单排程) public RScheduleResult schedule(PathVariable Long id, RequestBody ScheduleRequest request) { WorkOrder order workOrderService.getById(id); if (order null) { return R.failed(工单不存在); } ScheduleResult result schedulingService.backwardSchedule(order, request.getDeliveryDate()); return R.ok(result); } }注意R是一个自定义的通用响应体包含code、msg、data。VO是视图对象用于过滤掉不必要的实体字段。5.2 前端页面关键功能使用Vue 3 Element Plus可以快速搭建以下核心页面基础数据维护产品、BOM、工作中心、工艺路线的增删改查列表页。BOM维护界面最好支持树形展示和拖拽。销售订单管理列表页和表单页。在表单页选择产品后可以联动显示产品信息。MRP运算界面提供一个操作按钮选择销售订单后触发后端计算并以表格形式展示计算出的物料净需求清单。工单管理工单列表显示所有工单支持按状态、产品、时间筛选。状态可以用标签Tag直观显示。工单详情/编辑查看和修改工单信息。排程操作在工单行或详情页有一个“排程”按钮点击后弹出对话框让用户确认或修改要求完工日期然后调用排程API并将返回的计划时间展示出来。甘特图视图这是计划系统的“仪表盘”。可以使用如dhtmlx-gantt或frappe-gantt等开源库将工单和工序以时间条的形式展示在时间轴上。拖拽时间条可以调整计划并同步回后端。库存查询查看物料的当前库存、锁定库存和可用库存。前后端联调时重点关注数据一致性和用户体验。例如创建工单时前端应实时验证产品ID是否存在排程计算可能较耗时需要添加加载状态提示。6. 部署、监控与生产环境考量系统开发完成如何在生产环境稳定运行是另一个挑战。6.1 部署方式选择传统部署将Spring Boot打成的可执行JAR包放在服务器上用nohup java -jar app.jar 或systemd服务来运行。SpringBoot 直接打jar包运行是最简单的方式。容器化部署使用Docker。编写Dockerfile将应用、JDK打包成镜像。Docker部署SpringBoot项目能保证环境一致性。FROM openjdk:17-jdk-slim VOLUME /tmp COPY target/*.jar app.jar ENTRYPOINT [java,-jar,/app.jar]容器编排部署在微服务架构或需要高可用时使用Kubernetes。k8s部署SpringBoot项目涉及Deployment、Service、Ingress等资源配置。6.2 生产环境关键配置数据库连接池使用HikariCP在application-prod.yml中调整参数。spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 10 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000日志配置Logback或Log4j2将日志按级别输出到文件并设置滚动策略。生产环境关闭DEBUG日志。监控集成Spring Boot Actuator暴露健康检查、指标等信息。可以搭配Spring Boot Admin搭建一个简单的监控面板。异常处理使用ControllerAdvice实现全局异常处理器将系统异常转换为友好的错误信息返回给前端同时记录详细日志用于排查。安全使用Spring Security实现认证和授权。API接口做好权限控制。对用户上传的文件如果有进行病毒扫描和大小限制防止恶意上传。SpringBoot解决PDF XSS攻击这类问题本质是对所有外部输入进行严格的校验和过滤。6.3 信创环境适配如果项目需要适配信创环境国产化这是一个系统工程不仅仅是更换应用服务器。服务器可能从CentOS转向麒麟、统信UOS。中间件数据库可能换为达梦、金仓、OceanBase。缓存可能换为腾讯云Tendis等兼容Redis协议的国产产品。应用服务器Tomcat是Spring Boot内嵌的通常没问题。如果需要外置东方通的TongWeb、金蝶的Apusic等是常见选择。是否需要更换取决于部署环境的具体要求。通常Spring Boot内嵌Tomcat打成的JAR包只要JDK是兼容的如龙芯的Loongson JDK、华为的毕昇JDK在国产操作系统上可以直接运行。只有在客户明确要求必须使用特定国产应用服务器时才需要将应用打包成WAR包并部署到TongWeb中。芯片可能运行在鲲鹏、飞腾、龙芯等架构上。关键是要使用对应架构的JDK。适配信创的首要步骤是在目标国产化环境上从编译到运行完整地走通一遍CI/CD流程尽早发现兼容性问题。6.4 常见问题排查清单系统上线后遇到问题可按此顺序排查应用启动失败检查java -version确认JDK版本符合Spring Boot要求。检查application.yml配置特别是数据库、Redis连接信息。检查端口是否被占用。查看启动日志寻找Error或Exception关键字。数据库连接问题检查数据库服务是否启动。检查连接IP、端口、用户名、密码是否正确。检查数据库驱动版本是否匹配。检查防火墙设置。业务逻辑错误MRP计算不准检查BOM数据是否正确库存数据是否及时更新计算逻辑的循环和累加是否有误。排程时间不合理检查工艺路线中的工时单位是小时还是分钟检查工作中心日历数据检查排程算法的日期计算逻辑是否考虑了非工作日。库存数据不同步检查工单创建、领料、入库等操作是否都在事务内是否有并发操作导致的数据覆盖。考虑使用数据库悲观锁或乐观锁。性能问题列表查询慢检查是否缺少索引特别是where和order by涉及的字段。使用MyBatis-Plus的TableField注解优化查询字段。排程计算慢当工单和工序数量很大时后向排程的循环计算可能变慢。考虑对算法进行优化或引入缓存将已排程结果缓存起来除非基础数据变更。前端甘特图加载卡顿一次不要加载太多时间范围的数据采用分页或滚动加载。前端显示问题控制台乱码确认后端接口返回的Content-Type头包含charsetUTF-8前端Axios请求也统一使用UTF-8编码。IDEA中SpringBoot应用运行控制台乱码通常是因为IDE或终端编码设置问题与项目本身关系不大。时间显示不对前后端传递时间时统一使用时间戳或ISO 8601格式如yyyy-MM-ddTHH:mm:ss并明确时区。开发这样一个系统最大的挑战往往不是技术实现而是对生产管理业务的理解和抽象。最好的做法是与未来的使用人员计划员、生产主管保持紧密沟通用最短的周期交付一个可用的最小版本然后根据他们的实际反馈快速迭代。把系统当作一个不断进化的“活工具”而不是一个一次性交付的“死项目”。