2026-07-27代码优化.md 13 KB

2026-07-27 代码优化

product-category 新增 Company 适用范围(companyIds)

背景

产品分类(Product Category)与标签分类(Label Category)对齐,新增/编辑/详情/列表支持 Company 多选 传参与 ALL 哨兵 回显。

涉及接口

方法 路径
GET /api/app/product-category/{id}
GET /api/app/product-category(列表 items[] 同步)
POST /api/app/product-category
PUT /api/app/product-category/{id}

示例详情:GET /api/app/product-category/3a22b3d6-897d-d89a-e263-b30761fe48be

新增入参字段(POST / PUT)

字段 类型 说明
appliedPartnerType string 适用 Company:ALL / SPECIFIED
partnerIds string[] Company Id(fl_partner.Id);与 companyIds 合并去重
companyIds string[] partnerIds 相同(推荐前端使用本字段)

原有 availabilityTyperegionIds / groupIdslocationIds 规则不变,仍支持 ["ALL"] 哨兵。

新增出参字段(GET 详情 / 列表)

字段 类型 说明
appliedPartnerType string ALL / SPECIFIED
company string 展示文案:All Companies 或公司名称逗号拼接
partnerIds string[] Company Id 数组
companyIds string[] partnerIds 相同

ALL 哨兵约定(与 Team Member / Label Category 一致)

入参 保存行为
companyIds: ["ALL"]appliedPartnerType: "ALL" 主表 AppliedPartnerType=ALL,不写 fl_product_category_partner 快照
appliedPartnerType: "SPECIFIED" + 具体 Guid 写入 fl_product_category_partner 每 Company 一行
appliedPartnerType: "SPECIFIED" + companyIds: ["ALL"] 识别为全选,归档 AppliedPartnerType=ALL
勾选当前全部 Company(传全量 Guid) 归档 ALL,编辑回显 companyIds: ["ALL"]
出参折叠 条件
companyIds: ["ALL"] AppliedPartnerType=ALL,或绑定覆盖系统全部 Company
regionIds / locationIds: ["ALL"] 见下方「范围内 ALL」规则

说明:Company 为 ALL 时 Region/Location 可为 ALL;Company 为 SPECIFIED 且 Region/Location 全选时,companyIds 仍保留具体 Company Guid(与 Label Category 一致)。

范围内 ALL(2026-07-27 修复)

编辑/新增若已指定具体 companyIds/partnerIds 或具体 groupIds/regionIds,再传 locationIds: ["ALL"](或仅 Region=ALL):

入参 落库 回显
具体 Company + 具体 Region + locationIds:["ALL"] AvailabilityType=SPECIFIED,展开该 Region(且属该 Company)下门店快照 Region 仍为具体 Id;Location 可折叠为 ["ALL"]
具体 Company + locationIds:["ALL"](无具体 Region) SPECIFIED,展开该公司全部门店 Location/Region 按覆盖全集折叠
无具体 Company 且无具体 Region + Location/Region ALL 仍为全局 AvailabilityType=ALL(不写门店快照) Region/Location 均为 ["ALL"]

修复前问题:具体 Company + Region + locationIds:["ALL"] 被误归档为全局 AvailabilityType=ALL,列表 Region/Location 都显示 All。

具体 locationIds 被 Region 并集冲掉(2026-07-27 再修)

前端编辑时常同时传 groupIds/regionIds(当前 Region)+ locationIds(用户勾选的门店)。旧逻辑 MergeToLocationIdsAsync(Region ∪ Location) 会把「只选 1 个门店」扩成整 Region,回显再折成 locationIds:["ALL"]

入参 修复后落库
具体 locationIds: ["{loc}"](可同传 Region) 只绑该门店AvailabilityType=SPECIFIED,回显仍为该 Guid
仅具体 Region、无具体 Location 仍按 Region 展开门店
具体 Location 覆盖 Company 下全部门店 仍可归档为全局 AvailabilityType=ALL

locationIds:["ALL"] 回显未折成 ALL(2026-07-27 再修)

落库仍为 AvailabilityType=SPECIFIED + 区内门店快照(正确);但回显用 ResolveAllLocationIdsAsync(Company, Region) 时旧实现是 Company∪Region 并集,用「公司全部门店」去比,导致区内全选无法折叠为 locationIds:["ALL"],列表 Location 也不显示 All。

修复:同时传 Company + Region 时改为交集。再编:具体 Company + Region + locationIds:["ALL"] → 回显 locationIds:["ALL"]regionIds 仍为具体 Region。

label-category / label-type / label-multiple-option 范围内 ALL(2026-07-27)

与 product-category 对齐:具体 Company + Region + locationIds:["ALL"] 不再误归档全局 AvailabilityType=ALL,改为展开区内门店快照(SPECIFIED),回显 locationIds 可折回 ["ALL"]

共用:LocationScopeBindingHelper.ExpandScopedAllLocationsForSaveAsync

team-member 范围内 ALL(2026-07-27)

入参 旧行为 新行为
具体 Company + 具体 Region + locationIds/locations:["ALL"] 忽略 Region,展开整公司门店 展开该 Region(且属该公司)下门店
回显 非整公司时 locationIds 无法折成 ALL 区内全选时 locationIds:["ALL"]regionIds 仍为具体 Region

Region=ALL + 单个 locationId(2026-07-27 再修)

入参示例:regionIds/groupIds:["ALL"] + locationIds:["{单店Guid}"]

旧问题 修复
无 Region 维度字段,Region=ALL 无法落库;回显只能从门店反推具体 Region 新增 AppliedRegionType(对齐 Label)
单店落库后 Region 回显不成 ALL AppliedRegionType=ALL + AvailabilityType=SPECIFIED + 门店快照

DDL:执行 美国版/.../scripts/fl_entity_applied_region_type.sql(给 label-category / product-category / label-type / label-multiple-option 加列)。

落库后回显示例:

{
  "appliedPartnerType": "SPECIFIED",
  "availabilityType": "SPECIFIED",
  "regionIds": ["ALL"],
  "groupIds": ["ALL"],
  "locationIds": ["3a22a490-6bcc-ee4f-2163-44f3e7b82906"]
}

请求示例(新增 / 编辑)

{
  "categoryName": "Prep",
  "appliedPartnerType": "SPECIFIED",
  "companyIds": ["{partnerGuid1}", "{partnerGuid2}"],
  "availabilityType": "SPECIFIED",
  "regionIds": ["ALL"],
  "groupIds": ["ALL"],
  "locationIds": ["ALL"],
  "state": true,
  "orderNum": 1
}

全选 Company + 全选门店:

{
  "categoryName": "Prep",
  "appliedPartnerType": "SPECIFIED",
  "companyIds": ["ALL"],
  "availabilityType": "SPECIFIED",
  "regionIds": ["ALL"],
  "locationIds": ["ALL"]
}

落库AppliedPartnerType=ALLAvailabilityType=ALL;不写 partner/location 关联快照。

响应示例(详情回显)

{
  "id": "3a22b3d6-897d-d89a-e263-b30761fe48be",
  "categoryName": "Prep",
  "appliedPartnerType": "ALL",
  "company": "All Companies",
  "companyIds": ["ALL"],
  "partnerIds": ["ALL"],
  "availabilityType": "ALL",
  "regionIds": ["ALL"],
  "groupIds": ["ALL"],
  "locationIds": ["ALL"]
}

数据库迁移(部署前执行)

脚本路径:

美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/fl_product_category_partner_scope.sql

内容概要:

  • fl_product_category 增加 AppliedPartnerType(默认 ALL
  • 新建 fl_product_category_partnerCategoryId + PartnerId

未执行迁移时:AppliedPartnerType=ALL 可正常保存;SPECIFIED + 具体 companyIds 保存会提示执行迁移。

改动文件

文件 变更
scripts/fl_product_category_partner_scope.sql 新增 迁移脚本
DbModels/FlProductCategoryDbEntity.cs AppliedPartnerType
DbModels/FlProductCategoryPartnerDbEntity.cs 新增
Helpers/LabelEntityPartnerScopeHelper.cs ProductCategory 种类 + 列表筛选
Dtos/ProductCategory/* 入参/出参 companyIds
Services/ProductCategoryAppService.cs Create/Update/Get/List 集成 Company 范围

联调注意

  1. 先执行 SQL 迁移,再重启美国版 API。
  2. 编辑弹窗回显以 companyIds 为准(与 partnerIds 等价)。
  3. 列表 company 为展示字段;勾选状态以 companyIds 数组为准。

列表筛选:ALL 绑定命中任意具体 Id(2026-07-27 续)

约定

实体绑定 Query 传入 应命中
Company = ALLappliedPartnerType=ALL / 无 partner 关联行) 任意 partnerId
Region = ALLavailabilityType/appliedRegionType=ALL / 无 region 关联行) 任意 groupId
Location = ALLavailabilityType/appliedLocationType=ALL 任意 locationId
维度 = SPECIFIED 对应具体 Id 仅关联命中

涉及列表接口

  • GET /api/app/label-type
  • GET /api/app/label-multiple-option
  • GET /api/app/label-template
  • GET /api/app/label-category
  • GET /api/app/label(原已支持 AppliedRegionType=ALL
  • GET /api/app/product-category
  • GET /api/app/product(原已支持 AvailabilityType=ALL
  • GET /api/app/product-location(按 locationId 时并入 AvailabilityType=ALL 产品)

实现要点

文件 变更
LabelEntityPartnerScopeHelper Partner 筛选:AppliedPartnerType=ALL SPECIFIED 关联命中
LabelEntityListScopeHelper Location 筛选:AvailabilityType=ALL SPECIFIED 门店命中(去掉「须 SPECIFIED Company」限制)
LabelTemplateScopeHelper.ApplyTemplateScopeFilterAsync Company/Region 无关联行视为 ALL;Location 保留 AppliedLocationType=ALL
ProductLocationAppService 按门店查时并入 AvailabilityType=ALL 产品

联调示例

GET /api/app/label-type?partnerId={任意公司Guid}&SkipCount=0&MaxResultCount=50

绑定 appliedPartnerType=ALL 的类型应出现在结果中。

GET /api/app/product-location?locationId={任意门店Guid}&MaxResultCount=2000

AvailabilityType=ALL 的产品应与该门店 SPECIFIED 关联产品一并返回。


label-multiple-option 仅 PartnerId 查不到第二家公司(2026-07-27 续)

原因

列表在传 PartnerId 时会:

  1. 按 Company 关联表过滤(正确)
  2. 把该公司下门店展开,与 AvailabilityType / 门店关联做 AND

多公司绑定时,若第二家公司暂无门店、或门店未写入 location 关联表,第 2 步会把已命中的记录误杀。

修复

  • 仅传 PartnerId(未传 GroupId / LocationId):只按 Company 维度过滤,跳过门店 Availability AND
  • 传了 GroupId / LocationId:仍按 Region/Location 过滤
  • 门店范围为 empty 时:保留 AvailabilityType=ALL,不再 Where false 清空

涉及:label-multiple-option / label-type / label-category / product-category / label-template / label / product / product-location

各接口要点

接口 修复
label-type / label-category / product-category / label-multiple-option PartnerId 跳过门店 AND
label-template PartnerId只返回 fl_label_template_partner 含该公司的模板;不再把「无关联行」当成 ALL(避免查出其他公司/AppliedPartnerType=ALL 的无关数据)
label 门店筛选补 AppliedRegionType=ALL;无门店时保留 ALL
product PartnerId 且公司无门店时保留 AvailabilityType=ALL
product-location 支持 PartnerId;按公司/门店查时并入 AvailabilityType=ALL

product 新增/编辑 companyIds(单选)(2026-07-27 续)

接口

方法 路径
POST /api/app/product
PUT /api/app/product/{id}
GET /api/app/product/{id}(编辑回显)

入参

字段 类型 说明
companyIds string[] 仅单选具体 Guid不支持 ALL;传多个 Guid 或含 ALL 报错
partnerId string 兼容旧字段;与 companyIds 同时传须一致;不支持 ALL

出参(详情)

字段 说明
companyIds 单选回显:最多 1 个具体 Guid;全部门店(AvailabilityType=ALL)时为空
partnerId companyIds[0] 对齐;无 Company 时为 null

示例

{
  "productName": "Milk",
  "companyIds": ["3a22a4f2-1ec6-c7a1-b1a9-f82e71e9754c"],
  "availabilityType": "SPECIFIED",
  "groupIds": ["ALL"],
  "locationIds": ["ALL"]
}

companyIds: ["ALL"]partnerId: "ALL" 将返回错误:产品适用 Company 不支持 ALL,请传单个具体 Company Id

product partnerId 兼容数组 + 范围内 ALL(2026-07-27)

问题 处理
前端传 "partnerId":["{guid}"] 导致 JSON 反序列化失败 PartnerId 增加转换器,兼容字符串或数组(取首项)
增加 regionIds groupIds 合并解析
具体 Company/Region + locationIds:["ALL"] 同 product-category:展开为 SPECIFIED 快照,回显可折回 ["ALL"]