Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# 官方博客 RSS 订阅源集成提案

## 概述

在 Hagicode Desktop 应用主页集成 Hagicode 官方博客的 RSS 订阅源,允许用户直接在应用内查看最新的官方动态、技术文章和产品更新公告。

**变更 ID**: `official-blog-rss-feed-integration`
**状态**: ExecutionCompleted
**目标版本**: 待定

## 背景与动机

### 当前状态

Hagicode Desktop 是一个基于 Electron 的跨平台桌面应用,提供 Web 服务管理、包管理等功能。目前主页缺少官方博客内容的展示,用户需要:

- 手动访问外部网站获取 Hagicode 最新动态
- 无法及时了解产品更新和功能发布公告
- 缺少快速访问官方文档和教程资源的入口

### 目标

通过集成官方博客 RSS 订阅源(`https://docs.hagicode.com/blog/rss.xml`),在应用主页提供:
- 最新 5 条博客文章的快速预览
- 自动刷新机制,确保内容及时更新
- 一键跳转至完整文章

## 范围

### 包含内容

1. **主进程 RSS 管理器**
- 创建 `rss-feed-manager.ts` 单例管理器
- 实现从 `https://docs.hagicode.com/blog/rss.xml` 获取和解析 RSS 数据
- 使用 electron-store 持久化缓存 RSS 数据
- 实现每 24 小时自动刷新机制

2. **IPC 通信层**
- `rss-get-feed-items` - 获取 RSS 文章列表
- `rss-refresh-feed` - 手动触发刷新
- `rss-get-last-update` - 获取上次更新时间

3. **渲染进程状态管理**
- 创建 `rssFeedSlice.ts` 管理 RSS 状态
- 创建 `rssFeedSaga.ts` 处理异步操作

4. **UI 组件**
- 创建 `BlogFeedCard.tsx` 展示博客文章列表
- 集成到主页(SystemManagementView.tsx)

5. **国际化支持**
- 中英文翻译文件更新

### 排除内容

- RSS 订阅源配置界面(仅使用固定的官方博客地址)
- 离线模式下的缓存阅读(仅缓存数据用于刷新间隔)
- 博客内容的全文展示(仅摘要和跳转链接)

## 技术设计
Comment on lines +3 to +60

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the standard proposal sections (Why / What Changes / UI Design Changes / Code Flow Changes / Impact).
Please add or rename headings to match the required template; the current structure uses Overview/Background/Scope/Technical Design instead.

Based on learnings: Structure proposal.md with Why, What Changes, UI Design Changes (if applicable), Code Flow Changes (if applicable), and Impact sections.

🤖 Prompt for AI Agents
In
`@openspec/changes/archive/2025-02-10-official-blog-rss-feed-integration/proposal.md`
around lines 3 - 60, Update the proposal headings to match the standard template
by replacing or adding the sections: "Why" (move Background & motivation content
here), "What Changes" (move Scope and high-level change list here), "UI Design
Changes" (extract and expand any UI/UX details like
BlogFeedCard/SystemManagementView integration), "Code Flow Changes" (move
Technical Design items like rss-feed-manager.ts, IPC channels, rssFeedSlice/saga
and persistence/refresh logic here), and "Impact" (list rollout, performance,
privacy and maintenance impacts); ensure each section contains the existing
relevant text from Overview/Background/Scope/Technical Design and rename
headings accordingly while keeping the RSS URL, change ID and metadata intact.


### 架构概览

```
┌─────────────────────────────────────────────────────────────┐
│ 渲染进程 (Renderer) │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ BlogFeedCard │◄────│ rssFeedSlice │ │
│ │ (UI 组件) │ │ (Redux 状态) │ │
│ └─────────────────┘ └─────────────────┘ │
│ ▲ ▲ │
│ │ │ │
│ └───────┬───────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ rssFeedSaga │ │
│ │ (异步处理) │ │
│ └────────┬────────┘ │
└──────────────────┼───────────────────────────────────────────┘
│ IPC 通信
▼
┌─────────────────────────────────────────────────────────────┐
│ 主进程 (Main) │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ rss-feed-manager.ts (单例) │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ • fetchRSSFeed() - 获取 RSS 数据 │ │ │
│ │ │ • parseRSSXML() - 解析 XML │ │ │
│ │ │ • getCachedFeed() - 获取缓存数据 │ │ │
│ │ │ • refreshFeed() - 刷新 RSS 数据 │ │ │
│ │ │ • startAutoRefresh() - 启动定时刷新 │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ electron-store (持久化) │ │
│ │ • rssFeed.items - 文章列表 │ │
│ │ • rssFeed.lastUpdate - 最后更新时间 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 外部数据源 │
│ https://docs.hagicode.com/blog/rss.xml │
└─────────────────────────────────────────────────────────────┘
```
Comment on lines +64 to +110

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Specify a language for the fenced diagram block.
markdownlint MD040 requires a language on fenced code blocks.

📝 Suggested fix
-```
+```text
┌─────────────────────────────────────────────────────────────┐
│                      渲染进程 (Renderer)                      │
...
└─────────────────────────────────────────────────────────────┘
-```
+```
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
┌─────────────────────────────────────────────────────────────┐
│ 渲染进程 (Renderer) │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ BlogFeedCard │◄────│ rssFeedSlice │ │
│ │ (UI 组件) │ │ (Redux 状态) │ │
│ └─────────────────┘ └─────────────────┘ │
│ ▲ ▲ │
│ │ │ │
│ └───────┬───────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ rssFeedSaga │ │
│ │ (异步处理) │ │
│ └────────┬────────┘ │
└──────────────────┼───────────────────────────────────────────┘
│ IPC 通信
▼
┌─────────────────────────────────────────────────────────────┐
│ 主进程 (Main) │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ rss-feed-manager.ts (单例) │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ • fetchRSSFeed() - 获取 RSS 数据 │ │ │
│ │ │ • parseRSSXML() - 解析 XML │ │ │
│ │ │ • getCachedFeed() - 获取缓存数据 │ │ │
│ │ │ • refreshFeed() - 刷新 RSS 数据 │ │ │
│ │ │ • startAutoRefresh() - 启动定时刷新 │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ electron-store (持久化) │ │
│ │ • rssFeed.items - 文章列表 │ │
│ │ • rssFeed.lastUpdate - 最后更新时间 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 外部数据源 │
│ https://docs.hagicode.com/blog/rss.xml │
└─────────────────────────────────────────────────────────────┘
```
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 64-64: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In
`@openspec/changes/archive/2025-02-10-official-blog-rss-feed-integration/proposal.md`
around lines 64 - 110, The fenced ASCII diagram in proposal.md lacks a language
tag, triggering markdownlint MD040; update the opening fence for the diagram
(the triple-backtick block that begins the ASCII diagram containing "渲染进程
(Renderer)" and the box-drawing characters) to include a language identifier
such as text (e.g., change ``` to ```text) so the fenced code block is properly
annotated.


### 数据结构

```typescript
// RSS 文章项
interface RSSFeedItem {
title: string; // 文章标题
link: string; // 文章链接
pubDate: string; // 发布日期 (ISO 8601)
description: string; // 文章描述/摘要
guid?: string; // 唯一标识符
}

// RSS 缓存数据
interface RSSFeedCache {
items: RSSFeedItem[];
lastUpdate: string; // ISO 8601 时间戳
}
```

### IPC 通道定义

| 通道名称 | 类型 | 参数 | 返回值 | 描述 |
|---------|------|------|-------|------|
| `rss-get-feed-items` | invoke | 无 | `RSSFeedItem[]` | 获取缓存的 RSS 文章列表 |
| `rss-refresh-feed` | invoke | 无 | `Promise<RSSFeedItem[]>` | 手动触发刷新并返回最新文章 |
| `rss-get-last-update` | invoke | 无 | `string \| null` | 获取上次更新时间戳 |

## 实施计划

详细的实施任务清单请参见 [tasks.md](./tasks.md)。

## 影响分析

### 用户体验影响

**正面影响**:
- 用户可快速获取官方最新资讯
- 减少访问外部网站的需求
- 提升应用的信息聚合能力

**潜在风险**:
- 网络故障可能导致加载失败(需友好错误提示)
- RSS 源不可用时的降级处理

### 性能影响

- RSS 数据缓存减少网络请求
- 定时刷新在后台执行,不影响用户操作
- 仅显示最新 5 条文章,内存开销极小

### 兼容性影响

- 需要网络连接获取 RSS 数据
- 离线状态下显示缓存数据和提示信息

## 依赖项

### 新增依赖

| 包名 | 用途 | 版本要求 |
|-----|------|---------|
| `rss-parser` | RSS/XML 解析 | ^3.13.0 |
| `electron-store` | 数据持久化 | 已安装 ^10.0.0 |

### 现有依赖利用

- `axios` ^1.13.2 - HTTP 请求(已安装)
- `@reduxjs/toolkit` ^2.5.0 - 状态管理(已安装)
- `redux-saga` ^1.4.2 - 异步操作(已安装)
- `shadcn` ^3.6.2 - UI 组件(已安装)

## 风险与缓解

| 风险 | 影响 | 缓解措施 |
|-----|------|---------|
| RSS 源不可用 | 用户无法加载博客内容 | 显示友好错误提示,提供重试按钮 |
| RSS 格式变更 | 解析失败 | 添加错误处理和日志记录 |
| 网络延迟 | 加载时间过长 | 使用缓存数据,后台刷新 |
| 解析性能问题 | 主进程阻塞 | 使用异步解析,限制文章数量 |

## 测试策略

1. **单元测试**
- RSS 解析逻辑
- 缓存读写操作
- Redux slice reducers

2. **集成测试**
- IPC 通信正确性
- 自动刷新机制

3. **UI 测试**
- 组件渲染正确性
- 加载状态显示
- 错误状态处理

## 成功标准

- [x] 主进程成功获取并解析 RSS 数据
- [x] 渲染进程正确显示最新 5 条博客文章
- [x] 自动刷新机制正常工作(24小时间隔)
- [x] 手动刷新按钮功能正常
- [x] 网络错误时有友好提示
- [x] 中英文国际化支持完整
- [x] 点击文章正确跳转到浏览器

## 附录

### 参考资料

- [RSS 2.0 规范](https://www.rssboard.org/rss-specification)
- [rss-parser 文档](https://github.com/rbren/rss-parser)
- [项目代码结构文档](../../../docs/)

### 变更历史

| 日期 | 版本 | 作者 | 变更说明 |
|-----|------|------|---------|
| 2025-02-10 | 1.0 | Claude | 初始提案版本 |
Loading
Loading