6-25代码优化.md 8.28 KB

6-25 代码优化

本文档说明 2026-06-25 对美国版标签模板(Label Template)接口的 contents 字段改造:新建/编辑时持久化模板内各控件的 elementName,列表与详情接口返回该字段,供前端 Contents 列展示。


一、背景与目标

项目 说明
原行为 列表 Contents 列依赖实时查询 fl_label_template_element 汇总控件名(items / itemNames
新行为 新增 contents 字段,落库 fl_label_template.Contents;保存时写入,列表/详情直接返回
控件名来源 编辑器右侧 Element name(对应 elements[].elementName),按 orderNum 排序、去重后逗号拼接
兼容 未传 contents 时后端按 elements 自动推导;库内 Contents 为空时列表回退 element 汇总

示例:模板含控件 labelnametextcontents = "labelname, text"


二、数据库迁移

脚本路径:美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/fl_label_template_contents.sql

步骤 内容
1 fl_label_template 增加列 Contents varchar(2000) NULL
2 fl_label_template_element.ElementName 回填已有模板

执行前请备份数据库。


二点五、列表 500:Unknown column 'Contents'

项目 说明
现象 GET /api/app/label-template?SkipCount=1&MaxResultCount=10Unknown column 'Contents' in 'field list'
原因 代码已支持 contents,但库表尚未执行 fl_label_template_contents.sql,ORM 主查询 SELECT 了不存在的列
修复 Contents 不参与 SqlSugar 列投影(实体 IsIgnore);读写经 LabelTemplateScopeSchemaHelper 探测列是否存在
未迁移时 列表/详情 contents 回退fl_label_template_element 汇总(items / itemNames 逻辑),接口可正常 200
已迁移时 保存写入 fl_label_template.Contents;列表优先读库内 contents,空时再回退 element 汇总

仍需执行迁移:若要在保存后持久化 contents(不依赖每次查 element 表),请执行 fl_label_template_contents.sql 并重启服务。


三、contents 字段规范

入参(POST / PUT)

字段 类型 必填 说明
contents string 控件名称逗号拼接,如 "labelname, text"
elements array 是(保存时) 全量重建;未传 contents 时由后端从 elements[].elementName 推导

推导规则(LabelTemplateContentsHelper.ResolveForSave

  1. 入参 contents 非空 → 原样 trim 后落库
  2. 否则按 elementsorderNum 升序、id 次序排序
  3. 取非空 elementName大小写不敏感去重
  4. ", " 拼接(英文逗号 + 空格)

出参(GET 列表 / 详情)

字段 类型 说明
contents string 持久化控件名列表;空时详情回退 elements 推导
contentsCount number 仅列表:elements 数量
items string 兼容:与 contents 同值(列表)
itemNames string[] 兼容:展示名数组(仍来自 element 表汇总,可能与 contents 文案略有差异)

四、接口说明

1. 模板列表

项目 内容
方法 GET
路径 /api/app/label-template
鉴权 Bearer Token

Query / data 参数(节选)

参数 说明
SkipCount 页码,从 1 起
MaxResultCount 每页条数
Keyword 模板名称/编码模糊搜索
PartnerId / GroupId / LocationId 适用范围筛选
State 启用状态

出参 items[] 相关字段

字段 示例 说明
id tpl_c23gov_mqri4g5a templateCode
templateName Unnamed template 模板名称
contents labelname, text Contents 列展示
contentsCount 2 控件数量
items labelname, text 兼容字段
sizeText 6.00x4.00cm 尺寸展示
location All Locations 适用门店

curl 示例

curl -s -G "http://localhost:5000/api/app/label-template" \
  -H "Authorization: Bearer <TOKEN>" \
  --data-urlencode "SkipCount=1" \
  --data-urlencode "MaxResultCount=10"

2. 模板详情

项目 内容
方法 GET
路径 /api/app/label-template/{id}
路径参数 id = templateCode,如 tpl_c23gov_mqri4g5a

出参新增

字段 说明
contents 持久化控件名;库内为空时由当前 elements 推导
elements 控件明细(含 elementName

curl 示例

curl -s "http://localhost:5000/api/app/label-template/tpl_c23gov_mqri4g5a" \
  -H "Authorization: Bearer <TOKEN>"

3. 新建模板

项目 内容
方法 POST
路径 /api/app/label-template
Content-Type application/json

Body 节选

{
  "id": "tpl_new_example",
  "name": "Unnamed template",
  "unit": "cm",
  "width": 6,
  "height": 4,
  "printOrientation": "vertical",
  "contents": "labelname, text",
  "elements": [
    {
      "id": "el_1",
      "elementName": "labelname",
      "type": "TEXT_PRODUCT",
      "orderNum": 1,
      "x": 0.5,
      "y": 0.5,
      "width": 2,
      "height": 0.8
    },
    {
      "id": "el_2",
      "elementName": "text",
      "type": "TEXT_STATIC",
      "orderNum": 2,
      "x": 0.5,
      "y": 1.5,
      "width": 3,
      "height": 1
    }
  ]
}

4. 编辑模板

项目 内容
方法 PUT
路径 /api/app/label-template/{id}
说明 与 POST 相同 Body 结构;elements 全量重建;contents 随保存更新

curl 示例

curl -s -X PUT "http://localhost:5000/api/app/label-template/tpl_c23gov_mqri4g5a" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d "{\"id\":\"tpl_c23gov_mqri4g5a\",\"name\":\"Unnamed template\",\"unit\":\"cm\",\"width\":6,\"height\":4,\"printOrientation\":\"vertical\",\"contents\":\"labelname, text\",\"elements\":[...]}"

五、前端改动

文件 改动
LabelTemplateEditor/index.tsx 保存时提交 contents: buildTemplateContentsFromElements(elements)
labelTemplateService.ts 列表归一化优先读取 contents
LabelTemplatesView.tsx Contents 列优先展示 contents / contentsText
types/labelTemplate.ts 新增 buildTemplateContentsFromElements

六、后端改动摘要

文件 改动
FlLabelTemplateDbEntity.cs Contents 为内存字段(IsIgnore),避免未迁移时 ORM SELECT/INSERT 报错
LabelTemplateScopeSchemaHelper.cs 探测 HasContentsColumnGetContentsMapAsync / SetContentsAsync
LabelTemplateCreateInputVo.cs 入参 contents
LabelTemplateGetListOutputDto.cs / LabelTemplateGetOutputDto.cs 出参 contents
LabelTemplateContentsHelper.cs 推导与保存解析
LabelTemplateAppService.cs Create/Update 条件落库;List/Get 条件读取 + element 回退
LabelTemplateQueryHelper.cs 列表投影不含 Contents(与 scope/border 列策略一致)

七、部署与验证

  1. 重新编译并重启 Yi.Abp.Web(未迁移 Contents 列时列表亦应 200,contents 来自 element 汇总)
  2. (推荐)执行 fl_label_template_contents.sql,使保存后的 contents 持久化到主表
  3. 编辑模板 tpl_c23gov_mqri4g5a 保存后,GET 列表应返回 "contents": "labelname, text"(与编辑器 Element name 一致)
  4. 模板列表 Contents 列应显示相同文案

八、注意事项

  • elementName 为必填(保存校验「组件名字不能为空」),与 contents 中各项一一对应
  • contents 存的是 elementName 原文(如 labelname),不是面板展示标签(如 Label Name
  • itemNames 仍保留旧汇总逻辑,新 UI 请以 contents 为准
  • 未执行 SQL 迁移:接口可用,但 contents 不落主表,每次列表从 element 表实时汇总;执行迁移后保存才会写入 fl_label_template.Contents