wanshenmean
2026-03-30 0a94fa4b54ace3d217a7f981fb81af12ee6a20ee
feat(Dashboard): 添加仪表盘控制器,包含6个统计接口

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
已添加1个文件
212 ■■■■■ 文件已修改
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,212 @@
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WIDESEA_Core;
using WIDESEA_Model.Models;
namespace WIDESEA_WMSServer.Controllers.Dashboard
{
    /// <summary>
    /// ä»ªè¡¨ç›˜
    /// </summary>
    [Route("api/Dashboard")]
    [ApiController]
    public class DashboardController : ControllerBase
    {
        private readonly ISqlSugarClient _db;
        public DashboardController(ISqlSugarClient db)
        {
            _db = db;
        }
        /// <summary>
        /// æ€»è§ˆæ•°æ®
        /// </summary>
        [HttpGet("Overview")]
        public async Task<WebResponseContent> Overview()
        {
            var today = DateTime.Today;
            var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
            // ä»Šæ—¥å…¥åº“æ•°
            var todayInbound = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= today && t.TaskType >= 500 && t.TaskType < 600)
                .CountAsync();
            // ä»Šæ—¥å‡ºåº“æ•°
            var todayOutbound = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= today && t.TaskType >= 100 && t.TaskType < 200)
                .CountAsync();
            // æœ¬æœˆå…¥åº“æ•°
            var monthInbound = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= firstDayOfMonth && t.TaskType >= 500 && t.TaskType < 600)
                .CountAsync();
            // æœ¬æœˆå‡ºåº“æ•°
            var monthOutbound = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= firstDayOfMonth && t.TaskType >= 100 && t.TaskType < 200)
                .CountAsync();
            // å½“前总库存
            var totalStock = await _db.Queryable<Dt_StockInfo>().CountAsync();
            return WebResponseContent.Instance.OK(null, new
            {
                TodayInbound = todayInbound,
                TodayOutbound = todayOutbound,
                MonthInbound = monthInbound,
                MonthOutbound = monthOutbound,
                TotalStock = totalStock
            });
        }
        /// <summary>
        /// æ¯æ—¥ç»Ÿè®¡
        /// </summary>
        [HttpGet("DailyStats")]
        public async Task<WebResponseContent> DailyStats([FromQuery] int days = 30)
        {
            if (days <= 0) days = 30;
            if (days > 365) days = 365;
            var startDate = DateTime.Today.AddDays(-days + 1);
            var query = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= startDate)
                .Select(t => new { t.InsertTime, t.TaskType })
                .ToListAsync();
            var result = query
                .GroupBy(t => t.InsertTime.Date)
                .Select(g => new
                {
                    Date = g.Key.ToString("yyyy-MM-dd"),
                    Inbound = g.Count(t => t.TaskType >= 500 && t.TaskType < 600),
                    Outbound = g.Count(t => t.TaskType >= 100 && t.TaskType < 200)
                })
                .OrderBy(x => x.Date)
                .ToList();
            return WebResponseContent.Instance.OK(null, result);
        }
        /// <summary>
        /// æ¯å‘¨ç»Ÿè®¡
        /// </summary>
        [HttpGet("WeeklyStats")]
        public async Task<WebResponseContent> WeeklyStats([FromQuery] int weeks = 12)
        {
            if (weeks <= 0) weeks = 12;
            var startDate = DateTime.Today.AddDays(-weeks * 7);
            var query = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= startDate)
                .Select(t => new { t.InsertTime, t.TaskType })
                .ToListAsync();
            var result = query
                .GroupBy(t => GetWeekKey(t.InsertTime))
                .Select(g => new
                {
                    Week = g.Key,
                    Inbound = g.Count(t => t.TaskType >= 500 && t.TaskType < 600),
                    Outbound = g.Count(t => t.TaskType >= 100 && t.TaskType < 200)
                })
                .OrderBy(x => x.Week)
                .ToList();
            return WebResponseContent.Instance.OK(null, result);
        }
        private string GetWeekKey(DateTime date)
        {
            // èŽ·å–å‘¨ä¸€å¼€å§‹çš„å‘¨ (ISO 8601)
            var diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7;
            var monday = date.AddDays(-diff);
            var weekNum = System.Globalization.CultureInfo.InvariantCulture
                .Calendar.GetWeekOfYear(monday, System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
            return $"{monday.Year}-W{weekNum:D2}";
        }
        /// <summary>
        /// æ¯æœˆç»Ÿè®¡
        /// </summary>
        [HttpGet("MonthlyStats")]
        public async Task<WebResponseContent> MonthlyStats([FromQuery] int months = 12)
        {
            if (months <= 0) months = 12;
            var startDate = DateTime.Today.AddMonths(-months + 1);
            startDate = new DateTime(startDate.Year, startDate.Month, 1);
            var query = await _db.Queryable<Dt_Task_Hty>()
                .Where(t => t.InsertTime >= startDate)
                .Select(t => new { t.InsertTime, t.TaskType })
                .ToListAsync();
            var result = query
                .GroupBy(t => new { t.InsertTime.Year, t.InsertTime.Month })
                .Select(g => new
                {
                    Month = $"{g.Key.Year}-{g.Key.Month:D2}",
                    Inbound = g.Count(t => t.TaskType >= 500 && t.TaskType < 600),
                    Outbound = g.Count(t => t.TaskType >= 100 && t.TaskType < 200)
                })
                .OrderBy(x => x.Month)
                .ToList();
            return WebResponseContent.Instance.OK(null, result);
        }
        /// <summary>
        /// åº“存库龄分布
        /// </summary>
        [HttpGet("StockAgeDistribution")]
        public async Task<WebResponseContent> StockAgeDistribution()
        {
            var now = DateTime.Now;
            // ä½¿ç”¨ SQL ç›´æŽ¥åˆ†ç»„统计,避免加载所有数据到内存
            var result = new[]
            {
                new { Range = "7天内", Count = await _db.Queryable<Dt_StockInfo>().Where(s => SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) <= 7).CountAsync() },
                new { Range = "7-30天", Count = await _db.Queryable<Dt_StockInfo>().Where(s => SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) > 7 && SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) <= 30).CountAsync() },
                new { Range = "30-90天", Count = await _db.Queryable<Dt_StockInfo>().Where(s => SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) > 30 && SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) <= 90).CountAsync() },
                new { Range = "90天以上", Count = await _db.Queryable<Dt_StockInfo>().Where(s => SqlFunc.DateDiff(DateType.Day, s.CreateDate, now) > 90).CountAsync() }
            };
            return WebResponseContent.Instance.OK(null, result);
        }
        /// <summary>
        /// å„仓库库存分布
        /// </summary>
        [HttpGet("StockByWarehouse")]
        public async Task<WebResponseContent> StockByWarehouse()
        {
            // å…ˆæŸ¥è¯¢ä»“库名称
            var warehouses = await _db.Queryable<Dt_Warehouse>()
                .Select(w => new { w.WarehouseId, w.WarehouseName })
                .ToListAsync();
            var warehouseDict = warehouses.ToDictionary(w => w.WarehouseId, w => w.WarehouseName);
            // æŸ¥è¯¢åº“存数据并在内存中分组
            var stocks = await _db.Queryable<Dt_StockInfo>()
                .Select(s => new { s.WarehouseId })
                .ToListAsync();
            var result = stocks
                .GroupBy(s => s.WarehouseId)
                .Select(g => new
                {
                    Warehouse = warehouseDict.TryGetValue(g.Key, out var name) ? name : $"仓库{g.Key}",
                    Count = g.Count()
                })
                .ToList();
            return WebResponseContent.Instance.OK(null, result);
        }
    }
}