2026-07-09 代码修改
本文档说明 2026-07-09 对美国版标签(Label)模块的接口补充:标签列表与批量导入(Bulk Add Labels)。
一、背景与目标
| 项目 |
说明 |
| 业务场景 |
Web 管理端 Bulk Add Labels 页面:同一模板下多行录入标签基本字段 + 模板数据字段后一次性保存 |
| 原行为 |
前端 LabelsList.tsx 对每行循环调用 POST /api/app/label 单条创建,模板数据再单独 updateLabelTemplate |
| 新行为 |
新增 POST /api/app/label/batch-create,一次提交多行;可选合并写入 fl_label_template_product_default |
| 列表接口 |
GET /api/app/label?SkipCount=1&MaxResultCount=10 为标签分页列表(按标签维度分页,非 label-product 笛卡尔行) |
二、标签列表
基本信息
| 项目 |
内容 |
| 方法 |
GET |
| 路径 |
/api/app/label |
| 鉴权 |
Bearer Token |
| 示例 |
/api/app/label?SkipCount=1&MaxResultCount=10 |
分页参数
| 参数 |
类型 |
说明 |
SkipCount |
int |
页码,从 1 起(非 0) |
MaxResultCount |
int |
每页条数 |
筛选参数(Query)
| 参数 |
说明 |
PartnerId |
按 Company(fl_partner.Id)下门店集合筛选 |
GroupId |
按 Region(fl_group.Id)筛选:命中 fl_label_region、fl_label_location 或 AppliedRegionType=ALL |
LocationId |
按门店(location.Id)筛选;传则优先于 GroupId |
ProductId |
按产品筛选(一个产品可对应多个标签) |
Keyword |
关键词 |
LabelCategoryId |
标签分类 |
LabelTypeId |
标签类型(可选) |
TemplateCode |
模板编码 |
State |
启用状态 |
出参结构
{
"pageIndex": 1,
"pageSize": 10,
"totalCount": 100,
"totalPages": 10,
"items": [
{
"id": "LBL_xxx",
"labelName": "Turkey Breast",
"locationName": "Store A, Store B",
"locationIds": ["loc-id-1", "loc-id-2"],
"region": "Region A",
"regionIds": ["group-id-1"],
"groupIds": ["group-id-1"],
"appliedRegionType": "SPECIFIED",
"labelCategoryName": "Prep",
"productCategoryName": "Meat",
"products": "Turkey Breast",
"templateName": "3\"x6\" Nutrition Details",
"templateCode": "tpl_229mx5_mr05n3cq",
"labelTypeName": "Use By",
"state": true,
"lastEdited": "2026-07-09T10:00:00",
"hasError": false
}
]
}
列表 curl 示例
# 登录(管理端)
curl -X POST "http://192.168.31.88:19001/api/app/account/login" \
-H "Content-Type: application/json" \
-d '{"userName":"sandi@123.com","password":"123456"}'
# 标签列表第一页(10 条)
curl -G "http://192.168.31.88:19001/api/app/label" \
-H "Authorization: Bearer {token}" \
--data-urlencode "SkipCount=1" \
--data-urlencode "MaxResultCount=10"
三、标签批量导入
基本信息
| 项目 |
内容 |
| 方法 |
POST |
| 路径 |
/api/app/label/batch-create |
| 鉴权 |
Bearer Token |
| 对应页面 |
Web 端 Bulk Add Labels(LabelsList.tsx → LabelBulkAddPage) |
| 单次上限 |
500 行 |
Body 顶层字段
| 字段 |
类型 |
必填 |
说明 |
templateCode |
string |
是 |
所有行共用的模板编码 |
items |
array |
是 |
导入行列表 |
saveTemplateProductDefaults |
bool |
否 |
是否合并写入模板 ProductDefaults,默认 true |
items[] 每行字段
标签基本字段(与单条 POST /api/app/label 一致)
| 字段 |
类型 |
必填 |
说明 |
labelName |
string |
是 |
标签名称 |
labelCategoryId |
string |
是 |
标签分类 Id |
labelTypeId |
string |
建议 |
标签类型 Id |
productIds |
string[] |
是 |
至少 1 个产品 |
locationIds |
string[] |
建议 |
适用门店(主字段) |
locationId |
string |
否 |
兼容单门店,与 locationIds 合并 |
appliedRegionType |
string |
否 |
ALL / SPECIFIED |
regionIds / groupIds |
string[] |
条件 |
SPECIFIED 时传 Region |
partnerId / partnerIds |
string / string[] |
否 |
Company 范围 |
labelCode |
string |
否 |
不传则自动生成 LBL_{guid} |
labelInfoJson |
object |
否 |
标签级模板 JSON(通常走 ProductDefaults) |
state |
bool |
否 |
默认 true |
模板数据字段(对应 Bulk Add 表格列)
| 字段 |
类型 |
说明 |
templateDefaultValues |
object |
已组装的 elementId → 值;优先使用,不再从下方字段推导 |
templateDataValues |
object |
文本类录入(如 Text、Barcode 手填值) |
templateDateOffsets |
object |
日期/时间/时长:{ "el-id": { "unit": "Days", "value": "3" } } |
nutritionByElementId |
object |
营养成分:{ "el-nutrition": { "calories": "120" } } |
模板数据落库规则
saveTemplateProductDefaults=true 时:按 productId + labelTypeId 合并写入 fl_label_template_product_default(与前端 saveTemplateDefaultsAfterLabels 一致)
- 日期偏移存为 JSON 字符串:
{"unit":"Days","value":"3"}
- Template 面板条码/二维码自动填充产品
codeValue;Label Name / Label Type 自动绑定行内 labelName、类型名
请求示例
{
"templateCode": "tpl_229mx5_mr05n3cq",
"saveTemplateProductDefaults": true,
"items": [
{
"labelName": "Chicken Salad",
"labelCategoryId": "3a2228ca-42fa-5273-1105-3d8252ffdd99",
"labelTypeId": "3a2228e5-33c5-278e-a09f-47fd6e2ddbc7",
"locationIds": ["3a222878-b4c1-d27b-d437-93da14886350"],
"productIds": ["3a2228a8-6a51-6cc4-fee2-b77769766b33"],
"appliedRegionType": "SPECIFIED",
"regionIds": [],
"templateDataValues": {
"el-1782794752668-0gixa9y": "Fresh batch text",
"el-1782794771519-4360c0p": "123456789"
},
"templateDateOffsets": {
"el-1782794481721-sdf7mvy": { "unit": "Days", "value": "3" }
},
"state": true
},
{
"labelName": "Turkey Wrap",
"labelCategoryId": "3a2228ca-42fa-5273-1105-3d8252ffdd99",
"labelTypeId": "3a2228e6-3ed0-b056-a08b-ea8b1eea46a0",
"locationIds": ["3a222878-b4c1-d27b-d437-93da14886350"],
"productIds": ["3a2228a8-6a51-6cc4-fee2-b77769766b33"],
"templateDataValues": {
"el-1782794752668-0gixa9y": "Ready to serve"
},
"templateDateOffsets": {
"el-1782794481721-sdf7mvy": { "unit": "Days", "value": "5" }
}
}
]
}
响应示例
{
"successCount": 2,
"failCount": 0,
"successItems": [
{ "rowNumber": 1, "labelCode": "LBL_abc...", "labelName": "Chicken Salad" },
{ "rowNumber": 2, "labelCode": "LBL_def...", "labelName": "Turkey Wrap" }
],
"errors": []
}
部分成功示例(第 2 行校验失败、第 1 行仍创建):
{
"successCount": 1,
"failCount": 1,
"successItems": [
{ "rowNumber": 1, "labelCode": "LBL_abc...", "labelName": "Chicken Salad" }
],
"errors": [
{ "rowNumber": 2, "labelName": "", "message": "标签名称不能为空" }
]
}
批量导入 curl 示例
curl -X POST "http://192.168.31.88:19001/api/app/label/batch-create" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"templateCode": "tpl_229mx5_mr05n3cq",
"saveTemplateProductDefaults": true,
"items": [
{
"labelName": "Batch Test",
"labelCategoryId": "3a2228ca-42fa-5273-1105-3d8252ffdd99",
"labelTypeId": "3a2228e5-33c5-278e-a09f-47fd6e2ddbc7",
"locationIds": ["3a222878-b4c1-d27b-d437-93da14886350"],
"productIds": ["3a2228a8-6a51-6cc4-fee2-b77769766b33"],
"templateDataValues": { "el-1782794752668-0gixa9y": "Fresh" },
"templateDateOffsets": { "el-1782794481721-sdf7mvy": { "unit": "Days", "value": "3" } }
}
]
}'
四、与单条创建对比
| 能力 |
POST /api/app/label |
POST /api/app/label/batch-create |
| 行数 |
1 条 |
最多 500 条 |
| 模板编码 |
每 Body 自带 |
顶层 templateCode 共用 |
| 模板数据 |
仅 labelInfoJson |
支持结构化模板字段 + ProductDefaults 合并 |
| 失败处理 |
整请求失败 |
行级错误收集,支持部分成功 |
| 返回值 |
标签详情 DTO |
successCount / failCount / errors / successItems |
五、代码改动摘要
| 文件 |
改动 |
ILabelAppService.cs |
新增 BatchCreateAsync |
LabelAppService.cs |
实现批量导入;逐行复用 CreateAsync;可选合并模板 ProductDefaults |
LabelBatchCreateInputVo.cs |
批量入参 DTO |
LabelBatchCreateItemInputVo.cs |
单行(基本字段 + 模板数据字段) |
LabelBatchDateOffsetInputVo.cs |
日期偏移单位+数值 |
LabelBatchCreateResultDto.cs |
批量结果 DTO |
LabelBatchTemplateDefaultsHelper.cs |
组装/合并模板 ProductDefaults |
六、部署与联调注意
dotnet build 编译 FoodLabeling.Application 与 Yi.Abp.Web 后重启 API 进程(未重启时 batch-create 会返回 405)
- 管理端登录:
POST /api/app/account/login(非 /api/oauth/Login)
- 本地 Base URL 以
appsettings.json 中 App:SelfUrl 为准(当前示例为 http://192.168.31.88:19001)
- 前端
LabelsList.tsx 的 submit() 仍循环调单条 createLabel;对接批量接口时需改为调用 batch-create
七、相关文档
- 标签多门店
locationIds:项目相关文档/6-23代码优化.md
- 模板三维 scope:
项目相关文档/6-4代码优化.md