From 76fd0d23dc8b7b5af849a7ead2e376122dec510d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E8=AF=9A?= Date: Fri, 9 Jan 2026 16:59:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E9=A2=84=E7=AE=97?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=92=8C=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=9F=E8=AE=A1=E4=BF=A1=E6=81=AF=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=BC=BA=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Service/BudgetService.cs | 104 +++++++++++++++++++---- Web/src/components/Budget/BudgetCard.vue | 1 - WebApi/Controllers/BudgetController.cs | 12 ++- 3 files changed, 97 insertions(+), 20 deletions(-) diff --git a/Service/BudgetService.cs b/Service/BudgetService.cs index ad7ea9d..879f77b 100644 --- a/Service/BudgetService.cs +++ b/Service/BudgetService.cs @@ -4,7 +4,7 @@ public interface IBudgetService { Task> GetListAsync(DateTime? referenceDate = null); - Task GetStatisticsAsync(long id, DateTime? referenceDate = null); + Task GetStatisticsAsync(long id, DateTime referenceDate); Task ArchiveBudgetsAsync(int year, int month); @@ -48,8 +48,54 @@ public class BudgetService( return dtos.Where(dto => dto != null).Cast().ToList(); } - public async Task GetStatisticsAsync(long id, DateTime? referenceDate = null) + public async Task GetStatisticsAsync(long id, DateTime referenceDate) { + bool isArchive = false; + BudgetRecord? budget = null; + if (id == -1) + { + if (isAcrhiveFunc(BudgetPeriodType.Year)) + { + isArchive = true; + budget = await BuildVirtualSavingsBudgetRecordAsync(-1, referenceDate, 0); + } + + } + else if (id == -2) + { + if (isAcrhiveFunc(BudgetPeriodType.Month)) + { + isArchive = true; + budget = await BuildVirtualSavingsBudgetRecordAsync(-2, referenceDate, 0); + } + } + else + { + budget = await budgetRepository.GetByIdAsync(id); + + if (budget == null) + { + return null; + } + + isArchive = isAcrhiveFunc(budget.Type); + } + + if (isArchive && budget != null) + { + var archive = await budgetArchiveRepository.GetArchiveAsync( + id, + referenceDate.Year, + referenceDate.Month); + + if (archive != null) // 存在归档 直接读取归档数据 + { + budget.Limit = archive.BudgetedAmount; + return BudgetResult.FromEntity(budget, archive.RealizedAmount, referenceDate); + } + } + + if (id == -1) { return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Year, referenceDate); @@ -59,7 +105,7 @@ public class BudgetService( return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Month, referenceDate); } - var budget = await budgetRepository.GetByIdAsync(id); + budget = await budgetRepository.GetByIdAsync(id); if (budget == null) { return null; @@ -67,6 +113,21 @@ public class BudgetService( var currentAmount = await CalculateCurrentAmountAsync(budget, referenceDate); return BudgetResult.FromEntity(budget, currentAmount, referenceDate); + + bool isAcrhiveFunc(BudgetPeriodType periodType) + { + if (periodType == BudgetPeriodType.Year) + { + return DateTime.Now.Year > referenceDate.Year; + } + else if (periodType == BudgetPeriodType.Month) + { + return DateTime.Now.Year > referenceDate.Year + || (DateTime.Now.Year == referenceDate.Year + && DateTime.Now.Month > referenceDate.Month); + } + return false; + } } public async Task GetCategoryStatsAsync(BudgetCategory category, DateTime? referenceDate = null) @@ -481,19 +542,10 @@ public class BudgetService( description.Append($"

计划存款 = 收入 {incomeLimitAtPeriod:N0} - 支出 {expenseLimitAtPeriod:N0}

"); description.Append($"

最终目标:{incomeLimitAtPeriod - expenseLimitAtPeriod:N0}

"); - var savingsCategories = await configService.GetConfigByKeyAsync("SavingsCategories") ?? string.Empty; - var virtualBudget = new BudgetRecord - { - Id = periodType == BudgetPeriodType.Year ? -1 : -2, - Name = periodType == BudgetPeriodType.Year ? "年度存款" : "月度存款", - Category = BudgetCategory.Savings, - Type = periodType, - Limit = incomeLimitAtPeriod - expenseLimitAtPeriod, - StartDate = periodType == BudgetPeriodType.Year - ? new DateTime(date.Year, 1, 1) - : new DateTime(date.Year, date.Month, 1), - SelectedCategories = savingsCategories - }; + var virtualBudget = await BuildVirtualSavingsBudgetRecordAsync( + periodType == BudgetPeriodType.Year ? -1 : -2, + date, + incomeLimitAtPeriod - expenseLimitAtPeriod); // 计算实际发生的 收入 - 支出 var current = await CalculateCurrentAmountAsync(new BudgetRecord @@ -506,6 +558,26 @@ public class BudgetService( return BudgetResult.FromEntity(virtualBudget, current, date, description.ToString()); } + + private async Task BuildVirtualSavingsBudgetRecordAsync( + long id, + DateTime date, + decimal limit) + { + var savingsCategories = await configService.GetConfigByKeyAsync("SavingsCategories") ?? string.Empty; + return new BudgetRecord + { + Id = id, + Name = id == -1 ? "年度存款" : "月度存款", + Category = BudgetCategory.Savings, + Type = id == -1 ? BudgetPeriodType.Year : BudgetPeriodType.Month, + Limit = limit, + StartDate = id == -1 + ? new DateTime(date.Year, 1, 1) + : new DateTime(date.Year, date.Month, 1), + SelectedCategories = savingsCategories + }; + } } public record BudgetResult diff --git a/Web/src/components/Budget/BudgetCard.vue b/Web/src/components/Budget/BudgetCard.vue index 0ff5634..759f327 100644 --- a/Web/src/components/Budget/BudgetCard.vue +++ b/Web/src/components/Budget/BudgetCard.vue @@ -225,7 +225,6 @@ const handleQueryBills = async () => { billLoading.value = true try { - debugger const classify = props.budget.selectedCategories ? props.budget.selectedCategories.join(',') : '' diff --git a/WebApi/Controllers/BudgetController.cs b/WebApi/Controllers/BudgetController.cs index 82692c3..80ee5d4 100644 --- a/WebApi/Controllers/BudgetController.cs +++ b/WebApi/Controllers/BudgetController.cs @@ -35,10 +35,16 @@ public class BudgetController( /// 获取单个预算统计信息 /// [HttpGet] - public async Task> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime? referenceDate = null) + public async Task> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime referenceDate) { try { + // 参数验证 + if (id == 0) + { + return "预算 Id 无效".Fail(); + } + var result = await budgetService.GetStatisticsAsync(id, referenceDate); if (result == null) @@ -204,11 +210,11 @@ public class BudgetController( { var msg = await budgetService.ArchiveBudgetsAsync(year, month); - if(!string.IsNullOrEmpty(msg)) + if (!string.IsNullOrEmpty(msg)) { return msg.Fail(); } - + return BaseResponse.Done(); } catch (Exception ex)