diff --git a/src/MilitaryTrainingManagement/Controllers/StatsController.cs b/src/MilitaryTrainingManagement/Controllers/StatsController.cs new file mode 100644 index 0000000..c4f2ea8 --- /dev/null +++ b/src/MilitaryTrainingManagement/Controllers/StatsController.cs @@ -0,0 +1,102 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using MilitaryTrainingManagement.Data; +using MilitaryTrainingManagement.Models.Enums; + +namespace MilitaryTrainingManagement.Controllers; + +/// +/// 统计数据控制器 +/// +[Authorize] +public class StatsController : BaseApiController +{ + private readonly ApplicationDbContext _context; + + public StatsController(ApplicationDbContext context) + { + _context = context; + } + + /// + /// 获取首页统计数据 + /// + [HttpGet("dashboard")] + public async Task GetDashboardStats() + { + var unitId = GetCurrentUnitId(); + var unitLevel = GetCurrentUnitLevel(); + + if (unitId == null || unitLevel == null) + return Unauthorized(new { message = "无法获取用户组织信息" }); + + // 获取当前单位及下级单位ID列表 + var unitIds = await GetUnitAndSubordinateIds(unitId.Value); + + // 统计配额数 + var allocationsCount = await _context.MaterialAllocations + .Where(a => a.CreatedByUnitId == unitId.Value || unitIds.Contains(a.CreatedByUnitId)) + .CountAsync(); + + // 统计完成率 + var distributions = await _context.AllocationDistributions + .Where(d => unitIds.Contains(d.TargetUnitId)) + .ToListAsync(); + + decimal completionRate = 0; + if (distributions.Any()) + { + var totalQuota = distributions.Sum(d => d.UnitQuota); + var totalCompletion = distributions.Sum(d => d.ActualCompletion ?? 0); + if (totalQuota > 0) + { + completionRate = Math.Round((totalCompletion / totalQuota) * 100, 1); + } + } + + // 统计人员数 + var personnelCount = await _context.Personnel + .Where(p => unitIds.Contains(p.SubmittedByUnitId) && p.Status == PersonnelStatus.Approved) + .CountAsync(); + + // 统计待审批数(仅师团级别显示) + var pendingApprovals = 0; + if (unitLevel == OrganizationalLevel.Division) + { + pendingApprovals = await _context.ApprovalRequests + .Where(r => r.Status == ApprovalStatus.Pending) + .CountAsync(); + + // 加上待审批的人员 + pendingApprovals += await _context.Personnel + .Where(p => p.Status == PersonnelStatus.Pending) + .CountAsync(); + } + + return Ok(new + { + allocations = allocationsCount, + completionRate = completionRate, + personnel = personnelCount, + pendingApprovals = pendingApprovals + }); + } + + private async Task> GetUnitAndSubordinateIds(int unitId) + { + var result = new List { unitId }; + var children = await _context.OrganizationalUnits + .Where(u => u.ParentId == unitId) + .Select(u => u.Id) + .ToListAsync(); + + foreach (var childId in children) + { + var subIds = await GetUnitAndSubordinateIds(childId); + result.AddRange(subIds); + } + + return result; + } +} diff --git a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.dll b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.dll index 6065104..8658df2 100644 Binary files a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.dll and b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.dll differ diff --git a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.exe b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.exe index 3f4f0ed..19b37b9 100644 Binary files a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.exe and b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.exe differ diff --git a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.pdb b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.pdb index 787c806..3c83b97 100644 Binary files a/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.pdb and b/src/MilitaryTrainingManagement/bin/Debug/net8.0/MilitaryTrainingManagement.pdb differ diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfo.cs b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfo.cs index a870dce..42b0d69 100644 --- a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfo.cs +++ b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("MilitaryTrainingManagement")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+dea416c1206a35a2f77e33f37406891d5377f1a6")] [assembly: System.Reflection.AssemblyProductAttribute("MilitaryTrainingManagement")] [assembly: System.Reflection.AssemblyTitleAttribute("MilitaryTrainingManagement")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfoInputs.cache b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfoInputs.cache index f59bf64..af04cf4 100644 --- a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfoInputs.cache +++ b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.AssemblyInfoInputs.cache @@ -1 +1 @@ -407f322c0b72f117c925ae6a80f31111d05088df1322e7b528cdc9a219109c9a +71761eb666e1de962287ab2d3efffb4d59f9a1ceb181540c49222eadb77fb760 diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.csproj.CoreCompileInputs.cache b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.csproj.CoreCompileInputs.cache index 3c21725..a074306 100644 --- a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.csproj.CoreCompileInputs.cache +++ b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -c42f36142723a436c8872fc0ee41f859ea9256e151b6b81825ce7ce0070f694e +9aa7a804a7b716c6d51cb391fd2292638fb67f08685ae7d440982f042b40fd5e diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.dll b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.dll index 6065104..8658df2 100644 Binary files a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.dll and b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.dll differ diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.pdb b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.pdb index 787c806..3c83b97 100644 Binary files a/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.pdb and b/src/MilitaryTrainingManagement/obj/Debug/net8.0/MilitaryTrainingManagement.pdb differ diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/apphost.exe b/src/MilitaryTrainingManagement/obj/Debug/net8.0/apphost.exe index 3f4f0ed..19b37b9 100644 Binary files a/src/MilitaryTrainingManagement/obj/Debug/net8.0/apphost.exe and b/src/MilitaryTrainingManagement/obj/Debug/net8.0/apphost.exe differ diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/ref/MilitaryTrainingManagement.dll b/src/MilitaryTrainingManagement/obj/Debug/net8.0/ref/MilitaryTrainingManagement.dll index 90e2928..e16aafd 100644 Binary files a/src/MilitaryTrainingManagement/obj/Debug/net8.0/ref/MilitaryTrainingManagement.dll and b/src/MilitaryTrainingManagement/obj/Debug/net8.0/ref/MilitaryTrainingManagement.dll differ diff --git a/src/MilitaryTrainingManagement/obj/Debug/net8.0/refint/MilitaryTrainingManagement.dll b/src/MilitaryTrainingManagement/obj/Debug/net8.0/refint/MilitaryTrainingManagement.dll index 90e2928..e16aafd 100644 Binary files a/src/MilitaryTrainingManagement/obj/Debug/net8.0/refint/MilitaryTrainingManagement.dll and b/src/MilitaryTrainingManagement/obj/Debug/net8.0/refint/MilitaryTrainingManagement.dll differ diff --git a/src/frontend/src/api/index.ts b/src/frontend/src/api/index.ts index e88dd6e..df6cc75 100644 --- a/src/frontend/src/api/index.ts +++ b/src/frontend/src/api/index.ts @@ -4,4 +4,5 @@ export { allocationsApi } from './allocations' export { reportsApi } from './reports' export { personnelApi } from './personnel' export { approvalsApi } from './approvals' +export { statsApi } from './stats' export { default as apiClient } from './client' diff --git a/src/frontend/src/api/stats.ts b/src/frontend/src/api/stats.ts new file mode 100644 index 0000000..ad2c7b1 --- /dev/null +++ b/src/frontend/src/api/stats.ts @@ -0,0 +1,15 @@ +import apiClient from './client' + +export interface DashboardStats { + allocations: number + completionRate: number + personnel: number + pendingApprovals: number +} + +export const statsApi = { + async getDashboardStats(): Promise { + const response = await apiClient.get('/stats/dashboard') + return response.data + } +} diff --git a/src/frontend/src/views/Dashboard.vue b/src/frontend/src/views/Dashboard.vue index 94f4731..22cab8e 100644 --- a/src/frontend/src/views/Dashboard.vue +++ b/src/frontend/src/views/Dashboard.vue @@ -97,8 +97,10 @@ diff --git a/src/frontend/src/views/allocations/AllocationForm.vue b/src/frontend/src/views/allocations/AllocationForm.vue index 8c82e7b..6571976 100644 --- a/src/frontend/src/views/allocations/AllocationForm.vue +++ b/src/frontend/src/views/allocations/AllocationForm.vue @@ -22,29 +22,31 @@ 配额分配 -
-
- - - - - +
+
+
+ + + + + +
+
+
+ + + 添加分配 + + 已分配: {{ distributedTotal }} + + 剩余: {{ (form.totalQuota - distributedTotal).toFixed(2) }} +
- - - 添加分配 - -
-
- 已分配: {{ distributedTotal }} - - 剩余: {{ (form.totalQuota - distributedTotal).toFixed(2) }} -
@@ -181,10 +183,15 @@ onMounted(() => {