Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs
@@ -1,10 +1,5 @@ using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace WIDESEAWCS_Core.BaseRepository { @@ -15,6 +10,7 @@ /// </summary> /// <returns>SqlSugarClient数据库客户端对象</returns> SqlSugarClient GetDbClient(); int TranCount { get; } /// <summary> @@ -27,24 +23,36 @@ /// 开始一个事务 /// </summary> void BeginTran(); /// <summary> /// 开始一个事务 /// </summary> /// <param name="method">触发事务的方法信息</param> void BeginTran(MethodInfo method); /// <summary> /// 开始一个事务,并执行提供的函数 /// </summary> /// <param name="func">委托方法</param> /// <returns></returns> WebResponseContent BeginTran(Func<WebResponseContent> func); /// <summary> /// 提交当前事务 /// </summary> void CommitTran(); /// <summary> /// 提交事务 /// </summary> /// <param name="method">触发提交事务的方法信息</param> void CommitTran(MethodInfo method); /// <summary> /// 回滚当前事务 /// </summary> void RollbackTran(); /// <summary> /// 回滚当前事务 /// </summary> Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs
@@ -1,13 +1,7 @@ using Microsoft.Extensions.Logging; using SqlSugar; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using WIDESEAWCS_Core.Helper; namespace WIDESEAWCS_Core.BaseRepository @@ -16,13 +10,16 @@ { // 定义日志记录器 private readonly ILogger<UnitOfWorkManage> _logger; // 定义SqlSugarClient private readonly ISqlSugarClient _sqlSugarClient; // 定义事务计数器 private int _tranCount { get; set; } // 定义事务计数器的只读属性 public int TranCount => _tranCount; // 定义事务栈 public readonly ConcurrentStack<string> TranStack = new(); @@ -43,7 +40,6 @@ // 必须要as,后边会用到切换数据库操作 return _sqlSugarClient as SqlSugarClient; } // 创建UnitOfWork public UnitOfWork CreateUnitOfWork() @@ -141,7 +137,6 @@ { spinner.SpinOnce(); } if (result == method.GetFullName()) { Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -1,19 +1,18 @@ using Autofac; using Newtonsoft.Json; using System.Diagnostics.CodeAnalysis; using WIDESEA_Core; using WIDESEAWCS_Common.HttpEnum; using WIDESEAWCS_Common.TaskEnum; using WIDESEA_Core; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_Core.BaseRepository; using WIDESEAWCS_Core.Enums; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_DTO; using WIDESEAWCS_DTO.Stock; using WIDESEAWCS_DTO.TaskInfo; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob.DTO; using WIDESEAWCS_QuartzJob.Models; using WIDESEAWCS_QuartzJob.Service; @@ -28,8 +27,8 @@ private readonly IRouterService _routerService; private readonly HttpClientHelper _httpClientHelper; private readonly IRobotTaskService _robotTaskService; private readonly ITaskRepository _taskRepository; private readonly IComponentContext _componentContext; private readonly IUnitOfWorkManage _unitOfWorkManage; /// <summary> /// 初始化出库任务流程服务。 @@ -37,15 +36,14 @@ /// <param name="routerService">路由服务。</param> /// <param name="httpClientHelper">WMS接口调用帮助类。</param> /// <param name="robotTaskService">机械手任务服务。</param> /// <param name="taskRepository">任务仓储(用于删除出库任务)。</param> /// <param name="componentContext">Autofac组件上下文(用于延迟解析ITaskService以避免循环依赖)。</param> public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService, ITaskRepository taskRepository, IComponentContext componentContext) public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService, IComponentContext componentContext, IUnitOfWorkManage unitOfWorkManage) { _routerService = routerService; _httpClientHelper = httpClientHelper; _robotTaskService = robotTaskService; _taskRepository = taskRepository; _componentContext = componentContext; _unitOfWorkManage = unitOfWorkManage; } /// <summary> @@ -154,8 +152,14 @@ if (inboundTaskDto != null) { _unitOfWorkManage.BeginTran(() => { // 先删除本地出库任务,避免托盘号唯一键冲突 _taskRepository.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成); bool isDeleted = TaskService.Repository.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成); if (!isDeleted) { return content.Error($"删除本地出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】"); } // 调用ReceiveWMSTask创建本地入库任务 var receiveResult = TaskService.ReceiveWMSTask(new List<WMSTaskDTO> { inboundTaskDto }); @@ -163,6 +167,8 @@ { return content.Error($"创建本地入库任务失败: {receiveResult.Message}"); } return content.OK("创建本地入库任务成功"); }); } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RobotTaskFlowService.cs
@@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_DTO.TaskInfo; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -676,8 +676,7 @@ return BaseDal.QueryFirst(x => x.TaskType == (int)TaskInboundTypeEnum.Inbound && x.TaskStatus == (int)TaskInStatusEnum.InNew && x.SourceAddress == sourceAddress && x.Creater == "WMS"); x.SourceAddress == sourceAddress); } } Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs
@@ -17,6 +17,8 @@ void BeginTran(); void BeginTran(MethodInfo method); WebResponseContent BeginTran(Func<WebResponseContent> func); Task<WebResponseContent> BeginTranAsync(Func<Task<WebResponseContent>> funcAsync); void CommitTran(); void CommitTran(MethodInfo method); void RollbackTran(); Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs
@@ -100,6 +100,32 @@ } } private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1); public async Task<WebResponseContent> BeginTranAsync(Func<Task<WebResponseContent>> funcAsync) { await _asyncLock.WaitAsync(); try { BeginTran(); // 假设这是同步方法,启动事务 WebResponseContent content = await funcAsync(); if (content.Status) CommitTran(); // 同步提交 else RollbackTran(); // 同步回滚 return content; } catch (Exception ex) { RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } finally { _asyncLock.Release(); } } public void CommitTran() { lock (this) Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_WCS.cs
@@ -1,27 +1,15 @@ using Mapster; using MapsterMapper; using Microsoft.Extensions.Configuration; using SqlSugar; using System.DirectoryServices.Protocols; using System.Text.Json; using WIDESEA_Common.Constants; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Core; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_DTO.GradingMachine; using WIDESEA_DTO.MES; using WIDESEA_DTO.Stock; using WIDESEA_DTO.Task; using WIDESEA_IBasicService; using WIDESEA_IStockService; using WIDESEA_ITaskInfoService; using WIDESEA_Model.Models; namespace WIDESEA_TaskInfoService @@ -185,7 +173,6 @@ // 判断是不是极卷库任务 if (taskDto.WarehouseId == (int)WarehouseEnum.FJ1 || taskDto.WarehouseId == (int)WarehouseEnum.ZJ1) { return await CompleteAgvInboundTaskAsync(taskDto); } @@ -885,31 +872,31 @@ { try { // 1. 根据任务类型字符串确定 TaskType 和 TaskStatus int taskType; int taskStatus; switch (dto.TaskType) { case "入库": taskType = TaskTypeEnum.Inbound.GetHashCode(); taskType = TaskInboundTypeEnum.Inbound.GetHashCode(); taskStatus = TaskInStatusEnum.InNew.GetHashCode(); break; case "出库": taskType = TaskTypeEnum.Outbound.GetHashCode(); taskType = TaskOutboundTypeEnum.Outbound.GetHashCode(); taskStatus = TaskOutStatusEnum.OutNew.GetHashCode(); break; case "移库": taskType = TaskTypeEnum.Relocation.GetHashCode(); taskType = TaskRelocationTypeEnum.Relocation.GetHashCode(); taskStatus = TaskRelocationStatusEnum.RelocationNew.GetHashCode(); break; default: return WebResponseContent.Instance.Error($"不支持的任务类型: {dto.TaskType}"); } // 2. 生成任务号 int taskNum = await BaseDal.GetTaskNo(); // 3. 构建任务实体 var task = new Dt_Task { TaskNum = taskNum, @@ -919,6 +906,7 @@ TaskType = taskType, TaskStatus = taskStatus, Grade = dto.Grade, Roadway = dto.TargetAddress, WarehouseId = dto.WarehouseId, CurrentAddress = dto.SourceAddress, NextAddress = dto.TargetAddress, @@ -927,31 +915,37 @@ ModifyDate = DateTime.Now }; // 4. 保存到数据库 var result = await BaseDal.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error("创建任务失败"); // 5. 发送到 WCS var wmsTaskDto = new WMSTaskDTO var wmsTaskDtos = new List<WMSTaskDTO>() { new() { TaskNum = task.TaskNum, PalletCode = task.PalletCode, SourceAddress = task.SourceAddress, TargetAddress = task.TargetAddress, TaskType = task.TaskType, Roadway = task.Roadway, TaskStatus = task.TaskStatus, WarehouseId = task.WarehouseId } }; await _unitOfWorkManage.BeginTranAsync(async () => { // 4. 保存到数据库 var result = await BaseDal.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error("创建任务失败"); var wcsResult = _httpClientHelper.Post<WebResponseContent>( "http://localhost:9292/api/Task/ReceiveManualTask", wmsTaskDto.ToJson()); wmsTaskDtos.ToJson()); if (!wcsResult.IsSuccess || !wcsResult.Data.Status) return WebResponseContent.Instance.Error($"任务已创建但发送给WCS失败: {wcsResult.Data?.Message}"); return WebResponseContent.Instance.OK($"手动创建任务成功,任务号: {taskNum}"); }); } catch (Exception ex) {