dev #1

Merged
wenjy merged 3 commits from dev into master 1 month ago

@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(dotnet build *)"
]
}
}

@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.6.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sln.Wcs.Business\Sln.Wcs.Business.csproj" />
</ItemGroup>
</Project>

@ -1,515 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
|* (c) 2026 WenJY
|* CLR4.0.30319.42000
|* Mr.Wen's MacBook Pro
|* Sln.Wcs.Business.Tests
|*
|*
|* WenJY
|*
|* 2026-05-17
|* V1.0.0
|* StoreTaskBusiness
|*
|*--------------------------------------------------------------------
|*
|*
|*
|*
|* V1.0.0
|*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Moq;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
using Xunit;
namespace Sln.Wcs.Business.Tests;
/// <summary>
/// 可测试的 StoreTaskBusiness 子类,用于访问 protected 方法
/// </summary>
public class TestableStoreTaskBusiness : StoreTaskBusiness
{
public TestableStoreTaskBusiness(
IBasePathInfoService basePathInfoService,
ILiveTaskQueueService liveTaskQueueService,
IBaseStoreInfoService baseStoreInfoService)
: base(basePathInfoService, liveTaskQueueService, baseStoreInfoService)
{
}
public void PublicValidateCreateTaskParams(CreateTaskDto dto) =>
ValidateCreateTaskParams(dto);
public void PublicValidateFilterLocationParams(FilterLocationDto dto) =>
ValidateFilterLocationParams(dto);
public string PublicGenerateTaskCode() => GenerateTaskCode();
public string PublicGetCategoryName(TaskCategoryEnum category) =>
GetCategoryName(category);
public string PublicGetTaskTypeName(TaskTypeEnum taskType) =>
GetTaskTypeName(taskType);
public string PublicGetTaskSuccessMessage(
string taskCode, string pathName, TaskTypeEnum taskType, TaskCategoryEnum taskCategory) =>
GetTaskSuccessMessage(taskCode, pathName, taskType, taskCategory);
public BasePathInfo PublicGetPathInfo(
CreateTaskDto createTaskDto, TaskTypeEnum taskType, TaskCategoryEnum taskCategory) =>
GetPathInfo(createTaskDto, taskType, taskCategory);
}
public class StoreTaskBusinessTests
{
private readonly Mock<IBasePathInfoService> _mockBasePathInfoService;
private readonly Mock<ILiveTaskQueueService> _mockLiveTaskQueueService;
private readonly Mock<IBaseStoreInfoService> _mockBaseStoreInfoService;
private readonly TestableStoreTaskBusiness _storeTaskBusiness;
public StoreTaskBusinessTests()
{
_mockBasePathInfoService = new Mock<IBasePathInfoService>();
_mockLiveTaskQueueService = new Mock<ILiveTaskQueueService>();
_mockBaseStoreInfoService = new Mock<IBaseStoreInfoService>();
_storeTaskBusiness = new TestableStoreTaskBusiness(
_mockBasePathInfoService.Object,
_mockLiveTaskQueueService.Object,
_mockBaseStoreInfoService.Object);
}
#region GetCategoryName 测试
[Theory]
[InlineData(TaskCategoryEnum.Material, "包材")]
[InlineData(TaskCategoryEnum.Product, "成品")]
[InlineData(TaskCategoryEnum.Pallet, "托盘")]
public void GetCategoryName_ValidCategory_ReturnsCorrectName(TaskCategoryEnum category, string expected)
{
var result = _storeTaskBusiness.PublicGetCategoryName(category);
Assert.Equal(expected, result);
}
#endregion
#region GetTaskTypeName 测试
[Theory]
[InlineData(TaskTypeEnum.InStore, "入库")]
[InlineData(TaskTypeEnum.OutStore, "出库")]
public void GetTaskTypeName_ValidType_ReturnsCorrectName(TaskTypeEnum taskType, string expected)
{
var result = _storeTaskBusiness.PublicGetTaskTypeName(taskType);
Assert.Equal(expected, result);
}
#endregion
#region ValidateCreateTaskParams 测试
[Fact]
public void ValidateCreateTaskParams_NullMaterialCode_ThrowsException()
{
var dto = new CreateTaskDto
{
materialCode = null!,
palletBarcode = "PLT001",
startPoint = "A",
endPoint = "B"
};
var exception = Assert.Throws<InvalidOperationException>(() =>
_storeTaskBusiness.PublicValidateCreateTaskParams(dto));
Assert.Contains("物料编号不允许为 NULL", exception.Message);
}
[Fact]
public void ValidateCreateTaskParams_NullPalletBarcode_ThrowsException()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
palletBarcode = null!,
startPoint = "A",
endPoint = "B",
taskCategory = TaskCategoryEnum.Material
};
var exception = Assert.Throws<InvalidOperationException>(() =>
_storeTaskBusiness.PublicValidateCreateTaskParams(dto));
Assert.Contains("条码不允许为 NULL", exception.Message);
}
[Fact]
public void ValidateCreateTaskParams_NullStartPoint_ThrowsException()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = null!,
endPoint = "B"
};
var exception = Assert.Throws<InvalidOperationException>(() =>
_storeTaskBusiness.PublicValidateCreateTaskParams(dto));
Assert.Contains("起始位置、终点位置不允许为 NULL", exception.Message);
}
[Fact]
public void ValidateCreateTaskParams_EmptyEndPoint_ThrowsException()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = "A",
endPoint = ""
};
var exception = Assert.Throws<InvalidOperationException>(() =>
_storeTaskBusiness.PublicValidateCreateTaskParams(dto));
Assert.Contains("起始位置、终点位置不允许为 NULL", exception.Message);
}
[Fact]
public void ValidateCreateTaskParams_ValidParams_NoException()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = "A",
endPoint = "B",
taskCategory = TaskCategoryEnum.Material
};
var exception = Record.Exception(() =>
_storeTaskBusiness.PublicValidateCreateTaskParams(dto));
Assert.Null(exception);
}
#endregion
#region ValidateFilterLocationParams 测试
[Fact]
public void ValidateFilterLocationParams_NullMaterialCode_ThrowsException()
{
var dto = new FilterLocationDto
{
materialCode = null!
};
var exception = Assert.Throws<InvalidOperationException>(() =>
_storeTaskBusiness.PublicValidateFilterLocationParams(dto));
Assert.Contains("物料编号不允许为 NULL", exception.Message);
}
[Fact]
public void ValidateFilterLocationParams_ValidParams_NoException()
{
var dto = new FilterLocationDto
{
materialCode = "MAT001"
};
var exception = Record.Exception(() =>
_storeTaskBusiness.PublicValidateFilterLocationParams(dto));
Assert.Null(exception);
}
#endregion
#region GenerateTaskCode 测试
[Fact]
public void GenerateTaskCode_ReturnsCorrectFormat()
{
var taskCode = _storeTaskBusiness.PublicGenerateTaskCode();
Assert.NotNull(taskCode);
Assert.Equal(18, taskCode.Length);
Assert.True(long.TryParse(taskCode[..14], out _));
Assert.True(int.TryParse(taskCode[14..], out var randomPart));
Assert.InRange(randomPart, 1000, 9999);
}
[Fact]
public void GenerateTaskCode_MultipleCalls_GeneratesUniqueCodes()
{
var codes = new HashSet<string>();
for (int i = 0; i < 100; i++)
{
codes.Add(_storeTaskBusiness.PublicGenerateTaskCode());
}
Assert.Equal(100, codes.Count);
}
#endregion
#region CreateTask 测试
[Fact]
public void CreateTask_ValidInput_ReturnsSuccessResult()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
materialBarcode = "MAT001BAR",
palletBarcode = "PLT001",
amount = 100,
startPoint = "START",
endPoint = "END",
taskType = TaskTypeEnum.InStore,
taskCategory = TaskCategoryEnum.Material
};
var pathDetails = new List<BasePathDetails>
{
new BasePathDetails
{
objId = 1,
pathCode = "PATH1",
startPoint = "START",
endPoint = "MID",
deviceType = 0
},
new BasePathDetails
{
objId = 2,
pathCode = "PATH2",
startPoint = "MID",
endPoint = "END",
deviceType = 0
}
};
var pathInfo = new BasePathInfo
{
objId = 1,
pathCode = "MAIN_PATH",
pathName = "主输送线",
pathType = 1,
pathCategory = 1,
startPoint = "START",
endPoint = "END",
pathDetails = pathDetails
};
_mockBasePathInfoService
.Setup(x => x.GetBasePathInfo(It.IsAny<System.Linq.Expressions.Expression<Func<BasePathInfo, bool>>>()))
.Returns(new List<BasePathInfo> { pathInfo });
var result = _storeTaskBusiness.CreateTask(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.NotNull(result.data);
Assert.NotNull(result.data.taskCode);
Assert.Equal(2, result.data.taskDetails.Count);
Assert.Equal(2, result.data.taskQueue.taskSteps);
}
[Fact]
public void CreateTask_PathNotFound_ReturnsErrorResult()
{
var dto = new CreateTaskDto
{
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = "INVALID",
endPoint = "INVALID",
taskType = TaskTypeEnum.InStore,
taskCategory = TaskCategoryEnum.Material
};
_mockBasePathInfoService
.Setup(x => x.GetBasePathInfo(It.IsAny<System.Linq.Expressions.Expression<Func<BasePathInfo, bool>>>()))
.Returns(new List<BasePathInfo>());
var result = _storeTaskBusiness.CreateTask(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.Contains("输送路径为 NULL", result.msg);
}
#endregion
#region FilterLocation 测试
[Fact]
public void FilterLocation_ValidInput_ReturnsSuccessResult()
{
var dto = new FilterLocationDto
{
materialCode = "MAT001",
taskType = TaskTypeEnum.InStore,
taskCategory = TaskCategoryEnum.Material
};
var locationInfos = new List<BaseLocationInfo>
{
new BaseLocationInfo
{
locationCode = "LOC001",
locationRows = 1,
locationColumns = 1,
locationLayers = 1,
locationStatus = 0,
materialCode = "MAT001",
isFlag = 1
}
};
var storeInfo = new BaseStoreInfo
{
storeCode = "STORE001",
storeName = "测试仓库",
storeType = 1,
isFlag = 1,
locationInfos = locationInfos
};
_mockBaseStoreInfoService
.Setup(x => x.GetBasePathInfo(
It.IsAny<System.Linq.Expressions.Expression<Func<BaseStoreInfo, bool>>>(),
It.IsAny<System.Linq.Expressions.Expression<Func<BaseLocationInfo, bool>>>()))
.Returns(new List<BaseStoreInfo> { storeInfo });
var result = _storeTaskBusiness.FilterLocation(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.NotNull(result.data);
Assert.NotNull(result.data.storeInfo);
Assert.NotNull(result.data.locationInfo);
Assert.Single(result.data.locationInfos);
}
[Fact]
public void FilterLocation_NoAvailableStore_ReturnsErrorResult()
{
var dto = new FilterLocationDto
{
materialCode = "MAT001",
taskType = TaskTypeEnum.InStore,
taskCategory = TaskCategoryEnum.Material
};
_mockBaseStoreInfoService
.Setup(x => x.GetBasePathInfo(
It.IsAny<System.Linq.Expressions.Expression<Func<BaseStoreInfo, bool>>>(),
It.IsAny<System.Linq.Expressions.Expression<Func<BaseLocationInfo, bool>>>()))
.Returns(new List<BaseStoreInfo>());
var result = _storeTaskBusiness.FilterLocation(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.Contains("未获取到可用仓库", result.msg);
}
#endregion
#region SaveTask 测试
[Fact]
public void SaveTask_ValidInput_ReturnsSuccessResult()
{
var dto = new SaveTaskDto
{
taskQueue = new LiveTaskQueue
{
taskCode = "TASK001",
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = "A",
endPoint = "B",
taskType = 1,
taskCategory = 1
}
};
_mockLiveTaskQueueService
.Setup(x => x.InsertTaskQueue(It.IsAny<LiveTaskQueue>()))
.Returns(true);
var result = _storeTaskBusiness.SaveTask(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.NotNull(result.data);
Assert.True(result.data.isRes);
}
[Fact]
public void SaveTask_InsertFails_ReturnsFalse()
{
var dto = new SaveTaskDto
{
taskQueue = new LiveTaskQueue
{
taskCode = "TASK001",
materialCode = "MAT001",
palletBarcode = "PLT001",
startPoint = "A",
endPoint = "B",
taskType = 1,
taskCategory = 1
}
};
_mockLiveTaskQueueService
.Setup(x => x.InsertTaskQueue(It.IsAny<LiveTaskQueue>()))
.Returns(false);
var result = _storeTaskBusiness.SaveTask(dto);
Assert.Equal(BusinessStatusEnum., result.code);
Assert.NotNull(result.data);
Assert.False(result.data.isRes);
}
#endregion
#region GetTaskSuccessMessage 测试
[Fact]
public void GetTaskSuccessMessage_ReturnsCorrectMessage()
{
var message = _storeTaskBusiness.PublicGetTaskSuccessMessage(
"TASK001",
"主输送线",
TaskTypeEnum.InStore,
TaskCategoryEnum.Material);
Assert.Equal("包材入库任务创建成功:TASK001;关联路径:主输送线", message);
}
[Fact]
public void GetTaskSuccessMessage_ProductOutStore_ReturnsCorrectMessage()
{
var message = _storeTaskBusiness.PublicGetTaskSuccessMessage(
"TASK002",
"成品出库线",
TaskTypeEnum.OutStore,
TaskCategoryEnum.Product);
Assert.Equal("成品出库任务创建成功:TASK002;关联路径:成品出库线", message);
}
#endregion
}

@ -1,64 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business.InStore
* 6D5BA916-0FBB-4B9D-BBE9-692F39B7F962
*
* WenJY
*
* 2026-05-07 08:48:17
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Util;
namespace Sln.Wcs.Business;
public abstract class BaseBusiness:EntityWrapper
{
/// <summary>
/// 校验物料
/// </summary>
/// <param name="validateMaterialDto"></param>
/// <returns></returns>
public abstract ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto);
/// <summary>
/// 创建任务
/// </summary>
/// <param name="taskDto"></param>
public abstract CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto );
/// <summary>
/// 筛选目标库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
public abstract FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto);
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public abstract SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto);
}

@ -1,203 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* A6C78343-F3B7-49DB-A582-768186595E02
*
* WenJY
*
* 2026-05-06 18:13:10
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.InStore;
/// <summary>
/// 包材入库
/// </summary>
public class MaterialInStore:BaseBusiness
{
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public MaterialInStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"托盘条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.InStore;
createTaskDto.taskCategory = TaskCategoryEnum.Material;
//获取包材入库路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"包材入库输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"包材入库任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Material;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 0 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -1,199 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* B0E9FC96-6FA3-48E1-9BD9-9CF0360B168D
*
* WenJY
*
* 2026-05-06 18:15:32
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.InStore;
public class PalletInStore:BaseBusiness
{private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public PalletInStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"托盘条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.InStore;
createTaskDto.taskCategory = TaskCategoryEnum.Pallet;
//获取托盘入库路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"托盘入库输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"托盘入库任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Material;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 0 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -1,200 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* 1DC1227B-C3E0-4E56-803E-0C42C7065515
*
* WenJY
*
* 2026-05-06 18:13:44
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.InStore;
public class ProductInStore:BaseBusiness
{
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public ProductInStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"成品条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.InStore;
createTaskDto.taskCategory = TaskCategoryEnum.Product;
//获取成品入库路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"成品入库输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"成品入库任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Material;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 0 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -1,203 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* F9D6319A-1B6A-4036-A197-6D5EAE31D711
*
* WenJY
*
* 2026-05-06 18:13:28
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.OutStore;
/// <summary>
/// 包材出库
/// </summary>
public class MaterialOutStore:BaseBusiness
{
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public MaterialOutStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"托盘条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.OutStore;
createTaskDto.taskCategory = TaskCategoryEnum.Material;
//获取包材出库路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"包材出库输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"包材出库任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Material;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 1 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -1,200 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* 1377DAE2-C6B2-4B2D-A553-905D3588649F
*
* WenJY
*
* 2026-05-06 18:15:46
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.OutStore;
public class PalletOutStore:BaseBusiness
{
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public PalletOutStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"托盘条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.OutStore;
createTaskDto.taskCategory = TaskCategoryEnum.Material;
//获取托盘出库路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"托盘出库输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"托盘出库任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Pallet;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 1 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -1,200 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.Business
* CA9C52F5-4F55-406E-BD31-EF2856EB75DE
*
* WenJY
*
* 2026-05-06 18:14:10
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.Domain.Dto.ValidateMaterial;
using Sln.Wcs.Business.Domain.Enum;
using Sln.Wcs.Business.Domain.Model.CreateTask;
using Sln.Wcs.Business.Domain.Model.FilterLocation;
using Sln.Wcs.Business.Domain.Model.SaveTask;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Business.OutStore;
public class ProductOutStore:BaseBusiness
{
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
public ProductOutStore(IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService)
{
_basePathInfoService = basePathInfoService;
_liveTaskQueueService = liveTaskQueueService;
_baseStoreInfoService = baseStoreInfoService;
}
public override ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto)
{
throw new NotImplementedException();
}
/// <summary>
/// 创建任务
/// </summary>
/// <param name="createTaskDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto)
{
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
#region CreateTaskDto 参数校验
if (string.IsNullOrEmpty(createTaskDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.palletBarcode))
{
throw new InvalidOperationException($"托盘条码不允许为 NULL");
}
if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint))
{
throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL");
}
#endregion
createTaskDto.taskType = TaskTypeEnum.OutStore;
createTaskDto.taskCategory = TaskCategoryEnum.Material;
//获取托盘成品路径
Expression<Func<BasePathInfo, bool>> exp = x=>x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory;
BasePathInfo pathInfo = _basePathInfoService.GetBasePathInfo(exp).FirstOrDefault() ?? throw new InvalidOperationException($"托盘成品输送路径为 NULL");
#region 路径转为任务
string taskCode = "2026050700001"; //需根据现场实际定义生成规则
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails.Select( item => base.LiveTaskDetailWrapper(taskCode,createTaskDto,item)).ToList();
var taskQueue = base.LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo);
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
#endregion
resultDto.code = BusinessStatusEnum.;
resultDto.msg = $"托盘成品任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
taskQueue = taskQueue,
taskDetails = taskDetails,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 筛选库位
/// </summary>
/// <param name="filterLocationDto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto)
{
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
#region 参数校验
if (string.IsNullOrEmpty(filterLocationDto.materialCode))
{
throw new InvalidOperationException($"物料编号不允许为 NULL");
}
#endregion
Expression<Func<BaseStoreInfo,bool>> storeWhere = x => x.storeType == (int)StoreTypeEnum.Product;
Expression<Func<BaseLocationInfo,bool>> locationWhere = x=>x.materialCode==filterLocationDto.materialCode && x.locationStatus == 1 && x.isFlag == 1;
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere,locationWhere);
//先对仓库进行排序
BaseStoreInfo? storeInfo = storeInfos.Where(s => s.locationInfos.Count > 0).OrderBy(x=>x.storeCode).FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库");
BaseLocationInfo? locationInfo = storeInfo.locationInfos.OrderBy(x => x.locationRows).ThenBy(x=>x.locationColumns).ThenBy(x=>x.locationLayers).FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位");
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new FilterLocationResultModel()
{
storeInfo = storeInfo,
locationInfos = storeInfo.locationInfos,
locationInfo = locationInfo,
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
/// <summary>
/// 保存任务
/// </summary>
/// <param name="saveTaskDto"></param>
/// <returns></returns>
public override SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto)
{
SaveTaskResultDto resultDto = new SaveTaskResultDto();
try
{
var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue);
resultDto.code = BusinessStatusEnum.;
resultDto.msg = "执行完成";
resultDto.data = new SaveTaskResultModel()
{
isRes = inRes
};
}
catch (Exception e)
{
resultDto.code = BusinessStatusEnum.;
resultDto.msg = e.Message;
}
return resultDto;
}
}

@ -44,9 +44,9 @@ namespace Sln.Wcs.Business;
/// </summary>
public class StoreTaskBusiness : EntityWrapper
{
protected readonly IBasePathInfoService _basePathInfoService;
protected readonly ILiveTaskQueueService _liveTaskQueueService;
protected readonly IBaseStoreInfoService _baseStoreInfoService;
private readonly IBasePathInfoService _basePathInfoService;
private readonly ILiveTaskQueueService _liveTaskQueueService;
private readonly IBaseStoreInfoService _baseStoreInfoService;
/// <summary>
/// 构造函数
@ -83,16 +83,12 @@ public class StoreTaskBusiness : EntityWrapper
CreateTaskResultDto resultDto = new CreateTaskResultDto();
try
{
// 1. 参数校验(可扩展)
ValidateCreateTaskParams(createTaskDto);
// 2. 获取输送路径
BasePathInfo pathInfo = GetPathInfo(createTaskDto, createTaskDto.taskType, createTaskDto.taskCategory);
BasePathInfo pathInfo = GetPathInfo(createTaskDto);
// 4. 生成任务编号
string taskCode = GenerateTaskCode();
// 5. 路径转为任务
List<LiveTaskDetail> taskDetails = pathInfo.pathDetails
.Select(item => LiveTaskDetailWrapper(taskCode, createTaskDto, item))
.ToList();
@ -101,9 +97,8 @@ public class StoreTaskBusiness : EntityWrapper
taskQueue.taskSteps = taskDetails.Count;
taskQueue.taskDetails = taskDetails;
// 6. 返回结果
resultDto.code = Domain.Enum.BusinessStatusEnum.;
resultDto.msg = GetTaskSuccessMessage(taskCode, pathInfo.pathName, createTaskDto.taskType, createTaskDto.taskCategory);
resultDto.msg = $"{GetCategoryName(createTaskDto.taskCategory)}{GetTaskTypeName(createTaskDto.taskType)}任务创建成功:{taskCode};关联路径:{pathInfo.pathName}";
resultDto.data = new CreateTaskResultModel()
{
taskCode = taskCode,
@ -128,20 +123,15 @@ public class StoreTaskBusiness : EntityWrapper
FilterLocationResultDto resultDto = new FilterLocationResultDto();
try
{
// 1. 参数校验(可扩展)
ValidateFilterLocationParams(filterLocationDto);
// 2. 获取库位状态(入库:未使用=0出库已使用=1
int locationStatus = filterLocationDto.taskType == TaskTypeEnum.InStore ? 0 : 1;
// 3. 构建查询条件
Expression<Func<BaseStoreInfo, bool>> storeWhere = GetStoreWhere(filterLocationDto.taskType, filterLocationDto.taskCategory);
Expression<Func<BaseLocationInfo, bool>> locationWhere = GetLocationWhere(filterLocationDto, locationStatus);
// 4. 查询仓库和库位
List<BaseStoreInfo> storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere, locationWhere);
// 5. 选择最优仓库和库位
BaseStoreInfo? storeInfo = storeInfos
.Where(s => s.locationInfos.Count > 0)
.OrderBy(x => x.storeCode)
@ -235,16 +225,16 @@ public class StoreTaskBusiness : EntityWrapper
/// <summary>
/// 获取路径信息(可被子类重写定制路径查询逻辑)
/// </summary>
protected virtual BasePathInfo GetPathInfo(CreateTaskDto createTaskDto, TaskTypeEnum taskType, TaskCategoryEnum taskCategory)
protected virtual BasePathInfo GetPathInfo(CreateTaskDto createTaskDto)
{
Expression<Func<BasePathInfo, bool>> exp = x =>
x.startPoint == createTaskDto.startPoint &&
x.endPoint == createTaskDto.endPoint &&
x.pathType == (int)taskType &&
x.pathCategory == (int)taskCategory;
x.pathType == (int)createTaskDto.taskType &&
x.pathCategory == (int)createTaskDto.taskCategory;
return _basePathInfoService.GetBasePathInfo(exp)
.FirstOrDefault() ?? throw new InvalidOperationException($"{GetCategoryName(taskCategory)}{GetTaskTypeName(taskType)}输送路径为 NULL");
.FirstOrDefault() ?? throw new InvalidOperationException($"{GetCategoryName(createTaskDto.taskCategory)}{GetTaskTypeName(createTaskDto.taskType)}输送路径为 NULL");
}
/// <summary>
@ -252,15 +242,7 @@ public class StoreTaskBusiness : EntityWrapper
/// </summary>
protected virtual string GenerateTaskCode()
{
return DateTime.Now.ToString("yyyyMMddHHmmss") + new Random().Next(1000, 9999);
}
/// <summary>
/// 获取任务成功的消息(可被子类重写)
/// </summary>
protected virtual string GetTaskSuccessMessage(string taskCode, string pathName, TaskTypeEnum taskType, TaskCategoryEnum taskCategory)
{
return $"{GetCategoryName(taskCategory)}{GetTaskTypeName(taskType)}任务创建成功:{taskCode};关联路径:{pathName}";
return DateTime.Now.ToString("yyyyMMddHHmmss") + new Random().Next(10, 99);
}
/// <summary>
@ -283,12 +265,10 @@ public class StoreTaskBusiness : EntityWrapper
#endregion
#region 辅助方法
/// <summary>
/// 获取分类名称
/// </summary>
protected string GetCategoryName(TaskCategoryEnum taskCategory)
private string GetCategoryName(TaskCategoryEnum taskCategory)
{
return taskCategory switch
{
@ -302,7 +282,7 @@ public class StoreTaskBusiness : EntityWrapper
/// <summary>
/// 获取任务类型名称
/// </summary>
protected string GetTaskTypeName(TaskTypeEnum taskType)
private string GetTaskTypeName(TaskTypeEnum taskType)
{
return taskType switch
{
@ -311,6 +291,4 @@ public class StoreTaskBusiness : EntityWrapper
_ => "未知"
};
}
#endregion
}

@ -1,6 +1,5 @@
using Sln.Wcs.HikRoBotApi.Domain.Dto.CancelTask;
using Sln.Wcs.HikRoBotApi.Domain.Dto.ContinueTask;
using Sln.Wcs.HikRoBotApi.Domain.Dto.GenAgvSchedulingTask;
using Sln.Wcs.HikRoBotApi.Enum;
using Sln.Wcs.HikRoBotApi.Util;
using Sln.Wcs.HikRoBotSdk;
@ -10,6 +9,9 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Sln.Wcs.HikRoBotSdk.Dto.GenAgvSchedulingTask;
using GenAgvSchedulingTaskDto = Sln.Wcs.HikRoBotApi.Domain.Dto.GenAgvSchedulingTask.GenAgvSchedulingTaskDto;
using GenAgvSchedulingTaskResultDto = Sln.Wcs.HikRoBotApi.Domain.Dto.GenAgvSchedulingTask.GenAgvSchedulingTaskResultDto;
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
@ -65,10 +67,19 @@ namespace Sln.Wcs.HikRoBotApi.Service.Impl
throw new ArgumentException($"输入参数为空。");
}
// var data = new HikRoBotSdk.Dto.GenAgvSchedulingTask.GenAgvSchedulingTaskDto()
// {
// reqCode = genAgvSchedulingTask.reqCode,
// taskTyp = genAgvSchedulingTask.taskTyp,
// };
var data = new HikRoBotSdk.Dto.GenAgvSchedulingTask.GenAgvSchedulingTaskDto()
{
reqCode = genAgvSchedulingTask.reqCode,
taskTyp = genAgvSchedulingTask.taskTyp,
taskType = "PF-FMR-COMMON",
targetRoutes = new List<targetRoute>()
{
new targetRoute(){type = "STORAGE",code = "R5001A02011"},
new targetRoute(){type = "STORAGE",code = "R5001A01011"}
}
};
var resp = this.hikRoBotSdk.GenAgvSchedulingTask(data);
@ -83,8 +94,8 @@ namespace Sln.Wcs.HikRoBotApi.Service.Impl
{
code = resp.code,
message = resp.message,
reqCode = resp.reqCode,
data = resp.data
//reqCode = resp.reqCode,
//data = resp.data
},
};

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Flurl.Http;
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
@ -32,11 +33,10 @@ namespace Sln.Wcs.HikRoBotSdk.Config
public class HikRoBotConfig
{
public readonly string api = "";
public readonly string partnerId;
public readonly string accesskey;
public readonly string secretkey;
public readonly string version;
public readonly string test;
public readonly string contentType = "";
public readonly string userAgent="";
public readonly string xlrRequestId="";//随机生成
public readonly string xlrVersion="";
/// <summary>
/// 注入海康 SDK 配置参数
@ -45,36 +45,26 @@ namespace Sln.Wcs.HikRoBotSdk.Config
/// <exception cref="Exception"></exception>IConfiguration configuration
public HikRoBotConfig(IConfiguration configuration)
{
if (string.IsNullOrEmpty(configuration["sdk_api"]))
if (string.IsNullOrEmpty(configuration["HikRoBot_Url"]))
{
throw new Exception("sdk_api 配置不正确,请检查Apollo配置.");
throw new Exception("HikRoBot_Url 配置不正确,请检查Apollo配置.");
}
if (string.IsNullOrEmpty(configuration["sdk_json_str"]))
if (string.IsNullOrEmpty(configuration["HikRoBot_Content-Type"]))
{
throw new Exception("sdk_partner_id 配置不正确,请检查Apollo配置.");
throw new Exception("HikRoBot_Content-Type 配置不正确,请检查Apollo配置.");
}
//if (string.IsNullOrEmpty(configuration["sdk_accesskey"]))
//{
// throw new Exception("sdk_accesskey 配置不正确,请检查Apollo配置.");
//}
//if (string.IsNullOrEmpty(configuration["sdk_secretkey"]))
//{
// throw new Exception("sdk_secretkey 配置不正确,请检查Apollo配置.");
//}
//if (string.IsNullOrEmpty(configuration["sdk_partner_id"]))
//{
// throw new Exception("sdk_partner_id 配置不正确,请检查Apollo配置.");
//}
//if (string.IsNullOrEmpty(configuration["sdk_version"]))
//{
// throw new Exception("sdk_version 配置不正确,请检查Apollo配置.");
//}
api = configuration["sdk_json_str"];
//accesskey = configuration["sdk_accesskey"];
//secretkey = configuration["sdk_secretkey"];
//version = configuration["sdk_version"];
//test = configuration["sdk_test"];
if (string.IsNullOrEmpty(configuration["HikRoBot_User-Agent"]))
{
throw new Exception("HikRoBot_User-Agent 配置不正确,请检查Apollo配置.");
}
if (string.IsNullOrEmpty(configuration["HikRoBot_X-lr-version"]))
{
throw new Exception("HikRoBot_X-lr-version 配置不正确,请检查Apollo配置.");
}
api = configuration["HikRoBot_Url"];
contentType = configuration["HikRoBot_ContentType"];
userAgent = configuration["HikRoBot_User-Agent"];
xlrVersion = configuration["HikRoBot_X-lr-version"];
}
}

@ -30,129 +30,139 @@ namespace Sln.Wcs.HikRoBotSdk.Dto.GenAgvSchedulingTask
{
public class GenAgvSchedulingTaskDto
{
//这里写请求参数
/// <summary>
/// 请求编号,每个请求都要一个唯一编号, 同一个请求重复提交, 使用同一编号。;
/// </summary>
public string reqCode { get; set; }
public string taskType{get;set;}
public List<targetRoute> targetRoutes{get;set;}
// /// <summary>
// /// 请求编号,每个请求都要一个唯一编号, 同一个请求重复提交, 使用同一编号。;
// /// </summary>
// public string reqCode { get; set; }
//
// /// <summary>
// /// 请求时间截 格式: “yyyy-MM-dd HH:mm:ss”。
// /// </summary>
// public string reqTime { get; set; }
//
// /// <summary>
// /// 客户端编号如PDAHCWMS等。
// /// </summary>
// public string clientCode { get; set; }
//
// /// <summary>
// /// 令牌号, 由调度系统颁发
// /// </summary>
// public string tokenCode { get; set; }
//
// /// <summary>
// /// 任务类型,
// /// 业务流程
// /// 5层柜体来料验收拆分 柜体物料 提升机输送线对接位-验收拆分区 WMS F501 2
// /// 5层柜体来料入库 柜体物料 验收拆分区-原材料周转区 WMS F502 2
// /// 5层辅料立体库物料入库 辅料料箱 回转输送线回库口-辅料库货架 WMS F503 1
// /// 5层辅料立体库分拣出库 辅料料箱 辅料库货架-回转输送线出库口 WMS F504 1
// /// 5层辅料立体库分拣回库 辅料料箱 回转输送线回库口-辅料库货架 WMS F505 1
// /// 5层辅料配送流程 辅料料箱 物料分拣位-装配区领料工位 WMS F506 空值
// /// 5层背板安装区物料配送 柜体物料 原材料周转区-背板安装区 WMS F507 2
// /// 5层半成品下线 半成品柜 背板安装区-半成品周转区 WMS F508 2
// /// 5层半成品检验 半成品柜 半成品周转区-检测台 WMS F509 2
// /// 5层成品柜体入库 成品柜体 检验台-成品区 WMS F510 2
// /// 5层成品柜体出库 成品柜体 成品区-提升机输送线对接点 WMS F511 2
// /// </summary>
// public string taskTyp { get; set; }
//
// /// <summary>
// /// 容器类型(叉车/CTU专用叉车项目必传
// /// </summary>
// public string ctnrTyp { get; set; }
//
// /// <summary>
// /// 容器编号(叉车/CTU专用
// /// </summary>
// public string ctnrCode { get; set; }
//
// /// <summary>
// /// 容器数量叉车堆叠专用默认值1仅记录堆叠的数量不记录堆叠的每个容器号
// /// </summary>
// public string ctnrNum { get; set; }
//
// /// <summary>
// /// 任务模式 0-普通move 1-出库move 2-入库move 3-移库move
// /// </summary>
// public string taskMode { get; set; }
//
// /// <summary>
// /// 工作位一般为机台或工作台位置与RCS-2000端配置的位置名称一致, 工作位名称为字母\数字\或组合, 不超过32位。
// /// </summary>
// public string wbCode { get; set; }
//
// /// <summary>
// /// 位置路径AGV关键路径位置集合与任务类型中模板配置的位置路径一一对应。待现场地图部署、配置完成后可获取。
// /// </summary>
// public List<Position> positionCodePath { get; set; }
//
// /// <summary>
// /// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
// /// </summary>
// public string podDir { get; set; }
//
// /// <summary>
// /// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
// /// </summary>
// public string podTyp { get; set; }
//
// /// <summary>
// /// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
// /// </summary>
// public string podCode { get; set; }
//
// /// <summary>
// /// 物料批次或货架上的物料唯一编码,
// /// </summary>
// public string materialLot { get; set; }
//
// /// <summary>
// /// 物料类型, 仅移载机器人协议专用必填, 其它车型任务不填
// /// </summary>
// public string materialType { get; set; }
//
// /// <summary>
// /// 优先级1~127最大优先级最高。为空时采用任务模板的优先级。
// /// </summary>
// public string priority { get; set; }
//
// /// <summary>
// /// 任务单号,选填, 不填系统自动生成UUID小于等于64位
// /// </summary>
// public string taskCode { get; set; }
//
// /// <summary>
// /// AGV编号填写表示指定某一编号的AGV执行该任务
// /// </summary>
// public string agvCode { get; set; }
//
// /// <summary>
// /// 组编号
// /// </summary>
// public string groupId { get; set; }
//
// /// <summary>
// /// 设备类型
// /// </summary>
// public string agvTyp { get; set; }
//
// /// <summary>
// /// 区域/策略中挑选货架以及根据物料批次挑选货架时的先进先出规则
// /// </summary>
// public string positionSelStrategy { get; set; }
//
// public string data { get; set; }
}
/// <summary>
/// 请求时间截 格式: “yyyy-MM-dd HH:mm:ss”。
/// </summary>
public string reqTime { get; set; }
/// <summary>
/// 客户端编号如PDAHCWMS等。
/// </summary>
public string clientCode { get; set; }
/// <summary>
/// 令牌号, 由调度系统颁发
/// </summary>
public string tokenCode { get; set; }
/// <summary>
/// 任务类型,
/// 业务流程
/// 5层柜体来料验收拆分 柜体物料 提升机输送线对接位-验收拆分区 WMS F501 2
/// 5层柜体来料入库 柜体物料 验收拆分区-原材料周转区 WMS F502 2
/// 5层辅料立体库物料入库 辅料料箱 回转输送线回库口-辅料库货架 WMS F503 1
/// 5层辅料立体库分拣出库 辅料料箱 辅料库货架-回转输送线出库口 WMS F504 1
/// 5层辅料立体库分拣回库 辅料料箱 回转输送线回库口-辅料库货架 WMS F505 1
/// 5层辅料配送流程 辅料料箱 物料分拣位-装配区领料工位 WMS F506 空值
/// 5层背板安装区物料配送 柜体物料 原材料周转区-背板安装区 WMS F507 2
/// 5层半成品下线 半成品柜 背板安装区-半成品周转区 WMS F508 2
/// 5层半成品检验 半成品柜 半成品周转区-检测台 WMS F509 2
/// 5层成品柜体入库 成品柜体 检验台-成品区 WMS F510 2
/// 5层成品柜体出库 成品柜体 成品区-提升机输送线对接点 WMS F511 2
/// </summary>
public string taskTyp { get; set; }
/// <summary>
/// 容器类型(叉车/CTU专用叉车项目必传
/// </summary>
public string ctnrTyp { get; set; }
/// <summary>
/// 容器编号(叉车/CTU专用
/// </summary>
public string ctnrCode { get; set; }
/// <summary>
/// 容器数量叉车堆叠专用默认值1仅记录堆叠的数量不记录堆叠的每个容器号
/// </summary>
public string ctnrNum { get; set; }
/// <summary>
/// 任务模式 0-普通move 1-出库move 2-入库move 3-移库move
/// </summary>
public string taskMode { get; set; }
/// <summary>
/// 工作位一般为机台或工作台位置与RCS-2000端配置的位置名称一致, 工作位名称为字母\数字\或组合, 不超过32位。
/// </summary>
public string wbCode { get; set; }
/// <summary>
/// 位置路径AGV关键路径位置集合与任务类型中模板配置的位置路径一一对应。待现场地图部署、配置完成后可获取。
/// </summary>
public List<Position> positionCodePath { get; set; }
/// <summary>
/// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
/// </summary>
public string podDir { get; set; }
/// <summary>
/// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
/// </summary>
public string podTyp { get; set; }
/// <summary>
/// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下” ,不指定方向可以为空
/// </summary>
public string podCode { get; set; }
/// <summary>
/// 物料批次或货架上的物料唯一编码,
/// </summary>
public string materialLot { get; set; }
/// <summary>
/// 物料类型, 仅移载机器人协议专用必填, 其它车型任务不填
/// </summary>
public string materialType { get; set; }
/// <summary>
/// 优先级1~127最大优先级最高。为空时采用任务模板的优先级。
/// </summary>
public string priority { get; set; }
/// <summary>
/// 任务单号,选填, 不填系统自动生成UUID小于等于64位
/// </summary>
public string taskCode { get; set; }
/// <summary>
/// AGV编号填写表示指定某一编号的AGV执行该任务
/// </summary>
public string agvCode { get; set; }
/// <summary>
/// 组编号
/// </summary>
public string groupId { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public string agvTyp { get; set; }
/// <summary>
/// 区域/策略中挑选货架以及根据物料批次挑选货架时的先进先出规则
/// </summary>
public string positionSelStrategy { get; set; }
public string data { get; set; }
public class targetRoute
{
public string type{get;set;}
public string code{get;set;}
}
}

@ -43,14 +43,21 @@ namespace Sln.Wcs.HikRoBotSdk.Dto.GenAgvSchedulingTask
/// </summary>
public string message { get; set; }
public data data { get; set; }
/// <summary>
/// 请求编号
/// </summary>
public string reqCode { get; set; }
public string errorCode { get; set; }
/// <summary>
/// 自定义返回(返回任务单号)
/// </summary>
public string data { get; set; }
public bool success { get; set; }
}
public class data
{
public string robotTaskCode { get; set; }
}
}

@ -7,6 +7,7 @@ using Sln.Wcs.HikRoBotSdk.Dto.GenAgvSchedulingTask;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
@ -55,10 +56,15 @@ namespace Sln.Wcs.HikRoBotSdk
/// <returns></returns>
public GenAgvSchedulingTaskResultDto GenAgvSchedulingTask(GenAgvSchedulingTaskDto genAgvSchedulingTask)
{
string url = $"{hikRoBotConfig.api}/task/submit";
var request = url
.WithHeader("Content-Type", hikRoBotConfig.contentType)
.WithHeader("User-Agent",hikRoBotConfig.userAgent)
.WithHeader("X-lr-request-id", System.Guid.NewGuid().ToString("N"))
.WithHeader("X-lr-version", hikRoBotConfig.xlrVersion);
Console.WriteLine($"请求报文:{JsonConvert.SerializeObject(genAgvSchedulingTask)}");
return this.hikRoBotConfig.api.PostJsonAsync(genAgvSchedulingTask).Result.GetJsonAsync<GenAgvSchedulingTaskResultDto>().Result;
return request.PostJsonAsync(genAgvSchedulingTask).Result.GetJsonAsync<GenAgvSchedulingTaskResultDto>().Result;
}
/// <summary>

@ -155,7 +155,8 @@ public class LiveTaskQueue
/// <summary>
/// 明细集合
/// </summary>
/// </summary>x
[SugarColumn(IsIgnore = true)]
[Navigate(NavigateType.OneToMany, nameof(LiveTaskDetail.taskCode), nameof(taskCode))]
public List<LiveTaskDetail> taskDetails { get; set; }
}

@ -37,6 +37,7 @@ namespace Sln.Wcs.Repository
{
itenant = db.AsTenant(); //用来处理事务
base.Context = db.AsTenant().GetConnectionScopeWithAttr<T>(); //获取子Db
//base.Context = db.AsTenant().GetConnectionScope("core");
//如果不想通过注入多个仓储
//用到ChangeRepository或者Db.GetMyRepository需要看标题4写法

@ -23,6 +23,7 @@
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service.@base;
@ -31,4 +32,12 @@ namespace Sln.Wcs.Repository.service;
public interface ILiveTaskQueueService:IBaseService<LiveTaskQueue>
{
bool InsertTaskQueue(LiveTaskQueue taskQueue);
/// <summary>
/// 获取任务队列:关联任务明细
/// </summary>
/// <param name="taskWhere"></param>
/// <param name="detailWhere"></param>
/// <returns></returns>
List<LiveTaskQueue> getLiveTaskQueues(Expression<Func<LiveTaskQueue, bool>> exp);
}

@ -23,6 +23,7 @@
#endregion << 版 本 注 释 >>
using System.Linq.Expressions;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service.@base;
@ -56,4 +57,42 @@ public class LiveTaskQueueServiceImpl: BaseServiceImpl<LiveTaskQueue>, ILiveTask
}
return res;
}
public List<LiveTaskQueue> getLiveTaskQueues(Expression<Func<LiveTaskQueue, bool>> exp = null)
{
try
{
var res = _rep.Context.Queryable<LiveTaskQueue>()
.Includes(x => x.taskDetails) // 先加载所有
.Where(exp)
.ToList()
.Select(task => new LiveTaskQueue
{
objId = task.objId,
taskCode = task.taskCode,
materialCode = task.materialCode,
palletBarcode = task.palletBarcode,
materialBarcode = task.materialBarcode,
materialCount = task.materialCount,
taskType = task.taskType,
taskCategory = task.taskCategory,
startPoint = task.startPoint,
endPoint = task.endPoint,
pathCode = task.pathCode,
taskSteps = task.taskSteps,
isFlag = task.isFlag,
remark = task.remark,
taskDetails = task.taskDetails.AsQueryable()
//.Where(detailWhere) // 应用子表查询条件
.Where(p => p.isFlag == 1)
.ToList()
}).ToList();
return res;
}
catch (Exception ex)
{
throw new InvalidOperationException($"通过导航查询方式获取任务信息及下属参数执行异常:{ex.Message}");
}
}
}

@ -1,13 +0,0 @@
namespace Sln.Wcs.Strategy;
/// <summary>
/// 任务执行策略接口 - 从任务队列中取出待执行任务,根据设备类型下发到对应 SDK
/// </summary>
public interface ITaskExecuteStrategy
{
/// <summary>
/// 执行一轮任务调度:查询待执行任务,按设备类型下发
/// </summary>
/// <returns>本次下发的任务数量</returns>
Task<int> ExecuteAsync();
}

@ -0,0 +1,175 @@
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
using Sln.Wcs.Serilog;
namespace Sln.Wcs.Strategy;
public class MaterialStrategy
{
private readonly SerilogHelper _logger;
private readonly ILiveTaskQueueService _taskQueueService;
private readonly ILiveTaskDetailService _taskDetailService;
private CancellationTokenSource? _cts;
private bool _isRunning;
public MaterialStrategy(
SerilogHelper logger,
ILiveTaskQueueService taskQueueService,
ILiveTaskDetailService taskDetailService)
{
_logger = logger;
_taskQueueService = taskQueueService;
_taskDetailService = taskDetailService;
}
public void Run()
{
_logger.Info("包材任务调度就绪,输入 start 启动stop 停止quit 退出");
while (true)
{
var input = Console.ReadLine()?.Trim().ToLower();
switch (input)
{
case "start":
Start();
break;
case "stop":
Stop();
break;
case "quit":
Stop();
return;
default:
_logger.Info("未知指令,可用: start | stop | quit");
break;
}
}
}
private void Start()
{
if (_isRunning)
{
_logger.Info("调度已在运行中");
return;
}
_cts = new CancellationTokenSource();
_isRunning = true;
Task.Run(() => SchedulingLoop(_cts.Token));
_logger.Info("调度已启动");
}
private void Stop()
{
if (!_isRunning)
{
_logger.Info("调度未在运行");
return;
}
_cts?.Cancel();
_isRunning = false;
_logger.Info("调度已停止");
}
private void SchedulingLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
var taskQueues = _taskQueueService.getLiveTaskQueues(x =>
x.taskCategory == 1 && x.taskStatus == 1);
_logger.Info($"查询待执行包材任务,共 {taskQueues.Count} 条");
if (taskQueues.Count > 0)
{
Parallel.ForEach(taskQueues, task =>
{
ProcessTask(task, ct);
});
}
Thread.Sleep(1000);
}
_logger.Info("调度循环已退出");
}
private void ProcessTask(LiveTaskQueue task, CancellationToken ct)
{
if (ct.IsCancellationRequested) return;
_logger.Info($"开始执行任务 {task.taskCode},子任务数 {task.taskDetails.Count}");
task.taskStatus = 2;
_taskQueueService.Update(task);
foreach (var detail in task.taskDetails.OrderBy(x => x.objId))
{
if (ct.IsCancellationRequested)
{
_logger.Info($"任务 {task.taskCode} 被中断,当前步骤 {detail.objId} 未执行");
return;
}
_logger.Info($"子任务 {task.taskCode}-{detail.objId},设备类型 {detail.deviceType}");
if (detail.taskStatus == 2 || detail.taskStatus == 3)
{
_logger.Info($"子任务 {task.taskCode}-{detail.objId},已下发,不再重复下发");
continue;
}
var success = detail.deviceType switch
{
1 => DispatchToAgv(detail),
2 => DispatchToHoist(detail),
_ => true
};
if (success)
{
detail.taskStatus = 2;
_taskDetailService.Update(detail);
_logger.Info($"子任务 {task.taskCode}-{detail.objId} 下发成功");
}
else
{
_logger.Error($"子任务 {task.taskCode}-{detail.objId} 下发失败,中断后续步骤");
break;
}
}
if (ct.IsCancellationRequested) return;
task.taskStatus = 3;
_taskQueueService.Update(task);
_logger.Info($"任务 {task.taskCode} 执行完成");
}
private bool DispatchToAgv(LiveTaskDetail detail)
{
if (detail.taskCode == "2026051816004580")
{
Task.Delay(1000 * 3).Wait();
}
_logger.Info($"AGV 下发: {detail.taskCode}-{detail.objId},起点 {detail.startPoint} → 终点 {detail.endPoint}");
return true;
}
private bool DispatchToHoist(LiveTaskDetail detail)
{
if (detail.taskCode == "2026050700001")
{
Task.Delay(1000 * 3).Wait();
}
_logger.Info($"提升机下发: {detail.taskCode}-{detail.objId},起点 {detail.startPoint} → 终点 {detail.endPoint}");
return true;
}
}

@ -9,8 +9,8 @@
<ItemGroup>
<ProjectReference Include="..\Sln.Wcs.Model\Sln.Wcs.Model.csproj" />
<ProjectReference Include="..\Sln.Wcs.Repository\Sln.Wcs.Repository.csproj" />
<ProjectReference Include="..\Sln.Wcs.HikRoBotSdk\Sln.Wcs.HikRoBotSdk.csproj" />
<ProjectReference Include="..\Sln.Wcs.HoistSdk\Sln.Wcs.HoistSdk.csproj" />
<ProjectReference Include="..\Sln.Wcs.HikRoBotApi\Sln.Wcs.HikRoBotApi.csproj" />
<ProjectReference Include="..\Sln.Wcs.HoistApi\Sln.Wcs.HoistApi.csproj" />
</ItemGroup>
</Project>

@ -1,169 +0,0 @@
using Sln.Wcs.HikRoBotSdk;
using Sln.Wcs.HikRoBotSdk.Dto.GenAgvSchedulingTask;
using Sln.Wcs.HoistSdk;
using Sln.Wcs.HoistSdk.Dto.HoistTaskExecutor;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository.service;
namespace Sln.Wcs.Strategy;
/// <summary>
/// 任务执行策略 - 轮询数据库中待执行的任务,根据设备类型调用对应 SDK 下发
/// </summary>
public class TaskExecuteStrategy : ITaskExecuteStrategy
{
private readonly ILiveTaskQueueService _taskQueueService;
private readonly ILiveTaskDetailService _taskDetailService;
private readonly IHIKRoBotSdk _hikRobotSdk;
private readonly IHoistSdk _hoistSdk;
public TaskExecuteStrategy(
ILiveTaskQueueService taskQueueService,
ILiveTaskDetailService taskDetailService,
IHIKRoBotSdk hikRobotSdk,
IHoistSdk hoistSdk)
{
_taskQueueService = taskQueueService;
_taskDetailService = taskDetailService;
_hikRobotSdk = hikRobotSdk;
_hoistSdk = hoistSdk;
}
/// <summary>
/// 执行一轮任务调度:查询所有待执行任务,按设备类型下发
/// </summary>
public Task<int> ExecuteAsync()
{
return Task.Run(() =>
{
// 1. 查询所有待执行的任务队列task_status = 1
var pendingTasks = _taskQueueService.Query(x => x.taskStatus == 1);
if (pendingTasks.Count == 0)
return 0;
int dispatchedCount = 0;
foreach (var task in pendingTasks)
{
try
{
// 2. 查询任务明细
var details = _taskDetailService.Query(x => x.taskCode == task.taskCode);
if (details.Count == 0)
continue;
// 3. 取第一个未执行的明细步骤
var currentDetail = details
.Where(x => x.taskStatus == 1)
.OrderBy(x => x.objId)
.FirstOrDefault();
if (currentDetail == null)
continue;
// 4. 根据设备类型下发任务
var success = DispatchByDeviceType(currentDetail);
if (success)
{
// 5. 更新明细状态为执行中
currentDetail.taskStatus = 2;
_taskDetailService.Update(currentDetail);
// 6. 更新队列状态为执行中
task.taskStatus = 2;
_taskQueueService.Update(task);
dispatchedCount++;
}
}
catch (Exception ex)
{
Console.WriteLine($"任务 {task.taskCode} 下发失败: {ex.Message}");
}
}
return dispatchedCount;
});
}
/// <summary>
/// 根据设备类型分发到对应 SDK
/// </summary>
private bool DispatchByDeviceType(LiveTaskDetail detail)
{
return detail.deviceType switch
{
1 => DispatchToAgv(detail),
2 => DispatchToHoist(detail),
_ => throw new NotSupportedException($"不支持的设备类型: {detail.deviceType}")
};
}
/// <summary>
/// 下发 AGV 任务(海康机器人 SDK
/// </summary>
private bool DispatchToAgv(LiveTaskDetail detail)
{
var dto = new GenAgvSchedulingTaskDto
{
reqCode = detail.taskCode,
reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
clientCode = "WCS",
taskCode = detail.taskCode,
taskTyp = detail.taskType switch
{
1 => "1", // 入库
2 => "2", // 出库
_ => "0"
},
taskMode = detail.taskType switch
{
1 => "2", // 入库 move
2 => "1", // 出库 move
_ => "0"
},
wbCode = detail.startPoint,
ctnrCode = detail.palletBarcode,
materialLot = detail.materialBarcode,
positionCodePath = new List<Position>
{
new() { positionCode = detail.startPoint, type = "00" },
new() { positionCode = detail.endPoint, type = "00" }
}
};
var result = _hikRobotSdk.GenAgvSchedulingTask(dto);
return result.code == "0";
}
/// <summary>
/// 下发提升机任务Hoist SDK
/// </summary>
private bool DispatchToHoist(LiveTaskDetail detail)
{
var dto = new HoistTaskExeDto
{
hoistCode = detail.startPoint,
taskCode = detail.taskCode,
startPoint = ParseIntPoint(detail.startPoint),
endPoint = ParseIntPoint(detail.endPoint)
};
var result = _hoistSdk.HoistTaskExecutor(dto);
return result.code == "0";
}
/// <summary>
/// 将位置字符串转为整数楼层/层号
/// </summary>
private static int ParseIntPoint(string? point)
{
if (string.IsNullOrEmpty(point))
return 0;
return int.TryParse(point, out var val) ? val : 0;
}
}

@ -28,8 +28,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Wcs.Business", "Sln.Wcs
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Wcs.Strategy", "Sln.Wcs.Strategy\Sln.Wcs.Strategy.csproj", "{F7658F97-F78A-4612-A1A5-490F2CDE49DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sln.Wcs.Business.Tests", "Sln.Wcs.Business.Tests\Sln.Wcs.Business.Tests.csproj", "{0911EA85-F152-453E-BB7D-4C7079361443}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -88,10 +86,6 @@ Global
{F7658F97-F78A-4612-A1A5-490F2CDE49DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7658F97-F78A-4612-A1A5-490F2CDE49DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7658F97-F78A-4612-A1A5-490F2CDE49DD}.Release|Any CPU.Build.0 = Release|Any CPU
{0911EA85-F152-453E-BB7D-4C7079361443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0911EA85-F152-453E-BB7D-4C7079361443}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0911EA85-F152-453E-BB7D-4C7079361443}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0911EA85-F152-453E-BB7D-4C7079361443}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -23,18 +23,19 @@
#endregion << 版 本 注 释 >>
using Sln.Wcs.Business;
using Sln.Wcs.Business.Domain.Dto.CreateTask;
using Sln.Wcs.Business.Domain.Dto.FilterLocation;
using Sln.Wcs.Business.Domain.Dto.SaveTask;
using Sln.Wcs.Business.InStore;
using Sln.Wcs.Business.Domain.Enum;
namespace Sln.Wcs;
public class MaterialInStoreTest
{
private readonly MaterialInStore _service;
private readonly StoreTaskBusiness _service;
public MaterialInStoreTest(MaterialInStore service)
public MaterialInStoreTest(StoreTaskBusiness service)
{
_service = service;
}
@ -47,22 +48,31 @@ public class MaterialInStoreTest
palletBarcode = "20260507000001"
});
var info = _service.CreateTask(new CreateTaskDto()
for (int i = 0; i < 10; i++)
{
materialCode = "20260507000001",
materialBarcode = "20260507000001",
palletBarcode = "20260507000001",
amount = 1,
startPoint = "13#_L1_01",
endPoint = "15#_L3_03",
});
var materialBarcode = $"2026050700000{i + 1}";
var palletBarcode = $"PALLET{i + 1:D2}";
var res = _service.SaveTask(new SaveTaskDto()
{
taskCode = info.data.taskCode,
taskQueue = info.data.taskQueue,
taskDetails = info.data.taskDetails,
});
var info = _service.CreateTask(new CreateTaskDto()
{
materialCode = "20260507000001",
materialBarcode = materialBarcode,
palletBarcode = palletBarcode,
amount = 1,
startPoint = "13#_L1_01",
endPoint = "15#_L3_03",
taskCategory = TaskCategoryEnum.Material,
taskType = TaskTypeEnum.InStore
});
_service.SaveTask(new SaveTaskDto()
{
taskCode = info.data.taskCode,
taskQueue = info.data.taskQueue,
taskDetails = info.data.taskDetails,
});
Console.WriteLine($"[MaterialInStoreTest] 第 {i + 1} 条任务创建完成: {info.data.taskCode}");
}
}
}

@ -1,11 +1,17 @@
using System.Reflection;
using Com.Ctrip.Framework.Apollo;
using Flurl.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NeoSmart.Caching.Sqlite;
using Sln.Wcs.HikRoBotApi.Domain.Dto.GenAgvSchedulingTask;
using Sln.Wcs.HikRoBotApi.Service;
using Sln.Wcs.HikRoBotApi.Service.Impl;
using Sln.Wcs.Repository;
using Sln.Wcs.Serilog;
using Sln.Wcs.Plc;
using Sln.Wcs.Strategy;
using ZiggyCreatures.Caching.Fusion;
using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson;
@ -16,6 +22,11 @@ namespace Sln.Wcs
static async Task Main(string[] args)
{
TimeZoneInfo chinaZone = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
DateTimeOffset utcNow = DateTimeOffset.UtcNow;
DateTimeOffset beijingTime = TimeZoneInfo.ConvertTime(utcNow, chinaZone);
string beijingTimeString = beijingTime.ToString("yyyy-MM-dd HH:mm");
Console.WriteLine(beijingTimeString);
var services = new ServiceCollection();
ConfigureServices(services);
@ -28,6 +39,20 @@ namespace Sln.Wcs
log.Info($"系统启动成功,日志存放位置:{config["logPath"]}");
// MaterialInStoreTest? service = serviceProvider.GetService<MaterialInStoreTest>();
// service?.Run();
//禁用 SSL
FlurlHttp.ConfigureClientForUrl("https://172.16.12.11")
.ConfigureInnerHandler(handler =>
{
handler.ServerCertificateCustomValidationCallback = (_, _, _, _) => true;
});
// var service = serviceProvider.GetService<HikRoBotService>();
// var res = service.GetGenAgvSchedulingTask(new GenAgvSchedulingTaskDto());
Task.Delay(-1).Wait();
}
private static void ConfigureServices(IServiceCollection services)
@ -46,6 +71,7 @@ namespace Sln.Wcs
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistSdk.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Plc.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Business.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Strategy.dll")),
};
services.Scan(scan => scan.FromAssemblies(assemblies)
@ -55,6 +81,8 @@ namespace Sln.Wcs
.WithTransientLifetime());
services.AddSingleton(typeof(SerilogHelper));
services.AddSingleton(typeof(MaterialInStoreTest));
services.AddSqlSugarSetup();

@ -35,6 +35,7 @@
<ProjectReference Include="..\Sln.Wcs.Plc\Sln.Wcs.Plc.csproj" />
<ProjectReference Include="..\Sln.Wcs.Repository\Sln.Wcs.Repository.csproj" />
<ProjectReference Include="..\Sln.Wcs.Serilog\Sln.Wcs.Serilog.csproj" />
<ProjectReference Include="..\Sln.Wcs.Strategy\Sln.Wcs.Strategy.csproj" />
</ItemGroup>
</Project>

Loading…
Cancel
Save