# 云软件项目开发实训 ## MES 系统的工件排序实现 --- ## 目录 1. 项目目标 2. 项目分析 * 2.1 ER分析 * 2.2 表格设计 3. Restful API接口规范 * 3.1 RESTful API 设计规范 * 3.1.1 使用 HTTP Method 动词来表达操作 * 3.1.2 使用名词来表示资源 * 3.1.3 使用 URI 来定位资源 * 3.1.4 使用查询参数来过滤和分页 * 3.1.5 使用 HTTP状态码来表示请求结果 * 3.1.6 使用 JSON或XML 来表示数据 * 3.1.7 使用版本号来管理 API * 3.1.8 提供清晰的错误信息 * 3.1.9 使用标准的HTTP头部 * 3.2 URI 书写规范 * 3.2.1 使用小写字母 * 3.2.2 使用短划线或下划线分隔单词 * 3.2.3 避免使用空格和特殊字符 * 3.2.4 避免深层嵌套 4. 参考文献 5. Web前端网格布局与最大化功能设计 * 概述 * 网格布局与全屏切换实现 * 功能说明 * 使用说明 6. 用vue 实现前端网格布局与最大化功能设计 * 概述 * Vue 实现网格布局与最大化功能 * 设计思路 * 最终实现 * 功能说明 * 使用说明 --- ### 1. 项目目标 (1) `pplanitem` 是一个生产计划的产品条目表格,见图1所示。 **图1: 生产计划与生产条码关系** * 一个生产任务单 (pplansheet) 对应多个生产物品 (pplanitem),形成一对多 (1-m) 的关系。 一个生产任务对应多条生产物品,表示要生产的产品及数量。`pplanitem` 表格包括以下字段: * `id`: 序号 * `pid`: 生产的产品 * `amount`: 生产产品的数量 * `pplansheet`: 所属的生产任务 见表1所示是一个`pplanitem` 表格的实际例子,该例子包含了生产任务(20250524)所生产产品及数量。 **表1: 生产任务20250524的生产条目** | id | pid | amount | pplansheet | | --- | ----------- | ------ | ---------- | | 1 | PIM-ROB-001 | 2 | 20250524 | | 2 | PIM-CNV-002 | 4 | 20250524 | | 3 | PIM-GEA-003 | 6 | 20250524 | | 4 | PIM-SPD-004 | 10 | 20250524 | | 5 | PIM-MET-005 | 8 | 20250524 | | 6 | PIM-HYD-006 | 7 | 20250524 | | 7 | PIM-LIN-007 | 6 | 20250524 | | 8 | PIM-SEN-008 | 5 | 20250524 | 其中 `pplansheet` 是一个生产任务号。 请根据表1的产品和数量,为每一“件”产品唯一编号,生成 `piece` 表格中的记录。 (2) 利用最小等待时间算法,把`piece` 中的每一件产品依次填写在 `dispatch` 表格里形成该件的一个队列,默认状态为1(等待加工)。每个工位有2个按钮[启动]和[完成],按下[启动]把该工位排在第1的件的状态设置为2(正在加工)。按下[完成]按钮,在`dispatch`中该件的状态设置为3(结束加工)。 (3) 根据工位号,列出该工位的排队信息。 例如设计(01号)工位的队列表见表2所示。 **表2: 设计(01)工位加工产品队列** | 队列号 | 件号 | 产品号 | 产品名称 | 预计耗时 | 备注 | | ------ | ----------- | ----------- | ------------------ | -------- | --------- | | 1 | ps202505001 | PIM-ROB-001 | 全自动装配机器人 | 65 | | | 2 | ps202505002 | PIM-CNV-002 | 智能物流分拣系统 | 45 | | | 3 | ps202505003 | PIM-GEA-003 | 高耐蚀齿轮箱 | 90 | | | | **预计总耗时** | | **200** | | | --- 程序框架如下: ```java @Controller @RequestMapping("/erp/mes") public class MesController { @Autowired private WorkStationService workstationservice; @Autowired private PieceService pieceservice; @Autowired private DispatchService dispatchservice; @RequestMapping("/piece/PUT") public void creatPieceDataByPplan (//依据生产任务生成待加工的“件” @RequestParam("pplanid") String pplanid) { pieceservice.createPieceDataByPplanid(pplanid); } @RequestMapping("/dispatch/PUT") public void dispatch(//将 piece 表格中的每一“件”调度到工位,处于待加工状态 @RequestParam("pieid") String piece) { dispatchservice.dispatch(pieid); } @RequestMapping("/workstation/GET") public List getWorkstationQueue ( @RequestParam("wkid") String workstation) { List list; list = workstationservice.getWorkstationQueueByid(wkid); return list; } } WorkStation 类封装了有关工位的方法,getWorkstationQueueByid()方法依据工位号,得到该工位的加工队列。 2. 项目分析 2.1 ER 分析 E-R 图描述: 实体 (Entities): 工人 (worker) 工位 (Workstation) 生产设备 (Production equipment) 工序 (workingprocedure) 产品 (product) 件 (piece) 关系 (Relationships): 工人 和 工位 是多对多 (m-m) 关系。 工位 和 生产设备 是一对多 (1-m) 关系。 工位 和 工序 是多对一 (m-1) 关系。 产品 和 工序 通过 prodwkpro 表建立多对多 (m-m) 关系。 产品 和 工位 通过 process (加工耗时) 建立多对多 (m-m) 关系,该关系有属性 标准耗时。 产品 和 件 是一对多 (1-m) 关系。 件 和 工位 通过 dispatch (调度) 建立多对多 (m-m) 关系,该关系有属性 实际耗时。 2.2 表格设计 1) product(产品) id: 产品号 name: 产品名称 例如某生产企业生产的产品列表见表7-1所示。 表7-1: 某制造企业生产产品列表 产品编码 (id) 产品名称 (name) 产品型号 (type) 关键参数/功能 第一工序 PIM-ROB-001 全自动装配机器人 XFR-5000 AI 视觉定位, 精度±0.01mm 成型301 PIM-CNV-002 智能物流分拣系统 XFL-300 分拣速度2000件/小时, AGV 兼容 组装501 PIM-GEA-003 高耐蚀齿轮箱 XFG-450 钛合金材质, 耐盐雾腐蚀2000小时 设计101 PIM-SPD-004 数控机床主轴 XFM-200 转速 20,000 RPM, 动态平衡等级 G1.0 成型301 PIM-MET-005 三维激光测量仪 XFC-7 精度±1µm, 支持3D建模 设计101 PIM-HYD-006 智能温控液压系统 XFH-880 节能30%, 物联网远程监控 组装 501 PIM-LIN-007 模块化柔性生产线 XFL-Pro 支持快速换线, 兼容5种产品类型 组装501 PIM-SEN-008 工业级压力传感器 XFS-100 量程0-100MPa, IP67 防护 备料 201 匯出到試算表 2) workstation(工位) id: 工位 id name: 工位名称 ipaddr: 工位操作终端的ip地址,固定ip。 wpid: 工序 id。一个工序可以有多个工位,工位和工序是1-m关系。所以在工位表格中需要记录工序号。 例如某企业有12个工位,实现7道工序,见表7-2所示。 表7-2: 某制造企业工位列表 工位号 工位名称 IP 实施工序 01 设计 192.168.1.101 101 02 备料 192.168.1.102 201 03 成型 192.168.1.103 301 04 表面处理 192.168.1.104 401 05 组装 192.168.1.105 501 06 质检 192.168.1.106 601 07 包装 192.168.1.107 701 08 成型 192.168.1.108 301 09 组装 192.168.1.109 501 10 质检 192.168.1.110 601 11 质检 192.168.1.111 601 12 包装 192.168.1.112 701 匯出到試算表 3) wkproc(工序) id name 常见的工序列表见表7-3所示。 表7-3: 工序列表 id name 101 设计 201 备料 301 成型 401 表面处理 501 组装 601 质检 701 包装 匯出到試算表 4) prodwkpro(产品工序) 产能和工序之间的m-m关系表格。 id: 唯一号 pid: 产品号 wpid: 工序号 lastwkpro: 上一个工序 表7-4: 产品和工序的对应关系表 prodwkpro 序号 (id) 产品编码 (pid) 工序号 (wpid) 上一工序 (last) 备注 3 PIM-GEA-003 101 0 表示第一道工序 5 PIM-MET-005 101 0 表示第一道工序 11 PIMGEA--003 201 101 13 PIM-MET-005 201 101 16 PIM-SEN-008 201 0 表示第一道工序 17 PIM-ROB-001 301 0 表示第一道工序 19 PIM-GEA-003 301 201 20 PIM-SPD-004 301 0 表示第一道工序 21 PIM-MET-005 301 201 24 PIM-SEN-008 301 201 25 PIM-ROB-001 401 301 27 PIM-GEA-003 401 301 28 PIM-SPD-004 401 301 29 PIM-MET-005 401 301 32 PIM-SEN-008 401 301 33 PIM-ROB-001 501 401 34 PIM-CNV-002 501 0 表示第一道工序 37 PIM-MET-005 501 401 38 PIM-HYD-006 501 0 表示第一道工序 39 PIM-LIN-007 501 0 表示第一道工序 41 PIM-ROB-001 601 501 42 PIM-CNV-002 601 501 43 PIM-GEA-003 601 401 没有组装(501)工序 44 PIM-SPD-004 601 401 没有组装(501)工序 45 PIM-MET-005 601 501 46 PIM-HYD-006 601 501 47 PIM-LIN-007 601 501 48 PIM-SEN-008 601 401 没有组装(501)工序 49 PIM-ROB-001 701 601 50 PIM-CNV-002 701 601 51 PIM-GEA-003 701 601 52 PIM-SPD-004 701 601 53 PIM-MET-005 701 601 54 PIM-HYD-006 701 601 55 PIM-LIN-007 701 601 56 PIM-SEN-008 701 601 匯出到試算表 其中,高耐蚀齿轮箱(PIM-GEA-003)、数控机床主轴(PIM-SPD-004)和工业级压力传感器 (PIM-SEN-008)这3类产品没有组装(501)工序。 5) 加工耗时(process) 产品在工位上加工,并记录经验的标准耗时。 id: 唯一号 pid: 产品号 wsid: 工位号。记录标准耗时仅与工序有关,也与工位有关,受该工位的加工设备先进程度限制等。 elapsed: 标准耗时(分钟为单位)。根据平常的经验数据指定的耗时时间。 见表7-5所示,是各个产品在每个工位的耗时表。 表7-5: 产品工位耗时表 序号 (id) 产品编码 (pid) 工位号 (wsid) 标准耗时 (elapsed) 备注 3 PIM-GEA-003 1 90 5 PIM-MET-005 1 35 11 PIM-GEA-003 2 105 13 PIM-MET-005 2 90 16 PIM-SEN-008 2 90 17 PIM-ROB-001 3 25 19 PIM-GEA-003 3 125 20 PIM-SPD-004 3 205 21 PIM-MET-005 3 245 22 PIM-HYD-006 3 90 23 PIM-LIN-007 3 250 24 PIM-SEN-008 3 45 25 PIM-ROB-001 4 105 26 PIM-CNV-002 4 205 27 PIM-GEA-003 4 300 28 PIM-SPD-004 4 90 29 PIM-MET-005 4 35 30 PIM-HYD-006 4 85 31 PIM-LIN-007 4 130 32 PIM-SEN-008 4 145 33 PIM-ROB-001 5 280 34 PIM-CNV-002 5 405 35 PIM-GEA-003 5 225 36 PIM-SPD-004 5 375 37 PIM-MET-005 5 155 38 PIM-HYD-006 5 215 39 PIM-LIN-007 5 90 40 PIM-SEN-008 5 275 41 PIM-ROB-001 6 210 42 PIM-CNV-002 6 55 43 PIM-GEA-003 6 50 44 PIM-SPD-004 6 60 45 PIM-MET-005 6 75 46 PIM-HYD-006 6 85 47 PIM-LIN-007 6 105 48 PIM-SEN-008 6 150 49 PIM-ROB-001 7 65 50 PIM-CNV-002 7 60 51 PIM-GEA-003 7 45 52 PIM-SPD-004 7 35 53 PIM-MET-005 7 100 54 PIM-HYD-006 7 90 55 PIM-LIN-007 7 85 56 PIM-SEN-008 7 75 57 PIM-ROB-001 8 35 58 PIM-CNV-002 8 215 59 PIM-GEA-003 8 145 60 PIM-SPD-004 8 225 61 PIM-MET-005 8 255 62 PIM-HYD-006 8 95 63 PIM-LIN-007 8 255 64 PIM-SEN-008 8 65 65 PIM-ROB-001 9 285 66 PIM-CNV-002 9 425 67 PIM-GEA-003 9 235 68 PIM-SPD-004 9 385 69 PIM-MET-005 9 165 70 PIM-HYD-006 9 225 71 PIM-LIN-007 9 105 72 PIM-SEN-008 9 285 73 PIM-ROB-001 10 215 74 PIM-CNV-002 10 75 75 PIM-GEA-003 10 55 76 PIM-SPD-004 10 65 77 PIM-MET-005 10 85 78 PIM-HYD-006 10 95 79 PIM-LIN-007 10 115 80 PIM-SEN-008 10 155 81 PIM-ROB-001 11 205 82 PIM-CNV-002 11 50 83 PIM-GEA-003 11 40 84 PIM-SPD-004 11 50 85 PIM-MET-005 11 65 86 PIM-HYD-006 11 75 87 PIM-LIN-007 11 95 88 PIM-SEN-008 11 140 89 PIM-ROB-001 12 75 90 PIM-CNV-002 12 65 91 PIM-GEA-003 12 55 92 PIM-SPD-004 12 55 93 PIM-MET-005 12 110 94 PIM-HYD-006 12 95 95 PIM-LIN-007 12 95 96 PIM-SEN-008 12 85 匯出到試算表 6) piece(件) id: 件号 pid: 产品号 7) dispatch(调度) 建立产品的件与工位之间的m-m关系表。 id: 唯一标识 pieid: 件号 wsid: 工位号 qid: 某件产品的队列(queue)号 startingtime: 起始时间 endtime: 结束时间 status: 状态。1-等待加工, 2-正在加工, 3-结束加工 8) workerstation(工人工位) id: 唯一号 wkid: 工人号 wsid: 工位号 pid: 生产产品件号 starttime: 开始时间 endtime: 完成时间 memo: 备注,如异常信息等。 9) equipment(生产设备) id name type: 1-主设备; 2-辅助设备; 3-人工 3. Restful API 接口规范 RESTful API 是应用程序接口(API)的一种架构风格,它使用 HTTP 请求来访问和使用数据。该数据可用于GET、PUT、POST和DELETE 数据类型,这些数据类型是指有关资源的操作的读取、更新、创建和删除。 [注意] RESTful是一种风格而不是标准。 HTTP 方法 使用 RESTful 风格的接口,从接口上可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断。具体的HTTP方法和方法含义如下: GET (SELECT): 从服务器取出资源(一项或多项)。 POST (CREATE): 在服务器新建一个资源。 PUT (UPDATE): 在服务器更新资源(客户端提供完整资源数据)。 PATCH (UPDATE): 在服务器更新资源(客户端提供需要修改的资源数据)。 DELETE (DELETE):从服务器删除资源。 当然也有很多在具体使用的时候使用PUT表示更新。从请求的流程来看,RESTful API 和传统API 大致架构如下: 传统 url 接口与RESTful 风格接口的区别 客户端请求 传统 url 接口 REST ful 风格接口 查询所有用户 /user/findAll GET /users 查询编号为1的用户 /user/findById?id=1 GET /user/1 新增一个用户 /user/save POST /user 修改编号为1的用户 /user/update PUT /user/1 删除编号为1的用户 /user/delete?id=1 DELETE /user/1 匯出到試算表 安全性和幂等性 在谈及GET、POST、PUT、DELETE的时候,就必须提一下接口的安全性和幂等性。上述四个HTTP请求方法的安全性和幂等性如下: HTTP Method 资源操作 CRUD操作 安全性 幂等性 解释 GET SELECT SELECT 安全 幂等 读操作安全,查询一次多次结果一致 POST INSERT CREATE 非安全 非幂等 写操作非安全,每多插入一次都会出现新结果 PUT UPDATE UPDATE 非安全 幂等 写操作非安全,一次和多次更新结果一致 DELETE DELETE DELETE 非安全 幂等 写操作非安全,一次和多次删除结果一致 匯出到試算表 幂等性: 对同一REST接口的多次访问,得到的资源状态是相同的。 安全性: 对该REST接口访问,不会使服务器端资源的状态发生改变。 3.1 RESTful API 设计规范 既然了解了 RESTful的一些规则和特性,那么具体该怎么去设计一个RESTful API 呢? 3.1.1 使用 HTTP Method 动词来表达操作 操作应该使用HTTP 动词来表达,例如GET(获取资源)、POST(创建资源)、PUT(更新资源)、DELETE(删除资源)等,以确保对资源的操作被明确表示和限制。如下所示: # 获取用户列表 GET /users # 获取单个用户 GET /users/{id} # 创建新用户 POST /users # 更新用户信息 PUT /users/{id} # 删除用户 DELETE /users/{id} CRUD 的操作不要体现在URL中。避免getUsers、createUser、findUsers、addUsers、updateUsers、deleteUsers等。 操作 不推荐的URL 查询用户 GET /findUsers?id=1000 新增用户 POST /addUsers 更新用户 POST /updateUsers?id=1000 删除用户 POST /deleteUsers?id=1000 匯出到試算表 3.1.2 使用名词来表示资源 在URI中使用名词来表示资源,而不是动词,以避免歧义和混淆。对于表示资源集合 URI,通常使用复数形式,以便明确表示这是一个集合而不是单个资源。例如: # 推荐 /users # 用户资源 /orders # 订单资源 # 避免 /user /order 3.1.3 使用 URI 来定位资源 RESTful API 应该使用 URI 来定位资源,以确保每个资源都有一个唯一的标识符。URI 应该具有层级结构,以便表示资源之间的关系。例如: GET /users/1/orders/1 3.1.4 使用查询参数来过滤和分页 使用查询参数来过滤和分页资源,例如:?page=1&limit=10 操作 示例 获取前10个用户: GET /users?limit=10 获取第二页的用户: GET /users?page=2&limit=10 匯出到試算表 3.1.5 使用 HTTP状态码来表示请求结果 使用合适的HTTP 状态码来表示请求结果,以便客户端能够根据状态码进行处理。例如:状态码主要分为五大类: 1xx: 相关信息 2xx: 操作成功 3xx: 重定向 4xx: 客户端错误 5xx: 服务器错误 例如: 200: 请求成功 201: 资源创建成功 400: 请求参数错误 401: 未授权访问 403: 表示禁止访问资源。 404: 表示未找到资源。 500: 表示服务器内部错误。 3.1.6 使用 JSON 或 XML 来表示数据 使用JSON 或 XML 来表示数据,以便不同的客户端能够方便地进行数据解析和处理。例如: GET /users/1 JSON { "id": 1, "name": "Tom", "age": 25 } 3.1.7 使用版本号来管理 API RESTful API 应该使用版本号来管理API的不同版本,以便支持旧版 API 的兼容性和平稳升级。应该将API的版本号放入URL。版本号以字符v开头,比如:v1、v2。 /v1/users /v2/users 3.1.8 提供清晰的错误信息: 在响应中包含清晰、详细的错误信息,帮助客户端理解问题的原因和解决方案。 JSON { "error": { "code": 404, "message": "User not found" } } 3.1.9 使用标准的HTTP头部: 使用HTTP头部中的Accept 和 Content-Type 字段进行内容协商,以确定客户端期望的表示形式和服务器返回的表示形式。 接受JSON 格式的响应: Accept: application/json 发送 JSON 格式的请求体: Content-Type: application/json 3.2 URI 书写规范 在RESTful API设计中,URI(Uniform Resource Identifier)的书写通常遵循一些规范和最佳实践,以提高可读性、一致性和可维护性。以下是一些关于URI书写的常见规范: 3.2.1 使用小写字母: 建议使用小写字母,因为URI是区分大小写的。 # 推荐 /users /articles # 避免 /Users /Articles 3.2.2 使用短划线或下划线分隔单词: 使用短划线(-)或下划线(_)来分隔单词,而不是使用空格或驼峰命名法。这有助于确保URI的可读性。 # 推荐 /user-profiles /article-comments # 避免 /userProfiles /articleComments 3.2.3 避免使用空格和特殊字符: URI 中不应包含空格和特殊字符,可以使用短划线或下划线来替代。 # 推荐 /user-profiles /article-comments # 避免 /user profiles /article@comments 3.2.4 避免深层嵌套: 尽量避免过深的嵌套结构,以保持URI的简洁性和易读性。 # 推荐 /users/{userId}/orders /articles/{articleId}/comments # 避免 /users/{userId}/orders/{orderId}/items /articles/{articleId}/comments/{commentId}/replies 总之,RESTful 风格的API 固然很好很规范,但大多数互联网公司并没有按照或者完全按照其规则来设计,因为REST是一种风格,而不是一种约束或规则,过于理想的 RESTful API 会付出太多的成本。