wanshenmean
2026-02-11 e6b190354191122069b1a0518f050d6504f7ec5e
重构WMS服务并简化逻辑

清理并重构多个WMS服务:移除未使用的引用和DI参数,使用GetHashCode()标准化枚举值访问,简化空值检查和返回路径,并现代化循环/变量命名。在LocationInfoService中添加辅助方法(CalculateDepth, CreateLocationInfo)并整合位置初始化逻辑。通过入站/出站完成方法扩展ITaskService。通过改进查询、历史记录创建和提前退出来优化StockService操作(组盘/换盘/拆盘)。改进StockViewService的分页/详情处理并简化Sys_UserService登录/密码流和页面查询。整体提升了代码库的可读性、性能和一致性。
已修改10个文件
984 ■■■■■ 文件已修改
Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/18.0.988.22099/CodeChunks.db 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/18.0.988.22099/SemanticSymbols.db 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfo_HtyService.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_SystemService/Sys_UserService.cs 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 245 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/18.0.988.22099/CodeChunks.db
Binary files differ
Code/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/18.0.988.22099/SemanticSymbols.db
Binary files differ
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -1,23 +1,9 @@
using HslCommunication.WebSocket;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Const;
using WIDESEA_Core.DB;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_Core.Seed;
using WIDESEA_Core.Utilities;
using WIDESEA_DTO.Basic;
using WIDESEA_IBasicService;
@@ -27,124 +13,71 @@
{
    public partial class LocationInfoService : ServiceBase<Dt_LocationInfo, IRepository<Dt_LocationInfo>>, ILocationInfoService
    {
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly IRepository<Dt_StockInfo> _stockInfoRepository;
        public IRepository<Dt_LocationInfo> Repository => BaseDal;
        public LocationInfoService(IRepository<Dt_LocationInfo> BaseDal, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockInfoRepository) : base(BaseDal)
        public LocationInfoService(IRepository<Dt_LocationInfo> BaseDal) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoRepository = stockInfoRepository;
        }
        /// <summary>
        /// 批量启用货位
        /// </summary>
        /// <param name="keys">货位主键数组</param>
        /// <returns></returns>
        public WebResponseContent LocationEnableStatus(int[] keys)
        {
            List<Dt_LocationInfo> locationInfos = Repository.QueryData(x => keys.Contains(x.Id));
            locationInfos.ForEach(x =>
            {
                x.EnableStatus = EnableStatusEnum.Normal.ObjToInt();
            });
            var locationInfos = Repository.QueryData(x => keys.Contains(x.Id));
            locationInfos.ForEach(x => x.EnableStatus = EnableStatusEnum.Normal.GetHashCode());
            Repository.UpdateData(locationInfos);
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// 批量禁用货位
        /// </summary>
        /// <param name="keys">货位主键数组</param>
        /// <returns></returns>
        public WebResponseContent LocationDisableStatus(int[] keys)
        {
            List<Dt_LocationInfo> locationInfos = Repository.QueryData(x => keys.Contains(x.Id));
            locationInfos.ForEach(x =>
            {
                x.EnableStatus = EnableStatusEnum.Disable.ObjToInt();
            });
            var locationInfos = Repository.QueryData(x => keys.Contains(x.Id));
            locationInfos.ForEach(x => x.EnableStatus = EnableStatusEnum.Disable.GetHashCode());
            Repository.UpdateData(locationInfos);
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
        /// 单个启用货位
        /// </summary>
        /// <param name="key">货位主键</param>
        /// <returns></returns>
        public WebResponseContent LocationEnableStatus(int key)
        {
            return LocationEnableStatus(new int[] { key });
        }
        public WebResponseContent LocationEnableStatus(int key) => LocationEnableStatus(new[] { key });
        /// <summary>
        /// 单个禁用货位
        /// </summary>
        /// <param name="key">货位主键</param>
        /// <returns></returns>
        public WebResponseContent LocationDisableStatus(int key)
        {
            return LocationDisableStatus(new int[] { key });
        }
        public WebResponseContent LocationDisableStatus(int key) => LocationDisableStatus(new[] { key });
        /// <summary>
        /// 初始化货位
        /// </summary>
        /// <param name="initializationLocationDTO"></param>
        /// <returns></returns>
        public WebResponseContent InitializationLocation(InitializationLocationDTO initializationLocationDTO)
        public WebResponseContent InitializationLocation(InitializationLocationDTO dto)
        {
            try
            {
                (bool, string, object?) result = ModelValidate.ValidateModelData(initializationLocationDTO);
                if (!result.Item1) return WebResponseContent.Instance.Error(result.Item2);
                var (isValid, errorMsg, _) = ModelValidate.ValidateModelData(dto);
                if (!isValid) return WebResponseContent.Instance.Error(errorMsg);
                int depth = initializationLocationDTO.Depth;
                List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
                for (int i = 0; i < initializationLocationDTO.MaxRow; i++)
                var locationInfos = new List<Dt_LocationInfo>();
                int depth = dto.Depth;
                for (int row = 1; row <= dto.MaxRow; row++)
                {
                    if ((i + 1) % initializationLocationDTO.MaxRow == 1)
                    depth = CalculateDepth(row, dto.MaxRow, dto.Depth, depth);
                    for (int col = 1; col <= dto.MaxColumn; col++)
                    {
                        depth = initializationLocationDTO.Depth;
                    }
                    else if ((i + 1) % initializationLocationDTO.MaxRow == initializationLocationDTO.Depth + 1)
                    {
                        depth = 1;
                    }
                    else if ((i + 1) % initializationLocationDTO.MaxRow > 1 && (i + 1) % initializationLocationDTO.MaxRow <= initializationLocationDTO.Depth)
                    {
                        depth -= 1;
                    }
                    else
                    {
                        depth += 1;
                    }
                    for (int j = 0; j < initializationLocationDTO.MaxColumn; j++)
                    {
                        for (int k = 0; k < initializationLocationDTO.MaxLayer; k++)
                        for (int layer = 1; layer <= dto.MaxLayer; layer++)
                        {
                            Dt_LocationInfo locationInfo = new Dt_LocationInfo()
                            {
                                WarehouseId = 0,
                                Column = j + 1,
                                EnableStatus = EnableStatusEnum.Normal.ObjToInt(),
                                Layer = k + 1,
                                LocationStatus = LocationStatusEnum.Free.ObjToInt(),
                                LocationType = LocationTypeEnum.Undefined.ObjToInt(),
                                RoadwayNo = $"{initializationLocationDTO.Roadway.ToString()}",
                                Row = i + 1,
                                Depth = depth,
                            };
                            locationInfo.LocationCode = $"{locationInfo.RoadwayNo}-{locationInfo.Row.ToString().PadLeft(3, '0')}-{locationInfo.Column.ToString().PadLeft(3, '0')}-{locationInfo.Layer.ToString().PadLeft(3, '0')}-{locationInfo.Depth.ToString().PadLeft(2, '0')}";
                            locationInfo.LocationName = $"{locationInfo.RoadwayNo}巷道{locationInfo.Row.ToString().PadLeft(3, '0')}行{locationInfo.Column.ToString().PadLeft(3, '0')}列{locationInfo.Layer.ToString().PadLeft(3, '0')}层{locationInfo.Depth.ToString().PadLeft(2, '0')}深";
                            locationInfos.Add(locationInfo);
                            var location = CreateLocationInfo(dto.Roadway, row, col, layer, depth);
                            locationInfos.Add(location);
                        }
                    }
                }
                BaseDal.AddData(locationInfos);
                return WebResponseContent.Instance.OK();
            }
@@ -154,71 +87,67 @@
            }
        }
        private static int CalculateDepth(int row, int maxRow, int maxDepth, int currentDepth)
        {
            int mod = row % maxRow;
            if (mod == 1) return maxDepth;
            if (mod == maxDepth + 1) return 1;
            if (mod > 1 && mod <= maxDepth) return currentDepth - 1;
            return currentDepth + 1;
        }
        private static Dt_LocationInfo CreateLocationInfo(string roadwayNo, int row, int col, int layer, int depth)
        {
            return new Dt_LocationInfo
            {
                WarehouseId = 0,
                Row = row,
                Column = col,
                Layer = layer,
                Depth = depth,
                RoadwayNo = roadwayNo,
                EnableStatus = EnableStatusEnum.Normal.GetHashCode(),
                LocationStatus = LocationStatusEnum.Free.GetHashCode(),
                LocationType = LocationTypeEnum.Undefined.GetHashCode(),
                LocationCode = $"{roadwayNo}-{row:D3}-{col:D3}-{layer:D3}-{depth:D2}",
                LocationName = $"{roadwayNo}巷道{row:D3}行{col:D3}列{layer:D3}层{depth:D2}深"
            };
        }
        /// <summary>
        /// 获取空闲货位信息(根据巷道查询)
        /// </summary>
        /// <param name="RoadwayNo">巷道</param>
        /// <returns></returns>
        public async Task<Dt_LocationInfo?> GetLocationInfo(string RoadwayNo)
        public async Task<Dt_LocationInfo?> GetLocationInfo(string roadwayNo)
        {
            try
            {
                var locations = await BaseDal.QueryDataAsync(x => x.EnableStatus == EnableStatusEnum.Normal.GetHashCode() && x.RoadwayNo == RoadwayNo && x.LocationStatus == LocationStatusEnum.Free.GetHashCode());
            var locations = await BaseDal.QueryDataAsync(x =>
                x.EnableStatus == EnableStatusEnum.Normal.GetHashCode() &&
                x.RoadwayNo == roadwayNo &&
                x.LocationStatus == LocationStatusEnum.Free.GetHashCode());
                if (locations == null || locations.Count == 0)
                {
                    return null;
                }
                return locations.OrderBy(x => x.Layer).ThenBy(x => x.Depth).ThenBy(x => x.Column).ThenBy(x => x.Row).FirstOrDefault();
            }
            catch (Exception)
            {
                return null;
            }
            return locations?
                .OrderBy(x => x.Layer)
                .ThenBy(x => x.Depth)
                .ThenBy(x => x.Column)
                .ThenBy(x => x.Row)
                .FirstOrDefault();
        }
        /// <summary>
        /// 获取空闲货位信息(根据巷道查询)
        /// 获取货位信息(根据巷道和货位编码查询)
        /// </summary>
        /// <param name="RoadwayNo">巷道</param>
        /// <returns></returns>
        public async Task<Dt_LocationInfo?> GetLocationInfo(string RoadwayNo,string locationCode)
        public async Task<Dt_LocationInfo?> GetLocationInfo(string roadwayNo, string locationCode)
        {
            try
            {
                var locations = await BaseDal.QueryFirstAsync(x => x.RoadwayNo == RoadwayNo && x.LocationCode == locationCode);
                if (locations == null)
                {
                    return null;
                }
                return locations;
            }
            catch (Exception)
            {
                return null;
            }
            return await BaseDal.QueryFirstAsync(x => x.RoadwayNo == roadwayNo && x.LocationCode == locationCode);
        }
        /// <summary>
        /// 更新货位信息
        /// </summary>
        /// <param name="locationInfo"></param>
        /// <returns></returns>
        public async Task<bool> UpdateLocationInfoAsync(Dt_LocationInfo locationInfo)
        {
            try
            {
                return await BaseDal.UpdateDataAsync(locationInfo);
            }
            catch (Exception)
            {
                return false;
            }
            return await BaseDal.UpdateDataAsync(locationInfo);
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -60,5 +60,15 @@
        /// <param name="taskType"></param>
        /// <returns></returns>
        public Task<WebResponseContent> GetTasksLocationAsync(CreateTaskDto taskDto);
        /// <summary>
        /// 入库任务完成:添加库存,修改货位状态,删除任务数据,添加历史任务数据
        /// </summary>
        public Task<WebResponseContent> InboundFinishTaskAsync(CreateTaskDto taskDto);
        /// <summary>
        /// 出库任务完成 :修改库存,修改货位状态,删除任务数据,添加历史任务数据
        /// </summary>
        public Task<WebResponseContent> OutboundFinishTaskAsync(CreateTaskDto taskDto);
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -1,5 +1,4 @@
using AutoMapper;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_IStockService;
@@ -9,49 +8,44 @@
{
    public partial class StockInfoService : ServiceBase<Dt_StockInfo, IRepository<Dt_StockInfo>>, IStockInfoService
    {
        private readonly IMapper _mapper;
        public IRepository<Dt_StockInfo> Repository => BaseDal;
        public StockInfoService(IRepository<Dt_StockInfo> BaseDal, IMapper mapper) : base(BaseDal)
        public StockInfoService(IRepository<Dt_StockInfo> BaseDal) : base(BaseDal)
        {
            _mapper = mapper;
        }
        /// <summary>
        /// 获取库存信息列表(出库日期小于当前时间且库存状态为入库完成的记录)
        /// </summary>
        /// <returns></returns>
        public async Task<List<Dt_StockInfo>> GetStockInfoAsync()
        {
            return await BaseDal.QueryDataAsync(x => x.OutboundDate < DateTime.Now && x.StockStatus == StockStatusEmun.入库完成.GetHashCode());
            return await BaseDal.QueryDataAsync(x =>
                x.OutboundDate < DateTime.Now &&
                x.StockStatus == StockStatusEmun.入库完成.GetHashCode());
        }
        /// <summary>
        /// 获取库存信息列表(出库日期小于当前时间且库存状态为入库完成的记录,且仓库ID匹配)
        /// </summary>
        /// <param name="WarehouseId"></param>
        /// <returns></returns>
        public async Task<List<Dt_StockInfo>> GetStockInfoAsync(int WarehouseId)
        public async Task<List<Dt_StockInfo>> GetStockInfoAsync(int warehouseId)
        {
            return await BaseDal.QueryDataAsync(x => x.OutboundDate < DateTime.Now && x.StockStatus == StockStatusEmun.入库完成.GetHashCode() && x.WarehouseId == WarehouseId);
            return await BaseDal.QueryDataAsync(x =>
                x.OutboundDate < DateTime.Now &&
                x.StockStatus == StockStatusEmun.入库完成.GetHashCode() &&
                x.WarehouseId == warehouseId);
        }
        /// <summary>
        /// 获取库存信息(根据托盘码查询)
        /// </summary>
        /// <param name="PalletCode"></param>
        /// <returns></returns>
        public async Task<Dt_StockInfo> GetStockInfoAsync(string PalletCode)
        public async Task<Dt_StockInfo> GetStockInfoAsync(string palletCode)
        {
            return await BaseDal.QueryFirstAsync(x => x.PalletCode == PalletCode);
            return await BaseDal.QueryFirstAsync(x => x.PalletCode == palletCode);
        }
        /// <summary>
        /// 更新库存数据
        /// </summary>
        /// <param name="stockInfo"></param>
        /// <returns></returns>
        public async Task<bool> UpdateStockAsync(Dt_StockInfo stockInfo)
        {
            return await BaseDal.UpdateDataAsync(stockInfo);
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfo_HtyService.cs
@@ -1,5 +1,4 @@
using AutoMapper;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
@@ -8,13 +7,10 @@
{
    public partial class StockInfo_HtyService : ServiceBase<Dt_StockInfo_Hty, IRepository<Dt_StockInfo_Hty>>, IStockInfo_HtyService
    {
        private readonly IMapper _mapper;
        public IRepository<Dt_StockInfo_Hty> Repository => BaseDal;
        public StockInfo_HtyService(IRepository<Dt_StockInfo_Hty> BaseDal, IMapper mapper) : base(BaseDal)
        public StockInfo_HtyService(IRepository<Dt_StockInfo_Hty> BaseDal) : base(BaseDal)
        {
            _mapper = mapper;
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -11,20 +11,15 @@
    public class StockSerivce : IStockService
    {
        public IStockInfoDetailService StockInfoDetailService { get; }
        public IStockInfoService StockInfoService { get; }
        public IStockInfoDetail_HtyService StockInfoDetail_HtyService { get; }
        public IStockInfo_HtyService StockInfo_HtyService { get; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="stockInfoDetailService">库存明细服务</param>
        /// <param name="stockInfoService">库存服务</param>
        /// <param name="stockInfoDetail_HtyService">库存明细历史服务</param>
        /// <param name="stockInfo_HtyService">库存历史服务</param>
        public StockSerivce(IStockInfoDetailService stockInfoDetailService, IStockInfoService stockInfoService, IStockInfoDetail_HtyService stockInfoDetail_HtyService, IStockInfo_HtyService stockInfo_HtyService)
        public StockSerivce(
            IStockInfoDetailService stockInfoDetailService,
            IStockInfoService stockInfoService,
            IStockInfoDetail_HtyService stockInfoDetail_HtyService,
            IStockInfo_HtyService stockInfo_HtyService)
        {
            StockInfoDetailService = stockInfoDetailService;
            StockInfoService = stockInfoService;
@@ -35,15 +30,13 @@
        /// <summary>
        /// 组盘
        /// </summary>
        /// <param name="stock">组盘数据</param>
        /// <returns>是否成功</returns>
        public async Task<bool> GroupPallet(StockDTO stock)
        {
            // 组装明细数据
            var now = DateTime.Now;
            var details = stock.Details.Select(item => new Dt_StockInfoDetail()
            var details = stock.Details.Select(item => new Dt_StockInfoDetail
            {
                MaterielCode = "电芯",
                MaterielName = "电芯",
                StockQuantity = item.Quantity,
                Unit = "PCS",
                Creater = "system",
@@ -52,20 +45,17 @@
                EffectiveDate = now.AddYears(1).ToString(),
                SerialNumber = item.CellBarcode,
                InboundOrderRowNo = item.Channel,
                MaterielName = "电芯",
                Status = StockStatusEmun.组盘暂存.GetHashCode(),
            }).ToList();
            // 如果托盘已存在,直接新增明细
            var existingStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo);
            if (existingStock != null)
            {
                details.ForEach(detail => detail.StockId = existingStock.Id);
                details.ForEach(d => d.StockId = existingStock.Id);
                return await StockInfoDetailService.Repository.AddDataAsync(details) > 0;
            }
            // 托盘不存在则创建并写入明细
            var entity = new Dt_StockInfo()
            var entity = new Dt_StockInfo
            {
                PalletCode = stock.TargetPalletNo,
                WarehouseId = 1,
@@ -80,34 +70,23 @@
        /// <summary>
        /// 换盘
        /// </summary>
        /// <param name="stock">需要换盘的明细数据</param>
        /// <returns>是否成功</returns>
        public async Task<bool> ChangePallet(StockDTO stock)
        {
            // 参数校验
            if (stock == null || string.IsNullOrWhiteSpace(stock.TargetPalletNo) || string.IsNullOrWhiteSpace(stock.SourcePalletNo))
            if (stock == null ||
                string.IsNullOrWhiteSpace(stock.TargetPalletNo) ||
                string.IsNullOrWhiteSpace(stock.SourcePalletNo) ||
                string.Equals(stock.SourcePalletNo, stock.TargetPalletNo, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            // 新旧托盘一致不处理
            if (string.Equals(stock.SourcePalletNo, stock.TargetPalletNo, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            // 查询源托盘
            var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo);
            if (sourceStock == null)
            {
                return false;
            }
            if (sourceStock == null) return false;
            // 查询或创建目标托盘
            var targetStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo);
            if (targetStock == null)
            {
                var newStock = new Dt_StockInfo()
                var newStock = new Dt_StockInfo
                {
                    PalletCode = stock.TargetPalletNo,
                    WarehouseId = sourceStock.WarehouseId,
@@ -116,146 +95,103 @@
                };
                var newId = StockInfoService.Repository.AddData(newStock);
                if (newId <= 0)
                {
                    return false;
                }
                if (newId <= 0) return false;
                targetStock = newStock;
                targetStock.Id = newId;
            }
            // 获取需要转移的条码
            var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList();
            if (!serialNumbers.Any())
            {
            if (!serialNumbers.Any()) return false;
            var detailEntities = StockInfoDetailService.Repository.QueryData(
                d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
            if (!detailEntities.Any()) return false;
            if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "换盘")) <= 0)
                return false;
            }
            // 查询源托盘对应的明细
            var detailEntities = StockInfoDetailService.Repository.QueryData(d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
            if (!detailEntities.Any())
            {
            if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock, targetStock }, "换盘")) <= 0)
                return false;
            }
            // 写入历史记录
            var detailHistory = CreateDetailHistory(detailEntities, "换盘");
            if (await StockInfoDetail_HtyService.Repository.AddDataAsync(detailHistory) <= 0)
            {
                return false;
            }
            var stockHistory = CreateStockHistory(new List<Dt_StockInfo> { sourceStock, targetStock }, "换盘");
            if (await StockInfo_HtyService.Repository.AddDataAsync(stockHistory) <= 0)
            {
                return false;
            }
            // 更新明细的托盘主键
            detailEntities.ForEach(detail => detail.StockId = targetStock.Id);
            detailEntities.ForEach(d => d.StockId = targetStock.Id);
            return await StockInfoDetailService.Repository.UpdateDataAsync(detailEntities);
        }
        /// <summary>
        /// 拆盘
        /// </summary>
        /// <param name="stock">需要拆盘的明细数据</param>
        /// <returns>是否成功</returns>
        public async Task<bool> SplitPallet(StockDTO stock)
        {
            // 参数校验
            if (stock == null || string.IsNullOrWhiteSpace(stock.SourcePalletNo))
            {
                return false;
            }
            // 查询源托盘
            var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo);
            if (sourceStock == null)
            {
                return false;
            }
            if (sourceStock == null) return false;
            // 获取需要拆除的条码
            var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList();
            if (!serialNumbers.Any())
            {
                return false;
            }
            if (!serialNumbers.Any()) return false;
            // 查询源托盘对应的明细
            var detailEntities = StockInfoDetailService.Repository.QueryData(d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
            if (!detailEntities.Any())
            {
                return false;
            }
            var detailEntities = StockInfoDetailService.Repository.QueryData(
                d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber));
            if (!detailEntities.Any()) return false;
            // 写入历史记录
            var detailHistory = CreateDetailHistory(detailEntities, "拆盘");
            if (await StockInfoDetail_HtyService.Repository.AddDataAsync(detailHistory) <= 0)
            {
            if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "拆盘")) <= 0)
                return false;
            }
            var stockHistory = CreateStockHistory(new List<Dt_StockInfo> { sourceStock }, "拆盘");
            if (await StockInfo_HtyService.Repository.AddDataAsync(stockHistory) <= 0)
            {
            if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock }, "拆盘")) <= 0)
                return false;
            }
            // 删除明细
            return await StockInfoDetailService.Repository.DeleteDataAsync(detailEntities);
        }
        private List<Dt_StockInfoDetail_Hty> CreateDetailHistory(IEnumerable<Dt_StockInfoDetail> details, string operateType)
        private static List<Dt_StockInfoDetail_Hty> CreateDetailHistory(IEnumerable<Dt_StockInfoDetail> details, string operateType)
        {
            var now = DateTime.Now;
            return details.Select(detail => new Dt_StockInfoDetail_Hty
            return details.Select(d => new Dt_StockInfoDetail_Hty
            {
                SourceId = detail.Id,
                SourceId = d.Id,
                OperateType = operateType,
                InsertTime = now,
                StockId = detail.StockId,
                MaterielCode = detail.MaterielCode,
                MaterielName = detail.MaterielName,
                OrderNo = detail.OrderNo,
                BatchNo = detail.BatchNo,
                ProductionDate = detail.ProductionDate,
                EffectiveDate = detail.EffectiveDate,
                SerialNumber = detail.SerialNumber,
                StockQuantity = detail.StockQuantity,
                OutboundQuantity = detail.OutboundQuantity,
                Status = detail.Status,
                Unit = detail.Unit,
                InboundOrderRowNo = detail.InboundOrderRowNo,
                Remark = detail.Remark,
                Creater = detail.Creater,
                CreateDate = detail.CreateDate,
                Modifier = detail.Modifier,
                ModifyDate = detail.ModifyDate
                StockId = d.StockId,
                MaterielCode = d.MaterielCode,
                MaterielName = d.MaterielName,
                OrderNo = d.OrderNo,
                BatchNo = d.BatchNo,
                ProductionDate = d.ProductionDate,
                EffectiveDate = d.EffectiveDate,
                SerialNumber = d.SerialNumber,
                StockQuantity = d.StockQuantity,
                OutboundQuantity = d.OutboundQuantity,
                Status = d.Status,
                Unit = d.Unit,
                InboundOrderRowNo = d.InboundOrderRowNo,
                Remark = d.Remark,
                Creater = d.Creater,
                CreateDate = d.CreateDate,
                Modifier = d.Modifier,
                ModifyDate = d.ModifyDate
            }).ToList();
        }
        private List<Dt_StockInfo_Hty> CreateStockHistory(IEnumerable<Dt_StockInfo> stocks, string operateType)
        private static List<Dt_StockInfo_Hty> CreateStockHistory(IEnumerable<Dt_StockInfo> stocks, string operateType)
        {
            var now = DateTime.Now;
            return stocks.Select(stock => new Dt_StockInfo_Hty
            return stocks.Select(s => new Dt_StockInfo_Hty
            {
                SourceId = stock.Id,
                SourceId = s.Id,
                OperateType = operateType,
                InsertTime = now,
                PalletCode = stock.PalletCode,
                PalletType = stock.PalletType,
                LocationCode = stock.LocationCode,
                WarehouseId = stock.WarehouseId,
                StockStatus = stock.StockStatus,
                Remark = stock.Remark,
                Creater = stock.Creater,
                CreateDate = stock.CreateDate,
                Modifier = stock.Modifier,
                ModifyDate = stock.ModifyDate
                PalletCode = s.PalletCode,
                PalletType = s.PalletType,
                LocationCode = s.LocationCode,
                WarehouseId = s.WarehouseId,
                StockStatus = s.StockStatus,
                Remark = s.Remark,
                Creater = s.Creater,
                CreateDate = s.CreateDate,
                Modifier = s.Modifier,
                ModifyDate = s.ModifyDate
            }).ToList();
        }
    }
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs
@@ -1,13 +1,10 @@
using SqlSugar;
using System.Dynamic;
using System.Reflection;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.DB.Models;
using WIDESEA_Core.Helper;
//using WIDESEA_Core.HostedService;
using WIDESEA_Core.Utilities;
using WIDESEA_DTO.Stock;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
@@ -16,86 +13,71 @@
{
    public partial class StockViewService : IStockViewService
    {
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly SqlSugarClient _dbBase;
        public StockViewService(IUnitOfWorkManage unitOfWorkManage)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _dbBase = unitOfWorkManage.GetDbClient();
        }
        public virtual PageGridData<StockViewDTO> GetPageData(PageDataOptions options)
        {
            string where = options.ValidatePageOptions(typeof(StockViewDTO).GetProperties());
            //获取排序字段
            //Dictionary<string, OrderByType> orderbyDic = options.GetPageDataSort(typeof(StockViewDTO).GetProperties());
            //List<OrderByModel> orderByModels = new List<OrderByModel>();
            //foreach (var item in orderbyDic)
            //{
            //    OrderByModel orderByModel = new OrderByModel()
            //    {
            //        FieldName = item.Key,
            //        OrderByType = item.Value
            //    };
            //    orderByModels.Add(orderByModel);
            //}
            int totalCount = 0;
            ISugarQueryable<Dt_StockInfo> sugarQueryable1 = _dbBase.Queryable<Dt_StockInfo>();
            ISugarQueryable<Dt_LocationInfo> sugarQueryable = _dbBase.Queryable<Dt_LocationInfo>();
            ISugarQueryable<Dt_StockInfoDetail> sugarQueryable2 = _dbBase.Queryable<Dt_StockInfoDetail>();
            List<StockViewDTO> list = sugarQueryable1.InnerJoin(sugarQueryable, (b, a) => a.LocationCode == b.LocationCode).WhereIF(!string.IsNullOrEmpty(where), where).Select((b, a) => new StockViewDTO
            {
                LocationCode = b.LocationCode,
                Column = a.Column,
                CreateDate = b.CreateDate,
                Creater = b.Creater,
                Depth = a.Depth,
                EnalbeStatus = a.EnableStatus,
                Layer = a.Layer,
                LocationName = a.LocationName,
                LocationStatus = a.LocationStatus,
                LocationType = a.LocationType,
                Modifier = b.Modifier,
                ModifyDate = b.ModifyDate,
                PalletCode = b.PalletCode,
                StockRemark = b.Remark,
                RoadwayNo = a.RoadwayNo,
                Row = a.Row,
                StockId = b.Id,
                StockStatus = b.StockStatus,
                Details = b.Details,
            }).ToPageList(options.Page, options.Rows, ref totalCount);
            var list = _dbBase.Queryable<Dt_StockInfo>()
                .InnerJoin<Dt_LocationInfo>((b, a) => a.LocationCode == b.LocationCode)
                .WhereIF(!string.IsNullOrEmpty(where), where)
                .Select((b, a) => new StockViewDTO
                {
                    LocationCode = b.LocationCode,
                    Column = a.Column,
                    CreateDate = b.CreateDate,
                    Creater = b.Creater,
                    Depth = a.Depth,
                    EnalbeStatus = a.EnableStatus,
                    Layer = a.Layer,
                    LocationName = a.LocationName,
                    LocationStatus = a.LocationStatus,
                    LocationType = a.LocationType,
                    Modifier = b.Modifier,
                    ModifyDate = b.ModifyDate,
                    PalletCode = b.PalletCode,
                    StockRemark = b.Remark,
                    RoadwayNo = a.RoadwayNo,
                    Row = a.Row,
                    StockId = b.Id,
                    StockStatus = b.StockStatus,
                    Details = b.Details,
                })
                .ToPageList(options.Page, options.Rows, ref totalCount);
            return new PageGridData<StockViewDTO>(totalCount, list);
        }
        public virtual object GetDetailPage(PageDataOptions pageData)
        {
            Type t = typeof(StockViewDTO);
            if (pageData.Value == null)
                return new PageGridData<object>(total: 0, null);
            if (pageData.Value == null) return new PageGridData<object>(total: 0, null);
            string keyName = t.GetKeyName();
            ////生成查询条件
            //Expression<Func<TEntity, bool>> whereExpression = keyName.CreateExpression<TEntity>(pageData.Value, LinqExpressionType.Equal);
            var propertyInfo = typeof(StockViewDTO).GetProperties()
                .FirstOrDefault(x => x.GetCustomAttribute<Navigate>() != null);
            if (propertyInfo == null)
                return new PageGridData<object>(total: 0, null);
            var detailType = propertyInfo.PropertyType.GetGenericArguments()[0];
            var navigate = propertyInfo.GetCustomAttribute<Navigate>();
            if (navigate == null)
                return new PageGridData<object>(total: 0, null);
            int totalCount = 0;
            PropertyInfo? propertyInfo = t.GetProperties().FirstOrDefault(x => x.GetCustomAttribute<Navigate>() != null);
            if (propertyInfo != null)
            {
                Type detailType = propertyInfo.PropertyType.GetGenericArguments()[0];
                Navigate? navigate = propertyInfo.GetCustomAttribute<Navigate>();
                if (navigate != null)
                {
                    List<ExpandoObject> list = _dbBase.Queryable(detailType.Name, "detail").Where(navigate.GetName(), "=", pageData.Value).ToPageList(pageData.Page, pageData.Rows, ref totalCount);
                    return new PageGridData<ExpandoObject>(totalCount, list);
                }
            }
            return new PageGridData<object>(total: 0, null);
            var list = _dbBase.Queryable(detailType.Name, "detail")
                .Where(navigate.GetName(), "=", pageData.Value)
                .ToPageList(pageData.Page, pageData.Rows, ref totalCount);
            return new PageGridData<ExpandoObject>(totalCount, list);
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_SystemService/Sys_UserService.cs
@@ -1,5 +1,7 @@
using WIDESEA_Core.Authorization;
using SqlSugar;
using WIDESEA_Core;
using WIDESEA_Core.Authorization;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Const;
using WIDESEA_Core.Helper;
@@ -7,18 +9,8 @@
using WIDESEA_ISystemService;
using WIDESEA_Model;
using WIDESEA_Model.Models;
using WIDESEA_Core.BaseRepository;
using System.Net;
using WIDESEA_Core.Caches;
using SqlSugar;
using ICacheService = WIDESEA_Core.Caches.ICacheService;
using HslCommunication.WebSocket;
using System.Drawing.Drawing2D;
using System.Linq;
using MailKit.Search;
using OrderByType = SqlSugar.OrderByType;
using System.Drawing.Printing;
//using WIDESEA_Core.HostedService;
namespace WIDESEA_SystemService
{
@@ -41,62 +33,47 @@
        public WebResponseContent Login(LoginInfo loginInfo)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                //BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName);
                string msg = string.Empty;
                #region 临时使用
                try
                {
                    loginInfo.Password = loginInfo.Password.EncryptDES(AppSecret.User);
                }
                catch
                {
                catch { }
                }
                #endregion
                UserInfo user = BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName && x.UserPwd == loginInfo.Password, x => new UserInfo { HeadImageUrl = x.HeadImageUrl, RoleId = x.RoleId, TenantId = x.TenantId, UserId = x.UserId, UserName = x.UserName, UserTrueName = x.UserTrueName });
                if (user != null)
                {
                    object obj = _menuService.GetMenuActionList(user.RoleId);
                    if (obj is not IEnumerable<object> list)
                var user = BaseDal.QueryFirst(
                    x => x.UserName == loginInfo.UserName && x.UserPwd == loginInfo.Password,
                    x => new UserInfo
                    {
                        return WebResponseContent.Instance.Error("无登录权限");
                    }
                    if (!list.Any())
                    {
                        return WebResponseContent.Instance.Error("无登录权限");
                    }
                    string token = JwtHelper.IssueJwt(new TokenModelJwt()
                    {
                        UserId = user.UserId,
                        RoleId = user.RoleId,
                        UserName = user.UserName,
                        TenantId = user.TenantId,
                        HeadImageUrl = x.HeadImageUrl,
                        RoleId = x.RoleId,
                        TenantId = x.TenantId,
                        UserId = x.UserId,
                        UserName = x.UserName,
                        UserTrueName = x.UserTrueName
                    });
                    App.User.UpdateToke(token, user.UserId);
                    //if (PermissionDataHostService.UserRoles.FirstOrDefault(x => x.UserId == user.UserId) == null)
                    //    PermissionDataHostService.UserRoles.AddRange(PermissionDataHostService.GetUserRoles(Db, user.UserId));
                if (user == null)
                    return WebResponseContent.Instance.Error("账号或密码错误");
                    content = WebResponseContent.Instance.OK(data: new { token, userName = user.UserName, img = user.HeadImageUrl, user.UserTrueName });
                }
                else
                if (_menuService.GetMenuActionList(user.RoleId) is not IEnumerable<object> { } list || !list.Any())
                    return WebResponseContent.Instance.Error("无登录权限");
                var token = JwtHelper.IssueJwt(new TokenModelJwt
                {
                    content = WebResponseContent.Instance.Error("账号或密码错误");
                }
                    UserId = user.UserId,
                    RoleId = user.RoleId,
                    UserName = user.UserName,
                    TenantId = user.TenantId,
                });
                App.User.UpdateToke(token, user.UserId);
                return WebResponseContent.Instance.OK(data: new { token, userName = user.UserName, img = user.HeadImageUrl, user.UserTrueName });
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
                return WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        public override WebResponseContent UpdateData(SaveModel saveModel)
@@ -114,53 +91,41 @@
        public override PageGridData<Sys_User> GetPageData(PageDataOptions options)
        {
            int roleId = -1;
            //树形菜单传查询角色下所有用户
            if (options.Value != null)
            {
                roleId = options.Value.ObjToInt();
            }
            int roleId = options.Value?.ObjToInt() ?? -1;
            if (roleId <= 0)
            {
                if (App.User.IsHighestRole) return base.GetPageData(options);
                roleId = App.User.RoleId;
            }
            int totalCount = 0;
            List<int> roleIds = _roleService.GetAllChildrenRoleId(roleId).Where(x => x != roleId).ToList();
            ISugarQueryable<Sys_User> sugarQueryable = Db.Queryable<Sys_User>();
            var roleIds = _roleService.GetAllChildrenRoleId(roleId).Where(x => x != roleId).ToList();
            var sugarQueryable = Db.Queryable<Sys_User>();
            ValidatePageOptions(options, ref sugarQueryable);
            Dictionary<string, OrderByType> orderbyDic = options.GetPageDataSort(TProperties);
            List<OrderByModel> orderByModels = new List<OrderByModel>();
            foreach (var item in orderbyDic)
            {
                OrderByModel orderByModel = new OrderByModel()
                {
                    FieldName = item.Key,
                    OrderByType = item.Value
                };
                orderByModels.Add(orderByModel);
            }
            List<Sys_User> users = sugarQueryable.Where(x => roleIds.Contains(x.RoleId) || x.UserId == App.User.UserId).OrderBy(orderByModels).ToPageList(options.Page, options.Rows, ref totalCount);
            var orderByModels = options.GetPageDataSort(TProperties)
                .Select(item => new OrderByModel { FieldName = item.Key, OrderByType = item.Value })
                .ToList();
            int totalCount = 0;
            var users = sugarQueryable
                .Where(x => roleIds.Contains(x.RoleId) || x.UserId == App.User.UserId)
                .OrderBy(orderByModels)
                .ToPageList(options.Page, options.Rows, ref totalCount);
            return new PageGridData<Sys_User> { Rows = users, Total = totalCount };
        }
        public override WebResponseContent AddData(SaveModel saveModel)
        {
            string pwd = "123456";
            string uesrName = saveModel.MainData[nameof(Sys_User.UserName).FirstLetterToLower()].ToString();
            saveModel.MainData[nameof(Sys_User.UserPwd).FirstLetterToLower()] = pwd.EncryptDES(AppSecret.User);
            const string defaultPwd = "123456";
            string userName = saveModel.MainData[nameof(Sys_User.UserName).FirstLetterToLower()].ToString();
            saveModel.MainData[nameof(Sys_User.UserPwd).FirstLetterToLower()] = defaultPwd.EncryptDES(AppSecret.User);
            WebResponseContent content = base.AddData(saveModel);
            if (content.Status)
            {
                return WebResponseContent.Instance.OK($"用户新建成功.帐号{uesrName}密码{pwd}");
            }
            else
            {
                return content;
            }
            var content = base.AddData(saveModel);
            return content.Status
                ? WebResponseContent.Instance.OK($"用户新建成功.帐号{userName}密码{defaultPwd}")
                : content;
        }
        /// <summary>
@@ -188,16 +153,13 @@
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public WebResponseContent ModifyPwd(string oldPwd, string newPwd)
        {
            WebResponseContent content = WebResponseContent.Instance;
            oldPwd = oldPwd?.Trim();
            newPwd = newPwd?.Trim();
            string message = "";
            try
            {
                oldPwd = oldPwd?.Trim();
                newPwd = newPwd?.Trim();
                if (string.IsNullOrEmpty(oldPwd)) return WebResponseContent.Instance.Error("旧密码不能为空");
                if (string.IsNullOrEmpty(newPwd)) return WebResponseContent.Instance.Error("新密码不能为空");
                if (newPwd.Length < 6) return WebResponseContent.Instance.Error("密码不能少于6位");
@@ -205,49 +167,42 @@
                int userId = App.User.UserId;
                string userCurrentPwd = BaseDal.QueryFirst(x => x.UserId == userId, s => s.UserPwd);
                string _oldPwd = oldPwd.EncryptDES(AppSecret.User);
                if (_oldPwd != userCurrentPwd) return WebResponseContent.Instance.Error("旧密码不正确");
                string encryptedOldPwd = oldPwd.EncryptDES(AppSecret.User);
                if (encryptedOldPwd != userCurrentPwd) return WebResponseContent.Instance.Error("旧密码不正确");
                string _newPwd = newPwd.EncryptDES(AppSecret.User);
                if (userCurrentPwd == _newPwd) return WebResponseContent.Instance.Error("新密码不能与旧密码相同");
                string encryptedNewPwd = newPwd.EncryptDES(AppSecret.User);
                if (userCurrentPwd == encryptedNewPwd) return WebResponseContent.Instance.Error("新密码不能与旧密码相同");
                BaseDal.UpdateData(new Sys_User
                {
                    UserId = userId,
                    UserPwd = _newPwd,
                    UserPwd = encryptedNewPwd,
                    LastModifyPwdDate = DateTime.Now
                }, new List<string>
                {
                    nameof(Sys_User.LastModifyPwdDate),
                    nameof(Sys_User.UserPwd)
                });
                }, new List<string> { nameof(Sys_User.LastModifyPwdDate), nameof(Sys_User.UserPwd) });
                content = WebResponseContent.Instance.OK("密码修改成功");
                return WebResponseContent.Instance.OK("密码修改成功");
            }
            catch (Exception ex)
            catch (Exception)
            {
                message = ex.Message;
                content = WebResponseContent.Instance.Error("服务器了点问题,请稍后再试");
                return WebResponseContent.Instance.Error("服务器了点问题,请稍后再试");
            }
            return content;
        }
        public WebResponseContent ModifyUserPwd(string password, string userName)
        {
            WebResponseContent content = new WebResponseContent();
            string message = "";
            password = password?.Trim();
            try
            {
                password = password?.Trim();
                if (string.IsNullOrEmpty(password)) return WebResponseContent.Instance.Error("密码不能为空");
                //获取用户
                Sys_User user = BaseDal.QueryFirst(x => x.UserName == userName);
                var user = BaseDal.QueryFirst(x => x.UserName == userName);
                if (user == null) return WebResponseContent.Instance.Error("用户不存在");
                user.UserPwd = password.EncryptDES(AppSecret.User);
                BaseDal.UpdateData(user);
                if (App.User.UserId == user.UserId)
                {
                    string token = JwtHelper.IssueJwt(new TokenModelJwt()
                    var token = JwtHelper.IssueJwt(new TokenModelJwt
                    {
                        UserId = user.UserId,
                        RoleId = user.RoleId,
@@ -256,14 +211,13 @@
                    });
                    _cacheService.AddOrUpdate(user.UserId.ToString(), token);
                }
                return content.OK("更改成功");
                return WebResponseContent.Instance.OK("更改成功");
            }
            catch (Exception ex)
            catch (Exception)
            {
                message = ex.Message;
                content.Error("服务器了点问题,请稍后再试");
                return WebResponseContent.Instance.Error("服务器了点问题,请稍后再试");
            }
            return content;
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -1,21 +1,4 @@
#region << 版 本 注 释 >>
/*----------------------------------------------------------------
 * 命名空间:WIDESEA_TaskInfoService
 * 创建者:胡童庆
 * 创建时间:2024/8/2 16:13:36
 * 版本:V1.0.0
 * 描述:
 *
 * ----------------------------------------------------------------
 * 修改人:
 * 修改时间:
 * 版本:V1.0.1
 * 修改说明:
 *
 *----------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using AutoMapper;
using AutoMapper;
using SqlSugar;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.TaskEnum;
@@ -24,9 +7,6 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_DTO.Task;
using WIDESEA_IBasicService;
using WIDESEA_IInboundService;
using WIDESEA_IOutboundService;
using WIDESEA_IRecordService;
using WIDESEA_IStockService;
using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
@@ -36,26 +16,27 @@
    public partial class TaskService : ServiceBase<Dt_Task, IRepository<Dt_Task>>, ITaskService
    {
        private readonly IMapper _mapper;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly IStockInfoService _stockInfoService;
        private readonly ILocationInfoService _locationInfoService;
        public IRepository<Dt_Task> Repository => BaseDal;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
                {nameof(Dt_Task.Grade),OrderByType.Desc },
                {nameof(Dt_Task.CreateDate),OrderByType.Asc},
            };
        private readonly Dictionary<string, OrderByType> _taskOrderBy = new()
        {
            { nameof(Dt_Task.Grade), OrderByType.Desc },
            { nameof(Dt_Task.CreateDate), OrderByType.Asc },
        };
        public List<int> TaskTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, ILocationInfoService locationInfoService) : base(BaseDal)
        public TaskService(
            IRepository<Dt_Task> BaseDal,
            IMapper mapper,
            IStockInfoService stockInfoService,
            ILocationInfoService locationInfoService) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
            _locationInfoService = locationInfoService;
        }
@@ -63,21 +44,21 @@
        /// <summary>
        /// 创建任务(组盘入库任务、空托盘回库任务)
        /// </summary>
        /// <param name="taskDto">要创建的出库任务的详细信息。不能为null。</param>
        /// <returns>是否成功</returns>
        public async Task<WebResponseContent> CreateTaskInboundAsync(CreateTaskDto taskDto)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                if (string.IsNullOrWhiteSpace(taskDto.PalletCode) || string.IsNullOrWhiteSpace(taskDto.SourceAddress) || string.IsNullOrWhiteSpace(taskDto.TargetAddress) || string.IsNullOrWhiteSpace(taskDto.Roadway))
                if (string.IsNullOrWhiteSpace(taskDto.PalletCode) ||
                    string.IsNullOrWhiteSpace(taskDto.SourceAddress) ||
                    string.IsNullOrWhiteSpace(taskDto.TargetAddress) ||
                    string.IsNullOrWhiteSpace(taskDto.Roadway))
                {
                    return content.Error("Invalid task details.");
                    return WebResponseContent.Instance.Error("Invalid task details.");
                }
                if (taskDto.TaskType != TaskTypeEnum.Inbound || taskDto.TaskType != TaskTypeEnum.InEmpty)
                if (taskDto.TaskType != TaskTypeEnum.Inbound && taskDto.TaskType != TaskTypeEnum.InEmpty)
                {
                    return content.Error("Invalid task details.");
                    return WebResponseContent.Instance.Error("Invalid task details.");
                }
                var task = new Dt_Task
@@ -97,66 +78,54 @@
                    Creater = "system"
                };
                var result = await Repository.AddDataAsync(task) > 0 ? true : false;
                if (result)
                {
                    var WmstaskDto = _mapper.Map<WMSTaskDTO>(task);
                    return content.OK("任务创建成功", WmstaskDto);
                }
                else
                {
                    return content.Error("任务创建失败");
                }
                var result = await Repository.AddDataAsync(task) > 0;
                if (!result) return WebResponseContent.Instance.Error("任务创建失败");
                var wmstaskDto = _mapper.Map<WMSTaskDTO>(task);
                return WebResponseContent.Instance.OK("任务创建成功", wmstaskDto);
            }
            catch (Exception ex)
            {
                return content.Error($"任务创建失败: {ex.Message}");
                return WebResponseContent.Instance.Error($"任务创建失败: {ex.Message}");
            }
        }
        /// <summary>
        /// 根据指定的任务详情异步创建新的出库任务。
        /// 根据指定的任务详情异步创建新的出库任务
        /// </summary>
        /// <param name="taskDto">要创建的出库任务的详细信息。不能为null。</param>
        /// <returns>表示异步操作的任务。任务结果包含表示已创建的出库任务的<see cref="WMSTaskDTO"/>,如果任务无法创建则为<see langword="null"/>。</returns>
        public async Task<WebResponseContent> CreateTaskOutboundAsync(CreateTaskDto taskDto)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var stockResult = await _stockInfoService.GetStockInfoAsync(taskDto.WarehouseId);
                if (stockResult == null || !stockResult.Any())
                    return WebResponseContent.Instance.Error("未找到库存信息");
                List<Dt_StockInfo>? stockResult = await _stockInfoService.GetStockInfoAsync(taskDto.WarehouseId);
                var taskList = new List<Dt_Task>();
                foreach (var item in stockResult)
                var taskList = stockResult.Select(item => new Dt_Task
                {
                    var taskInfo = new Dt_Task()
                    {
                        WarehouseId = item.WarehouseId,
                        PalletCode = item.PalletCode,
                        PalletType = item.PalletType,
                        SourceAddress = item.LocationCode,
                        TargetAddress = taskDto.TargetAddress,
                        Roadway = item.LocationDetails.RoadwayNo,
                        TaskType = TaskTypeEnum.Outbound.GetHashCode(),
                        TaskStatus = TaskStatusEnum.New.GetHashCode(),
                        Grade = 1,
                        TaskNum = 0,
                        CurrentAddress = item.LocationCode,
                        NextAddress = taskDto.TargetAddress,
                        Creater = "system",
                    };
                    taskList.Add(taskInfo);
                }
                    WarehouseId = item.WarehouseId,
                    PalletCode = item.PalletCode,
                    PalletType = item.PalletType,
                    SourceAddress = item.LocationCode,
                    TargetAddress = taskDto.TargetAddress,
                    Roadway = item.LocationDetails.RoadwayNo,
                    TaskType = TaskTypeEnum.Outbound.GetHashCode(),
                    TaskStatus = TaskStatusEnum.New.GetHashCode(),
                    Grade = 1,
                    TaskNum = 0,
                    CurrentAddress = item.LocationCode,
                    NextAddress = taskDto.TargetAddress,
                    Creater = "system",
                }).ToList();
                var result = await BaseDal.AddDataAsync(taskList) > 0;
                var wmstaskDto = result ? _mapper.Map<WMSTaskDTO>(taskList) : null;
                return content.OK(result ? "任务创建成功" : "任务创建失败", wmstaskDto);
                return WebResponseContent.Instance.OK(result ? "任务创建成功" : "任务创建失败", wmstaskDto);
            }
            catch (Exception e)
            catch (Exception ex)
            {
                return content.Error($"任务创建失败: {e.Message}");
                return WebResponseContent.Instance.Error($"任务创建失败: {ex.Message}");
            }
        }
@@ -164,76 +133,114 @@
        /// <summary>
        /// 获取可入库货位
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <param name="taskType"></param>
        /// <returns></returns>
        public async Task<WebResponseContent> GetTasksLocationAsync(CreateTaskDto taskDto)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var stockResult = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode);
                if (stockResult == null) return content.Error("未找到对应的任务");
                var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode);
                if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务");
                var locationInfo = await _locationInfoService.GetLocationInfo(task.Roadway);
                if (locationInfo == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                var locationInfo = await _locationInfoService.GetLocationInfo(stockResult.Roadway);
                if (locationInfo == null) return content.Error("未找到对应的货位");
                // 更新货位信息
                locationInfo.LocationStatus = LocationStatusEnum.FreeLock.GetHashCode();
                task.CurrentAddress = taskDto.SourceAddress;
                task.NextAddress = locationInfo.LocationCode;
                task.TargetAddress = taskDto.TargetAddress;
                task.TaskStatus = TaskStatusEnum.Line_Finish.GetHashCode();
                // 跟新任务信息
                stockResult.CurrentAddress = taskDto.SourceAddress;
                stockResult.NextAddress = locationInfo.LocationCode;
                stockResult.TargetAddress = taskDto.TargetAddress;
                stockResult.TaskStatus = TaskStatusEnum.Line_Finish.GetHashCode();
                var updateResult = await BaseDal.UpdateDataAsync(stockResult);
                var updateResult = await BaseDal.UpdateDataAsync(task);
                var locationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo);
                return content.OK(updateResult && locationResult ? "任务更新成功" : "任务更新失败", locationInfo.LocationCode);
                return WebResponseContent.Instance.OK(
                    updateResult && locationResult ? "任务更新成功" : "任务更新失败",
                    locationInfo.LocationCode);
            }
            catch (Exception ex)
            {
                return content.Error($"获取任务失败: {ex.Message}");
                return WebResponseContent.Instance.Error($"获取任务失败: {ex.Message}");
            }
        }
        // 任务完成。添加库存,修改货位状态,删除任务数据,添加历史任务数据
        public async Task<WebResponseContent> FinishTaskAsync(CreateTaskDto taskDto)
        /// <summary>
        /// 入库任务完成:添加库存,修改货位状态,删除任务数据,添加历史任务数据
        /// </summary>
        public async Task<WebResponseContent> InboundFinishTaskAsync(CreateTaskDto taskDto)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var taskResult = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode);
                if (taskResult == null) return content.Error("未找到对应的任务");
                var locationResult = await _locationInfoService.GetLocationInfo(taskResult.Roadway, taskDto.PalletCode);
                if (locationResult == null) return content.Error("未找到对应的货位");
                var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode);
                if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务");
                // 添加库存信息
                var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.TargetAddress);
                if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode);
                stockInfo.LocationCode = locationResult.LocationCode;
                stockInfo.LocationId = locationResult.Id;
                stockInfo.OutboundDate = taskResult.Roadway.Contains("GW") ? DateTime.Now.AddHours(2) : taskResult.Roadway.Contains("CW") ? DateTime.Now.AddHours(1) : DateTime.Now.AddHours(0);
                stockInfo.LocationCode = location.LocationCode;
                stockInfo.LocationId = location.Id;
                stockInfo.OutboundDate = task.Roadway switch
                {
                    var r when r.Contains("GW") => DateTime.Now.AddHours(2),
                    var r when r.Contains("CW") => DateTime.Now.AddHours(1),
                    _ => DateTime.Now
                };
                // 修改货位状态
                locationResult.LocationStatus = LocationStatusEnum.InStock.GetHashCode();
                var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationResult);
                var addStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !addStockResult) return content.Error("任务完成失败");
                location.LocationStatus = LocationStatusEnum.InStock.GetHashCode();
                // 删除任务数据
                var deleteTaskResult = await BaseDal.DeleteDataAsync(taskResult);
                var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location);
                var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !updateStockResult)
                    return WebResponseContent.Instance.Error("任务完成失败");
                // 添加历史任务数据
                var historyTask = _mapper.Map<Dt_Task_Hty>(taskResult);
                var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
                if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
                var historyTask = _mapper.Map<Dt_Task_Hty>(task);
                historyTask.InsertTime = DateTime.Now;
                if (!deleteTaskResult) return content.Error("任务完成失败");
                return content.OK("任务完成");
                return WebResponseContent.Instance.OK("任务完成");
            }
            catch (Exception ex)
            {
                return content.Error($"完成任务失败: {ex.Message}");
                return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}");
            }
        }
        /// <summary>
        /// 出库任务完成 :修改库存,修改货位状态,删除任务数据,添加历史任务数据
        /// </summary>
        public async Task<WebResponseContent> OutboundFinishTaskAsync(CreateTaskDto taskDto)
        {
            try
            {
                var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode);
                if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务");
                var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress);
                if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); stockInfo.LocationCode = location.LocationCode;
                stockInfo.LocationId = location.Id;
                stockInfo.OutboundDate = DateTime.Now;
                location.LocationStatus = LocationStatusEnum.Free.GetHashCode();
                var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location);
                var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !updateStockResult)
                    return WebResponseContent.Instance.Error("任务完成失败");
                var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
                if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
                var historyTask = _mapper.Map<Dt_Task_Hty>(task);
                historyTask.InsertTime = DateTime.Now;
                return WebResponseContent.Instance.OK("任务完成");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}");
            }
        }
    }