培训接口文档(泰额版)
模块:培训 / 资料中心
范围:泰额版后端(租户业务库,非antis-foodlabeling-host)
认证:Authorization: Bearer {token};业务请求建议带__tenant: {tenantId}
JSON:camelCase
Base URL 示例:http://127.0.0.1:19002(以实际部署为准)
更新日期:2026-08-07
1. 业务说明
| 概念 | 说明 |
|---|---|
| 一级分类 | parentId 为空 |
| 二级分类 | parentId 指向一级分类 Id;仅两级 |
| 培训文件 | 只能挂在二级分类下 |
| 文件权限 | 落在文件上:Company / Region / Location,各为 ALL 或 SPECIFIED |
| Company | fl_partner;字段 partnerIds / companyIds 等价 |
| Region | fl_group;字段 regionIds / groupIds 等价 |
| Location | location;字段 locationIds |
权限约定(推荐做法)
主路径:上传 / 编辑文件时直接传公司、区域、门店范围(可传 ALL 或具体多值 Id)。
独立「编辑文件权限」接口仅作兼容保留,前端可不使用。
| 维度 | 类型字段 | Id 数组 | 说明 |
|---|---|---|---|
| Company | appliedPartnerType |
partnerIds / companyIds |
ALL 或 SPECIFIED + Guid 列表(可含哨兵 "ALL") |
| Region | appliedRegionType |
regionIds / groupIds |
同上 |
| Location | availabilityType(别名 appliedLocationType) |
locationIds |
同上 |
- 上传时不传任何 scope 字段 → 默认三维度均为
ALL - 编辑时不传任何 scope 字段 → 不改原权限(仅改文件名/排序)
- 编辑时传入任一 scope 字段 → 整套权限按入参覆盖保存
SPECIFIED且仅选当前上下文「恰好全集」时,回显保持具体 Guid / 声明类型,不误折成["ALL"](与标签模板等一致)
文件存储
| 环境 | 路径 |
|---|---|
| Linux 生产 | /www/wwwroot/FoodLabelingManagementSAAS/training |
| 本地兜底 | {API ContentRoot}/wwwroot/FoodLabelingManagementSAAS/training |
库中 fileUrl |
/training/{存储文件名} |
- 单文件最大 20MB
- 扩展名:
.jpg/.jpeg/.png/.webp/.gif/.bmp、.pdf/.doc/.docx/.xls/.xlsx/.ppt/.pptx/.txt/.csv fileType:image/doc/other
建表
- 脚本:
module/food-labeling-us/scripts/fl_training.sql - 在每个租户业务库执行;新租户开通时会自动执行
2. 接口一览
2.1 管理端 TrainingAppService
| 功能 | 方法 | 路由 |
|---|---|---|
| 分类树 | GET | /api/app/training/category-tree |
| 新增分类 | POST | /api/app/training/category |
| 编辑分类 | PUT | /api/app/training/category/{id} |
| 删除分类 | DELETE | /api/app/training/category/{id} |
| 上传文件(含权限) | POST | /api/app/training/file/upload |
| 编辑文件(含权限) | PUT | /api/app/training/{id}/file |
| 删除文件 | DELETE | /api/app/training/{id}/file |
| 文件排序 | PUT | /api/app/training/sort-files |
| 获取文件权限(兼容) | GET | /api/app/training/file-scope/{id} |
| 设置文件权限(兼容) | PUT | /api/app/training/file-scope/{id} |
上传、
file-scope为显式路由;其余多为 ABP 约定路由。以 Swagger 为准。
另有约定路径GET/PUT /api/app/training/{id}/file-scope,与file-scope/{id}等价兼容。
2.2 APP UsAppTrainingAppService
| 功能 | 方法 | 路由 |
|---|---|---|
| 门店可见分类树+文件 | GET | /api/app/us-app-training/tree |
3. 管理端接口详情
3.1 获取分类树
GET /api/app/training/category-tree
Query
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| keyword | string | 否 | 匹配分类名或文件名 |
| locationId | string | 否 | 按门店过滤可见文件;不传则不过滤权限 |
| includeFiles | bool | 否 | 是否返回文件,默认 true |
响应要点:一级 children 为二级;二级 files 为 TrainingFileDto(含完整 scope 回显字段)。
[
{
"id": "1001",
"categoryName": "分类1",
"parentId": null,
"orderNum": 100,
"children": [
{
"id": "1002",
"categoryName": "子1",
"parentId": "1001",
"orderNum": 90,
"children": [],
"files": [
{
"id": "23148558702612480",
"categoryId": "1002",
"fileName": "学情测评试题.pdf",
"fileUrl": "/training/20260807120000_xxx.pdf",
"fileType": "doc",
"fileSize": 102400,
"orderNum": 100,
"appliedPartnerType": "ALL",
"company": "All Companies",
"partnerIds": ["ALL"],
"companyIds": ["ALL"],
"appliedRegionType": "SPECIFIED",
"region": "武侯区",
"regionIds": ["3a22e2f6-0679-9a5b-19b4-fc6db2d92dcc"],
"groupIds": ["3a22e2f6-0679-9a5b-19b4-fc6db2d92dcc"],
"availabilityType": "SPECIFIED",
"location": "分店2",
"locationIds": ["3a22e2f6-e944-2038-ffd8-fc82d9d388ac"],
"creationTime": "2026-08-07T12:00:00",
"lastModificationTime": "2026-08-07T12:00:00"
}
]
}
],
"files": []
}
]
3.2 新增分类
POST /api/app/training/category
{
"categoryName": "Training",
"parentId": null,
"orderNum": 100
}
| 字段 | 说明 |
|---|---|
| categoryName | 必填;同级不可重名 |
| parentId | 空 = 一级;传一级 Id = 二级 |
| orderNum | 排序 |
响应:TrainingCategoryGetOutputDto(id / categoryName / parentId / orderNum / 时间字段)
常见错误:名称为空、父级不存在、在二级下再建子级、同级重名。
3.3 编辑分类
PUT /api/app/training/category/{id}
{
"categoryName": "Training(更新)",
"orderNum": 90
}
不可改层级(parentId 不可改)。
3.4 删除分类
DELETE /api/app/training/category/{id}
软删除。规则:一级下仍有二级不可删;二级下仍有文件不可删。
3.5 上传文件(主路径,含权限)
POST /api/app/training/file/upload
Content-Type: multipart/form-data
| 表单字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | file | 是 | 文件本体 |
| categoryId | string | 是 | 二级分类 Id |
| orderNum | int | 否 | 排序 |
| appliedPartnerType | string | 否 | ALL / SPECIFIED |
| partnerIds | string[] | 否 | 可重复传多个 form 字段;可含 ALL |
| companyIds | string[] | 否 | 同 partnerIds |
| appliedRegionType | string | 否 | ALL / SPECIFIED |
| regionIds | string[] | 否 | 可含 ALL |
| groupIds | string[] | 否 | 同 regionIds |
| availabilityType | string | 否 | Location:ALL / SPECIFIED |
| appliedLocationType | string | 否 | availabilityType 别名 |
| locationIds | string[] | 否 | 可含 ALL |
curl 示例(全 ALL)
curl -X POST "http://127.0.0.1:19002/api/app/training/file/upload" \
-H "Authorization: Bearer <token>" \
-H "__tenant: <tenantId>" \
-F "file=@./手册.pdf" \
-F "categoryId=<二级分类Id>" \
-F "orderNum=100" \
-F "appliedPartnerType=ALL" \
-F "partnerIds=ALL" \
-F "appliedRegionType=ALL" \
-F "regionIds=ALL" \
-F "availabilityType=ALL" \
-F "locationIds=ALL"
curl 示例(指定公司 + 门店)
curl -X POST "http://127.0.0.1:19002/api/app/training/file/upload" \
-H "Authorization: Bearer <token>" \
-H "__tenant: <tenantId>" \
-F "file=@./手册.pdf" \
-F "categoryId=<二级分类Id>" \
-F "appliedPartnerType=SPECIFIED" \
-F "partnerIds=<partnerGuid>" \
-F "appliedRegionType=SPECIFIED" \
-F "regionIds=<groupGuid>" \
-F "availabilityType=SPECIFIED" \
-F "locationIds=<locationGuid1>" \
-F "locationIds=<locationGuid2>"
响应:完整 TrainingFileDto(含 scope 回显,结构见 3.1)。
3.6 编辑文件(主路径,含权限)
PUT /api/app/training/{id}/file
{
"fileName": "操作手册.pdf",
"orderNum": 100,
"appliedPartnerType": "SPECIFIED",
"partnerIds": ["3a22e2f5-a785-ba39-9847-de45bdd47e50"],
"companyIds": ["3a22e2f5-a785-ba39-9847-de45bdd47e50"],
"appliedRegionType": "ALL",
"regionIds": ["ALL"],
"groupIds": ["ALL"],
"availabilityType": "SPECIFIED",
"locationIds": ["3a22e2f6-e944-2038-ffd8-fc82d9d388ac"]
}
| 字段 | 说明 |
|---|---|
| fileName | 必填;展示名(不换物理文件) |
| orderNum | 排序 |
| scope 各字段 | 见第 1 节;只要传了任一 scope 字段即整套覆盖;全不传则保持原权限 |
响应:完整 TrainingFileDto。
curl -X PUT "http://127.0.0.1:19002/api/app/training/<fileId>/file" \
-H "Authorization: Bearer <token>" \
-H "__tenant: <tenantId>" \
-H "Content-Type: application/json" \
-d "{\"fileName\":\"学情测评试题.pdf\",\"orderNum\":100,\"appliedPartnerType\":\"ALL\",\"partnerIds\":[\"ALL\"],\"appliedRegionType\":\"ALL\",\"availabilityType\":\"ALL\",\"locationIds\":[\"ALL\"]}"
3.7 删除文件
DELETE /api/app/training/{id}/file
软删除,并清理 scope 关联行。
3.8 文件排序
PUT /api/app/training/sort-files
{
"items": [
{ "id": "23148558702612480", "orderNum": 100 },
{ "id": "23148558702612481", "orderNum": 90 }
]
}
3.9 获取 / 设置文件权限(兼容,非推荐主路径)
| 方法 | 路由 |
|---|---|
| GET | /api/app/training/file-scope/{id} |
| PUT | /api/app/training/file-scope/{id} |
推荐:权限在 上传 / 编辑文件 中一并提交,不必单独调本接口。
本接口与 create/update 共用同一套 scope 保存逻辑;PUT body 与 scope 字段相同(无 fileName)。
GET 响应(TrainingFileScopeOutputDto)
{
"appliedPartnerType": "SPECIFIED",
"company": "成都分店",
"partnerIds": ["3a22e2f5-a785-ba39-9847-de45bdd47e50"],
"companyIds": ["3a22e2f5-a785-ba39-9847-de45bdd47e50"],
"appliedRegionType": "SPECIFIED",
"region": "武侯区",
"regionIds": ["3a22e2f6-0679-9a5b-19b4-fc6db2d92dcc"],
"groupIds": ["3a22e2f6-0679-9a5b-19b4-fc6db2d92dcc"],
"availabilityType": "SPECIFIED",
"location": "分店2",
"locationIds": ["3a22e2f6-e944-2038-ffd8-fc82d9d388ac"]
}
PUT body 示例
{
"appliedPartnerType": "ALL",
"partnerIds": ["ALL"],
"appliedRegionType": "SPECIFIED",
"regionIds": ["3a22e2f6-0679-9a5b-19b4-fc6db2d92dcc"],
"availabilityType": "SPECIFIED",
"locationIds": ["3a22e2f6-e944-2038-ffd8-fc82d9d388ac"]
}
4. APP 接口
4.1 门店可见分类树
GET /api/app/us-app-training/tree
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| locationId | string | 是 | 当前门店 Id;校验用户可访问该门店 |
| keyword | string | 否 | 匹配分类名或文件名 |
按门店过滤文件:Company / Region / Location 三维度 ALL 或 SPECIFIED 命中该门店才可见。
响应结构同管理端分类树(includeFiles=true)。
curl -G "http://127.0.0.1:19002/api/app/us-app-training/tree" \
--data-urlencode "locationId=<locationGuid>" \
-H "Authorization: Bearer <token>" \
-H "__tenant: <tenantId>"
5. TrainingFileDto 字段说明
| 字段 | 说明 |
|---|---|
| id | 文件 Id |
| categoryId | 所属二级分类 |
| fileName / fileUrl / fileType / fileSize | 文件信息 |
| orderNum | 排序 |
| appliedPartnerType | Company:ALL / SPECIFIED |
| company | Company 展示文案 |
| partnerIds / companyIds | Company Id 列表(可含 ALL) |
| appliedRegionType | Region:ALL / SPECIFIED |
| region | Region 展示文案 |
| regionIds / groupIds | Region Id 列表 |
| availabilityType | Location:ALL / SPECIFIED |
| location | Location 展示文案 |
| locationIds | 门店 Id 列表 |
| creationTime / lastModificationTime | 时间 |
6. 联调检查清单
- [ ] 分类仅两级;文件只能挂二级
- [ ] 上传可不传 scope → 默认三维度 ALL
- [ ] 上传/编辑传
ALL或具体多值 Guid → 库表 type 字段 + 关联表正确 - [ ] 分类树
files[]含完整 scope 回显 - [ ]
PUT .../file不传 scope 时不改权限;传了则覆盖 - [ ]
GET/PUT /api/app/training/file-scope/{id}不再 404(兼容路径) - [ ] APP
us-app-training/tree按 locationId 过滤可见文件 - [ ] 文件 ≤20MB、扩展名合法
查库(租户业务库):
SELECT Id, FileName, AppliedPartnerType, AppliedRegionType, AvailabilityType
FROM fl_training_file WHERE IsDeleted = 0;
SELECT * FROM fl_training_file_partner WHERE TrainingFileId = '<fileId>';
SELECT * FROM fl_training_file_region WHERE TrainingFileId = '<fileId>';
SELECT * FROM fl_training_file_location WHERE TrainingFileId = '<fileId>';
7. 相关代码
| 说明 | 路径 |
|---|---|
| 管理端服务 | FoodLabeling.Application/Services/TrainingAppService.cs |
| APP 服务 | FoodLabeling.Application/Services/UsAppTrainingAppService.cs |
| Scope 辅助 | FoodLabeling.Application/Helpers/TrainingFileScopeHelper.cs |
| 建表脚本 | module/food-labeling-us/scripts/fl_training.sql |
8. 变更记录
| 日期 | 说明 |
|---|---|
| 2026-08-07 | 重写文档:权限并入上传/编辑;file-scope 改为兼容路径;补全 TrainingFileDto scope 回显与 curl 示例 |
| (历史) | 初版:分类树、文件 CRUD、独立 file-scope、APP tree |