From 0a94fa4b54ace3d217a7f981fb81af12ee6a20ee Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期一, 30 三月 2026 11:47:56 +0800
Subject: [PATCH] feat(Dashboard): 添加仪表盘控制器,包含6个统计接口

---
 Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs |  212 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Dashboard/DashboardController.cs
new file mode 100644
index 0000000..78a21e9
--- /dev/null
+++ b/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);
+        }
+    }
+}

--
Gitblit v1.9.3