2026-06-20-dimension-knowledge-base-plan.md 16 KB

维度配置 + 知识库管理平台 — 实施计划

日期: 2026-06-21 状态: 准备就绪 基准: docs/superpowers/specs/2026-06-20-dimension-knowledge-base-design.md 范围: cfc-backend(5实体 + 3 Service + 5 Controller)+ cfc-web(api + store + 4组件 + 2页面)+ Dify 集成


总览

17 个任务,分 4 阶段执行。后端先于前端,模块独立,可并行。


Phase 1: 后端基础设施(Task 1–7)

Task 1: 创建 5 张数据库表

文件: cfc-backend/src/main/resources/

操作:

  • schema.sqlDatabaseInitializer 中添加 5 张表的 CREATE TABLE 语句(见设计文档 2.1–2.5)
  • 表名: product_dimension_config, dan_knowledge_base, dan_knowledge_base_dimension, dan_knowledge_tag, dan_knowledge_base_tag
  • 自增主键、默认值、唯一约束、外键级联删除

验证:

DESC product_dimension_config;
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='cfc' AND TABLE_NAME IN ('product_dimension_config','dan_knowledge_base','dan_knowledge_base_dimension','dan_knowledge_tag','dan_knowledge_base_tag');

Task 2: 创建 Entity + Mapper

文件: 每个 Entity 一个文件,Mapper 接口同理

Entity 文件 说明
ProductDimensionConfig entity/ProductDimensionConfig.java @TableName("product_dimension_config")
DanKnowledgeBase entity/DanKnowledgeBase.java @TableName("dan_knowledge_base")
DanKnowledgeBaseDimension entity/DanKnowledgeBaseDimension.java @TableName("dan_knowledge_base_dimension")
DanKnowledgeTag entity/DanKnowledgeTag.java @TableName("dan_knowledge_tag")
DanKnowledgeBaseTag entity/DanKnowledgeBaseTag.java @TableName("dan_knowledge_base_tag")

模式参考: ZodiacConfig.java@Data, @TableId(type = IdType.AUTO), implements SerializableMapper 参考: ZodiacConfigMapper.javaextends BaseMapper<ZodiacConfig>

API 路径:

  • Entity: cfc-backend/src/main/java/com/etotem/cfc/entity/
  • Mapper: cfc-backend/src/main/java/com/etotem/cfc/mapper/

验证: mvn clean compile 通过


Task 3: DimensionConfig CRUD Controller + Service

文件:

  • service/ProductDimensionConfigService.java
  • controller/admin/ProductDimensionConfigController.java

Service 方法:

  • list(String dimensionType, Integer enabled) — 列表(含筛选)
  • get(Long id) — 详情
  • save(ProductDimensionConfig config) — 新增/更新(id 有值则 update,否则 insert)
  • delete(Long id) — 删除
  • tree() — 树形结构(递归组装 parent/children)

Controller 端点: | 端点 | Service 方法 | |------|-------------| | POST /api/admin/dimension-config/list | list() | | POST /api/admin/dimension-config/get | get() | | POST /api/admin/dimension-config/save | save() | | POST /api/admin/dimension-config/delete | delete() | | POST /api/admin/dimension-config/tree | tree() |

验证: mvn clean compile → 启动 → curl 测试端点

模式参考: ZodiacConfigController.java@Resource Service, @PostMapping, 返回 Result


Task 4: KnowledgeBase CRUD Controller + Service

文件:

  • service/DanKnowledgeBaseService.java
  • controller/admin/DanKnowledgeBaseController.java

Service 方法:

  • list(String keyword, Integer page, Integer size) — 分页(支持 keyword 标题搜索)
  • get(Long id) — 详情(含关联的 dimensionIds、tagIds)
  • save(DanKnowledgeBase knowledge) — 新增/更新
  • delete(Long id) — 物理删除(级联删除关联表记录)

Controller 端点: | 端点 | Service 方法 | |------|-------------| | POST /api/admin/knowledge-base/list | list() | | POST /api/admin/knowledge-base/get | get() | | POST /api/admin/knowledge-base/save | save() | | POST /api/admin/knowledge-base/delete | delete() |

验证: mvn clean compile 通过

注:筛选(dimensionCode/tagId)依赖关联表查询,在 Task 6 完善


Task 5: KnowledgeTag CRUD Controller + Service

文件:

  • service/DanKnowledgeTagService.java
  • controller/admin/DanKnowledgeTagController.java

Service 方法:

  • list() — 全量列表(无分页,标签数量少)
  • save(DanKnowledgeTag tag) — 新增/更新(tag_name 有 UNIQUE 约束)
  • delete(Long id) — 删除(级联删除关联记录)

Controller 端点: | 端点 | Service 方法 | |------|-------------| | POST /api/admin/knowledge-tag/list | list() | | POST /api/admin/knowledge-tag/save | save() | | POST /api/admin/knowledge-tag/delete | delete() |

验证: mvn clean compile 通过


Task 6: 关联管理(KnowledgeBase ↔ Dimension ↔ Tag)

文件: 在已有的 DanKnowledgeBaseServiceDanKnowledgeBaseController 中增强

新增 Service 方法:

  • bindDimensions(Long knowledgeId, List<Long> dimensionIds) — 先删后加(先删 dan_knowledge_base_dimension 中该 knowledge 的所有记录,再批量插入)
  • bindTags(Long knowledgeId, List<Long> tagIds) — 同上
  • listByDimension(String dimensionCode, int page, int size) — 按维度代码筛选分页
  • listByTag(Long tagId, int page, int size) — 按标签筛选分页
  • listWithFilters(String keyword, Long dimensionId, Long tagId, int page, int size) — 综合筛选

新增/增强 Controller 端点: | 端点 | 说明 | |------|------| | POST /api/admin/knowledge-base/bind-dimensions | 绑定维度 | | POST /api/admin/knowledge-base/bind-tags | 绑定标签 |

增强 save(): 保存知识点的同时保存关联的 dimensionIds/tagIds(避免两次调用)

验证: 手动测试绑定/解绑逻辑


Task 7: DifySyncService(占位符)

文件:

  • service/DifySyncService.java

Service 方法:

  • syncToDify(Long knowledgeId, List<String> dimensionCodes)@Async 异步推送
  • removeFromDify(Long knowledgeId, String difyDatasetId)@Async 异步删除

实现:

  • 读取 dify.base-urldify.api-key 配置
  • Dify API 调用先用 log.warn("Dify sync not configured: {}", url) 占位
  • DanKnowledgeBaseService.save()delete() 末尾调用 difySyncService.syncToDify() / removeFromDify()(try-catch,失败只 log 不抛异常)

配置:

# application.yml
dify:
  base-url: http://dify.bianwoyou.cn
  api-key:
  timeout: 10000

验证: 启动后执行知识库 CRUD,观察日志无异常


Phase 2: 前端核心组件(Task 8–13)

Phase 2 模式参考

  • API 文件: cfc-web/src/api/xxx.js(已有模式: export const func = (data) => request({ url, method: 'post', data })
  • Vuex store: cfc-web/src/store/index.js(目前是 flat 结构,无 modules 目录。为保持一致性,新增 dimension.js 作为独立模块,在 store/index.jsimport dimension from './modules/dimension' 注册 modules: { dimension }
  • 组件: Element UI 组件库(el-table, el-dialog, el-select, el-tree, el-tag
  • 页面: cfc-web/src/views/admin/ 下的 Vue 2 组件(Options API)

Task 8: api/dimension.js API 封装

文件: cfc-web/src/api/dimension.js

函数列表:

// 维度配置
export const getDimensionList = (params) => request(...)
export const getDimensionDetail = (id) => request(...)
export const saveDimension = (data) => request(...)
export const deleteDimension = (id) => request(...)
export const getDimensionTree = () => request(...)

// 知识库
export const getKnowledgeList = (params) => request(...)
export const getKnowledgeDetail = (id) => request(...)
export const saveKnowledge = (data) => request(...)
export const deleteKnowledge = (id) => request(...)
export const bindKnowledgeDimensions = (data) => request(...)
export const bindKnowledgeTags = (data) => request(...)

// 标签
export const getTagList = () => request(...)
export const saveTag = (data) => request(...)
export const deleteTag = (id) => request(...)

验证: 无运行时验证,作为模块静态检查


Task 9: store/modules/dimension.js Vuex 模块

文件: cfc-web/src/store/modules/dimension.js

State:

  • dimensions: [] — 维度列表(flat)
  • dimensionTree: [] — 树形维度
  • knowledgeList: { items, total } — 知识点分页
  • tags: [] — 标签列表
  • loading: false

Actions: 对应 Task 8 的 API 调用 Mutations: 更新 state

注册:store/index.jsimport dimension from './modules/dimension'modules: { dimension }

验证:dimension.js import 到 store 后无 Babel 错误


Task 10: DimensionSelector 组件

文件: cfc-web/src/components/DimensionSelector/index.vue

Props:

  • value — v-model 绑定值(多选时是 Array,单选时是 String/Number)
  • multiple — 是否多选(默认 true)
  • dimensionType — 筛选维度类型(可选,传则只展示该类型的维度)
  • showTree — 是否树形展示(默认 false,flat)
  • placeholder — 默认 "请选择维度"

实现: 基于 el-select + el-option,options 来自 Vuex dimensions (flat) 或 dimensionTree (树形转 flat)

事件: @input 同步 v-model

验证: 在任意页面临时引用测试


Task 11: TagSelector 组件

文件: cfc-web/src/components/TagSelector/index.vue

Props:

  • value — v-model 绑定(Array of tagIds)
  • placeholder — 默认 "请选择标签"

实现:

  • el-select 多选
  • 支持输入新标签(filterable, allow-create),触发 @new-tag 事件调用 saveTag API
  • options 来自 Vuex tags

事件: @input, @new-tag

验证: 在任意页面临时引用测试


Task 12: KnowledgeTable 组件

文件: cfc-web/src/components/KnowledgeTable/index.vue

Props:

  • dimensionCode — 筛选维度(可选)
  • tagId — 筛选标签(可选)
  • keyword — 搜索关键词(可选,双向绑定)
  • page / size — 分页参数

实现:

  • el-table:datav-loading
  • 列: 标题、内容(截断)、关联维度(tag 形式)、状态(switch)、排序、操作按钮
  • el-pagination 底部
  • 行内操作: 编辑 / 删除 / 绑定维度 / 绑定标签(emit 事件,由父页面处理弹窗)
  • 内容列过长时 show-overflow-tooltip

事件:

  • @edit(row) / @delete(row) / @bind-dimensions(row) / @bind-tags(row)
  • @page-change(page, size) — 分页切换

验证: 在任意页面临时引用测试


Task 13: KnowledgeDialog 组件

文件: cfc-web/src/components/KnowledgeDialog/index.vue

Props:

  • visible — 显示/隐藏
  • knowledge — 编辑时传入数据(新增传 null)

实现:

  • el-dialog 包装
  • 表单: 标题(el-input)、内容(el-input type="textarea")、维度多选(DimensionSelector)、标签多选(TagSelector)、排序(el-input-number)、状态(el-switch
  • 表单验证(标题必填、内容必填)
  • @open 时如果 knowledge 有值则 populate 表单
  • 提交时调用 saveKnowledge API

事件:

  • @close — 关闭对话框
  • @saved — 保存成功后通知父页面刷新列表

验证: 在任意页面临时引用测试


Phase 3: 管理页面(Task 14–15)

Task 14: 维度配置管理页

文件: cfc-web/src/views/admin/dimension/index.vue

布局:

  • 左上方搜索栏: 维度类型筛选 + 新增按钮
  • 主区域: el-tree 树形展示(node-key="id", default-expand-all
  • 点击树节点 → 右侧展示详情/编辑弹窗

功能:

  • 新增维度: 弹窗表单输入所有字段
  • 编辑维度: 点击树节点行内编辑按钮 → 弹窗预填
  • 删除维度: 行内删除,二次确认
  • dify_dataset_id 字段为可选项,文本框输入

路由: /admin/dimension(在 router/index.js 的 admin 路由下添加)

验证: npm run serve → 浏览器访问页面,测试 CRUD


Task 15: 知识库管理页

文件: cfc-web/src/views/admin/knowledge/index.vue

布局:

┌──────────────────────────────────────┐
│      搜索框 [keyword]    [新增按钮]   │
├──────────┬───────────────────────────┤
│ 筛选面板  │    KnowledgeTable 组件    │
│ - 维度树  │                           │
│ - 标签列表 │                           │
│          │                           │
└──────────┴───────────────────────────┘

左侧筛选面板:

  • 维度树(el-tree)— 点击筛选该维度的知识点
  • 标签列表(el-tag + el-select)— 点击筛选该标签的知识点
  • 支持组合筛选(dimensionCode + tagId + keyword)

实现:

  • 引用 KnowledgeTable 组件展示主区域
  • 点击筛选 → 更新 dimensionCode/tagId/keyword → 传入 KnowledgeTable
  • 新增知识点 → 打开 KnowledgeDialog
  • 删除/绑定操作 → 分别调用对应 API,成功后刷新

路由: /admin/knowledge(在 router/index.js 的 admin 路由下添加)

验证: npm run serve → 浏览器访问页面,测试完整流


Phase 4: Dify 集成(Task 16–17)

Task 16: 补充 Dify API 实现

前置条件: 获取 Dify 最新的 Document Create API 格式

操作:

  • 确认 Dify 文档创建 API endpoint
  • DifySyncService 中补全实际 HTTP 调用(使用 RestTemplate)
  • 配置 dify.api-key 从环境变量读取

Dify REST API 调用:

// 参考实现
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(difyApiKey);
headers.setContentType(MediaType.APPLICATION_JSON);

String url = difyBaseUrl + "/v1/datasets/" + datasetId + "/documents/";
// POST with text content

验证: 用 curl 手动测试 Dify API 连通性


Task 17: 全流程联调

操作:

  1. 后端启动 → 验证所有 API 端点
  2. 前端启动 → 验证维度管理页面 CRUD
  3. 前端启动 → 验证知识库管理页面完整流程
  4. 验证 Dify 同步(如果有可用 Dify 环境)
  5. mvn clean compile 最终编译确认

验证清单:

  • POST /api/admin/dimension-config/list 返回正确
  • POST /api/admin/dimension-config/tree 返回树形结构
  • POST /api/admin/knowledge-base/save 含 dimensionIds 时同步保存关联
  • POST /api/admin/knowledge-base/list 支持维度/标签筛选
  • 前端维度管理页: 新增/编辑/删除/树形展示
  • 前端知识库管理页: 筛选/分页/新增/编辑/删除/绑定维度/绑定标签
  • 新增维度后前端正常展示(无需改代码)

依赖图

Task 1 (DB)
  ↓
Task 2 (Entity+Mapper)
  ├─→ Task 3 (DimensionConfig CRUD)
  ├─→ Task 4 (KnowledgeBase CRUD)
  └─→ Task 5 (KnowledgeTag CRUD)
        ↓
Task 6 (关联管理) ← 依赖 Task 3,4,5
Task 7 (DifySyncService) ← 依赖 Task 4
  ↓
Task 8 (api/dimension.js) ← 依赖 Task 3,4,5
Task 9 (store/modules/dimension.js) ← 依赖 Task 8
  ↓
Task 10 (DimensionSelector) ← 依赖 Task 9
Task 11 (TagSelector) ← 依赖 Task 9
Task 12 (KnowledgeTable) ← 依赖 Task 8
Task 13 (KnowledgeDialog) ← 依赖 Task 10,11,8
  ↓
Task 14 (dimension/index.vue) ← 依赖 Task 10,8,9
Task 15 (knowledge/index.vue) ← 依赖 Task 12,13,8,9
  ↓
Task 16 (Dify API) ← 依赖 Task 7
Task 17 (联调)

各阶段验证

阶段 验证命令 预期
Phase 1 cd cfc-backend && mvn clean compile BUILD SUCCESS
Phase 1 mvn spring-boot:run + curl 端点 200 OK
Phase 2 cd cfc-web && npm run serve 编译无错
Phase 3 浏览器访问页面 页面正常渲染
Phase 4 curl Dify API 连通性确认