first commit
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.Dto.Enum;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.Business.RcsCallBack.IService;
|
||||
using JSMachine.WMS.Common.Dto.Business;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NLog.Web.LayoutRenderers;
|
||||
using NPOI.POIFS.Crypt.Agile;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
/// <summary>
|
||||
/// 提供 AGV 任务查询和报警处理相关的 HTTP 接口。
|
||||
/// </summary>
|
||||
public class AgvTaskController : ControllerBase
|
||||
{
|
||||
private IAGVTaskService _agvTaskService;
|
||||
private IRcsCallBackService _rcsCallBackService;
|
||||
/// <summary>创建 AGV 任务控制器。</summary>
|
||||
/// <param name="agvTaskService">AGV 任务查询服务。</param>
|
||||
/// <param name="rcsCallBackService">RCS 回调及报警处理服务。</param>
|
||||
public AgvTaskController(
|
||||
IAGVTaskService agvTaskService,
|
||||
IRcsCallBackService rcsCallBackService)
|
||||
{
|
||||
_agvTaskService = agvTaskService;
|
||||
_rcsCallBackService = rcsCallBackService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
/// <summary>
|
||||
/// 查询指定条件下最近创建的 AGV 任务。
|
||||
/// </summary>
|
||||
/// <returns>按创建时间倒序返回 AGV 任务列表。</returns>
|
||||
public async Task<ApiResult<List<AGVTaskDto>>> GetAll()
|
||||
{
|
||||
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
|
||||
p.Floor == 10 && p.TaskType == 2,
|
||||
nameof(AGVTaskDto.CreationTime),
|
||||
OrderByType.Desc);
|
||||
|
||||
return new ApiResult<List<AGVTaskDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = agvTaska
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
/// <summary>查询指定 ERP 任务关联的 AGV 任务。</summary>
|
||||
/// <param name="erpTaskId">ERP 任务标识。</param>
|
||||
/// <returns>按创建时间升序返回关联任务。</returns>
|
||||
public async Task<ApiResult<List<AGVTaskDto>>> GetAgvTasksRelatedToErpTask(Guid erpTaskId)
|
||||
{
|
||||
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
|
||||
p.ErpTaskId == erpTaskId,nameof(AGVTaskDto.CreationTime),OrderByType.Asc);
|
||||
|
||||
return new ApiResult<List<AGVTaskDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = agvTaska
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有agv小车报警信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public ApiResult<List<AgvTaskFailedAlarmInfo>> GetAlarmInfoes()
|
||||
{
|
||||
//return new ApiResult<List<AgvTaskFailedAlarmInfo>>
|
||||
//{
|
||||
// ResultCode="200",
|
||||
// Data =
|
||||
// [
|
||||
// new AgvTaskFailedAlarmInfo{ AgvTaskId=Guid.NewGuid(),Operation="请把把托盘放到提升机入库口1"},
|
||||
// new AgvTaskFailedAlarmInfo{AgvTaskId=Guid.NewGuid(),Operation="请把把托盘放到提升机入库口2" }
|
||||
// ]
|
||||
//};
|
||||
|
||||
return new ApiResult<List<AgvTaskFailedAlarmInfo>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = GlobalAgvTaskFailedAlarmInfo.GetAlarmInfoes()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传报警处理结果
|
||||
/// </summary>
|
||||
/// <param name="agvTaskId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> PostAlarmHandleResult(Guid agvTaskId)
|
||||
{
|
||||
LogHelper.Warn($"PDA上传报警处理,AgvTaskId {agvTaskId}");
|
||||
|
||||
bool bRet = await _rcsCallBackService.DealWithAlarmHandleResult(agvTaskId);
|
||||
|
||||
return new ApiResult<bool> { ResultCode = bRet ? "200" : "500", Data = bRet };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取搬运物料的AgvTask
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<AGVTaskDto>>> GetCarryAgvTask()
|
||||
{
|
||||
List<AGVTaskDto> agvTaska = await _agvTaskService.GetListByExpression(p =>
|
||||
p.TaskType == 6 && p.CreationTime >= DateTime.Now.AddHours(-4),
|
||||
nameof(AGVTaskDto.CreationTime),
|
||||
OrderByType.Desc);
|
||||
|
||||
return new ApiResult<List<AGVTaskDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = agvTaska
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否重复入库(30分钟内同一库位存在入库任务,则弹窗提示二次确认)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> IsReStockIn(string wareHouse)
|
||||
{
|
||||
bool exist = await _agvTaskService.Exist(p =>
|
||||
p.CreationTime >= DateTime.Now.AddMinutes(-30) &&
|
||||
p.StartPositionCode == wareHouse &&
|
||||
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn)
|
||||
);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode="200",
|
||||
Data=exist
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class ElevatorCountController : ControllerBase
|
||||
{
|
||||
private IElevatorCountService _elevatorCountService;
|
||||
public ElevatorCountController(IElevatorCountService elevatorCountService)
|
||||
{
|
||||
_elevatorCountService = elevatorCountService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<ElevatorCountDto>>> GetElevatorCountToday()
|
||||
{
|
||||
List<ElevatorCountDto> elevatorCounts = await _elevatorCountService.GetListByExpression(p => p.CreationTime >= DateTime.Now.Date);
|
||||
|
||||
return new ApiResult<List<ElevatorCountDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = elevatorCounts
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.App.ServiceImpl;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class ElevatorQueController : ControllerBase
|
||||
{
|
||||
private IElevatorPlcQueueService _elevatorPlcQueueService;
|
||||
public ElevatorQueController(IElevatorPlcQueueService elevatorPlcQueueService)
|
||||
{
|
||||
_elevatorPlcQueueService = elevatorPlcQueueService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<ElevatorPlcQueueDto>>> GetElevatorQueToday()
|
||||
{
|
||||
List<ElevatorPlcQueueDto> elevatorPlcQueues = await _elevatorPlcQueueService.GetListByExpression(p =>
|
||||
p.CreationTime >= DateTime.Now.Date &&
|
||||
(p.ElevatorChannel == 1001 || p.ElevatorChannel == 1011));
|
||||
|
||||
return new ApiResult<List<ElevatorPlcQueueDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = elevatorPlcQueues
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.Dto.Enum;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Application.IService;
|
||||
using JSMachine.WMS.Business.StockIn.IService;
|
||||
using JSMachine.WMS.Business.StockOut.IService;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.Domain.Entity.Enums;
|
||||
using JSMachine.WMS.Infrastructure;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.ErpRPC.IService;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class ErpController : ControllerBase
|
||||
{
|
||||
private IStockInService _stockInByPdaService;
|
||||
private IStockOutService _stockOutService;
|
||||
private IERPTaskService _erpTaskService;
|
||||
private IStorageRackService _storageRackService;
|
||||
private IPaperStorageService _paperStorageService;
|
||||
private IOperationLogService _operationLogService;
|
||||
|
||||
|
||||
public ErpController(
|
||||
IStockInService stockInByPdaService,
|
||||
IStockOutService stockOutService,
|
||||
IERPTaskService erpTaskService,
|
||||
IStorageRackService storageRackService,
|
||||
IPaperStorageService paperStorageService,
|
||||
IOperationLogService operationLogService
|
||||
)
|
||||
{
|
||||
_stockInByPdaService = stockInByPdaService;
|
||||
_stockOutService = stockOutService;
|
||||
_erpTaskService = erpTaskService;
|
||||
_storageRackService = storageRackService;
|
||||
_paperStorageService = paperStorageService;
|
||||
_operationLogService = operationLogService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<ERPTaskDto>>> GetLatestErpTasks(TaskTypeEnum taskType)
|
||||
{
|
||||
List<ERPTaskDto> erpTasks = await _erpTaskService
|
||||
.GetListByExpression(p =>
|
||||
p.LastModifiedTime >= DateTime.Now.Date &&
|
||||
p.TaskType == taskType
|
||||
);
|
||||
|
||||
erpTasks = erpTasks?.OrderByDescending(p => p.CreationTime).ToList();
|
||||
|
||||
return new ApiResult<List<ERPTaskDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = erpTasks
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 条件查询erp任务
|
||||
/// </summary>
|
||||
/// <param name="startTime"></param>
|
||||
/// <param name="endTime"></param>
|
||||
/// <param name="taskType"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<List<ERPTaskDto>>> GetErpTasks([FromBody]ErpTaskQueryParam erpTaskQueryParam)
|
||||
{
|
||||
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
|
||||
p.CreationTime >= erpTaskQueryParam.StartTime &&
|
||||
p.CreationTime <= erpTaskQueryParam.EndTime &&
|
||||
(erpTaskQueryParam.TaskType == 0 ? true : p.TaskType == erpTaskQueryParam.TaskType),
|
||||
"CreationTime", SqlSugar.OrderByType.Desc);
|
||||
|
||||
return new ApiResult<List<ERPTaskDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = erpTasks
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合格证号是否已存在
|
||||
/// </summary>
|
||||
/// <param name="barCode"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> IsBarCodeExist(string barCode, TaskTypeEnum taskType)
|
||||
{
|
||||
bool exist = false;
|
||||
if (taskType == TaskTypeEnum.PdaIn)
|
||||
{
|
||||
exist = await _erpTaskService.Exist(p =>
|
||||
p.BarCode == barCode &&
|
||||
(p.TaskStatus == TaskStatusEnum.Initial || p.TaskStatus == TaskStatusEnum.InExecution || p.TaskStatus == TaskStatusEnum.Completed) &&
|
||||
p.TaskType == TaskTypeEnum.PdaIn
|
||||
);
|
||||
}
|
||||
else if (taskType == TaskTypeEnum.TailIn)
|
||||
{
|
||||
exist = await _erpTaskService.Exist(p =>
|
||||
p.CreationTime >= DateTime.Now.AddHours(-1) &&
|
||||
p.BarCode == barCode &&
|
||||
(p.TaskStatus == TaskStatusEnum.Initial || p.TaskStatus == TaskStatusEnum.InExecution || p.TaskStatus == TaskStatusEnum.Completed) &&
|
||||
p.TaskType == TaskTypeEnum.TailIn
|
||||
);
|
||||
}
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = exist
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从erp获取物料信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<StorageRackDto>> GetMaterialInfoFromErp(string barCode)
|
||||
{
|
||||
XRResultDto erpResult = await _paperStorageService.GetMateriaInfo(barCode);
|
||||
|
||||
StorageRackDto storageRack = new();
|
||||
|
||||
if (erpResult != null && erpResult.data != null)
|
||||
{
|
||||
storageRack.BarCode = erpResult.data.BarCode;
|
||||
storageRack.OrderNo = erpResult.data.OrderNo;
|
||||
storageRack.MateriaName = erpResult.data.MateriaName;
|
||||
storageRack.MateriaType = erpResult.data.MateriaType;
|
||||
storageRack.MateriaNum = int.Parse(erpResult.data.MateriaNum);
|
||||
storageRack.MateriaBatch = erpResult.data.MateriaBatch;
|
||||
storageRack.MateriaCode = erpResult.data.MateriaCode;
|
||||
}
|
||||
|
||||
return new ApiResult<StorageRackDto>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = storageRack
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新单个任务状态
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> UpdateTaskStatus(Guid id, TaskStatusEnum taskStatus)
|
||||
{
|
||||
LogHelper.Info($"收到pda更新erp任务请求,任务id {id} 更新后的状态 {taskStatus}");
|
||||
|
||||
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p => p.Id == id);
|
||||
|
||||
if (erpTask.TaskStatus != TaskStatusEnum.Initial)
|
||||
{
|
||||
LogHelper.Warn($"任务 {id} 当前状态已不是待下发状态,无法取消");
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data = false,
|
||||
ResultCode = "500",
|
||||
ErrorMsg = "所选择的任务当前已不是待下发状态,无法取消"
|
||||
};
|
||||
}
|
||||
|
||||
erpTask.TaskStatus = taskStatus;
|
||||
|
||||
bool bRet = await _erpTaskService.EditSingal(erpTask);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data = bRet,
|
||||
ResultCode = bRet ? "200" : "500"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务操作
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="taskStatus"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> OperateTask(Guid id, TaskStatusEnum taskStatus)
|
||||
{
|
||||
LogHelper.Info($"收到网站更新erp任务请求,任务id {id} 更新后的状态 {taskStatus}");
|
||||
|
||||
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.WEB,
|
||||
OperationType = OperationType.UpdateErpTask,
|
||||
NewObject = string.Format("ErpTaskId:{0},TaskStatus:{1}", id, taskStatus.GetDescription()),
|
||||
UserId = userIdValues
|
||||
});
|
||||
|
||||
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p => p.Id == id);
|
||||
|
||||
if(erpTask==null)
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data=false,
|
||||
ResultCode="500",
|
||||
ErrorMsg="任务不存在,请刷新后再次重试"
|
||||
};
|
||||
}
|
||||
|
||||
erpTask.LastModifiedTime=DateTime.Now;
|
||||
erpTask.TaskStatus = taskStatus;
|
||||
|
||||
bool bRet = await _erpTaskService.EditSingalWithSpecificCols(erpTask,[nameof(ERPTaskDto.LastModifiedTime),nameof(ERPTaskDto.TaskStatus)]);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data = bRet,
|
||||
ResultCode = bRet ? "200" : "500"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停所有待执行的任务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<bool>> StopAll(TaskTypeEnum taskType)
|
||||
{
|
||||
LogHelper.Info("收到PDA暂停所有任务请求");
|
||||
|
||||
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
|
||||
p.CreationTime > DateTime.Now.Date &&
|
||||
p.TaskStatus == TaskStatusEnum.Initial &&
|
||||
p.TaskType == taskType);
|
||||
|
||||
if (erpTasks.IsNullOrEmpty())
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = true
|
||||
};
|
||||
}
|
||||
|
||||
erpTasks.ForEach(p => p.TaskStatus = TaskStatusEnum.Paused);
|
||||
|
||||
bool bRet = await _erpTaskService.EditBatch(erpTasks);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data = bRet,
|
||||
ResultCode = bRet ? "200" : "500"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 恢复所有暂停的任务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<bool>> ResumeAll(TaskTypeEnum taskType)
|
||||
{
|
||||
LogHelper.Info("收到PDA恢复所有任务请求");
|
||||
|
||||
List<ERPTaskDto> erpTasks = await _erpTaskService.GetListByExpression(p =>
|
||||
p.CreationTime > DateTime.Now.Date &&
|
||||
p.TaskStatus == TaskStatusEnum.Paused &&
|
||||
p.TaskType == taskType);
|
||||
|
||||
if (erpTasks.IsNullOrEmpty())
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = true
|
||||
};
|
||||
}
|
||||
|
||||
erpTasks.ForEach(p => p.TaskStatus = TaskStatusEnum.Initial);
|
||||
|
||||
bool bRet = await _erpTaskService.EditBatch(erpTasks);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
Data = bRet,
|
||||
ResultCode = bRet ? "200" : "500"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Application.IService;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class OperationLogController : ControllerBase
|
||||
{
|
||||
private readonly IOperationLogService _operationLogService;
|
||||
|
||||
public OperationLogController(IOperationLogService operationLogService)
|
||||
{
|
||||
_operationLogService = operationLogService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有操作日志
|
||||
/// </summary>
|
||||
/// <returns>操作日志列表</returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<OperationLogDto>>> GetAll()
|
||||
{
|
||||
var logs = await _operationLogService.GetListByExpression(
|
||||
p => true,
|
||||
nameof(OperationLogDto.CreationTime),
|
||||
OrderByType.Desc);
|
||||
|
||||
return new ApiResult<List<OperationLogDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = logs
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取操作日志
|
||||
/// </summary>
|
||||
/// <param name="id">操作日志ID</param>
|
||||
/// <returns>单个操作日志</returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<OperationLogDto>> GetById(Guid id)
|
||||
{
|
||||
var log = await _operationLogService.GetSingalByExpression(p => p.Id == id);
|
||||
|
||||
return new ApiResult<OperationLogDto>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = log
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建操作日志
|
||||
/// </summary>
|
||||
/// <param name="logDto">操作日志DTO</param>
|
||||
/// <returns>是否创建成功</returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> Create(OperationLogDto logDto)
|
||||
{
|
||||
if (logDto == null)
|
||||
return new ApiResult<bool> { ResultCode = "400", Data = false, ErrorMsg = "参数不能为空" };
|
||||
|
||||
bool success = await _operationLogService.Add(logDto);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = success ? "200" : "500",
|
||||
Data = success,
|
||||
ErrorMsg = success ? "创建成功" : "创建失败"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新操作日志
|
||||
/// </summary>
|
||||
/// <param name="logDto">操作日志DTO</param>
|
||||
/// <returns>是否更新成功</returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> Update(OperationLogDto logDto)
|
||||
{
|
||||
if (logDto == null || logDto.Id == Guid.Empty)
|
||||
return new ApiResult<bool> { ResultCode = "400", Data = false, ErrorMsg = "参数无效" };
|
||||
|
||||
bool success = await _operationLogService.EditSingal(logDto);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = success ? "200" : "500",
|
||||
Data = success,
|
||||
ErrorMsg = success ? "更新成功" : "更新失败"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除操作日志
|
||||
/// </summary>
|
||||
/// <param name="id">操作日志ID</param>
|
||||
/// <returns>是否删除成功</returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> Delete(Guid id)
|
||||
{
|
||||
bool success = await _operationLogService.DeleteById(id);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = success ? "200" : "500",
|
||||
Data = success,
|
||||
ErrorMsg = success ? "删除成功" : "删除失败"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询操作日志
|
||||
/// </summary>
|
||||
/// <param name="pageQuery">分页查询条件</param>
|
||||
/// <returns>分页结果</returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<PagedResult<OperationLogDto>>> QueryByPage([FromBody]OperationLogQueryParam pageQuery)
|
||||
{
|
||||
var condition = pageQuery.BuildConditional();
|
||||
|
||||
var result = await _operationLogService.QueryByPage(condition);
|
||||
|
||||
return new ApiResult<PagedResult<OperationLogDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = result
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using JSMachine.WMS.Business.SSE;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于向前端网站推送消息
|
||||
/// </summary>
|
||||
[Route("api/sse")]
|
||||
public class SseController: ControllerBase
|
||||
{
|
||||
[HttpGet("connect")]
|
||||
public async Task Connect()
|
||||
{
|
||||
var response = Response;
|
||||
response.Headers.Append("Content-Type", "text/event-stream");
|
||||
response.Headers.Append("Cache-Control", "no-cache");
|
||||
response.Headers.Append("Connection", "keep-alive");
|
||||
|
||||
// 记录客户端连接(用于后续推送消息)
|
||||
ClientConnection client = new()
|
||||
{
|
||||
Response = response,
|
||||
ClientId = Guid.NewGuid().ToString()
|
||||
};
|
||||
SseEngine.AddClient(client);
|
||||
|
||||
// 保持连接,直到客户端断开
|
||||
while (!response.HttpContext.RequestAborted.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(1000); // 防止 CPU 占用过高
|
||||
}
|
||||
|
||||
// 客户端断开时移除
|
||||
SseEngine.RemoveClient(client);
|
||||
}
|
||||
|
||||
[HttpPost("send")]
|
||||
public IActionResult SendMessage([FromBody] string message)
|
||||
{
|
||||
// 向所有连接的客户端推送消息
|
||||
SseEngine.BrodCast(message);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using JSMachine.WMS.App.Dto.Enum;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class StatisticController: ControllerBase
|
||||
{
|
||||
private IStorageRackService _storageRackService;
|
||||
private IAGVTaskService _agvTaskService;
|
||||
private IERPTaskService _erptaskService;
|
||||
public StatisticController(IStorageRackService storageRackService, IAGVTaskService agvTaskService, IERPTaskService erptaskService)
|
||||
{
|
||||
_storageRackService = storageRackService;
|
||||
_agvTaskService = agvTaskService;
|
||||
_erptaskService = erptaskService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<StockInAndOutStatisticInfo>> GetStockInAndOutStatistic()
|
||||
{
|
||||
int stockInCount = await _erptaskService.Count(p =>
|
||||
p.CreationTime > DateTime.Now.Date &&
|
||||
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn)
|
||||
);
|
||||
|
||||
int stockOutCount = await _agvTaskService.Count(p =>
|
||||
p.CreationTime > DateTime.Now.Date &&
|
||||
(p.TaskType == TaskTypeEnum.SaleOut || p.TaskType == TaskTypeEnum.ProductionOut) &&
|
||||
p.Floor == FloorEnum.FirstFloor
|
||||
);
|
||||
|
||||
int allGoodsCount = await _storageRackService.Count(p =>
|
||||
p.Floor == FloorEnum.SecondFloor &&
|
||||
p.Transport == TransportEnum.NormalArea &&
|
||||
!string.IsNullOrEmpty(p.BarCode)
|
||||
);
|
||||
|
||||
int emptyStorageCount = await _storageRackService.Count(p =>
|
||||
p.Floor == FloorEnum.SecondFloor &&
|
||||
p.Transport == TransportEnum.NormalArea &&
|
||||
string.IsNullOrEmpty(p.BarCode)
|
||||
);
|
||||
|
||||
|
||||
decimal storageRackeUsedRatio = (allGoodsCount) * 100m / (allGoodsCount+emptyStorageCount);
|
||||
|
||||
return new ApiResult<StockInAndOutStatisticInfo>
|
||||
{
|
||||
ResultCode="200",
|
||||
Data = new StockInAndOutStatisticInfo
|
||||
{
|
||||
StockInCount = stockInCount,
|
||||
StockOutCount = stockOutCount,
|
||||
AllGoodsCount = allGoodsCount,
|
||||
EmptyStorageCount = emptyStorageCount,
|
||||
StorageRackeUsedRatio = Math.Floor(storageRackeUsedRatio)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.App.ServiceImpl;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.RcsRPC.Dto.In;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Org.BouncyCastle.Asn1.Mozilla;
|
||||
using System.Net;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试用控制器(模拟erp等服务)
|
||||
/// </summary>
|
||||
public class TestController : ControllerBase
|
||||
{
|
||||
private IRcsTaskService _rcsTaskService;
|
||||
public TestController(IRcsTaskService rcsTaskService)
|
||||
{
|
||||
_rcsTaskService = rcsTaskService;
|
||||
}
|
||||
|
||||
private static List<MateriaInfoDto> MateriaInfos = new()
|
||||
{
|
||||
new MateriaInfoDto{ BarCode="HZYD23053001730001",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23053001730002",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23053001730003",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23053001730004",MateriaNum="600",MateriaCode="20230206003782",MateriaBatch="ZYD23053001732024-10-231",OrderNo="ZYD2305300173_0",MateriaName="220847达利250mlx12包x3盒花生牛奶条型原味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23053001730005",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD23060700682024-10-231",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680001",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680002",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680003",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680004",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680005",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680006",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680007",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23060700680008",MateriaNum="600",MateriaCode="20230206003783",MateriaBatch="ZYD25063002332025-07-041",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
|
||||
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690001",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690002",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690003",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690004",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690005",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23070700690006",MateriaNum="600",MateriaCode="20230206003784",MateriaBatch="ZYD25070900902025-07-142",OrderNo="ZYD2306070068_0",MateriaName="220848达利250mlx12包x3盒花生牛奶条型核桃味水印箱(平顶)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HZYD23080800760001",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23080800760002",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23080800760003",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23080800760004",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23080800760005",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25040100142025-04-081",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760001",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760002",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760003",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760004",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760005",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD23090800760006",MateriaNum="1000",MateriaCode="20230206003780",MateriaBatch="ZYD25010800682025-01-091",OrderNo="ZYD2306080076_0",MateriaName="220846达利250mlx12包花生牛奶条型原味彩盒(平顶)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_381_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_367_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_366_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_365_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_364_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_363_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_383_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_349_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_348_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HZYD25102702680174",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD25102702680178",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD25102702680173",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
new MateriaInfoDto{ BarCode="HZYD25102702680177",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-171",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
|
||||
new MateriaInfoDto{ BarCode="HLZYD2510270268_0_362_0000",MateriaNum="240",MateriaCode="20241026017105",MateriaBatch="ZYD25102702682025-11-20",OrderNo="ZYD2510270268_0",MateriaName="241152 伊利康美苗条砖臻浓金装高钙250mlx10包x5提储运外箱(去奥运logo版)"},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 模拟erp提供查询物料信息服务
|
||||
/// </summary>
|
||||
/// <param name="barcodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("wms_erp_interface/select/materiaInformation")]
|
||||
public async Task<XRApiResult<XRResultDto>> QueryMateriaInfor([FromBody] dynamic barcodeInfo)
|
||||
{
|
||||
return new XRApiResult<XRResultDto>
|
||||
{
|
||||
id = Guid.NewGuid().ToString(),
|
||||
jsonrpc = "",
|
||||
result = new XRResultDto
|
||||
{
|
||||
status = 200,
|
||||
data = MateriaInfos.FirstOrDefault(p => p.BarCode == barcodeInfo["barCode"].ToString()),
|
||||
success = true
|
||||
}.ToJson()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟erp提供入库上传接口
|
||||
/// </summary>
|
||||
/// <param name="barcodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("wms_erp_interface/api/wms/produce/in")]
|
||||
public async Task<XRApiResult<XRResultDto>> UploadStockIn([FromBody] dynamic barcodeInfo)
|
||||
{
|
||||
return new XRApiResult<XRResultDto>
|
||||
{
|
||||
id = Guid.NewGuid().ToString(),
|
||||
jsonrpc = "",
|
||||
result = new XRResultDto
|
||||
{
|
||||
status = 200,
|
||||
success = true
|
||||
}.ToJson()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟erp提供入库上传接口
|
||||
/// </summary>
|
||||
/// <param name="barcodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("wms_erp_interface/wms/sale/out")]
|
||||
public async Task<XRApiResult<XRResultDto>> UploadStockOut([FromBody] dynamic barcodeInfo)
|
||||
{
|
||||
return new XRApiResult<XRResultDto>
|
||||
{
|
||||
id = Guid.NewGuid().ToString(),
|
||||
jsonrpc = "",
|
||||
result = new XRResultDto
|
||||
{
|
||||
status = 200,
|
||||
success = true
|
||||
}.ToJson()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟erp提供生产退库上传接口
|
||||
/// </summary>
|
||||
/// <param name="barcodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("wms_erp_interface/erp/produce/out")]
|
||||
public async Task<XRResultDto> UploadProducitonOut([FromBody] dynamic barcodeInfo)
|
||||
{
|
||||
return new XRResultDto
|
||||
{
|
||||
status = 200,
|
||||
success = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟出库
|
||||
/// </summary>
|
||||
/// <param name="stockOutParam"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("api/Test/StockOut")]
|
||||
public async Task<ApiResult<bool>> StockOut([FromBody] StockOutParam stockOutParam)
|
||||
{
|
||||
string url = "http://localhost:8078/api/erp/out";
|
||||
string jsonParam = JsonConvert.SerializeObject(stockOutParam);
|
||||
string resJson = await HttpRequestHelper.RequestByJson(url, RestSharp.Method.POST, jsonParam);
|
||||
if (string.IsNullOrEmpty(resJson))
|
||||
{
|
||||
return new ApiResult<bool> { ResultCode = "500", Data = false };
|
||||
}
|
||||
|
||||
XRResultDto erpRet = JsonConvert.DeserializeObject<XRResultDto>(resJson);
|
||||
return new ApiResult<bool> { Data = erpRet.success, ResultCode = erpRet.success ? "200" : "500", ErrorMsg = erpRet.errors };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// wms上传agv任务
|
||||
/// </summary>
|
||||
/// <param name="taskParam"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("ics/taskOrder/addTask")]
|
||||
public async Task<JSMachine.WMS.RPC.RcsRPC.Dto.RcsApiResult> UploadRcsTask([FromBody] CreateTaskParam taskParam)
|
||||
{
|
||||
RcsTaskDto rcsTask = new()
|
||||
{
|
||||
TaskId = taskParam.orderId,
|
||||
StartPositionCode = taskParam.taskOrderDetail.taskPath.Split(',', StringSplitOptions.RemoveEmptyEntries)[0],
|
||||
EndPositionCode = taskParam.taskOrderDetail.taskPath.Split(',', StringSplitOptions.RemoveEmptyEntries)[1],
|
||||
Status = 9,
|
||||
UploadTime=DateTime.Now
|
||||
};
|
||||
|
||||
bool bRet = await _rcsTaskService.Add(rcsTask);
|
||||
return new JSMachine.WMS.RPC.RcsRPC.Dto.RcsApiResult { code = 1000 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取rcs任务列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("api/Test/GetRcsTaskLst")]
|
||||
public async Task<ApiResult<List<RcsTaskDto>>> GetRcsTaskLst()
|
||||
{
|
||||
List<RcsTaskDto> rcsTasks = await _rcsTaskService.GetListByExpression(p =>
|
||||
p.CreationTime > DateTime.Now.Date,
|
||||
nameof(RcsTaskDto.CreationTime),
|
||||
SqlSugar.OrderByType.Desc);
|
||||
return new ApiResult<List<RcsTaskDto>>() { ResultCode = "200", Data = rcsTasks };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改rcs任务信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("api/Test/UpdateRcsTask")]
|
||||
public async Task<ApiResult<bool>> UpdateRcsTask([FromBody] RcsTaskDto rcsTask)
|
||||
{
|
||||
bool bRet = await _rcsTaskService.EditSingal(rcsTask);
|
||||
|
||||
return new ApiResult<bool>() { ResultCode = "200", Data = bRet };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.Common.Dto.Business;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class UserInfoController : ControllerBase
|
||||
{
|
||||
private readonly IUserInfoService _userInfoService;
|
||||
|
||||
public UserInfoController(IUserInfoService userInfoService)
|
||||
{
|
||||
_userInfoService = userInfoService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<UserInfoDto>>> GetAll()
|
||||
{
|
||||
var users = await _userInfoService.GetListByExpression(p => true,
|
||||
nameof(UserInfoDto.CreationTime),
|
||||
OrderByType.Desc);
|
||||
|
||||
return new ApiResult<List<UserInfoDto>>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = users
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取用户信息
|
||||
/// </summary>
|
||||
/// <param name="id">用户ID</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<ApiResult<UserInfoDto>> GetById(Guid id)
|
||||
{
|
||||
var user = await _userInfoService.GetSingalByExpression(p => p.Id == id);
|
||||
if (user == null)
|
||||
{
|
||||
return new ApiResult<UserInfoDto>
|
||||
{
|
||||
ResultCode = "404",
|
||||
ErrorMsg = "用户不存在"
|
||||
};
|
||||
}
|
||||
|
||||
return new ApiResult<UserInfoDto>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = user
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建新用户
|
||||
/// </summary>
|
||||
/// <param name="userDto">用户信息</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> Create([FromBody] UserInfoDto userDto)
|
||||
{
|
||||
if (userDto == null)
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "400",
|
||||
ErrorMsg = "请求参数不能为空"
|
||||
};
|
||||
}
|
||||
|
||||
var result = await _userInfoService.Add(userDto);
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = result
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户信息
|
||||
/// </summary>
|
||||
/// <param name="id">用户ID</param>
|
||||
/// <param name="userDto">更新后的用户信息</param>
|
||||
/// <returns></returns>
|
||||
[HttpPut("{id}")]
|
||||
public async Task<ApiResult<bool>> Update(Guid id, [FromBody] UserInfoDto userDto)
|
||||
{
|
||||
if (userDto == null)
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "400",
|
||||
ErrorMsg = "请求参数不能为空"
|
||||
};
|
||||
}
|
||||
|
||||
var existingUser = await _userInfoService.GetSingalByExpression(p => p.Id == id);
|
||||
if (existingUser == null)
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "404",
|
||||
ErrorMsg = "用户不存在"
|
||||
};
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
var result = await _userInfoService.EditSingal(userDto);
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = result
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除用户
|
||||
/// </summary>
|
||||
/// <param name="id">用户ID</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<ApiResult<bool>> Delete(Guid id)
|
||||
{
|
||||
var existingUser = await _userInfoService.GetSingalByExpression(p => p.Id == id);
|
||||
if (existingUser == null)
|
||||
{
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "404",
|
||||
ErrorMsg = "用户不存在"
|
||||
};
|
||||
}
|
||||
|
||||
var result = await _userInfoService.DeleteById(id);
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = result
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<UserPermission>> Login([FromBody] UserInfoDto userInfo)
|
||||
{
|
||||
if (userInfo == null || string.IsNullOrEmpty(userInfo.UserId) || string.IsNullOrEmpty(userInfo.Password))
|
||||
return new ApiResult<UserPermission> { ResultCode = "500", ErrorMsg = "参数不合法" };
|
||||
|
||||
UserInfoDto validUser = await _userInfoService.GetSingalByExpression(p=>p.UserId== userInfo.UserId&&p.Password== userInfo.Password);
|
||||
if (validUser == null)
|
||||
return new ApiResult<UserPermission> { ResultCode = "500", ErrorMsg = "用户名或密码错误" };
|
||||
|
||||
return new ApiResult<UserPermission> { ResultCode="200",Data=new UserPermission {Token=Guid.NewGuid().ToString("N"),UserInfo= validUser } };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
using AutoMapper;
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.App.Dto.Enum;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.App.ServiceImpl;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Application.IService;
|
||||
using JSMachine.WMS.Business.StockIn.IService;
|
||||
using JSMachine.WMS.Business.StockIn.ServiceImpl.Strategy;
|
||||
using JSMachine.WMS.Business.StockOut.IService;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.Domain.Entity.Enums;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
using SqlSugar;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
public class WarehouseController : ControllerBase
|
||||
{
|
||||
private IStorageRackService _storageRackService;
|
||||
private IStockOutService _stockOutService;
|
||||
private IERPTaskService _erpTaskService;
|
||||
private IAGVTaskService _agvTaskService;
|
||||
private IOperationLogService _operationLogService;
|
||||
private IMapper _mapper;
|
||||
|
||||
public WarehouseController(
|
||||
IStorageRackService storageRackService,
|
||||
IStockOutService stockOutService,
|
||||
IERPTaskService erpTaskService,
|
||||
IAGVTaskService agvTaskService,
|
||||
IOperationLogService operationLogService,
|
||||
IMapper mapper
|
||||
)
|
||||
{
|
||||
_storageRackService = storageRackService;
|
||||
_stockOutService = stockOutService;
|
||||
_erpTaskService = erpTaskService;
|
||||
_agvTaskService = agvTaskService;
|
||||
_operationLogService = operationLogService;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
#region 库位维护
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> UpdateWarehouseStatus(Guid id, bool isLocked)
|
||||
{
|
||||
//_ = _operationLogService.Add(new OperationLogDto
|
||||
//{
|
||||
// OperationSource = OperationSource.WEB,
|
||||
// OperationType = OperationType.UpdateStorageRack,
|
||||
// NewObject = $"StorageRackId:{id},IsLocked:{isLocked}",
|
||||
// UserId=
|
||||
//});
|
||||
|
||||
bool bRet = await _storageRackService.UpdateLockStatus(id, isLocked);
|
||||
return new ApiResult<bool> { ResultCode = "200", Data = bRet };
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> UpdateWarehouseDisableStatus(Guid id, bool isDisabled)
|
||||
{
|
||||
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
|
||||
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.WEB,
|
||||
OperationType = OperationType.UpdateStorageRack,
|
||||
NewObject = $"StorageRackId:{id},IsDisabled:{isDisabled}",
|
||||
UserId = userIdValues
|
||||
});
|
||||
|
||||
bool bRet = await _storageRackService.UpdateDisableStatus(id, isDisabled);
|
||||
return new ApiResult<bool> { ResultCode = "200", Data = bRet };
|
||||
}
|
||||
#endregion
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<List<StorageRackDto>>> GetStorageRackLst(FloorEnum floor)
|
||||
{
|
||||
List<StorageRackDto> storageRack = new();
|
||||
if (floor == 0)
|
||||
{
|
||||
storageRack = await _storageRackService.GetAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
storageRack = await _storageRackService.GetListByExpression(p => p.Floor == floor);
|
||||
}
|
||||
|
||||
return new ApiResult<List<StorageRackDto>>() { ResultCode = "200", Data = storageRack };
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<List<WareHouseAreaInfo>>> GetWareHouseAreaInfo(FloorEnum floor)
|
||||
{
|
||||
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(p => p.Floor == floor);
|
||||
if (storageRacks.IsNullOrEmpty())
|
||||
return new ApiResult<List<WareHouseAreaInfo>>();
|
||||
|
||||
storageRacks = storageRacks.OrderBy(p => p.ReservoirAreaColumnId).ThenBy(p => p.NumSort).ToList();
|
||||
|
||||
List<WareHouseAreaInfo> wareHouseAreaInfos = new();
|
||||
var stockAreaGroups = storageRacks.GroupBy(p => p.ReservoirAreaId);
|
||||
foreach (var areaGroup in stockAreaGroups)
|
||||
{
|
||||
var stockColGroup = areaGroup.GroupBy(p => p.ReservoirAreaColumnId);
|
||||
WareHouseAreaInfo wareHouseAreaInfo = new()
|
||||
{
|
||||
AreaId = (int)areaGroup.Key.Value,
|
||||
AreaName = areaGroup.First().StorageRackName,
|
||||
};
|
||||
|
||||
List<WareHouseColumnInfo> Columns = new();
|
||||
foreach (var colGroup in stockColGroup)
|
||||
{
|
||||
WareHouseColumnInfo wareHouseColumnInfo = new()
|
||||
{
|
||||
ColId = (int)colGroup.Key,
|
||||
StorageRacks = colGroup.ToList()
|
||||
};
|
||||
|
||||
Columns.Add(wareHouseColumnInfo);
|
||||
}
|
||||
|
||||
wareHouseAreaInfo.Columns = Columns;
|
||||
wareHouseAreaInfos.Add(wareHouseAreaInfo);
|
||||
}
|
||||
|
||||
return new ApiResult<List<WareHouseAreaInfo>> { ResultCode = "200", Data = wareHouseAreaInfos };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据库位查询物料信息
|
||||
/// </summary>
|
||||
/// <param name="wareHouse"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<StorageRackDto>> QueryMaterialInfo(string wareHouse)
|
||||
{
|
||||
StorageRackDto storageRack = await _storageRackService.GetSingalByExpression(p => p.StorageRackNo == wareHouse);
|
||||
return new ApiResult<StorageRackDto>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = storageRack
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> Update([FromBody] StorageRackDto storageRack)
|
||||
{
|
||||
HttpContext.Request.Headers.TryGetValue("UserId", out Microsoft.Extensions.Primitives.StringValues userIdValues);
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = string.IsNullOrEmpty(userIdValues) ? OperationSource.PDA : OperationSource.WEB,
|
||||
OperationType = OperationType.UpdateStorageRack,
|
||||
NewObject = JsonConvert.SerializeObject(storageRack),
|
||||
UserId = userIdValues
|
||||
});
|
||||
|
||||
bool bRet = await _storageRackService.EditSingal(storageRack);
|
||||
|
||||
return new ApiResult<bool>
|
||||
{
|
||||
ResultCode = bRet ? "200" : "500",
|
||||
Data = bRet
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询入库物料已上传erp的数量
|
||||
/// </summary>
|
||||
/// <param name="barcode"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<int>> QueryUploadErpNum(string barCode)
|
||||
{
|
||||
ERPTaskDto erpTask = await _erpTaskService.GetSingalByExpression(p =>
|
||||
p.BarCode == barCode &&
|
||||
p.TaskType == TaskTypeEnum.PdaIn &&
|
||||
p.TaskStatus == TaskStatusEnum.Completed);
|
||||
|
||||
return new ApiResult<int>
|
||||
{
|
||||
ResultCode = "200",
|
||||
Data = erpTask == null ? 0 : erpTask.AlreadyUploadNum
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取今日入库明细
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ApiResult<List<StockInDetail>>> GetStockinDetailToday(string elvatorStockinNo)
|
||||
{
|
||||
List<ERPTaskDto> erpTasksToday = await _erpTaskService.GetListByExpression(p =>
|
||||
p.CreationTime > DateTime.Now.Date &&
|
||||
(p.TaskType == TaskTypeEnum.PdaIn || p.TaskType == TaskTypeEnum.TailIn));
|
||||
if (erpTasksToday.IsNullOrEmpty())
|
||||
{
|
||||
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||||
}
|
||||
|
||||
List<AGVTaskDto> agvTasks = await _agvTaskService.GetListByExpression(p => erpTasksToday.Select(x => x.Id).Contains(p.ErpTaskId));
|
||||
if(agvTasks.IsNullOrEmpty())
|
||||
{
|
||||
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||||
}
|
||||
|
||||
List<StorageRackDto> storageRacks=await _storageRackService.GetAll();
|
||||
if(storageRacks.IsNullOrEmpty())
|
||||
return new ApiResult<List<StockInDetail>> { Data = [], ResultCode = "200" };
|
||||
|
||||
var agvTaskGroup = agvTasks.GroupBy(p=>p.ErpTaskId);
|
||||
|
||||
List<StockInDetail> stockInDetails = new();
|
||||
|
||||
foreach (var group in agvTaskGroup)
|
||||
{
|
||||
List<AGVTaskDto> agvTaskThisGroup = group.ToList();
|
||||
List<StorageRackDto> endPositionThisGroup = storageRacks
|
||||
.Where(p => agvTaskThisGroup.Select(x => x.EndPositionCode).Contains(p.StorageRackNo))
|
||||
.ToList();
|
||||
|
||||
StorageRackDto storagerack = endPositionThisGroup.FirstOrDefault(p=>p.Transport==TransportEnum.NormalArea);
|
||||
if(storagerack==null)
|
||||
continue;
|
||||
|
||||
if (string.IsNullOrEmpty(elvatorStockinNo))
|
||||
{
|
||||
StockInDetail stockInDetail = _mapper.Map<ERPTaskDto, StockInDetail>(
|
||||
erpTasksToday.First(p => p.Id == agvTaskThisGroup.First().ErpTaskId));
|
||||
|
||||
stockInDetail.StoragePosition = storagerack.StorageRackNo;
|
||||
stockInDetails.Add(stockInDetail);
|
||||
}
|
||||
else
|
||||
{
|
||||
AGVTaskDto agvTask = agvTaskThisGroup.FirstOrDefault(p=>p.StartPositionCode== elvatorStockinNo);
|
||||
if(agvTask==null)
|
||||
continue;
|
||||
|
||||
StockInDetail stockInDetail = _mapper.Map<ERPTaskDto, StockInDetail>(
|
||||
erpTasksToday.First(p => p.Id == agvTaskThisGroup.First().ErpTaskId));
|
||||
|
||||
stockInDetail.StoragePosition = storagerack.StorageRackNo;
|
||||
stockInDetails.Add(stockInDetail);
|
||||
}
|
||||
}
|
||||
|
||||
stockInDetails = stockInDetails.OrderBy(p=>p.StoragePosition).ToList();
|
||||
|
||||
return new ApiResult<List<StockInDetail>>
|
||||
{
|
||||
Data = stockInDetails,
|
||||
ResultCode = "200"
|
||||
};
|
||||
}
|
||||
|
||||
#region 搬运物料
|
||||
|
||||
/// <summary>
|
||||
/// 物料搬运,起点库位验证
|
||||
/// </summary>
|
||||
/// <param name="startRankNo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<string>> CheckCarryStartRankNo(string startRankNo)
|
||||
{
|
||||
return await _stockOutService.CheckCarryStartRankNo(startRankNo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物料搬运,起点库位验证
|
||||
/// </summary>
|
||||
/// <param name="endRankNo"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<string>> CheckCarryEndRankNo(string endRankNo)
|
||||
{
|
||||
return await _stockOutService.CheckCarryEndRankNo(endRankNo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 搬运物料
|
||||
/// </summary>
|
||||
/// <param name="erpSaleOutParam"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<string>> CarryMaterial([FromBody] CarryInParam carryInParam)
|
||||
{
|
||||
LogHelper.Info($"收到PDA搬运物料请求,提交信息\n {JsonConvert.SerializeObject(carryInParam)}");
|
||||
|
||||
HttpContext.Request.Headers.TryGetValue("UserId", out var userIdValues);
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.PDA,
|
||||
OperationType = OperationType.Carry,
|
||||
NewObject = JsonConvert.SerializeObject(carryInParam),
|
||||
UserId = userIdValues
|
||||
});
|
||||
|
||||
return await _stockOutService.CarryMaterialInfo(carryInParam);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 出库码头维护
|
||||
|
||||
/// <summary>
|
||||
/// 清空出库码头
|
||||
/// </summary>
|
||||
/// <param name="transport"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> ClearWharf(TransportEnum transport)
|
||||
{
|
||||
if (!(transport == TransportEnum.NorthArea || transport == TransportEnum.SouthArea || transport == TransportEnum.MiddleOutArea))
|
||||
{
|
||||
return new ApiResult<bool> { ResultCode = "500", Data = false, ErrorMsg = "码头编号错误" };
|
||||
}
|
||||
|
||||
LogHelper.Info($"收到pda清空出库码头请求,码头类型 {transport.ToString()}");
|
||||
|
||||
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(p => p.Transport == transport);
|
||||
storageRacks?.ForEach(p => { p.IsLock = false; p.BarCode = null; });
|
||||
|
||||
await _storageRackService.EditBatch(storageRacks);
|
||||
|
||||
return new ApiResult<bool> { ResultCode = "200", Data = true };
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解锁南区码头
|
||||
/// </summary>
|
||||
/// <param name="storageRack"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<string>> UnlockSourthStorageRack()
|
||||
{
|
||||
LogHelper.Info($"收到PDA解锁南区码头库位请求");
|
||||
var bRet = new ApiResult<string>() { ResultCode = "500", ErrorMsg = "解锁南区码头失败" };
|
||||
|
||||
var dataList = await _storageRackService.GetListByExpression(p => p.Transport == TransportEnum.SouthArea);
|
||||
if (dataList != null && dataList.Count > 0)
|
||||
{
|
||||
foreach (var data in dataList)
|
||||
{
|
||||
data.IsLock = false;
|
||||
}
|
||||
|
||||
var result = await _storageRackService.EditBatch(dataList);
|
||||
if (result)
|
||||
{
|
||||
bRet.ResultCode = "200";
|
||||
}
|
||||
else
|
||||
{
|
||||
bRet.ErrorMsg = "解锁南区码头:数据库操作失败";
|
||||
}
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解锁北区码头
|
||||
/// </summary>
|
||||
/// <param name="storageRack"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<string>> UnlockNorthAreaStorageRack()
|
||||
{
|
||||
LogHelper.Info($"收到PDA解锁北区码头库位请求");
|
||||
var bRet = new ApiResult<string>() { ResultCode = "500", ErrorMsg = "解锁北区码头失败" };
|
||||
|
||||
var dataList = await _storageRackService.GetListByExpression(p => p.Transport == TransportEnum.NorthArea);
|
||||
if (dataList != null && dataList.Count > 0)
|
||||
{
|
||||
foreach (var data in dataList)
|
||||
{
|
||||
data.IsLock = false;
|
||||
}
|
||||
|
||||
var result = await _storageRackService.EditBatch(dataList);
|
||||
if (result)
|
||||
{
|
||||
bRet.ResultCode = "200";
|
||||
}
|
||||
else
|
||||
{
|
||||
bRet.ErrorMsg = "解锁北区码头:数据库操作失败";
|
||||
}
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 物料查询
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<List<StorageRackDto>>> GetMaterialInfo([FromBody] MaterialQueryParam materialQueryParam)
|
||||
{
|
||||
Expression<Func<StorageRackDto, bool>> express = materialQueryParam.BuildExpress();
|
||||
List<StorageRackDto> storageRacks = await _storageRackService.GetListByExpression(express);
|
||||
|
||||
storageRacks = storageRacks?.OrderBy(p=>p.Floor).ThenBy(p=>p.AreaNumSort).ThenBy(p=>p.ReservoirAreaColumnId).ThenBy(p=>p.NumSort).ToList();
|
||||
|
||||
return new ApiResult<List<StorageRackDto>>() { ResultCode = "200", Data = storageRacks };
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
using JSMachine.WMS.Business.RcsCallBack.IService;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out;
|
||||
using JSMachine.WMS.RPC.RcsRPC.Dto.In;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using JSMachine.WMS.RPC.RcsRPC.Dto;
|
||||
using JSMachine.WMS.Business.StockIn.IService;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.In.XRBusinessResult;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.Out.XRBusinessResult;
|
||||
using JSMachine.WMS.Business.StockOut.IService;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using Newtonsoft.Json;
|
||||
using JSMachine.WMS.App.Dto.Enum;
|
||||
using JSMachine.WMS.RPC.ErpRPC.Dto.In;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.Common.Cache;
|
||||
using JSMachine.WMS.Application.IService;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Domain.Entity.Enums;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// WMS 核心业务接口,接收 RCS、PDA 和 ERP 请求并委托给对应业务服务。
|
||||
/// </summary>
|
||||
public class WmsController : ControllerBase
|
||||
{
|
||||
private IStockInService _stockInService;
|
||||
private IOperationLogService _operationLogService;
|
||||
private IStockOutService _stockOutService;
|
||||
/// <summary>创建 WMS 核心业务控制器。</summary>
|
||||
/// <param name="stockInService">入库业务服务。</param>
|
||||
/// <param name="stockOutService">出库业务服务。</param>
|
||||
/// <param name="operationLogService">操作日志服务。</param>
|
||||
public WmsController(
|
||||
IStockInService stockInService,
|
||||
IStockOutService stockOutService,
|
||||
IOperationLogService operationLogService)
|
||||
|
||||
{
|
||||
_stockInService = stockInService;
|
||||
_stockOutService = stockOutService;
|
||||
_operationLogService = operationLogService;
|
||||
}
|
||||
|
||||
#region 通过提供接口,给Rcs调用,获取AGV上报的任务状态
|
||||
/// <summary>
|
||||
/// Rcs上传agv作业执行状态
|
||||
/// </summary>
|
||||
/// <param name="callBackWmsParam"></param>
|
||||
/// <returns></returns>
|
||||
[Route("api/Wms/PostAgvExcutionStatus")]
|
||||
[HttpPost]
|
||||
public async Task<RcsApiResult> PostAgvExcutionStatus([FromBody] AgvExcutionInfo agvExcutionInfo)
|
||||
{
|
||||
LogHelper.Info($"收到Rcs上报的小车执行状态信息,任务Id {agvExcutionInfo.OrderId},当前状态 {agvExcutionInfo.Status}");
|
||||
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.RCS,
|
||||
OperationType = OperationType.RcsCallBack,
|
||||
NewObject = JsonConvert.SerializeObject(agvExcutionInfo)
|
||||
});
|
||||
|
||||
if (agvExcutionInfo == null || string.IsNullOrEmpty(agvExcutionInfo.OrderId))
|
||||
{
|
||||
return await Task.FromResult(new RcsApiResult { code = 500, data = "参数不合法" });
|
||||
}
|
||||
|
||||
RcsCallbackCache.RcsCallbackQueue.Enqueue(agvExcutionInfo);
|
||||
|
||||
return await Task.FromResult(new RcsApiResult()
|
||||
{
|
||||
code = 1000,
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PDA入库
|
||||
/// <summary>接收 PDA 入库请求并创建入库业务任务。</summary>
|
||||
/// <param name="pdaInParam">PDA 提交的入库参数。</param>
|
||||
/// <returns>标准化入库处理结果。</returns>
|
||||
[Route("api/wms/StockInByPda")]
|
||||
[HttpPost]
|
||||
public async Task<ApiResult<bool>> StockInByPda([FromBody] PDAInParam pdaInParam)
|
||||
{
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.PDA,
|
||||
OperationType = OperationType.StockIn,
|
||||
NewObject = JsonConvert.SerializeObject(pdaInParam)
|
||||
});
|
||||
|
||||
ApiResult<bool> apiResult = new();
|
||||
|
||||
string msg = await _stockInService.StockIn(pdaInParam);
|
||||
if (string.IsNullOrEmpty(msg))
|
||||
{
|
||||
apiResult.ResultCode = "200";
|
||||
apiResult.Data = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
apiResult.ResultCode = "500";
|
||||
apiResult.Data = false;
|
||||
apiResult.ErrorMsg = msg;
|
||||
}
|
||||
|
||||
return apiResult;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 销售出库/生产退库
|
||||
private static readonly SemaphoreSlim _requestSemaphore = new(1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// 销售出库/生产退库
|
||||
/// </summary>
|
||||
/// <param name="erpSaleOutParam"></param>
|
||||
/// <returns></returns>
|
||||
[Route("api/erp/out")]
|
||||
[HttpPost]
|
||||
public async Task<XRResultDto> Out([FromBody] StockOutParam erpSaleOutParam)
|
||||
{
|
||||
await _requestSemaphore.WaitAsync();
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.Info($"收到erp出库请求,请求方IP {HttpContext.Connection.RemoteIpAddress}," +
|
||||
$"原始参数信息 {JsonConvert.SerializeObject(erpSaleOutParam)}");
|
||||
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.ERP,
|
||||
OperationType = erpSaleOutParam.transport==4 ? OperationType.ProductionOut : OperationType.SaleOut,
|
||||
NewObject = JsonConvert.SerializeObject(erpSaleOutParam)
|
||||
});
|
||||
|
||||
XRResultDto apiResult = new();
|
||||
string errMsg = await _stockOutService.Stockout(erpSaleOutParam);
|
||||
|
||||
if (string.IsNullOrEmpty(errMsg))
|
||||
{
|
||||
apiResult.success = true;
|
||||
apiResult.status = 200;
|
||||
}
|
||||
else
|
||||
{
|
||||
apiResult.success = false;
|
||||
apiResult.status = 500;
|
||||
apiResult.errors = errMsg;
|
||||
}
|
||||
return apiResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(ex);
|
||||
return new XRResultDto { status = 500, success = false, errors = "WMS服务端发生未知错误" };
|
||||
}
|
||||
finally
|
||||
{
|
||||
_requestSemaphore.Release();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 出库撤单
|
||||
/// <summary>
|
||||
/// 出库撤单
|
||||
/// </summary>
|
||||
/// <param name="cancelOrderParam"></param>
|
||||
/// <returns></returns>
|
||||
[Route("api/erp/retreat")]
|
||||
[HttpPost]
|
||||
public async Task<XRNewResultDto<int>> ErpCancelOrder([FromBody] ErpCancelOrderParam cancelOrderParam)
|
||||
{
|
||||
LogHelper.Info($"收到erp出库撤单请求,请求方IP {HttpContext.Connection.RemoteIpAddress}," +
|
||||
$"原始参数信息 {JsonConvert.SerializeObject(cancelOrderParam)}");
|
||||
|
||||
_ = _operationLogService.Add(new OperationLogDto
|
||||
{
|
||||
OperationSource = OperationSource.ERP,
|
||||
OperationType = OperationType.StockOutCancel,
|
||||
NewObject = JsonConvert.SerializeObject(cancelOrderParam)
|
||||
});
|
||||
|
||||
return await _stockOutService.ErpCancelOrder(cancelOrderParam);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using AutoMapper;
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Exstention
|
||||
{
|
||||
public static class AutoMapperConfig
|
||||
{
|
||||
public static void UseAutoMapperConfig(this IApplicationBuilder app)
|
||||
{
|
||||
IMapperConfigurationExpression expression = app.UseAutoMapper();
|
||||
|
||||
|
||||
expression.CreateMap<AGVTask, AGVTaskDto>().ReverseMap();
|
||||
|
||||
expression.CreateMap<ERPTask, ERPTaskDto>().ReverseMap();
|
||||
|
||||
expression.CreateMap<ElevatorPlcQueue, ElevatorPlcQueueDto>().ReverseMap();
|
||||
|
||||
expression.CreateMap<StorageRack, StorageRackDto>().ReverseMap();
|
||||
|
||||
expression.CreateMap<ElevatorCount, ElevatorCountDto>().ReverseMap();
|
||||
|
||||
expression.CreateMap<ERPTaskDto, StockInDetail>();
|
||||
|
||||
expression.CreateMap<RcsTaskDto, RcsTask>().ReverseMap();
|
||||
|
||||
expression.CreateMap<UserInfoDto, UserInfo>().ReverseMap();
|
||||
|
||||
expression.CreateMap<OperationLogDto, OperationLog>().ReverseMap();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using AutoMapper;
|
||||
using AutoMapper.Configuration;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Exstention
|
||||
{
|
||||
public static class AutoMapperExtension
|
||||
{
|
||||
public static IServiceCollection AddAutoMapper(this IServiceCollection service)
|
||||
{
|
||||
service.TryAddSingleton<MapperConfigurationExpression>();
|
||||
service.TryAddSingleton(serviceProvider =>
|
||||
{
|
||||
var mapperConfigurationExpression = serviceProvider.GetRequiredService<MapperConfigurationExpression>();
|
||||
var instance = new MapperConfiguration(mapperConfigurationExpression);
|
||||
|
||||
//instance.AssertConfigurationIsValid();
|
||||
|
||||
return instance;
|
||||
});
|
||||
service.TryAddSingleton(serviceProvider =>
|
||||
{
|
||||
var mapperConfiguration = serviceProvider.GetRequiredService<MapperConfiguration>();
|
||||
|
||||
return mapperConfiguration.CreateMapper();
|
||||
});
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
public static IMapperConfigurationExpression UseAutoMapper(this IApplicationBuilder applicationBuilder)
|
||||
{
|
||||
return applicationBuilder.ApplicationServices.GetRequiredService<MapperConfigurationExpression>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using NPOI.OpenXmlFormats.Dml;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Filters
|
||||
{
|
||||
public class CustomActionFilter : IActionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 方法执行后为结果统一包装
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
if (context.Exception != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string actionName = ((ControllerActionDescriptor)context.ActionDescriptor).ControllerName;
|
||||
//企望的测试接口需要跳过返回值包装拦截器,不然返回数据又被包装一层,无法解析
|
||||
if (actionName == "Wantit")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectResult objectResult = context.Result as ObjectResult;
|
||||
context.Result = new ObjectResult(new CommonQueryResult<object>(true, true, objectResult?.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 方法执行前检测参数是否合法
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
CommonQueryResult<bool> result = new(false, false, false);
|
||||
|
||||
foreach (var item in context.ModelState.Values)
|
||||
{
|
||||
foreach (var error in item.Errors)
|
||||
{
|
||||
result.Msg += error.ErrorMessage + "|";
|
||||
}
|
||||
}
|
||||
result.Msg = result.Msg.TrimEnd('|');
|
||||
context.Result = new JsonResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一捕获控制器执行期间未处理的异常,并转换为标准错误响应。
|
||||
/// </summary>
|
||||
public class ExceptionFilter : IExceptionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录异常并结束异常传播,向客户端返回内部服务器错误结果。
|
||||
/// </summary>
|
||||
/// <param name="context">包含异常和 HTTP 上下文的过滤器上下文。</param>
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
CommonQueryResult<bool> commonQueryResult = new(false, false, false) { ErrorCode = ErrorCode.InternalServerError };
|
||||
LogHelper.Error($"发生了全局异常,异常信息 {context.Exception.Message} \n 跟踪信息 {context.Exception.StackTrace}");
|
||||
context.Result = new JsonResult(commonQueryResult);
|
||||
context.ExceptionHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using JSMachine.WMS.WebHost.Models;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Filters
|
||||
{
|
||||
public class RateLimitFilter : IAsyncActionFilter
|
||||
{
|
||||
private IMemoryCache memoryCache;
|
||||
public RateLimitFilter(IMemoryCache memoryCache)
|
||||
{
|
||||
this.memoryCache = memoryCache;
|
||||
}
|
||||
|
||||
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
string remoteIP = context.HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||
string cacheKey = $"LastVisitTick_{remoteIP}";
|
||||
long? lastTick = memoryCache.Get<long?>(cacheKey);
|
||||
if (lastTick == null || Environment.TickCount64 - lastTick > 1000)
|
||||
{
|
||||
memoryCache.Set(cacheKey, Environment.TickCount64, TimeSpan.FromSeconds(10));//距离现在10秒过期
|
||||
return next();
|
||||
}
|
||||
else//1秒之内只允许访问一次
|
||||
{
|
||||
context.Result = new ObjectResult(new CommonQueryResult<object>(true, false, null) { Msg="访问过于频繁"});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Platforms>x64</Platforms>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Autofac" Version="8.0.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.15" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\JSMachine.WMS.Application\JSMachine.WMS.App.csproj" />
|
||||
<ProjectReference Include="..\JSMachine.WMS.Business\JSMachine.WMS.Business.csproj" />
|
||||
<ProjectReference Include="..\JSMachine.WMS.Common\JSMachine.WMS.Common.csproj" />
|
||||
<ProjectReference Include="..\JSMachine.WMS.Job\JSMachine.WMS.Job.csproj" />
|
||||
<ProjectReference Include="..\JSMachine.WMS.RPC\JSMachine.WMS.RPC.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appSettingsWebhost.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<NameOfLastUsedPublishProfile>D:\项目\金世泰WMS\source\wmsjst\JSMachine.WMS.WebHost\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
|
||||
<Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
|
||||
<ActiveDebugProfile>JSMachine.WMS.WebHost</ActiveDebugProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// webapi查询结果封装
|
||||
/// </summary>
|
||||
public class CommonQueryResult<T>
|
||||
{
|
||||
public CommonQueryResult() { }
|
||||
|
||||
public CommonQueryResult(bool isParamValid, bool isSucess, T result)
|
||||
{
|
||||
if (!isParamValid)
|
||||
{
|
||||
IsSucess = false;
|
||||
ErrorCode = ErrorCode.InValidInputParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSucess = isSucess;
|
||||
ErrorCode = isSucess ? ErrorCode.Sucess : ErrorCode.OperateFailed;
|
||||
Result = result;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSucess { get; set; }
|
||||
public ErrorCode ErrorCode { get; set; }
|
||||
/// <summary>
|
||||
/// 返回数据(可以是bool也可是实体等等)
|
||||
/// </summary>
|
||||
public T Result { get; set; }
|
||||
public string Msg { get; set; }
|
||||
}
|
||||
|
||||
public enum ErrorCode
|
||||
{
|
||||
Sucess = 0,
|
||||
OperateFailed = 1,
|
||||
InValidInputParam = 2,
|
||||
InternalServerError = 3,
|
||||
UnknownError = 4
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
public class ErpTaskQueryParam
|
||||
{
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public int TaskType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using SqlSugar;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 物料查询参数
|
||||
/// </summary>
|
||||
public class MaterialQueryParam
|
||||
{
|
||||
/// <summary>
|
||||
/// 库位编号
|
||||
/// </summary>
|
||||
public string StorageRackNo { get; set; }
|
||||
/// <summary>
|
||||
/// 合格证号
|
||||
/// </summary>
|
||||
public string Barcode { get; set; }
|
||||
/// <summary>
|
||||
/// 物料批次号
|
||||
/// </summary>
|
||||
public string MaterialBatch { get; set; }
|
||||
/// <summary>
|
||||
/// 客户名称
|
||||
/// </summary>
|
||||
public string CustomerName { get; set; }
|
||||
|
||||
public Expression<Func<StorageRackDto, bool>> BuildExpress()
|
||||
{
|
||||
var express = Expressionable.Create<StorageRackDto>();
|
||||
|
||||
express.AndIF(!string.IsNullOrEmpty(StorageRackNo), p => p.StorageRackNo.Contains(StorageRackNo));
|
||||
express.AndIF(!string.IsNullOrEmpty(Barcode), p => p.BarCode.Contains(Barcode));
|
||||
express.AndIF(!string.IsNullOrEmpty(MaterialBatch), p => p.MateriaBatch.Contains(MaterialBatch));
|
||||
express.AndIF(!string.IsNullOrEmpty(CustomerName), p => p.CustomName.Contains(CustomerName));
|
||||
|
||||
return express.ToExpression();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
using JSMachine.WMS.Application.Dto;
|
||||
using JSMachine.WMS.Domain.Entity;
|
||||
using JSMachine.WMS.Domain.Entity.Enums;
|
||||
using SqlSugar;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
public class OperationLogQueryParam
|
||||
{
|
||||
public DateTime? StartTime { get; set; }
|
||||
public DateTime? EndTime { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public OperationType OperationType { get; set; }
|
||||
public OperationSource OperationSource { get; set; }
|
||||
public int PageIndex { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
|
||||
|
||||
public PageQueryCondition BuildConditional()
|
||||
{
|
||||
|
||||
List<IConditionalModel> conditionalModels = new();
|
||||
|
||||
if (StartTime != null)
|
||||
{
|
||||
conditionalModels.Add(new ConditionalModel()
|
||||
{
|
||||
FieldName = nameof(OperationLogDto.CreationTime),
|
||||
ConditionalType = ConditionalType.GreaterThanOrEqual,
|
||||
FieldValue = StartTime.Value.ToString()
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (EndTime != null)
|
||||
{
|
||||
conditionalModels.Add(new ConditionalModel()
|
||||
{
|
||||
FieldName = nameof(OperationLogDto.CreationTime),
|
||||
ConditionalType = ConditionalType.LessThanOrEqual,
|
||||
FieldValue = EndTime.Value.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(UserId))
|
||||
{
|
||||
conditionalModels.Add(new ConditionalModel()
|
||||
{
|
||||
FieldName = nameof(OperationLogDto.UserId),
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
FieldValue = UserId
|
||||
});
|
||||
}
|
||||
|
||||
if (OperationType != OperationType.None)
|
||||
|
||||
{
|
||||
conditionalModels.Add(new ConditionalModel()
|
||||
{
|
||||
FieldName = nameof(OperationLogDto.OperationType),
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
FieldValue = ((int)OperationType).ToString()
|
||||
});
|
||||
}
|
||||
|
||||
if (OperationSource != OperationSource.None)
|
||||
{
|
||||
conditionalModels.Add(new ConditionalModel()
|
||||
{
|
||||
FieldName = nameof(OperationLogDto.OperationSource),
|
||||
ConditionalType = ConditionalType.Equal,
|
||||
FieldValue = ((int)OperationSource).ToString()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return new PageQueryCondition
|
||||
{
|
||||
CurrentPage = PageIndex,
|
||||
PageSize = PageSize,
|
||||
OrderByFiled = nameof(OperationLogDto.CreationTime),
|
||||
OrderByType = OrderByType.Desc,
|
||||
Filters = conditionalModels
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
public class OrderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单编号
|
||||
/// </summary>
|
||||
public string OrderNum { get; set; }
|
||||
/// <summary>
|
||||
/// 产品编号(该订单属于哪一种产品)
|
||||
/// </summary>
|
||||
public string ProductionNum { get; set; }
|
||||
/// <summary>
|
||||
/// 客户名称
|
||||
/// </summary>
|
||||
public string CustomerName { get; set; }
|
||||
/// <summary>
|
||||
/// 计划数量
|
||||
/// </summary>
|
||||
public int PlanningNum { get; set; }
|
||||
/// <summary>
|
||||
/// 每捆数
|
||||
/// </summary>
|
||||
public int PerBunchNum { get; set; }
|
||||
/// <summary>
|
||||
/// 箱型
|
||||
/// </summary>
|
||||
public string BoxType { get; set; }
|
||||
/// <summary>
|
||||
/// 楞型
|
||||
/// </summary>
|
||||
public string Flute { get; set; }
|
||||
/// <summary>
|
||||
/// 纸厚
|
||||
/// </summary>
|
||||
public decimal PaperThickness { get; set; }
|
||||
/// <summary>
|
||||
/// 修边值
|
||||
/// </summary>
|
||||
public decimal TrimValue { get; set; }
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
/// <summary>
|
||||
/// 是否开槽
|
||||
/// </summary>
|
||||
public bool IsSlotted { get; set; }
|
||||
/// <summary>
|
||||
/// 是否模切
|
||||
/// </summary>
|
||||
public bool IsMoldCut { get; set; }
|
||||
/// <summary>
|
||||
/// 粘箱机是否折叠粘箱
|
||||
/// </summary>
|
||||
public bool IsFoldingGlueBox { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 横一长(mm)
|
||||
/// </summary>
|
||||
public decimal HorizontalFirstWidth { get; set; }
|
||||
/// <summary>
|
||||
/// 横二长(mm)
|
||||
/// </summary>
|
||||
public decimal HorizontalSecondWidth { get; set; }
|
||||
/// <summary>
|
||||
/// 横三长(mm)
|
||||
/// </summary>
|
||||
public decimal HorizontalThirdWidth { get; set; }
|
||||
/// <summary>
|
||||
/// 横四长(mm)
|
||||
/// </summary>
|
||||
public decimal HorizontalFourWidth { get; set; }
|
||||
/// <summary>
|
||||
/// 纵一高(mm)
|
||||
/// </summary>
|
||||
public decimal VerticalFirstHeight { get; set; }
|
||||
/// <summary>
|
||||
/// 纵二高(mm)
|
||||
/// </summary>
|
||||
public decimal VerticalSecondHeight { get; set; }
|
||||
/// <summary>
|
||||
/// 纵三高(mm)
|
||||
/// </summary>
|
||||
public decimal VerticalThridHeight { get; set; }
|
||||
/// <summary>
|
||||
/// 舌口宽(mm)
|
||||
/// </summary>
|
||||
public decimal TongueWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 纸总长
|
||||
/// </summary>
|
||||
public decimal PaperLength { get; set; }
|
||||
/// <summary>
|
||||
/// 纸总宽
|
||||
/// </summary>
|
||||
public decimal PaperWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单时间(导入等非本系统添加的订单时间以信息源时间为准,本系统添加的订单则取提交订单的时间为准)
|
||||
/// </summary>
|
||||
public DateTime? OrderTime { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime? CreationTime { get; set; }
|
||||
/// <summary>
|
||||
/// /最近一次得修改时间
|
||||
/// </summary>
|
||||
public DateTime? LastModifiedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 拆刀提示(旧单使用保存的拆刀提示,新单直接从PLC读取拆刀提示)
|
||||
/// </summary>
|
||||
//public string RemoveKnifeInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已生产
|
||||
/// </summary>
|
||||
public bool IsFinished { get; set; }
|
||||
/// <summary>
|
||||
/// 印版补偿值
|
||||
/// </summary>
|
||||
public decimal PrintPlateOffset { get; set; }
|
||||
/// <summary>
|
||||
/// 模板补偿值
|
||||
/// </summary>
|
||||
public decimal MoldCutPlateOffset { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 出入库统计信息
|
||||
/// </summary>
|
||||
public class StockInAndOutStatisticInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 入库数量
|
||||
/// </summary>
|
||||
public int StockInCount { get; set; }
|
||||
/// <summary>
|
||||
/// 出库数量
|
||||
/// </summary>
|
||||
public int StockOutCount { get; set; }
|
||||
/// <summary>
|
||||
/// 所有货物数量
|
||||
/// </summary>
|
||||
public int AllGoodsCount { get; set; }
|
||||
/// <summary>
|
||||
/// 空库位数量
|
||||
/// </summary>
|
||||
public int EmptyStorageCount { get; set; }
|
||||
/// <summary>
|
||||
/// 库位使用率
|
||||
/// </summary>
|
||||
public decimal StorageRackeUsedRatio { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 入库详情
|
||||
/// </summary>
|
||||
public class StockInDetail
|
||||
{
|
||||
/// <summary>
|
||||
/// ErpTask的Id
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// 库位编号(起点)
|
||||
/// </summary>
|
||||
public string StorageRackNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 合格证号
|
||||
/// </summary>
|
||||
public string BarCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string CustomName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料名称
|
||||
/// </summary>
|
||||
public string MateriaName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料类型
|
||||
/// </summary>
|
||||
public string MateriaType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 批次号的生成规则为: 作业单号+日期+班次
|
||||
/// </summary>
|
||||
public string MateriaBatch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料编号
|
||||
/// </summary>
|
||||
public string MateriaCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// erp下发命令中出入库总数量
|
||||
/// </summary>
|
||||
public int ErpOrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已上传给Erp的数量
|
||||
/// </summary>
|
||||
public int AlreadyUploadNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料入库最终存放库位
|
||||
/// </summary>
|
||||
public string StoragePosition { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
public class UserPermission
|
||||
{
|
||||
public string Token { get; set; }
|
||||
public UserInfoDto UserInfo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using JSMachine.WMS.App.Dto;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 库区信息
|
||||
/// </summary>
|
||||
public class WareHouseAreaInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 库区Id
|
||||
/// </summary>
|
||||
public int AreaId { get; set; }
|
||||
/// <summary>
|
||||
/// 库区名称
|
||||
/// </summary>
|
||||
public string AreaName { get; set; }
|
||||
/// <summary>
|
||||
/// 库区列信息
|
||||
/// </summary>
|
||||
public List<WareHouseColumnInfo> Columns { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 库位列信息
|
||||
/// </summary>
|
||||
public class WareHouseColumnInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 列Id
|
||||
/// </summary>
|
||||
public int ColId { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<StorageRackDto> StorageRacks { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using JSMachine.WMS.App.IService;
|
||||
using JSMachine.WMS.App.ServiceImpl;
|
||||
using JSMachine.WMS.Domain.IRepository;
|
||||
using JSMachine.WMS.Domain.Repository;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.Job;
|
||||
using JSMachine.WMS.WebHost;
|
||||
using JSMachine.WMS.WebHost.Exstention;
|
||||
using JSMachine.WMS.WebHost.Filters;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
|
||||
WebHostEngine1.Start();
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "weatherforecast",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"JSMachine.WMS.WebHost": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "weatherforecast",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5069"
|
||||
}
|
||||
},
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:23998",
|
||||
"sslPort": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using Autofac;
|
||||
using FluentValidation;
|
||||
using FluentValidation.AspNetCore;
|
||||
using JSMachine.WMS.Domain.Repository;
|
||||
using JSMachine.WMS.Infrastructure;
|
||||
using JSMachine.WMS.Infrastructure.Helper;
|
||||
using JSMachine.WMS.Job;
|
||||
using JSMachine.WMS.PLC.ModbusImpl.Elevator.Exstension;
|
||||
using JSMachine.WMS.WebHost.Exstention;
|
||||
using JSMachine.WMS.WebHost.Filters;
|
||||
using JSMachine.WMS.WebHost.Validators;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using SqlSugar;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace JSMachine.WMS.WebHost
|
||||
{
|
||||
/// <summary>
|
||||
/// WebHost 的服务注册和 HTTP 请求管道配置入口。
|
||||
/// </summary>
|
||||
public class Startup
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建启动配置对象。
|
||||
/// </summary>
|
||||
/// <param name="configuration">应用配置,包含数据库、ERP、RCS 和设备配置。</param>
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 注册控制器、参数验证、跨域、对象映射、缓存、数据库及应用服务所需的依赖。
|
||||
/// </summary>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers(op =>
|
||||
{
|
||||
//op.Filters.Add<RateLimitFilter>();
|
||||
//op.Filters.Add<CustomActionFilter>();
|
||||
op.Filters.Add<ExceptionFilter>();
|
||||
})
|
||||
.AddNewtonsoftJson(jsonOp =>
|
||||
{
|
||||
jsonOp.SerializerSettings.ContractResolver = null;
|
||||
jsonOp.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||
jsonOp.SerializerSettings.Converters.Add(new StringEnumConverter());
|
||||
});
|
||||
|
||||
|
||||
//services.AddAuthentication("Bearer")
|
||||
// .AddJwtBearer("Bearer", options =>
|
||||
// {
|
||||
// options.Authority = Configuration["AuthorityUrl"];
|
||||
// options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false };
|
||||
// options.RequireHttpsMetadata = false;
|
||||
// });
|
||||
//services.AddAuthorization(option =>
|
||||
//{
|
||||
// option.AddPolicy("DefaultPolicy", builder =>
|
||||
// {
|
||||
// builder.RequireAuthenticatedUser();
|
||||
// builder.RequireClaim("scope", "PostOrderApi");
|
||||
// });
|
||||
//});
|
||||
|
||||
services.AddFluentValidationAutoValidation(p => p.DisableDataAnnotationsValidation = true);
|
||||
services.AddValidatorsFromAssemblyContaining<BarCodeUploadParamValidator>();
|
||||
|
||||
services.AddCors(option => option.AddPolicy("any", build =>
|
||||
{
|
||||
build
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyOrigin()
|
||||
.AllowAnyMethod();
|
||||
}));
|
||||
|
||||
services.AddAutoMapper();
|
||||
|
||||
services.AddSingleton<IMemoryCache, MemoryCache>();
|
||||
|
||||
services.AddSingleton(s =>
|
||||
{
|
||||
SqlSugarScope sqlSugarScope = new(new BccDbConnectionConfig().ConnectionConfig);
|
||||
|
||||
sqlSugarScope.Aop.OnLogExecuting = async (sql, pars) =>
|
||||
{
|
||||
|
||||
//await File.WriteAllTextAsync(@"C:\Users\admin\Desktop\123.txx", sql);
|
||||
};
|
||||
|
||||
sqlSugarScope.Ado.CommandTimeOut = 5;
|
||||
|
||||
sqlSugarScope.Aop.OnError = error =>
|
||||
{
|
||||
LogHelper.Error($"操作数据库出错 {error.Message} {error.StackTrace}");
|
||||
};
|
||||
|
||||
return sqlSugarScope;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置 HTTP 请求处理中间件。中间件顺序决定跨域、路由、认证授权和控制器执行时机,
|
||||
/// 末尾启动后台任务及电梯 PLC 通信功能。
|
||||
/// </summary>
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
app.UseCors("any");
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseAutoMapperConfig();
|
||||
app.UseGlobalServiceProvider();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
app.UseAllJobs();
|
||||
|
||||
app.UseElevatorPlc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用 Autofac 扫描领域、应用、业务和 RPC 程序集,注册约定命名的服务实现。
|
||||
/// </summary>
|
||||
/// <param name="builder">Autofac 容器构建器。</param>
|
||||
public void ConfigureContainer(ContainerBuilder builder)
|
||||
{
|
||||
builder
|
||||
.RegisterAssemblyTypes([
|
||||
Assembly.LoadFrom($"{AppDomain.CurrentDomain.BaseDirectory}JSMachine.WMS.Domain.dll"),
|
||||
Assembly.LoadFrom($"{AppDomain.CurrentDomain.BaseDirectory}JSMachine.WMS.App.dll"),
|
||||
Assembly.LoadFrom($"{AppDomain.CurrentDomain.BaseDirectory}JSMachine.WMS.Business.dll"),
|
||||
Assembly.LoadFrom($"{AppDomain.CurrentDomain.BaseDirectory}JSMachine.WMS.RPC.dll")
|
||||
])
|
||||
.Where(x => x.Name.EndsWith("Repository", StringComparison.OrdinalIgnoreCase) ||
|
||||
x.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase)||
|
||||
x.Name.EndsWith("Strategy", StringComparison.OrdinalIgnoreCase)||
|
||||
x.Name.EndsWith("Handler", StringComparison.OrdinalIgnoreCase))
|
||||
.AsImplementedInterfaces()
|
||||
.AsSelf()
|
||||
.SingleInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using FluentValidation;
|
||||
using JSMachine.WMS.Common.Dto.Http.In;
|
||||
|
||||
namespace JSMachine.WMS.WebHost.Validators
|
||||
{
|
||||
public class BarCodeUploadParamValidator:AbstractValidator<StockInByPdaRequestParam>
|
||||
{
|
||||
//public BarCodeUploadParamValidator()
|
||||
//{
|
||||
// RuleFor(p => p.BarCode)
|
||||
// .Must(p => !string.IsNullOrEmpty(p))
|
||||
// .WithMessage("条码不能为空");
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
|
||||
namespace JSMachine.WMS.WebHost
|
||||
{
|
||||
/// <summary>
|
||||
/// WebHost 进程启动入口,配置文件和 Autofac 容器由此加载。
|
||||
/// </summary>
|
||||
public static class WebHostEngine1
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建并运行 WebHost;宿主同时注册为 Windows 服务。
|
||||
/// </summary>
|
||||
public static void Start()
|
||||
{
|
||||
Host.CreateDefaultBuilder()
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||
{
|
||||
config
|
||||
.SetBasePath($"{hostingContext.HostingEnvironment.ContentRootPath}")
|
||||
.AddJsonFile("appSettingsWebhost.json", false, true)
|
||||
.AddEnvironmentVariables();
|
||||
})
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||
.UseWindowsService()
|
||||
.Build()
|
||||
.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"urls": "http://*:8078",
|
||||
|
||||
"AppSettings": {
|
||||
//"DataBaseCon": "Server=219.140.177.52,40001;Database=wms_jst;User ID=sa;Password=ibs-2017;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=True;Connection Timeout=5",
|
||||
"DataBaseCon": "Server=localhost;Database=wms_jst2.0;User ID=sa;Password=123456;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=True;Connection Timeout=5",
|
||||
"DelLogDate": 100,
|
||||
//放置模式(0-完全不混放 1-混合模式,优先同批次放一列,没有空库位再混放 2-完全混放模式,不用批次货物放一起)
|
||||
"PlcaementMod": 1,
|
||||
"ErpConfig": {
|
||||
"ErpType": 3, //Erp类型 0-企望ERP 1-IBS 2-晨龙 3-新荣
|
||||
"ErpUrl": "http://127.0.0.1:8078/",
|
||||
"ErpIP": "127.0.0.1",
|
||||
"ErpUploadBefore": -5, //回传Erp前几天数据
|
||||
"RetryNum": 5, //上传数据,重试次数
|
||||
|
||||
//新荣需要配置
|
||||
"QueryMateriaInforUrl": "wms_erp_interface/select/materiaInformation", //PDA扫合格证码获取物料信息
|
||||
"ProduceInUrl": "wms_erp_interface/api/wms/produce/in", //生产入库
|
||||
"ProduceOutUrl": "wms_erp_interface/erp/produce/out", //(生产退库)
|
||||
"SaleOutUrl": "wms_erp_interface/wms/sale/out", //销售出库接口
|
||||
"Userkey": "5601874e6cc011efa968258da89a748b" //用户标识
|
||||
},
|
||||
"RcsConfig": {
|
||||
"RcsUrl": "http://127.0.0.1:8078/", //"http://172.18.101.10:7000/",
|
||||
"CreateTaskUrl": "ics/taskOrder/addTask", //创建任务Url
|
||||
"CancelTaskUrl": "ics/out/task/cancelTask" //取消任务Url
|
||||
},
|
||||
"ElevatorConfig": [
|
||||
{
|
||||
"ElevatorNo": 1,
|
||||
"IP": "127.0.0.1",
|
||||
"Port": 502
|
||||
},
|
||||
{
|
||||
"ElevatorNo": 2,
|
||||
"IP": "192.168.1.5",
|
||||
"Port": 503
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user