# 综合牧业知识库 — 技术方案

> 依据：`综合牧业知识库管理功能需求.md`（同目录）

---

## 1. 技术架构

| 项 | 说明 |
| --- | --- |
| **整体** | RuoYi **v3.9.2**（**springboot2** 分支）单体后端 + 若依 **Vue2** 前端（与分支配套） |
| **运行时** | JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
| **数据库** | MySQL **5.7.39**，InnoDB，`utf8mb4` |
| **文件** | 复用 RuoYi **`/common/upload`**；表存正文 **URL + 存储路径 + 原始文件名**；**不入库**文件大小 |
| **知识库** | 复用项目 `KnowledgeBaseClient`（`uploadFileByUrl` / `deleteFile`）；分类常量建议 **`综合牧业知识`** |

**分层**：`Controller` → `Service`（入库状态机、事务、知识库编排、删附件）→ `Mapper`/XML → `domain` + `support`（校验、规则）。

**代码包（建议）**：`com.ruoyi.web.modules.farming`（与「畜牧科技资源」同域）  
**初始化脚本**：`sql/biz_livestock_knowledge.sql`

**一致性（与功能需求对齐）**

| 规则 | 实现要点 |
| --- | --- |
| 无发布态 | **不设** `publish_status`；仅以 `kb_sync_status` 表示入库 |
| 改删 | 仅 `kb_sync_status=0` 且 `del_flag=0` |
| 已入库 | 拒绝 `PUT`、逻辑删除；仅 `syncKb` / `removeKb` |
| 同步 | `kb_sync_status=0` → 调知识库上传成功 → 置 `1` 并写 `kb_doc_id`；失败**不**改状态 |
| 移出 | `kb_sync_status=1` → `deleteFile(kb_doc_id)` 成功 → 置 `0` 并清空 `kb_doc_id` |
| 修改不推库 | **已入库不可编辑**；未入库保存**不**自动调知识库 |
| 删除 | 逻辑删除 `del_flag=2` + 删 `content_file_path` 物理文件；`kb_sync_status=0` 时一般无需调 `deleteFile` |

---

## 2. 数据库设计

### 2.1 表 `biz_livestock_knowledge`（综合牧业知识条目）

| 字段 | 类型 | 非空 | 默认 | 说明 |
| --- | --- | --- | --- | --- |
| `id` | `bigint(20)` | Y | 自增 | 主键 |
| `knowledge_title` | `varchar(64)` | Y | — | 知识标题（业务 1～20 字） |
| `knowledge_topic` | `tinyint(4)` | Y | — | 知识主题，见 **2.2** |
| `introduction` | `varchar(200)` | N | NULL | 知识简介，选填 ≤50 字 |
| `content_file_url` | `varchar(512)` | Y | — | 正文附件访问 URL |
| `content_file_path` | `varchar(512)` | Y | — | 正文存储路径（上传 `fileName`） |
| `content_file_name` | `varchar(256)` | Y | — | 正文原始文件名（列表/下载展示） |
| `kb_sync_status` | `tinyint(4)` | Y | `0` | 入库状态：`0` 未入库，`1` 已入库 |
| `kb_doc_id` | `varchar(128)` | N | NULL | 知识库文档 ID（`file_id`） |
| `del_flag` | `char(1)` | Y | `'0'` | `0` 正常 / `2` 逻辑删除 |
| `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | — | — |
| `remark` | `varchar(500)` | N | NULL | 备注 |

**索引**：`PRIMARY KEY (id)`；`KEY idx_create_time (create_time)`；`KEY idx_topic (knowledge_topic)`；`KEY idx_kb (kb_sync_status)`；`KEY idx_del (del_flag)`。

**DDL（MySQL 5.7）**

```sql
CREATE TABLE `biz_livestock_knowledge` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `knowledge_title` varchar(64) NOT NULL COMMENT '知识标题（业务1～20字）',
  `knowledge_topic` tinyint(4) NOT NULL COMMENT '知识主题1-5',
  `introduction` varchar(200) DEFAULT NULL COMMENT '知识简介',
  `content_file_url` varchar(512) NOT NULL COMMENT '正文附件URL',
  `content_file_path` varchar(512) NOT NULL COMMENT '正文存储路径',
  `content_file_name` varchar(256) NOT NULL COMMENT '正文原始文件名',
  `kb_sync_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0未入库1已入库',
  `kb_doc_id` varchar(128) DEFAULT NULL COMMENT '知识库文档ID',
  `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '0正常2删除',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `idx_create_time` (`create_time`),
  KEY `idx_topic` (`knowledge_topic`),
  KEY `idx_kb` (`kb_sync_status`),
  KEY `idx_del` (`del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='综合牧业知识条目';
```

### 2.2 枚举

**`knowledge_topic`**

| 值 | 含义 |
| --- | --- |
| `1` | 饲养管理 |
| `2` | 疫病管理 |
| `3` | 设备选型 |
| `4` | 牧场设计 |
| `5` | 政策解读 |

**`kb_sync_status`（界面「入库状态」）**

| 值 | 含义 |
| --- | --- |
| `0` | 未入库 |
| `1` | 已入库 |

**`del_flag`**：`0` 正常 / `2` 逻辑删除；列表默认 `del_flag=0`。

---

## 3. 接口设计

统一响应：RuoYi `AjaxResult`（`code` / `msg` / `data`）或分页 `TableDataInfo`。

**权限标识（示例）**：`techService:knowledge:list|query|add|edit|remove|syncKb|removeKb`

**Base Path（示例）**：`/techService/knowledge`

| # | 说明 | Method | URI | 权限 | 要点 |
| --- | --- | --- | --- | --- | --- |
| 3.1 | 分页列表 | GET | `/techService/knowledge/list` | `techService:knowledge:list` | Query：`pageNum`（默认 1）、`pageSize`（默认 **20**）、`keyword`（标题/简介 OR 模糊）、`knowledgeTopic`（精确，可空）、`kbSyncStatus`（`0`/`1`，可空）；`del_flag=0`；排序 `create_time DESC, id DESC` |
| 3.2 | 详情 | GET | `/techService/knowledge/{id}` | `techService:knowledge:query` | 全字段；`del_flag=2` 可返回 404 或业务错误 |
| 3.3 | 新增 | POST | `/techService/knowledge` | `techService:knowledge:add` | Body：`knowledgeTitle`、`knowledgeTopic`、`introduction`（可空）、`contentFileUrl`、`contentFilePath`、`contentFileName`；落库 `kb_sync_status=0`，`kb_doc_id=null` |
| 3.4 | 修改 | PUT | `/techService/knowledge` | `techService:knowledge:edit` | Body 含 `id`；**仅** `kb_sync_status=0` 且未删除；替换附件后删旧 `content_file_path` 文件 |
| 3.5 | 删除 | DELETE | `/techService/knowledge/{ids}` | `techService:knowledge:remove` | **仅** `kb_sync_status=0`；逻辑删除 + 删正文物理文件；不调知识库（未入库无 `kb_doc_id`） |
| 3.6 | 同步知识库 | POST | `/techService/knowledge/syncKb/{id}` | `techService:knowledge:syncKb` | 前置 `kb_sync_status=0`；`KnowledgeBaseClient.uploadFileByUrl(contentFileUrl, "综合牧业知识", knowledgeTitle)`；成功写 `kb_sync_status=1`、`kb_doc_id` |
| 3.7 | 移出知识库 | POST | `/techService/knowledge/removeKb/{id}` | `techService:knowledge:removeKb` | 前置 `kb_sync_status=1` 且 `kb_doc_id` 非空；`deleteFile(kb_doc_id)` 成功后 `kb_sync_status=0`，清空 `kb_doc_id` |

### 3.1 列表响应字段（示例）

`id`、`knowledgeTitle`、`knowledgeTopic`、`introduction`、`contentFileName`、`kbSyncStatus`、`createTime`。

### 3.2 校验（Service 层）

| 项 | 规则 |
| --- | --- |
| `knowledgeTitle` | 必填，trim 后长度 1～20 |
| `knowledgeTopic` | 必填，`∈ {1,2,3,4,5}` |
| `introduction` | 选填，≤50 字 |
| 正文附件 | 必填；后缀 `pdf,md,doc,docx,xls,xlsx,pptx`；≤30MB（上传阶段 + 保存前二次校验，`LivestockKnowledgeRules.isContentExtensionAllowed`） |

### 3.3 业务错误（`msg` 示例）

| 场景 | 文案 |
| --- | --- |
| 已入库编辑/删除 | 已入库条目请先移出知识库后再操作 |
| 重复同步 | 该条目已入库 |
| 未入库移出 | 仅已入库条目可移出知识库 |
| 知识库失败 | 同步知识库失败：{原因} / 移出知识库失败：{原因} |

---

## 4. 知识库交互（摘要）

```text
同步：校验 kb_sync_status=0
  → uploadFileByUrl(content_file_url, category="综合牧业知识", description=knowledge_title)
  ← file_id → 本地 kb_doc_id，kb_sync_status=1

移出：校验 kb_sync_status=1
  → deleteFile(kb_doc_id)
  ← 成功 → kb_sync_status=0，kb_doc_id=NULL
```

- **配置**：复用 `KbApiProperties`（`kb.admin.base-url` 等）。  
- **URL 可达性**：`content_file_url` 须为知识库服务可 HTTP 拉取的地址（与饲喂/养殖标准一致，必要时经 `KbFileUrlResolver` 解析）。  
- **事务**：同步/移出建议「调知识库成功后再更新本地状态」；失败不改 `kb_sync_status`。  
- **问答**：终端提问走知识库查询接口，**不经**本模块 Controller 转发（与标准类模块一致）。

---

## 5. 附件与交付

- **上传**：前端先 `/common/upload`，再提交 `contentFileUrl` / `contentFilePath` / `contentFileName`。  
- **交付勾选**：DDL + 菜单按钮权限 SQL；Domain / Mapper / Service / Controller；单元测试 + MockMvc（列表筛选、状态拦截、同步/移出）。

---

## 6. 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初稿：对齐功能需求 v2.0；单表 `biz_livestock_knowledge`；仅 `kb_sync_status` 无发布态；7 个 REST 接口 |
| 1.1 | **2026-05-20**：正文白名单 `pdf/md/doc/docx/xls/xlsx/pptx`（不含 `ppt`）；`md` 经 `/common/upload` 全局白名单放行 |
