feat(MES): 添加MES接口相关实体和DTO JS扩展文件至JSX格式并更新配置
- 添加 Dt_MesApiLog 日志实体
- 添加 MesApiLogDto 及各接口请求DTO
- 支持进站、出站、绑定、解绑、NG上报接口
feat: 迁移JS扩展文件至JSX格式并更新配置
refactor: 重构Vue组件导入路径为JSX扩展文件
build: 添加@vitejs/plugin-vue-jsx依赖支持JSX
build: 更新vite配置为mjs格式并添加JSX插件
style: 统一扩展文件代码格式
chore: 清理旧的JS扩展文件
chore: 更新状态和配置文件
docs: 添加注释说明JSX扩展文件用途
perf: 优化库存页面按钮渲染逻辑
test: 更新测试相关配置
ci: 调整构建配置支持JSX语法
refactor(MES): 扩展文件改用JSX语法重写
- 将扩展文件从.js重命名为.jsx以支持JSX语法
- 使用JSX语法重写按钮render函数
- 更新Vue组件中的import语句引用.jsx文件
fix(MES): 修正扩展文件使用h()函数语法
.js文件不支持JSX语法,改用h()函数渲染按钮:
- 使用h()创建el-button组件
- 使用props定义组件属性
- 使用on: { click: ... }绑定点击事件
- 使用style定义内联样式
fix(MES): 根据实际库存状态枚举修正按钮显示逻辑
根据 StockStatusEmun 枚举更新按钮显示规则:
stockInfo.js (库存信息页面):
- 进站按钮: status ∈ [1, 3, 12, 13]
1=组盘暂存, 3=入库确认, 12=手动组盘暂存, 13=手动组盘入库确认
- 出站按钮: status ∈ [6, 7, 8, 10, 22]
6=入库完成, 7=出库锁定, 8=出库完成, 10=入库完成未建出库单, 22=空托盘库存
stockInfoDetail.js (库存明细页面):
- 锁定状态: status ∈ [7, 9, 99, 199]
7=出库锁定, 9=移库锁定, 99=组盘撤销, 199=入库撤销
feat(MES): 库存页面添加MES操作列(扩展文件实现)
在扩展文件中实现MES操作逻辑:
- stockInfo.js: 添加进站/出站按钮和API调用
- stockInfoDetail.js: 添加绑定/解绑/NG上报按钮和API调用
- 使用this.columns.push()添加操作列
- 使用h()函数渲染按钮
- 使用this.()显示确认对话框
- 使用this.http.post()调用后端API
feat(MES): 新增MES确认对话框组件
创建可复用的MesConfirmDialog.vue组件,用于在执行MES操作前显示确认信息。
功能特性:
- 支持5种操作类型(进站/出站/绑定/解绑/NG上报)
- 动态显示操作标题和提示文本
- 展示关键信息(托盘码、电芯数量、库位)
- 错误消息展示区域,带图标提示
- 确认/取消按钮,支持loading状态
- 通过回调函数处理操作成功/失败结果
技术实现:
- Vue 3 Composition API (defineComponent)
- 双向绑定支持 (v-model)
- Element Plus UI组件库
- Less预处理器样式
- 完整的JSDoc注释
该组件将被stockInfo.vue和stockInfoDetail.vue使用,提供统一的MES操作确认体验。
fix(MES API): 使用项目统一的http模块替代直接axios调用
- 将mes.js中的axios导入替换为项目统一的http模块
- 所有5个API方法改用http.post()以确保正确处理:
* Authorization token自动管理
* 全局错误处理和401重定向
* Loading指示器
* Token刷新拦截器
- 为所有MES接口添加application/json Content-Type头
- 增强模块文档注释
修复问题:
- 之前直接使用axios绕过了项目的认证和错误处理机制
- 修复Content-Type配置问题(项目默认为x-www-form-urlencoded)
feat(MES): 添加前端MES API调用模块
- 封装库存信息进站/出站接口
- 封装库存明细绑定/解绑/NG上报接口
fix(MES): 添加库存明细状态验证到MES接口
在三个MES接口中添加电芯状态验证,拒绝已锁定状态(Status=99)的操作:
- BindContainer: 绑定前验证电芯状态
- UnbindContainer: 解绑前验证电芯状态
- ContainerNgReport: NG上报前验证电芯状态
使用QueryDataAsync查询SerialNumber匹配的库存明细,检查Status是否为99(已锁定)
feat(MES): 库存明细页面添加绑定/解绑/NG上报接口
- POST /api/StockInfoDetail/bindContainer 托盘电芯绑定
- POST /api/StockInfoDetail/unbindContainer 托盘电芯解绑
- POST /api/StockInfoDetail/containerNgReport NG电芯上报
- 记录完整调用日志
fix(MES): 修正StockInfoController进站出站接口
- 修正库存状态验证使用正确的枚举值
- 优化数据库查询使用单条记录查询
- 改进async/await模式
feat(WMS): 扩展StockInfoController添加MES进站/出站接口
- 添加托盘进站接口 inboundInContainer
- 添加托盘出站接口 outboundInContainer
- 集成MES服务调用和日志记录
- 支持系统配置获取(设备编码、资源编码)
- 库存状态验证(进站:待入库, 出站:在库/出库中)
- 性能计时和异常处理
fix(WMS): 添加WIDESEA_MesService项目引用到WIDESEA_WMSServer
修复Task 3实施中遗漏的项目引用。WIDESEA_MesService实现项目现在已被引用,从而允许Autofac DI注册在运行时成功。
feat(MES): 添加MES日志服务
- 实现 IMesLogService 接口
- 支持记录和查询MES接口调用日志
- 异常处理不影响主流程
fix(MES): 修正DTO命名空间大小写以匹配现有代码
将所有新增的MES相关DTO的命名空间从 WIDESEA_DTO.Mes 改为 WIDESEA_DTO.MES,以符合现有代码库的命名规范。
修改文件:
- InboundInContainerRequestDto.cs
- OutboundInContainerRequestDto.cs
- BindContainerRequestDto.cs
- UnbindContainerRequestDto.cs
- ContainerNgReportRequestDto.cs
- MesApiLogDto.cs
feat(MES): 添加MES接口日志表和系统配置
- 创建 Dt_MesApiLog 表记录接口调用日志
- 添加MES相关系统配置项(设备编码、资源编码、接口地址等)
docs: 添加WMS库存页面MES接口集成实现计划
- 9个任务:数据库、实体DTO、服务、控制器、前端组件
- 详细的代码步骤和测试检查清单
- 遵循TDD、DRY、YAGNI原则
docs: 添加WMS库存页面MES接口集成设计文档
- 新增库存信息页面进站/出站操作设计
- 新增库存明细页面绑定/解绑/NG上报操作设计
- 定义API接口、数据库表结构、服务层设计
- 完整的交互流程和错误处理方案
已添加32个文件
已复制12个文件
已重命名47个文件
已删除15个文件
已修改64个文件
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | {"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:brainstorming"} |
| | | {"t":0,"agent":"a9501da","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a9501da","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":8663} |
| | | {"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:writing-plans"} |
| | | {"t":0,"agent":"abb2829","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"abb2829","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":12576} |
| | | {"t":0,"agent":"system","event":"skill_invoked","skill_name":"superpowers:subagent-driven-development"} |
| | | {"t":0,"agent":"ab6a2d9","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"ab6a2d9","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":55725} |
| | | {"t":0,"agent":"a3a7fd0","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a3a7fd0","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":11968} |
| | | {"t":0,"agent":"a0ed568","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a0ed568","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":84239} |
| | | {"t":0,"agent":"a32ad6a","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a32ad6a","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":155707} |
| | | {"t":0,"agent":"a4dd492","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a4dd492","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":17301} |
| | | {"t":0,"agent":"aefc20e","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"aefc20e","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":180634} |
| | | {"t":0,"agent":"a18fadb","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a18fadb","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":92939} |
| | | {"t":0,"agent":"a379d3a","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a379d3a","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":19656} |
| | | {"t":0,"agent":"a7985a3","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a7985a3","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":79712} |
| | | {"t":0,"agent":"ab97ed1","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"ab97ed1","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":57941} |
| | | {"t":0,"agent":"ad231d3","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"ad231d3","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":119172} |
| | | {"t":0,"agent":"a7e494a","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a7e494a","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":53504} |
| | | {"t":0,"agent":"aba5116","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"aba5116","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":94295} |
| | | {"t":0,"agent":"a8e5fbf","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a8e5fbf","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":192007} |
| | | {"t":0,"agent":"a9a1cc3","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a9a1cc3","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":29527} |
| | | {"t":0,"agent":"a581cc0","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a581cc0","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":35311} |
| | | {"t":0,"agent":"a6536cf","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a6536cf","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":154828} |
| | | {"t":0,"agent":"ab287b4","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"ab287b4","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":22379} |
| | | {"t":0,"agent":"a3bba61","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a3bba61","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":106152} |
| | | {"t":0,"agent":"a0a843a","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a0a843a","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":30220} |
| | | {"t":0,"agent":"afd8eac","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"afd8eac","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":167934} |
| | | {"t":0,"agent":"aa4ea81","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"aa4ea81","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":28896} |
| | | {"t":0,"agent":"a522225","agent_type":"superpowers:code-reviewer","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a522225","agent_type":"superpowers:code-reviewer","event":"agent_stop","success":true,"duration_ms":35164} |
| | | {"t":0,"agent":"ac7c987","agent_type":"unknown","event":"agent_stop","success":true} |
| | | {"t":0,"agent":"a405c70","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a405c70","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":59509} |
| | | {"t":0,"agent":"a0ff377","agent_type":"general-purpose","event":"agent_start","parent_mode":"none"} |
| | | {"t":0,"agent":"a0ff377","agent_type":"general-purpose","event":"agent_stop","success":true,"duration_ms":7226} |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "created_at": "2026-04-12T13:52:50.251Z", |
| | | "trigger": "auto", |
| | | "active_modes": {}, |
| | | "todo_summary": { |
| | | "pending": 0, |
| | | "in_progress": 0, |
| | | "completed": 0 |
| | | }, |
| | | "wisdom_exported": false, |
| | | "background_jobs": { |
| | | "active": [], |
| | | "recent": [], |
| | | "stats": null |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "tool_name": "Read", |
| | | "tool_input_preview": "{\"file_path\":\"D:\\\\Git\\\\ShanMeiXinNengYuan\\\\Code\\\\WMS\\\\WIDESEA_WMSServer\\\\WIDESEA_WMSServer\\\\Controllers\\\\BatteryCellController.cs\"}", |
| | | "error": "File does not exist. Note: your current working directory is D:\\Git\\ShanMeiXinNengYuan\\Code.", |
| | | "timestamp": "2026-04-12T13:48:48.578Z", |
| | | "retry_count": 1 |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "updatedAt": "2026-04-12T13:54:45.455Z", |
| | | "missions": [ |
| | | { |
| | | "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none", |
| | | "source": "session", |
| | | "name": "none", |
| | | "objective": "Session mission", |
| | | "createdAt": "2026-04-12T13:05:45.505Z", |
| | | "updatedAt": "2026-04-12T13:54:45.455Z", |
| | | "status": "done", |
| | | "workerCount": 27, |
| | | "taskCounts": { |
| | | "total": 27, |
| | | "pending": 0, |
| | | "blocked": 0, |
| | | "inProgress": 0, |
| | | "completed": 27, |
| | | "failed": 0 |
| | | }, |
| | | "agents": [ |
| | | { |
| | | "name": "general-purpose:a9501da", |
| | | "role": "general-purpose", |
| | | "ownership": "a9501da36be20eb24", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:53:13.149Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:abb2829", |
| | | "role": "general-purpose", |
| | | "ownership": "abb28297f69440cf9", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:10:58.257Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:ab6a2d9", |
| | | "role": "general-purpose", |
| | | "ownership": "ab6a2d9ed6f459274", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:13:25.065Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a3a7fd0", |
| | | "role": "general-purpose", |
| | | "ownership": "a3a7fd0c0829e5f0c", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:13:48.330Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:a0ed568", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "a0ed568f9e32bd5b0", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:17:47.626Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a32ad6a", |
| | | "role": "general-purpose", |
| | | "ownership": "a32ad6a96659ec279", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:24:23.170Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a4dd492", |
| | | "role": "general-purpose", |
| | | "ownership": "a4dd4923f28eeaea9", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:24:47.505Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:aefc20e", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "aefc20e8f3f9438f3", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:27:54.713Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a18fadb", |
| | | "role": "general-purpose", |
| | | "ownership": "a18fadb164b0dfdb8", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:29:34.186Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:a379d3a", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "a379d3a8646888a66", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:29:58.098Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a7985a3", |
| | | "role": "general-purpose", |
| | | "ownership": "a7985a337688f4971", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:31:36.395Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:ab97ed1", |
| | | "role": "general-purpose", |
| | | "ownership": "ab97ed1012975ec79", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:32:42.067Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:ad231d3", |
| | | "role": "general-purpose", |
| | | "ownership": "ad231d3220b6ba05e", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:34:46.714Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a7e494a", |
| | | "role": "general-purpose", |
| | | "ownership": "a7e494aa6cfed7748", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:35:43.945Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:aba5116", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "aba5116eaa0ef6b17", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:37:25.682Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a8e5fbf", |
| | | "role": "general-purpose", |
| | | "ownership": "a8e5fbfad6a90c9c9", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:41:43.878Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a9a1cc3", |
| | | "role": "general-purpose", |
| | | "ownership": "a9a1cc30ce01dd110", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:42:18.517Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:a581cc0", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "a581cc05f79eed2ab", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:42:59.753Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a6536cf", |
| | | "role": "general-purpose", |
| | | "ownership": "a6536cf10ec91573d", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:45:40.542Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:ab287b4", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "ab287b483b80dd1ab", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:46:06.732Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a3bba61", |
| | | "role": "general-purpose", |
| | | "ownership": "a3bba6185e3ada31c", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:48:07.136Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a0a843a", |
| | | "role": "general-purpose", |
| | | "ownership": "a0a843ae77e400e58", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:48:41.191Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:afd8eac", |
| | | "role": "general-purpose", |
| | | "ownership": "afd8eacdfadd73310", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:51:34.998Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:aa4ea81", |
| | | "role": "general-purpose", |
| | | "ownership": "aa4ea817d9e391ac6", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:52:08.592Z" |
| | | }, |
| | | { |
| | | "name": "superpowers:code-reviewer:a522225", |
| | | "role": "superpowers:code-reviewer", |
| | | "ownership": "a5222258aed5f5f3d", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:52:49.666Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a405c70", |
| | | "role": "general-purpose", |
| | | "ownership": "a405c7090be2886ee", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:54:30.286Z" |
| | | }, |
| | | { |
| | | "name": "general-purpose:a0ff377", |
| | | "role": "general-purpose", |
| | | "ownership": "a0ff37729a29ea04f", |
| | | "status": "done", |
| | | "currentStep": null, |
| | | "latestUpdate": "completed", |
| | | "completedSummary": null, |
| | | "updatedAt": "2026-04-12T13:54:45.455Z" |
| | | } |
| | | ], |
| | | "timeline": [ |
| | | { |
| | | "id": "session-start:a405c7090be2886ee:2026-04-12T13:53:30.777Z", |
| | | "at": "2026-04-12T13:53:30.777Z", |
| | | "kind": "update", |
| | | "agent": "general-purpose:a405c70", |
| | | "detail": "started general-purpose:a405c70", |
| | | "sourceKey": "session-start:a405c7090be2886ee" |
| | | }, |
| | | { |
| | | "id": "session-stop:a405c7090be2886ee:2026-04-12T13:54:30.286Z", |
| | | "at": "2026-04-12T13:54:30.286Z", |
| | | "kind": "completion", |
| | | "agent": "general-purpose:a405c70", |
| | | "detail": "completed", |
| | | "sourceKey": "session-stop:a405c7090be2886ee" |
| | | }, |
| | | { |
| | | "id": "session-start:a0ff37729a29ea04f:2026-04-12T13:54:38.229Z", |
| | | "at": "2026-04-12T13:54:38.229Z", |
| | | "kind": "update", |
| | | "agent": "general-purpose:a0ff377", |
| | | "detail": "started general-purpose:a0ff377", |
| | | "sourceKey": "session-start:a0ff37729a29ea04f" |
| | | }, |
| | | { |
| | | "id": "session-stop:a0ff37729a29ea04f:2026-04-12T13:54:45.455Z", |
| | | "at": "2026-04-12T13:54:45.455Z", |
| | | "kind": "completion", |
| | | "agent": "general-purpose:a0ff377", |
| | | "detail": "completed", |
| | | "sourceKey": "session-stop:a0ff37729a29ea04f" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "agents": [ |
| | | { |
| | | "agent_id": "a9501da36be20eb24", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:05:45.505Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:05:54.168Z", |
| | | "duration_ms": 8663 |
| | | }, |
| | | { |
| | | "agent_id": "abb28297f69440cf9", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:10:45.681Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:10:58.257Z", |
| | | "duration_ms": 12576 |
| | | }, |
| | | { |
| | | "agent_id": "ab6a2d9ed6f459274", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:12:29.340Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:13:25.065Z", |
| | | "duration_ms": 55725 |
| | | }, |
| | | { |
| | | "agent_id": "a3a7fd0c0829e5f0c", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:13:36.362Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:13:48.330Z", |
| | | "duration_ms": 11968 |
| | | }, |
| | | { |
| | | "agent_id": "a0ed568f9e32bd5b0", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:16:23.387Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:17:47.626Z", |
| | | "duration_ms": 84239 |
| | | }, |
| | | { |
| | | "agent_id": "a32ad6a96659ec279", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:21:47.463Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:24:23.170Z", |
| | | "duration_ms": 155707 |
| | | }, |
| | | { |
| | | "agent_id": "a4dd4923f28eeaea9", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:24:30.204Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:24:47.505Z", |
| | | "duration_ms": 17301 |
| | | }, |
| | | { |
| | | "agent_id": "aefc20e8f3f9438f3", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:24:54.079Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:27:54.713Z", |
| | | "duration_ms": 180634 |
| | | }, |
| | | { |
| | | "agent_id": "a18fadb164b0dfdb8", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:28:01.247Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:29:34.186Z", |
| | | "duration_ms": 92939 |
| | | }, |
| | | { |
| | | "agent_id": "a379d3a8646888a66", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:29:38.442Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:29:58.098Z", |
| | | "duration_ms": 19656 |
| | | }, |
| | | { |
| | | "agent_id": "a7985a337688f4971", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:30:16.683Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:31:36.395Z", |
| | | "duration_ms": 79712 |
| | | }, |
| | | { |
| | | "agent_id": "ab97ed1012975ec79", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:31:44.126Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:32:42.067Z", |
| | | "duration_ms": 57941 |
| | | }, |
| | | { |
| | | "agent_id": "ad231d3220b6ba05e", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:32:47.542Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:34:46.714Z", |
| | | "duration_ms": 119172 |
| | | }, |
| | | { |
| | | "agent_id": "a7e494aa6cfed7748", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:34:50.441Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:35:43.945Z", |
| | | "duration_ms": 53504 |
| | | }, |
| | | { |
| | | "agent_id": "aba5116eaa0ef6b17", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:35:51.387Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:37:25.682Z", |
| | | "duration_ms": 94295 |
| | | }, |
| | | { |
| | | "agent_id": "a8e5fbfad6a90c9c9", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:38:31.871Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:41:43.878Z", |
| | | "duration_ms": 192007 |
| | | }, |
| | | { |
| | | "agent_id": "a9a1cc30ce01dd110", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:41:48.990Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:42:18.517Z", |
| | | "duration_ms": 29527 |
| | | }, |
| | | { |
| | | "agent_id": "a581cc05f79eed2ab", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:42:24.442Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:42:59.753Z", |
| | | "duration_ms": 35311 |
| | | }, |
| | | { |
| | | "agent_id": "a6536cf10ec91573d", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:43:05.714Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:45:40.542Z", |
| | | "duration_ms": 154828 |
| | | }, |
| | | { |
| | | "agent_id": "ab287b483b80dd1ab", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:45:44.353Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:46:06.732Z", |
| | | "duration_ms": 22379 |
| | | }, |
| | | { |
| | | "agent_id": "a3bba6185e3ada31c", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:46:20.984Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:48:07.136Z", |
| | | "duration_ms": 106152 |
| | | }, |
| | | { |
| | | "agent_id": "a0a843ae77e400e58", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:48:10.971Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:48:41.191Z", |
| | | "duration_ms": 30220 |
| | | }, |
| | | { |
| | | "agent_id": "afd8eacdfadd73310", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:48:47.064Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:51:34.998Z", |
| | | "duration_ms": 167934 |
| | | }, |
| | | { |
| | | "agent_id": "aa4ea817d9e391ac6", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:51:39.696Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:52:08.592Z", |
| | | "duration_ms": 28896 |
| | | }, |
| | | { |
| | | "agent_id": "a5222258aed5f5f3d", |
| | | "agent_type": "superpowers:code-reviewer", |
| | | "started_at": "2026-04-12T13:52:14.502Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:52:49.666Z", |
| | | "duration_ms": 35164 |
| | | }, |
| | | { |
| | | "agent_id": "a405c7090be2886ee", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:53:30.777Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:54:30.286Z", |
| | | "duration_ms": 59509 |
| | | }, |
| | | { |
| | | "agent_id": "a0ff37729a29ea04f", |
| | | "agent_type": "general-purpose", |
| | | "started_at": "2026-04-12T13:54:38.229Z", |
| | | "parent_mode": "none", |
| | | "status": "completed", |
| | | "completed_at": "2026-04-12T13:54:45.455Z", |
| | | "duration_ms": 7226 |
| | | } |
| | | ], |
| | | "total_spawned": 27, |
| | | "total_completed": 27, |
| | | "total_failed": 0, |
| | | "last_updated": "2026-04-12T13:54:45.571Z" |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | {"reason":"idle timeout","timestamp":1776000741677} |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <h2>æé®æ¾ç¤ºä¸ç¶ææ§å¶</h2> |
| | | <p class="subtitle">æ ¹æ®åºåç¶ææ§å¶æä½æé®çæ¾ç¤º</p> |
| | | |
| | | <div class="section"> |
| | | <h3>åºæ¯åæ</h3> |
| | | <p class="subtitle">ä¸åç¶æçåºåå¯è½å
许æç¦æ¢æäºæä½</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">åºåç¶ææä¸¾</div> |
| | | <div class="mockup-body"> |
| | | <div class="status-list"> |
| | | <div class="status-item"> |
| | | <span class="status-badge status-badge-idle">å¾
å
¥åº</span> |
| | | <div class="status-desc">æçå·²å建ä½å°æªå®æå
¥åº</div> |
| | | </div> |
| | | <div class="status-item"> |
| | | <span class="status-badge status-badge-instock">å¨åº</span> |
| | | <div class="status-desc">æçæ£å¸¸å¨åºä¸</div> |
| | | </div> |
| | | <div class="status-item"> |
| | | <span class="status-badge status-badge-outbound">åºåºä¸</span> |
| | | <div class="status-desc">æçæ£å¨åºåºæµç¨ä¸</div> |
| | | </div> |
| | | <div class="status-item"> |
| | | <span class="status-badge status-badge-lock">éå®</span> |
| | | <div class="status-desc">æç被éå®ï¼ä¸å¯æä½</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>æé®æ¾ç¤ºçç¥éæ©</h3> |
| | | <p class="subtitle">ä¸åçç¥çç¨æ·ä½éªåå®ç°å¤æåº¦</p> |
| | | |
| | | <div class="options"> |
| | | <div class="option" data-choice="always" onclick="toggleSelect(this)"> |
| | | <div class="letter">A</div> |
| | | <div class="content"> |
| | | <h3>å§ç»æ¾ç¤º</h3> |
| | | <p>æææä½æé®å§ç»æ¾ç¤ºï¼ç¹å»åå¨å¼¹çªä¸æ ¡éªç¶æ</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>å®ç°ç®å</li><li>ç¨æ·æ¸
æ¥æåªäºåè½</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>å¯è½äº§çæ æç¹å»</li><li>ä½éªè¾å·®</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="dynamic" onclick="toggleSelect(this)"> |
| | | <div class="letter">B</div> |
| | | <div class="content"> |
| | | <h3>卿æ¾ç¤º</h3> |
| | | <p>æ ¹æ®åºåç¶æå¨ææ¾ç¤º/éèæé®</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>ç颿¸
æ°</li><li>åå°è¯¯æä½</li><li>ä½éªæ´å¥½</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>éè¦ç»´æ¤ç¶ææ å°</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="disable" onclick="toggleSelect(this)"> |
| | | <div class="letter">C</div> |
| | | <div class="content"> |
| | | <h3>æ¾ç¤ºå¹¶ç¦ç¨</h3> |
| | | <p>æææé®é½æ¾ç¤ºï¼ä½ä¸å¯ç¨çæ¾ç¤ºä¸ºç¦ç¨ç¶æ</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>ç¨æ·ç¥éææ¤åè½</li><li>æ¸
æ¥ä¸ºä½ä¸å¯ç¨</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>çé¢å¯è½æ¥æ¤</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>示ä¾ï¼å¨ææ¾ç¤ºææ</h3> |
| | | <p class="subtitle">ä¸åç¶æä¸çæé®æ¾ç¤ºæ
åµ</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼ä¸åç¶æçæé®æ¾ç¤º</div> |
| | | <div class="mockup-body"> |
| | | <table class="mock-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>æçç¼å·</th> |
| | | <th>åºåç¶æ</th> |
| | | <th>æä½æé®</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>P001</td> |
| | | <td><span class="status-badge status-badge-idle">å¾
å
¥åº</span></td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">è¿ç«</button> |
| | | <button class="mock-btn-inline mock-btn-disabled">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>P002</td> |
| | | <td><span class="status-badge status-badge-instock">å¨åº</span></td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-disabled">è¿ç«</button> |
| | | <button class="mock-btn-inline mock-btn-success">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>P003</td> |
| | | <td><span class="status-badge status-badge-lock">éå®</span></td> |
| | | <td> |
| | | <span class="text-muted">ææ å¯æ§è¡æä½</span> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <style> |
| | | .status-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | .status-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 12px; |
| | | background: #fafafa; |
| | | border-radius: 6px; |
| | | } |
| | | .status-badge { |
| | | padding: 4px 12px; |
| | | border-radius: 4px; |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | white-space: nowrap; |
| | | } |
| | | .status-badge-idle { |
| | | background: #e3f2fd; |
| | | color: #1976d2; |
| | | } |
| | | .status-badge-instock { |
| | | background: #e8f5e9; |
| | | color: #388e3c; |
| | | } |
| | | .status-badge-outbound { |
| | | background: #fff3e0; |
| | | color: #f57c00; |
| | | } |
| | | .status-badge-lock { |
| | | background: #ffebee; |
| | | color: #d32f2f; |
| | | } |
| | | .status-desc { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | } |
| | | .mock-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | font-size: 13px; |
| | | } |
| | | .mock-table th, .mock-table td { |
| | | border: 1px solid #e0e0e0; |
| | | padding: 10px 12px; |
| | | text-align: left; |
| | | } |
| | | .mock-table th { |
| | | background: #f5f5f5; |
| | | font-weight: 600; |
| | | } |
| | | .mock-table tbody tr:nth-child(even) { |
| | | background: #fafafa; |
| | | } |
| | | .mock-btn-inline { |
| | | padding: 6px 14px; |
| | | font-size: 13px; |
| | | border-radius: 4px; |
| | | border: 1px solid #dcdfe6; |
| | | background: white; |
| | | cursor: pointer; |
| | | margin-right: 8px; |
| | | } |
| | | .mock-btn-primary { |
| | | background: #1f5eff; |
| | | color: white; |
| | | border-color: #1f5eff; |
| | | } |
| | | .mock-btn-success { |
| | | background: #67c23a; |
| | | color: white; |
| | | border-color: #67c23a; |
| | | } |
| | | .mock-btn-disabled { |
| | | background: #f5f5f5; |
| | | color: #c0c4cc; |
| | | border-color: #e4e7ed; |
| | | cursor: not-allowed; |
| | | } |
| | | .text-muted { |
| | | color: #909399; |
| | | font-size: 13px; |
| | | } |
| | | .pros-cons { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-top: 12px; |
| | | } |
| | | .pros, .cons { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | } |
| | | .pros h4 { |
| | | color: #4caf50; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .cons h4 { |
| | | color: #f56c6c; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .pros ul, .cons ul { |
| | | margin: 0; |
| | | padding-left: 16px; |
| | | } |
| | | .pros li, .cons li { |
| | | margin-bottom: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <h2>é误å¤çä¸åé¦</h2> |
| | | <p class="subtitle">MESæ¥å£è°ç¨å¤±è´¥æ¶çå¤çæ¹å¼</p> |
| | | |
| | | <div class="section"> |
| | | <h3>åºæ¯åæ</h3> |
| | | <p class="subtitle">MESæ¥å£å¯è½å ç½ç»ãMESç³»ç»å¼å¸¸ãåæ°é误çåå 失败</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">常è§é误类å</div> |
| | | <div class="mockup-body"> |
| | | <div class="error-list"> |
| | | <div class="error-item"> |
| | | <span class="error-icon error-icon-network">ð¡</span> |
| | | <div class="error-content"> |
| | | <div class="error-title">ç½ç»è¶
æ¶</div> |
| | | <div class="error-desc">MESæå¡å¨æ ååºæè¿æ¥è¶
æ¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="error-item"> |
| | | <span class="error-icon error-icon-server">â ï¸</span> |
| | | <div class="error-content"> |
| | | <div class="error-title">MESä¸å¡é误</div> |
| | | <div class="error-desc">æçä¸åå¨ãçµè¯å·²ç»å®çä¸å¡æ ¡éªå¤±è´¥</div> |
| | | </div> |
| | | </div> |
| | | <div class="error-item"> |
| | | <span class="error-icon error-icon-auth">ð</span> |
| | | <div class="error-content"> |
| | | <div class="error-title">认è¯å¤±è´¥</div> |
| | | <div class="error-desc">MESæ¥å£è®¤è¯ä¿¡æ¯è¿æææ æ</div> |
| | | </div> |
| | | </div> |
| | | <div class="error-item"> |
| | | <span class="error-icon error-icon-unknown">â</span> |
| | | <div class="error-content"> |
| | | <div class="error-title">æªç¥é误</div> |
| | | <div class="error-desc">MESç³»ç»è¿åå¼å¸¸ææªé¢æçååº</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>é误å¤çæ¹å¼éæ©</h3> |
| | | <p class="subtitle">éæ©é忍ä¸å¡çå¤ççç¥</p> |
| | | |
| | | <div class="options"> |
| | | <div class="option" data-choice="simple" onclick="toggleSelect(this)"> |
| | | <div class="letter">A</div> |
| | | <div class="content"> |
| | | <h3>ç®åæç¤º</h3> |
| | | <p>è°ç¨å¤±è´¥åå¼¹åºé误æç¤ºï¼ç¨æ·èªè¡å³å®æ¯å¦éè¯</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>å®ç°ç®å</li><li>ç¨æ·å®å
¨æ§å¶</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>éè¦æå¨éè¯</li><li>容æéæ¼</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="auto-retry" onclick="toggleSelect(this)"> |
| | | <div class="letter">B</div> |
| | | <div class="content"> |
| | | <h3>èªå¨éè¯</h3> |
| | | <p>失败åèªå¨éè¯æå®æ¬¡æ°ï¼å¦3次ï¼ï¼ä»å¤±è´¥åæç¤ºç¨æ·</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>å¤ç临æ¶ç½ç»é®é¢</li><li>æé«æåç</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>å¯è½é夿§è¡ä¸å¡</li><li>å¢å ååºæ¶é´</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="queue" onclick="toggleSelect(this)"> |
| | | <div class="letter">C</div> |
| | | <div class="content"> |
| | | <h3>弿¥éå</h3> |
| | | <p>失败åå å
¥éè¯éåï¼åå°å®æ¶ä»»å¡èªå¨éè¯</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>ä¸é»å¡ç¨æ·æä½</li><li>å¯è¿½æº¯éè¯è®°å½</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>å®ç°å¤æ</li><li>éè¦é¢å¤çæ§</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>é误æç¤ºå±ç¤º</h3> |
| | | <p class="subtitle">ç¨æ·çå°çéè¯¯ä¿¡æ¯æ ·å¼</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼é误æç¤ºæ ·å¼</div> |
| | | <div class="mockup-body"> |
| | | <div class="error-toast error-toast-error"> |
| | | <span class="error-toast-icon">â</span> |
| | | <div class="error-toast-content"> |
| | | <div class="error-toast-title">æä½å¤±è´¥</div> |
| | | <div class="error-toast-message">MESæå¡å¨è¿æ¥è¶
æ¶ï¼è¯·æ£æ¥ç½ç»åéè¯</div> |
| | | </div> |
| | | <button class="error-toast-retry">éè¯</button> |
| | | </div> |
| | | <div style="height: 12px;"></div> |
| | | <div class="error-toast error-toast-warning"> |
| | | <span class="error-toast-icon">â </span> |
| | | <div class="error-toast-content"> |
| | | <div class="error-toast-title">ä¸å¡æ ¡éªå¤±è´¥</div> |
| | | <div class="error-toast-message">æç P001 å¨MESä¸ä¸åå¨ï¼è¯·å
å¨MESä¸å建</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <style> |
| | | .error-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | .error-item { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 12px; |
| | | padding: 12px; |
| | | background: #fafafa; |
| | | border-radius: 6px; |
| | | border: 1px solid #e0e0e0; |
| | | } |
| | | .error-icon { |
| | | font-size: 24px; |
| | | flex-shrink: 0; |
| | | } |
| | | .error-content { |
| | | flex: 1; |
| | | } |
| | | .error-title { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | margin-bottom: 4px; |
| | | } |
| | | .error-desc { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | } |
| | | .pros-cons { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-top: 12px; |
| | | } |
| | | .pros, .cons { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | } |
| | | .pros h4 { |
| | | color: #4caf50; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .cons h4 { |
| | | color: #f56c6c; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .pros ul, .cons ul { |
| | | margin: 0; |
| | | padding-left: 16px; |
| | | } |
| | | .pros li, .cons li { |
| | | margin-bottom: 4px; |
| | | } |
| | | .error-toast { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 14px 16px; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
| | | } |
| | | .error-toast-error { |
| | | background: #fef0f0; |
| | | border: 1px solid #fde2e2; |
| | | } |
| | | .error-toast-warning { |
| | | background: #fdf6ec; |
| | | border: 1px solid #f5dab1; |
| | | } |
| | | .error-toast-icon { |
| | | font-size: 20px; |
| | | flex-shrink: 0; |
| | | } |
| | | .error-toast-error .error-toast-icon { |
| | | color: #f56c6c; |
| | | } |
| | | .error-toast-warning .error-toast-icon { |
| | | color: #e6a23c; |
| | | } |
| | | .error-toast-content { |
| | | flex: 1; |
| | | } |
| | | .error-toast-title { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | margin-bottom: 4px; |
| | | } |
| | | .error-toast-error .error-toast-title { |
| | | color: #f56c6c; |
| | | } |
| | | .error-toast-warning .error-toast-title { |
| | | color: #e6a23c; |
| | | } |
| | | .error-toast-message { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | } |
| | | .error-toast-retry { |
| | | padding: 6px 16px; |
| | | background: #1f5eff; |
| | | color: white; |
| | | border: none; |
| | | border-radius: 4px; |
| | | font-size: 13px; |
| | | cursor: pointer; |
| | | flex-shrink: 0; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <h2>åºå页颿ä½å设计</h2> |
| | | <p class="subtitle">为åºåä¿¡æ¯ååºåæç»é¡µé¢æ·»å MESæ¥å£æä½æé®</p> |
| | | |
| | | <div class="section"> |
| | | <h3>1. åºåä¿¡æ¯é¡µé¢ - æççº§å«æä½</h3> |
| | | <p class="subtitle">å½å页颿¾ç¤ºæçç¼å·ãè´§ä½ç¼å·çä¿¡æ¯ï¼éè¦æ·»å è¿ç«/åºç«æä½</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼åºåä¿¡æ¯è¡¨æ ¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mock-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>æçç¼å·</th> |
| | | <th>è´§ä½ç¼å·</th> |
| | | <th>ä»åº</th> |
| | | <th>å建人</th> |
| | | <th class="op-col">æä½</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>P001</td> |
| | | <td>A01-01-01</td> |
| | | <td>ä¸å·ä»</td> |
| | | <td>å¼ ä¸</td> |
| | | <td class="op-col"> |
| | | <button class="mock-button mock-btn-sm">è¿ç«</button> |
| | | <button class="mock-button mock-btn-sm mock-btn-primary">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>P002</td> |
| | | <td>A01-01-02</td> |
| | | <td>ä¸å·ä»</td> |
| | | <td>æå</td> |
| | | <td class="op-col"> |
| | | <button class="mock-button mock-btn-sm">è¿ç«</button> |
| | | <button class="mock-button mock-btn-sm mock-btn-primary">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>2. åºåæç»é¡µé¢ - çµè¯çº§å«æä½</h3> |
| | | <p class="subtitle">å½å页颿¾ç¤ºç©æç¼å·ãçµè¯ç çä¿¡æ¯ï¼éè¦æ·»å ç»å®/è§£ç»/NG䏿¥æä½</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼åºåæç»è¡¨æ ¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mock-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>ç©æç¼å·</th> |
| | | <th>ç©æåç§°</th> |
| | | <th>çµè¯ç </th> |
| | | <th>åºåæ°é</th> |
| | | <th>ç¶æ</th> |
| | | <th class="op-col">æä½</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>M001</td> |
| | | <td>ä¸å
éçµæ± </td> |
| | | <td>SN20240101001</td> |
| | | <td>100</td> |
| | | <td><span class="mock-tag mock-tag-success">æ£å¸¸</span></td> |
| | | <td class="op-col"> |
| | | <button class="mock-button mock-btn-sm mock-btn-primary">ç»å®</button> |
| | | <button class="mock-button mock-btn-sm">è§£ç»</button> |
| | | <button class="mock-button mock-btn-sm mock-btn-danger">NG䏿¥</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>M001</td> |
| | | <td>ä¸å
éçµæ± </td> |
| | | <td>SN20240101002</td> |
| | | <td>100</td> |
| | | <td><span class="mock-tag mock-tag-warning">å¼å¸¸</span></td> |
| | | <td class="op-col"> |
| | | <button class="mock-button mock-btn-sm mock-btn-primary">ç»å®</button> |
| | | <button class="mock-button mock-btn-sm">è§£ç»</button> |
| | | <button class="mock-button mock-btn-sm mock-btn-danger">NG䏿¥</button> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>æé®æä½ç¡®è®¤é®é¢</h3> |
| | | <p class="subtitle">MESæ¥å£è°ç¨å¯è½å¤±è´¥æéè¦é¢å¤åæ°</p> |
| | | |
| | | <div class="options"> |
| | | <div class="option" data-choice="direct" onclick="toggleSelect(this)"> |
| | | <div class="letter">A</div> |
| | | <div class="content"> |
| | | <h3>ç´æ¥è°ç¨</h3> |
| | | <p>ç¹å»æé®ç´æ¥è°ç¨MESæ¥å£ï¼æå/失败åå¼¹åºæç¤º</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>æä½ç®åå¿«æ·</li><li>éåé«é¢æä½</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>æ æ³è¾å
¥é¢å¤åæ°</li><li>é误åé¾ä»¥éè¯</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="dialog" onclick="toggleSelect(this)"> |
| | | <div class="letter">B</div> |
| | | <div class="content"> |
| | | <h3>å¼¹çªç¡®è®¤</h3> |
| | | <p>ç¹å»åå¼¹åºç¡®è®¤å¯¹è¯æ¡ï¼æ¾ç¤ºåæ°å¹¶å¯ä¿®æ¹ï¼ç¡®è®¤åè°ç¨</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>å¯é¢è§/ä¿®æ¹åæ°</li><li>鲿¢è¯¯æä½</li><li>æ¾ç¤ºè¯¦ç»é误信æ¯</li></ul></div> |
| | | <div class="cons"><h4>缺ç¹</h4><ul><li>æä½æ¥éª¤å¤</li><li>å½±åæç</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <style> |
| | | .mock-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | font-size: 13px; |
| | | } |
| | | .mock-table th, .mock-table td { |
| | | border: 1px solid #e0e0e0; |
| | | padding: 10px 12px; |
| | | text-align: left; |
| | | } |
| | | .mock-table th { |
| | | background: #f5f5f5; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .mock-table .op-col { |
| | | width: 180px; |
| | | text-align: center; |
| | | } |
| | | .mock-table tbody tr:nth-child(even) { |
| | | background: #fafafa; |
| | | } |
| | | .mock-btn-sm { |
| | | padding: 5px 12px; |
| | | font-size: 12px; |
| | | margin: 0 3px; |
| | | } |
| | | .mock-btn-primary { |
| | | background: #1f5eff; |
| | | color: white; |
| | | border: none; |
| | | } |
| | | .mock-btn-danger { |
| | | background: #f56c6c; |
| | | color: white; |
| | | border: none; |
| | | } |
| | | .mock-tag { |
| | | display: inline-block; |
| | | padding: 3px 8px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | } |
| | | .mock-tag-success { |
| | | background: #e1f5e1; |
| | | color: #4caf50; |
| | | } |
| | | .mock-tag-warning { |
| | | background: #fff3e0; |
| | | color: #ff9800; |
| | | } |
| | | .pros-cons { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-top: 12px; |
| | | } |
| | | .pros, .cons { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | } |
| | | .pros h4 { |
| | | color: #4caf50; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .cons h4 { |
| | | color: #f56c6c; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .pros ul, .cons ul { |
| | | margin: 0; |
| | | padding-left: 16px; |
| | | } |
| | | .pros li, .cons li { |
| | | margin-bottom: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <h2>æä½åå¸å±ä¼å</h2> |
| | | <p class="subtitle">æé®å¨å䏿æ¾ç¤ºï¼è®¾ç½®åºå®å®½åº¦é²æ¢çé¢åå½¢</p> |
| | | |
| | | <div class="section"> |
| | | <h3>1. åºåä¿¡æ¯é¡µé¢ - æççº§å«æä½</h3> |
| | | <p class="subtitle">æä½ååºå®å®½åº¦ï¼æé®æ¨ªåæå</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼åºåä¿¡æ¯è¡¨æ ¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mock-table"> |
| | | <thead> |
| | | <tr> |
| | | <th style="width: 120px;">æçç¼å·</th> |
| | | <th style="width: 150px;">è´§ä½ç¼å·</th> |
| | | <th style="width: 100px;">ä»åº</th> |
| | | <th style="width: 90px;">å建人</th> |
| | | <th style="width: 200px;">æä½</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>P001</td> |
| | | <td>A01-01-01</td> |
| | | <td>ä¸å·ä»</td> |
| | | <td>å¼ ä¸</td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">è¿ç«</button> |
| | | <button class="mock-btn-inline mock-btn-success">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>P002</td> |
| | | <td>A01-01-02</td> |
| | | <td>ä¸å·ä»</td> |
| | | <td>æå</td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">è¿ç«</button> |
| | | <button class="mock-btn-inline mock-btn-success">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>P003</td> |
| | | <td>B01-01-01</td> |
| | | <td>äºå·ä»</td> |
| | | <td>çäº</td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">è¿ç«</button> |
| | | <button class="mock-btn-inline mock-btn-success">åºç«</button> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>2. åºåæç»é¡µé¢ - çµè¯çº§å«æä½</h3> |
| | | <p class="subtitle">ä¸ä¸ªæé®æ¨ªåæåï¼æä½ååºå®å®½åº¦</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼åºåæç»è¡¨æ ¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mock-table"> |
| | | <thead> |
| | | <tr> |
| | | <th style="width: 100px;">ç©æç¼å·</th> |
| | | <th style="width: 140px;">ç©æåç§°</th> |
| | | <th style="width: 150px;">çµè¯ç </th> |
| | | <th style="width: 90px;">æ°é</th> |
| | | <th style="width: 80px;">ç¶æ</th> |
| | | <th style="width: 280px;">æä½</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>M001</td> |
| | | <td>ä¸å
éçµæ± </td> |
| | | <td>SN20240101001</td> |
| | | <td>100</td> |
| | | <td><span class="mock-tag mock-tag-success">æ£å¸¸</span></td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">ç»å®</button> |
| | | <button class="mock-btn-inline mock-btn-warning">è§£ç»</button> |
| | | <button class="mock-btn-inline mock-btn-danger">NG䏿¥</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>M001</td> |
| | | <td>ä¸å
éçµæ± </td> |
| | | <td>SN20240101002</td> |
| | | <td>100</td> |
| | | <td><span class="mock-tag mock-tag-warning">å¼å¸¸</span></td> |
| | | <td> |
| | | <button class="mock-btn-inline mock-btn-primary">ç»å®</button> |
| | | <button class="mock-btn-inline mock-btn-warning">è§£ç»</button> |
| | | <button class="mock-btn-inline mock-btn-danger">NG䏿¥</button> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>å¼¹çªç¡®è®¤äº¤äºæµç¨</h3> |
| | | <p class="subtitle">ç¹å»æé® â å¼¹åºç¡®è®¤å¯¹è¯æ¡ â 确认åè°ç¨MESæ¥å£</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">é¢è§ï¼ç¡®è®¤å¯¹è¯æ¡ç¤ºä¾</div> |
| | | <div class="mockup-body"> |
| | | <div class="mock-dialog"> |
| | | <div class="mock-dialog-header"> |
| | | <span class="mock-dialog-title">确认æä½</span> |
| | | <span class="mock-dialog-close">â</span> |
| | | </div> |
| | | <div class="mock-dialog-body"> |
| | | <p class="mock-dialog-text">æ¨å³å°æ§è¡ <strong>æçè¿ç«</strong> æä½</p> |
| | | <div class="mock-dialog-info"> |
| | | <div class="mock-info-row"> |
| | | <span class="mock-info-label">æçç ï¼</span> |
| | | <span class="mock-info-value">P001</span> |
| | | </div> |
| | | <div class="mock-info-row"> |
| | | <span class="mock-info-label">设å¤ç¼ç ï¼</span> |
| | | <span class="mock-info-value">WCS_001</span> |
| | | </div> |
| | | <div class="mock-info-row"> |
| | | <span class="mock-info-label">èµæºç¼ç ï¼</span> |
| | | <span class="mock-info-value">RESOURCE_001</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="mock-dialog-footer"> |
| | | <button class="mock-btn-inline mock-btn-default">åæ¶</button> |
| | | <button class="mock-btn-inline mock-btn-primary">确认æ§è¡</button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>ä¸ä¸ä¸ªé®é¢</h3> |
| | | <p class="subtitle">å
³äºMESæ¥å£è°ç¨çåæ°è·åæ¹å¼</p> |
| | | |
| | | <div class="options"> |
| | | <div class="option" data-choice="config" onclick="toggleSelect(this)"> |
| | | <div class="letter">A</div> |
| | | <div class="content"> |
| | | <h3>ç³»ç»é
ç½®</h3> |
| | | <p>设å¤ç¼ç ãèµæºç¼ç çåæ°ä»ç³»ç»é
ç½®ä¸è¯»åï¼ç¨æ·æ éè¾å
¥</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>æä½ç®å</li><li>åå°äººä¸ºé误</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="input" onclick="toggleSelect(this)"> |
| | | <div class="letter">B</div> |
| | | <div class="content"> |
| | | <h3>å¼¹çªè¾å
¥</h3> |
| | | <p>å¨ç¡®è®¤å¯¹è¯æ¡ä¸æ¾ç¤ºåæ°è¾å
¥æ¡ï¼å
è®¸ç¨æ·ä¿®æ¹é»è®¤å¼</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>çµæ´»æ§é«</li><li>éåºä¸ååºæ¯</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="hybrid" onclick="toggleSelect(this)"> |
| | | <div class="letter">C</div> |
| | | <div class="content"> |
| | | <h3>æ··åæ¨¡å¼</h3> |
| | | <p>å
³é®åæ°ä»é
置读åï¼å¯éåæ°å¨å¼¹çªä¸æä¾è¾å
¥</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>平衡ç®ä¾¿æ§åçµæ´»æ§</li><li>å¸¸è§æä½å¿«éï¼ç¹æ®åºæ¯å¯è°æ´</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <style> |
| | | .mock-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | font-size: 13px; |
| | | table-layout: fixed; |
| | | } |
| | | .mock-table th, .mock-table td { |
| | | border: 1px solid #e0e0e0; |
| | | padding: 10px 12px; |
| | | text-align: left; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | .mock-table th { |
| | | background: #f5f5f5; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .mock-table tbody tr:nth-child(even) { |
| | | background: #fafafa; |
| | | } |
| | | .mock-table tbody tr:hover { |
| | | background: #f0f7ff; |
| | | } |
| | | .mock-btn-inline { |
| | | padding: 6px 14px; |
| | | font-size: 13px; |
| | | border: 1px solid #dcdfe6; |
| | | background: white; |
| | | border-radius: 4px; |
| | | cursor: pointer; |
| | | margin-right: 8px; |
| | | transition: all 0.2s; |
| | | } |
| | | .mock-btn-inline:last-child { |
| | | margin-right: 0; |
| | | } |
| | | .mock-btn-inline:hover { |
| | | opacity: 0.85; |
| | | } |
| | | .mock-btn-primary { |
| | | background: #1f5eff; |
| | | color: white; |
| | | border-color: #1f5eff; |
| | | } |
| | | .mock-btn-success { |
| | | background: #67c23a; |
| | | color: white; |
| | | border-color: #67c23a; |
| | | } |
| | | .mock-btn-warning { |
| | | background: #e6a23c; |
| | | color: white; |
| | | border-color: #e6a23c; |
| | | } |
| | | .mock-btn-danger { |
| | | background: #f56c6c; |
| | | color: white; |
| | | border-color: #f56c6c; |
| | | } |
| | | .mock-btn-default { |
| | | background: white; |
| | | color: #606266; |
| | | border-color: #dcdfe6; |
| | | } |
| | | .mock-tag { |
| | | display: inline-block; |
| | | padding: 3px 8px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | } |
| | | .mock-tag-success { |
| | | background: #e1f5e1; |
| | | color: #4caf50; |
| | | } |
| | | .mock-tag-warning { |
| | | background: #fff3e0; |
| | | color: #ff9800; |
| | | } |
| | | .mock-dialog { |
| | | width: 420px; |
| | | margin: 20px auto; |
| | | border: 1px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0,0,0,0.1); |
| | | background: white; |
| | | } |
| | | .mock-dialog-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #e0e0e0; |
| | | background: #f8fafc; |
| | | } |
| | | .mock-dialog-title { |
| | | font-weight: 600; |
| | | font-size: 16px; |
| | | color: #303133; |
| | | } |
| | | .mock-dialog-close { |
| | | cursor: pointer; |
| | | color: #909399; |
| | | font-size: 18px; |
| | | } |
| | | .mock-dialog-body { |
| | | padding: 20px; |
| | | } |
| | | .mock-dialog-text { |
| | | margin: 0 0 16px 0; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | .mock-dialog-info { |
| | | background: #f8fafc; |
| | | border-radius: 6px; |
| | | padding: 12px 16px; |
| | | } |
| | | .mock-info-row { |
| | | display: flex; |
| | | margin-bottom: 10px; |
| | | font-size: 13px; |
| | | } |
| | | .mock-info-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | .mock-info-label { |
| | | color: #909399; |
| | | width: 80px; |
| | | } |
| | | .mock-info-value { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | .mock-dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 12px; |
| | | padding: 16px 20px; |
| | | border-top: 1px solid #e0e0e0; |
| | | background: #f8fafc; |
| | | } |
| | | .pros-cons { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-top: 12px; |
| | | } |
| | | .pros, .cons { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | } |
| | | .pros h4 { |
| | | color: #4caf50; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .pros ul { |
| | | margin: 0; |
| | | padding-left: 16px; |
| | | } |
| | | .pros li { |
| | | margin-bottom: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <h2>ç¶æä¸æä½æ å°è§å</h2> |
| | | <p class="subtitle">å®ä¹åªäºåºåç¶æä¸å
许æ§è¡åªäºMESæä½</p> |
| | | |
| | | <div class="section"> |
| | | <h3>åºåä¿¡æ¯é¡µé¢ - æç级å«</h3> |
| | | <p class="subtitle">è¿ç«/åºç«æä½çè§¦åæ¡ä»¶</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">ç¶ææ å°è¡¨ï¼è¯·å¨æµè§å¨ä¸éæ©ï¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mapping-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>åºåç¶æ</th> |
| | | <th>è¿ç«æä½</th> |
| | | <th>åºç«æä½</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td><span class="status-tag status-idle">å¾
å
¥åº</span></td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | </tr> |
| | | <tr> |
| | | <td><span class="status-tag status-instock">å¨åº</span></td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | </tr> |
| | | <tr> |
| | | <td><span class="status-tag status-outbound">åºåºä¸</span></td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | </tr> |
| | | <tr> |
| | | <td><span class="status-tag status-lock">éå®</span></td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <p class="hint">æç¤ºï¼ä»¥ä¸æ¯é»è®¤å»ºè®®ï¼è¯·å¨ç»ç«¯ä¸åè¯æéè¦è°æ´çå°æ¹</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>åºåæç»é¡µé¢ - çµè¯çº§å«</h3> |
| | | <p class="subtitle">ç»å®/è§£ç»/NG䏿¥æä½çè§¦åæ¡ä»¶</p> |
| | | |
| | | <div class="mockup"> |
| | | <div class="mockup-header">ç¶ææ å°è¡¨ï¼è¯·å¨æµè§å¨ä¸éæ©ï¼</div> |
| | | <div class="mockup-body"> |
| | | <table class="mapping-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>çµè¯ç¶æ</th> |
| | | <th>ç»å®æä½</th> |
| | | <th>è§£ç»æä½</th> |
| | | <th>NG䏿¥</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td><span class="status-tag status-normal">æ£å¸¸</span></td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | </tr> |
| | | <tr> |
| | | <td><span class="status-tag status-exception">å¼å¸¸</span></td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | <td><input type="checkbox" checked> å
许</td> |
| | | </tr> |
| | | <tr> |
| | | <td><span class="status-tag status-locked">å·²éå®</span></td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | <td><input type="checkbox"> ç¦æ¢</td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <p class="hint">æç¤ºï¼ä»¥ä¸æ¯é»è®¤å»ºè®®ï¼è¯·å¨ç»ç«¯ä¸åè¯æéè¦è°æ´çå°æ¹</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="section"> |
| | | <h3>ä¸ä¸ä¸ªé®é¢</h3> |
| | | <p class="subtitle">æ¯å¦éè¦è®°å½MESæ¥å£è°ç¨æ¥å¿ï¼</p> |
| | | |
| | | <div class="options"> |
| | | <div class="option" data-choice="log-full" onclick="toggleSelect(this)"> |
| | | <div class="letter">A</div> |
| | | <div class="content"> |
| | | <h3>宿´æ¥å¿</h3> |
| | | <p>è®°å½æ¯æ¬¡MESæ¥å£è°ç¨ç宿´ä¿¡æ¯ï¼è¯·æ±ãååºãèæ¶ãç»æï¼</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>便äºé®é¢ææ¥</li><li>æ¯æå®¡è®¡è¿½æº¯</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="log-simple" onclick="toggleSelect(this)"> |
| | | <div class="letter">B</div> |
| | | <div class="content"> |
| | | <h3>ç®åæ¥å¿</h3> |
| | | <p>ä»
è®°å½è°ç¨æå/å¤±è´¥ç¶æåé误信æ¯</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>åå¨å ç¨å°</li><li>æ»¡è¶³åºæ¬éæ±</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="option" data-choice="log-none" onclick="toggleSelect(this)"> |
| | | <div class="letter">C</div> |
| | | <div class="content"> |
| | | <h3>ä¸è®°å½</h3> |
| | | <p>ä¸åç¬è®°å½æ¥å¿ï¼ä»
ä¾èµç³»ç»æ¥å¿åMESç³»ç»æ¥å¿</p> |
| | | <div class="pros-cons"> |
| | | <div class="pros"><h4>ä¼ç¹</h4><ul><li>æ é¢å¤åå¨</li><li>å®ç°ç®å</li></ul></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <style> |
| | | .mapping-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | font-size: 13px; |
| | | } |
| | | .mapping-table th, .mapping-table td { |
| | | border: 1px solid #e0e0e0; |
| | | padding: 10px 12px; |
| | | text-align: center; |
| | | } |
| | | .mapping-table th { |
| | | background: #f5f5f5; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | .mapping-table tbody tr:nth-child(even) { |
| | | background: #fafafa; |
| | | } |
| | | .mapping-table input[type="checkbox"] { |
| | | width: 16px; |
| | | height: 16px; |
| | | cursor: pointer; |
| | | } |
| | | .status-tag { |
| | | padding: 4px 10px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | .status-idle { |
| | | background: #e3f2fd; |
| | | color: #1976d2; |
| | | } |
| | | .status-instock { |
| | | background: #e8f5e9; |
| | | color: #388e3c; |
| | | } |
| | | .status-outbound { |
| | | background: #fff3e0; |
| | | color: #f57c00; |
| | | } |
| | | .status-lock { |
| | | background: #ffebee; |
| | | color: #d32f2f; |
| | | } |
| | | .status-normal { |
| | | background: #e8f5e9; |
| | | color: #388e3c; |
| | | } |
| | | .status-exception { |
| | | background: #fff3e0; |
| | | color: #f57c00; |
| | | } |
| | | .status-locked { |
| | | background: #ffebee; |
| | | color: #d32f2f; |
| | | } |
| | | .hint { |
| | | margin: 12px 0 0 0; |
| | | padding: 10px 12px; |
| | | background: #f0f7ff; |
| | | border-left: 3px solid #1f5eff; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | } |
| | | .pros-cons { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-top: 12px; |
| | | } |
| | | .pros, .cons { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | } |
| | | .pros h4 { |
| | | color: #4caf50; |
| | | margin: 0 0 6px 0; |
| | | } |
| | | .pros ul { |
| | | margin: 0; |
| | | padding-left: 16px; |
| | | } |
| | | .pros li { |
| | | margin-bottom: 4px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <div style="display:flex;align-items:center;justify-content:center;min-height:60vh"> |
| | | <p class="subtitle">æ£å¨çæè®¾è®¡æ¹æ¡...</p> |
| | | </div> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "lastSentAt": "2026-04-12T15:31:49.457Z" |
| | | } |
| | |
| | | }, |
| | | "devDependencies": { |
| | | "@vitejs/plugin-vue": "^4.0.0", |
| | | "@vitejs/plugin-vue-jsx": "^5.1.5", |
| | | "@vue/compiler-sfc": "^3.0.0", |
| | | "eslint": "^8.50.0", |
| | | "less": "^4.1.1", |
copy from Code/WCS/WIDESEAWCS_Client/src/extension/quartzJob/deviceProtocol.js
copy to Code/WCS/WIDESEAWCS_Client/src/extension/quartzJob/deviceProtocolDetail.jsx
copy from Code/WCS/WIDESEAWCS_Client/src/extension/quartzJob/deviceProtocol.js
copy to Code/WCS/WIDESEAWCS_Client/src/extension/quartzJob/dispatchInfo.jsx
copy from Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotTask.js
copy to Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/taskHty.jsx
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basicinfo/router.js"; |
| | | import extend from "@/extension/basicinfo/router.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/quartzJob/deviceInfo.js"; |
| | | import extend from "@/extension/quartzJob/deviceInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/quartzJob/deviceProtocol.js"; |
| | | import extend from "@/extension/quartzJob/deviceProtocol.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/quartzJob/deviceProtocolDetail.js"; |
| | | import extend from "@/extension/quartzJob/deviceProtocolDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/quartzJob/dispatchInfo.js"; |
| | | import extend from "@/extension/quartzJob/dispatchInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Dictionary.js"; |
| | | import extend from "@/extension/system/Sys_Dictionary.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import extend from "@/extension/system/Sys_DictionaryList.js"; |
| | | import extend from "@/extension/system/Sys_DictionaryList.jsx"; |
| | | var vueParam = { |
| | | data() { |
| | | return { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Log.js"; |
| | | import extend from "@/extension/system/Sys_Log.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Role.js"; |
| | | import extend from "@/extension/system/Sys_Role.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Role1.js"; |
| | | import extend from "@/extension/system/Sys_Role1.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Tenant.js"; |
| | | import extend from "@/extension/system/Sys_Tenant.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_User.js"; |
| | | import extend from "@/extension/system/Sys_User.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/system/Sys_Department.js"; |
| | | import extend from "@/extension/system/system/Sys_Department.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import extend from "@/extension/taskinfo/robotTask.js"; |
| | | import extend from "@/extension/taskinfo/robotTask.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/taskinfo/task.js"; |
| | | import extend from "@/extension/taskinfo/task.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/taskinfo/taskHty.js"; |
| | | import extend from "@/extension/taskinfo/taskHty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| ÎļþÃû´Ó Code/WCS/WIDESEAWCS_Client/vite.config.js ÐÞ¸Ä |
| | |
| | | import { defineConfig } from 'vite' |
| | | import vue from '@vitejs/plugin-vue' |
| | | import vueJsx from '@vitejs/plugin-vue-jsx' |
| | | import { fileURLToPath, URL } from 'node:url' |
| | | |
| | | const __dirname = fileURLToPath(new URL('.', import.meta.url)) |
| | | |
| | | export default defineConfig({ |
| | | plugins: [vue()], |
| | | plugins: [vue(), vueJsx()], |
| | | |
| | | server: { |
| | | host: '0.0.0.0', |
| | |
| | | "devDependencies": { |
| | | "@babel/plugin-syntax-dynamic-import": "^7.8.3", |
| | | "@vitejs/plugin-vue": "^4.0.0", |
| | | "@vitejs/plugin-vue-jsx": "^5.1.5", |
| | | "@vue/compiler-sfc": "^3.0.0", |
| | | "@vue/test-utils": "^2.0.0-0", |
| | | "chai": "^4.1.2", |
| | |
| | | '@vitejs/plugin-vue': |
| | | specifier: ^4.0.0 |
| | | version: 4.6.2(vite@5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1))(vue@3.5.30) |
| | | '@vitejs/plugin-vue-jsx': |
| | | specifier: ^5.1.5 |
| | | version: 5.1.5(vite@5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1))(vue@3.5.30) |
| | | '@vue/compiler-sfc': |
| | | specifier: ^3.0.0 |
| | | version: 3.5.30 |
| | |
| | | resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-annotate-as-pure@7.27.3': |
| | | resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-compilation-targets@7.28.6': |
| | | resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-create-class-features-plugin@7.28.6': |
| | | resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-globals@7.28.0': |
| | | resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-member-expression-to-functions@7.28.5': |
| | | resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-module-imports@7.28.6': |
| | |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-optimise-call-expression@7.27.1': |
| | | resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-plugin-utils@7.28.6': |
| | | resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-replace-supers@7.28.6': |
| | | resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0 |
| | | |
| | | '@babel/helper-skip-transparent-expression-wrappers@7.27.1': |
| | | resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} |
| | | engines: {node: '>=6.9.0'} |
| | | |
| | | '@babel/helper-string-parser@7.27.1': |
| | |
| | | |
| | | '@babel/plugin-syntax-dynamic-import@7.8.3': |
| | | resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/plugin-syntax-jsx@7.28.6': |
| | | resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/plugin-syntax-typescript@7.28.6': |
| | | resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@babel/plugin-transform-typescript@7.28.6': |
| | | resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} |
| | | engines: {node: '>=6.9.0'} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | |
| | | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} |
| | | engines: {node: '>=14'} |
| | | |
| | | '@rolldown/pluginutils@1.0.0-rc.15': |
| | | resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} |
| | | |
| | | '@rollup/rollup-android-arm-eabi@4.60.0': |
| | | resolution: {integrity: sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==} |
| | | cpu: [arm] |
| | |
| | | '@types/web-bluetooth@0.0.20': |
| | | resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} |
| | | |
| | | '@vitejs/plugin-vue-jsx@5.1.5': |
| | | resolution: {integrity: sha512-jIAsvHOEtWpslLOI2MeElGFxH7M8pM83BU/Tor4RLyiwH0FM4nUW3xdvbw20EeU9wc5IspQwMq225K3CMnJEpA==} |
| | | engines: {node: ^20.19.0 || >=22.12.0} |
| | | peerDependencies: |
| | | vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 |
| | | vue: ^3.0.0 |
| | | |
| | | '@vitejs/plugin-vue@4.6.2': |
| | | resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==} |
| | | engines: {node: ^14.18.0 || >=16.0.0} |
| | | peerDependencies: |
| | | vite: ^4.0.0 || ^5.0.0 |
| | | vue: ^3.2.25 |
| | | |
| | | '@vue/babel-helper-vue-transform-on@2.0.1': |
| | | resolution: {integrity: sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==} |
| | | |
| | | '@vue/babel-plugin-jsx@2.0.1': |
| | | resolution: {integrity: sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | peerDependenciesMeta: |
| | | '@babel/core': |
| | | optional: true |
| | | |
| | | '@vue/babel-plugin-resolve-type@2.0.1': |
| | | resolution: {integrity: sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==} |
| | | peerDependencies: |
| | | '@babel/core': ^7.0.0-0 |
| | | |
| | | '@vue/compiler-core@3.5.30': |
| | | resolution: {integrity: sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==} |
| | |
| | | '@jridgewell/trace-mapping': 0.3.31 |
| | | jsesc: 3.1.0 |
| | | |
| | | '@babel/helper-annotate-as-pure@7.27.3': |
| | | dependencies: |
| | | '@babel/types': 7.29.0 |
| | | |
| | | '@babel/helper-compilation-targets@7.28.6': |
| | | dependencies: |
| | | '@babel/compat-data': 7.29.0 |
| | |
| | | lru-cache: 5.1.1 |
| | | semver: 6.3.1 |
| | | |
| | | '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-annotate-as-pure': 7.27.3 |
| | | '@babel/helper-member-expression-to-functions': 7.28.5 |
| | | '@babel/helper-optimise-call-expression': 7.27.1 |
| | | '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) |
| | | '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 |
| | | '@babel/traverse': 7.29.0 |
| | | semver: 6.3.1 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-globals@7.28.0': {} |
| | | |
| | | '@babel/helper-member-expression-to-functions@7.28.5': |
| | | dependencies: |
| | | '@babel/traverse': 7.29.0 |
| | | '@babel/types': 7.29.0 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-module-imports@7.28.6': |
| | | dependencies: |
| | |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-optimise-call-expression@7.27.1': |
| | | dependencies: |
| | | '@babel/types': 7.29.0 |
| | | |
| | | '@babel/helper-plugin-utils@7.28.6': {} |
| | | |
| | | '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-member-expression-to-functions': 7.28.5 |
| | | '@babel/helper-optimise-call-expression': 7.27.1 |
| | | '@babel/traverse': 7.29.0 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-skip-transparent-expression-wrappers@7.27.1': |
| | | dependencies: |
| | | '@babel/traverse': 7.29.0 |
| | | '@babel/types': 7.29.0 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/helper-string-parser@7.27.1': {} |
| | | |
| | |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | |
| | | '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | |
| | | '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | |
| | | '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-annotate-as-pure': 7.27.3 |
| | | '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 |
| | | '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@babel/template@7.28.6': |
| | | dependencies: |
| | |
| | | '@pkgjs/parseargs@0.11.0': |
| | | optional: true |
| | | |
| | | '@rolldown/pluginutils@1.0.0-rc.15': {} |
| | | |
| | | '@rollup/rollup-android-arm-eabi@4.60.0': |
| | | optional: true |
| | | |
| | |
| | | |
| | | '@types/web-bluetooth@0.0.20': {} |
| | | |
| | | '@vitejs/plugin-vue-jsx@5.1.5(vite@5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1))(vue@3.5.30)': |
| | | dependencies: |
| | | '@babel/core': 7.29.0 |
| | | '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) |
| | | '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) |
| | | '@rolldown/pluginutils': 1.0.0-rc.15 |
| | | '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0) |
| | | vite: 5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1) |
| | | vue: 3.5.30 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vitejs/plugin-vue@4.6.2(vite@5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1))(vue@3.5.30)': |
| | | dependencies: |
| | | vite: 5.4.21(@types/node@25.5.0)(less@4.6.4)(sass@1.98.0)(stylus@0.54.8)(terser@5.46.1) |
| | | vue: 3.5.30 |
| | | |
| | | '@vue/babel-helper-vue-transform-on@2.0.1': {} |
| | | |
| | | '@vue/babel-plugin-jsx@2.0.1(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/helper-module-imports': 7.28.6 |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) |
| | | '@babel/template': 7.28.6 |
| | | '@babel/traverse': 7.29.0 |
| | | '@babel/types': 7.29.0 |
| | | '@vue/babel-helper-vue-transform-on': 2.0.1 |
| | | '@vue/babel-plugin-resolve-type': 2.0.1(@babel/core@7.29.0) |
| | | '@vue/shared': 3.5.30 |
| | | optionalDependencies: |
| | | '@babel/core': 7.29.0 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vue/babel-plugin-resolve-type@2.0.1(@babel/core@7.29.0)': |
| | | dependencies: |
| | | '@babel/code-frame': 7.29.0 |
| | | '@babel/core': 7.29.0 |
| | | '@babel/helper-module-imports': 7.28.6 |
| | | '@babel/helper-plugin-utils': 7.28.6 |
| | | '@babel/parser': 7.29.2 |
| | | '@vue/compiler-sfc': 3.5.30 |
| | | transitivePeerDependencies: |
| | | - supports-color |
| | | |
| | | '@vue/compiler-core@3.5.30': |
| | | dependencies: |
| | | '@babel/parser': 7.29.2 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * MESæ¥å£API模å |
| | | * æä¾ä¸MESç³»ç»çäº¤äºæ¥å£ï¼å
æ¬æçè¿åºç«ãçµè¯ç»å®è§£ç»ãNG䏿¥çåè½ |
| | | */ |
| | | import http from '@/api/http.js'; |
| | | |
| | | const baseURL = '/api'; |
| | | |
| | | // åºåä¿¡æ¯ç¸å
³MESæ¥å£ |
| | | export const stockInfoMesApi = { |
| | | /** |
| | | * æçè¿ç« |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, stockId } |
| | | * @returns {Promise} |
| | | */ |
| | | inboundInContainer(data) { |
| | | return http.post(`${baseURL}/StockInfo/inboundInContainer`, data, false, { |
| | | headers: { 'Content-Type': 'application/json' } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * æçåºç« |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, stockId, paramList } |
| | | * @returns {Promise} |
| | | */ |
| | | outboundInContainer(data) { |
| | | return http.post(`${baseURL}/StockInfo/outboundInContainer`, data, false, { |
| | | headers: { 'Content-Type': 'application/json' } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // åºåæç»ç¸å
³MESæ¥å£ |
| | | export const stockDetailMesApi = { |
| | | /** |
| | | * æççµè¯ç»å® |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, sfcList, location, operationType } |
| | | * @returns {Promise} |
| | | */ |
| | | bindContainer(data) { |
| | | return http.post(`${baseURL}/StockInfoDetail/bindContainer`, data, false, { |
| | | headers: { 'Content-Type': 'application/json' } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * æççµè¯è§£ç» |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, sfcList } |
| | | * @returns {Promise} |
| | | */ |
| | | unbindContainer(data) { |
| | | return http.post(`${baseURL}/StockInfoDetail/unbindContainer`, data, false, { |
| | | headers: { 'Content-Type': 'application/json' } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * æçNGçµè¯ä¸æ¥ |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, ngSfcList } |
| | | * @returns {Promise} |
| | | */ |
| | | containerNgReport(data) { |
| | | return http.post(`${baseURL}/StockInfoDetail/containerNgReport`, data, false, { |
| | | headers: { 'Content-Type': 'application/json' } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | export default { |
| | | stockInfo: stockInfoMesApi, |
| | | stockDetail: stockDetailMesApi |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | :title="dialogTitle" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="mes-confirm-content"> |
| | | <p class="operation-text">{{ operationText }}</p> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row" v-for="(item, index) in displayInfo" :key="index"> |
| | | <span class="info-label">{{ item.label }}:</span> |
| | | <span class="info-value">{{ item.value }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-if="errorMessage" class="error-message"> |
| | | <el-icon><Warning /></el-icon> |
| | | <span>{{ errorMessage }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="handleClose">åæ¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | :loading="loading" |
| | | @click="handleConfirm" |
| | | > |
| | | 确认æ§è¡ |
| | | </el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { defineComponent, ref, computed, watch } from 'vue'; |
| | | import { Warning } from '@element-plus/icons-vue'; |
| | | |
| | | /** |
| | | * MESç¡®è®¤å¯¹è¯æ¡ç»ä»¶ |
| | | * ç¨äºå¨æ§è¡MESæä½ï¼è¿ç«/åºç«/ç»å®/è§£ç»/NG䏿¥ï¼åæ¾ç¤ºç¡®è®¤ä¿¡æ¯ |
| | | */ |
| | | export default defineComponent({ |
| | | name: 'MesConfirmDialog', |
| | | |
| | | components: { |
| | | Warning |
| | | }, |
| | | |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | /** |
| | | * æä½ç±»å: inbound(è¿ç«) | outbound(åºç«) | bind(ç»å®) | unbind(è§£ç») | ngReport(NG䏿¥) |
| | | */ |
| | | operationType: { |
| | | type: String, |
| | | required: true |
| | | }, |
| | | /** |
| | | * æçç |
| | | */ |
| | | palletCode: { |
| | | type: String, |
| | | required: true |
| | | }, |
| | | /** |
| | | * åºåä¿¡æ¯å¯¹è±¡ï¼ç¨äºè¿ç«/åºç«æä½ï¼ |
| | | */ |
| | | stockInfo: { |
| | | type: Object, |
| | | default: null |
| | | }, |
| | | /** |
| | | * åºåæç»ä¿¡æ¯å¯¹è±¡ï¼ç¨äºç»å®/è§£ç»/NG䏿¥æä½ï¼ |
| | | */ |
| | | detailInfo: { |
| | | type: Object, |
| | | default: null |
| | | } |
| | | }, |
| | | |
| | | emits: ['update:modelValue', 'confirm'], |
| | | |
| | | setup(props, { emit }) { |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const errorMessage = ref(''); |
| | | |
| | | // çå¬modelValueååï¼åæ¥å°visible |
| | | watch( |
| | | () => props.modelValue, |
| | | (newVal) => { |
| | | visible.value = newVal; |
| | | // å¯¹è¯æ¡æå¼æ¶éç½®éè¯¯ä¿¡æ¯ |
| | | if (newVal) { |
| | | errorMessage.value = ''; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // çå¬visibleååï¼åæ¥å°modelValue |
| | | watch(visible, (newVal) => { |
| | | emit('update:modelValue', newVal); |
| | | }); |
| | | |
| | | /** |
| | | * æä½ç±»åé
ç½®æ å° |
| | | */ |
| | | const operationConfig = { |
| | | inbound: { title: 'æçè¿ç«', text: 'æ¨å³å°æ§è¡æçè¿ç«æä½' }, |
| | | outbound: { title: 'æçåºç«', text: 'æ¨å³å°æ§è¡æçåºç«æä½' }, |
| | | bind: { title: 'çµè¯ç»å®', text: 'æ¨å³å°æ§è¡çµè¯ç»å®æä½' }, |
| | | unbind: { title: 'çµè¯è§£ç»', text: 'æ¨å³å°æ§è¡çµè¯è§£ç»æä½' }, |
| | | ngReport: { title: 'NG䏿¥', text: 'æ¨å³å°æ§è¡NGçµè¯ä¸æ¥æä½' } |
| | | }; |
| | | |
| | | /** |
| | | * å¯¹è¯æ¡æ é¢ |
| | | */ |
| | | const dialogTitle = computed(() => { |
| | | return operationConfig[props.operationType]?.title || '确认æä½'; |
| | | }); |
| | | |
| | | /** |
| | | * æä½æç¤ºææ¬ |
| | | */ |
| | | const operationText = computed(() => { |
| | | return operationConfig[props.operationType]?.text || ''; |
| | | }); |
| | | |
| | | /** |
| | | * æ¾ç¤ºçä¿¡æ¯å表 |
| | | */ |
| | | const displayInfo = computed(() => { |
| | | const info = [ |
| | | { label: 'æçç ', value: props.palletCode || '-' } |
| | | ]; |
| | | |
| | | // 妿ææç»ä¿¡æ¯ï¼æ¾ç¤ºçµè¯æ°é |
| | | if (props.detailInfo) { |
| | | info.push({ |
| | | label: 'çµè¯æ°é', |
| | | value: props.detailInfo.sfcCount !== undefined ? props.detailInfo.sfcCount : '-' |
| | | }); |
| | | } |
| | | |
| | | // 妿æåºåä¿¡æ¯ï¼å¯ä»¥æ¾ç¤ºåºä½çä¿¡æ¯ |
| | | if (props.stockInfo) { |
| | | info.push({ |
| | | label: 'åºä½', |
| | | value: props.stockInfo.location || '-' |
| | | }); |
| | | } |
| | | |
| | | return info; |
| | | }); |
| | | |
| | | /** |
| | | * å
³éå¯¹è¯æ¡ |
| | | */ |
| | | const handleClose = () => { |
| | | visible.value = false; |
| | | errorMessage.value = ''; |
| | | loading.value = false; |
| | | }; |
| | | |
| | | /** |
| | | * 确认æ§è¡æä½ |
| | | * 触åconfirmäºä»¶ï¼ä¼ éæä½åè°åé误å¤ç彿° |
| | | */ |
| | | const handleConfirm = () => { |
| | | loading.value = true; |
| | | errorMessage.value = ''; |
| | | |
| | | // 触åconfirmäºä»¶ï¼ä¼ éæä½åæ°ååè°å½æ° |
| | | emit('confirm', { |
| | | operationType: props.operationType, |
| | | palletCode: props.palletCode, |
| | | stockInfo: props.stockInfo, |
| | | detailInfo: props.detailInfo, |
| | | onSuccess: () => { |
| | | // æä½æåï¼å
³éå¯¹è¯æ¡å¹¶éç½®ç¶æ |
| | | visible.value = false; |
| | | loading.value = false; |
| | | errorMessage.value = ''; |
| | | }, |
| | | onError: (error) => { |
| | | // æä½å¤±è´¥ï¼æ¾ç¤ºé误信æ¯å¹¶ä¿æå¯¹è¯æ¡æå¼ |
| | | errorMessage.value = error || 'æä½å¤±è´¥ï¼è¯·éè¯'; |
| | | loading.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | return { |
| | | visible, |
| | | loading, |
| | | errorMessage, |
| | | dialogTitle, |
| | | operationText, |
| | | displayInfo, |
| | | handleClose, |
| | | handleConfirm |
| | | }; |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .mes-confirm-content { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .operation-text { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | margin-bottom: 20px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .info-section { |
| | | background: #f8fafc; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | margin-bottom: 12px; |
| | | font-size: 14px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .info-label { |
| | | color: #909399; |
| | | width: 80px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .error-message { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | padding: 12px; |
| | | background: #fef0f0; |
| | | border: 1px solid #fde2e2; |
| | | border-radius: 6px; |
| | | color: #f56c6c; |
| | | font-size: 14px; |
| | | |
| | | .el-icon { |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | </style> |
copy from Code/WMS/WIDESEA_WMSClient/src/extension/basic/supplierInfo.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/basic/userInfo.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/check/checkOrder.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/check/checkOrderResult.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrderDetail.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrderDetail_Hty.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrder_Hty.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrder.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/inbound/purchaseOrder.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrderDetail_Hty.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/inbound/purchaseOrderDetail.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/inbound/inboundOrderDetail_Hty.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/inbound/receiveOrderDetail.jsx
copy from Code/WMS/WIDESEA_WMSClient/src/extension/outbound/outboundOrderDetail_Hty.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/outbound/outboundOrder_Hty.jsx
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | //æ¤jsæä»¶æ¯ç¨æ¥èªå®ä¹æ©å±ä¸å¡ä»£ç ï¼å¯ä»¥æ©å±ä¸äºèªå®ä¹é¡µé¢æè
éæ°é
ç½®çæç代ç |
| | | |
| | | let extension = { |
| | | components: { |
| | | //æ¥è¯¢ç颿©å±ç»ä»¶ |
| | | gridHeader: '', |
| | | gridBody: '', |
| | | gridFooter: '', |
| | | //æ°å»ºãç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶ |
| | | modelHeader: '', |
| | | modelBody: '', |
| | | modelFooter: '' |
| | | }, |
| | | tableAction: '', |
| | | buttons: { view: [], box: [], detail: [] }, |
| | | methods: { |
| | | onInit() { |
| | | // æ·»å MESæä½å |
| | | this.columns.push({ |
| | | title: 'æä½', |
| | | field: 'æä½', |
| | | align: 'center', |
| | | width: 200, |
| | | fixed: 'right', |
| | | render: (h, { row, column, index }) => { |
| | | return ( |
| | | <div> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | onClick={($e) => { this.handleInbound(row); }} |
| | | >è¿ç«</el-button> |
| | | <el-button |
| | | type="success" |
| | | size="small" |
| | | style="margin-left: 8px" |
| | | onClick={($e) => { this.handleOutbound(row); }} |
| | | >åºç«</el-button> |
| | | </div> |
| | | ); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æçè¿ç«æä½ |
| | | async handleInbound(row) { |
| | | try { |
| | | await this.$confirm(`确认æ§è¡æçè¿ç«æä½ï¼\næçç¼å·ï¼${row.palletCode}`, "è¿ç«ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfo/inboundInContainer", { |
| | | palletCode: row.palletCode, |
| | | stockId: row.id |
| | | }, "æ£å¨è°ç¨MESæ¥å£..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "æçè¿ç«æå"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "æçè¿ç«å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // æçåºç«æä½ |
| | | async handleOutbound(row) { |
| | | try { |
| | | await this.$confirm(`确认æ§è¡æçåºç«æä½ï¼\næçç¼å·ï¼${row.palletCode}`, "åºç«ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfo/outboundInContainer", { |
| | | palletCode: row.palletCode, |
| | | stockId: row.id |
| | | }, "æ£å¨è°ç¨MESæ¥å£..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "æçåºç«æå"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "æçåºç«å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | onInited() { |
| | | // æ¡æ¶åå§åé
ç½®å |
| | | }, |
| | | searchBefore(param) { |
| | | return true; |
| | | }, |
| | | searchAfter(result) { |
| | | return true; |
| | | }, |
| | | addBefore(formData) { |
| | | return true; |
| | | }, |
| | | updateBefore(formData) { |
| | | return true; |
| | | }, |
| | | rowClick({ row, column, event }) { |
| | | this.$refs.table.$refs.table.toggleRowSelection(row); |
| | | }, |
| | | modelOpenAfter(row) { |
| | | // ç¹å»ç¼è¾ãæ°å»ºæé®å¼¹åºæ¡å |
| | | } |
| | | } |
| | | }; |
| | | |
| | | export default extension; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | //æ¤jsæä»¶æ¯ç¨æ¥èªå®ä¹æ©å±ä¸å¡ä»£ç ï¼å¯ä»¥æ©å±ä¸äºèªå®ä¹é¡µé¢æè
éæ°é
ç½®çæç代ç |
| | | |
| | | let extension = { |
| | | components: { |
| | | //æ¥è¯¢ç颿©å±ç»ä»¶ |
| | | gridHeader: '', |
| | | gridBody: '', |
| | | gridFooter: '', |
| | | //æ°å»ºãç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶ |
| | | modelHeader: '', |
| | | modelBody: '', |
| | | modelFooter: '' |
| | | }, |
| | | tableAction: '', |
| | | buttons: { view: [], box: [], detail: [] }, |
| | | methods: { |
| | | onInit() { |
| | | // æ·»å MESæä½å |
| | | this.columns.push({ |
| | | title: 'æä½', |
| | | field: 'æä½', |
| | | align: 'center', |
| | | width: 280, |
| | | fixed: 'right', |
| | | render: (h, { row, column, index }) => { |
| | | // éå®ç¶æä¸æ¾ç¤ºæé® |
| | | // ç¶æ: 7=åºåºéå®, 9=ç§»åºéå®, 99=ç»çæ¤é, 199=å
¥åºæ¤é |
| | | const lockedStatuses = [7, 9, 99, 199]; |
| | | if (lockedStatuses.includes(row.status)) { |
| | | return <span style="color: #909399">ææ å¯æ§è¡æä½</span>; |
| | | } |
| | | |
| | | return ( |
| | | <div> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | onClick={($e) => { this.handleBind(row); }} |
| | | >ç»å®</el-button> |
| | | <el-button |
| | | type="warning" |
| | | size="small" |
| | | style="margin-left: 6px" |
| | | onClick={($e) => { this.handleUnbind(row); }} |
| | | >è§£ç»</el-button> |
| | | <el-button |
| | | type="danger" |
| | | size="small" |
| | | style="margin-left: 6px" |
| | | onClick={($e) => { this.handleNgReport(row); }} |
| | | >NG䏿¥</el-button> |
| | | </div> |
| | | ); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æççµè¯ç»å®æä½ |
| | | async handleBind(row) { |
| | | try { |
| | | await this.$confirm(`确认æ§è¡çµè¯ç»å®æä½ï¼\nçµè¯ç ï¼${row.serialNumber}`, "ç»å®ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/bindContainer", { |
| | | palletCode: row.palletCode || "P001", |
| | | sfcList: [row.serialNumber], |
| | | location: row.location || "", |
| | | operationType: 1 |
| | | }, "æ£å¨è°ç¨MESæ¥å£..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "çµè¯ç»å®æå"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "çµè¯ç»å®å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // æççµè¯è§£ç»æä½ |
| | | async handleUnbind(row) { |
| | | try { |
| | | await this.$confirm(`确认æ§è¡çµè¯è§£ç»æä½ï¼\nçµè¯ç ï¼${row.serialNumber}`, "è§£ç»ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/unbindContainer", { |
| | | palletCode: row.palletCode || "P001", |
| | | sfcList: [row.serialNumber] |
| | | }, "æ£å¨è°ç¨MESæ¥å£..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "çµè¯è§£ç»æå"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "çµè¯è§£ç»å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // æçNGçµè¯ä¸æ¥æä½ |
| | | async handleNgReport(row) { |
| | | try { |
| | | await this.$confirm(`确认æ§è¡NGçµè¯ä¸æ¥æä½ï¼\nçµè¯ç ï¼${row.serialNumber}`, "NG䏿¥ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/containerNgReport", { |
| | | palletCode: row.palletCode || "P001", |
| | | ngSfcList: [{ |
| | | sfc: row.serialNumber, |
| | | ngCode: "NG001", |
| | | ngEquipmentCode: "WCS_001", |
| | | ngResourceCode: "RESOURCE_001" |
| | | }] |
| | | }, "æ£å¨è°ç¨MESæ¥å£..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "NG䏿¥æå"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "NG䏿¥å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "ç½ç»é误ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | onInited() { |
| | | // æ¡æ¶åå§åé
ç½®å |
| | | }, |
| | | searchBefore(param) { |
| | | return true; |
| | | }, |
| | | searchAfter(result) { |
| | | return true; |
| | | }, |
| | | addBefore(formData) { |
| | | return true; |
| | | }, |
| | | updateBefore(formData) { |
| | | return true; |
| | | }, |
| | | rowClick({ row, column, event }) { |
| | | this.$refs.table.$refs.table.toggleRowSelection(row); |
| | | }, |
| | | modelOpenAfter(row) { |
| | | // ç¹å»ç¼è¾ãæ°å»ºæé®å¼¹åºæ¡å |
| | | } |
| | | } |
| | | }; |
| | | |
| | | export default extension; |
copy from Code/WMS/WIDESEA_WMSClient/src/extension/stock/stockInfoDetail_Hty.js
copy to Code/WMS/WIDESEA_WMSClient/src/extension/stock/stockInfo_Hty.jsx
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/customerInfo.js"; |
| | | import extend from "@/extension/basic/customerInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/locationInfo.js"; |
| | | import extend from "@/extension/basic/locationInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/materielCodeInfo.js"; |
| | | import extend from "@/extension/basic/materielCodeInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/materielInfo.js"; |
| | | import extend from "@/extension/basic/materielInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/palletCodeInfo.js"; |
| | | import extend from "@/extension/basic/palletCodeInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/supplierInfo.js"; |
| | | import extend from "@/extension/basic/supplierInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/userInfo.js"; |
| | | import extend from "@/extension/basic/userInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/basic/warehouse.js"; |
| | | import extend from "@/extension/basic/warehouse.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/check/checkOrder.js"; |
| | | import extend from "@/extension/check/checkOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/check/checkOrderResult.js"; |
| | | import extend from "@/extension/check/checkOrderResult.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/inboundOrder.js"; |
| | | import extend from "@/extension/inbound/inboundOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/inboundOrderDetail.js"; |
| | | import extend from "@/extension/inbound/inboundOrderDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/inboundOrderDetail_Hty.js"; |
| | | import extend from "@/extension/inbound/inboundOrderDetail_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/inboundOrder_Hty.js"; |
| | | import extend from "@/extension/inbound/inboundOrder_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/purchaseOrder.js"; |
| | | import extend from "@/extension/inbound/purchaseOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/purchaseOrderDetail.js"; |
| | | import extend from "@/extension/inbound/purchaseOrderDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/receiveOrder.js"; |
| | | import extend from "@/extension/inbound/receiveOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/receiveOrderDetail.js"; |
| | | import extend from "@/extension/inbound/receiveOrderDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/mesOutboundOrder.js"; |
| | | import extend from "@/extension/outbound/mesOutboundOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/outStockLockInfo.js"; |
| | | import extend from "@/extension/outbound/outStockLockInfo.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/outboundOrder.js"; |
| | | import extend from "@/extension/outbound/outboundOrder.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/outboundOrderDetail.js"; |
| | | import extend from "@/extension/outbound/outboundOrderDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/outboundOrderDetail_Hty.js"; |
| | | import extend from "@/extension/outbound/outboundOrderDetail_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/outbound/outboundOrder_Hty.js"; |
| | | import extend from "@/extension/outbound/outboundOrder_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/record/locationStatusChangeRecord.js"; |
| | | import extend from "@/extension/record/locationStatusChangeRecord.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/record/stockQuantityChangeRecord.js"; |
| | | import extend from "@/extension/record/stockQuantityChangeRecord.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/stock/stock.js"; |
| | | import extend from "@/extension/stock/stock.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import extend from "@/extension/stock/stockInfo.js"; |
| | | import extend from "@/extension/stock/stockInfo.jsx"; |
| | | import { |
| | | defineComponent, |
| | | getCurrentInstance, |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/stock/stockInfoDetail.js"; |
| | | import extend from "@/extension/stock/stockInfoDetail.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/stock/stockInfoDetail_Hty.js"; |
| | | import extend from "@/extension/stock/stockInfoDetail_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/stock/stockInfo_Hty.js"; |
| | | import extend from "@/extension/stock/stockInfo_Hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/stock/stockView.js"; |
| | | import extend from "@/extension/stock/stockView.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Dictionary.js"; |
| | | import extend from "@/extension/system/Sys_Dictionary.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import extend from "@/extension/system/Sys_DictionaryList.js"; |
| | | import extend from "@/extension/system/Sys_DictionaryList.jsx"; |
| | | var vueParam = { |
| | | data() { |
| | | return { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Log.js"; |
| | | import extend from "@/extension/system/Sys_Log.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Role.js"; |
| | | import extend from "@/extension/system/Sys_Role.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Role1.js"; |
| | | import extend from "@/extension/system/Sys_Role1.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_Tenant.js"; |
| | | import extend from "@/extension/system/Sys_Tenant.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | export default defineComponent({ |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/Sys_User.js"; |
| | | import extend from "@/extension/system/Sys_User.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/system/system/Sys_Department.js"; |
| | | import extend from "@/extension/system/system/Sys_Department.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/taskinfo/task.js"; |
| | | import extend from "@/extension/taskinfo/task.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| | |
| | | </view-grid> |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/taskinfo/task_hty.js"; |
| | | import extend from "@/extension/taskinfo/task_hty.jsx"; |
| | | import { ref, defineComponent } from "vue"; |
| | | export default defineComponent({ |
| | | setup() { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineConfig } from 'vite' |
| | | import vue from '@vitejs/plugin-vue' |
| | | import vueJsx from '@vitejs/plugin-vue-jsx' |
| | | import { resolve, dirname } from 'path' |
| | | import { fileURLToPath } from 'url' |
| | | |
| | | // https://vitejs.dev/config/ |
| | | export default defineConfig({ |
| | | plugins: [vue(), vueJsx()], |
| | | resolve: { |
| | | alias: { |
| | | '@': resolve(dirname(fileURLToPath(import.meta.url)), 'src') |
| | | } |
| | | }, |
| | | server: { |
| | | host: '0.0.0.0', |
| | | port: 8080, |
| | | open: false |
| | | }, |
| | | build: { |
| | | sourcemap: false |
| | | } |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ============================================= |
| | | -- WMS MESæ¥å£è°ç¨æ¥å¿è¡¨ |
| | | -- åå»ºæ¥æ: 2026-04-12 |
| | | -- æè¿°: è®°å½ææMESæ¥å£çè°ç¨æ¥å¿ï¼å
æ¬è¯·æ±ãååºãèæ¶ãæå/å¤±è´¥ç¶æçä¿¡æ¯ |
| | | -- ============================================= |
| | | |
| | | IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Dt_MesApiLog') |
| | | BEGIN |
| | | CREATE TABLE Dt_MesApiLog ( |
| | | Id BIGINT PRIMARY KEY IDENTITY(1,1), |
| | | ApiType NVARCHAR(50) NOT NULL, -- æ¥å£ç±»å |
| | | RequestJson NVARCHAR(MAX) NULL, -- 请æ±JSON |
| | | ResponseJson NVARCHAR(MAX) NULL, -- ååºJSON |
| | | IsSuccess BIT NOT NULL DEFAULT 0, -- æ¯å¦æå |
| | | ErrorMessage NVARCHAR(500) NULL, -- éè¯¯ä¿¡æ¯ |
| | | ElapsedMs INT NOT NULL DEFAULT 0, -- èæ¶(毫ç§) |
| | | CreateDate DATETIME NOT NULL, -- å建æ¶é´ |
| | | Creator NVARCHAR(50) NULL, -- å建人 |
| | | ModifyDate DATETIME NULL, -- ä¿®æ¹æ¶é´ |
| | | Modifier NVARCHAR(50) NULL -- ä¿®æ¹äºº |
| | | ); |
| | | |
| | | -- åå»ºç´¢å¼ |
| | | CREATE INDEX IX_MesApiLog_ApiType ON Dt_MesApiLog(ApiType); |
| | | CREATE INDEX IX_MesApiLog_CreateDate ON Dt_MesApiLog(CreateDate); |
| | | CREATE INDEX IX_MesApiLog_IsSuccess ON Dt_MesApiLog(IsSuccess); |
| | | |
| | | PRINT 'MESæ¥å£æ¥å¿è¡¨ Dt_MesApiLog å建æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MESæ¥å£æ¥å¿è¡¨ Dt_MesApiLog å·²åå¨'; |
| | | END |
| | | GO |
| | | |
| | | -- ============================================= |
| | | -- æå
¥MESç³»ç»é
ç½® |
| | | -- ============================================= |
| | | |
| | | -- æ£æ¥å¹¶æå
¥MES设å¤ç¼ç é
ç½® |
| | | IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_EquipmentCode') |
| | | BEGIN |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_EquipmentCode', 'WCS_001', 'MES设å¤ç¼ç ', GETDATE(), 'System'); |
| | | PRINT 'MES设å¤ç¼ç é
ç½®æå
¥æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MES设å¤ç¼ç é
置已åå¨'; |
| | | END |
| | | GO |
| | | |
| | | -- æ£æ¥å¹¶æå
¥MESèµæºç¼ç é
ç½® |
| | | IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_ResourceCode') |
| | | BEGIN |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_ResourceCode', 'RESOURCE_001', 'MESèµæºç¼ç ', GETDATE(), 'System'); |
| | | PRINT 'MESèµæºç¼ç é
ç½®æå
¥æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MESèµæºç¼ç é
置已åå¨'; |
| | | END |
| | | GO |
| | | |
| | | -- æ£æ¥å¹¶æå
¥MESæ¥å£å°åé
ç½® |
| | | IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_ApiBaseUrl') |
| | | BEGIN |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_ApiBaseUrl', 'http://mes-server/api', 'MESæ¥å£å°å', GETDATE(), 'System'); |
| | | PRINT 'MESæ¥å£å°åé
ç½®æå
¥æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MESæ¥å£å°åé
置已åå¨'; |
| | | END |
| | | GO |
| | | |
| | | -- æ£æ¥å¹¶æå
¥MESæ¥å£è¶
æ¶æ¶é´é
ç½® |
| | | IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_TimeoutSeconds') |
| | | BEGIN |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_TimeoutSeconds', '30', 'MESæ¥å£è¶
æ¶æ¶é´(ç§)', GETDATE(), 'System'); |
| | | PRINT 'MESæ¥å£è¶
æ¶æ¶é´é
ç½®æå
¥æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MESæ¥å£è¶
æ¶æ¶é´é
置已åå¨'; |
| | | END |
| | | GO |
| | | |
| | | PRINT 'MESæ¥å£æ¥å¿è¡¨åç³»ç»é
ç½®èæ¬æ§è¡å®æ'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// æççµè¯ç»å®è¯·æ±DTO |
| | | /// </summary> |
| | | public class BindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä½ç½®ä¿¡æ¯ |
| | | /// </summary> |
| | | public string Location { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æä½ç±»åï¼0-é»è®¤ 1-è¿ç« 2-åºç« 3-è¿åºç« |
| | | /// </summary> |
| | | public int OperationType { get; set; } = 1; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥è¯·æ±DTO |
| | | /// </summary> |
| | | public class ContainerNgReportRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯å表 |
| | | /// </summary> |
| | | public List<NgSfcItemDto> NgSfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯é¡¹DTO |
| | | /// </summary> |
| | | public class NgSfcItemDto |
| | | { |
| | | /// <summary> |
| | | /// äº§åæ¡ç |
| | | /// </summary> |
| | | public string Sfc { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NG代ç |
| | | /// </summary> |
| | | public string NgCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGè®¾å¤ |
| | | /// </summary> |
| | | public string NgEquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGèµæº |
| | | /// </summary> |
| | | public string NgResourceCode { get; set; } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// æçè¿ç«è¯·æ±DTO |
| | | /// </summary> |
| | | public class InboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿DTO |
| | | /// </summary> |
| | | public class MesApiLogDto |
| | | { |
| | | /// <summary> |
| | | /// æ¥å£ç±»å |
| | | /// </summary> |
| | | public string ApiType { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 请æ±JSON |
| | | /// </summary> |
| | | public string RequestJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºJSON |
| | | /// </summary> |
| | | public string ResponseJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦æå |
| | | /// </summary> |
| | | public bool IsSuccess { get; set; } |
| | | |
| | | /// <summary> |
| | | /// éè¯¯ä¿¡æ¯ |
| | | /// </summary> |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èæ¶ï¼æ¯«ç§ï¼ |
| | | /// </summary> |
| | | public int ElapsedMs { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建人 |
| | | /// </summary> |
| | | public string Creator { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// æçåºç«è¯·æ±DTO |
| | | /// </summary> |
| | | public class OutboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 产ååæ°å表ï¼å¯éï¼ |
| | | /// </summary> |
| | | public List<ParamItemDto> ParamList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 忰项DTO |
| | | /// </summary> |
| | | public class ParamItemDto |
| | | { |
| | | /// <summary> |
| | | /// åæ°ç¼ç |
| | | /// </summary> |
| | | public string ParamCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åæ°å¼ |
| | | /// </summary> |
| | | public string ParamValue { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ééæ¶é´ |
| | | /// </summary> |
| | | public string CollectionTime { get; set; } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// æççµè¯è§£ç»è¯·æ±DTO |
| | | /// </summary> |
| | | public class UnbindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Collections.Generic; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_DTO.MES; |
| | | |
| | | namespace WIDESEA_IMesService |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡æ¥å£ |
| | | /// </summary> |
| | | public interface IMesLogService : IDependency |
| | | { |
| | | /// <summary> |
| | | /// è®°å½MESæ¥å£è°ç¨æ¥å¿ |
| | | /// </summary> |
| | | /// <param name="log">æ¥å¿DTO</param> |
| | | /// <returns>æ¯å¦è®°å½æå</returns> |
| | | Task<bool> LogAsync(MesApiLogDto log); |
| | | |
| | | /// <summary> |
| | | /// è·åæè¿çMESæ¥å£è°ç¨è®°å½ |
| | | /// </summary> |
| | | /// <param name="apiType">æ¥å£ç±»å</param> |
| | | /// <param name="count">è®°å½æ°é</param> |
| | | /// <returns>æ¥å¿å表</returns> |
| | | Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <TargetFramework>net8.0</TargetFramework> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <Nullable>enable</Nullable> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_DTO\WIDESEA_DTO.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Threading.Tasks; |
| | | using SqlSugar; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_IMesService; |
| | | using WIDESEA_Model.Models.Mes; |
| | | |
| | | namespace WIDESEA_MesService |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡å®ç° |
| | | /// </summary> |
| | | public class MesLogService : IMesLogService |
| | | { |
| | | private readonly ISqlSugarClient _db; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="db">æ°æ®åºå®¢æ·ç«¯</param> |
| | | public MesLogService(ISqlSugarClient db) |
| | | { |
| | | _db = db; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è®°å½MESæ¥å£è°ç¨æ¥å¿ |
| | | /// </summary> |
| | | /// <param name="log">æ¥å¿DTO</param> |
| | | /// <returns>æ¯å¦è®°å½æå</returns> |
| | | public async Task<bool> LogAsync(MesApiLogDto log) |
| | | { |
| | | try |
| | | { |
| | | var entity = new Dt_MesApiLog |
| | | { |
| | | ApiType = log.ApiType, |
| | | RequestJson = log.RequestJson, |
| | | ResponseJson = log.ResponseJson, |
| | | IsSuccess = log.IsSuccess, |
| | | ErrorMessage = log.ErrorMessage, |
| | | ElapsedMs = log.ElapsedMs, |
| | | CreateDate = DateTime.Now, |
| | | Creator = log.Creator |
| | | }; |
| | | |
| | | var result = await _db.Insertable(entity).ExecuteCommandAsync(); |
| | | return result > 0; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // è®°å½æ¥å¿å¤±è´¥ä¸å½±å主æµç¨ |
| | | Console.WriteLine($"è®°å½MESæ¥å¿å¤±è´¥: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæè¿çMESæ¥å£è°ç¨è®°å½ |
| | | /// </summary> |
| | | /// <param name="apiType">æ¥å£ç±»å</param> |
| | | /// <param name="count">è®°å½æ°é</param> |
| | | /// <returns>æ¥å¿å表</returns> |
| | | public async Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50) |
| | | { |
| | | try |
| | | { |
| | | var entities = await _db.Queryable<Dt_MesApiLog>() |
| | | .Where(x => x.ApiType == apiType) |
| | | .OrderByDescending(x => x.CreateDate) |
| | | .Take(count) |
| | | .ToListAsync(); |
| | | |
| | | return entities.Select(e => new MesApiLogDto |
| | | { |
| | | ApiType = e.ApiType, |
| | | RequestJson = e.RequestJson, |
| | | ResponseJson = e.ResponseJson, |
| | | IsSuccess = e.IsSuccess, |
| | | ErrorMessage = e.ErrorMessage, |
| | | ElapsedMs = e.ElapsedMs, |
| | | Creator = e.Creator |
| | | }).ToList(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"è·åMESæ¥å¿å¤±è´¥: {ex.Message}"); |
| | | return new List<MesApiLogDto>(); |
| | | } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <TargetFramework>net8.0</TargetFramework> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <Nullable>enable</Nullable> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_IMesService\WIDESEA_IMesService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_Model\WIDESEA_Model.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_DTO\WIDESEA_DTO.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | |
| | | namespace WIDESEA_Model.Models.Mes |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£è°ç¨æ¥å¿å®ä½ |
| | | /// </summary> |
| | | [SugarTable("Dt_MesApiLog")] |
| | | public class Dt_MesApiLog |
| | | { |
| | | /// <summary> |
| | | /// 主é®ID |
| | | /// </summary> |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public long Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¥å£ç±»åï¼InboundInContainer, OutboundInContainer, BindContainer, UnbindContainer, ContainerNgReport |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = false)] |
| | | public string ApiType { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 请æ±JSON |
| | | /// </summary> |
| | | [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)] |
| | | public string RequestJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºJSON |
| | | /// </summary> |
| | | [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)] |
| | | public string ResponseJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦æå |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public bool IsSuccess { get; set; } |
| | | |
| | | /// <summary> |
| | | /// éè¯¯ä¿¡æ¯ |
| | | /// </summary> |
| | | [SugarColumn(Length = 500, IsNullable = true)] |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èæ¶ï¼æ¯«ç§ï¼ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public int ElapsedMs { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建æ¶é´ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public DateTime CreateDate { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建人 |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = true)] |
| | | public string Creator { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹æ¶é´ |
| | | /// </summary> |
| | | public DateTime? ModifyDate { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹äºº |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = true)] |
| | | public string Modifier { get; set; } |
| | | } |
| | | } |
| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_DTO.Stock; |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IMesService; |
| | | using WIDESEA_ISystemService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Common.StockEnum; |
| | | using System.Diagnostics; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Stock |
| | | { |
| | |
| | | [ApiController] |
| | | public class StockInfoController : ApiBaseController<IStockInfoService, Dt_StockInfo> |
| | | { |
| | | public StockInfoController(IStockInfoService service) : base(service) |
| | | private readonly IMesLogService _mesLogService; |
| | | private readonly IMesService _mesService; |
| | | private readonly ISys_DictionaryService _sysDictionaryService; |
| | | |
| | | public StockInfoController( |
| | | IStockInfoService service, |
| | | IMesLogService mesLogService, |
| | | IMesService mesService, |
| | | ISys_DictionaryService sysDictionaryService) : base(service) |
| | | { |
| | | _mesLogService = mesLogService; |
| | | _mesService = mesService; |
| | | _sysDictionaryService = sysDictionaryService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | var result = await Service.Get3DLayoutAsync(warehouseId); |
| | | return WebResponseContent.Instance.OK(data: result); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æçè¿ç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">è¿ç«è¯·æ±åæ°</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("inboundInContainer")] |
| | | public async Task<WebResponseContent> InboundInContainer([FromBody] InboundInContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. æ¥è¯¢åºåä¿¡æ¯ - 使ç¨åæ¡è®°å½æ¥è¯¢æ¹æ³æé«æç |
| | | var stockInfo = await Service.Repository.QueryDataNavFirstAsync(x => x.Id == dto.StockId); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | return response.Error("åºåä¿¡æ¯ä¸åå¨"); |
| | | } |
| | | |
| | | // 3. éªè¯åºåç¶æï¼ä»
"å
¥åºå®æ"ç¶æå
许è¿ç«ï¼ |
| | | if (stockInfo.StockStatus != StockStatusEmun.å
¥åºå®æ.GetHashCode()) |
| | | { |
| | | return response.Error($"å½ååºåç¶æä¸å
许è¿ç«æä½ï¼å½åç¶æï¼{stockInfo.StockStatus}"); |
| | | } |
| | | |
| | | // 4. è·åç³»ç»é
ç½® - ç´æ¥ä»æ°æ®åºæ¥è¯¢ |
| | | var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); |
| | | |
| | | string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); |
| | | string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); |
| | | |
| | | // 5. æé MESè¯·æ± |
| | | var mesRequest = new InboundInContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 6. è°ç¨MESæ¥å£ï¼åæ¥æ¹æ³ï¼ |
| | | var mesResult = _mesService.InboundInContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 7. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "InboundInContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.IsSuccess, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | // 8. è¿åç»æ |
| | | if (mesResult.IsSuccess) |
| | | { |
| | | return response.OK("æçè¿ç«æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "InboundInContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | return response.Error($"æçè¿ç«å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æçåºç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">åºç«è¯·æ±åæ°</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("outboundInContainer")] |
| | | public async Task<WebResponseContent> OutboundInContainer([FromBody] OutboundInContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. æ¥è¯¢åºåä¿¡æ¯ - 使ç¨åæ¡è®°å½æ¥è¯¢æ¹æ³æé«æç |
| | | var stockInfo = await Service.Repository.QueryDataNavFirstAsync(x => x.Id == dto.StockId); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | return response.Error("åºåä¿¡æ¯ä¸åå¨"); |
| | | } |
| | | |
| | | // 3. éªè¯åºåç¶æï¼"åºåºéå®"æ"åºåºå®æ"ç¶æå
许åºç«ï¼ |
| | | var allowedStatuses = new[] |
| | | { |
| | | StockStatusEmun.åºåºéå®.GetHashCode(), |
| | | StockStatusEmun.åºåºå®æ.GetHashCode() |
| | | }; |
| | | |
| | | if (!allowedStatuses.Contains(stockInfo.StockStatus)) |
| | | { |
| | | return response.Error($"å½ååºåç¶æä¸å
许åºç«æä½ï¼å½åç¶æï¼{stockInfo.StockStatus}"); |
| | | } |
| | | |
| | | // 4. è·åç³»ç»é
ç½® |
| | | var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); |
| | | |
| | | string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); |
| | | string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); |
| | | |
| | | // 5. æé MESè¯·æ± |
| | | var mesRequest = new OutboundInContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | ParamList = dto.ParamList?.Select(p => new ParamItem |
| | | { |
| | | ParamCode = p.ParamCode, |
| | | ParamValue = p.ParamValue, |
| | | CollectionTime = DateTime.TryParse(p.CollectionTime, out var ct) ? ct : DateTime.Now |
| | | }).ToList() |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 6. è°ç¨MESæ¥å£ï¼åæ¥æ¹æ³ï¼ |
| | | var mesResult = _mesService.OutboundInContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 7. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "OutboundInContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.IsSuccess, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | // 8. è¿åç»æ |
| | | if (mesResult.IsSuccess) |
| | | { |
| | | return response.OK("æçåºç«æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "OutboundInContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | return response.Error($"æçåºç«å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä»é
ç½®åå
¸ä¸è·åé
ç½®å¼ |
| | | /// </summary> |
| | | /// <param name="configs">é
ç½®åå
¸å表</param> |
| | | /// <param name="key">é
ç½®é®</param> |
| | | /// <param name="defaultValue">é»è®¤å¼</param> |
| | | /// <returns>é
ç½®å¼</returns> |
| | | private string GetConfigValue(System.Collections.Generic.List<WIDESEA_DTO.System.VueDictionaryDTO> configs, string key, string defaultValue = "") |
| | | { |
| | | if (configs != null) |
| | | { |
| | | var config = configs.FirstOrDefault(c => c.DicNo == key); |
| | | if (config != null && config.Data != null) |
| | | { |
| | | // Dataæ¯dynamicç±»åï¼å°è¯è·å第ä¸ä¸ªå
ç´ çvalue屿§ |
| | | try |
| | | { |
| | | // 使ç¨dynamicæ¥è®¿é®å¿åç±»åç屿§ |
| | | dynamic data = config.Data; |
| | | if (data != null) |
| | | { |
| | | // dataå¯è½æ¯IEnumerableæè
å个对象 |
| | | var enumerable = data as System.Collections.IEnumerable; |
| | | if (enumerable != null) |
| | | { |
| | | foreach (var item in enumerable) |
| | | { |
| | | // è·å第ä¸ä¸ªå
ç´ |
| | | dynamic firstItem = item; |
| | | var value = firstItem.value; |
| | | return value?.ToString() ?? defaultValue; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | // å¦ææ æ³è·åï¼è¿åé»è®¤å¼ |
| | | return defaultValue; |
| | | } |
| | | } |
| | | } |
| | | return defaultValue; |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IMesService; |
| | | using WIDESEA_ISystemService; |
| | | using WIDESEA_Model.Models; |
| | | using System.Diagnostics; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Stock |
| | | { |
| | |
| | | [ApiController] |
| | | public class StockInfoDetailController : ApiBaseController<IStockInfoDetailService, Dt_StockInfoDetail> |
| | | { |
| | | public StockInfoDetailController(IStockInfoDetailService service) : base(service) |
| | | private readonly IMesLogService _mesLogService; |
| | | private readonly IMesService _mesService; |
| | | private readonly ISys_DictionaryService _sysDictionaryService; |
| | | |
| | | public StockInfoDetailController( |
| | | IStockInfoDetailService service, |
| | | IMesLogService mesLogService, |
| | | IMesService mesService, |
| | | ISys_DictionaryService sysDictionaryService) : base(service) |
| | | { |
| | | _mesLogService = mesLogService; |
| | | _mesService = mesService; |
| | | _sysDictionaryService = sysDictionaryService; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æççµè¯ç»å® - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">ç»å®è¯·æ±åæ°</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("bindContainer")] |
| | | public async Task<WebResponseContent> BindContainer([FromBody] BindContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.SfcList == null || !dto.SfcList.Any()) |
| | | { |
| | | return response.Error("çµè¯ç å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. éªè¯çµè¯ç¶æï¼é'å·²éå®'ç¶æå
许ç»å®ï¼ |
| | | var stockDetails = await Service.Repository.QueryDataAsync(x => dto.SfcList.Contains(x.SerialNumber)); |
| | | if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) |
| | | { |
| | | return response.Error("å½ååºåæç»å
å«å·²éå®ç¶æï¼ä¸å
许æ§è¡ç»å®æä½"); |
| | | } |
| | | |
| | | // 3. è·åç³»ç»é
ç½® |
| | | var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); |
| | | |
| | | string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); |
| | | string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); |
| | | |
| | | // 3. æé MESè¯·æ± - å°çµè¯å表转æ¢ä¸ºContainerSfcItemæ ¼å¼ |
| | | var mesRequest = new BindContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem |
| | | { |
| | | Sfc = sfc, |
| | | Location = dto.Location ?? "" |
| | | }).ToList(), |
| | | OperationType = dto.OperationType |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ï¼åæ¥æ¹æ³ï¼ |
| | | var mesResult = _mesService.BindContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "BindContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.IsSuccess, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.IsSuccess) |
| | | { |
| | | return response.OK("æççµè¯ç»å®æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "BindContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | return response.Error($"æççµè¯ç»å®å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æççµè¯è§£ç» - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">è§£ç»è¯·æ±åæ°</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("unbindContainer")] |
| | | public async Task<WebResponseContent> UnbindContainer([FromBody] UnbindContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.SfcList == null || !dto.SfcList.Any()) |
| | | { |
| | | return response.Error("çµè¯ç å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. éªè¯çµè¯ç¶æï¼é'å·²éå®'ç¶æå
许解ç»ï¼ |
| | | var stockDetails = await Service.Repository.QueryDataAsync(x => dto.SfcList.Contains(x.SerialNumber)); |
| | | if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) |
| | | { |
| | | return response.Error("å½ååºåæç»å
å«å·²éå®ç¶æï¼ä¸å
许æ§è¡è§£ç»æä½"); |
| | | } |
| | | |
| | | // 3. è·åç³»ç»é
ç½® |
| | | var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); |
| | | |
| | | string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); |
| | | string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); |
| | | |
| | | // 3. æé MESè¯·æ± |
| | | var mesRequest = new UnBindContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainCode = dto.PalletCode, |
| | | SfcList = dto.SfcList |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ï¼åæ¥æ¹æ³ï¼ |
| | | var mesResult = _mesService.UnBindContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "UnbindContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.IsSuccess, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.IsSuccess) |
| | | { |
| | | return response.OK("æççµè¯è§£ç»æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "UnbindContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | return response.Error($"æççµè¯è§£ç»å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥ - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">NG䏿¥è¯·æ±åæ°</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("containerNgReport")] |
| | | public async Task<WebResponseContent> ContainerNgReport([FromBody] ContainerNgReportRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.NgSfcList == null || !dto.NgSfcList.Any()) |
| | | { |
| | | return response.Error("NGçµè¯å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. éªè¯çµè¯ç¶æï¼é'å·²éå®'ç¶æå
许NG䏿¥ï¼ |
| | | var sfcList = dto.NgSfcList.Select(x => x.Sfc).ToList(); |
| | | var stockDetails = await Service.Repository.QueryDataAsync(x => sfcList.Contains(x.SerialNumber)); |
| | | if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) |
| | | { |
| | | return response.Error("å½ååºåæç»å
å«å·²éå®ç¶æï¼ä¸å
许æ§è¡NG䏿¥æä½"); |
| | | } |
| | | |
| | | // 3. è·åç³»ç»é
ç½® |
| | | var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); |
| | | |
| | | string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); |
| | | string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); |
| | | |
| | | // 3. æé MESè¯·æ± - å°DTOæ ¼å¼è½¬æ¢ä¸ºMESè¯·æ±æ ¼å¼ |
| | | var mesRequest = new ContainerNgReportRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | NgSfcList = dto.NgSfcList.Select(ng => new NgSfcItem |
| | | { |
| | | Sfc = ng.Sfc, |
| | | NgCode = ng.NgCode, |
| | | NgEquipmentCode = ng.NgEquipmentCode, |
| | | NgResourceCode = ng.NgResourceCode |
| | | }).ToList() |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ï¼åæ¥æ¹æ³ï¼ |
| | | var mesResult = _mesService.ContainerNgReport(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "ContainerNgReport", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.IsSuccess, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.IsSuccess) |
| | | { |
| | | return response.OK("NGçµè¯ä¸æ¥æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "ContainerNgReport", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = App.User.UserName |
| | | }); |
| | | |
| | | return response.Error($"NGçµè¯ä¸æ¥å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä»é
ç½®åå
¸ä¸è·åé
ç½®å¼ |
| | | /// </summary> |
| | | /// <param name="configs">é
ç½®åå
¸å表</param> |
| | | /// <param name="key">é
ç½®é®</param> |
| | | /// <param name="defaultValue">é»è®¤å¼</param> |
| | | /// <returns>é
ç½®å¼</returns> |
| | | private string GetConfigValue(System.Collections.Generic.List<WIDESEA_DTO.System.VueDictionaryDTO> configs, string key, string defaultValue = "") |
| | | { |
| | | if (configs != null) |
| | | { |
| | | var config = configs.FirstOrDefault(c => c.DicNo == key); |
| | | if (config != null && config.Data != null) |
| | | { |
| | | // Dataæ¯dynamicç±»åï¼å°è¯è·å第ä¸ä¸ªå
ç´ çvalue屿§ |
| | | try |
| | | { |
| | | // 使ç¨dynamicæ¥è®¿é®å¿åç±»åç屿§ |
| | | dynamic data = config.Data; |
| | | if (data != null) |
| | | { |
| | | // dataå¯è½æ¯IEnumerableæè
å个对象 |
| | | var enumerable = data as System.Collections.IEnumerable; |
| | | if (enumerable != null) |
| | | { |
| | | foreach (var item in enumerable) |
| | | { |
| | | // è·å第ä¸ä¸ªå
ç´ |
| | | dynamic firstItem = item; |
| | | var value = firstItem.value; |
| | | return value?.ToString() ?? defaultValue; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | // å¦ææ æ³è·åï¼è¿åé»è®¤å¼ |
| | | return defaultValue; |
| | | } |
| | | } |
| | | } |
| | | return defaultValue; |
| | | } |
| | | } |
| | | } |
| | |
| | | <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_CheckService\WIDESEA_CheckService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_InboundService\WIDESEA_InboundService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_MesService\WIDESEA_MesService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_OutboundService\WIDESEA_OutboundService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_RecordService\WIDESEA_RecordService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_StockService\WIDESEA_StockService.csproj" /> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # WMSåºå页é¢MESæ¥å£éæå®ç°è®¡å |
| | | |
| | | > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| | | |
| | | **Goal:** 为WMSåºåä¿¡æ¯é¡µé¢ååºåæç»é¡µé¢æ·»å æä½åï¼è°ç¨MESç³»ç»çè¿ç«/åºç«/ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | |
| | | **Architecture:** å端å¨åºåè¡¨æ ¼ä¸æ·»å æä½åï¼ç¹å»åå¼¹åºç¡®è®¤å¯¹è¯æ¡ï¼ç¡®è®¤åè°ç¨å端APIï¼åç«¯æ¥æ¶è¯·æ±ï¼è°ç¨MESæå¡ï¼è®°å½å®æ´æ¥å¿ï¼è¿åç»æ |
| | | |
| | | **Tech Stack:** Vue 3, Element Plus, .NET 8, SqlSugar ORM, SQL Server, HttpClient |
| | | |
| | | --- |
| | | |
| | | ## æä»¶ç»æ |
| | | |
| | | ### å端æä»¶ |
| | | |
| | | ``` |
| | | WMS/WIDESEA_WMSClient/src/ |
| | | âââ views/stock/ |
| | | â âââ stockInfo.vue # ä¿®æ¹ï¼æ·»å æä½å |
| | | â âââ stockInfoDetail.vue # ä¿®æ¹ï¼æ·»å æä½å |
| | | âââ components/ |
| | | â âââ MesConfirmDialog.vue # æ°å¢ï¼MESç¡®è®¤å¯¹è¯æ¡ |
| | | âââ api/ |
| | | âââ mes.js # æ°å¢ï¼MES APIè°ç¨ |
| | | ``` |
| | | |
| | | ### å端æä»¶ |
| | | |
| | | ``` |
| | | WMS/WIDESEA_WMSServer/ |
| | | âââ Controllers/ |
| | | â âââ Stock/ |
| | | â âââ StockInfoController.cs # ä¿®æ¹ï¼æ·»å è¿ç«/åºç«æ¥å£ |
| | | â âââ StockInfoDetailController.cs # ä¿®æ¹ï¼æ·»å ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | âââ Services/ |
| | | â âââ Mes/ |
| | | â âââ IMesLogService.cs # æ°å¢ï¼æ¥å¿æå¡æ¥å£ |
| | | â âââ MesLogService.cs # æ°å¢ï¼æ¥å¿æå¡å®ç° |
| | | âââ DTO/ |
| | | â âââ Mes/ |
| | | â â âââ MesApiLogDto.cs # æ°å¢ï¼æ¥å¿DTO |
| | | â â âââ InboundInContainerRequestDto.cs # æ°å¢ï¼è¿ç«è¯·æ±DTO |
| | | â â âââ OutboundInContainerRequestDto.cs # æ°å¢ï¼åºç«è¯·æ±DTO |
| | | â â âââ BindContainerRequestDto.cs # æ°å¢ï¼ç»å®è¯·æ±DTO |
| | | â â âââ UnbindContainerRequestDto.cs # æ°å¢ï¼è§£ç»è¯·æ±DTO |
| | | â â âââ ContainerNgReportRequestDto.cs # æ°å¢ï¼NG䏿¥è¯·æ±DTO |
| | | â âââ Models/ |
| | | â âââ Mes/ |
| | | â âââ Dt_MesApiLog.cs # æ°å¢ï¼æ¥å¿å®ä½ |
| | | âââ Database/ |
| | | âââ Scripts/ |
| | | âââ 20260412_MesApiLog.sql # æ°å¢ï¼æ¥å¿è¡¨åå»ºèæ¬ |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 1: åå»ºæ°æ®åºè¡¨ |
| | | |
| | | **Files:** |
| | | - Create: `WMS/WIDESEA_WMSServer/Database/Scripts/20260412_MesApiLog.sql` |
| | | |
| | | - [ ] **Step 1: å建MESæ¥å£æ¥å¿è¡¨SQLèæ¬** |
| | | |
| | | ```sql |
| | | -- ============================================= |
| | | -- WMS MESæ¥å£è°ç¨æ¥å¿è¡¨ |
| | | -- ============================================= |
| | | |
| | | IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Dt_MesApiLog') |
| | | BEGIN |
| | | CREATE TABLE Dt_MesApiLog ( |
| | | Id BIGINT PRIMARY KEY IDENTITY(1,1), |
| | | ApiType NVARCHAR(50) NOT NULL, -- æ¥å£ç±»å |
| | | RequestJson NVARCHAR(MAX) NULL, -- 请æ±JSON |
| | | ResponseJson NVARCHAR(MAX) NULL, -- ååºJSON |
| | | IsSuccess BIT NOT NULL DEFAULT 0, -- æ¯å¦æå |
| | | ErrorMessage NVARCHAR(500) NULL, -- éè¯¯ä¿¡æ¯ |
| | | ElapsedMs INT NOT NULL DEFAULT 0, -- èæ¶(毫ç§) |
| | | CreateDate DATETIME NOT NULL, -- å建æ¶é´ |
| | | Creator NVARCHAR(50) NULL, -- å建人 |
| | | ModifyDate DATETIME NULL, -- ä¿®æ¹æ¶é´ |
| | | Modifier NVARCHAR(50) NULL -- ä¿®æ¹äºº |
| | | ); |
| | | |
| | | -- åå»ºç´¢å¼ |
| | | CREATE INDEX IX_MesApiLog_ApiType ON Dt_MesApiLog(ApiType); |
| | | CREATE INDEX IX_MesApiLog_CreateDate ON Dt_MesApiLog(CreateDate); |
| | | CREATE INDEX IX_MesApiLog_IsSuccess ON Dt_MesApiLog(IsSuccess); |
| | | |
| | | PRINT 'MESæ¥å£æ¥å¿è¡¨ Dt_MesApiLog å建æå'; |
| | | END |
| | | ELSE |
| | | BEGIN |
| | | PRINT 'MESæ¥å£æ¥å¿è¡¨ Dt_MesApiLog å·²åå¨'; |
| | | END |
| | | |
| | | -- æå
¥MESç³»ç»é
ç½® |
| | | IF NOT EXISTS (SELECT * FROM Dt_SystemConfig WHERE ConfigKey = 'MES_EquipmentCode') |
| | | BEGIN |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_EquipmentCode', 'WCS_001', 'MES设å¤ç¼ç ', GETDATE(), 'System'); |
| | | |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_ResourceCode', 'RESOURCE_001', 'MESèµæºç¼ç ', GETDATE(), 'System'); |
| | | |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_ApiBaseUrl', 'http://mes-server/api', 'MESæ¥å£å°å', GETDATE(), 'System'); |
| | | |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate, Modifier) |
| | | VALUES ('MES_TimeoutSeconds', '30', 'MESæ¥å£è¶
æ¶æ¶é´(ç§)', GETDATE(), 'System'); |
| | | |
| | | PRINT 'MESç³»ç»é
ç½®æå
¥æå'; |
| | | END |
| | | ``` |
| | | |
| | | - [ ] **Step 2: æ§è¡SQLèæ¬å建表** |
| | | |
| | | Run: å¨SQL Server Management Studio䏿§è¡è¯¥èæ¬ |
| | | Expected: 表å建æåï¼é
ç½®æå
¥æå |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSServer/Database/Scripts/20260412_MesApiLog.sql |
| | | git commit -m "feat(MES): æ·»å MESæ¥å£æ¥å¿è¡¨åç³»ç»é
ç½® |
| | | |
| | | - å建 Dt_MesApiLog è¡¨è®°å½æ¥å£è°ç¨æ¥å¿ |
| | | - æ·»å MESç¸å
³ç³»ç»é
置项ï¼è®¾å¤ç¼ç ãèµæºç¼ç ãæ¥å£å°åçï¼ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 2: å建å端å®ä½åDTO |
| | | |
| | | **Files:** |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Mes/Dt_MesApiLog.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/MesApiLogDto.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/InboundInContainerRequestDto.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/OutboundInContainerRequestDto.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/BindContainerRequestDto.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/UnbindContainerRequestDto.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/ContainerNgReportRequestDto.cs` |
| | | |
| | | - [ ] **Step 1: å建MESæ¥å¿å®ä½** |
| | | |
| | | ```csharp |
| | | using SqlSugar; |
| | | using System; |
| | | |
| | | namespace WIDESEA_Model.Models.Mes |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£è°ç¨æ¥å¿å®ä½ |
| | | /// </summary> |
| | | [SugarTable("Dt_MesApiLog")] |
| | | public class Dt_MesApiLog |
| | | { |
| | | /// <summary> |
| | | /// 主é®ID |
| | | /// </summary> |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public long Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¥å£ç±»åï¼InboundInContainer, OutboundInContainer, BindContainer, UnbindContainer, ContainerNgReport |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = false)] |
| | | public string ApiType { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 请æ±JSON |
| | | /// </summary> |
| | | [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)] |
| | | public string RequestJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºJSON |
| | | /// </summary> |
| | | [SugarColumn(ColumnDataType = "nvarchar(max)", IsNullable = true)] |
| | | public string ResponseJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦æå |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public bool IsSuccess { get; set; } |
| | | |
| | | /// <summary> |
| | | /// éè¯¯ä¿¡æ¯ |
| | | /// </summary> |
| | | [SugarColumn(Length = 500, IsNullable = true)] |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èæ¶ï¼æ¯«ç§ï¼ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public int ElapsedMs { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建æ¶é´ |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false)] |
| | | public DateTime CreateDate { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建人 |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = true)] |
| | | public string Creator { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹æ¶é´ |
| | | /// </summary> |
| | | public DateTime? ModifyDate { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä¿®æ¹äºº |
| | | /// </summary> |
| | | [SugarColumn(Length = 50, IsNullable = true)] |
| | | public string Modifier { get; set; } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: å建MESæ¥å¿DTO** |
| | | |
| | | ```csharp |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿DTO |
| | | /// </summary> |
| | | public class MesApiLogDto |
| | | { |
| | | /// <summary> |
| | | /// æ¥å£ç±»å |
| | | /// </summary> |
| | | public string ApiType { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 请æ±JSON |
| | | /// </summary> |
| | | public string RequestJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºJSON |
| | | /// </summary> |
| | | public string ResponseJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦æå |
| | | /// </summary> |
| | | public bool IsSuccess { get; set; } |
| | | |
| | | /// <summary> |
| | | /// éè¯¯ä¿¡æ¯ |
| | | /// </summary> |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èæ¶ï¼æ¯«ç§ï¼ |
| | | /// </summary> |
| | | public int ElapsedMs { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å建人 |
| | | /// </summary> |
| | | public string Creator { get; set; } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 3: å建è¿ç«è¯·æ±DTO** |
| | | |
| | | ```csharp |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// æçè¿ç«è¯·æ±DTO |
| | | /// </summary> |
| | | public class InboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 4: å建åºç«è¯·æ±DTO** |
| | | |
| | | ```csharp |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// æçåºç«è¯·æ±DTO |
| | | /// </summary> |
| | | public class OutboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 产ååæ°å表ï¼å¯éï¼ |
| | | /// </summary> |
| | | public List<ParamItemDto> ParamList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 忰项DTO |
| | | /// </summary> |
| | | public class ParamItemDto |
| | | { |
| | | /// <summary> |
| | | /// åæ°ç¼ç |
| | | /// </summary> |
| | | public string ParamCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åæ°å¼ |
| | | /// </summary> |
| | | public string ParamValue { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ééæ¶é´ |
| | | /// </summary> |
| | | public string CollectionTime { get; set; } |
| | | } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 5: å建ç»å®è¯·æ±DTO** |
| | | |
| | | ```csharp |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// æççµè¯ç»å®è¯·æ±DTO |
| | | /// </summary> |
| | | public class BindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä½ç½®ä¿¡æ¯ |
| | | /// </summary> |
| | | public string Location { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æä½ç±»åï¼0-é»è®¤ 1-è¿ç« 2-åºç« 3-è¿åºç« |
| | | /// </summary> |
| | | public int OperationType { get; set; } = 1; |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 6: å建解ç»è¯·æ±DTO** |
| | | |
| | | ```csharp |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// æççµè¯è§£ç»è¯·æ±DTO |
| | | /// </summary> |
| | | public class UnbindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 7: å建NG䏿¥è¯·æ±DTO** |
| | | |
| | | ```csharp |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.Mes |
| | | { |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥è¯·æ±DTO |
| | | /// </summary> |
| | | public class ContainerNgReportRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯å表 |
| | | /// </summary> |
| | | public List<NgSfcItemDto> NgSfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯é¡¹DTO |
| | | /// </summary> |
| | | public class NgSfcItemDto |
| | | { |
| | | /// <summary> |
| | | /// äº§åæ¡ç |
| | | /// </summary> |
| | | public string Sfc { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NG代ç |
| | | /// </summary> |
| | | public string NgCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGè®¾å¤ |
| | | /// </summary> |
| | | public string NgEquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGèµæº |
| | | /// </summary> |
| | | public string NgResourceCode { get; set; } |
| | | } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 8: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Mes/Dt_MesApiLog.cs |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_DTO/Mes/*.cs |
| | | git commit -m "feat(MES): æ·»å MESæ¥å£ç¸å
³å®ä½åDTO |
| | | |
| | | - æ·»å Dt_MesApiLog æ¥å¿å®ä½ |
| | | - æ·»å MesApiLogDto å忥å£è¯·æ±DTO |
| | | - æ¯æè¿ç«ãåºç«ãç»å®ãè§£ç»ãNG䏿¥æ¥å£ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 3: å建MESæ¥å¿æå¡ |
| | | |
| | | **Files:** |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_IMesService/IMesLogService.cs` |
| | | - Create: `WMS/WIDESEA_WMSServer/WIDESEA_MesService/MesLogService.cs` |
| | | |
| | | - [ ] **Step 1: å建MESæ¥å¿æå¡æ¥å£** |
| | | |
| | | ```csharp |
| | | using System.Collections.Generic; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_DTO.Mes; |
| | | |
| | | namespace WIDESEA_IMesService |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡æ¥å£ |
| | | /// </summary> |
| | | public interface IMesLogService : IDependency |
| | | { |
| | | /// <summary> |
| | | /// è®°å½MESæ¥å£è°ç¨æ¥å¿ |
| | | /// </summary> |
| | | /// <param name="log">æ¥å¿DTO</param> |
| | | /// <returns>æ¯å¦è®°å½æå</returns> |
| | | Task<bool> LogAsync(MesApiLogDto log); |
| | | |
| | | /// <summary> |
| | | /// è·åæè¿çMESæ¥å£è°ç¨è®°å½ |
| | | /// </summary> |
| | | /// <param name="apiType">æ¥å£ç±»å</param> |
| | | /// <param name="count">è®°å½æ°é</param> |
| | | /// <returns>æ¥å¿å表</returns> |
| | | Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: å建MESæ¥å¿æå¡å®ç°** |
| | | |
| | | ```csharp |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_DTO.Mes; |
| | | using WIDESEA_IMesService; |
| | | using WIDESEA_Model.Models.Mes; |
| | | |
| | | namespace WIDESEA_MesService |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡å®ç° |
| | | /// </summary> |
| | | public class MesLogService : IMesLogService |
| | | { |
| | | private readonly ISqlSugarClient _db; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | public MesLogService(ISqlSugarClient db) |
| | | { |
| | | _db = db; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è®°å½MESæ¥å£è°ç¨æ¥å¿ |
| | | /// </summary> |
| | | public async Task<bool> LogAsync(MesApiLogDto log) |
| | | { |
| | | try |
| | | { |
| | | var entity = new Dt_MesApiLog |
| | | { |
| | | ApiType = log.ApiType, |
| | | RequestJson = log.RequestJson, |
| | | ResponseJson = log.ResponseJson, |
| | | IsSuccess = log.IsSuccess, |
| | | ErrorMessage = log.ErrorMessage, |
| | | ElapsedMs = log.ElapsedMs, |
| | | CreateDate = DateTime.Now, |
| | | Creator = log.Creator |
| | | }; |
| | | |
| | | var result = await _db.Insertable(entity).ExecuteCommandAsync(); |
| | | return result > 0; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // è®°å½æ¥å¿å¤±è´¥ä¸å½±å主æµç¨ |
| | | Console.WriteLine($"è®°å½MESæ¥å¿å¤±è´¥: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæè¿çMESæ¥å£è°ç¨è®°å½ |
| | | /// </summary> |
| | | public async Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50) |
| | | { |
| | | try |
| | | { |
| | | var entities = await _db.Queryable<Dt_MesApiLog>() |
| | | .Where(x => x.ApiType == apiType) |
| | | .OrderByDescending(x => x.CreateDate) |
| | | .Take(count) |
| | | .ToListAsync(); |
| | | |
| | | return entities.Select(e => new MesApiLogDto |
| | | { |
| | | ApiType = e.ApiType, |
| | | RequestJson = e.RequestJson, |
| | | ResponseJson = e.ResponseJson, |
| | | IsSuccess = e.IsSuccess, |
| | | ErrorMessage = e.ErrorMessage, |
| | | ElapsedMs = e.ElapsedMs, |
| | | Creator = e.Creator |
| | | }).ToList(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"è·åMESæ¥å¿å¤±è´¥: {ex.Message}"); |
| | | return new List<MesApiLogDto>(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_IMesService/IMesLogService.cs |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_MesService/MesLogService.cs |
| | | git commit -m "feat(MES): æ·»å MESæ¥å¿æå¡ |
| | | |
| | | - å®ç° IMesLogService æ¥å£ |
| | | - æ¯æè®°å½åæ¥è¯¢MESæ¥å£è°ç¨æ¥å¿ |
| | | - å¼å¸¸å¤çä¸å½±å主æµç¨ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 4: æ©å±StockInfoControlleræ·»å è¿ç«/åºç«æ¥å£ |
| | | |
| | | **Files:** |
| | | - Modify: `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs` |
| | | |
| | | - [ ] **Step 1: å¨StockInfoController䏿·»å MESæ¥å£æ¹æ³** |
| | | |
| | | å¨ç°æStockInfoControllerç±»ä¸æ·»å 以䏿¹æ³ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// MESæ¥å¿æå¡ |
| | | /// </summary> |
| | | private readonly IMesLogService _mesLogService; |
| | | |
| | | /// <summary> |
| | | /// MESæå¡ï¼å·²å¨é¡¹ç®ä¸å®ä¹ï¼ |
| | | /// </summary> |
| | | private readonly IMesService _mesService; |
| | | |
| | | /// <summary> |
| | | /// ç³»ç»é
ç½®æå¡ |
| | | /// </summary> |
| | | private readonly ISystemConfigService _configService; |
| | | |
| | | // 卿é 彿°ä¸æ³¨å
¥è¿äºæå¡ï¼å¦æå°æªæ³¨å
¥ï¼ |
| | | ``` |
| | | |
| | | æ·»å è¿ç«æ¥å£ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçè¿ç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">è¿ç«è¯·æ±DTO</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("inboundInContainer")] |
| | | [Permission("MES_INBOUND")] |
| | | public async Task<WebResponseContent> InboundInContainer([FromBody] InboundInContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = System.Diagnostics.Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. æ¥è¯¢åºåä¿¡æ¯ |
| | | var stockInfo = await _service.FindAsIQueryable(x => x.Id == dto.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | return response.Error("åºåä¿¡æ¯ä¸åå¨"); |
| | | } |
| | | |
| | | // 3. éªè¯åºåç¶æï¼ä»
"å¾
å
¥åº"ç¶æå
许è¿ç«ï¼ |
| | | if (stockInfo.Status != 0) // å设0=å¾
å
¥åº |
| | | { |
| | | return response.Error($"å½ååºåç¶æä¸å
许è¿ç«æä½"); |
| | | } |
| | | |
| | | // 4. è·åç³»ç»é
ç½® |
| | | var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode"); |
| | | var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode"); |
| | | |
| | | if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode)) |
| | | { |
| | | return response.Error("MESç³»ç»é
ç½®ä¸å®æ´ï¼è¯·è系管çå"); |
| | | } |
| | | |
| | | // 5. æé MESè¯·æ± |
| | | var mesRequest = new InboundInContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 6. è°ç¨MESæ¥å£ |
| | | var mesResult = await _mesService.InboundInContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 7. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "InboundInContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.Success, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | // 8. è¿åç»æ |
| | | if (mesResult.Success) |
| | | { |
| | | return response.OK("æçè¿ç«æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "InboundInContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | return response.Error($"æçè¿ç«å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | æ·»å åºç«æ¥å£ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçåºç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">åºç«è¯·æ±DTO</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("outboundInContainer")] |
| | | [Permission("MES_OUTBOUND")] |
| | | public async Task<WebResponseContent> OutboundInContainer([FromBody] OutboundInContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = System.Diagnostics.Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. æ¥è¯¢åºåä¿¡æ¯ |
| | | var stockInfo = await _service.FindAsIQueryable(x => x.Id == dto.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | { |
| | | return response.Error("åºåä¿¡æ¯ä¸åå¨"); |
| | | } |
| | | |
| | | // 3. éªè¯åºåç¶æï¼"å¨åº"æ"åºåºä¸"ç¶æå
许åºç«ï¼ |
| | | if (stockInfo.Status != 1 && stockInfo.Status != 2) // å设1=å¨åº, 2=åºåºä¸ |
| | | { |
| | | return response.Error($"å½ååºåç¶æä¸å
许åºç«æä½"); |
| | | } |
| | | |
| | | // 4. è·åç³»ç»é
ç½® |
| | | var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode"); |
| | | var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode"); |
| | | |
| | | if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode)) |
| | | { |
| | | return response.Error("MESç³»ç»é
ç½®ä¸å®æ´ï¼è¯·è系管çå"); |
| | | } |
| | | |
| | | // 5. æé MESè¯·æ± |
| | | var mesRequest = new OutboundInContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | ParamList = dto.ParamList?.Select(p => new ParamItem |
| | | { |
| | | ParamCode = p.ParamCode, |
| | | ParamValue = p.ParamValue, |
| | | CollectionTime = DateTime.TryParse(p.CollectionTime, out var ct) ? ct : DateTime.Now |
| | | }).ToList() |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 6. è°ç¨MESæ¥å£ |
| | | var mesResult = await _mesService.OutboundInContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 7. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "OutboundInContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.Success, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | // 8. è¿åç»æ |
| | | if (mesResult.Success) |
| | | { |
| | | return response.OK("æçåºç«æå"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | // è®°å½é误æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "OutboundInContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | return response.Error($"æçåºç«å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: æ·»å å¿
è¦çusingè¯å¥** |
| | | |
| | | 卿件顶鍿·»å ï¼ |
| | | |
| | | ```csharp |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_DTO.Mes; |
| | | using WIDESEA_IMesService; |
| | | ``` |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs |
| | | git commit -m "feat(MES): åºåä¿¡æ¯é¡µé¢æ·»å è¿ç«/åºç«æ¥å£ |
| | | |
| | | - POST /api/StockInfo/inboundInContainer æçè¿ç« |
| | | - POST /api/StockInfo/outboundInContainer æçåºç« |
| | | - æ·»å åºåç¶ææ ¡éª |
| | | - è®°å½å®æ´è°ç¨æ¥å¿ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 5: æ©å±StockInfoDetailControlleræ·»å ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | |
| | | **Files:** |
| | | - Modify: `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs` |
| | | |
| | | - [ ] **Step 1: å¨StockInfoDetailController䏿·»å MESæ¥å£æ¹æ³** |
| | | |
| | | å¨ç°æStockInfoDetailControllerç±»ä¸æ·»å ä¾èµæ³¨å
¥åæ¥å£æ¹æ³ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// MESæ¥å¿æå¡ |
| | | /// </summary> |
| | | private readonly IMesLogService _mesLogService; |
| | | |
| | | /// <summary> |
| | | /// MESæå¡ |
| | | /// </summary> |
| | | private readonly IMesService _mesService; |
| | | |
| | | /// <summary> |
| | | /// ç³»ç»é
ç½®æå¡ |
| | | /// </summary> |
| | | private readonly ISystemConfigService _configService; |
| | | ``` |
| | | |
| | | æ·»å ç»å®æ¥å£ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æççµè¯ç»å® - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">ç»å®è¯·æ±DTO</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("bindContainer")] |
| | | [Permission("MES_BIND")] |
| | | public async Task<WebResponseContent> BindContainer([FromBody] BindContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = System.Diagnostics.Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.SfcList == null || !dto.SfcList.Any()) |
| | | { |
| | | return response.Error("çµè¯ç å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. è·åç³»ç»é
ç½® |
| | | var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode"); |
| | | var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode"); |
| | | |
| | | if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode)) |
| | | { |
| | | return response.Error("MESç³»ç»é
ç½®ä¸å®æ´ï¼è¯·è系管çå"); |
| | | } |
| | | |
| | | // 3. æé MESè¯·æ± |
| | | var mesRequest = new BindContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem |
| | | { |
| | | Sfc = sfc, |
| | | Location = dto.Location ?? "" |
| | | }).ToList(), |
| | | OperationType = dto.OperationType |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ |
| | | var mesResult = await _mesService.BindContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "BindContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.Success, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.Success) |
| | | { |
| | | return response.OK($"æåç»å® {dto.SfcList.Count} 个çµè¯"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "BindContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | return response.Error($"çµè¯ç»å®å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | æ·»å è§£ç»æ¥å£ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æççµè¯è§£ç» - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">è§£ç»è¯·æ±DTO</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("unbindContainer")] |
| | | [Permission("MES_UNBIND")] |
| | | public async Task<WebResponseContent> UnbindContainer([FromBody] UnbindContainerRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = System.Diagnostics.Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.SfcList == null || !dto.SfcList.Any()) |
| | | { |
| | | return response.Error("çµè¯ç å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. è·åç³»ç»é
ç½® |
| | | var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode"); |
| | | var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode"); |
| | | |
| | | if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode)) |
| | | { |
| | | return response.Error("MESç³»ç»é
ç½®ä¸å®æ´ï¼è¯·è系管çå"); |
| | | } |
| | | |
| | | // 3. æé MESè¯·æ± |
| | | var mesRequest = new UnBindContainerRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainCode = dto.PalletCode, |
| | | SfcList = dto.SfcList |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ |
| | | var mesResult = await _mesService.UnBindContainer(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "UnbindContainer", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.Success, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.Success) |
| | | { |
| | | return response.OK($"æåè§£ç» {dto.SfcList.Count} 个çµè¯"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "UnbindContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | return response.Error($"çµè¯è§£ç»å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | æ·»å NG䏿¥æ¥å£ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥ - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | /// <param name="dto">NG䏿¥è¯·æ±DTO</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("containerNgReport")] |
| | | [Permission("MES_NG_REPORT")] |
| | | public async Task<WebResponseContent> ContainerNgReport([FromBody] ContainerNgReportRequestDto dto) |
| | | { |
| | | var response = new WebResponseContent(); |
| | | var stopwatch = System.Diagnostics.Stopwatch.StartNew(); |
| | | |
| | | try |
| | | { |
| | | // 1. åæ°éªè¯ |
| | | if (string.IsNullOrWhiteSpace(dto.PalletCode)) |
| | | { |
| | | return response.Error("æçç¼å·ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | if (dto.NgSfcList == null || !dto.NgSfcList.Any()) |
| | | { |
| | | return response.Error("NGçµè¯å表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. è·åç³»ç»é
ç½® |
| | | var equipmentCode = await _configService.GetConfigValueAsync("MES_EquipmentCode"); |
| | | var resourceCode = await _configService.GetConfigValueAsync("MES_ResourceCode"); |
| | | |
| | | if (string.IsNullOrWhiteSpace(equipmentCode) || string.IsNullOrWhiteSpace(resourceCode)) |
| | | { |
| | | return response.Error("MESç³»ç»é
ç½®ä¸å®æ´ï¼è¯·è系管çå"); |
| | | } |
| | | |
| | | // 3. æé MESè¯·æ± |
| | | var mesRequest = new ContainerNgReportRequest |
| | | { |
| | | EquipmentCode = equipmentCode, |
| | | ResourceCode = resourceCode, |
| | | LocalTime = DateTime.Now, |
| | | ContainerCode = dto.PalletCode, |
| | | NgSfcList = dto.NgSfcList.Select(ng => new NgSfcItem |
| | | { |
| | | Sfc = ng.Sfc, |
| | | NgCode = ng.NgCode, |
| | | NgEquipmentCode = ng.NgEquipmentCode, |
| | | NgResourceCode = ng.NgResourceCode |
| | | }).ToList() |
| | | }; |
| | | |
| | | string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); |
| | | |
| | | // 4. è°ç¨MESæ¥å£ |
| | | var mesResult = await _mesService.ContainerNgReport(mesRequest); |
| | | stopwatch.Stop(); |
| | | |
| | | // 5. è®°å½æ¥å¿ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "ContainerNgReport", |
| | | RequestJson = requestJson, |
| | | ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), |
| | | IsSuccess = mesResult.Success, |
| | | ErrorMessage = mesResult.ErrorMessage, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | // 6. è¿åç»æ |
| | | if (mesResult.Success) |
| | | { |
| | | return response.OK($"æå䏿¥ {dto.NgSfcList.Count} 个NGçµè¯"); |
| | | } |
| | | else |
| | | { |
| | | return response.Error($"MESæ¥å£è°ç¨å¤±è´¥: {mesResult.ErrorMessage}"); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | stopwatch.Stop(); |
| | | |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "ContainerNgReport", |
| | | IsSuccess = false, |
| | | ErrorMessage = ex.Message, |
| | | ElapsedMs = (int)stopwatch.ElapsedMilliseconds, |
| | | Creator = UserContext.Current.UserName |
| | | }); |
| | | |
| | | return response.Error($"NG䏿¥å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: æ·»å å¿
è¦çusingè¯å¥** |
| | | |
| | | 卿件顶鍿·»å ï¼ |
| | | |
| | | ```csharp |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_DTO.Mes; |
| | | using WIDESEA_IMesService; |
| | | ``` |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs |
| | | git commit -m "feat(MES): åºåæç»é¡µé¢æ·»å ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | |
| | | - POST /api/StockInfoDetail/bindContainer æççµè¯ç»å® |
| | | - POST /api/StockInfoDetail/unbindContainer æççµè¯è§£ç» |
| | | - POST /api/StockInfoDetail/containerNgReport NGçµè¯ä¸æ¥ |
| | | - è®°å½å®æ´è°ç¨æ¥å¿ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 6: å建å端MES APIè°ç¨æ¨¡å |
| | | |
| | | **Files:** |
| | | - Create: `WMS/WIDESEA_WMSClient/src/api/mes.js` |
| | | |
| | | - [ ] **Step 1: å建MES API模å** |
| | | |
| | | ```javascript |
| | | /** |
| | | * MESæ¥å£API模å |
| | | */ |
| | | import axios from 'axios'; |
| | | |
| | | const baseURL = '/api'; |
| | | |
| | | // åºåä¿¡æ¯ç¸å
³MESæ¥å£ |
| | | export const stockInfoMesApi = { |
| | | /** |
| | | * æçè¿ç« |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, stockId } |
| | | * @returns {Promise} |
| | | */ |
| | | inboundInContainer(data) { |
| | | return axios.post(`${baseURL}/StockInfo/inboundInContainer`, data); |
| | | }, |
| | | |
| | | /** |
| | | * æçåºç« |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, stockId, paramList } |
| | | * @returns {Promise} |
| | | */ |
| | | outboundInContainer(data) { |
| | | return axios.post(`${baseURL}/StockInfo/outboundInContainer`, data); |
| | | } |
| | | }; |
| | | |
| | | // åºåæç»ç¸å
³MESæ¥å£ |
| | | export const stockDetailMesApi = { |
| | | /** |
| | | * æççµè¯ç»å® |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, sfcList, location, operationType } |
| | | * @returns {Promise} |
| | | */ |
| | | bindContainer(data) { |
| | | return axios.post(`${baseURL}/StockInfoDetail/bindContainer`, data); |
| | | }, |
| | | |
| | | /** |
| | | * æççµè¯è§£ç» |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, sfcList } |
| | | * @returns {Promise} |
| | | */ |
| | | unbindContainer(data) { |
| | | return axios.post(`${baseURL}/StockInfoDetail/unbindContainer`, data); |
| | | }, |
| | | |
| | | /** |
| | | * æçNGçµè¯ä¸æ¥ |
| | | * @param {Object} data - è¯·æ±æ°æ® { palletCode, ngSfcList } |
| | | * @returns {Promise} |
| | | */ |
| | | containerNgReport(data) { |
| | | return axios.post(`${baseURL}/StockInfoDetail/containerNgReport`, data); |
| | | } |
| | | }; |
| | | |
| | | export default { |
| | | stockInfo: stockInfoMesApi, |
| | | stockDetail: stockDetailMesApi |
| | | }; |
| | | ``` |
| | | |
| | | - [ ] **Step 2: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSClient/src/api/mes.js |
| | | git commit -m "feat(MES): æ·»å å端MES APIè°ç¨æ¨¡å |
| | | |
| | | - å°è£
åºåä¿¡æ¯è¿ç«/åºç«æ¥å£ |
| | | - å°è£
åºåæç»ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 7: å建MESç¡®è®¤å¯¹è¯æ¡ç»ä»¶ |
| | | |
| | | **Files:** |
| | | - Create: `WMS/WIDESEA_WMSClient/src/components/MesConfirmDialog.vue` |
| | | |
| | | - [ ] **Step 1: åå»ºç¡®è®¤å¯¹è¯æ¡ç»ä»¶** |
| | | |
| | | ```vue |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | :title="dialogTitle" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <div class="mes-confirm-content"> |
| | | <p class="operation-text">{{ operationText }}</p> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row" v-for="(item, index) in displayInfo" :key="index"> |
| | | <span class="info-label">{{ item.label }}:</span> |
| | | <span class="info-value">{{ item.value }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-if="errorMessage" class="error-message"> |
| | | <el-icon><Warning /></el-icon> |
| | | <span>{{ errorMessage }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="handleClose">åæ¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | :loading="loading" |
| | | @click="handleConfirm" |
| | | > |
| | | 确认æ§è¡ |
| | | </el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref, computed } from 'vue'; |
| | | import { Warning } from '@element-plus/icons-vue'; |
| | | import { ElMessage } from 'element-plus'; |
| | | |
| | | export default { |
| | | name: 'MesConfirmDialog', |
| | | |
| | | components: { |
| | | Warning |
| | | }, |
| | | |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | operationType: { |
| | | type: String, |
| | | required: true |
| | | }, |
| | | palletCode: { |
| | | type: String, |
| | | required: true |
| | | }, |
| | | stockInfo: { |
| | | type: Object, |
| | | default: null |
| | | }, |
| | | detailInfo: { |
| | | type: Object, |
| | | default: null |
| | | } |
| | | }, |
| | | |
| | | emits: ['update:modelValue', 'confirm'], |
| | | |
| | | setup(props, { emit }) { |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (val) => emit('update:modelValue', val) |
| | | }); |
| | | |
| | | const loading = ref(false); |
| | | const errorMessage = ref(''); |
| | | |
| | | const operationConfig = { |
| | | inbound: { title: 'æçè¿ç«', text: 'æ¨å³å°æ§è¡æçè¿ç«æä½' }, |
| | | outbound: { title: 'æçåºç«', text: 'æ¨å³å°æ§è¡æçåºç«æä½' }, |
| | | bind: { title: 'çµè¯ç»å®', text: 'æ¨å³å°æ§è¡çµè¯ç»å®æä½' }, |
| | | unbind: { title: 'çµè¯è§£ç»', text: 'æ¨å³å°æ§è¡çµè¯è§£ç»æä½' }, |
| | | ngReport: { title: 'NG䏿¥', text: 'æ¨å³å°æ§è¡NGçµè¯ä¸æ¥æä½' } |
| | | }; |
| | | |
| | | const dialogTitle = computed(() => { |
| | | return operationConfig[props.operationType]?.title || '确认æä½'; |
| | | }); |
| | | |
| | | const operationText = computed(() => { |
| | | return operationConfig[props.operationType]?.text || ''; |
| | | }); |
| | | |
| | | const displayInfo = computed(() => { |
| | | const info = [ |
| | | { label: 'æçç ', value: props.palletCode } |
| | | ]; |
| | | |
| | | if (props.detailInfo) { |
| | | info.push({ label: 'çµè¯æ°é', value: props.detailInfo.sfcCount || '-' }); |
| | | } |
| | | |
| | | return info; |
| | | }); |
| | | |
| | | const handleClose = () => { |
| | | visible.value = false; |
| | | errorMessage.value = ''; |
| | | }; |
| | | |
| | | const handleConfirm = async () => { |
| | | loading.value = true; |
| | | errorMessage.value = ''; |
| | | |
| | | try { |
| | | emit('confirm', { |
| | | operationType: props.operationType, |
| | | palletCode: props.palletCode, |
| | | stockInfo: props.stockInfo, |
| | | detailInfo: props.detailInfo, |
| | | onSuccess: () => { |
| | | visible.value = false; |
| | | loading.value = false; |
| | | }, |
| | | onError: (error) => { |
| | | errorMessage.value = error; |
| | | loading.value = false; |
| | | } |
| | | }); |
| | | } catch (error) { |
| | | errorMessage.value = error.message || 'æä½å¤±è´¥'; |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | return { |
| | | visible, |
| | | loading, |
| | | errorMessage, |
| | | dialogTitle, |
| | | operationText, |
| | | displayInfo, |
| | | handleClose, |
| | | handleConfirm |
| | | }; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .mes-confirm-content { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .operation-text { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | margin-bottom: 20px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .info-section { |
| | | background: #f8fafc; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | margin-bottom: 12px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .info-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .info-label { |
| | | color: #909399; |
| | | width: 80px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .error-message { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | padding: 12px; |
| | | background: #fef0f0; |
| | | border: 1px solid #fde2e2; |
| | | border-radius: 6px; |
| | | color: #f56c6c; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .error-message .el-icon { |
| | | font-size: 18px; |
| | | } |
| | | </style> |
| | | ``` |
| | | |
| | | - [ ] **Step 2: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSClient/src/components/MesConfirmDialog.vue |
| | | git commit -m "feat(MES): æ·»å MESæä½ç¡®è®¤å¯¹è¯æ¡ç»ä»¶ |
| | | |
| | | - æ¯æå¤ç§æä½ç±»åï¼è¿ç«ãåºç«ãç»å®ãè§£ç»ãNG䏿¥ï¼ |
| | | - æ¾ç¤ºå
³é®ä¿¡æ¯ï¼æçç ãçµè¯æ°éçï¼ |
| | | - éè¯¯ç¶æå±ç¤º |
| | | - 确认/åæ¶æä½ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 8: ä¿®æ¹stockInfo.vueæ·»å æä½å |
| | | |
| | | **Files:** |
| | | - Modify: `WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue` |
| | | |
| | | - [ ] **Step 1: å¨script䏿·»å ç»ä»¶å¼å
¥åæ¹æ³** |
| | | |
| | | å¨ç°æçscript setup䏿·»å ï¼ |
| | | |
| | | ```javascript |
| | | import MesConfirmDialog from '@/components/MesConfirmDialog.vue'; |
| | | import { stockInfoMesApi } from '@/api/mes'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { ref } from 'vue'; |
| | | |
| | | // MESå¯¹è¯æ¡ç¶æ |
| | | const mesDialogVisible = ref(false); |
| | | const currentOperationType = ref(''); |
| | | const currentStockRow = ref(null); |
| | | const mesLoading = ref(false); |
| | | |
| | | // æå¼MESç¡®è®¤å¯¹è¯æ¡ |
| | | const openMesDialog = (operationType, row) => { |
| | | currentOperationType.value = operationType; |
| | | currentStockRow.value = row; |
| | | mesDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å¤çMES确认 |
| | | const handleMesConfirm = async ({ onSuccess, onError }) => { |
| | | const row = currentStockRow.value; |
| | | const operationType = currentOperationType.value; |
| | | |
| | | try { |
| | | let result; |
| | | |
| | | switch (operationType) { |
| | | case 'inbound': |
| | | result = await stockInfoMesApi.inboundInContainer({ |
| | | palletCode: row.palletCode, |
| | | stockId: row.id |
| | | }); |
| | | break; |
| | | case 'outbound': |
| | | result = await stockInfoMesApi.outboundInContainer({ |
| | | palletCode: row.palletCode, |
| | | stockId: row.id |
| | | }); |
| | | break; |
| | | } |
| | | |
| | | if (result.data.status) { |
| | | ElMessage.success(result.data.message || 'æä½æå'); |
| | | onSuccess(); |
| | | // å·æ°å表 |
| | | proxy.$refs.grid.load(); |
| | | } else { |
| | | onError(result.data.message || 'æä½å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | onError(error.response?.data?.message || error.message || 'ç½ç»é误ï¼è¯·ç¨åéè¯'); |
| | | } |
| | | }; |
| | | |
| | | // æ£æ¥æé®æ¯å¦åºè¯¥æ¾ç¤º |
| | | const shouldShowButton = (buttonType, row) => { |
| | | const status = row.status; // 0=å¾
å
¥åº, 1=å¨åº, 2=åºåºä¸, 3=éå® |
| | | |
| | | switch (buttonType) { |
| | | case 'inbound': |
| | | return status === 0; // ä»
å¾
å
¥åºæ¾ç¤ºè¿ç« |
| | | case 'outbound': |
| | | return status === 1 || status === 2; // å¨åºæåºåºä¸æ¾ç¤ºåºç« |
| | | default: |
| | | return false; |
| | | } |
| | | }; |
| | | ``` |
| | | |
| | | - [ ] **Step 2: å¨columns䏿·»å æä½å** |
| | | |
| | | å¨ç°æçcolumns refå®ä¹ä¸æ·»å æä½åï¼å¨æåæ·»å ï¼ï¼ |
| | | |
| | | ```javascript |
| | | const columns = ref([ |
| | | // ... ç°æåå®ä¹ ... |
| | | { |
| | | field: "actions", |
| | | title: "æä½", |
| | | width: 200, |
| | | fixed: "right", |
| | | align: "center", |
| | | formatter: (row) => { |
| | | const buttons = []; |
| | | |
| | | if (shouldShowButton('inbound', row)) { |
| | | buttons.push( |
| | | `<el-button type="primary" size="small" onclick="window.handleInbound(${row.id})">è¿ç«</el-button>` |
| | | ); |
| | | } |
| | | |
| | | if (shouldShowButton('outbound', row)) { |
| | | buttons.push( |
| | | `<el-button type="success" size="small" onclick="window.handleOutbound(${row.id})">åºç«</el-button>` |
| | | ); |
| | | } |
| | | |
| | | return buttons.join(' '); |
| | | } |
| | | } |
| | | ]); |
| | | ``` |
| | | |
| | | - [ ] **Step 3: 卿¨¡æ¿ä¸æ·»å å¯¹è¯æ¡ç»ä»¶** |
| | | |
| | | å¨templateä¸çview-gridæ ç¾åæ·»å ï¼ |
| | | |
| | | ```vue |
| | | <template> |
| | | <view-grid ... > |
| | | </view-grid> |
| | | |
| | | <!-- MESç¡®è®¤å¯¹è¯æ¡ --> |
| | | <MesConfirmDialog |
| | | v-model="mesDialogVisible" |
| | | :operation-type="currentOperationType" |
| | | :pallet-code="currentStockRow?.palletCode" |
| | | :stock-info="currentStockRow" |
| | | @confirm="handleMesConfirm" |
| | | /> |
| | | </template> |
| | | ``` |
| | | |
| | | - [ ] **Step 4: æ·»å å
¨å±æ¹æ³ç¨äºHTMLå符串ä¸çonclick** |
| | | |
| | | å¨setupçæåæ·»å ï¼ |
| | | |
| | | ```javascript |
| | | // æè½½å°windowä¾HTMLå符串ä¸çonclickä½¿ç¨ |
| | | window.handleInbound = (id) => { |
| | | const row = proxy.$refs.grid.tableData.find(item => item.id === id); |
| | | if (row) openMesDialog('inbound', row); |
| | | }; |
| | | |
| | | window.handleOutbound = (id) => { |
| | | const row = proxy.$refs.grid.tableData.find(item => item.id === id); |
| | | if (row) openMesDialog('outbound', row); |
| | | }; |
| | | ``` |
| | | |
| | | - [ ] **Step 5: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue |
| | | git commit -m "feat(MES): åºåä¿¡æ¯é¡µé¢æ·»å è¿ç«/åºç«æä½å |
| | | |
| | | - æ·»å æä½åï¼æ ¹æ®åºåç¶æå¨ææ¾ç¤ºæé® |
| | | - å¾
å
¥åºç¶ææ¾ç¤ºè¿ç«æé® |
| | | - å¨åº/åºåºä¸ç¶ææ¾ç¤ºåºç«æé® |
| | | - éæMESç¡®è®¤å¯¹è¯æ¡ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 9: ä¿®æ¹stockInfoDetail.vueæ·»å æä½å |
| | | |
| | | **Files:** |
| | | - Modify: `WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue` |
| | | |
| | | - [ ] **Step 1: å¨script䏿·»å ç»ä»¶å¼å
¥åæ¹æ³** |
| | | |
| | | å¨ç°æçscript setup䏿·»å ï¼ |
| | | |
| | | ```javascript |
| | | import MesConfirmDialog from '@/components/MesConfirmDialog.vue'; |
| | | import { stockDetailMesApi } from '@/api/mes'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { ref } from 'vue'; |
| | | |
| | | // MESå¯¹è¯æ¡ç¶æ |
| | | const mesDialogVisible = ref(false); |
| | | const currentOperationType = ref(''); |
| | | const currentDetailRow = ref(null); |
| | | const mesLoading = ref(false); |
| | | |
| | | // æå¼MESç¡®è®¤å¯¹è¯æ¡ |
| | | const openMesDialog = (operationType, row) => { |
| | | currentOperationType.value = operationType; |
| | | currentDetailRow.value = row; |
| | | mesDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å¤çMES确认 |
| | | const handleMesConfirm = async ({ onSuccess, onError }) => { |
| | | const row = currentDetailRow.value; |
| | | const operationType = currentOperationType.value; |
| | | |
| | | try { |
| | | let result; |
| | | |
| | | switch (operationType) { |
| | | case 'bind': |
| | | result = await stockDetailMesApi.bindContainer({ |
| | | palletCode: row.palletCode || 'P001', // éè¦ä»åºåä¿¡æ¯è·å |
| | | sfcList: [row.serialNumber], |
| | | location: row.location || '', |
| | | operationType: 1 |
| | | }); |
| | | break; |
| | | case 'unbind': |
| | | result = await stockDetailMesApi.unbindContainer({ |
| | | palletCode: row.palletCode || 'P001', |
| | | sfcList: [row.serialNumber] |
| | | }); |
| | | break; |
| | | case 'ngReport': |
| | | result = await stockDetailMesApi.containerNgReport({ |
| | | palletCode: row.palletCode || 'P001', |
| | | ngSfcList: [{ |
| | | sfc: row.serialNumber, |
| | | ngCode: 'NG001', |
| | | ngEquipmentCode: 'WCS_001', |
| | | ngResourceCode: 'RESOURCE_001' |
| | | }] |
| | | }); |
| | | break; |
| | | } |
| | | |
| | | if (result.data.status) { |
| | | ElMessage.success(result.data.message || 'æä½æå'); |
| | | onSuccess(); |
| | | proxy.$refs.grid.load(); |
| | | } else { |
| | | onError(result.data.message || 'æä½å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | onError(error.response?.data?.message || error.message || 'ç½ç»é误ï¼è¯·ç¨åéè¯'); |
| | | } |
| | | }; |
| | | |
| | | // æ£æ¥æé®æ¯å¦åºè¯¥æ¾ç¤º |
| | | const shouldShowButton = (row) => { |
| | | const status = row.status; // 1=æ£å¸¸, 2=å¼å¸¸, 99=å·²éå® |
| | | return status !== 99; // é"å·²éå®"ç¶ææ¾ç¤ºæææé® |
| | | }; |
| | | ``` |
| | | |
| | | - [ ] **Step 2: å¨columns䏿·»å æä½å** |
| | | |
| | | å¨ç°æçcolumns refå®ä¹ä¸æ·»å æä½åï¼å¨æåæ·»å ï¼ï¼ |
| | | |
| | | ```javascript |
| | | const columns = ref([ |
| | | // ... ç°æåå®ä¹ ... |
| | | { |
| | | field: "actions", |
| | | title: "æä½", |
| | | width: 280, |
| | | fixed: "right", |
| | | align: "center", |
| | | formatter: (row) => { |
| | | if (!shouldShowButton(row)) { |
| | | return '<span class="text-muted">ææ å¯æ§è¡æä½</span>'; |
| | | } |
| | | |
| | | return ` |
| | | <el-button type="primary" size="small" onclick="window.handleBind(${row.id})">ç»å®</el-button> |
| | | <el-button type="warning" size="small" onclick="window.handleUnbind(${row.id})">è§£ç»</el-button> |
| | | <el-button type="danger" size="small" onclick="window.handleNgReport(${row.id})">NG䏿¥</el-button> |
| | | `; |
| | | } |
| | | } |
| | | ]); |
| | | ``` |
| | | |
| | | - [ ] **Step 3: 卿¨¡æ¿ä¸æ·»å å¯¹è¯æ¡ç»ä»¶** |
| | | |
| | | å¨templateä¸çview-gridæ ç¾åæ·»å ï¼ |
| | | |
| | | ```vue |
| | | <template> |
| | | <view-grid ... > |
| | | </view-grid> |
| | | |
| | | <!-- MESç¡®è®¤å¯¹è¯æ¡ --> |
| | | <MesConfirmDialog |
| | | v-model="mesDialogVisible" |
| | | :operation-type="currentOperationType" |
| | | :pallet-code="currentDetailRow?.palletCode" |
| | | :detail-info="{ sfcCount: 1 }" |
| | | @confirm="handleMesConfirm" |
| | | /> |
| | | </template> |
| | | ``` |
| | | |
| | | - [ ] **Step 4: æ·»å å
¨å±æ¹æ³** |
| | | |
| | | å¨setupçæåæ·»å ï¼ |
| | | |
| | | ```javascript |
| | | window.handleBind = (id) => { |
| | | const row = proxy.$refs.grid.tableData.find(item => item.id === id); |
| | | if (row) openMesDialog('bind', row); |
| | | }; |
| | | |
| | | window.handleUnbind = (id) => { |
| | | const row = proxy.$refs.grid.tableData.find(item => item.id === id); |
| | | if (row) openMesDialog('unbind', row); |
| | | }; |
| | | |
| | | window.handleNgReport = (id) => { |
| | | const row = proxy.$refs.grid.tableData.find(item => item.id === id); |
| | | if (row) openMesDialog('ngReport', row); |
| | | }; |
| | | ``` |
| | | |
| | | - [ ] **Step 5: æäº¤** |
| | | |
| | | ```bash |
| | | git add WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue |
| | | git commit -m "feat(MES): åºåæç»é¡µé¢æ·»å ç»å®/è§£ç»/NG䏿¥æä½å |
| | | |
| | | - æ·»å æä½åï¼æ ¹æ®çµè¯ç¶æå¨ææ¾ç¤ºæé® |
| | | - ééå®ç¶ææ¾ç¤ºç»å®ãè§£ç»ãNG䏿¥æé® |
| | | - éæMESç¡®è®¤å¯¹è¯æ¡ |
| | | |
| | | Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## æµè¯æ£æ¥æ¸
å |
| | | |
| | | 宿以䏿æä»»å¡åï¼è¿è¡ä»¥ä¸æµè¯ï¼ |
| | | |
| | | ### å端æµè¯ |
| | | |
| | | - [ ] éªè¯æ°æ®åºè¡¨ Dt_MesApiLog å·²å建 |
| | | - [ ] éªè¯ç³»ç»é
置已æå
¥ |
| | | - [ ] æµè¯è¿ç«æ¥å£ï¼PostmanæSwaggerï¼ |
| | | - [ ] æµè¯åºç«æ¥å£ |
| | | - [ ] æµè¯ç»å®æ¥å£ |
| | | - [ ] æµè¯è§£ç»æ¥å£ |
| | | - [ ] æµè¯NG䏿¥æ¥å£ |
| | | - [ ] éªè¯æ¥å¿è®°å½æ£ç¡® |
| | | |
| | | ### å端æµè¯ |
| | | |
| | | - [ ] åºåä¿¡æ¯é¡µé¢æä½åæ£å¸¸æ¾ç¤º |
| | | - [ ] æé®æ ¹æ®ç¶ææ£ç¡®æ¾ç¤º/éè |
| | | - [ ] ç¹å»æé®å¼¹åºç¡®è®¤å¯¹è¯æ¡ |
| | | - [ ] 确认åæåè°ç¨æ¥å£ |
| | | - [ ] æååå·æ°å表 |
| | | - [ ] å¤±è´¥åæ¾ç¤ºé误æç¤º |
| | | - [ ] åºåæç»é¡µé¢æä½åæ£å¸¸æ¾ç¤º |
| | | - [ ] æææé®åè½æ£å¸¸ |
| | | |
| | | ### éææµè¯ |
| | | |
| | | - [ ] 宿´æµç¨æµè¯ï¼ç¹å»âç¡®è®¤âæ§è¡âç»æï¼ |
| | | - [ ] ç½ç»å¼å¸¸å¤ç |
| | | - [ ] MESæå¡å¼å¸¸å¤ç |
| | | - [ ] æéæ§å¶æµè¯ |
| | | |
| | | --- |
| | | |
| | | ## 夿³¨ |
| | | |
| | | 1. **ç¶æå¼æ å°**ï¼ä»£ç ä¸ä½¿ç¨çç¶æå¼ï¼0=å¾
å
¥åº, 1=å¨åºçï¼éè¦æ ¹æ®å®é
æä¸¾å¼è°æ´ |
| | | 2. **æçç è·å**ï¼åºåæç»é¡µé¢ä¸éè¦éè¿stockIdå
³èè·åæçç |
| | | 3. **æéé
ç½®**ï¼éè¦å¨ç³»ç»ä¸æ·»å MESç¸å
³æé项 |
| | | 4. **MESæ¥å£å°å**ï¼å¨ç³»ç»é
ç½®ä¸è®¾ç½®æ£ç¡®çMESæ¥å£å°å |
| | | 5. **é误å¤ç**ï¼æ ¹æ®å®é
MESè¿åçé误ç è°æ´æç¤ºä¿¡æ¯ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # WMSåºå页é¢MESæ¥å£éæè®¾è®¡ææ¡£ |
| | | |
| | | **æ¥æ**: 2026-04-12 |
| | | **项ç®**: WIDESEA WMS |
| | | **ä½è
**: Claude Code |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãéæ±æ¦è¿° |
| | | |
| | | 为WMSåºåä¿¡æ¯é¡µé¢ååºåæç»é¡µé¢æ·»å æä½åï¼è°ç¨MESç³»ç»çåºç«/å
¥ç«/ç»å®/è§£ç»/NG䏿¥æ¥å£ï¼å®ç°WMSä¸MESçæ°æ®åæ¥ã |
| | | |
| | | ### åè½èå´ |
| | | |
| | | **åºåä¿¡æ¯é¡µé¢ï¼stockInfo.vueï¼- æç级å«ï¼** |
| | | - æçè¿ç«ï¼è°ç¨MES InboundInContaineræ¥å£ï¼ |
| | | - æçåºç«ï¼è°ç¨MES OutboundInContaineræ¥å£ï¼ |
| | | |
| | | **åºåæç»é¡µé¢ï¼stockInfoDetail.vueï¼- çµè¯çº§å«ï¼** |
| | | - æççµè¯ç»å®ï¼è°ç¨MES BindContaineræ¥å£ï¼ |
| | | - æççµè¯è§£ç»ï¼è°ç¨MES UnBindContaineræ¥å£ï¼ |
| | | - æçNGçµè¯ä¸æ¥ï¼è°ç¨MES ContainerNgReportæ¥å£ï¼ |
| | | |
| | | --- |
| | | |
| | | ## äºãæ¶æè®¾è®¡ |
| | | |
| | | ### 2.1 ç³»ç»æ¶æå¾ |
| | | |
| | | ``` |
| | | âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ |
| | | â å端 (Vue 3) â |
| | | â ââââââââââââââââââââ ââââââââââââââââââââ ââââââââââââââââââ â |
| | | â â stockInfo.vue â âstockInfoDetail â â MesDialog.vue â â |
| | | â â (åºåä¿¡æ¯) â â .vue(åºåæç») â â (ç¡®è®¤å¯¹è¯æ¡) â â |
| | | â â + æä½å â â + æä½å â â â â |
| | | â ââââââââââ¬ââââââââââ ââââââââââ¬ââââââââââ ââââââââââ¬ââââââââ â |
| | | â â â â â |
| | | â âââââââââââââââââââââââ´âââââââââââââââââââââââ â |
| | | â â â |
| | | ââââââââââââââââââââââââââââââââ¼ââââââââââââââââââââââââââââââââââââ |
| | | â HTTP API |
| | | ââââââââââââââââââââââââââââââââ¼ââââââââââââââââââââââââââââââââââââ |
| | | â â¼ å端 (.NET) â |
| | | â ââââââââââââââââââââ ââââââââââââââââââââ ââââââââââââââââââ â |
| | | â â StockController ââ â MesController â â MesLogService â â |
| | | â â â â â â â â |
| | | â ââââââââââââââââââââ ââââââââââ¬ââââââââââ ââââââââââââââââââ â |
| | | â â â |
| | | â â¼ â |
| | | â ââââââââââââââââââââ ââââââââââââââââââââ ââââââââââââââââââ â |
| | | â â IMesService ââ â MesService â âDt_MesApiLog â â |
| | | â â (æ¥å£å®ä¹) â â (HTTPè°ç¨) â â (æ¥å¿è¡¨) â â |
| | | â ââââââââââââââââââââ ââââââââââââââââââââ ââââââââââââââââââ â |
| | | âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ |
| | | â |
| | | â¼ |
| | | ââââââââââââââââ |
| | | â MESç³»ç» â |
| | | â (å¤é¨æ¥å£) â |
| | | ââââââââââââââââ |
| | | ``` |
| | | |
| | | ### 2.2 ææ¯æ |
| | | |
| | | - **å端**: Vue 3, Element Plus, Pinia |
| | | - **å端**: .NET 8, ASP.NET Core, SqlSugar ORM |
| | | - **æ°æ®åº**: SQL Server |
| | | - **HTTP客æ·ç«¯**: HttpClient (å端è°ç¨MES) |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãå端设计 |
| | | |
| | | ### 3.1 åºåä¿¡æ¯é¡µé¢ (stockInfo.vue) |
| | | |
| | | #### æä½å设计 |
| | | |
| | | **è¡¨æ ¼åé
ç½®ï¼** |
| | | ```javascript |
| | | { |
| | | field: "actions", |
| | | title: "æä½", |
| | | width: 200, |
| | | fixed: "right", |
| | | align: "center", |
| | | formatter: (row) => renderActions(row) |
| | | } |
| | | ``` |
| | | |
| | | **æé®å®ä¹ï¼** |
| | | - è¿ç«æé®ï¼è°ç¨æçè¿ç«æ¥å£ |
| | | - åºç«æé®ï¼è°ç¨æçåºç«æ¥å£ |
| | | |
| | | **æé®æ¾ç¤ºè§åï¼** |
| | | |
| | | | åºåç¶æ | è¿ç« | åºç« | |
| | | |---------|:----:|:----:| |
| | | | å¾
å
¥åº (0) | â | â | |
| | | | å¨åº (1) | â | â | |
| | | | åºåºä¸ (2) | â | â | |
| | | | éå® (3) | â | â | |
| | | |
| | | ### 3.2 åºåæç»é¡µé¢ (stockInfoDetail.vue) |
| | | |
| | | #### æä½å设计 |
| | | |
| | | **è¡¨æ ¼åé
ç½®ï¼** |
| | | ```javascript |
| | | { |
| | | field: "actions", |
| | | title: "æä½", |
| | | width: 280, |
| | | fixed: "right", |
| | | align: "center", |
| | | formatter: (row) => renderActions(row) |
| | | } |
| | | ``` |
| | | |
| | | **æé®å®ä¹ï¼** |
| | | - ç»å®æé®ï¼è°ç¨æççµè¯ç»å®æ¥å£ |
| | | - è§£ç»æé®ï¼è°ç¨æççµè¯è§£ç»æ¥å£ |
| | | - NG䏿¥æé®ï¼è°ç¨æçNGçµè¯ä¸æ¥æ¥å£ |
| | | |
| | | **æé®æ¾ç¤ºè§åï¼** |
| | | |
| | | | çµè¯ç¶æ | ç»å® | è§£ç» | NG䏿¥ | |
| | | |---------|:----:|:----:|:------:| |
| | | | æ£å¸¸ (1) | â | â | â | |
| | | | å¼å¸¸ (2) | â | â | â | |
| | | | å·²éå® (99) | â | â | â | |
| | | |
| | | ### 3.3 ç¡®è®¤å¯¹è¯æ¡ç»ä»¶ (MesConfirmDialog.vue) |
| | | |
| | | **ç»ä»¶èè´£ï¼** |
| | | - æ¾ç¤ºå³å°æ§è¡çæä½ä¿¡æ¯ |
| | | - å±ç¤ºå
³é®åæ°ï¼æçç ã设å¤ç¼ç çï¼ |
| | | - æä¾ç¡®è®¤/åæ¶æé® |
| | | - æ¾ç¤ºè°ç¨ç»æï¼æå/å¤±è´¥ï¼ |
| | | |
| | | **Propså®ä¹ï¼** |
| | | ```typescript |
| | | interface MesConfirmDialogProps { |
| | | visible: boolean; |
| | | operationType: 'inbound' | 'outbound' | 'bind' | 'unbind' | 'ngReport'; |
| | | palletCode: string; |
| | | stockInfo?: any; |
| | | detailInfo?: any; |
| | | } |
| | | ``` |
| | | |
| | | ### 3.4 äº¤äºæµç¨ |
| | | |
| | | ``` |
| | | ç¨æ·ç¹å»æä½æé® |
| | | â |
| | | â¼ |
| | | æ£æ¥ç»å½ç¶æ âââââââ æªç»å½ âââââ æç¤º"请å
ç»å½" |
| | | â |
| | | â¼ å·²ç»å½ |
| | | æ£æ¥æä½æé âââââââ æ æé âââââ æç¤º"æ æéæ§è¡æ¤æä½" |
| | | â |
| | | â¼ ææé |
| | | å¼¹åºç¡®è®¤å¯¹è¯æ¡ |
| | | â |
| | | â¼ |
| | | ç¨æ·ç¹å»"确认æ§è¡" |
| | | â |
| | | â¼ |
| | | æ¾ç¤ºloadingç¶æ |
| | | â |
| | | â¼ |
| | | è°ç¨å端API |
| | | â |
| | | âââ æå âââââ æ¾ç¤ºæåæç¤º âââââ å·æ°å表 |
| | | â |
| | | âââ 失败 âââââ æ¾ç¤ºé误æç¤º + "éè¯"æé® |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## åãå端设计 |
| | | |
| | | ### 4.1 APIæ¥å£è®¾è®¡ |
| | | |
| | | #### 4.1.1 åºåä¿¡æ¯ç¸å
³æ¥å£ |
| | | |
| | | **æçè¿ç«** |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçè¿ç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | [HttpPost("inboundInContainer")] |
| | | public async Task<WebResponseContent> InboundInContainer([FromBody] InboundInContainerRequestDto dto) |
| | | ``` |
| | | |
| | | **请æ±DTOï¼** |
| | | ```csharp |
| | | public class InboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | } |
| | | ``` |
| | | |
| | | **æçåºç«** |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçåºç« - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | [HttpPost("outboundInContainer")] |
| | | public async Task<WebResponseContent> OutboundInContainer([FromBody] OutboundInContainerRequestDto dto) |
| | | ``` |
| | | |
| | | **请æ±DTOï¼** |
| | | ```csharp |
| | | public class OutboundInContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åºåID |
| | | /// </summary> |
| | | public long StockId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 产ååæ°å表ï¼å¯éï¼ |
| | | /// </summary> |
| | | public List<ParamItemDto> ParamList { get; set; } |
| | | } |
| | | ``` |
| | | |
| | | #### 4.1.2 åºåæç»ç¸å
³æ¥å£ |
| | | |
| | | **æççµè¯ç»å®** |
| | | ```csharp |
| | | /// <summary> |
| | | /// æççµè¯ç»å® - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | [HttpPost("bindContainer")] |
| | | public async Task<WebResponseContent> BindContainer([FromBody] BindContainerRequestDto dto) |
| | | ``` |
| | | |
| | | **请æ±DTOï¼** |
| | | ```csharp |
| | | public class BindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä½ç½®ä¿¡æ¯ |
| | | /// </summary> |
| | | public string Location { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æä½ç±»åï¼0-é»è®¤ 1-è¿ç« 2-åºç« 3-è¿åºç« |
| | | /// </summary> |
| | | public int OperationType { get; set; } = 1; |
| | | } |
| | | ``` |
| | | |
| | | **æççµè¯è§£ç»** |
| | | ```csharp |
| | | /// <summary> |
| | | /// æççµè¯è§£ç» - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | [HttpPost("unbindContainer")] |
| | | public async Task<WebResponseContent> UnbindContainer([FromBody] UnbindContainerRequestDto dto) |
| | | ``` |
| | | |
| | | **请æ±DTOï¼** |
| | | ```csharp |
| | | public class UnbindContainerRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯ç å表 |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | } |
| | | ``` |
| | | |
| | | **æçNGçµè¯ä¸æ¥** |
| | | ```csharp |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥ - è°ç¨MESæ¥å£ |
| | | /// </summary> |
| | | [HttpPost("containerNgReport")] |
| | | public async Task<WebResponseContent> ContainerNgReport([FromBody] ContainerNgReportRequestDto dto) |
| | | ``` |
| | | |
| | | **请æ±DTOï¼** |
| | | ```csharp |
| | | public class ContainerNgReportRequestDto |
| | | { |
| | | /// <summary> |
| | | /// æçç¼å· |
| | | /// </summary> |
| | | public string PalletCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯å表 |
| | | /// </summary> |
| | | public List<NgSfcItemDto> NgSfcList { get; set; } |
| | | } |
| | | |
| | | public class NgSfcItemDto |
| | | { |
| | | /// <summary> |
| | | /// äº§åæ¡ç |
| | | /// </summary> |
| | | public string Sfc { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NG代ç |
| | | /// </summary> |
| | | public string NgCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGè®¾å¤ |
| | | /// </summary> |
| | | public string NgEquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGèµæº |
| | | /// </summary> |
| | | public string NgResourceCode { get; set; } |
| | | } |
| | | ``` |
| | | |
| | | ### 4.2 æ°æ®åºè®¾è®¡ |
| | | |
| | | #### 4.2.1 MESæ¥å£è°ç¨æ¥å¿è¡¨ |
| | | |
| | | ```sql |
| | | CREATE TABLE Dt_MesApiLog ( |
| | | Id BIGINT PRIMARY KEY IDENTITY(1,1), |
| | | ApiType NVARCHAR(50) NOT NULL, -- æ¥å£ç±»å |
| | | RequestJson NVARCHAR(MAX) NULL, -- 请æ±JSON |
| | | ResponseJson NVARCHAR(MAX) NULL, -- ååºJSON |
| | | IsSuccess BIT NOT NULL DEFAULT 0, -- æ¯å¦æå |
| | | ErrorMessage NVARCHAR(500) NULL, -- éè¯¯ä¿¡æ¯ |
| | | ElapsedMs INT NOT NULL DEFAULT 0, -- èæ¶(毫ç§) |
| | | CreateDate DATETIME NOT NULL, -- å建æ¶é´ |
| | | Creator NVARCHAR(50) NULL, -- å建人 |
| | | INDEX IX_MesApiLog_ApiType (ApiType), |
| | | INDEX IX_MesApiLog_CreateDate (CreateDate) |
| | | ); |
| | | ``` |
| | | |
| | | **åæ®µè¯´æï¼** |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | Id | bigint | ä¸»é® | |
| | | | ApiType | string(50) | æ¥å£ç±»åï¼InboundInContainer, OutboundInContainer, BindContainer, UnbindContainer, ContainerNgReport | |
| | | | RequestJson | string(MAX) | MESæ¥å£è¯·æ±JSON | |
| | | | ResponseJson | string(MAX) | MESæ¥å£ååºJSON | |
| | | | IsSuccess | bool | è°ç¨æ¯å¦æå | |
| | | | ErrorMessage | string(500) | 失败æ¶çéè¯¯ä¿¡æ¯ | |
| | | | ElapsedMs | int | æ¥å£è°ç¨èæ¶ï¼æ¯«ç§ï¼ | |
| | | | CreateDate | datetime | å建æ¶é´ | |
| | | | Creator | string(50) | å建人 | |
| | | |
| | | #### 4.2.2 ç³»ç»é
置表æ©å± |
| | | |
| | | ```sql |
| | | -- å¨ Dt_SystemConfig è¡¨ä¸æ°å¢MESé
置项 |
| | | INSERT INTO Dt_SystemConfig (ConfigKey, ConfigValue, Description, CreateDate) |
| | | VALUES |
| | | ('MES_EquipmentCode', 'WCS_001', 'MES设å¤ç¼ç ', GETDATE()), |
| | | ('MES_ResourceCode', 'RESOURCE_001', 'MESèµæºç¼ç ', GETDATE()), |
| | | ('MES_ApiBaseUrl', 'http://mes-server/api', 'MESæ¥å£å°å', GETDATE()), |
| | | ('MES_TimeoutSeconds', '30', 'MESæ¥å£è¶
æ¶æ¶é´(ç§)', GETDATE()); |
| | | ``` |
| | | |
| | | ### 4.3 æå¡å±è®¾è®¡ |
| | | |
| | | #### 4.3.1 MESæ¥å¿æå¡æ¥å£ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡æ¥å£ |
| | | /// </summary> |
| | | public interface IMesLogService : IDependency |
| | | { |
| | | /// <summary> |
| | | /// è®°å½MESæ¥å£è°ç¨æ¥å¿ |
| | | /// </summary> |
| | | Task<bool> LogAsync(MesApiLogDto log); |
| | | |
| | | /// <summary> |
| | | /// è·åæè¿çMESæ¥å£è°ç¨è®°å½ |
| | | /// </summary> |
| | | Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50); |
| | | } |
| | | ``` |
| | | |
| | | #### 4.3.2 MESæ¥å¿æå¡å®ç° |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// MESæ¥å£æ¥å¿æå¡å®ç° |
| | | /// </summary> |
| | | public class MesLogService : IMesLogService |
| | | { |
| | | private readonly ISqlSugarClient _db; |
| | | |
| | | public async Task<bool> LogAsync(MesApiLogDto log) |
| | | { |
| | | var entity = new Dt_MesApiLog |
| | | { |
| | | ApiType = log.ApiType, |
| | | RequestJson = log.RequestJson, |
| | | ResponseJson = log.ResponseJson, |
| | | IsSuccess = log.IsSuccess, |
| | | ErrorMessage = log.ErrorMessage, |
| | | ElapsedMs = log.ElapsedMs, |
| | | CreateDate = DateTime.Now, |
| | | Creator = log.Creator |
| | | }; |
| | | |
| | | return await _db.Insertable(entity).ExecuteCommandAsync() > 0; |
| | | } |
| | | |
| | | public async Task<List<MesApiLogDto>> GetRecentLogsAsync(string apiType, int count = 50) |
| | | { |
| | | return await _db.Queryable<Dt_MesApiLog>() |
| | | .Where(x => x.ApiType == apiType) |
| | | .OrderByDescending(x => x.CreateDate) |
| | | .Take(count) |
| | | .ToListAsync(); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## äºãæ¥å£è°ç¨æµç¨ |
| | | |
| | | ### 5.1 æçè¿ç«æµç¨ |
| | | |
| | | ``` |
| | | ç¨æ·ç¹å»"è¿ç«"æé® |
| | | â |
| | | â¼ |
| | | å端弹åºç¡®è®¤å¯¹è¯æ¡ï¼æ¾ç¤ºæçç ã设å¤ç¼ç çï¼ |
| | | â |
| | | â¼ |
| | | ç¨æ·ç¡®è®¤ |
| | | â |
| | | â¼ |
| | | å端è°ç¨ POST /api/StockInfo/inboundInContainer |
| | | â |
| | | â¼ |
| | | å端 StockInfoController.InboundInContainer() |
| | | â |
| | | âââ 1. éªè¯åºåç¶æï¼ä»
"å¾
å
¥åº"ç¶æå
许è¿ç«ï¼ |
| | | â |
| | | âââ 2. è·åç³»ç»é
ç½®ï¼è®¾å¤ç¼ç ãèµæºç¼ç ï¼ |
| | | â |
| | | âââ 3. æé MES请æ±å¯¹è±¡ |
| | | â |
| | | âââ 4. è°ç¨ IMesService.InboundInContainer() |
| | | â â |
| | | â âââ è®°å½å¼å§æ¶é´ |
| | | â âââ åéHTTP请æ±å°MES |
| | | â âââ è®°å½ååºãèæ¶ |
| | | â âââ ä¿åæ¥å¿å° Dt_MesApiLog |
| | | â |
| | | âââ 5. è¿åç»æç»å端 |
| | | â |
| | | âââ å端æ¾ç¤ºæå/失败æç¤º |
| | | ``` |
| | | |
| | | ### 5.2 æççµè¯ç»å®æµç¨ |
| | | |
| | | ``` |
| | | ç¨æ·ç¹å»"ç»å®"æé® |
| | | â |
| | | â¼ |
| | | å端弹åºç¡®è®¤å¯¹è¯æ¡ï¼æ¾ç¤ºæçç ãçµè¯ç åè¡¨ï¼ |
| | | â |
| | | â¼ |
| | | ç¨æ·ç¡®è®¤ |
| | | â |
| | | â¼ |
| | | å端è°ç¨ POST /api/StockInfoDetail/bindContainer |
| | | â |
| | | â¼ |
| | | å端 StockInfoDetailController.BindContainer() |
| | | â |
| | | âââ 1. éªè¯çµè¯ç¶æï¼é"å·²éå®"ç¶æå
许ç»å®ï¼ |
| | | â |
| | | âââ 2. è·åç³»ç»é
ç½® |
| | | â |
| | | âââ 3. æé MES请æ±å¯¹è±¡ï¼å
å«çµè¯ç åè¡¨ï¼ |
| | | â |
| | | âââ 4. è°ç¨ IMesService.BindContainer() |
| | | â â |
| | | â âââ è®°å½å¼å§æ¶é´ |
| | | â âââ åéHTTP请æ±å°MES |
| | | â âââ è®°å½ååºãèæ¶ |
| | | â âââ ä¿åæ¥å¿å° Dt_MesApiLog |
| | | â |
| | | âââ 5. è¿åç»æç»å端 |
| | | â |
| | | âââ å端æ¾ç¤ºæå/失败æç¤º |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## å
ãé误å¤ç |
| | | |
| | | ### 6.1 é误类å |
| | | |
| | | | é误类å | 说æ | å¤çæ¹å¼ | |
| | | |---------|------|---------| |
| | | | ç½ç»è¶
æ¶ | MESæå¡å¨æ ååºæè¿æ¥è¶
æ¶ | æ¾ç¤ºé误æç¤ºï¼æä¾"éè¯"æé® | |
| | | | ä¸å¡æ ¡éªå¤±è´¥ | æçä¸åå¨ãçµè¯å·²ç»å®ç | æ¾ç¤ºMESè¿åçéè¯¯ä¿¡æ¯ | |
| | | | 认è¯å¤±è´¥ | MESæ¥å£è®¤è¯ä¿¡æ¯è¿æ | æ¾ç¤º"MES认è¯å¤±è´¥ï¼è¯·è系管çå" | |
| | | | åæ°é误 | 请æ±åæ°ä¸å®æ´ææ ¼å¼é误 | æ¾ç¤º"åæ°é误ï¼{å
·ä½é误}" | |
| | | | æªç¥é误 | MESç³»ç»è¿åå¼å¸¸ååº | æ¾ç¤º"MESç³»ç»å¼å¸¸ï¼è¯·ç¨åéè¯" | |
| | | |
| | | ### 6.2 å端é误æç¤º |
| | | |
| | | ```javascript |
| | | // æåæç¤º |
| | | ElMessage.success('æçè¿ç«æå'); |
| | | |
| | | // 失败æç¤º |
| | | ElMessage.error({ |
| | | message: 'MESæå¡å¨è¿æ¥è¶
æ¶ï¼è¯·æ£æ¥ç½ç»åéè¯', |
| | | showRetry: true, |
| | | onRetry: () => retryOperation() |
| | | }); |
| | | ``` |
| | | |
| | | ### 6.3 å端é误æ¥å¿ |
| | | |
| | | ```csharp |
| | | try |
| | | { |
| | | // è°ç¨MESæ¥å£ |
| | | } |
| | | catch (HttpRequestException ex) |
| | | { |
| | | // ç½ç»å¼å¸¸ |
| | | await _mesLogService.LogAsync(new MesApiLogDto |
| | | { |
| | | ApiType = "InboundInContainer", |
| | | IsSuccess = false, |
| | | ErrorMessage = $"ç½ç»å¼å¸¸: {ex.Message}", |
| | | ElapsedMs = elapsedMs |
| | | }); |
| | | return ResponseContent.Error("MESæå¡å¨è¿æ¥å¤±è´¥ï¼è¯·æ£æ¥ç½ç»"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // å
¶ä»å¼å¸¸ |
| | | _logger.LogError(ex, "è°ç¨MESæ¥å£å¼å¸¸"); |
| | | return ResponseContent.Error($"MESæ¥å£è°ç¨å¤±è´¥: {ex.Message}"); |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãæéæ§å¶ |
| | | |
| | | ### 7.1 åè½æéå®ä¹ |
| | | |
| | | 建议å¨ç³»ç»ä¸æ°å¢ä»¥ä¸åè½æéï¼ |
| | | |
| | | | æé代ç | æéåç§° | 说æ | |
| | | |---------|---------|------| |
| | | | MES_INBOUND | MESè¿ç«æä½ | å
许æ§è¡æçè¿ç«æä½ | |
| | | | MES_OUTBOUND | MESåºç«æä½ | å
许æ§è¡æçåºç«æä½ | |
| | | | MES_BIND | MESç»å®æä½ | å
许æ§è¡çµè¯ç»å®æä½ | |
| | | | MES_UNBIND | MESè§£ç»æä½ | å
许æ§è¡çµè¯è§£ç»æä½ | |
| | | | MES_NG_REPORT | MES NG䏿¥ | å
许æ§è¡NG䏿¥æä½ | |
| | | |
| | | ### 7.2 æééªè¯ |
| | | |
| | | ```csharp |
| | | [HttpPost("inboundInContainer")] |
| | | [Permission("MES_INBOUND")] |
| | | public async Task<WebResponseContent> InboundInContainer([FromBody] InboundInContainerRequestDto dto) |
| | | { |
| | | // æ¥å£å®ç° |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## å
«ãæä»¶åæ´æ¸
å |
| | | |
| | | ### 8.1 å端æä»¶ |
| | | |
| | | ``` |
| | | WMS/WIDESEA_WMSClient/src/ |
| | | âââ views/stock/ |
| | | â âââ stockInfo.vue # ä¿®æ¹ï¼æ·»å æä½å |
| | | â âââ stockInfoDetail.vue # ä¿®æ¹ï¼æ·»å æä½å |
| | | âââ components/ |
| | | â âââ MesConfirmDialog.vue # æ°å¢ï¼MESç¡®è®¤å¯¹è¯æ¡ |
| | | âââ api/ |
| | | âââ mes.js # æ°å¢ï¼MES APIè°ç¨ |
| | | ``` |
| | | |
| | | ### 8.2 å端æä»¶ |
| | | |
| | | ``` |
| | | WMS/WIDESEA_WMSServer/ |
| | | âââ Controllers/ |
| | | â âââ Stock/ |
| | | â âââ StockInfoController.cs # ä¿®æ¹ï¼æ·»å è¿ç«/åºç«æ¥å£ |
| | | â âââ StockInfoDetailController.cs # ä¿®æ¹ï¼æ·»å ç»å®/è§£ç»/NG䏿¥æ¥å£ |
| | | âââ Services/ |
| | | â âââ Mes/ |
| | | â âââ IMesLogService.cs # æ°å¢ï¼æ¥å¿æå¡æ¥å£ |
| | | â âââ MesLogService.cs # æ°å¢ï¼æ¥å¿æå¡å®ç° |
| | | âââ DTO/ |
| | | âââ Mes/ |
| | | â âââ MesApiLogDto.cs # æ°å¢ï¼æ¥å¿DTO |
| | | â âââ InboundInContainerRequestDto.cs # æ°å¢ï¼è¿ç«è¯·æ±DTO |
| | | â âââ OutboundInContainerRequestDto.cs # æ°å¢ï¼åºç«è¯·æ±DTO |
| | | â âââ BindContainerRequestDto.cs # æ°å¢ï¼ç»å®è¯·æ±DTO |
| | | â âââ UnbindContainerRequestDto.cs # æ°å¢ï¼è§£ç»è¯·æ±DTO |
| | | â âââ ContainerNgReportRequestDto.cs # æ°å¢ï¼NG䏿¥è¯·æ±DTO |
| | | âââ Models/ |
| | | âââ Mes/ |
| | | âââ Dt_MesApiLog.cs # æ°å¢ï¼æ¥å¿å®ä½ |
| | | ``` |
| | | |
| | | ### 8.3 æ°æ®åºæä»¶ |
| | | |
| | | ``` |
| | | Database/ |
| | | âââ Scripts/ |
| | | âââ 20260412_MesApiLog.sql # æ°å¢ï¼æ¥å¿è¡¨åå»ºèæ¬ |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ä¹ãæµè¯è¦ç¹ |
| | | |
| | | ### 9.1 åè½æµè¯ |
| | | |
| | | | æµè¯åºæ¯ | é¢æç»æ | |
| | | |---------|---------| |
| | | | å¾
å
¥åºç¶ææçç¹å»è¿ç« | å¼¹åºç¡®è®¤å¯¹è¯æ¡ï¼ç¡®è®¤åæåè°ç¨ | |
| | | | å¨åºç¶ææçç¹å»è¿ç« | è¿ç«æé®ä¸æ¾ç¤º | |
| | | | ç½ç»ä¸ææ¶ç¹å»æä½ | æ¾ç¤ºç½ç»é误æç¤ºï¼æä¾éè¯æé® | |
| | | | MESè¿åä¸å¡é误 | æ¾ç¤ºMESè¿åçå
·ä½éè¯¯ä¿¡æ¯ | |
| | | | ç¹å»æä½åå·æ°é¡µé¢ | æä½è®°å½å·²ä¿åå°æ¥å¿è¡¨ | |
| | | |
| | | ### 9.2 æ§è½æµè¯ |
| | | |
| | | | ææ | ç®æ å¼ | |
| | | |------|--------| |
| | | | MESæ¥å£ååºæ¶é´ | < 2ç§ | |
| | | | å端æé®ç¹å»ååº | < 100ms | |
| | | | æ¥å¿åå
¥èæ¶ | < 50ms | |
| | | |
| | | --- |
| | | |
| | | ## åãåç»ä¼å建议 |
| | | |
| | | 1. **æ¹éæä½**ï¼æ¯æéä¸å¤ä¸ªæç/çµè¯æ¹éè°ç¨MESæ¥å£ |
| | | 2. **èªå¨éè¯**ï¼å¯¹äºç½ç»è¶
æ¶çä¸´æ¶æ
éï¼èªå¨éè¯3次 |
| | | 3. **æ¥å£çæ§**ï¼å¢å MESæ¥å£è°ç¨ç宿¶çæ§ååè¦ |
| | | 4. **åæ°é
ç½®å**ï¼å°è¶
æ¶æ¶é´ãéè¯æ¬¡æ°çåæ°åæå¯é
置项 |
| | | 5. **æä½å®¡è®¡**ï¼å¢å æä½å®¡è®¡æ¥å¿ï¼è®°å½è°å¨ä»ä¹æ¶é´æ§è¡äºä»ä¹æä½ |
| | | |
| | | --- |
| | | |
| | | **ææ¡£çæ¬**: 1.0 |
| | | **æåæ´æ°**: 2026-04-12 |