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