Files
EmailBill/openspec/changes/icon-search-integration/design.md
SunCheng 9921cd5fdf 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
2026-02-16 21:55:38 +08:00

8.4 KiB
Raw Blame History

Context

当前系统使用AI生成SVG图标来表示分类但生成的图标不够直观与分类名称匹配度低用户体验不佳。Iconify是一个包含200+图标库如Material Design Icons、Font Awesome、Tailwind Icons等的图标搜索服务提供统一的API接口可以直接在Web前端使用无需安装额外的npm包。

Goals / Non-Goals

Goals:

  • 集成Iconify API实现图标搜索和检索功能
  • 使用AI生成英文搜索关键字提高搜索相关性
  • 将检索到的图标持久化到数据库,避免重复搜索
  • 提供RESTful API接口支持图标管理操作
  • 替换现有的AI生成SVG图标逻辑提升图标可视化质量

Non-Goals:

  • 不实现图标上传功能仅使用Iconify API检索
  • 不实现图标的在线编辑功能
  • 不支持自定义图标仅使用Iconify现有图标库
  • 不实现图标的热门推荐或相似图标推荐功能

Decisions

1. 使用Iconify API而非其他图标库

决策: 选择Iconify API作为图标检索服务

理由:

  • Iconify集成了200+图标库覆盖范围广包括Material Design Icons、Font Awesome、Bootstrap Icons等主流库
  • 提供统一的搜索API无需逐个调用不同图标库
  • 前端可以直接使用Iconify CDN无需安装npm包
  • 搜索API响应快返回数据结构清晰

替代方案考虑:

  • 方案A使用单个图标库如Material Design Icons→ 覆盖范围有限,图标数量不足
  • 方案B自建图标数据库 → 维护成本高,图标更新不及时
  • 方案C使用多个图标库API → 需要分别集成不同API开发复杂度高

2. AI生成搜索关键字而非直接使用分类名称翻译

决策: 使用AI生成多个英文搜索关键字而非直接翻译分类名称

理由:

  • 直接翻译可能不准确(如"餐饮"翻译为"catering",但更常用"food"或"restaurant"
  • 一个分类可能有多个相关的图标概念(如"交通"可以是"car"、"bus"、"transport"
  • AI能够理解语义生成更准确的英文搜索词

替代方案考虑:

  • 方案A直接翻译分类名称 → 关键字可能不准确,搜索结果相关性低
  • 方案B硬编码关键字映射表 → 维护成本高,不灵活
  • 方案C用户手动输入关键字 → 增加用户操作负担

3. 图标持久化到数据库而非实时搜索

决策: 将检索到的图标保存到数据库,避免重复搜索

理由:

  • 减少对Iconify API的调用次数降低依赖风险
  • 提高图标获取速度从数据库读取比API调用快
  • 可以记录每个图标使用的搜索关键字,便于后续分析和优化
  • 避免重复存储相同图标,节省存储空间

替代方案考虑:

  • 方案A每次都实时调用Iconify API → 依赖性强API可能限流或中断
  • 方案B使用缓存如Redis → 缓存可能过期,需要处理缓存失效逻辑
  • 方案C前端缓存图标 → 无法跨设备同步,数据不一致

4. 修改TransactionCategory实体

决策: 修改TransactionCategory.Icon字段从存储SVG格式改为存储Iconify图标标识符新增IconKeywords字段

理由:

  • 现有的TransactionCategory表已有Icon字段无需创建新表
  • 存储Iconify标识符如"mdi:home"比存储SVG字符串更简洁
  • 新增IconKeywords字段记录AI生成的搜索关键字便于后续分析和重新搜索

字段修改:

public class TransactionCategory : BaseEntity
{
    /// <summary>
    /// 图标Iconify标识符格式{collection}:{name},如"mdi:home"
    /// </summary>
    [Column(StringLength = 50)]
    public string? Icon { get; set; }
    
    /// <summary>
    /// 搜索关键字JSON数组如["food", "restaurant", "dining"]
    /// </summary>
    [Column(StringLength = 200)]
    public string? IconKeywords { get; set; }
}

数据库迁移:

  • 添加IconKeywords字段可选如果不需要记录关键字则跳过
  • 修改Icon字段长度限制从-1改为50

5. AI搜索关键字生成服务

决策: 使用Semantic Kernel或OpenAI API生成搜索关键字

理由:

  • 项目已集成Semantic Kernel复用现有基础设施
  • AI能够理解中文分类名称的语义生成准确的英文关键字
  • 可以配置生成的关键字数量如3-5个

实现方案:

  • 使用Semantic Kernel的Text Generation功能
  • Prompt模板为以下中文分类名称生成3-5个相关的英文搜索关键字用于搜索图标{categoryName}。输出格式为JSON数组。

6. Iconify API调用格式

决策: 使用Iconify搜索API https://api.iconify.design/search?query=<keyword>&limit=<limit>

理由:

  • Iconify官方API稳定可靠
  • 响应速度快,支持批量查询
  • 返回数据结构清晰,包含图标集名称和图标名称

响应数据格式:

{
  "icons": [
    {
      "name": "home",
      "collection": {
        "name": "mdi"
      }
    }
  ]
}

图标渲染标识符: mdi:home(图标集名称:图标名称)

Risks / Trade-offs

风险1Iconify API限流或中断

风险: Iconify API可能限流或服务中断导致无法检索图标 缓解措施:

  • 实现API调用重试机制指数退避
  • 记录API调用失败日志监控API可用性
  • 如果API长时间不可用提供备选方案如使用已缓存的图标

风险2AI生成搜索关键字不准确

风险: AI生成的搜索关键字可能不准确导致检索到的图标与分类不相关 缓解措施:

  • 优化AI Prompt提供更多上下文信息
  • 提供人工审核接口,允许用户修改或补充搜索关键字
  • 基于用户反馈不断优化AI Prompt

风险3图标数量过多导致前端性能问题

风险: 某个分类可能关联大量图标,导致前端渲染性能下降 缓解措施:

  • 前端分页加载图标如每页显示10-20个
  • 提供图标搜索功能,允许用户过滤图标
  • 图标懒加载,仅在可见区域渲染图标

风险4Iconify API返回的图标不匹配分类

风险: AI生成的搜索关键字可能不准确导致Iconify API返回的图标与分类不相关 缓解措施:

  • 优化AI Prompt提供更多上下文信息
  • 提供用户选择界面,允许用户从多个图标中选择最合适的
  • 支持用户手动输入Iconify图标标识符如"mdi:home"

权衡1实时搜索 vs 数据库存储

选择: 数据库存储 权衡: 数据库存储需要额外的存储空间但减少了API调用提高性能

权衡AI生成关键字 vs 硬编码映射表

选择: AI生成关键字 权衡: AI生成关键字增加了API调用成本但更灵活覆盖范围更广

Migration Plan

部署步骤

  1. 数据库迁移

    • 执行SQL脚本添加TransactionCategory.IconKeywords字段可选
    • 修改TransactionCategory.Icon字段长度限制从-1改为50
  2. 代码部署

    • 修改Entity层TransactionCategory实体
    • 部署Service层IconSearchService
    • 部署WebApi层IconController
    • 更新前端图标渲染逻辑使用Iconify图标组件
  3. 数据迁移

    • 为现有分类生成搜索关键字
    • 允许用户为现有分类选择新图标
  4. 验证

    • 测试API接口搜索关键字生成、图标搜索、更新分类图标
    • 测试前端图标渲染
    • 性能测试Iconify API调用速度

回滚策略

  • 如果新系统出现问题可以回滚到旧的AI生成SVG图标逻辑
  • 保留旧代码分支,确保回滚时可以使用
  • IconKeywords字段可以保留不影响回滚

Open Questions

  1. AI搜索关键字生成的准确性

    • 问题: 如何评估AI生成的搜索关键字是否准确
    • 解决方案: 可以先进行小规模测试,人工评估关键字质量,再逐步扩大范围
  2. Iconify API调用量限制

    • 问题: Iconify API是否有调用量限制是否需要付费
    • 解决方案: 需要查阅Iconify API文档确认限流策略和费用
  3. 前端图标渲染性能

    • 问题: 大量图标渲染是否会影响前端性能?
    • 解决方案: 需要进行性能测试,必要时使用虚拟滚动或分页加载
  4. 图标更新策略

    • 问题: Iconify图标库更新后如何同步更新系统中的图标
    • 解决方案: 可以定期运行同步任务,或提供手动刷新接口