PipeLineLems/server/src/CMS.Plugin.PipeLineLems.Application.Contracts/Dtos/WorkPlan/WorkPlanCreateOrUpdateDtoBase.cs
@@ -183,6 +183,11 @@ /// 创建人ID /// </summary> public string? CreatorId { get; set; } /// <summary> /// 创建人 /// </summary> public string CreatorName { get; set; } /// <summary> /// 修改人ID PipeLineLems/server/src/CMS.Plugin.PipeLineLems.Application.Contracts/Services/IWorkPlanAppService.cs
@@ -1,6 +1,7 @@ using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan; using CMS.Plugin.PipeLineLems.Domain.WorkPlan; using Volo.Abp.Application.Services; using Volo.Abp.Users; namespace CMS.Plugin.PipeLineLems.Application.Contracts.Services; @@ -45,7 +46,7 @@ /// </summary> /// <param name="input"></param> /// <returns></returns> Task ImportAsync(WorkPlansImportModel input); Task ImportAsync(WorkPlansImportModel input, string userId,string userAccount); /// <summary> /// 导出作业计划表 PipeLineLems/server/src/CMS.Plugin.PipeLineLems.Application/Implements/MesAppService.cs
@@ -8,6 +8,7 @@ using CMS.Plugin.ProductManagement.Abstractions; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Users; namespace CMS.Plugin.PipeLineLems.Application.Implements; @@ -30,9 +31,9 @@ _sharedService = sharedService; } public async Task<MesOrderResponse> CreateAsync(List<WorkPlanInput> input) public async Task<MesOrderResponse> CreateAsync(List<WorkPlanInput> input, string userId, string userAccount) { var response = await _sharedService.CommonCreatebyApsAsync(input, _serviceProvider, _workPlanAppService); var response = await _sharedService.CommonCreatebyApsAsync(input, _serviceProvider, _workPlanAppService, userId, userAccount); return response; } PipeLineLems/server/src/CMS.Plugin.PipeLineLems.Application/Implements/SharedService.cs
@@ -15,6 +15,7 @@ using System.Text; using CMS.Plugin.PipeLineLems.Domain.WorkPlan; using CMS.Plugin.PipeLineLems.Domain.CallMaterialOrderRecord; using Volo.Abp.Users; namespace CMS.Plugin.PipeLineLems.Application.Implements; @@ -33,9 +34,11 @@ /// <exception cref="UserFriendlyException"></exception> public async Task<MesOrderResponse> CommonCreatebyApsAsync(List<WorkPlanInput> input, IServiceProvider _serviceProvider, WorkPlanAppService workPlanAppService WorkPlanAppService workPlanAppService, string userId, string userAccount ) { if (input == null) { throw new UserFriendlyException("输入参数不能为空"); @@ -62,6 +65,7 @@ var orderManager = _serviceProvider.GetRequiredService<IOrderManager>(); var productProvider = _serviceProvider.GetRequiredService<IProductProvider>(); var formulaProvider = _serviceProvider.GetRequiredService<IFormulaProvider>(); List<OrderModel> orderModels = new List<OrderModel>(); #region 事务 @@ -185,7 +189,7 @@ //throw new UserFriendlyException($"主动触发失败"); //保存到 scms_workplans 表中 foreach (var item in input) { @@ -194,6 +198,8 @@ insertObj.CallMaterialStatus = Domain.Shared.Enums.CallMaterialStatusEnum.未执行; insertObj.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.未生产; insertObj.Sort = 1; insertObj.CreatorId = userId; insertObj.CreatorName = userAccount; await workPlanAppService.CreateAsync(insertObj); } PipeLineLems/server/src/CMS.Plugin.PipeLineLems.Application/Implements/WorkPlanAppService.cs
@@ -10,6 +10,7 @@ using Volo.Abp.Data; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; using Volo.Abp.Users; namespace CMS.Plugin.PipeLineLems.Application.Implements; @@ -307,13 +308,13 @@ /// <param name="input"></param> /// <returns></returns> /// <exception cref="UserFriendlyException"></exception> public async Task ImportAsync(WorkPlansImportModel input) public async Task ImportAsync(WorkPlansImportModel input, string userId,string userAccount) { //转换数据 var result = ObjectMapper.Map<List<WorkPlansImportModel.WorkPlanImportModel>, List<WorkPlanInput>>(input.WorkPlans); //await CreatebyApsAsync(result); await _sharedService.CommonCreatebyApsAsync(result, _serviceProvider, this); await _sharedService.CommonCreatebyApsAsync(result, _serviceProvider, this, userId, userAccount); // Check.NotNull(input, nameof(input)); // var workPlanCreateDtos = new List<(int RowIndex, WorkPlanCreateDto Item)>(); PipeLineLems/server/src/CMS.Plugin.PipeLineLems/Controller/WorkPlanController.cs
@@ -1,5 +1,6 @@ using Ao.Lang; using CMS.Extensions.Abp.AspNetCore.Mvc.Filters; using CMS.Framework.AspNetCore.Users; using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan; using CMS.Plugin.PipeLineLems.Application.Contracts.Services; using Microsoft.AspNetCore.Authorization; @@ -24,14 +25,16 @@ public class WorkPlanController : ControllerBase { private readonly IWorkPlanAppService _workPlanAppService; private readonly ICurrentUser _currentUser; /// <summary> /// Initializes a new instance of the <see cref="WorkPlanController"/> class. /// </summary> /// <param name="workPlanAppService">The workPlan application service.</param> public WorkPlanController(IWorkPlanAppService workPlanAppService) public WorkPlanController(IWorkPlanAppService workPlanAppService, ICurrentUser currentUser) { _workPlanAppService = workPlanAppService; _currentUser = currentUser; } /// <summary> @@ -147,6 +150,9 @@ await file.CopyToAsync(stream); stream.Seek(0L, SeekOrigin.Begin); var userAccount = _currentUser.UserAccount; var userId = _currentUser.UserId; var sheetNames = stream.GetSheetNames(); var workPlanRows = sheetNames.Contains("配置") ? MiniExcel.Query<WorkPlansImportModel.WorkPlanImportModel>(stream, sheetName: "配置").ToList() : new(); @@ -158,7 +164,7 @@ await _workPlanAppService.ImportAsync(new WorkPlansImportModel { WorkPlans = workPlanRows, }); }, userId, userAccount); return Ok(); } PipeLineLems/server/src/CMS.Plugin.PipeLineLems/ProjectService/PipeLineLemsProjectService.cs
@@ -20,6 +20,7 @@ using CMS.Plugin.PipeLineLems.Domain.WorkPlan; using CMS.Plugin.PipeLineLems.Domain.CallMaterialOrder; using System.Collections.Generic; using CMS.Framework.AspNetCore.Users; namespace CMS.Plugin.PipeLineLems.ProjectService { @@ -31,6 +32,7 @@ private IServiceProvider _serviceProvider; private readonly ILogger<PipeLineLemsProjectService> _logger; private readonly IVariableDataCache _variableDataCache; /// <summary> /// 变量服务 @@ -84,6 +86,7 @@ _monitorVariableNames = new Dictionary<string, string> { { "打码进站信号", "打码进站信号(描述)" }, { "请求生成打码产品码信号", "请求生成打码产品码信号(描述)" }, { "切割进站信号", "切割进站信号(描述)" }, }; @@ -142,6 +145,30 @@ _logger.LogInformation($"{changed.Name} 变量值发生变化,旧值{oldValue}=新值{newValue},TraceId={traceId}"); if (changed.Name == "请求生成打码产品码信号" && changed.New?.Value.SafeString().ToBool() == true) { // TODO: 处理变量值变化 // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97 /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。 注意事项: (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。 (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。 (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。 (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。 (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/ _ = Task.Run(async () => { await HanlderForPringBarCodeByCreateProductAsync(); // 例1:同步处理 //await ProcessAsync(); // 例2:调用外部API //await ExecuteExternalApiAsync(); }); } if (changed.Name == "打码进站信号" && changed.New?.Value.SafeString().ToBool() == true) { @@ -165,6 +192,8 @@ //await ExecuteExternalApiAsync(); }); } if (changed.Name == "切割进站信号" && changed.New?.Value.SafeString().ToBool() == true) { @@ -229,10 +258,128 @@ } /// <summary> /// 打码 /// 打码进站信号 /// </summary> /// <returns></returns> private async Task HanlderForPringBarCodeAsync() { var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>(); var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>(); var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>(); using var scope = _serviceProvider.CreateScope(); var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); using var uow = unitOfWorkManager.Begin(requiresNew: true); var plcTaskNo = await _variableService.ReadValueAsync("打码进站PLC任务号"); if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString())) { } else { var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString(); CallMaterialOrder callMaterialOrder = null; try { //根据wms任务号寻找 叫料工单 callMaterialOrder = await callMaterialOrderAppService.FindByWmsTaskNoAsync(myTaskNo); if (callMaterialOrder == null) return;//结束 //根据原料标识寻找 作业计划 var workPlanList = await workPlanAppService.FindByDataIdentifierAsync(callMaterialOrder.DataIdentifier); if (workPlanList?.Count == 0) return;//结束 ////TODO:暂时生成产品ID ////var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff"); //var productID = workPlanList.First().PipeSpecCode; //Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?> //{ // { "打码_ProductID", productID}, //}; //var ret = _variableService.WriteValueAsync(keyValuePairs_productID); ////更新为生产中 //foreach (var item in workPlanList) //{ // item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中; //} //await workPlanRepository.UpdateManyAsync(workPlanList); //得到码值 var code1 = ""; var code2 = ""; var code3 = ""; var pipeSpecCode1 = ""; var pipeSpecCode2 = ""; var pipeSpecCode3 = ""; var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "切割").ToList(); for (int i = 0; i < new_workPlanList.Count; i++) { if (i == 0) { code1 = new_workPlanList[i].MarkingContent; pipeSpecCode1 = new_workPlanList[i].PipeSpecCode; } if (i == 1) { code2 = new_workPlanList[i].MarkingContent; pipeSpecCode2 = new_workPlanList[i].PipeSpecCode; } if (i == 2) { code3 = new_workPlanList[i].MarkingContent; pipeSpecCode3 = new_workPlanList[i].PipeSpecCode; } } Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?> { { "打码工件1",code1}, { "打码工件2", code2}, { "打码工件3", code3 }, { "打码管段编码1",pipeSpecCode1}, { "打码管段编码2", pipeSpecCode2}, { "打码管段编码3", pipeSpecCode3 }, { "打码管段编码", new_workPlanList.First().PipeSpecCode }, { "打码管段名称", new_workPlanList.First().PipeSectionName }, { "打码原料管型号", new_workPlanList.First().MaterialMode }, { "打码原料标识", new_workPlanList.First().DataIdentifier } }; _variableService.WriteValueAsync(keyValuePairs); //TODO:模拟采集参数 keyValuePairs = new Dictionary<string, object?> { { "打码速度", 100}, { "打码质量", 2}, }; var ret2 = _variableService.WriteValueAsync(keyValuePairs); uow.CompleteAsync(); } catch (Exception) { uow.RollbackAsync(); throw; } } } /// <summary> /// 请求生成打码产品码信号 /// </summary> /// <returns></returns> private async Task HanlderForPringBarCodeByCreateProductAsync() { var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>(); @@ -283,48 +430,6 @@ item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中; } await workPlanRepository.UpdateManyAsync(workPlanList); //得到码值 var code1 = ""; var code2 = ""; var code3 = ""; var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "切割").ToList(); for (int i = 0; i < new_workPlanList.Count; i++) { if (i == 0) { code1 = new_workPlanList[i].MarkingContent; } if (i == 1) { code2 = new_workPlanList[i].MarkingContent; } if (i == 2) { code3 = new_workPlanList[i].MarkingContent; } } Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?> { { "打码工件1",code1}, { "打码工件2", code2}, { "打码工件3", code3 }, { "打码管段编码", new_workPlanList.First().PipeSpecCode }, { "打码管段名称", new_workPlanList.First().PipeSectionName }, { "打码原料管型号", new_workPlanList.First().MaterialMode }, { "打码原料标识", new_workPlanList.First().DataIdentifier } }; _variableService.WriteValueAsync(keyValuePairs); //TODO:模拟采集参数 keyValuePairs = new Dictionary<string, object?> { { "打码速度", 100}, { "打码质量", 2}, }; var ret2 = _variableService.WriteValueAsync(keyValuePairs); uow.CompleteAsync();