# 6-26 代码优化 本文档说明 **2026-06-26** 对美国版标签模板 `contents` 字段的**数据来源澄清**与**编辑不生效**修复。 --- ## 一、问题现象 | 项目 | 说明 | |------|------| | 接口 | `GET/PUT /api/app/label-template/{id}`(如 `tpl_c23gov_mqri4g5a`) | | 期望 | `contents` = `"Nutrition Facts, Text (For Template)"`(模板列表 Contents 列展示) | | 实际 | 返回/展示 `"nutritionfacts, text"` | | 用户反馈 | 在编辑器修改 Element name 后保存,列表 Contents **没有变化** | --- ## 二、`contents` 取自哪个字段? ### 结论(优先级) | 优先级 | 来源 | 字段 | 说明 | |--------|------|------|------| | 1 | 编辑器右侧 **Element name** | `elements[].elementName` | 用户可编辑;保存时写入 `fl_label_template_element.ElementName` | | 2 | 旧数据兼容(slug) | `elements[].typeAdd` | 当 `elementName` 为旧 slug(如 `nutritionfacts`、`text`)时,按 typeAdd 推导展示名 | | 3 | 持久化缓存 | `fl_label_template.Contents` | 保存时写入;**列表以 element 实时汇总为准**,避免旧缓存覆盖新编辑 | ### typeAdd 推导规则 `typeAdd` 形如 `{分组前缀}_{面板控件英文名}`: | typeAdd 示例 | 推导展示名 | |--------------|------------| | `label_Nutrition Facts` | `Nutrition Facts (For Label)` | | `template_Text` | `Text (For Template)` | | `auto_Company` | `Company (Entered Automatically)` | | `print_Multiple Options` | `Multiple Options (Entered When Printing)` | **拼接格式**:`{控件面板名称} ({分组标题})` 分组标题与左侧 Elements 面板一致:`For Template` / `For Label` / `Entered Automatically` / `Entered When Printing`。 ### 与 elementName 的关系 | 场景 | elementName 示例 | contents 单项 | |------|------------------|---------------| | 新拖入控件(修复后) | `Text (For Template)` | `Text (For Template)` | | 旧模板 slug | `text` | `Text (For Template)`(由 typeAdd 推导) | | 用户手动改 Element name | `My Custom Field` | `My Custom Field`(以用户输入为准) | **注意**:`elementName` 同时用于录入表表头;`contents` 是各控件展示名的逗号拼接,**不是** slug 字段。 --- ## 三、根因说明 1. **新建控件时** `allocateElementName` 把 Element name 默认成 slug(`nutritionfacts`),与 UI 期望的「Nutrition Facts (For Label)」不一致。 2. **列表 contents** 曾优先读 `fl_label_template.Contents` 缓存,保存后 element 已变但缓存仍是旧 slug 串。 3. **列表回退逻辑** 直接读 `ElementName` 原文,slug 原样展示为 `nutritionfacts, text`。 --- ## 四、修复内容 ### 后端 | 文件 | 改动 | |------|------| | `LabelTemplateContentsHelper.cs` | `ResolveElementContentsLabel`:Element name 优先;slug 则 typeAdd 推导 | | `LabelTemplateContentsHelper.cs` | `ResolveContentsMapFromElementsAsync`:列表按 element 表**实时**汇总 | | `LabelTemplateListItemsHelper.cs` | `items` / `itemNames` 与 contents 使用同一套展示名逻辑 | | `LabelTemplateAppService.cs` | 列表/详情 **优先** element 汇总 contents;保存仍写入 `Contents` 列(若已迁移) | ### 前端 | 文件 | 改动 | |------|------| | `labelTemplate.ts` | 新增 `allocateElementDisplayName`、`resolveElementContentsLabel`、`deriveContentsLabelFromTypeAdd` | | `LabelTemplateEditor/index.tsx` | 新控件默认 Element name = `控件名 (For Template/For Label…)` | | `LabelTemplateEditor/index.tsx` | 保存时 `contents: buildTemplateContentsFromElements(elements)` | --- ## 五、接口说明 ### 1. 模板详情 | 项目 | 内容 | |------|------| | 方法 | `GET` | | 路径 | `/api/app/label-template/{id}` | | 示例 | `/api/app/label-template/tpl_c23gov_mqri4g5a` | **出参(节选)** ```json { "id": "tpl_c23gov_mqri4g5a", "templateName": "Unnamed template", "contents": "Nutrition Facts (For Label), Text (For Template)", "elements": [ { "elementName": "nutritionfacts", "typeAdd": "label_Nutrition Facts", "type": "NUTRITIONFACTS" }, { "elementName": "text", "typeAdd": "template_Text", "type": "TEXT_STATIC" } ] } ``` > 旧 slug 的 `elementName` 可保留;`contents` 按 typeAdd 展示。保存后新模板会直接写入展示型 Element name。 ### 2. 模板列表 | 项目 | 内容 | |------|------| | 方法 | `GET` | | 路径 | `/api/app/label-template` | | 参数 | `SkipCount=1&MaxResultCount=10` | **出参 `items[]`** | 字段 | 说明 | |------|------| | `contents` | Contents 列文案,与详情一致 | | `items` | 兼容字段,与 `contents` 相同 | | `contentsCount` | 控件数量 | ### 3. 新建 / 编辑 | 方法 | 路径 | |------|------| | `POST` | `/api/app/label-template` | | `PUT` | `/api/app/label-template/{id}` | **Body 节选** ```json { "id": "tpl_c23gov_mqri4g5a", "name": "Unnamed template", "contents": "Nutrition Facts (For Label), Text (For Template)", "elements": [ { "id": "el_1", "elementName": "Nutrition Facts (For Label)", "typeAdd": "label_Nutrition Facts", "type": "NUTRITIONFACTS", "orderNum": 1 }, { "id": "el_2", "elementName": "Text (For Template)", "typeAdd": "template_Text", "type": "TEXT_STATIC", "orderNum": 2 } ] } ``` | 字段 | 说明 | |------|------| | `contents` | 可选;不传则后端按 `elements` 推导 | | `elements[].elementName` | **主数据源**(Element name) | | `elements[].typeAdd` | slug 兼容推导用 | --- ## 六、部署与验证 1. 重新编译并重启 `Yi.Abp.Web` 2. (可选)执行 `scripts/fl_label_template_contents.sql` 持久化 `Contents` 列 3. 打开 `tpl_c23gov_mqri4g5a` 保存一次 → GET 详情/列表 `contents` 应为展示名,而非 `nutritionfacts, text` 4. 修改 Element name 后再保存 → 列表 Contents **立即**更新(不再被旧 `Contents` 缓存挡住) **curl 示例** ```bash curl -s "http://localhost:5000/api/app/label-template/tpl_c23gov_mqri4g5a" \ -H "Authorization: Bearer " ``` --- ## 七、与 6-25 文档关系 - **6-25**:引入 `contents` 字段、DB 迁移、未迁移列兼容 - **6-26**:明确字段来源(Element name + typeAdd 推导)、修复 slug/缓存导致的展示与编辑不生效问题