☰
C# + Vue3 打造全流程MES制造执行系统:从工单到成品入库
2026/10/24 19:22:23 网站建设 项目流程

简介:这是一套面向工业数字化转型场景的智能工厂管理系统(MES)完整开发资源,适用于制造业IT工程师、高校毕业设计学生、求职者项目实战积累及.NET+Vue全栈开发者学习参考。系统聚焦生产制造过程管理核心业务,提供从订单排程、工单执行、工序报工到质量追溯的全流程支撑能力。资源包含1442个文件,主体为982个C#后端服务代码文件(含ServiceBase、EntityProperties等通用模块)、156个Vue3前端组件及130个JS业务逻辑脚本,辅以MSSQL与MySQL双数据库脚本、自动化部署bat脚本及Docker配置文件,整体压缩包仅20.2MB,结构清晰、开箱即用。目前已有477人学习下载,配套环境配置说明详尽,涵盖Vue3 CLI安装、镜像切换及历史版本回滚等实操细节,特别适合快速搭建本地开发环境并深入理解MES系统前后端协同机制。 做制造业数字化这几年,我经手过不少MES相关的项目,有从零搭建的,也有在老旧系统上做改造的。说实话,MES这个领域看着门槛不高,真要做扎实,牵扯的东西比想象中多得多——工单怎么流转、报工怎么防错、追溯怎么打通、权限怎么控制,每一环都是坑。今天想聊的这套系统,算是我个人比较满意的一套完整落地案例:C# + Vue3 + MSSQL/MySQL双库支持,从工单下发到成品入库的全流程制造执行管理,前后端源码和数据库脚本都是齐的。这篇文章我会从系统设计思路、核心功能拆解、数据库脚本设计、实际部署过程几个维度展开,顺便把开发中踩过的坑一并交代清楚,希望能给正在做MES选型或者准备自研MES的朋友一些参考。

1. 项目整体设计与技术选型思路

1.1 MES在工厂里的定位,和ERP到底有什么区别

很多刚接触这个领域的人会混淆MES和ERP,我这边简单说清楚。ERP管的是“计划层”,比如销售订单、采购计划、财务成本这些,颗粒度通常到天、到周;MES管的是“执行层”,负责车间里每一道工序的派工、报工、质检、设备状态、物料消耗,颗粒度要到分钟、到个人、到设备。举个直观的例子:ERP告诉你这个月要生产1000台设备,MES告诉你今天上午9点到12点,3号产线A工位的张三,正在组装第247台,用掉了143颗螺丝,其中2颗报废。

这套系统在设计时,我一开始就没有打算把MES做成一个孤岛系统。它保留了与ERP的关键接口位,比如工单可以由ERP下发,也可以直接在MES里手工创建;生产完成后的完工数据,也能通过接口回传给ERP用于成本核算。这是MES项目里非常常见的定位——既不越权去管计划层的事,又要把车间执行的数据牢牢抓在手里。

1.2 为什么选C# + Vue3,而不是Java或别的组合

技术栈选型这个问题,我在项目启动前反复权衡过。先说后端,C#(具体是.NET 6/8,Web API形式)在制造业主流生态里的地位确实特殊。国内的工厂一线设备,PLC通信、上位机、WinCC这些,大多是Windows环境,C#在这块的类库支持和社区积累非常厚。如果你后面要做设备数据采集(PLC、OPC UA、Modbus TCP),C#基本是首选语言。再说法务和部署,.NET的部署越来越简单,IIS一挂或者直接dotnet跑起来都行,不挑环境。

前端选Vue3是另一个维度的考量。MES这种系统的页面类型高度集中——表单、表格、弹窗、看板大屏,Vue3的Composition API在组织这类中后台业务逻辑时,比Options API顺手得多。尤其是一个组件里既要有表单校验、又要调接口、还要联动其他组件状态时,setup语法糖写起来非常清爽。配合Element Plus这套成熟组件库,开发效率比从零写组件高出几个数量级。更关键的是Vue3的生态现在很稳,不会像早期那样遇到插件断层的问题。

1.3 双数据库兼容:MSSQL和MySQL两套脚本的设计取舍

这个项目同时带MSSQL和MySQL两套脚本,可能有人会觉得是不是工作量翻倍了。确实,背后的开发量不小,但这是我从实际项目经验里总结出来的必要工作。国内制造业的数据库现状非常分裂:老牌外企和大型国企多用SQL Server,中小型民营制造企业用MySQL的比例则很高,甚至还有不少用Oracle的(这个我暂时没覆盖)。如果你的MES产品只支持一种数据库,销售阶段就会丢掉一大半机会。

要做到双库兼容,最核心的一条经验是:业务逻辑尽量放在C#代码里,数据库只做数据存储和基础约束。存储过程、触发器这类东西在双库环境下就是灾难,语法差异、函数差异会让你维护到怀疑人生。我在这个项目里所有的复杂业务都是在后端代码里处理的,SQL脚本里只有表结构、索引、初始化数据和少量视图,这样两套脚本的维护成本才可控。具体差异点我在后面第三章会详细展开。

2. MES核心功能模块与生产流程拆解

2.1 工单全生命周期管理:从创建到关闭

工单是MES系统的核心主线,几乎所有业务都是围绕工单展开的。这套系统里,工单的状态机我设计了五个节点:待下发、生产中、已完工、已关闭、已取消。前面四个是正常流程,最后一个是异常处理。很多没经验的设计会把状态搞得很复杂,什么待审核、待排产、待领料叠了一大堆,结果车间操作工根本记不住,反而容易点错。我的原则是:状态越少越好,每个状态对应一个明确的操作动作,这样一线工人不容易出错。

工单创建时,系统会带出产品对应的工艺路线和BOM(物料清单),这是MES有别于普通进销存软件的重要特性。一个产品走哪几道工序、每道工序在哪个车间、需要哪些物料,由工艺路线和BOM决定。操作人员在创建工单时只需要选择产品、填写数量和计划交付日期,系统自动展开后续的工序计划。这背后是“基础数据先行”的理念——如果物料、BOM、工艺路线这些基础档案不维护好,MES跑起来全是脏数据。

2.2 工序流转与报工:车间最核心的交互

车间层每天使用频率最高的功能就是工序报工和流转。一个工单从第一道工序开始,每完成一道就报一次工,然后进入下一道。这套系统的报工界面我在设计时反复推敲过:左边是待报工的工单列表,右边是选定工单的工序进度,操作工只需要输入“合格数量”和“不良数量”,点提交就完成报工,整个操作控制在3秒以内。车间里不是IT人员,界面做得越简单直接越好。

工序流转的底层逻辑是一个排队队列。每道工序报工完成后,系统自动判断是否所有前置工序都完成了,如果完成了,工单就进入下一道工序的待处理列表。这里有个容易被忽略的细节:并批和拆批。在实际生产中,两道工序之间经常会有多个工单合并生产(并批),或者一个工单因为设备产能原因拆成两批(拆批)。这套系统对这两种情况都做了支持,流转逻辑里维护了批次父子关系。

2.3 质量检验与不良品处理闭环

制造企业的质量部门对MES最看重的就是质检模块。这套系统的质检分三个环节:来料检验(IQC)、过程检验(IPQC)、完工检验(FQC)。来料检验在物料入库时触发,过程检验在工序报工完成时按比例抽检,完工检验在最后一道工序完成后整单检验。每个检验环节都支持判定结果——合格、让步接收、返工、报废,然后自动流转到对应的处理流程。

比较有意思的是不良品处理这块。返工不是简单地把状态改回去重新做,而是生成一条返工任务,关联到原工单和原工序,并记录返工原因、返工人、返工时间。报废则是从库存里扣减对应数量,同时留下质量追溯记录。这样月底质量部门做不良分析时,可以看到完整的不良品分布——哪个产品、哪个批次、哪道工序、哪种不良类型,全链路数据都是通的。

2.4 设备、物料与追溯管理

设备管理模块虽然不像工单那样天天被点到,但在MES里属于基础配置。设备台账记录了每台设备的基本信息、所属车间、稼动率计算基准。点检和保养计划按周期自动生成任务,维修记录则关联到具体设备。这些数据最终汇总到设备综合效率(OEE)报表里,是生产管理者评估产能瓶颈的重要依据。

物料管理这边,重点是“领料-投料-余料退回”的三步闭环。工单下发后,车间根据BOM开领料单;生产过程中每一步投料都会记录批次号;如果完工后有剩余物料,系统引导操作工做余料退回。这样每个工单实际消耗了多少物料,财务和仓库都能查得清清楚楚。追溯管理这块就更关键了——正追溯是从原材料批次到成品批次,反向追溯是从成品批次倒查使用了哪些原材料批次。系统里的关键物料(比如电子产品的主芯片)都要求扫码录入序列号,全程记录,真要出质量问题,几分钟就能锁定问题批次和影响范围。

2.5 报表看板:管理者的数据窗口

MES做得好不好,管理层最直观的感受就是报表。这套系统的报表模块包括:日产量报表(按产线、按班组、按产品维度)、工时统计报表、设备稼动率报表、不良率趋势分析、工单完工进度看板。前四个都是传统报表,最后一个看板我用了大屏模式——D3和ECharts结合,车间里挂一块电视屏幕,实时轮播各产线的生产进度、当前在线工单、报警信息,很能提升数字化观感。

这里有个实践心得:报表功能别一上来就做得很重。很多团队喜欢一上来就搞自助式BI、拖拽式报表平台,结果做着做着发现业务根本提不出需求,做出来的报表没人看。我的建议是先做固定报表,把管理层最常问的几个问题(今天产量多少、目前哪些工单逾期、哪个设备故障最多)做成固定页面,跑一段时间再慢慢沉淀自助分析的需求。

3. 数据库设计:MSSQL和MySQL双版本脚本的落地

3.1 核心表结构设计思路

数据库是MES的地基,表结构设计的好坏直接决定系统能用多久。这套系统的核心表大约二十多张,按业务域可以分成五组:

  • 基础数据域:产品表、物料表、BOM表、工序表、工艺路线表、车间/产线/工位表、设备台账表
  • 工单域:工单主表、工单工序表、工单物料表、报工记录表
  • 质量域:检验任务表、检验记录表、不良品处理表
  • 库存域:物料库存表、领料单表、投料记录表、退料记录表
  • 系统域:用户表、角色表、菜单权限表、用户角色关联表、操作日志表

工单主表是最关键的一张表,我把它的核心字段列出来给你们参考:工单号、产品ID、计划数量、已完成数量、不良数量、状态(对应前面说的五状态机)、当前工序ID、计划开始时间、计划结束时间、实际开始时间、实际结束时间、创建人、创建时间。其中“已完成数量”是冗余字段,实际计算是从报工记录表按工单汇总的,冗余存储是为了列表页查询性能。

3.2 两套SQL脚本的差异与适配

这是整个项目里最枯燥但又最考验细心的部分。MSSQL和MySQL虽然都是关系型数据库,但在脚本层面有太多细小的语法差异,不踩一遍根本不知道。我列几个典型的差异点:

功能项MSSQL写法MySQL写法
自增主键ID INT IDENTITY(1,1)ID INT AUTO_INCREMENT
分页查询OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLYLIMIT 10, 20
字符串拼接'a' + 'b'CONCAT('a','b')
获取当前时间GETDATE()NOW()
判断字段为NULLISNULL(col, 0)IFNULL(col, 0)
存储过程声明CREATE PROCEDURECREATE PROCEDURE(但内部语法差异更大)

看到这个对比你可能就明白了,为什么我前面强调业务逻辑要放在代码里。存储过程如果写得不兼容,双库适配的工作量会非常可观。这套系统的两套脚本,除了这些语法层面的差异外,我还注意了几个细节:字段类型的选择(比如金额字段两边都用DECIMAL(18,2))、字符集统一用utf8mb4(MySQL那边)和NVARCHAR(MSSQL那边)、以及每个表的主键索引命名规范。

另外在脚本文件组织上,我建议按“建库脚本 → 建表脚本 → 初始数据脚本 → 索引脚本”分文件管理,不要一把梭地把所有内容放在一个文件里。这样后期迭代维护时,哪个环节出问题就去看哪个文件,不用在一个几千行的脚本里翻来翻去。

3.3 索引、事务与并发控制

MES系统的访问模式很典型——频繁写、频繁查、并发不高但数据一致性要求高。这套系统里我建索引的策略是:每个表的外键字段和业务查询条件字段都建索引,比如工单表的“状态”、“当前工序ID”,报工记录表的“工单ID+工序ID”,物料表的“物料编码”。但索引不是越多越好,写入频繁的表上索引太多,会影响写入性能。这个度需要在压测时观察慢查询日志来调整。

事务控制这块重点说下报工。一个完整的报工动作,涉及的操作不止一条SQL:更新工单的已完成数量、插入报工记录、更新当前工序状态、可能还要扣减物料库存。这些操作必须放在同一个数据库事务里,任何一个环节失败都要整体回滚,否则就会出现“报工成功但工单进度没动”这种数据不一致的诡异问题。这套系统里,我在Web API层的报工接口上统一加了事务处理,并且在关键数据表(工单表)上使用乐观锁(版本号字段),防止两个人同时报工时互相覆盖。

注意:报工接口的并发控制不是小问题。车间里常有多个操作工同时报工的场景,如果不用乐观锁或数据库行锁,累计的完成数量就会被后者覆盖,导致产量统计少算。这属于上线后最容易暴露、也最影响信任感的问题。

4. 从源码到运行:开发环境与部署实操

4.1 开发环境准备

这套系统要跑起来,你需要准备以下基础环境。后端和数据库二选一即可(MSSQL和MySQL选一个),前端则是统一的。

  • 后端:Visual Studio 2022 或 Rider,.NET SDK 6.0 以上(建议 .NET 8),Windows/Linux均可
  • 前端:Node.js 16 以上,npm或pnpm包管理器
  • 数据库一:SQL Server 2016及以上版本,或者SQL Server Express(开发够用)
  • 数据库二:MySQL 5.7 或 8.0,Navicat或Workbench等客户端工具

我实际开发时用的是VS2022 + .NET 8 + SQL Server 2019,前端是Vue3 + Vite + TypeScript + Element Plus组合。需要提醒的是,如果你本机没有SQL Server,直接用MySQL跑也是完全没问题的,项目的两套脚本是等价的,按需执行一份即可。

4.2 后端启动与配置

后端项目用VS打开解决方案文件后,第一件事是修改appsettings.json里的连接字符串。以MySQL为例:

{ "ConnectionStrings": { "MySql": "Server=localhost;Port=3306;Database=mes_db;User=root;Password=123456;CharSet=utf8mb4;" } }

连接字符串里的CharSet=utf8mb4这个参数容易被忽视,但它是中文不乱码的关键。如果你用MSSQL,对应连接字符串类似:

{ "ConnectionStrings": { "SqlServer": "Server=localhost;Database=mes_db;User Id=sa;Password=123456;TrustServerCertificate=True;" } }

改完连接字符串后,先去执行数据库脚本,把表结构和初始数据跑出来。然后F5启动后端,默认监听端口在launchSettings.json里定义,我这边是http://localhost:50806,启动后浏览器访问 /swagger 就能看到接口文档列表。初期联调阶段,Swagger非常有用,可以直接在上面测试每个接口的入参出参。

4.3 前端运行与联调

前端部分,Vue3项目使用Vite构建,启动命令是常规的npm install,然后npm run dev。前端本地默认监听5173端口,但它不可能直接去请求后端50806端口(浏览器跨域限制),所以需要一个代理配置。Vite的代理在vite.config.ts里配置:

server: { port: 5173, proxy: { '/api': { target: 'http://localhost:50806', changeOrigin: true } } }

前端的axios实例基础路径设为 /api,这样开发时所有接口请求都会通过Vite代理转发到后端,既解决了跨域问题,又能在生产部署时无缝切换。前端里关于请求封装,我统一做了三件事:请求拦截器里自动带token(从localStorage读取)、响应拦截器里统一处理HTTP错误码和业务错误码、超时时间统一设15秒。这三个基础封装做好,后面开发业务页面的效率会高很多。

4.4 生产环境部署:IIS与Nginx两种方案

生产部署有两种常见方案,取决于你部署在Windows还是Linux服务器。

先说Windows + IIS部署后端。发布后端项目,在VS里右键项目选择发布到文件夹,把发布出来的文件拷到服务器的某个目录(比如D:\apps\mes-api),然后在IIS里新建网站,物理路径指向这个目录,应用程序池选择“无托管代码”,绑定端口比如8088。注意IIS需要安装ASP.NET Core Hosting Bundle运行时,否则网站会一直报503或500.19错误,这个问题我见过太多次了。

前端部署更简单。执行npm run build会生成一个dist目录,把dist里的文件拷到IIS的另一个网站目录或Nginx的html目录即可。如果前后端都在同一台服务器上,可以用IIS的URL Rewrite做一个反向代理:访问/api/*的请求转发到8088端口,其余请求走前端静态文件。

Linux + Nginx方案则优雅一些,把所有服务都容器化或直接用进程管理工具跑。后端用dotnet myapi.dll直接运行,前面挂Nginx做反向代理,MSSQL或MySQL也用Docker跑。一套docker-compose.yml就能编排整个环境,但MSSQL在Linux的Docker里内存占用较大,低配服务器会吃力,建议小项目直接用MySQL。

5. 开发中高频踩坑实录与排查技巧

5.1 前后端分离调试中的跨域与代理问题

这个坑几乎每个做前后端分离的人都遇到过,但具体到MES项目里会更头疼。因为MES操作工用的往往是车间里的老旧电脑,浏览器版本低,有时不是标准Chrome、Edge,而是各种套壳浏览器,这会导致前端某些新特性不支持。我踩过的一个实际问题:某台车间电脑上页面白屏,后来排查发现是那个套壳浏览器不支持ES6的某些新语法,Vite默认构建的target是modules(ES2020),老浏览器直接挂。

解决办法是在vite.config.ts里把build.target调低(比如es2015),或者干脆用@vitejs/plugin-legacy做兼容。另外,如果前端部署和生产环境不在同一个域名下,记得在后端Startup.cs里配CORS策略,允许指定来源的跨域请求。我第一次部署时忘记配CORS,前端Nginx代理已经把请求转发过去了,但浏览器端仍然报CORS错误,排查了大半天。

5.2 Vue3组件通信与权限控制的几个坑

Vue3的Composition API写业务逻辑确实方便,但组件通信场景多了以后,如果不注意规范,代码会变得很乱。这个项目里父子组件通信我统一用defineProps和defineEmits,跨级组件统一用Pinia。最怕的是有人直接用provide/inject到处传数据,一时爽了后面维护全是坑。举一个例子:工单详情页和工序报工弹窗是父子组件,报工成功后需要刷新工单详情,我的做法是子组件发射“report-success”事件,父组件监听后重新拉取详情接口,而不是直接修改父组件的状态。这样数据流清晰,不会出现“这个数据到底是谁改的”的悬案。

按钮级权限控制是MES系统里的刚需。很多厂里的要求是:班组长能看到报工按钮,操作工只看自己的工单列表但不能确认完工。前端我用了一个自定义指令v-permission,在登录接口返回的权限码集合里判断当前用户有没有对应权限码,没有就直接从DOM里移除按钮。后端则用[Authorize(Policy = "production:workorder:report")]特性做二次校验。记住一个原则:前端控制体验,后端控制安全。千万不要只做前端隐藏按钮就觉得权限万无一失了,接口可以被直接调用,后端的权限校验必不可少。

5.3 SQL脚本双库兼容的经典报错与解决

即使规划得再细,双库脚本还是会出现各种兼容问题。我印象最深的是分页查询的差异。MSSQL 2012以下版本用ROW_NUMBER()做分页,2012及以上可以用OFFSET...FETCH,而MySQL直接用LIMIT。两套脚本的分页查询写法完全不同,如果某天你在做月度报表时没注意数据库类型,直接拿MSSQL的OFFSET脚本到MySQL执行,肯定是语法错误。

另一个经典坑是NULL值处理。MSSQL里的空字符串和NULL是两回事,但MySQL里默认比较宽松,导致同样的数据在两边跑出不同的统计结果。比如查不良率时,如果不良数为NULL,MSSQL的运算结果是NULL,但MySQL的运算结果可能是0。这就要在SQL里统一使用COALESCE函数做空值兜底。这类问题只能靠经验积累,我做了一个“双库兼容检查清单”,每次写完SQL脚本过一遍清单,能过滤掉80%的兼容性错误。

5.4 并发报工与事务处理的实战经验

最后说一下并发问题。MES系统的并发量不算高,但报工这种高频操作一旦出问题,会直接动摇车间对系统的信任。我遇到过一次比较严重的事故:某天下班前,三个操作工同时给同一个工单报工,结果工单的“已完成数量”被覆盖,少了200多件。查了半天,发现是同事在更新工单数量时先读后写,没有加锁,三个请求互相覆盖了。

后来我把所有涉及数量更新的操作统一改成了原子SQL更新:

UPDATE work_order SET completed_qty = completed_qty + @qty WHERE order_id = @orderId

这样即使并发请求进来,数据库的行锁也会保证更新是顺序执行的,不会出现丢失更新。再配合事务回滚,整个报工链路才算稳定下来。这个经验后来我也写进了团队的开发规范:凡是涉及数值累加的操作,一律用SQL原子表达式,不允许读出来在代码里算完再写回去。

还有一个小细节:车间里的扫码枪本质上是一个键盘输入设备,扫完条码后会模拟回车键。这意味着前端输入框在聚焦状态下,扫码枪扫完会自动触发回车提交。如果你不小心在某个表单上绑定了回车事件,可能会莫名其妙地提交表单。我踩过一次后,专门在扫码输入框上做了处理:扫码枪触发回车的间隔极短,普通人工按键达不到那个速度,所以可以根据两次输入的时间间隔来区分是扫进来的还是手输的,然后做不同的处理逻辑。

MES开发这条路,越往深走越会发现它不只是技术问题,更是管理问题。技术框架选对了、代码写扎实了,解决了后面80%的功能性问题,剩下20%的坑基本都在数据规范和使用习惯层面。希望这套系统的前后端源码和双数据库脚本能帮你顺利起步,少走一些我已经走过的弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询