## 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生成的搜索关键字,便于后续分析和重新搜索
**字段修改**:
```csharp
public class TransactionCategory : BaseEntity
{
///
/// 图标(Iconify标识符格式:{collection}:{name},如"mdi:home")
///
[Column(StringLength = 50)]
public string? Icon { get; set; }
///
/// 搜索关键字(JSON数组,如["food", "restaurant", "dining"])
///
[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=&limit=`
**理由**:
- Iconify官方API,稳定可靠
- 响应速度快,支持批量查询
- 返回数据结构清晰,包含图标集名称和图标名称
**响应数据格式**:
```json
{
"icons": [
{
"name": "home",
"collection": {
"name": "mdi"
}
}
]
}
```
**图标渲染标识符**: `mdi:home`(图标集名称:图标名称)
## Risks / Trade-offs
### 风险1:Iconify API限流或中断
**风险**: Iconify API可能限流或服务中断,导致无法检索图标
**缓解措施**:
- 实现API调用重试机制(指数退避)
- 记录API调用失败日志,监控API可用性
- 如果API长时间不可用,提供备选方案(如使用已缓存的图标)
### 风险2:AI生成搜索关键字不准确
**风险**: AI生成的搜索关键字可能不准确,导致检索到的图标与分类不相关
**缓解措施**:
- 优化AI Prompt,提供更多上下文信息
- 提供人工审核接口,允许用户修改或补充搜索关键字
- 基于用户反馈不断优化AI Prompt
### 风险3:图标数量过多导致前端性能问题
**风险**: 某个分类可能关联大量图标,导致前端渲染性能下降
**缓解措施**:
- 前端分页加载图标(如每页显示10-20个)
- 提供图标搜索功能,允许用户过滤图标
- 图标懒加载,仅在可见区域渲染图标
### 风险4:Iconify 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图标库更新后,如何同步更新系统中的图标?
- 解决方案: 可以定期运行同步任务,或提供手动刷新接口