# Home 页新增“开源贡献”板块与后台可编辑支持 PRD ## 背景 用户希望在 `https://www.ephron.ren/` 首页新增一个独立板块:**开源贡献**,并且该板块内容必须能够在 Home 后台中编辑、保存草稿、发布,不接受只改前台模板的静态实现。 本 PRD 基于 `origin/main` 最新源码分析,覆盖 Home 的: - 公共渲染模板 - Admin 编辑模板 - content schema - 草稿 / 发布链路 - 兼容策略 - 测试要求 --- ## 现状分析 ### 1. 首页当前内容结构 当前 Home 页公共模板位于: - `home/templates/index.html` 当前页面主区块顺序大致为: 1. Hero 2. 工作经历 3. 项目经验 4. 技术栈 5. 页脚 6. 联系方式弹窗 其中内容类区块已经形成清晰模式: - `experience`:时间线列表 - `projects`:时间线列表 + tags + 可选 badge - `skills`:分类列表 ### 2. Home 内容 schema 当前主结构 当前 `home/src/services/content.py` 中 HomeContent 及默认内容模板包含: ```python hero experience projects skills contact footer ``` 当前**没有** `open_source` 或同义字段。 ### 3. 后台编辑页当前主结构 后台模板位于: - `home/templates/admin/index.html` 当前后台已提供以下可编辑区块: - Hero - 工作经历 - 项目经验 - 技术栈 - 联系方式 - 页脚 其 JS 通过 `initialContent` + 各类 `renderXxx()`、`addXxx()`、`updateXxx()`、`removeXxx()` 管理动态列表,再通过 `collectFormData()` 汇总为完整 `content_json`。 ### 4. Draft / Publish 机制已存在 Home Admin 已支持: - 保存草稿 - 发布内容 - 丢弃草稿 相关服务链路位于: - `home/src/routes/admin.py` - `home/src/services/content.py` 所以本次需求不应走“单独 API”或“静态 hardcode”路线,而应纳入现有 content schema。 --- ## 问题定义 如果只是简单在前台首页插入一个“开源贡献”区块,会有以下问题: 1. **后台无法维护** - 用户明确要求后台可修改 - 只改模板会让内容写死在代码里 2. **不进入草稿 / 发布流程** - 无法像其他首页内容一样先保存草稿再发布 3. **与 Home 当前内容架构不一致** - Home 当前是 schema 驱动 + admin 驱动 - 新区块也应遵循同样模式 4. **历史内容兼容问题** - 线上已有 `content_json` 一定不包含新字段 - 如果不做 normalize,可能出现模板取值缺失或后台初始值异常 --- ## 目标 ### 产品目标 在首页新增一个独立的 **开源贡献** 板块,用于展示用户的开源贡献记录。 ### 后台目标 管理员可在 Home 后台中: - 新增开源贡献条目 - 编辑开源贡献条目 - 删除开源贡献条目 - 标记草稿 / 已发布条目(如果沿用当前列表编辑模式) - 保存草稿 - 发布 ### 技术目标 将“开源贡献”纳入 Home 的统一内容 schema,而不是写死在模板中。 --- ## 核心设计判断 ## 为什么建议新增独立 `open_source` 区块,而不是复用 `projects` 虽然“开源贡献”看起来和“项目经验”都属于列表,但我**不建议复用 `projects`**,原因如下: 1. **语义不同** - 项目经验是个人项目 / 研究 / 比赛 /工程经历 - 开源贡献是对外部开源生态的参与记录 2. **展示重心不同** - 项目经验偏“我做了什么项目” - 开源贡献偏“我向哪些项目贡献了什么” 3. **后台认知更清晰** - 管理员能清楚区分两类信息 - 避免未来在同一列表中混入不同语义的数据 4. **后续扩展更容易** - 以后可独立增加 repo 链接、PR 链接、贡献类型、状态标签等 ### 结论 **本次建议新增独立字段:`open_source`** --- ## 数据结构设计 ### 建议新增主字段 在 Home content 顶层新增: ```json "open_source": [] ``` ### 单条条目建议结构 建议最小结构如下: ```json { "title": "Hermes Agent", "role": "提交 PR 修复 MiMo reasoning_content", "date": "2026.05", "description": [ "向上游提交并推动合并 MiMo reasoning_content 修复", "补充兼容性验证与使用说明" ], "tags": ["Python", "Hermes", "Open Source"], "link": "https://github.com/NousResearch/hermes-agent/pull/25358", "is_draft": false } ``` ### 字段说明 - `title` - 开源项目名 / 仓库名 / 贡献对象名 - `role` - 一句话说明贡献类型或身份 - 例如:修复 PR、功能贡献、文档维护、Issue triage - `date` - 贡献时间,沿用当前 Home 的字符串时间格式 - `description` - 多条描述,后台可按“每行一条”编辑 - `tags` - 技术标签或贡献类型标签 - `link` - 对外链接,建议指向 PR / repo / profile / issue - `is_draft` - 若沿用现有列表项 draft 切换机制,则保留该字段 ### 为什么建议有 `link` 因为“开源贡献”天然需要外部证明入口: - GitHub PR - 仓库主页 - 个人 Profile 如果没有链接,板块很容易退化成纯文字陈列。 --- ## 服务层改造 ### 必改文件 - `home/src/services/content.py` ### 要求 #### 1. 扩展默认 schema 在 `_get_empty_content()` 中新增: ```python "open_source": [] ``` #### 2. 扩展 normalize 在 `_normalize_content()` 中补: ```python content.setdefault("open_source", []) ``` #### 3. 兼容性原则 旧内容没有 `open_source` 时: - 首页应正常打开 - 后台应正常打开 - 不要求先清洗数据库历史内容 --- ## 前台首页改造 ### 必改文件 - `home/templates/index.html` ### 板块位置建议 建议插入在: - **项目经验之后** - **技术栈之前** 推荐顺序: 1. 工作经历 2. 项目经验 3. **开源贡献** 4. 技术栈 ### 原因 1. 信息层级更合理 - 工作 / 项目 / 开源 属于“经历与实践”一组 - 技术栈更适合作为总结性能力列表放在后面 2. 开源贡献不应放到页脚附近 - 会显得像附属信息,而不是正式内容资产 ### 渲染方式建议 建议复用当前 `timeline-item` 风格,保持页面一致性。 示意结构: ```jinja2 {% if content.open_source %}

开源贡献

{% for item in content.open_source if not item.get('is_draft', False) %}

{{ item.title }}

{{ item.role }}

{{ item.date }}
    {% for bullet in item.bullets %}
  • {{ bullet }}
  • {% endfor %}
{% if item.tags %}
{% for tag in item.tags %} {{ tag }} {% endfor %}
{% endif %} {% if item.link %} 查看贡献 {% endif %}
{% endfor %}
{% endif %} ``` ### 说明 - 样式可直接复用 `timeline-item`、`project-tags`、`project-badge` - 不建议本次重新发明一套视觉组件 - 重点是内容建模与后台可维护性,而不是视觉重构 --- ## 后台管理页改造 ### 必改文件 - `home/templates/admin/index.html` ### 建议新增一个完整 Section 在“项目经验”和“技术栈”之间新增: - 板块标题:`开源贡献` - 列表容器:`
` - 添加按钮:`+ 添加开源贡献` ### 建议沿用现有动态列表编辑模式 即仿照: - `renderProjects()` - `addProject()` - `removeProject()` - `updateProject()` - `toggleProjectDraft()` 新增一组: - `renderOpenSource()` - `addOpenSource()` - `removeOpenSource(index)` - `updateOpenSource(index, field, value)` - `updateOpenSourceBullets(index, value)` - `updateOpenSourceTags(index, value)` - `toggleOpenSourceDraft(index)`(若保留每项草稿状态) ### 单条后台表单建议字段 - 项目 / 仓库名称(title) - 贡献角色 / 一句话说明(role) - 时间(date) - 描述(每行一条) - 标签(逗号分隔) - 外部链接(link) ### collectFormData 必须同步补充 ```js open_source: initialContent.open_source, ``` 否则后台加了 UI 也不会进入 `content_json`。 --- ## 命名一致性要求 当前代码中存在一个值得注意的事实: - 前台项目区渲染使用的是 `project.bullets` - 但示例数据文件中很多项目仍然是 `description` 这说明 Home 当前已有一定字段漂移历史。 ### 本次 PRD 的要求 对于“开源贡献”,字段命名必须从一开始就统一,不要再制造第二套字段名。 建议直接统一使用: - `bullets` 作为前台 / 后台 / 存储字段名 而不是: - 后台叫 `description` - 前台叫 `bullets` - 示例数据再写成第三种 ### 结论 **开源贡献条目统一使用 `bullets`,不要引入 `description`。** --- ## 测试要求 ### 必改文件 - `home/tests/test_admin_permissions.py` 或 Home 对应测试文件 ### 建议至少补 4 类测试 #### 1. Admin 渲染测试 后台页面应出现: - `openSourceList` - `添加开源贡献` - 对应字段输入结构 #### 2. 首页渲染测试 当 `open_source` 有已发布数据时: - 首页应显示 `开源贡献` 标题 - 应显示条目标题 / 链接 #### 3. 空列表隐藏测试 当 `open_source` 为空时: - 首页不应显示空板块 #### 4. 旧 schema 兼容测试 当历史内容没有 `open_source` 字段时: - 首页正常打开 - 后台正常打开 ### 可选补充 如果你们继续沿用每项 `is_draft`: - 测试首页不会渲染 `open_source` 中 `is_draft=true` 的条目 --- ## 验收标准 ### 前台 1. 首页新增 `开源贡献` 板块 2. 板块位于“项目经验”之后、“技术栈”之前 3. 存在数据时正常渲染条目 4. 条目链接可打开外部页面 5. 无数据时不显示空板块 ### 后台 1. 管理页新增“开源贡献”编辑区块 2. 支持新增 / 编辑 / 删除条目 3. 保存草稿后刷新后台可回显 4. 发布后首页可见 5. 丢弃草稿后未发布修改可撤销 ### 兼容性 1. 历史 `content_json` 没有 `open_source` 字段时不报错 2. 不要求先手工迁移历史数据库内容 --- ## 非目标 本次 PRD 不包含: - 从 GitHub API 自动拉取开源贡献 - 统计贡献数量、Star、PR 数等自动指标 - 把开源贡献和项目经验合并 - 新增单独的 Home Service API - 重做首页视觉风格 --- ## 实施顺序建议 1. 先改 `home/src/services/content.py` - schema 默认值 - normalize 兼容 2. 再改 `home/templates/admin/index.html` - 新区块 UI - 新增 JS 列表管理逻辑 - 更新 `collectFormData()` 3. 最后改 `home/templates/index.html` - 新区块渲染 4. 补测试 这样可以避免先改模板后 schema 未补齐导致的半更新问题。 --- ## 结论 “开源贡献”不是单纯新增一段 HTML,而是一个完整的 **Home 内容模型扩展**。 要满足“前台显示 + 后台可改 + 草稿发布 + 历史兼容”,最小闭环必须同时覆盖: - schema - normalize - admin 区块 - 前台渲染 - 测试 建议采用独立 `open_source` 列表区块,而不是复用 `projects`。这样语义更清晰,也更利于后续继续扩展你的开源履历展示。