chore: migrate remaining ECharts components to Chart.js

- Migrated 4 components from ECharts to Chart.js:
  * MonthlyExpenseCard.vue (折线图)
  * DailyTrendChart.vue (双系列折线图)
  * ExpenseCategoryCard.vue (环形图)
  * BudgetChartAnalysis.vue (仪表盘 + 多种图表)

- Removed all ECharts imports and environment variable switches
- Unified all charts to use BaseChart.vue component
- Build verified: pnpm build success ✓
- No echarts imports remaining ✓

Refs: openspec/changes/migrate-remaining-echarts-to-chartjs
This commit is contained in:
SunCheng
2026-02-16 21:55:38 +08:00
parent a88556c784
commit 9921cd5fdf
77 changed files with 6964 additions and 1632 deletions

View File

@@ -0,0 +1,96 @@
using Service.IconSearch;
namespace WebApi.Test.Service.IconSearch;
/// <summary>
/// Iconify API 集成测试(需要网络连接)
/// 用于验证完整的图标搜索流程
/// </summary>
public class IconifyApiIntegrationTest : BaseTest
{
private readonly IconifyApiService _service;
private readonly ILogger<IconifyApiService> _logger;
public IconifyApiIntegrationTest()
{
_logger = Substitute.For<ILogger<IconifyApiService>>();
var settings = Options.Create(new IconifySettings
{
ApiUrl = "https://api.iconify.design/search",
DefaultLimit = 20,
MaxRetryCount = 3,
RetryDelayMs = 1000
});
_service = new IconifyApiService(settings, _logger);
}
[Fact]
public async Task _搜索玩具图标()
{
// Arrange
var keywords = new List<string> { "toy", "play" };
// Act
var icons = await _service.SearchIconsAsync(keywords, 10);
// Assert
icons.Should().NotBeNull();
icons.Should().NotBeEmpty("应该返回玩具相关的图标");
// 验证图标格式
icons.All(i => !string.IsNullOrEmpty(i.CollectionName)).Should().BeTrue("所有图标应该有 CollectionName");
icons.All(i => !string.IsNullOrEmpty(i.IconName)).Should().BeTrue("所有图标应该有 IconName");
icons.All(i => i.IconIdentifier.Contains(":")).Should().BeTrue("所有图标的 IconIdentifier 应该包含 ':'");
// 打印前5个图标用于验证
_logger.LogInformation("搜索到 {Count} 个图标", icons.Count);
foreach (var icon in icons.Take(5))
{
_logger.LogInformation(" - {Identifier} (Collection: {Collection}, Name: {Name})",
icon.IconIdentifier, icon.CollectionName, icon.IconName);
}
}
[Fact]
public async Task _搜索食物图标()
{
// Arrange
var keywords = new List<string> { "food", "meal", "restaurant" };
// Act
var icons = await _service.SearchIconsAsync(keywords, 15);
// Assert
icons.Should().NotBeNull();
icons.Should().NotBeEmpty("应该返回食物相关的图标");
icons.Count.Should().BeGreaterThan(0);
// 验证至少有一些常见的图标集
var collections = icons.Select(i => i.CollectionName).Distinct().ToList();
collections.Should().Contain(c => c == "mdi" || c == "material-symbols" || c == "tabler",
"应该包含常见的图标集");
}
[Fact]
public async Task ()
{
// Arrange
var keywords = new List<string> { "home" };
// Act
var icons = await _service.SearchIconsAsync(keywords, 5);
// Assert
icons.Should().NotBeNull();
icons.Should().NotBeEmpty();
foreach (var icon in icons)
{
// 验证标识符格式: "collection:iconName"
var parts = icon.IconIdentifier.Split(':');
parts.Should().HaveCount(2, $"图标标识符 '{icon.IconIdentifier}' 应该是 'collection:name' 格式");
parts[0].Should().Be(icon.CollectionName);
parts[1].Should().Be(icon.IconName);
}
}
}