# 草原指南管理：素材选择器支持顶级分类整树分页与文件夹名称搜索

> **服务**: hl-resource-service (8082)
> **后端 Issue**: [wx/HL#4999](https://git.1814.love:8443/wx/HL/issues/4999)
> **后端 PR**: [wx/HL#5000](https://git.1814.love:8443/wx/HL/pulls/5000)、[wx/HL#5001](https://git.1814.love:8443/wx/HL/pulls/5001)
> **管理端 PR**: [wx/hl-ui#7](https://git.1814.love:8443/wx/hl-ui/pulls/7)
> **日期**: 2026-07-15
> **影响范围**: 管理后台草原指南新增/编辑页的视频素材选择器
> **当前状态**: 后端已合入 `dev` 并同步 `dev-v3`，管理端已合入 `v2.1`；测试环境部署及 API 验收通过

---

## 一、关键变化

现有素材列表默认遵循“只查当前分类节点”的兼容规则。草原指南视频都可存放在 `grassland_guide` 的子文件夹中，因此选择器必须显式传 `includeDescendants=true`，才能分页读取顶级分类自身及全部后代文件夹中的素材。

不要删除或改变普通素材库现有请求；新参数默认 `false`，未传时行为完全不变。

---

## 二、变更接口

| 接口 | 方法 | 路径 | 变更类型 |
|---|---|---|---|
| 素材分页列表 | GET | `/admin/material/list` | Query 新增可选参数 |

### 新增 Query 参数

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---:|---:|---|
| `includeDescendants` | Boolean | 否 | `false` | 是否包含所选分类的全部后代。需同时传 `categoryCode` |

规则：

- `categoryCode=grassland_guide&includeDescendants=true`：查询该顶级分类直挂素材及所有层级子文件夹素材。
- 同时传 `subCategoryId`：查询该子文件夹及其全部后代，不扩到兄弟文件夹。
- `keyword` 在树范围模式下同时匹配素材名称、素材描述和子文件夹名称；命中文件夹名称时返回该文件夹及后代中的素材。
- 分页、`fileType`、标签、创建人、日期、排序、状态和分类权限过滤继续由后端统一执行。
- 不传 `includeDescendants` 或传 `false`：继续严格只查当前节点，保持普通素材库兼容。

响应结构无变化，仍为 `Result<PageResult<MaterialVO>>`。

---

## 三、草原指南前端接入

视频选择器请求示例：

```http
GET /admin/material/list?page=1&limit=12&categoryCode=grassland_guide&fileType=video&includeDescendants=true
```

按子文件夹名称搜索：

```http
GET /admin/material/list?page=1&limit=12&categoryCode=grassland_guide&fileType=video&includeDescendants=true&keyword=额小胖动画草原篇
```

管理端已经完成以下接入，后续调用方不得通过 `lockCategory` 隐式推导查询范围：

1. `src/views/grassland-guide/VideoEditDrawer.vue`：视频 `MaterialSelect` 显式传 `include-descendants` 和 `allow-sub-category-select`。
2. `src/components/material-select/MaterialSelect.vue`：声明两个 prop 并透传给 `SelectModal`。
3. `src/components/material-select/SelectModal.vue`：构造请求时仅在 prop 为 `true` 时添加 `includeDescendants=true`；展示“全部文件夹”和锁定顶级分类下的全部子文件夹。
4. 选择“全部文件夹”时不传 `subCategoryId`，查询顶级分类整树；选择子文件夹时传其 `subCategoryId`，查询该文件夹及其后代。

子文件夹下拉只允许选择 `grassland_guide` 顶级分类内的节点，不能越权切换到其他素材分类。普通素材选择器不启用上述两个 prop，现有行为保持不变。

`lockCategory` 只表示 UI 不允许切换分类，`includeDescendants` 表示后端查询范围，两者不得耦合。

---

## 四、不影响范围

- 不修改素材库页面的默认分类查询语义。
- 不修改素材分类树、数量统计、删除规则或权限规则。
- 不修改素材上传、草原指南内容保存和小程序接口。
- 不迁移数据库，不需要新增字典、菜单或 Nacos 配置。
- 测试环境仅通过既有管理 API 创建一个普通子文件夹并移动两条测试素材用于验收，不属于数据库结构或正式环境数据迁移。

---

## 五、验证状态

- [x] 生产代码编译通过。
- [x] 专项测试 18 个通过：默认兼容、根分类整树、子分类子树、文件夹名搜索、SQL 条件、DTO 默认值。
- [x] `hl-resource-service` 及依赖测试 1347 个通过，失败 0。
- [x] 后端 PR #5000 已合入 `dev`，同步 PR #5001 已合入 `dev-v3`。
- [x] `dev-v3` 基线执行 `hl-resource-service` 及依赖测试 1673 个，失败 0、错误 0、跳过 38。
- [x] 管理端 2 个测试文件、16 项测试通过；相关 ESLint 和 Vite 生产构建通过。
- [x] 后端测试部署任务 `fd6615a6` 成功，8082/8182 双实例滚动更新完成，Nacos 2 个实例健康。
- [x] 管理端测试部署任务 `e34686c3` 成功，`v2.1` 已发布至测试环境。
- [x] 测试网关验证：默认当前节点视频 8 条、整树视频 9 条、整树全部素材 14 条、指定子文件夹视频 1 条、按文件夹名搜索视频 1 条。
- [x] 分页验证：每页 3 条时第 1、2 页各 3 条，总数 14，两页素材 ID 无重叠。
