Files
ephron-ren-prd/prd-collection-enhancements.md

11 KiB
Raw Blame History

PRD集合功能增强

一、问题分析

问题 1集合详情页不显示已收录文章

页面https://blog.ephron.ren/collections/data-structure

现象:集合详情页显示「该集合暂无文章」,但实际上已有文章被收录到该集合。

根因分析

路由代码 blog/src/routes/pages.py 第 488-519 行:

for item in collection.get("items", []):
    post = get_post_by_slug(item["post_slug"], include_drafts=False)
    if post:
        items.append({...})

可能原因:

  1. blog_collection_items 表中没有对应数据
  2. 文章 slug 与集合中记录的 post_slug 不匹配
  3. 文章是草稿状态但使用了 include_drafts=False

需要验证:查询数据库确认 blog_collection_items 表是否有数据。


问题 2全部文章列表不显示集合归属

页面https://blog.ephron.ren/posts

现象:文章列表只显示置顶、日期、标签、草稿标记,不显示文章所属的集合。

用户期望:已收录到集合的文章应在全部文章列表中显示集合标记(类似标签),方便识别哪些文章已被组织到集合中。


问题 3新建文章/提示词时无法选择集合

页面

  • Bloghttps://blog.ephron.ren/admin/new
  • Prompthttps://prompt.ephron.ren/admin/new

现象:新建文章/提示词时,只能先创建内容,再手动编辑集合添加。

用户期望:创建时即可选择加入已有集合,提升内容组织效率。


二、需求详情

需求 1修复集合详情页文章显示

优先级P0Bug 修复)

验收标准

  • 访问 /collections/{key} 能正确显示已收录的文章
  • 文章按 sort_order 排序显示
  • 显示文章标题、摘要、备注
  • 空集合显示「该集合暂无文章」

技术方案

  1. 检查并修复 blog_collection_items 表数据
  2. 确保 get_post_by_slug 在包含草稿时能正确返回
  3. 添加日志排查 slug 匹配问题

需求 2全部文章列表显示集合标记

优先级P1功能增强

验收标准

  • 文章列表中,已收录到集合的文章显示集合标记
  • 标记可点击,跳转到集合详情页
  • 一篇文章可属于多个集合,显示所有集合标记
  • 未收录到任何集合的文章不显示标记

UI 设计

文章标题                                    📌 置顶
摘要内容...
2025-01-01  [标签1] [标签2]  [集合A] [集合B]  草稿

集合标记样式:

  • 背景色:var(--accent-glow)(蓝色半透明)
  • 文字色:var(--accent)
  • 圆角:4px
  • 前缀图标:📁📚

技术方案

  1. pages.pyposts_list 函数中,批量查询文章的集合归属
  2. 使用 get_all_collection_post_slugs() 或更高效的批量查询
  3. 将集合信息传递给模板
  4. 模板中渲染集合标记

API 变更

# 新增批量查询函数
def get_posts_collections(post_slugs: list[str]) -> dict[str, list[dict]]:
    """
    批量查询多篇文章的集合归属
    返回: {post_slug: [{key, title}, ...]}
    """

需求 3新建文章/提示词时选择集合

优先级P1功能增强

3.1 Blog 新建文章

页面/admin/new

验收标准

  • 新建文章表单增加「选择集合」下拉框
  • 支持多选(可加入多个集合)
  • 显示集合名称和已有文章数量
  • 提交时自动创建 blog_collection_items 记录
  • 权限控制:需要 blog.post.create_draft 权限

UI 设计

<div class="form-group">
    <label>加入集合(可选)</label>
    <select name="collection_keys" multiple class="input">
        <option value="">-- 不加入集合 --</option>
        <option value="data-structure">数据结构 (5篇)</option>
        <option value="algorithm">算法 (3篇)</option>
    </select>
    <span class="hint">按住 Ctrl/Cmd 可多选</span>
</div>

技术方案

  1. admin.pynew_collection_page 函数传递集合列表
  2. 表单增加 collection_keys 字段(数组)
  3. create_new_post 函数处理集合关联
  4. 调用 add_item_to_collection 创建关联记录

API 变更

# POST /admin/new 新增字段
collection_keys: list[str] = Form(default=[])  # 集合 key 列表

3.2 Prompt 新建提示词

页面/admin/new

验收标准

  • 新建提示词表单增加「选择集合」下拉框
  • 支持多选
  • 提交时自动创建 collection_items 记录
  • 权限控制:需要 prompt.create 权限

技术方案:同 Blog修改 Prompt 服务的 admin.py 和相关模板。

3.3 API 创建文章/提示词

Blog Service API

# POST /api/service/posts
{
    "title": "文章标题",
    "content": "...",
    "tags": ["tag1"],
    "collection_keys": ["col1", "col2"]  # 新增
}

Prompt Service API

# POST /api/service/prompts
{
    "key": "prompt-key",
    "title": "提示词标题",
    "content": "...",
    "collection_keys": ["col1", "col2"]  # 新增
}

验收标准

  • API 支持 collection_keys 参数
  • 参数可选,默认为空数组
  • 自动创建集合关联记录
  • 集合不存在时忽略(不报错)
  • 权限检查:需要对应集合的编辑权限

三、数据模型

Blog 集合表结构

-- 集合主表
CREATE TABLE blog_collections (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    key TEXT UNIQUE NOT NULL,
    title TEXT NOT NULL,
    description TEXT DEFAULT '',
    cover_image TEXT DEFAULT '',
    created_by TEXT,
    is_active INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now')),
    updated_at DATETIME DEFAULT (datetime('now'))
);

-- 集合关联表
CREATE TABLE blog_collection_items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    collection_key TEXT NOT NULL,
    post_slug TEXT NOT NULL,
    sort_order INTEGER DEFAULT 0,
    note TEXT DEFAULT '',
    created_at DATETIME DEFAULT (datetime('now')),
    FOREIGN KEY (collection_key) REFERENCES blog_collections(key) ON DELETE CASCADE,
    UNIQUE(collection_key, post_slug)
);

Prompt 集合表结构

-- 集合主表
CREATE TABLE collections (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    key TEXT UNIQUE NOT NULL,
    title TEXT NOT NULL,
    description TEXT DEFAULT '',
    created_by TEXT,
    is_active INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now')),
    updated_at DATETIME DEFAULT (datetime('now'))
);

-- 集合关联表
CREATE TABLE collection_items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    collection_key TEXT NOT NULL,
    prompt_key TEXT NOT NULL,
    sort_order INTEGER DEFAULT 0,
    note TEXT DEFAULT '',
    created_at DATETIME DEFAULT (datetime('now')),
    FOREIGN KEY (collection_key) REFERENCES collections(key) ON DELETE CASCADE,
    UNIQUE(collection_key, prompt_key)
);

四、与 Prompt 集合逻辑的差异

特性 Blog 集合 Prompt 集合
内容类型 文章Markdown 提示词(模板)
主键 post_slug(文件名) prompt_key(数据库 key
创建方式 文件系统扫描 数据库插入
集合显示 需求2全部文章列表显示集合标记 已有:全部提示词列表显示集合标记
创建时选择集合 需求3新建时可选 需求3新建时可选

关键差异

  • Blog 文章是文件系统驱动,集合关联是后加的
  • Prompt 提示词是数据库驱动,集合关联是原生支持

五、实施计划

Phase 1Bug 修复(需求 1

时间0.5 天

任务

  1. 检查 blog_collection_items 表数据
  2. 修复数据不一致问题
  3. 验证集合详情页正常显示

Phase 2全部文章显示集合标记需求 2

时间1 天

任务

  1. 实现 get_posts_collections() 批量查询函数
  2. 修改 pages.pyposts_list 函数
  3. 修改 index.html 模板
  4. 测试多集合、空集合场景

Phase 3新建时选择集合需求 3

时间1.5 天

任务

  1. Blog修改 admin.pynew.html
  2. Prompt修改 admin.pynew.html
  3. Blog API修改 Service API 支持 collection_keys
  4. Prompt API修改 Service API 支持 collection_keys
  5. 测试权限控制和边界场景

六、测试用例

需求 1 测试

编号 测试内容 预期结果
T-001 访收录有文章的集合详情页 显示文章列表
T-002 访问空集合详情页 显示「该集合暂无文章」
T-003 文章排序 按 sort_order 升序
T-004 草稿文章 不显示(公开页)

需求 2 测试

编号 测试内容 预期结果
T-010 已收录文章显示集合标记 显示蓝色标记
T-011 未收录文章 不显示集合标记
T-012 点击集合标记 跳转到集合详情页
T-013 文章属于多个集合 显示多个标记
T-014 搜索结果中显示 同样显示集合标记

需求 3 测试

编号 测试内容 预期结果
T-020 Blog 新建选择集合 自动关联到集合
T-021 Blog 新建不选集合 正常创建,不关联
T-022 Blog API 带 collection_keys 自动关联
T-023 Prompt 新建选择集合 自动关联到集合
T-024 Prompt API 带 collection_keys 自动关联
T-025 集合 key 不存在 忽略,不报错
T-026 权限不足 返回 403

七、风险与依赖

风险

  1. 数据一致性Blog 文章删除后,blog_collection_items 中的关联记录可能成为孤立数据
  2. 性能影响:全部文章列表需要额外查询集合信息,可能增加数据库压力
  3. 权限复杂性:创建文章时选择集合需要同时检查文章和集合的权限

依赖

  1. 需求 1 是需求 2 的前提(集合详情页必须能正常显示)
  2. 需求 3 依赖现有集合 CRUD 功能
  3. Blog 和 Prompt 服务的集合逻辑独立,可并行开发

八、相关代码位置

Blog 服务

  • 集合详情路由:blog/src/routes/pages.py 第 488-519 行
  • 文章列表路由:blog/src/routes/pages.py 第 120-160 行
  • Admin 新建路由:blog/src/routes/admin.py 第 431-497 行
  • Service API 路由:blog/src/routes/service_api.py
  • 集合服务层:blog/src/services/blog_collections.py
  • 集合详情模板:blog/templates/collection_detail.html
  • 文章列表模板:blog/templates/index.html
  • Admin 新建模板:blog/templates/admin/new.html

Prompt 服务

  • Admin 新建路由:prompt/src/routes/admin.py
  • Service API 路由:prompt/src/routes/service_api.py
  • 集合服务层:prompt/src/services/collections.py
  • Admin 新建模板:prompt/templates/admin/new.html

九、验收标准汇总

  • 集合详情页正确显示已收录文章
  • 全部文章列表显示集合标记
  • 新建文章时可选择加入集合
  • 新建提示词时可选择加入集合
  • API 创建支持 collection_keys 参数
  • 权限控制正确
  • 边界场景处理(空集合、不存在的 key、重复关联