知识库管理系统 - 架构设计
1. 技术栈
| 层 |
技术 |
版本 |
| 后端框架 |
Spring Boot |
3.2.x |
| ORM |
MyBatis Plus |
3.5.x |
| 数据库 |
MySQL |
8.0+ |
| 认证 |
JWT (jjwt) |
0.12.x |
| 抓取 |
Jsoup |
1.17.x |
| Diff |
google-diff-match-patch |
1.2 |
| HTTP 客户端 |
Spring RestClient(内置) |
- |
| 工具库 |
Hutool / Lombok |
最新稳定 |
| 前端框架 |
Vue |
3.4.x |
| 构建工具 |
Vite |
5.x |
| UI 库 |
Element Plus |
最新稳定 |
| 状态管理 |
Pinia |
最新稳定 |
| 路由 |
Vue Router |
4.x |
| 前端 Diff 展示 |
diff-match-patch(自渲染)或 vue-diff |
- |
2. 项目目录结构
knowledge-extractor/
├── backend/ 后端 Spring Boot 工程
│ ├── pom.xml
│ ├── src/main/java/com/knowledge/extractor/
│ │ ├── KnowledgeExtractorApplication.java
│ │ ├── config/
│ │ │ ├── WebMvcConfig.java (CORS)
│ │ │ ├── SpaController.java (SPA fallback)
│ │ │ ├── SecurityConfig.java (JWT 过滤器链)
│ │ │ ├── MybatisPlusConfig.java
│ │ │ └── RestClientConfig.java
│ │ ├── common/
│ │ │ ├── R.java (统一返回)
│ │ │ ├── PageResult.java
│ │ │ ├── BizException.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── JwtUtil.java
│ │ │ └── AesUtil.java
│ │ ├── module/
│ │ │ ├── auth/ 登录、JWT
│ │ │ │ ├── AuthController.java
│ │ │ │ ├── AuthService.java
│ │ │ │ ├── JwtFilter.java
│ │ │ │ └── entity/SysUser.java
│ │ │ ├── tag/ 标签体系(按 tag-system 技能)
│ │ │ │ ├── TagController.java
│ │ │ │ ├── TagService.java
│ │ │ │ ├── impl/TagServiceImpl.java
│ │ │ │ ├── entity/{TagGroup,Tag,TagAssignment}.java
│ │ │ │ ├── mapper/{TagGroupMapper,TagMapper,TagAssignmentMapper}.java
│ │ │ │ ├── dto/{TagExportDTO,TagImportDTO,TagImportResultDTO}.java
│ │ │ │ └── vo/TagBriefVO.java
│ │ │ ├── article/ 文章录入与抓取
│ │ │ │ ├── ArticleController.java
│ │ │ │ ├── ArticleService.java
│ │ │ │ ├── LinkFetcher.java (Jsoup + readability)
│ │ │ │ ├── entity/Article.java
│ │ │ │ └── mapper/ArticleMapper.java
│ │ │ ├── llm/ LLM 配置与客户端
│ │ │ │ ├── LlmConfigController.java
│ │ │ │ ├── LlmConfigService.java
│ │ │ │ ├── OpenAiCompatibleClient.java
│ │ │ │ ├── entity/LlmConfig.java
│ │ │ │ └── mapper/LlmConfigMapper.java
│ │ │ └── knowledge/ 知识聚合 + 版本管理
│ │ │ ├── KnowledgeController.java
│ │ │ ├── KnowledgeService.java
│ │ │ ├── KnowledgeAggregateService.java (调用 LLM、聚合、diff)
│ │ │ ├── DiffService.java
│ │ │ ├── entity/{Knowledge,KnowledgeVersion}.java
│ │ │ └── mapper/{KnowledgeMapper,KnowledgeVersionMapper}.java
│ │ └── mapper/ MyBatis mapper xml(如需)
│ └── src/main/resources/
│ ├── application.yml
│ ├── mapper/ MyBatis xml
│ └── static/ 前端构建产物(vite 直出)
├── frontend/ 前端 Vue 工程
│ ├── package.json
│ ├── vite.config.js
│ ├── index.html
│ └── src/
│ ├── main.js
│ ├── App.vue
│ ├── router/index.js
│ ├── stores/ Pinia stores
│ │ ├── auth.js
│ │ ├── tag.js
│ │ └── ...
│ ├── api/ axios 封装
│ │ ├── request.js
│ │ ├── auth.js
│ │ ├── tag.js
│ │ ├── article.js
│ │ ├── knowledge.js
│ │ └── llm.js
│ ├── layouts/
│ │ └── MainLayout.vue (顶部导航 + 侧边栏)
│ ├── components/
│ │ ├── tag/ (来自 tag-system 技能)
│ │ │ ├── TreeNodeItem.vue
│ │ │ └── TagSelector.vue
│ │ └── knowledge/
│ │ ├── VersionTimeline.vue
│ │ └── DiffViewer.vue
│ └── views/
│ ├── LoginView.vue
│ ├── SetupView.vue (首次启动引导)
│ ├── TagsView.vue (标签管理)
│ ├── ArticlesView.vue (文章录入)
│ ├── KnowledgeListView.vue (知识列表)
│ ├── KnowledgeDetailView.vue (知识详情 + 时间轴)
│ └── SettingsView.vue (LLM 配置 + 改密)
├── docs/ 本设计文档目录
├── run.bat Windows 一键构建脚本
├── run.sh Linux/macOS 一键构建脚本
└── .gitattributes
3. 数据库表设计(共 8 张)
3.1 标签体系(tag-system 技能标准)
-- 标签组(分类维度)
CREATE TABLE tag_group (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
description VARCHAR(500),
sort_order INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_name (name)
);
-- 标签节点(自引用树,每组有一个同名根节点 parent_id=NULL)
CREATE TABLE tag (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
group_id BIGINT NOT NULL,
parent_id BIGINT,
name VARCHAR(100) NOT NULL,
sort_order INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_group (group_id),
KEY idx_parent (parent_id)
);
-- 通用打标关联
CREATE TABLE tag_assignment (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
entity_type VARCHAR(50) NOT NULL, -- article / knowledge
entity_id BIGINT NOT NULL,
tag_id BIGINT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_entity_tag (entity_type, entity_id, tag_id),
KEY idx_entity (entity_type, entity_id)
);
3.2 系统与配置
-- 单用户
CREATE TABLE sys_user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password_hash VARCHAR(100) NOT NULL,
salt VARCHAR(50) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- LLM 配置(单行记录,id 固定为 1)
CREATE TABLE llm_config (
id BIGINT PRIMARY KEY,
base_url VARCHAR(255) NOT NULL, -- 如 https://api.openai.com/v1
api_key VARCHAR(500) NOT NULL, -- AES 加密后内容
model VARCHAR(100) NOT NULL, -- 如 gpt-4o-mini
temperature DECIMAL(3,2) DEFAULT 0.30,
max_tokens INT DEFAULT 4000,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
3.3 文章
CREATE TABLE article (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
source_type VARCHAR(20) NOT NULL, -- md / txt / link
source_url VARCHAR(500), -- link 类型记录原 URL
content MEDIUMTEXT, -- 原始正文(用于展示)
raw_text MEDIUMTEXT, -- 抽干后的纯文本(喂给 LLM)
llm_topic VARCHAR(100), -- LLM 归纳的主题名
status VARCHAR(20) DEFAULT 'pending', -- pending/classified/aggregated
error_msg VARCHAR(500), -- LLM 调用失败信息
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_status (status),
KEY idx_topic (llm_topic)
);
3.4 知识与版本
-- 聚合知识(每个 LLM 自由生成的主题对应一条记录)
CREATE TABLE knowledge (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200) NOT NULL, -- 主题名(如"大模型部署方法")
current_content MEDIUMTEXT NOT NULL, -- 最新版全文(前端展示)
article_count INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_title (title)
);
-- 版本快照(每次变更一条)
CREATE TABLE knowledge_version (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
knowledge_id BIGINT NOT NULL,
version_no INT NOT NULL, -- 第几版(1=初版)
article_id BIGINT NOT NULL, -- 触发本次变更的文章
change_type VARCHAR(20) NOT NULL, -- create / append / revise
change_desc VARCHAR(500) NOT NULL, -- 变更描述(LLM 生成)
content_snapshot MEDIUMTEXT NOT NULL, -- 本版完整 MD 快照
diff_added INT DEFAULT 0, -- 新增行数
diff_removed INT DEFAULT 0, -- 删除行数
diff_patch TEXT, -- diff-match-patch patch 文本(可选)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_knowledge (knowledge_id),
KEY idx_version (knowledge_id, version_no)
);
4. API 设计
4.1 认证
| 方法 |
路径 |
说明 |
| POST |
/api/auth/setup |
首次启动设置管理员账号 |
| GET |
/api/auth/setup-status |
查询是否已初始化 |
| POST |
/api/auth/login |
登录,返回 JWT |
| POST |
/api/auth/change-password |
修改密码 |
| GET |
/api/auth/me |
获取当前用户 |
4.2 标签(按 tag-system 技能规范)
| 方法 |
路径 |
说明 |
| GET |
/api/tags/groups |
列出所有标签组 |
| POST |
/api/tags/groups |
创建标签组 |
| POST |
/api/tags/groups/{id}/edit |
更新 |
| POST |
/api/tags/groups/{id}/delete |
删除 |
| GET |
/api/tags/groups/{groupId}/tags |
获取组内扁平标签列表 |
| POST |
/api/tags/groups/{groupId}/tags |
创建标签节点 |
| POST |
/api/tags/{id}/edit |
重命名 |
| POST |
/api/tags/{id}/delete |
删除(递归) |
| POST |
/api/tags/{id}/move |
移动(含防循环) |
| GET |
/api/tags/export |
导出 |
| POST |
/api/tags/import |
导入 |
| POST |
/api/tags/assignments |
设置实体标签(全量替换) |
| GET |
/api/tags/assignments?entityType=&entityId= |
获取实体标签 |
| GET |
/api/tags/all-with-tags |
全部标签(选择器用) |
4.3 文章
| 方法 |
路径 |
说明 |
| GET |
/api/articles?page=&size=&keyword= |
分页列表 |
| GET |
/api/articles/{id} |
文章详情 |
| POST |
/api/articles |
录入文章(md/txt/link) |
| POST |
/api/articles/{id}/fetch-link |
重新抓取链接 |
| POST |
/api/articles/{id}/classify |
触发 LLM 重新归类 |
| POST |
/api/articles/{id}/aggregate |
触发聚合(手动) |
| DELETE |
/api/articles/{id} |
删除 |
4.4 知识
| 方法 |
路径 |
说明 |
| GET |
/api/knowledge?page=&size=&keyword= |
知识列表 |
| GET |
/api/knowledge/{id} |
知识详情(含 current_content) |
| GET |
/api/knowledge/{id}/versions |
时间轴(版本列表) |
| GET |
/api/knowledge/{id}/versions/{versionNo} |
单版本详情(含 snapshot + diff) |
| GET |
/api/knowledge/{id}/versions/{versionNo}/article |
跳转关联原文章 |
| DELETE |
/api/knowledge/{id} |
删除知识(级联删版本) |
4.5 LLM 配置
| 方法 |
路径 |
说明 |
| GET |
/api/llm/config |
获取配置(api_key 返回掩码) |
| POST |
/api/llm/config |
保存配置 |
| POST |
/api/llm/config/test |
测试连通性 |
5. 业务流程
5.1 文章录入与归类流程
1. 用户提交文章(md/txt/link)
├── md/txt:直接保存 content + raw_text
└── link:Jsoup 抓取 + readability 提取正文;失败提示用户手动贴入
2. 文章入库后状态 = pending
└── 自动(或用户手动点)触发 classify
3. classify 流程:
a. 加载所有标签扁平列表(含路径,如"计算机/人工智能/LLM")
b. 调用 LLM 接口,prompt 让其输出 JSON:
{
"candidateTagIds": [12, 34], // 匹配的已有标签 ID
"newTags": [ // 需要新建的标签
{ "parentPath": "计算机/人工智能", "name": "RAG" }
],
"topic": "大模型部署方法" // 文章主题
}
c. 新建缺失标签,写入 tag_assignment
d. 更新 article.llm_topic = topic, status = classified
4. 自动触发 aggregate(或用户手动)
a. 查询现有所有 knowledge 列表(仅 id + title)
b. 调用 LLM,让其判断本文应归入哪个 knowledge(按 topic + 现有标题语义匹配)
c. 若归入已有:
- 调用 LLM 生成补充段落 + 变更描述
- 新建 knowledge_version(type=append, version_no=last+1)
- 更新 knowledge.current_content
d. 若不归入任何已有:
- 调用 LLM 生成初版知识全文
- 新建 knowledge + knowledge_version(type=create, version_no=1)
e. 计算 diff(前一版 vs 当前版),存入 diff_added/diff_removed/diff_patch
5.2 知识查看流程
1. 进入知识列表 → 选择一条知识 → 进入详情页
2. 详情页三栏布局:
├── 左:版本时间轴(点击节点)
├── 中:当前 knowledge.current_content 渲染
└── 右:选中版本的变更详情面板
├── 变更类型徽章(create/append/revise)
├── 变更描述
├── diff 行数(+x / -y)
├── diff 可视化(红绿块)
└── "查看关联原文章"按钮 → 跳转 /articles/{article_id}
3. 切换时间轴节点 → 右侧面板与中间内容联动:
- 点击历史版本 → 中间展示该版本 content_snapshot
6. 初始化与引导
首次启动 → 检查 sys_user 表
├── 空 → 前端访问任意页面跳转 /setup
│ → 用户设置 username/password → 同时配置 LLM
│ → 写入 sys_user + llm_config → 跳转 /login
└── 非空 → 正常登录流程
7. 安全设计
- JWT:HS256,密钥从配置读取,过期时间 7 天
- api_key:AES-128 加密入库,密钥从 application.yml 读取
- 密码:BCrypt 加盐
- 所有 /api/** 除 /api/auth/setup、/api/auth/login、/api/auth/setup-status 外需 JWT