wanshenmean
12 小时以前 314076388f664f8ce1a1d19c4c9717fe54634e05
Merge branch 'dev' of http://115.159.85.185:8098/r/SuZhouGuanHong/ShanMeiXinNengYuan into dev
已删除1个文件
已修改13个文件
346 ■■■■ 文件已修改
Code/WMS/WIDESEA_WMSClient/public/webconfig.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/api/http.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/basic/extend/GetLocationStatus.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/Home.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/basic/locationInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockChat.vue 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/taskinfo/task.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/taskinfo/task_hty.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_AGV.cs 141 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Record/LocationStatusChangeRecordController.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/极卷库AGV接口/~$极卷库出入库.docx 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/public/webconfig.js
@@ -1,4 +1,4 @@
window.webConfig = {
    "webApiBaseUrl": "http://localhost:9291/",
    "webApiProduction":"http://localhost:9291/"
    "webApiProduction":"http://192.168.60.30:9291/"
}
Code/WMS/WIDESEA_WMSClient/src/api/http.js
@@ -15,7 +15,7 @@
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
}
else if (process.env.NODE_ENV == 'debug') {
    axios.defaults.baseURL = 'http://127.0.0.1:8098/';
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
}
else if (process.env.NODE_ENV == 'production') {
Code/WMS/WIDESEA_WMSClient/src/extension/basic/extend/GetLocationStatus.vue
@@ -200,6 +200,7 @@
    open(row) {
      this.row = row;
      this.showDetialBox = true;
      this.tableData = [];
      this.getDetailData();
      this.getDictionaryData();
    },
Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -104,6 +104,7 @@
    async loadOverview() {
      try {
        const res = await this.http.get("/api/Dashboard/Overview");
        console.log("总览数据", res.Data);
        if (res.Status && res.Data) {
          this.overviewData = res.Data;
          this.updateTodayChart();
Code/WMS/WIDESEA_WMSClient/src/views/basic/locationInfo.vue
@@ -81,7 +81,7 @@
        field: "locationCode",
        title: "货位编号",
        type: "string",
        width: 200,
        width: 120,
        align: "left",
      },
      {
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockChat.vue
@@ -1,12 +1,8 @@
<template>
    <div class="stock-chat-container">
        <el-tabs v-model="activeWarehouse" @tab-change="onWarehouseChange">
            <el-tab-pane
                v-for="wh in warehouseList"
                :key="wh.warehouseId || wh.id"
                :label="wh.warehouseName"
                :name="wh.warehouseId || wh.id"
            />
            <el-tab-pane v-for="wh in warehouseList" :key="wh.warehouseId || wh.id" :label="wh.warehouseName"
                :name="wh.warehouseId || wh.id" />
        </el-tabs>
        <div class="toolbar">
@@ -57,11 +53,15 @@
            <div v-if="selectedLocation" class="detail-content">
                <el-descriptions :column="2" border>
                    <el-descriptions-item label="货位编号">{{ selectedLocation.locationCode }}</el-descriptions-item>
                    <el-descriptions-item label="货位状态">{{ getLocationStatusText(selectedLocation.locationStatus) }}</el-descriptions-item>
                    <el-descriptions-item label="货位状态">{{ getLocationStatusText(selectedLocation.locationStatus)
                        }}</el-descriptions-item>
                    <el-descriptions-item label="托盘编号">{{ selectedLocation.palletCode || '无' }}</el-descriptions-item>
                    <el-descriptions-item label="库存状态">{{ getStockStatusText(selectedLocation.stockStatus) }}</el-descriptions-item>
                    <el-descriptions-item label="总库存">{{ selectedLocation.stockQuantity }}{{ selectedLocation.unit || '' }}</el-descriptions-item>
                    <el-descriptions-item label="出库日期">{{ selectedLocation.outboundDate }}{{ selectedLocation.unit || '' }}</el-descriptions-item>
                    <el-descriptions-item label="库存状态">{{ getStockStatusText(selectedLocation.stockStatus)
                        }}</el-descriptions-item>
                    <el-descriptions-item label="总库存">{{ selectedLocation.stockQuantity }}{{ selectedLocation.unit || ''
                        }}</el-descriptions-item>
                    <el-descriptions-item label="出库日期">{{ selectedLocation.outboundDate }}{{ selectedLocation.unit || ''
                        }}</el-descriptions-item>
                </el-descriptions>
                <div v-if="selectedLocation.details && selectedLocation.details.length > 0" class="detail-table">
@@ -766,6 +766,16 @@
async function loadWarehouseData(warehouseId) {
    try {
        // æ¸…除高亮框
        if (selectionOutline) {
            selectionOutline.visible = false
        }
        selectedLocation.value = null
        // æ¸…空筛选条件
        filterStockStatus.value = null
        filterMaterielCode.value = null
        filterBatchNo.value = null
        const res = await proxy.http.get(`/api/StockInfo/Get3DLayout?warehouseId=${warehouseId}`)
        if (res.status && res.data) {
            const data = res.data
@@ -1139,9 +1149,25 @@
}
async function onWarehouseChange(warehouseId) {
    // æ¸…除选中的高亮框
    if (selectionOutline) {
        selectionOutline.visible = false
    }
    // æ¸…除选中的货位数据
    selectedLocation.value = null
    // æ¸…空所有筛选条件
    filterStockStatus.value = null
    filterMaterielCode.value = null
    filterBatchNo.value = null
    // æ¸…空筛选选项列表
    materielCodeList.value = []
    batchNoList.value = []
    // åŠ è½½æ–°ä»“åº“æ•°æ®
    await loadWarehouseData(warehouseId)
}
function onWindowResize() {
    if (!canvasContainer.value || !camera || !renderer) {
        return
Code/WMS/WIDESEA_WMSClient/src/views/taskinfo/task.vue
@@ -110,14 +110,14 @@
        field: "sourceAddress",
        title: "起始地址",
        type: "int",
        width: 220,
        width: 120,
        align: "left",
      },
      {
        field: "targetAddress",
        title: "目标地址",
        type: "string",
        width: 220,
        width: 120,
        align: "left",
      },
      {
@@ -141,13 +141,13 @@
        width: 90,
        align: "left",
      },
      {
        field: "grade",
        title: "优先级",
        type: "int",
        width: 80,
        align: "left",
      },
      // {
      //   field: "grade",
      //   title: "优先级",
      //   type: "int",
      //   width: 80,
      //   align: "left",
      // },
      {
        field: "depth",
        title: "深度",
Code/WMS/WIDESEA_WMSClient/src/views/taskinfo/task_hty.vue
@@ -110,14 +110,14 @@
        field: "sourceAddress",
        title: "起始地址",
        type: "int",
        width: 220,
        width: 120,
        align: "left",
      },
      {
        field: "targetAddress",
        title: "目标地址",
        type: "string",
        width: 220,
        width: 120,
        align: "left",
      },
      // {
@@ -142,13 +142,13 @@
        align: "left",
        hidden: true,
      },
      {
        field: "grade",
        title: "优先级",
        type: "int",
        width: 80,
        align: "left",
      },
      // {
      //   field: "grade",
      //   title: "优先级",
      //   type: "int",
      //   width: 80,
      //   align: "left",
      // },
      {
        field: "depth",
        title: "深度",
Code/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs
@@ -1,4 +1,5 @@
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_DTO.Stock;
using WIDESEA_Model.Models;
@@ -56,5 +57,12 @@
        /// <param name="warehouseId">仓库ID</param>
        /// <returns>3D布局DTO</returns>
        Task<Stock3DLayoutDTO> Get3DLayoutAsync(int warehouseId);
        /// <summary>
        /// ä½¿ç”¨äº‹åŠ¡åˆ é™¤åº“å­˜å’Œæ˜Žç»†ä¿¡æ¯ï¼ˆå…ˆæŸ¥è¯¢å†åˆ é™¤ï¼‰
        /// </summary>
        /// <param name="stockId">库存ID</param>
        /// <returns>删除结果</returns>
        Task<WebResponseContent> DeleteStockWithDetailsAsync(int stockId);
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -30,6 +30,8 @@
        /// </summary>
        private readonly IWarehouseService _warehouseService;
        private readonly IRecordService _recordService;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly IStockInfoDetailService _stockInfoDetailService;
        /// <summary>
        /// æž„造函数
@@ -39,11 +41,15 @@
            IRepository<Dt_StockInfo> baseDal,
            ILocationInfoService locationInfoService,
            IWarehouseService warehouseService,
            IRecordService recordService) : base(baseDal)
            IRecordService recordService,
            IUnitOfWorkManage unitOfWorkManage,
            IStockInfoDetailService stockInfoDetailService) : base(baseDal)
        {
            _locationInfoService = locationInfoService;
            _warehouseService = warehouseService;
            _recordService = recordService;
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoDetailService = stockInfoDetailService;
        }
        /// <summary>
@@ -316,5 +322,64 @@
                Locations = locationItems
            };
        }
        /// <summary>
        /// ä½¿ç”¨äº‹åŠ¡åˆ é™¤åº“å­˜å’Œæ˜Žç»†ä¿¡æ¯ï¼ˆå…ˆæŸ¥è¯¢å†åˆ é™¤ï¼‰
        /// </summary>
        /// <param name="stockId">库存ID</param>
        /// <returns>删除结果</returns>
        public async Task<WebResponseContent> DeleteStockWithDetailsAsync(int stockId)
        {
            if (stockId <= 0)
                return WebResponseContent.Instance.Error("库存ID无效");
            _unitOfWorkManage.BeginTran();
            try
            {
                // å…ˆæŸ¥è¯¢åº“存信息(包含明细)
                var stockInfo = await BaseDal.QueryDataNavFirstAsync(x => x.Id == stockId);
                if (stockInfo == null)
                {
                    _unitOfWorkManage.RollbackTran();
                    return WebResponseContent.Instance.Error("库存记录不存在");
                }
                // æŸ¥è¯¢å¹¶åˆ é™¤åº“存明细记录
                var existingDetails = await _stockInfoDetailService.Repository.QueryDataAsync(x => x.StockId == stockId);
                if (existingDetails != null && existingDetails.Any())
                {
                    var deleteDetailResult = await _stockInfoDetailService.Repository.DeleteDataAsync(existingDetails);
                    if (!deleteDetailResult)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return WebResponseContent.Instance.Error("删除库存明细记录失败");
                    }
                }
                // åˆ é™¤åº“存主记录
                var deleteStockResult = await BaseDal.DeleteDataAsync(stockInfo);
                if (!deleteStockResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return WebResponseContent.Instance.Error("删除库存主记录失败");
                }
                _unitOfWorkManage.CommitTran();
                // è®°å½•库存变更日志
                var saveRecordResult = await _recordService.AddStockChangeRecordAsync(stockInfo, null, StockChangeTypeEnum.Outbound, remark: "库存删除");
                if (!saveRecordResult)
                {
                    return WebResponseContent.Instance.Error("库存变更记录保存失败");
                }
                return WebResponseContent.Instance.OK("库存删除成功");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error($"删除库存和明细时发生异常: {ex.Message}");
            }
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_AGV.cs
@@ -1,5 +1,6 @@
using Mapster;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
@@ -8,6 +9,7 @@
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Task;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
namespace WIDESEA_TaskInfoService
@@ -168,7 +170,7 @@
                    return response.OK();
                if (task.TaskStatus == (int)TaskInStatusEnum.InNew)
                    return CancelAgvInboundTask(task);
                    return await CancelAgvInboundTask(task);
                if (task.TaskStatus == (int)TaskOutStatusEnum.OutNew)
                    return await CancelAgvOutboundTaskAsync(task);
@@ -300,35 +302,117 @@
                return response.Error($"当前托盘{dto.TrayNumber}已经入库了");
            // åˆ›å»ºåº“存明细
            var details = new Dt_StockInfoDetail
            {
                MaterielCode = dto.ProductNo,
                MaterielName = dto.ProductName,
                StockQuantity = int.TryParse(dto.Quantity, out int quantity) ? quantity : 0,
                Unit = dto.UomCode,
                OrderNo = dto.ProductNo,
                ProductionDate =dto.ProductionDate,
                EffectiveDate = dto.LowerLimitTime,
                SerialNumber = dto.TrayNumber,
                Status = (int)StockStatusEmun.入库确认,
                InboundOrderRowNo = 1,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}"
            };
            // åˆ›å»ºåº“存主记录
            var stock = new Dt_StockInfo
            {
                PalletCode = dto.TrayNumber,
                PalletType = dto.Floor,
                WarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1,
                StockStatus = (int)StockStatusEmun.入库确认,
                Creater = StockConstants.AGV_USER,
                CreateDate = DateTime.Now,
                Remark = $"AGV入库任务创建,任务号:{dto.TaskId}",
                Details = new List<Dt_StockInfoDetail> { details }
            };
            task.TaskType = (int)TaskInboundTypeEnum.Inbound;
            task.TaskStatus = (int)TaskInStatusEnum.InNew;
            task.CurrentAddress = task.SourceAddress;
            var addResult = await BaseDal.AddDataAsync(task) > 0;
            return addResult ? null : response.Error("入库任务创建失败");
            _unitOfWorkManage.BeginTran();
            try
            {
                // å…ˆåˆ›å»ºä»»åŠ¡
                var taskResult = await BaseDal.AddDataAsync(task) > 0;
                if (!taskResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("入库任务创建失败");
                }
                var result = _stockInfoService.Repository.AddData(stock, x => x.Details);
                if (result)
                {
                    _unitOfWorkManage.CommitTran();
                    return null;
                }
                else
                {
                    _unitOfWorkManage.RollbackTran();
                    return response.Error("库存信息创建失败");
                }
                // ä½¿ç”¨åº“存服务添加库存主记录和明细
                //var stockResult = await _stockInfoService.AddStockWithDetailsUsingTransactionAsync(stock);
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"入库任务创建异常:{ex.Message}");
            }
        }
        // å‡ºåº“创建
        private async Task<AGVResponse?> CreateAgvOutboundTaskAsync(Dt_Task task, ApplyInOutDto dto)
        {
            AGVResponse response = new AGVResponse();
            // æ£€æŸ¥åº“存是否存在
            var stockInfo = await _stockInfoService.GetStockInfoAsync(dto.TrayNumber);
            if (stockInfo == null)
                return response.Error($"未找到托盘{dto.TrayNumber}的库存信息");
            //if (stockInfo.WarehouseId != dto.YinYang)
            //    return response.Error($"托盘{dto.TrayNumber}不属于当前{(dto.YinYang == 1 ? "阴极" : "阳极")}");
            // æ£€æŸ¥åº“存是否有明细(即是否真的有库存)
            if (stockInfo.Details == null || !stockInfo.Details.Any())
                return response.Error($"托盘{dto.TrayNumber}没有库存明细,无法出库");
            // æ£€æŸ¥åº“存总数量是否大于0
            var totalQuantity = stockInfo.Details.Sum(d => d.StockQuantity);
            if (totalQuantity <= 0)
                return response.Error($"托盘{dto.TrayNumber}库存数量不足,无法出库");
            // æ ¹æ®dto参数进一步验证库存信息
            if (!string.IsNullOrEmpty(dto.ProductNo))
            {
                // æ£€æŸ¥åº“存明细中是否包含指定的物料编码
                var hasMatchingMaterial = stockInfo.Details.Any(d => d.MaterielCode == dto.ProductNo);
                if (!hasMatchingMaterial)
                    return response.Error($"托盘{dto.TrayNumber}中没有物料编码为{dto.ProductNo}的库存,无法出库");
            }
            // æ£€æŸ¥åº“存状态是否允许出库
            if (stockInfo.StockStatus != (int)StockStatusEmun.入库完成)
                return response.Error($"托盘{dto.TrayNumber}正在移动中,请稍后!");
            // æ£€æŸ¥è´§ä½ä¿¡æ¯
            var locationInfo = await _locationInfoService.GetLocationInfo(stockInfo.LocationCode);
            if (locationInfo == null)
                return response.Error($"未找到托盘{stockInfo.LocationCode}的货位信息");
            // æ£€æŸ¥è´§ä½çŠ¶æ€æ˜¯å¦å…è®¸å‡ºåº“
            if (locationInfo.LocationStatus != (int)LocationStatusEnum.InStock)
                return response.Error($"当前货位{locationInfo.LocationStatus}状态信息错误");
            // éªŒè¯ä»“库ID是否匹配(根据dto的阴阳极参数)
            var expectedWarehouseId = dto.YinYang == 1 ? (int)WarehouseEnum.FJ1 : (int)WarehouseEnum.ZJ1;
            if (stockInfo.WarehouseId != expectedWarehouseId)
                return response.Error($"托盘{dto.TrayNumber}不在预期的仓库中,无法出库");
            task.TaskType = (int)TaskOutboundTypeEnum.Outbound;
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
@@ -454,7 +538,8 @@
            task.TaskStatus = (int)TaskOutStatusEnum.OutFinish;
            _unitOfWorkManage.BeginTran();
            var deleteStockResult = _stockInfoService.DeleteData(stockInfo);
            //var deleteStockResult = _stockInfoService.DeleteData(stockInfo)
            var deleteStockResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            if (!deleteStockResult.Status || !updateLocationResult.Status)
@@ -499,23 +584,23 @@
            if (existingStock != null)
                return response.Error($"托盘{task.PalletCode}的库存信息已存在,请勿重复入库");
            Dt_StockInfo stockInfo = new Dt_StockInfo
            {
                PalletCode = task.PalletCode,
                StockStatus = (int)StockStatusEmun.入库确认,
                LocationCode = locationInfo.LocationCode,
                WarehouseId = task.WarehouseId,
                Creater = "AGV",
                CreateDate = DateTime.Now
            };
            //Dt_StockInfo stockInfo = new Dt_StockInfo
            //{
            //    PalletCode = task.PalletCode,
            //    StockStatus = (int)StockStatusEmun.入库确认,
            //    LocationCode = locationInfo.LocationCode,
            //    WarehouseId = task.WarehouseId,
            //    Creater = "AGV",
            //    CreateDate = DateTime.Now
            //};
            locationInfo.LocationStatus = (int)LocationStatusEnum.FreeLock;
            _unitOfWorkManage.BeginTran();
            var updateTaskResult = BaseDal.UpdateData(task);
            var updateLocationResult = _locationInfoService.UpdateData(locationInfo);
            var addStockResult = _stockInfoService.AddData(stockInfo);
            if (!updateTaskResult || !updateLocationResult.Status || !addStockResult.Status)
            //var addStockResult = _stockInfoService.AddData(stockInfo);
            if (!updateTaskResult || !updateLocationResult.Status /*|| !addStockResult.Status*/)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error("入库完成后,本地任务、库存或货位更新失败");
@@ -526,16 +611,36 @@
        }
        // AGV入库取消
        private AGVResponse CancelAgvInboundTask(Dt_Task task)
        private async Task<AGVResponse> CancelAgvInboundTask(Dt_Task task)
        {
            AGVResponse response = new AGVResponse();
            task.TaskStatus = (int)TaskInStatusEnum.InCancel;
            _unitOfWorkManage.BeginTran();
            try
            {
                var stockInfo = await _stockInfoService.GetStockInfoAsync(task.PalletCode);
                if (stockInfo != null)
                {
                    var deleteResult = await _stockInfoService.DeleteStockWithDetailsAsync(stockInfo.Id);
                    if (!deleteResult.Status)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return response.Error($"删除库存失败: {deleteResult.Message}");
                    }
                }
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            _unitOfWorkManage.CommitTran();
            return response.OK();
        }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return response.Error($"取消入库任务时发生异常: {ex.Message}");
            }
        }
        // AGV出库取消
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WIDESEA_Core;
@@ -22,7 +23,7 @@
        /// <summary>
        /// æ€»è§ˆæ•°æ®
        /// </summary>
        [HttpGet("Overview")]
        [HttpGet("Overview"), AllowAnonymous]
        public async Task<WebResponseContent> Overview()
        {
            try
@@ -76,7 +77,7 @@
        /// SqlSugar çš„ GroupBy ä¸æ”¯æŒå¯¹ .Date è¿™æ ·çš„计算列直接生成 SQL GROUP BY,
        /// å› æ­¤é‡‡ç”¨æ­¤æ–¹å¼ä»¥ç¡®ä¿è·¨æ•°æ®åº“兼容性。
        /// </remarks>
        [HttpGet("DailyStats")]
        [HttpGet("DailyStats"), AllowAnonymous]
        public async Task<WebResponseContent> DailyStats([FromQuery] int days = 30)
        {
            try
@@ -117,7 +118,7 @@
        /// æ³¨æ„ï¼šæ•°æ®åœ¨ SQL å±‚过滤后,在应用层按 ISO 8601 å‘¨é”®åˆ†ç»„。
        /// å‘¨é”®ä¸º "YYYY-Www" æ ¼å¼ï¼Œæ— æ³•直接在 SQL å±‚用 GROUP BY å®žçŽ°ã€‚
        /// </remarks>
        [HttpGet("WeeklyStats")]
        [HttpGet("WeeklyStats"), AllowAnonymous]
        public async Task<WebResponseContent> WeeklyStats([FromQuery] int weeks = 12)
        {
            try
@@ -168,7 +169,7 @@
        /// SqlSugar çš„ GroupBy ä¸æ”¯æŒåŒ¿åå¯¹è±¡ (Year, Month) ç›´æŽ¥æ˜ å°„到 SQL GROUP BY,
        /// å› æ­¤é‡‡ç”¨æ­¤æ–¹å¼ä»¥ç¡®ä¿è·¨æ•°æ®åº“兼容性。
        /// </remarks>
        [HttpGet("MonthlyStats")]
        [HttpGet("MonthlyStats"), AllowAnonymous]
        public async Task<WebResponseContent> MonthlyStats([FromQuery] int months = 12)
        {
            try
@@ -205,7 +206,7 @@
        /// <summary>
        /// åº“存库龄分布
        /// </summary>
        [HttpGet("StockAgeDistribution")]
        [HttpGet("StockAgeDistribution"), AllowAnonymous]
        public async Task<WebResponseContent> StockAgeDistribution()
        {
            try
@@ -235,7 +236,7 @@
        /// <remarks>
        /// ä½¿ç”¨ SQL GROUP BY åœ¨æ•°æ®åº“层面聚合,避免加载全部库存记录到内存。
        /// </remarks>
        [HttpGet("StockByWarehouse")]
        [HttpGet("StockByWarehouse"), AllowAnonymous]
        public async Task<WebResponseContent> StockByWarehouse()
        {
            try
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Record/LocationStatusChangeRecordController.cs
@@ -18,6 +18,29 @@
        public LocationStatusChangeRecordController(ILocationStatusChangeRecordService service) : base(service)
        {
        }
        /// <summary>
        /// æ ¹æ®ID获取货位状态变动记录
        /// </summary>
        /// <param name="id">货位状态变动记录ID</param>
        /// <returns>货位状态变动记录信息</returns>
        [HttpPost("GetLocationState"), AllowAnonymous]
        public WebResponseContent GetLocationState(int id)
        {
            try
            {
                if (id <= 0)
                    return WebResponseContent.Instance.Error("ID参数无效");
       
                var records = Service.Repository.QueryData(x => x.LocationId == id);
                if (records == null || records.Count == 0)
                    return WebResponseContent.Instance.Error("未找到对应的货位状态变动记录");
                return WebResponseContent.Instance.OK(null, records);
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"获取货位状态变动记录失败: {ex.Message}");
            }
        }
    }
}
ÏîÄ¿×ÊÁÏ/¼«¾í¿âAGV½Ó¿Ú/~$¼«¾í¿â³öÈë¿â.docx
Binary files differ