fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 4m27s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 4m27s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
This commit is contained in:
@@ -827,6 +827,14 @@ public class BudgetSavingsService(
|
||||
var savingsCategories = await configService.GetConfigByKeyAsync<string>("SavingsCategories") ?? string.Empty;
|
||||
|
||||
var currentActual = 0m;
|
||||
|
||||
// 1. 先累加已归档月份的存款金额
|
||||
if (archiveSavingsItems.Any())
|
||||
{
|
||||
currentActual += archiveSavingsItems.Sum(i => i.current);
|
||||
}
|
||||
|
||||
// 2. 再累加当前月的存款金额
|
||||
if (!string.IsNullOrEmpty(savingsCategories))
|
||||
{
|
||||
var cats = new HashSet<string>(savingsCategories.Split(',', StringSplitOptions.RemoveEmptyEntries));
|
||||
@@ -839,6 +847,7 @@ public class BudgetSavingsService(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var record = new BudgetRecord
|
||||
{
|
||||
Id = -1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
global using Repository;
|
||||
global using Repository;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
global using System.Text.RegularExpressions;
|
||||
@@ -14,5 +14,6 @@ global using System.Text.Json.Nodes;
|
||||
global using Microsoft.Extensions.Configuration;
|
||||
global using Common;
|
||||
global using System.Net;
|
||||
global using System.Net.Http;
|
||||
global using System.Text.Encodings.Web;
|
||||
global using JetBrains.Annotations;
|
||||
130
Service/HolidayService.cs
Normal file
130
Service/HolidayService.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Service;
|
||||
|
||||
/// <summary>
|
||||
/// 节假日服务接口
|
||||
/// </summary>
|
||||
public interface IHolidayService
|
||||
{
|
||||
/// <summary>
|
||||
/// 从API获取并缓存节假日数据
|
||||
/// </summary>
|
||||
Task<bool> FetchAndCacheHolidaysAsync(int year);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定年份的节假日数据
|
||||
/// </summary>
|
||||
Task<List<Holiday>> GetHolidaysByYearAsync(int year);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期范围的节假日数据
|
||||
/// </summary>
|
||||
Task<List<Holiday>> GetHolidaysByDateRangeAsync(string startDate, string endDate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节假日服务实现
|
||||
/// </summary>
|
||||
public class HolidayService(
|
||||
IHolidayRepository holidayRepository,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<HolidayService> logger) : IHolidayService
|
||||
{
|
||||
private const string HolidayApiUrl = "https://publicapi.xiaoai.me/holiday/year";
|
||||
|
||||
public async Task<bool> FetchAndCacheHolidaysAsync(int year)
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("开始获取 {Year} 年节假日数据", year);
|
||||
|
||||
// 调用API获取数据
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
var response = await httpClient.GetStringAsync($"{HolidayApiUrl}?date={year}");
|
||||
|
||||
// 解析JSON
|
||||
var apiResponse = JsonSerializer.Deserialize<HolidayApiResponse>(response);
|
||||
if (apiResponse?.Code != 0 || apiResponse.Data == null)
|
||||
{
|
||||
logger.LogError("获取节假日数据失败: {Message}", apiResponse?.Msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除旧数据
|
||||
await holidayRepository.DeleteByYearAsync(year);
|
||||
|
||||
// 转换并保存新数据
|
||||
var holidays = apiResponse.Data.Select(item => new Holiday
|
||||
{
|
||||
Year = year,
|
||||
DayType = item.DayType,
|
||||
HolidayName = item.Holiday,
|
||||
Rest = item.Rest,
|
||||
Date = item.Date,
|
||||
Week = item.Week,
|
||||
WeekDescCn = item.WeekDescCn
|
||||
}).ToList();
|
||||
|
||||
await holidayRepository.AddRangeAsync(holidays);
|
||||
|
||||
logger.LogInformation("成功缓存 {Count} 条节假日数据", holidays.Count);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 静默失败,仅记录日志
|
||||
logger.LogError(ex, "获取并缓存节假日数据失败");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<Holiday>> GetHolidaysByYearAsync(int year)
|
||||
{
|
||||
return await holidayRepository.GetByYearAsync(year);
|
||||
}
|
||||
|
||||
public async Task<List<Holiday>> GetHolidaysByDateRangeAsync(string startDate, string endDate)
|
||||
{
|
||||
return await holidayRepository.GetByDateRangeAsync(startDate, endDate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节假日API响应模型
|
||||
/// </summary>
|
||||
public class HolidayApiResponse
|
||||
{
|
||||
[JsonPropertyName("code")]
|
||||
public int Code { get; set; }
|
||||
|
||||
[JsonPropertyName("msg")]
|
||||
public string Msg { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public List<HolidayApiData>? Data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节假日API数据模型
|
||||
/// </summary>
|
||||
public class HolidayApiData
|
||||
{
|
||||
[JsonPropertyName("daytype")]
|
||||
public int DayType { get; set; }
|
||||
|
||||
[JsonPropertyName("holiday")]
|
||||
public string Holiday { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("rest")]
|
||||
public int Rest { get; set; }
|
||||
|
||||
[JsonPropertyName("date")]
|
||||
public string Date { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("week")]
|
||||
public int Week { get; set; }
|
||||
|
||||
[JsonPropertyName("week_desc_cn")]
|
||||
public string WeekDescCn { get; set; } = string.Empty;
|
||||
}
|
||||
45
Service/Jobs/HolidaySyncJob.cs
Normal file
45
Service/Jobs/HolidaySyncJob.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Quartz;
|
||||
|
||||
namespace Service.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 节假日同步定时任务 - 每10天执行一次
|
||||
/// </summary>
|
||||
[DisallowConcurrentExecution] // 防止并发执行
|
||||
public class HolidaySyncJob(
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<HolidaySyncJob> logger) : IJob
|
||||
{
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("开始执行节假日同步任务");
|
||||
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
var holidayService = scope.ServiceProvider.GetRequiredService<IHolidayService>();
|
||||
|
||||
// 获取当前年份和下一年份
|
||||
var currentYear = DateTime.Now.Year;
|
||||
var nextYear = currentYear + 1;
|
||||
|
||||
// 同步当前年和下一年的数据
|
||||
var currentYearResult = await holidayService.FetchAndCacheHolidaysAsync(currentYear);
|
||||
var nextYearResult = await holidayService.FetchAndCacheHolidaysAsync(nextYear);
|
||||
|
||||
if (currentYearResult && nextYearResult)
|
||||
{
|
||||
logger.LogInformation("节假日同步任务执行完成,成功同步 {CurrentYear} 和 {NextYear} 年数据", currentYear, nextYear);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogWarning("节假日同步任务部分失败,当前年: {CurrentResult}, 下一年: {NextResult}", currentYearResult, nextYearResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "节假日同步任务执行出错");
|
||||
throw; // 让 Quartz 知道任务失败
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Repository\Repository.csproj" />
|
||||
@@ -12,6 +12,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||
<PackageReference Include="Serilog" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
|
||||
Reference in New Issue
Block a user