# 6-4 代码优化 本文档说明 **2026-06-04** 对美国版 **`/api/app/label-template`** 新增/编辑接口的 **Company / Region / Location** 三维适用范围改造。 --- ## 背景 标签模板除画布与控件外,需按 **Company(Partner)**、**Region(Group)**、**Location(门店)** 三个维度配置可见范围: - 各维度支持 **全选(ALL)** 或 **指定(SPECIFIED + Id 数组)** - 支持 **单选 / 多选** - 新增与编辑使用同一套 Body 字段 测试环境基址:`http://flus-test.3ffoodsafety.com` --- ## 接口一览 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/app/label-template` | 分页列表(含 `company` / `region` / `location` 展示与 Id 数组) | | GET | `/api/app/label-template/{templateCode}` | 详情 | | POST | `/api/app/label-template` | 新增 | | PUT | `/api/app/label-template/{templateCode}` | 编辑(版本号 +1,全量重建 elements) | | DELETE | `/api/app/label-template/{templateCode}` | 逻辑删除 | --- ## 适用范围字段(POST / PUT Body) 三个维度 **相互独立**,列表/详情筛选时按 **AND** 组合(某维度为 ALL 表示该维度不限制)。 | 字段 | 类型 | 说明 | |------|------|------| | `appliedPartnerType` | `ALL` \| `SPECIFIED` | 适用 **Company**;默认 `ALL` | | `partnerIds` | `string[]` | Company Id(`fl_partner.Id`);与 `companyIds` 合并去重 | | `companyIds` | `string[]` | 与 `partnerIds` 相同(兼容别名) | | `appliedRegionType` | `ALL` \| `SPECIFIED` | 适用 **Region**;默认 `ALL` | | `regionIds` | `string[]` | Region Id(`fl_group.Id`);与 `groupIds` 合并去重 | | `groupIds` | `string[]` | 与 `regionIds` 相同(兼容别名) | | `appliedLocation` | `ALL` \| `SPECIFIED` | 适用 **Location**(与历史字段一致);默认 `ALL` | | `locationIds` | `string[]` | 门店 Id(`location.Id`) | | `appliedLocationIds` | `string[]` | 与 `locationIds` 合并去重(兼容旧前端) | ### 解析规则 1. 某维度 Id 数组 **非空** → 该维度自动视为 `SPECIFIED`(即使未传 `applied*Type`)。 2. 传了空数组 `[]` 且对应 `applied*Type=ALL` → 该维度 **全选**。 3. `applied*Type=SPECIFIED` 且对应 Id 数组为空 → 返回 **400** 友好错误。 4. 任一维度为 `SPECIFIED` 时,合并后的有效门店集合不能为空(至少匹配到一个门店)。 ### 示例 **全选(默认,三维度均 ALL)** ```json { "id": "tpl-price-001", "name": "Price Label", "labelType": "PRICE", "unit": "inch", "width": 4, "height": 2, "appliedPartnerType": "ALL", "appliedRegionType": "ALL", "appliedLocation": "ALL", "partnerIds": [], "regionIds": [], "locationIds": [], "elements": [] } ``` **指定 Company + Region 多选** ```json { "appliedPartnerType": "SPECIFIED", "partnerIds": ["1234567890123456789"], "appliedRegionType": "SPECIFIED", "regionIds": ["9876543210987654321", "9876543210987654322"], "appliedLocation": "ALL", "locationIds": [] } ``` **仅指定门店多选** ```json { "appliedPartnerType": "ALL", "appliedRegionType": "ALL", "appliedLocation": "SPECIFIED", "locationIds": ["550e8400-e29b-41d4-a716-446655440000"] } ``` --- ## 出参(详情 GET / 列表 Items) 除原有 `templateCode`、`elements`、`items` 等外,增加: | 字段 | 说明 | |------|------| | `company` | 展示文案:`All Companies` 或 Partner 名称逗号拼接 | | `region` | `All Regions` 或 Region 名称拼接 | | `location` | `All Locations` 或门店名称拼接 | | `appliedPartnerType` / `appliedRegionType` / `appliedLocationType` | 各维度类型 | | `partnerIds` / `companyIds` | Company Id 数组(ALL 时 `[]`) | | `regionIds` / `groupIds` | Region Id 数组 | | `locationIds` / `appliedLocationIds` | 门店 Id 数组 | --- ## 数据库存储 **DDL 脚本(可重复执行)**: `美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/fl_label_template_scope.sql` | 位置 | 说明 | |------|------| | `fl_label_template.AppliedPartnerType` | Company:`ALL` / `SPECIFIED` | | `fl_label_template.AppliedRegionType` | Region:`ALL` / `SPECIFIED` | | `fl_label_template.AppliedLocationType` | Location:`ALL` / `SPECIFIED`(原有列,语义收窄为 Location 维度) | | `fl_label_template_partner` | `TemplateId` + `PartnerId` 多选明细 | | `fl_label_template_region` | `TemplateId` + `GroupId` 多选明细 | | `fl_label_template_location` | `TemplateId` + `LocationId`(仅 Location 维度 SPECIFIED 时写入) | > **部署注意**:测试/生产库须先执行 DDL,再部署含本改动的后端,否则写入新字段可能失败。 ### 兼容旧数据 - 历史仅配置 `AppliedLocationType=SPECIFIED` + `fl_label_template_location` 的模板:Partner/Region 默认为 `ALL`,Location 仍按 junction 表回读。 - 列表权限筛选:三维度 AND;旧「仅门店 junction」数据行为保持不变。 --- ## 列表筛选 `GET /api/app/label-template` 仍支持 Query: - `groupId`(Region) - `locationId`(门店) 按当前用户 Token 可见门店范围过滤模板(与 Team Member / Label 列表一致)。 --- ## 涉及代码文件 | 层级 | 文件 | |------|------| | DDL | `scripts/fl_label_template_scope.sql` | | Helper | `Helpers/LabelTemplateScopeHelper.cs` | | 实体 | `FlLabelTemplateDbEntity.cs`、`FlLabelTemplatePartnerDbEntity.cs`、`FlLabelTemplateRegionDbEntity.cs` | | DTO | `LabelTemplateCreateInputVo.cs`、`LabelTemplateGetOutputDto.cs`、`LabelTemplateGetListOutputDto.cs` | | 服务 | `LabelTemplateAppService.cs` | | 前端类型 | `src/types/labelTemplate.ts`(`buildLabelTemplateScopePayload`) | | 前端 API | `src/services/labelTemplateService.ts` | | 前端页面 | `LabelTemplatesView.tsx`、`LabelTemplateEditor/index.tsx` | --- ## 验证步骤 1. 在目标库执行 `fl_label_template_scope.sql`。 2. 部署后端并重启。 3. **POST** 创建模板:`appliedRegionType=SPECIFIED` + `regionIds`,详情应回显 `regionIds` 与 `region` 文案。 4. **PUT** 编辑为全选:三维度 `ALL` + 空数组,junction 表对应记录应清空。 5. **GET** 列表:新列 `company` / `region` / `location` 与 Id 数组一致。 6. 库内抽查: ```sql SELECT AppliedPartnerType, AppliedRegionType, AppliedLocationType FROM fl_label_template WHERE TemplateCode = '你的模板编码'; SELECT * FROM fl_label_template_partner WHERE TemplateId = ( SELECT Id FROM fl_label_template WHERE TemplateCode = '你的模板编码' LIMIT 1 ); ``` --- ## curl 示例(需先登录取 Token) ```bash # 新增:指定 Region curl -X POST "http://flus-test.3ffoodsafety.com/api/app/label-template" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "id": "test-scope-tpl", "name": "Scope Test", "labelType": "PRICE", "unit": "inch", "width": 4, "height": 2, "appliedRegionType": "SPECIFIED", "regionIds": ["{fl_group.Id}"], "appliedPartnerType": "ALL", "appliedLocation": "ALL", "elements": [] }' ```