内容分类系统设计:从混乱到有序的信息架构实践
问题起源
一个知识库/博客有 30+ 篇文章时,单纯的时间倒序排列变得不可用——新访客看不到知识结构,老用户找不到特定内容。用户的原话:"笔记没有排序和归类,看着混乱。"
两级分类架构
最终采用"大类 → 子分类(分组)"的两级结构,既不过于扁平也不过于深嵌套:
📚 知识笔记(大类)
├── Agent 基础 (子分类 / 分组)
├── 提示词与工具
├── RAG 与检索
├── LLM 深入
└── 架构与协议
📝 项目笔记(大类)
├── 患者Agent
├── 旅行规划师
├── 企业多Agent
└── 工程实践
数据结构设计
每篇文章新增 group 字段,全局配置 groupMeta 定义分组的视觉和排序属性:
// 全局分组配置
const groupMeta = {
"agent-basics": {
name: "Agent 基础",
order: 1,
color: "#3b82f6", // 蓝色色条
section: "knowledge" // 属于知识笔记区
},
"prompt-tools": {
name: "提示词与工具",
order: 2,
color: "#8b5cf6", // 紫色色条
section: "knowledge"
},
"rag-retrieval": {
name: "RAG 与检索",
order: 3,
color: "#06b6d4", // 青色色条
section: "knowledge"
},
// ... 更多分组
};
// 每篇文章数据
{
title: "ReAct 循环实战",
group: "agent-basics",
date: "2026-06-11",
tags: ["Agent", "ReAct", "控制流"],
url: "knowledge/react-loop.html"
}
渲染逻辑
内容渲染的核心是:先按 section 分区 → 区内按 group 分组 → 组内按日期降序。侧边栏同理。
function buildGroupedPosts(allPosts, filter) {
const sections = { knowledge: [], project: [] };
// 1. 将文章分配到分区
for (const post of allPosts) {
const meta = groupMeta[post.group];
if (!meta) continue;
// 应用筛选
if (filter && filter !== post.group && filter !== meta.section) continue;
sections[meta.section].push(post);
}
// 2. 每个分区内:按分组聚合
const result = [];
for (const [sectionName, posts] of Object.entries(sections)) {
const groups = {};
for (const post of posts) {
if (!groups[post.group]) groups[post.group] = [];
groups[post.group].push(post);
}
// 组内按日期降序
for (const g of Object.values(groups)) {
g.sort((a, b) => new Date(b.date) - new Date(a.date));
}
// 分组按 groupMeta.order 排序
const sortedGroups = Object.entries(groups)
.sort(([a], [b]) =>
(groupMeta[a]?.order || 99) - (groupMeta[b]?.order || 99)
);
result.push({ section: sectionName, groups: sortedGroups });
}
return result;
}
视觉设计原则
分组标识
每篇文章卡片左侧用 3px 色条 标识分组归属,不用图标或 emoji(用户明确反馈"纯功能主义")。
<!-- 文章卡片 -->
<div class="post-card">
<div class="group-strip"
style="border-left: 3px solid var(--group-color)"></div>
<div class="post-content">
<span class="group-label">Agent 基础</span>
<h3>ReAct 循环实战</h3>
<p>...</p>
</div>
</div>
分组头部
<!-- 简洁的分组标题:只用文本 + 计数 -->
<div class="group-header">
<span class="group-name">Agent 基础</span>
<span class="group-count">5</span>
</div>
<style>
.group-header {
display: flex;
align-items: center;
padding: 12px 16px;
font-weight: 600;
color: #374151;
border-bottom: 1px solid #e5e7eb;
margin-bottom: 12px;
}
.group-count {
margin-left: auto;
font-size: 0.85em;
color: #9ca3af;
}
</style>
设计决策记录
| 决策 | 选项 | 选择 | 理由 |
|---|---|---|---|
| 标识方式 | emoji / 图标 / 颜色 | 纯颜色色条 | 用户偏好纯功能主义,视觉噪音最小 |
| 排序规则 | 字母序 / 逻辑序 | 逻辑序(groupMeta.order) | 字母序不符合直觉 |
| 区域顺序 | 项目在上 / 知识在上 | 知识在上、项目在下 | 用户明确偏好 |
| 嵌套层级 | 2 级 / 3 级 | 2 级 | 3 级在 30 篇规模下过度设计 |
| 侧边栏同步 | 独立 / 联动 | 完全联动 | 用户强调一致性 |
演进原则
- 分类不是一次定型的:当文章增加到一定数量(50+/100+),需要重新审视分组是否合理
- 分组数量控制在 5-8 个:太少失去分类意义,太多和没分类一样混乱
- 侧边栏和内容区必须同步更新:不一致会导致用户体验割裂
- 新文章加入时自动归入对应分组,不需要手动维护列表
- 分组元数据(名称、颜色、顺序)集中管理在一个配置对象中,不要散落各处