Files
EmailBill/Service/Jobs/CategoryIconGenerationJob.cs
SunCheng d052ae5197 fix
2026-02-10 17:49:19 +08:00

98 lines
3.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Quartz;
using Service.AI;
namespace Service.Jobs;
/// <summary>
/// 分类图标生成定时任务
/// 每10分钟扫描一次为没有图标的分类生成 5 个 SVG 图标
/// </summary>
public class CategoryIconGenerationJob(
ITransactionCategoryRepository categoryRepository,
ISmartHandleService smartHandleService,
ILogger<CategoryIconGenerationJob> logger) : IJob
{
private static readonly SemaphoreSlim _semaphore = new(1, 1);
public async Task Execute(IJobExecutionContext context)
{
// 尝试获取锁,如果失败则跳过本次执行
if (!await _semaphore.WaitAsync(0))
{
logger.LogInformation("上一个分类图标生成任务尚未完成,跳过本次执行");
return;
}
try
{
logger.LogInformation("开始执行分类图标生成任务");
// 查询所有分类,然后过滤出没有图标的
var allCategories = await categoryRepository.GetAllAsync();
var categoriesWithoutIcon = allCategories
.Where(c => string.IsNullOrEmpty(c.Icon))
.ToList();
if (categoriesWithoutIcon.Count == 0)
{
logger.LogInformation("所有分类都已有图标,跳过本次任务");
return;
}
logger.LogInformation("发现 {Count} 个分类没有图标,开始生成", categoriesWithoutIcon.Count);
// 为每个分类生成图标
foreach (var category in categoriesWithoutIcon)
{
try
{
await GenerateIconsForCategoryAsync(category);
}
catch (Exception ex)
{
logger.LogError(ex, "为分类 {CategoryName}(ID:{CategoryId}) 生成图标失败",
category.Name, category.Id);
}
}
logger.LogInformation("分类图标生成任务执行完成");
}
catch (Exception ex)
{
logger.LogError(ex, "分类图标生成任务执行出错");
throw;
}
finally
{
_semaphore.Release();
}
}
/// <summary>
/// 为单个分类生成 5 个 SVG 图标
/// </summary>
private async Task GenerateIconsForCategoryAsync(TransactionCategory category)
{
logger.LogInformation("正在为分类 {CategoryName}(ID:{CategoryId}) 生成图标",
category.Name, category.Id);
// 使用 SmartHandleService 统一封装的图标生成方法
var icons = await smartHandleService.GenerateCategoryIconsAsync(category.Name, category.Type, iconCount: 5);
if (icons == null || icons.Count == 0)
{
logger.LogWarning("为分类 {CategoryName}(ID:{CategoryId}) 生成图标失败",
category.Name, category.Id);
return;
}
// 保存图标到数据库
category.Icon = JsonSerializer.Serialize(icons);
await categoryRepository.UpdateAsync(category);
logger.LogInformation("成功为分类 {CategoryName}(ID:{CategoryId}) 生成并保存了 {IconCount} 个图标",
category.Name, category.Id, icons.Count);
}
}