# 培训大纲接口说明

## 功能概述

培训大纲使用统一层级表维护，支持三种层级：

- `1` 年度
- `2` 月度
- `3` 周度

层级关系如下：

- 年度大纲没有上级，`parentId=0`
- 月度大纲的上级必须是年度大纲
- 周度大纲的上级必须是月度大纲

培训类型字段 `trainingType` 为字典值，对应字典类型 `hot_training_type`，前端按项目现有字典接口获取可选项。

## 数据字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| id | Long | 否 | 主键，编辑/删除/详情时使用 |
| companyId | Long | 否 | 公司ID；不传时后端优先取当前登录公司 |
| parentId | Long | 条件必填 | 上级大纲ID；年度传 `0` 或不传，月度/周度必传 |
| outlineLevel | Long | 是 | 大纲层级：`1=年度`、`2=月度`、`3=周度` |
| outlineName | String | 是 | 大纲名称 |
| outlineFile | String | 是 | 大纲文件，建议传 OSS ID 或文件 URL |
| trainingType | String | 是 | 培训类型字典值 |
| isEnabled | Long | 否 | 是否启用：`0=禁用`、`1=启用`，默认 `1` |
| sortNo | Long | 否 | 排序号，越小越靠前，默认 `0` |
| remark | String | 否 | 备注 |

## 返回字段补充说明

除上述字段外，列表/详情接口还会返回：

- `parentName`：上级大纲名称
- `outlineLevelName`：层级名称，取值为 `年度`、`月度`、`周度`
- `trainingTypeLabel`：培训类型字典标签
- `isEnabled`：是否启用，`0=禁用`、`1=启用`
- `hasChildren`：是否存在直属子级

## 可见性规则

- 总部端可新增、修改 `isEnabled`
- 企业端查询列表、年度列表、直属子级、详情、导出时，只能看到 `isEnabled=1` 的大纲
- 企业端即使知道禁用大纲的 ID，也无法通过详情或子级接口查看

## 1. 分页查询培训大纲

- 路径：`GET /securityManagement/trainingOutline/list`
- 说明：后台通用分页查询，可按名称、层级、父级、培训类型筛选

### 请求参数

| 参数 | 类型 | 说明 |
| --- | --- | --- |
| pageNum | Integer | 页码 |
| pageSize | Integer | 每页条数 |
| companyId | Long | 公司ID |
| parentId | Long | 上级大纲ID |
| outlineLevel | Long | 层级 |
| outlineName | String | 大纲名称，模糊匹配 |
| trainingType | String | 培训类型字典值 |
| isEnabled | Long | 是否启用 |

## 2. 查询全部年度大纲

- 路径：`GET /securityManagement/trainingOutline/annuals`
- 说明：返回所有年度层级的大纲列表

### 可选参数

| 参数 | 类型 | 说明 |
| --- | --- | --- |
| companyId | Long | 公司ID |
| trainingType | String | 培训类型字典值 |
| outlineName | String | 大纲名称，模糊匹配 |
| isEnabled | Long | 是否启用，总部端可用 |

### 返回示例

```json
[
  {
    "id": 1,
    "companyId": 1,
    "parentId": 0,
    "outlineLevel": 1,
    "outlineLevelName": "年度",
    "outlineName": "2026年度培训大纲",
    "outlineFile": "197845612345678901",
    "trainingType": "pre-job",
    "trainingTypeLabel": "岗前培训",
    "isEnabled": 1,
    "sortNo": 1,
    "remark": "",
    "hasChildren": true
  }
]
```

## 3. 查询直属子大纲列表

- 路径：`GET /securityManagement/trainingOutline/children/{parentId}`
- 说明：前端传入某个大纲ID，返回该大纲的直属子级列表

### 场景说明

- 传入年度大纲ID：返回该年度下全部月度大纲
- 传入月度大纲ID：返回该月度下全部周度大纲
- 传入周度大纲ID：返回空数组

## 4. 查询详情

- 路径：`GET /securityManagement/trainingOutline/{id}`

## 5. 新增培训大纲

- 路径：`POST /securityManagement/trainingOutline`
- `Content-Type`：`application/json`

### 年度新增示例

```json
{
  "companyId": 1,
  "outlineLevel": 1,
  "outlineName": "2026年度培训大纲",
  "outlineFile": "197845612345678901",
  "trainingType": "pre-job",
  "isEnabled": 1,
  "sortNo": 1,
  "remark": "年度培训总纲"
}
```

### 月度新增示例

```json
{
  "companyId": 1,
  "parentId": 1,
  "outlineLevel": 2,
  "outlineName": "2026年12月培训大纲",
  "outlineFile": "197845612345678902",
  "trainingType": "pre-job",
  "isEnabled": 1,
  "sortNo": 12
}
```

### 周度新增示例

```json
{
  "companyId": 1,
  "parentId": 2,
  "outlineLevel": 3,
  "outlineName": "2026年12月第1周培训大纲",
  "outlineFile": "197845612345678903",
  "trainingType": "pre-job",
  "isEnabled": 1,
  "sortNo": 1
}
```

### 后端校验规则

- 年度大纲自动按 `parentId=0` 处理
- 月度大纲的上级必须是年度大纲
- 周度大纲的上级必须是月度大纲
- 同一公司、同一父级、同一层级下不允许同名
- `isEnabled` 仅总部端可控制；未传时默认按启用处理

## 6. 修改培训大纲

- 路径：`PUT /securityManagement/trainingOutline`
- `Content-Type`：`application/json`

### 请求示例

```json
{
  "id": 3,
  "companyId": 1,
  "parentId": 2,
  "outlineLevel": 3,
  "outlineName": "2026年12月第2周培训大纲",
  "outlineFile": "197845612345678904",
  "trainingType": "daily",
  "isEnabled": 0,
  "sortNo": 2,
  "remark": "更新后的周度大纲"
}
```

## 7. 删除培训大纲

- 路径：`DELETE /securityManagement/trainingOutline/{ids}`
- 示例：`DELETE /securityManagement/trainingOutline/3`
- 说明：支持批量，多个ID使用英文逗号分隔

### 删除限制

- 存在直属子级时不可删除

## 8. 导出列表

- 路径：`POST /securityManagement/trainingOutline/export`
- 说明：按查询条件导出 Excel

## 9. 导出 PDF

- 路径：`POST /securityManagement/trainingOutline/exportPdf`
- 说明：默认导出年度大纲；如传 `id`，则导出该节点所属年度的大纲内容
