Ver Fonte

docs(knowledge): 知识库统一实施计划 + PROJECT-OVERVIEW 同步(v2.19)

Xiaogang Liao há 5 dias atrás
pai
commit
ac451c9e8a

+ 5 - 1
docs/superpowers/PROJECT-OVERVIEW.md

@@ -1,11 +1,12 @@
 # 浠艾福 项目全景 — 阶段性需求与设计汇总
 
-**文档版本:** v2.18
+**文档版本:** v2.19
 **日期:** 2026-10-17
 **状态:** 已确认(v2.1 Phase 2-4 全栈完成)+ 虚拟支付改造(Tasks 1-12 已完成,退款闭环实施中)+ 新用户注册引导(12 Tasks 全栈完成)+ 家庭成员关系条增强(✅ 已实施)+ TabBar 重构(✅ 4Tab + 中间⭐扇形菜单,设计已对齐实现)+ **LIFETIME 终身会员(✅ 11 Tasks 全栈完成)** + **健康数据中心(✅ 全栈完成)** + **SKU 价格单位统一分 + 规格选择响应式修复(✅ 7 Tasks 全栈完成)** + **AI健康教练人格分化与管家自助选择(✅ 11 Tasks 全栈完成)** + **优惠券全链路改为家庭维度(待实施)** + **关系三图重构(关键人拓展章鱼图/珍珠图/能力图,设计规格已完成)** + **注册零填写+信息按需补充(✅ 全栈完成:登录直接进首页 + 家庭邀请独立页真实姓名/家庭身份必填 + 功能→信息字段映射表 + 添加成员手机号冲突邀请加入)** + **健康报告归属重分配(✅ 后端接口 + 管理端页面 + 小程序入口已实现,见 `specs/2026-10-05-health-report-reassign-design.md`)**
 **指标变化曲线·指标速查·指标关联(✅ 全栈完成:后端11任务+小程序M1-M8+管理端W1-W6;HBuilderX人工验收待用户执行,见 `specs/2026-10-09-indicator-change-curve-design.md`)**
 **饮食/睡眠/运动打卡接入任务完成链路(✅ 全栈完成:实体taskId字段 + 三个Controller isDailyProgress分流回写 + RepeatTaskGenerator每日生成打卡任务 + tasks.vue跳转 + 三打卡页taskId透传 + API文档;见 `specs/2026-10-13-health-checkin-task-linkage-design.md` 与 `plans/2026-10-13-health-checkin-task-linkage.md`)**
 **健康方案删除(✅ 全栈完成:后端级联删除接口含每日实例二次删除 + 小程序/管理端删除按钮 + 确认弹窗;见 `specs/2026-10-17-health-plan-deletion-design.md` 与 `plans/2026-10-17-health-plan-deletion.md`)**
+**菌群知识并入 dan_knowledge_base(🔄 实施中:809 篇文章以 source_type='article' 并入统一知识表 + 后端 sourceType/excludeSourceType 过滤 + langgraph 三源重建 + 管理端统一展示,见 `specs/2026-10-20-knowledge-unify-design.md` 与 `plans/2026-10-20-knowledge-unify.md`)**
 **维护:** 所有需求变更需更新本文档
 
 ---
@@ -234,6 +235,7 @@
 | Web端E2E测试修复 | Phase 1 | ✅ 已结束 | `plans/2026-06-20-cfc-web-e2e-test-fix.md` |
 | Web端重构(代码质量) | Phase 1 | ✅ 已结束 | `plans/2026-06-20-cfc-web-refactor.md` |
 | 维度知识库动态管理平台 | Phase 1 | ✅ 已实施(KnowledgeBaseController + HealthKnowledgeBaseController + LanggraphSyncService) | `specs/2026-06-20-dimension-knowledge-base-design.md` + `plans/2026-06-20-dimension-knowledge-base-plan.md` |
+| 知识库统一(菌群文章并入 dan_knowledge_base) | Phase 2 | 🔄 实施中(809 篇 source_type='article' + 管理端统一展示 + 健康知识库页下线) | `specs/2026-10-20-knowledge-unify-design.md` + `plans/2026-10-20-knowledge-unify.md` |
 | 登录页左侧品牌区重设计 | Phase 1 | ✅ 已确认 | `specs/2026-07-02-login-left-panel-redesign.md` |
 | 管理后台手机自适应 | Phase 2 | ✅ 已实施(Layout.vue响应式侧边栏+Login.vue全屏表单,commit 3ee7289e) | `specs/2026-07-24-cfc-web-responsive-design.md` + `plans/2026-07-24-cfc-web-responsive-implementation.md` |
 
@@ -334,6 +336,7 @@
 | `2026-06-24-cfc-ecommerce-extension-design.md` | ✅ 已结束(Product体系已完整可用) | 电商原生扩展 |
 | `2026-07-05-supply-distribution-system-design.md` | 🟡 待实施 | 供应商销售体系 |
 | `2026-06-20-dimension-knowledge-base-design.md` | ✅ 已实施(KnowledgeBaseController + LanggraphSyncService) | 维度知识库平台 |
+| `2026-10-20-knowledge-unify-design.md` | 🔄 实施中(809 篇菌群文章并入 dan_knowledge_base) | 知识库统一 |
 | `2026-06-20-web-permission-system-design.md` | 🔄 已暂停(未实现,待重新规划) | Web权限系统 |
 | `2026-06-26-health-dimensions-design-spec.md` | 🟡 设计稿 | 身体健康7维模型 |
 | `2026-06-22-growth-record-rebuild-design.md` | ✅ 后端已实现(HealthGrowthRecord + HealthGrowthRecordController + HealthGrowthRecordService) | 成长档案重建 |
@@ -424,6 +427,7 @@
 | `2026-06-22-family-relation-graph-redesign.md` | ✅ 已完成(FamilyRelationGraph.vue 797行,10+页面使用) | 关系图谱重构 |
 | `2026-06-22-营养健康部分缺陷修复计划.md` | ✅ 已实施(5项缺陷已修复) | 营养健康修复 |
 | `2026-06-20-dimension-knowledge-base-plan.md` | ✅ 已实施(KnowledgeBaseController + LanggraphSyncService) | 知识库平台 |
+| `2026-10-20-knowledge-unify.md` | 🔄 实施中(6 Tasks:后端过滤 / langgraph 重建 / DB 迁移 / 前端统一 / 清理) | 知识库统一 |
 | `2026-06-20-web-permission-system.md` | ✅ 已结束 | 权限系统 |
 | `2026-06-20-cfc-web-e2e-test-fix.md` | ✅ 已结束 | Web端E2E测试 |
 | `2026-06-20-cfc-web-refactor.md` | ✅ 已结束 | Web端重构 |

+ 354 - 0
docs/superpowers/plans/2026-10-20-knowledge-unify.md

@@ -0,0 +1,354 @@
+# 菌群知识并入 dan_knowledge_base 实施计划
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 将 809 篇菌群文章从 `health_knowledge_base` 并入 `dan_knowledge_base`,成为唯一知识条目表,管理端统一入口,langgraph 三源仍按 `metadata.source` 分流。
+
+**Architecture:** `dan_knowledge_base` 增加 `source_type='article'` 标记(该字段已存在且 39 条案例全为 `'file'`,无 title 唯一约束,809 篇零冲突);后端 list 接口增加 `sourceType`/`excludeSourceType` 参数;langgraph `dan_knowledge` 源用 `excludeSourceType='article'` 排除、`microbiome` 源用 `sourceType='article'` 拉取;前端知识库管理页增强后删除健康知识库页。
+
+**Tech Stack:** Spring Boot 2.7.18 + MyBatis-Plus(lambda wrapper)+ Vue 2.7 / Element UI + Python FastAPI / Chroma / httpx + MySQL 8.0.34
+
+**Spec:** `docs/superpowers/specs/2026-10-20-knowledge-unify-design.md`
+
+**关键事实(已勘察确认):**
+- `dan_knowledge_base` 唯一键:仅 PRIMARY(id),`title varchar(200)`,`content mediumtext`,现有 39 条全 `source_type='file'`
+- 809 篇文章 title 全部 ≤ 200 字符(无截断风险)
+- `DanKnowledgeBaseService.list` 的 `wrapper.orderByAsc(getSort)` **无 id tie-break**——所有文章 sort=0,重建索引可能漏块(与旧 `microbiome_article` 分页 bug 同类)
+- `knowledge_sync` 首次延迟 120s、之后每 3600s 定时全量重建三源,容器重启即重置计时
+
+## Global Constraints
+
+- 代码在 `111.228.6.214:/app/cfc`(git cfclub 分支),部署按 AGENTS.md:备份 → 构建 → 部署 → 验证 → 失败回滚
+- DB:`mysql -h mysql-internet-cn-north-1-23feae22680e4dfa.rds.jdcloud.com -P 3306 -u cfc -pcfc@1314 zxyj`
+- 后端 systemd `cfc-backend`(9082),生产 jar `/app/pro/cfc/backend/cfc-backend-1.0.0.jar`;langgraph `docker compose`(9000,容器 `cfc-langgraph-langgraph-svc-1`)
+- 管理端 API 统一 POST;管理端 axios 用 `import request from '@/utils/request'`(**不要用 `this.$axios`**,项目未注册该原型)
+- **category 字段丢弃**(不 ALTER 表)——Chroma metadata.category 写了从不读/过滤;`health_butler_graph` 读 category 走 `/api/health/knowledge/query`(读原表,不读 Chroma)
+- langgraph 新镜像 **必须先构建好(不部署)**,DB INSERT 后才 force-recreate 替换容器(避免窗口期双重索引)
+- 保留 `created_at`/`updated_at` 原始值(INSERT 显式指定列,不依赖默认 CURRENT_TIMESTAMP)
+- 生产目录 `/app/pro/cfc` 改动前必须先备份 jar;验证失败必须回滚 + 复验
+
+## Review Focus
+
+1. **langgraph 窗口期双重索引**(最高风险):DB INSERT 后若旧镜像仍在运行且定时同步触发,会把 848 条全部索引为 dan_knowledge。→ Task 2 先构建镜像,Task 3 立即 INSERT,Task 4 立即 force-recreate 替换容器。验证:重建日志 by_source 仅三源且块数与设计一致,`dan_knowledge` ≈ 1885。
+2. **分页稳定性**:`wrapper.orderByAsc(getSort)` 缺 id tie-break,809 篇 sort 全 0 → 重建漏块或重复。→ Task 1 加 `.orderByAsc(DanKnowledgeBase::getId)`。验证:重建后 microbiome 块数与 809 篇实际分块数一致,无重复 id。
+3. **dan_knowledge 源被误排除**:`excludeSourceType` 必须排除的是 `article`,不是 `file`。验证:`/api/admin/knowledge-base/list` 不传 sourceType 返回 848 条;传 excludeSourceType='article' 返回 39 条。
+4. **时间戳被覆盖**:INSERT 未显式指定 created_at/updated_at 会用 CURRENT_TIMESTAMP,809 篇 pub_date 全变 2026-10-20。验证:抽查 1 篇 pub_date = 原始健康表时间。
+5. **清理误删**:`DELETE` 必须限定 `item_type='article'`(表保留给未来指标条目)。验证:清理后表存在且 `COUNT(*)=0`,其他 item_type 行未动。
+6. **权限共享**:删路由与菜单共享 `knowledge:base` perm,删路由不应影响「知识库管理」页访问。验证:Layout.vue 与 router 均无 `health-knowledge`,知识库管理页仍可进入。
+
+---
+
+### Task 1: 后端 list 接口支持 sourceType/excludeSourceType + id tie-break
+
+**Files:**
+- Modify: `cfc-backend/src/main/java/com/etotem/cfc/service/DanKnowledgeBaseService.java:58-90`
+- Modify: `cfc-backend/src/main/java/com/etotem/cfc/controller/admin/KnowledgeBaseController.java:39-50`
+
+**Interfaces:**
+- Produces: `DanKnowledgeBaseService.list(String keyword, Integer status, int page, int size, Long tagId, Long dimensionId, String sourceType, String excludeSourceType)` — 8 参重载;保留 4 参/6 参重载委托 8 参(传 null),向后兼容现有调用方
+- Produces: API `POST /api/admin/knowledge-base/list` 接受 `sourceType`(精确匹配)与 `excludeSourceType`(排除匹配),不传则返回全部
+
+**Steps:**
+
+- [ ] **Step 1: Service 加 8 参重载与条件**
+
+在 `DanKnowledgeBaseService.java`:6 参 `list` 改为委托新 8 参方法(`list(keyword, status, page, size, tagId, dimensionId, null, null)`)。8 参方法内新增:
+
+```java
+if (sourceType != null && !sourceType.isEmpty()) {
+    wrapper.eq(DanKnowledgeBase::getSourceType, sourceType);
+}
+if (excludeSourceType != null && !excludeSourceType.isEmpty()) {
+    wrapper.ne(DanKnowledgeBase::getSourceType, excludeSourceType);
+}
+```
+
+排序改为 `wrapper.orderByAsc(DanKnowledgeBase::getSort).orderByAsc(DanKnowledgeBase::getId)`(id 作为稳定 tie-break)。
+
+- [ ] **Step 2: Controller 解析新参数**
+
+`KnowledgeBaseController.list` 在解析 dimensionId 后追加:
+
+```java
+String sourceType = (String) params.get("sourceType");
+String excludeSourceType = (String) params.get("excludeSourceType");
+```
+
+调用改为 `danKnowledgeBaseService.list(keyword, status, page, size, tagId, dimensionId, sourceType, excludeSourceType)`。
+
+- [ ] **Step 3: 删除 /article/list 死端点**
+
+langgraph 改用 `/api/admin/knowledge-base/list` 后,`HealthKnowledgeBaseController.article/list` 无人调用。同文件删除该端点方法及 `HealthKnowledgeBaseService.pageArticles`(**保留** `/query` `/list` `/import` `/delete` 等其他端点——`health_butler_graph` 依赖 `/query`)。
+
+- [ ] **Step 4: 编译验证**
+
+```bash
+cd /app/cfc/cfc-backend && mvn compile -DskipTests -q
+```
+Expected: BUILD SUCCESS,无编译错误。
+
+- [ ] **Step 5: 打包 + 备份 + 部署 + 验证**
+
+```bash
+BACKUP=/app/pro/cfc/backend/cfc-backend-$(date +%Y%m%d_%H%M%S)_b6_knowledge_unify.jar
+cp /app/pro/cfc/backend/cfc-backend-1.0.0.jar $BACKUP
+mvn package -DskipTests
+cp target/cfc-backend-1.0.0.jar /app/pro/cfc/backend/
+systemctl restart cfc-backend
+```
+
+验证(全部通过后才能进 Task 2):
+
+```bash
+curl -s -X POST http://localhost:9082/api/admin/knowledge-base/list -H 'Content-Type: application/json' -d '{"page":1,"size":1}' | jq '.data.total'        # 期望 39
+curl -s -X POST http://localhost:9082/api/admin/knowledge-base/list -H 'Content-Type: application/json' -d '{"page":1,"size":1,"excludeSourceType":"article"}' | jq '.data.total'  # 期望 39
+```
+Expected: 均 39(INSERT 前 article 为 0 条)。同时确认 `systemctl is-active cfc-backend` = active。
+
+- [ ] **Step 6: Commit**
+
+```bash
+cd /app/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/service/DanKnowledgeBaseService.java cfc-backend/src/main/java/com/etotem/cfc/service/HealthKnowledgeBaseService.java cfc-backend/src/main/java/com/etotem/cfc/controller/admin/KnowledgeBaseController.java cfc-backend/src/main/java/com/etotem/cfc/controller/HealthKnowledgeBaseController.java
+git commit -m "feat(knowledge): list 接口支持 sourceType/excludeSourceType 过滤 + id 稳定分页,移除废弃 /article/list 端点"
+```
+
+---
+
+### Task 2: langgraph 数据源改造 + 镜像构建(不部署)
+
+**Files:**
+- Modify: `cfc-langgraph/app/tools/java_client.py:146-166`(get_dan_knowledge_base)
+- Modify: `cfc-langgraph/app/tools/java_client.py:145-172`(get_microbiome_articles,当前调 `/api/health/knowledge/article/list`)
+
+**Interfaces:**
+- Consumes: Task 1 的 `POST /api/admin/knowledge-base/list`(`sourceType` / `excludeSourceType`)
+- Produces: `get_dan_knowledge_base()` → 仅案例报告(排除 article);`get_microbiome_articles()` → 仅菌群文章(article),返回结构与 `_build_chunks` 期望一致:`{id, title, content, category, source_url, sourceUrl, pubDate, createdAt, updatedAt}`
+
+**Steps:**
+
+- [ ] **Step 1: get_dan_knowledge_base 加排除**
+
+请求体改为 `{"page": page, "size": size, "status": 1, "excludeSourceType": "article"}`,size 保持 1000。docstring 补注:案例报告源,排除 article(菌群文章)。
+
+- [ ] **Step 2: get_microbiome_articles 改数据源**
+
+改为分页拉 `POST /api/admin/knowledge-base/list`,请求体 `{"page": page, "size": size, "status": 1, "sourceType": "article"}`(size 50,ORDER BY id 由后端保证)。字段映射对齐 `_build_chunks` 期望键(title/content/category 为空串/source_url 留空/pubDate 取 createdAt 或 updatedAt)。
+
+- [ ] **Step 3: 镜像构建(后台,不部署)**
+
+```bash
+cd /app/cfc/cfc-langgraph && nohup bash -c 'docker compose build langgraph-svc > /tmp/langgraph-build5.log 2>&1' &
+```
+等待完成(检查 `/tmp/langgraph-build5.log` 末行含 `Successfully built` 或 `DONE`,`docker images` 确认新镜像 tag)。**不要执行 `docker compose up`**。
+
+- [ ] **Step 4: 提交**
+
+```bash
+cd /app/cfc && git add cfc-langgraph/app/tools/java_client.py && git commit -m "feat(langgraph): microbiome 源改拉 dan_knowledge_base(source_type=article),dan 源排除 article"
+```
+
+**验收(进 Task 3 前):** 后端新接口可用 + langgraph 镜像已构建但容器未替换。
+
+---
+
+### Task 3: DB 迁移(备份 → INSERT 809 篇 → 校验)
+
+**Files:**
+- Create: `/tmp/migrate_articles.sql`(迁移脚本,上传远程执行)
+
+**Interfaces:**
+- Consumes: Task 1 的后端新接口(验证用)
+- Produces: `dan_knowledge_base` 含 848 条(39 file + 809 article),source_type 区分
+
+**Steps:**
+
+- [ ] **Step 1: 备份源表**
+
+```bash
+MY="mysql -h mysql-internet-cn-north-1-23feae22680e4dfa.rds.jdcloud.com -P 3306 -u cfc -pcfc@1314 zxyj"
+$MY -e "DROP TABLE IF EXISTS dan_knowledge_base_bak_20261020; CREATE TABLE dan_knowledge_base_bak_20261020 LIKE dan_knowledge_base; INSERT INTO dan_knowledge_base_bak_20261020 SELECT * FROM dan_knowledge_base;"
+$MY -e "DROP TABLE IF EXISTS health_knowledge_base_bak_20261020; CREATE TABLE health_knowledge_base_bak_20261020 LIKE health_knowledge_base; INSERT INTO health_knowledge_base_bak_20261020 SELECT * FROM health_knowledge_base;"
+```
+Expected: 两备份表行数 = 39 / 809。
+
+- [ ] **Step 2: INSERT 809 篇(保留原始时间戳)**
+
+```sql
+INSERT INTO dan_knowledge_base (title, content, sort, status, source_url, source_type, created_at, updated_at)
+SELECT item_name, description, 0, 1, source, 'article', created_at, updated_at
+FROM health_knowledge_base
+WHERE item_type = 'article';
+```
+Expected: `INSERT` 影响 809 行。
+
+- [ ] **Step 3: 校验**
+
+```bash
+$MY -e "SELECT source_type, COUNT(*) FROM dan_knowledge_base GROUP BY source_type;"   # 期望 file=39, article=809
+$MY -e "SELECT COUNT(*) FROM dan_knowledge_base WHERE CHAR_LENGTH(title) > 200;"         # 期望 0
+$MY -e "SELECT MIN(CHAR_LENGTH(content)), MAX(CHAR_LENGTH(content)) FROM dan_knowledge_base WHERE source_type='article';"
+$MY -e "SELECT MIN(created_at), MAX(created_at) FROM dan_knowledge_base WHERE source_type='article';"  # 期望为原始时间,非 2026-10-20
+curl -s -X POST http://localhost:9082/api/admin/knowledge-base/list -H 'Content-Type: application/json' -d '{"page":1,"size":1}' | jq '.data.total'   # 期望 848
+```
+若任一校验不符,**回滚**:`$MY -e "DELETE FROM dan_knowledge_base WHERE source_type='article';"` 后修正脚本重跑。
+
+- [ ] **Step 4: 提交迁移脚本**
+
+```bash
+mkdir -p /app/cfc/docs/migrations && cp /tmp/migrate_articles.sql /app/cfc/docs/migrations/20261020_articles_to_dan_knowledge.sql
+cd /app/cfc && git add docs/migrations && git commit -m "docs(knowledge): 809 篇菌群文章迁移至 dan_knowledge_base 脚本"
+```
+
+---
+
+### Task 4: 部署 langgraph 新镜像 + 全量重建索引
+
+**Files:** 无源码改动(仅部署 + 触发)
+
+**Interfaces:**
+- Consumes: Task 2 已构建镜像 + Task 3 已迁移数据
+- Produces: Chroma `cfc_knowledge` collection 三源重建完成,metadata 键 id/source/post_id/title/category/tags/source_url/pub_date/chunk_index/chunk_total
+
+**Steps:**
+
+- [ ] **Step 1: 替换容器**
+
+```bash
+cd /app/cfc/cfc-langgraph && docker compose up -d --force-recreate langgraph-svc
+docker ps --filter name=langgraph -f status=healthy
+```
+Expected: 容器 healthy 且使用 Task 2 的新镜像 digest。
+
+- [ ] **Step 2: 触发全量重建**
+
+```bash
+curl -s -m 60 -X POST http://localhost:9000/api/v1/knowledge-base/sync
+```
+Expected: 同步任务启动(首次延迟 120s 后执行)。
+
+- [ ] **Step 3: 监控重建进度**
+
+```bash
+docker logs --tail -50 cfc-langgraph-langgraph-svc-1 2>&1 | grep -E "知识库同步|同步完成|ERROR"
+```
+Expected: 依次看到 article / microbiome / dan_knowledge 三源同步日志,microbiome 为 809 篇,无 ERROR。重建约 20–30 分钟(SiliconFlow 429 退避)。
+
+- [ ] **Step 4: 验证三源统计**
+
+```bash
+curl -s -X POST http://localhost:9000/api/v1/knowledge-base/stats | python3 -m json.tool
+```
+Expected: `by_source` 三源均有数据,microbiome 块数 ≈ 原 25369 量级,dan_knowledge ≈ 1885,**无 source='microbiome' 出现在 article 或反之**(窗口期双重索引检查)。
+
+**验收(进 Task 5 前):** 三源重建完成 + 计数符合预期 + 无 ERROR 日志。
+
+---
+
+### Task 5: 前端知识库管理页增强 + 删除健康知识库页
+
+**Files:**
+- Modify: `cfc-web/src/components/KnowledgeTable/index.vue:10-25`(加来源方式列)
+- Modify: `cfc-web/src/views/admin/knowledge/index.vue:40-50`(加 sourceType 筛选下拉)+ fetch 参数
+- Modify: `cfc-web/src/components/KnowledgeDialog/index.vue`(查看长文详情对话框,如现有 content 列已支持展开则跳过)
+- Delete: `cfc-web/src/views/admin/health-knowledge.vue`
+- Modify: `cfc-web/src/router/index.js:772-776`(删 health-knowledge 路由)
+- Modify: `cfc-web/src/Layout.vue:235`(删菜单项)
+
+**Interfaces:**
+- Consumes: Task 1 的 `sourceType` 参数
+- Produces: 知识库管理页统一展示 848 条(source_type 可筛选/可识别),健康知识库页入口消失
+
+**Steps:**
+
+- [ ] **Step 1: KnowledgeTable 加来源列**
+
+在 sort 列前插入:
+
+```html
+<el-table-column prop="sourceType" label="来源方式" width="110" align="center">
+  <template slot-scope="{ row }">
+    <el-tag size="mini" :type="row.sourceType === 'article' ? 'success' : 'info'">{{ row.sourceType === 'article' ? '菌群文章' : (row.sourceType || '案例报告') }}</el-tag>
+  </template>
+</el-table-column>
+```
+
+- [ ] **Step 2: index.vue 加 sourceType 筛选**
+
+筛选区加下拉:
+
+```html
+<el-select v-model="filters.sourceType" placeholder="全部来源" clearable style="width:140px">
+  <el-option label="案例报告" value="file" />
+  <el-option label="菌群文章" value="article" />
+</el-select>
+```
+
+fetch 时传入 `sourceType`(不传则返回全部)。
+
+- [ ] **Step 3: 删除健康知识库页**
+
+```bash
+cd /app/cfc/cfc-web
+rm src/views/admin/health-knowledge.vue
+# 删 router/index.js 772-776 的 health-knowledge 路由对象
+# 删 Layout.vue:235 的菜单项
+grep -rn "health-knowledge\|健康知识库" src/  # 期望无残留(api 文件若有引用一并清理)
+```
+
+- [ ] **Step 4: 构建 + 部署 + 验证**
+
+```bash
+cd /app/cfc/cfc-web && npm run build 2>&1 | tail -3
+rsync -a --delete dist/ /app/pro/cfc/frontend/
+curl -s -k https://cfc.etotem.com.cn/admin/ -o /dev/null -w "%{http_code}\n"  # 期望 200
+```
+Expected: Build complete;前端 200;产物 js 中 grep 无 `health/knowledge` 残留。
+
+- [ ] **Step 5: Commit**
+
+```bash
+cd /app/cfc && git add -A cfc-web/src cfc-web/.last_build_commit && git commit -m "feat(knowledge): 知识库管理页统一展示案例报告与菌群文章(sourceType 筛选/标识),删除健康知识库页与路由"
+```
+
+---
+
+### Task 6: 全链路验证 + 清理源表文章 + 推送
+
+**Files:** 无源码改动
+
+**Steps:**
+
+- [ ] **Step 1: 全链路验证**
+
+```bash
+# 后端
+systemctl is-active cfc-backend
+curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:9082/api/cart/list    # 期望 200
+# 前端
+curl -s -o /dev/null -w "%{http_code}" -k https://cfc.etotem.com.cn/admin/           # 期望 200
+# 后端日志无 ERROR
+grep -c " ERROR " /app/pro/cfc/backend/cfc-backend.log
+# langgraph 三源统计
+curl -s -X POST http://localhost:9000/api/v1/knowledge-base/stats | python3 -m json.tool
+# 磁盘
+du -sh /var/lib/docker/volumes/cfc-langgraph_langgraph-data/_data/
+```
+
+- [ ] **Step 2: 清理源表文章数据(表保留)**
+
+```bash
+MY="mysql -h mysql-internet-cn-north-1-23feae22680e4dfa.rds.jdcloud.com -P 3306 -u cfc -pcfc@1314 zxyj"
+$MY -e "SELECT item_type, COUNT(*) FROM health_knowledge_base GROUP BY item_type;"   # 确认仅 article
+$MY -e "DELETE FROM health_knowledge_base WHERE item_type='article';"                 # 期望删 809
+$MY -e "SHOW TABLES LIKE 'health_knowledge_base';"                                    # 期望表仍存在
+$MY -e "SELECT COUNT(*) FROM health_knowledge_base;"                                  # 期望 0
+```
+Expected: 表存在且 `COUNT(*)=0`,其他 item_type 行未被删除。
+
+- [ ] **Step 3: 推送 + 工作区干净**
+
+```bash
+cd /app/cfc && git push origin cfclub && git status --short   # 期望空输出
+```
+
+**最终验收(全部通过):** 管理端「知识库管理」页 848 条统一展示且可筛选;「健康知识库」菜单/路由消失;向量库三源 by_source 计数符合设计(microbiome ≈ 25369、dan_knowledge ≈ 1885、article 不变);无 ERROR 日志;磁盘不膨胀;`health_knowledge_base` 表保留空置。