From 04a4c4559df225f2f499264a1ef47530f496be0f Mon Sep 17 00:00:00 2001
From: 李曜臣
Date: Tue, 14 Jul 2026 10:01:29 +0800
Subject: [PATCH] 2026-07-14
---
泰额版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts | 16 +++++++++++++---
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs | 12 ++++--------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs | 33 +++++++++------------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs | 27 ++++-----------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs | 30 +++++++++++++++++++++++++++---
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs | 46 ++++++++++++++++++----------------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs | 48 ++++++++++++++++++++++++++++--------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs | 23 +----------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs | 23 +----------------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs | 30 ++++++++++++++++--------------
泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs | 15 +++++++++------
美国版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts | 16 +++++++++++++---
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs | 12 ++++--------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs | 33 +++++++++------------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs | 27 ++++-----------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs | 30 +++++++++++++++++++++++++++---
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs | 46 ++++++++++++++++++----------------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs | 48 ++++++++++++++++++++++++++++--------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs | 23 +----------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs | 23 +----------------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs | 30 ++++++++++++++++--------------
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs | 15 +++++++++------
美国版/Food Labeling Management Platform/src/services/labelCategoryService.ts | 4 ++++
29 files changed, 698 insertions(+), 348 deletions(-)
create mode 100644 泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
create mode 100644 泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
create mode 100644 美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
create mode 100644 美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
diff --git a/泰额版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts b/泰额版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
index da000a3..fdda953 100644
--- a/泰额版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
+++ b/泰额版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
@@ -1,13 +1,23 @@
import type { UsAppMyProfileOutputDto } from '../services/usAppAuth'
-/** 与后端 ReportsRoleHelper.IsAdminRole 对齐(App 管理员级联选店) */
+function isCompanyAdminProfile(profile: UsAppMyProfileOutputDto): boolean {
+ const code = (profile.primaryRoleCode ?? '').trim().toLowerCase()
+ if (code === 'companyadmin' || code.includes('partner')) return true
+ const display = (profile.roleDisplay ?? '').trim().toLowerCase()
+ if (!display) return false
+ if (display === 'company admin') return true
+ if (display.includes('partner admin')) return true
+ return false
+}
+
+/** 平台管理员或 Company Admin(App 级联选店) */
export function isAppAdminUser(profile: UsAppMyProfileOutputDto | null | undefined): boolean {
if (!profile) return false
const code = (profile.primaryRoleCode ?? '').trim().toLowerCase()
if (code === 'admin') return true
const display = (profile.roleDisplay ?? '').trim().toLowerCase()
- if (!display) return false
+ if (!display) return isCompanyAdminProfile(profile)
if (display.includes('administrator')) return true
if (display.includes('super admin')) return true
- return false
+ return isCompanyAdminProfile(profile)
}
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
index 4f08361..be7c640 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
@@ -277,14 +277,10 @@ public static class AuthScopeQueryHelper
return;
}
- var lid = locationId.Trim();
- var userIdStr = currentUser.Id!.Value.ToString();
- var bound = await dbContext.SqlSugarClient.Queryable()
- .AnyAsync(x => !x.IsDeleted && x.UserId == userIdStr && x.LocationId == lid);
- if (!bound)
- {
- throw new UserFriendlyException("当前账号未绑定该门店,无法选择");
- }
+ await UsAppPrintLogScopeHelper.EnsureUserCanAccessLocationAsync(
+ currentUser,
+ dbContext.SqlSugarClient,
+ locationId);
}
private static async Task ResolveAndValidateSelectionAsync(
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
new file mode 100644
index 0000000..c53fee6
--- /dev/null
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
@@ -0,0 +1,67 @@
+using FoodLabeling.Domain.Shared;
+using SqlSugar;
+
+namespace FoodLabeling.Application.Helpers;
+
+///
+/// 标签类型/分类/多选项等:列表 Region/Location 列展示(适用全部时分别为 All Region / All Location)。
+///
+public static class EntityLocationScopeDisplayHelper
+{
+ ///
+ /// 根据可用范围类型与已解析的 Region/Location Id、名称,生成列表展示文案。
+ ///
+ public static async Task<(string Region, string Location)> BuildListDisplayAsync(
+ ISqlSugarClient db,
+ string? availabilityType,
+ IReadOnlyList regionIds,
+ IReadOnlyList locationIds,
+ IEnumerable regionNames,
+ IEnumerable locationNames,
+ IReadOnlyList? partnerIdsForContext)
+ {
+ if (AllScopeBindingHelper.IsDeclaredAll(availabilityType))
+ {
+ return (AllScopeBindingHelper.AllRegionsDisplay, AllScopeBindingHelper.AllLocationsDisplay);
+ }
+
+ var normRegionIds = LocationScopeBindingHelper.NormalizeIds(regionIds);
+ var normLocationIds = LocationScopeBindingHelper.NormalizeIds(locationIds);
+ var partnerContext = partnerIdsForContext is { Count: > 0 } ? partnerIdsForContext : null;
+
+ var allRegionIds = await AllScopeBindingHelper.ResolveAllRegionIdsAsync(db, partnerContext);
+ var regionIsAll = normRegionIds.Count > 0
+ && allRegionIds.Count > 0
+ && AllScopeBindingHelper.IsFullIdSelection(normRegionIds, allRegionIds);
+
+ var regionContextForLocations = regionIsAll ? null : normRegionIds.Count > 0 ? normRegionIds : null;
+ var allLocationIds = await AllScopeBindingHelper.ResolveAllLocationIdsAsync(
+ db,
+ partnerContext,
+ regionContextForLocations);
+ var locationIsAll = normLocationIds.Count > 0
+ && allLocationIds.Count > 0
+ && AllScopeBindingHelper.IsFullIdSelection(normLocationIds, allLocationIds);
+
+ var regionDisplay = regionIsAll
+ ? AllScopeBindingHelper.AllRegionsDisplay
+ : JoinDistinctNames(regionNames);
+
+ var locationDisplay = locationIsAll
+ ? AllScopeBindingHelper.AllLocationsDisplay
+ : JoinDistinctNames(locationNames);
+
+ return (regionDisplay, locationDisplay);
+ }
+
+ private static string JoinDistinctNames(IEnumerable names)
+ {
+ var ordered = names
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Select(x => x.Trim())
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ return ordered.Count > 0 ? string.Join(", ", ordered) : FoodLabelingDisplayConsts.NotAvailable;
+ }
+}
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
new file mode 100644
index 0000000..d8c8296
--- /dev/null
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
@@ -0,0 +1,88 @@
+using FoodLabeling.Application.Services.DbModels;
+using SqlSugar;
+
+namespace FoodLabeling.Application.Helpers;
+
+///
+/// 标签类型/分类/多选项列表:非平台管理员仅可见其绑定 Company 范围内数据。
+///
+public static class LabelEntityListScopeHelper
+{
+ ///
+ /// 标签类型列表:按 Company + Region/Location 范围过滤(Company Admin 不可见 All Companies 数据)。
+ ///
+ public static ISugarQueryable ApplyTypeLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(t =>
+ (t.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && t.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (t.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(tl => tl.LabelTypeId == t.Id && scopedLocationIds.Contains(tl.LocationId))
+ .Any()));
+ }
+
+ ///
+ /// 标签分类列表:按 Company + Region/Location 范围过滤。
+ ///
+ public static ISugarQueryable ApplyCategoryLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(c =>
+ (c.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && c.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (c.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(cl => cl.CategoryId == c.Id && scopedLocationIds.Contains(cl.LocationId))
+ .Any()));
+ }
+
+ ///
+ /// 标签多选项列表:按 Company + Region/Location 范围过滤。
+ ///
+ public static ISugarQueryable ApplyMultipleOptionLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(o =>
+ (o.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && o.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (o.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(ol => ol.MultipleOptionId == o.Id && scopedLocationIds.Contains(ol.LocationId))
+ .Any()));
+ }
+}
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
index 57e580c..1bdbc25 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
@@ -348,17 +348,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(t =>
- !SqlFunc.Subqueryable()
- .Where(p => p.LabelTypeId == t.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(t =>
- !SqlFunc.Subqueryable()
- .Where(p => p.LabelTypeId == t.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ t.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.LabelTypeId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
@@ -384,17 +379,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(c =>
- !SqlFunc.Subqueryable()
- .Where(p => p.CategoryId == c.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(c =>
- !SqlFunc.Subqueryable()
- .Where(p => p.CategoryId == c.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ c.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.CategoryId == c.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
@@ -420,17 +410,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(o =>
- !SqlFunc.Subqueryable()
- .Where(p => p.MultipleOptionId == o.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(o =>
- !SqlFunc.Subqueryable()
- .Where(p => p.MultipleOptionId == o.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ o.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.MultipleOptionId == o.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
index f7ae0ea..674a63b 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
@@ -437,23 +437,7 @@ public static class LabelTemplateScopeHelper
if (scopedLocationIds.Count == 0)
{
- return hasExtendedScope
- ? query.Where(t =>
- t.AppliedLocationType == ScopeAll
- && !SqlFunc.Subqueryable()
- .Where(l => l.TemplateId == t.Id)
- .Any()
- && !SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id)
- .Any()
- && !SqlFunc.Subqueryable()
- .Where(r => r.TemplateId == t.Id)
- .Any())
- : query.Where(t =>
- t.AppliedLocationType == ScopeAll
- && !SqlFunc.Subqueryable()
- .Where(l => l.TemplateId == t.Id)
- .Any());
+ return query.Where(_ => false);
}
if (!hasExtendedScope)
@@ -470,12 +454,9 @@ public static class LabelTemplateScopeHelper
db, scopedLocationIds);
return query.Where(t =>
- (!SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id)
- .Any()
- || SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
- .Any())
+ SqlFunc.Subqueryable()
+ .Where(p => p.TemplateId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
+ .Any()
&& (!SqlFunc.Subqueryable()
.Where(r => r.TemplateId == t.Id)
.Any()
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
index e9d0616..b0942ee 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
@@ -25,6 +25,7 @@ public static class LocationRegionScopeHelper
///
/// 解析当前用户可查询的 Region(公司 + 组织名)集合。
+ /// Company Admin 展开为绑定 Company 下全部 Region(与 一致)。
///
public static async Task ResolveLocationListScopeAsync(
ICurrentUser currentUser,
@@ -40,8 +41,15 @@ public static class LocationRegionScopeHelper
return new LocationListScopeFilter();
}
+ var db = dbContext.SqlSugarClient;
+
+ if (await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser))
+ {
+ return await ResolveCompanyAdminLocationListScopeAsync(db, currentUser.Id.Value);
+ }
+
var userId = currentUser.Id.Value.ToString();
- var rows = await dbContext.SqlSugarClient.Queryable()
+ var rows = await db.Queryable()
.InnerJoin((ul, loc) =>
!loc.IsDeleted && ul.LocationId == loc.Id.ToString())
.Where(ul => !ul.IsDeleted && ul.UserId == userId)
@@ -57,6 +65,59 @@ public static class LocationRegionScopeHelper
return new LocationListScopeFilter { RegionKeys = keys };
}
+ private static async Task ResolveCompanyAdminLocationListScopeAsync(
+ ISqlSugarClient db,
+ Guid userId)
+ {
+ var locationIds = await LocationScopeBindingHelper.ResolveBoundLocationIdsForUserAsync(db, userId);
+ if (locationIds.Count == 0)
+ {
+ return new LocationListScopeFilter();
+ }
+
+ var partnerIds = await LocationScopeBindingHelper.ResolvePartnerIdsFromLocationIdsAsync(db, locationIds);
+ if (partnerIds.Count == 0)
+ {
+ return new LocationListScopeFilter();
+ }
+
+ var partners = await db.Queryable()
+ .Where(p => !p.IsDeleted && partnerIds.Contains(p.Id))
+ .Select(p => new { p.Id, p.PartnerName })
+ .ToListAsync();
+
+ var groups = await db.Queryable()
+ .Where(g => !g.IsDeleted && partnerIds.Contains(g.PartnerId))
+ .Select(g => new { g.PartnerId, g.GroupName })
+ .ToListAsync();
+
+ var keys = new HashSet<(string Partner, string GroupName)>();
+ foreach (var group in groups)
+ {
+ var groupName = group.GroupName?.Trim();
+ if (string.IsNullOrEmpty(groupName))
+ {
+ continue;
+ }
+
+ var partner = partners.FirstOrDefault(p =>
+ string.Equals(p.Id, group.PartnerId, StringComparison.OrdinalIgnoreCase));
+ var partnerName = partner?.PartnerName?.Trim();
+ if (!string.IsNullOrEmpty(partnerName))
+ {
+ keys.Add((partnerName, groupName));
+ }
+
+ var partnerId = group.PartnerId?.Trim();
+ if (!string.IsNullOrEmpty(partnerId))
+ {
+ keys.Add((partnerId, groupName));
+ }
+ }
+
+ return new LocationListScopeFilter { RegionKeys = keys.ToList() };
+ }
+
///
/// 将 Region 范围应用到 location 查询(须在其它 Where 之前或之后均可,建议在 IsDeleted 之后)。
///
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
index 59661b7..f9f4c8c 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
@@ -19,7 +19,7 @@ public static class UsAppAuthScopeHelper
{
private const string CacheKeyPrefix = "FoodLabeling:UsAppAdminScope:";
- public static void EnsureAdminAppToken(ICurrentUser currentUser)
+ public static async Task EnsureAppScopeCallerAsync(ISqlSugarClient db, ICurrentUser currentUser)
{
if (currentUser.Id is null)
{
@@ -32,12 +32,30 @@ public static class UsAppAuthScopeHelper
throw new UserFriendlyException("请使用 App 登录令牌调用该接口");
}
- if (!ReportsRoleHelper.IsAdminRole(currentUser))
+ if (!await CanUseAdminScopeApisAsync(db, currentUser))
{
- throw new UserFriendlyException("仅管理员可使用公司/区域/门店筛选接口");
+ throw new UserFriendlyException("仅管理员或 Company Admin 可使用公司/区域/门店筛选接口");
}
}
+ ///
+ /// 平台管理员或 Company Admin 可使用 App 级联选店接口。
+ ///
+ public static async Task CanUseAdminScopeApisAsync(ISqlSugarClient db, ICurrentUser currentUser)
+ {
+ if (currentUser.Id is null)
+ {
+ return false;
+ }
+
+ if (ReportsRoleHelper.IsAdminRole(currentUser))
+ {
+ return true;
+ }
+
+ return await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser);
+ }
+
public static async Task> ListCompaniesAsync(ISqlSugarClient db)
{
return await db.Queryable()
@@ -119,6 +137,7 @@ public static class UsAppAuthScopeHelper
public static async Task SelectLocationAsync(
ISqlSugarClient db,
IDistributedCache cache,
+ ICurrentUser currentUser,
Guid userId,
UsAppSelectAdminScopeLocationInputVo input)
{
@@ -130,6 +149,11 @@ public static class UsAppAuthScopeHelper
throw new UserFriendlyException("请选择公司、区域和门店");
}
+ if (!ReportsRoleHelper.IsAdminRole(currentUser))
+ {
+ await UsAppPrintLogScopeHelper.EnsureUserCanAccessLocationAsync(currentUser, db, locationId);
+ }
+
var scopedIds = await LocationScopeBindingHelper.ResolveFilteredLocationIdsForListAsync(
db,
partnerId,
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
index cd4a368..d3adc88 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
@@ -62,38 +62,28 @@ public class LabelAppService : ApplicationService, ILabelAppService
var db = _dbContext.SqlSugarClient;
var regionSchema = await LabelRegionSchemaHelper.GetStatusAsync(db);
- var scopedLocationIds = await LocationScopeBindingHelper.ResolveScopedLocationIdsAsync(
- db, groupId, locationId);
+ var scopedLocationIds = await TeamMemberListScopeHelper.ResolveListLocationIdsAsync(
+ CurrentUser,
+ _dbContext,
+ partnerId,
+ groupId,
+ locationId);
var filterGroupId = groupId?.Trim();
- if (!string.IsNullOrWhiteSpace(filterGroupId))
+ if (scopedLocationIds is not null)
{
- labelIdsQuery = scopedLocationIds is { Count: 0 }
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelRegionListFilter(
+ if (scopedLocationIds.Count == 0)
+ {
+ labelIdsQuery = labelIdsQuery.Where(_ => false);
+ }
+ else if (!string.IsNullOrWhiteSpace(filterGroupId))
+ {
+ labelIdsQuery = LabelRegionScopeHelper.ApplyLabelRegionListFilter(
db, labelIdsQuery, filterGroupId, scopedLocationIds, regionSchema);
- }
- else if (scopedLocationIds is not null)
- {
- labelIdsQuery = scopedLocationIds.Count == 0
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelLocationListFilter(
- db, labelIdsQuery, scopedLocationIds, regionSchema);
- }
- else if (!string.IsNullOrWhiteSpace(groupId))
- {
- labelIdsQuery = LabelRegionScopeHelper.ApplyGroupIdListFilter(
- db, labelIdsQuery, groupId, regionSchema);
- }
- else if (!string.IsNullOrWhiteSpace(partnerId))
- {
- var partnerLocationIds = await LocationScopeBindingHelper.ResolveFilteredLocationIdsForListAsync(
- db, partnerId, null, null);
- if (partnerLocationIds is not null)
+ }
+ else
{
- labelIdsQuery = partnerLocationIds.Count == 0
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelLocationListFilter(
- db, labelIdsQuery, partnerLocationIds, regionSchema);
+ labelIdsQuery = LabelRegionScopeHelper.ApplyLabelLocationListFilter(
+ db, labelIdsQuery, scopedLocationIds, regionSchema);
}
}
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
index 9c9c71b..dd918a9 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
@@ -71,11 +71,11 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
var ids = entities.Select(x => x.Id).ToList();
var labelStatsMap = await BuildCategoryLabelStatsMapAsync(ids);
- var scopeMap = await BuildCategoryScopeMapAsync(entities);
var partnerScopeMap = await LabelEntityPartnerScopeHelper.BuildPartnerScopeDisplayMapAsync(
_dbContext.SqlSugarClient,
LabelEntityPartnerScopeHelper.LabelEntityPartnerKind.Category,
ids);
+ var scopeMap = await BuildCategoryScopeMapAsync(entities, partnerScopeMap);
var items = entities.Select(x =>
{
@@ -370,16 +370,7 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
return query;
}
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(c => c.AvailabilityType == "ALL");
- }
-
- return query.Where(c =>
- c.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(cl => cl.CategoryId == c.Id && scopedLocationIds.Contains(cl.LocationId))
- .Any());
+ return LabelEntityListScopeHelper.ApplyCategoryLocationAvailabilityFilter(query, scopedLocationIds);
}
private async Task SaveCategoryPartnerScopeAsync(
@@ -420,7 +411,8 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
private const string EmptyDisplay = FoodLabelingDisplayConsts.NotAvailable;
private async Task> BuildCategoryScopeMapAsync(
- List entities)
+ List entities,
+ Dictionary partnerScopeMap)
{
var result = new Dictionary(StringComparer.Ordinal);
if (entities.Count == 0)
@@ -428,8 +420,9 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
return result;
}
- foreach (var e in entities.Where(x =>
- !string.Equals(x.AvailabilityType, "SPECIFIED", StringComparison.OrdinalIgnoreCase)))
+ var entityById = entities.ToDictionary(x => x.Id, StringComparer.Ordinal);
+
+ foreach (var e in entities.Where(x => AllScopeBindingHelper.IsDeclaredAll(x.AvailabilityType)))
{
result[e.Id] = new CategoryScopeData
{
@@ -525,14 +518,29 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
var regionIds = await LocationScopeBindingHelper.ResolveGroupIdsFromLocationIdsAsync(
_dbContext.SqlSugarClient, locationIds);
+ entityById.TryGetValue(catId, out var entity);
+ partnerScopeMap.TryGetValue(catId, out var partnerScope);
+ var partnerContext = entity is not null
+ && string.Equals(
+ entity.AppliedPartnerType,
+ LabelEntityPartnerScopeHelper.ScopeSpecified,
+ StringComparison.OrdinalIgnoreCase)
+ ? partnerScope?.PartnerIds
+ : null;
+
+ var (regionDisplay, locationDisplay) = await EntityLocationScopeDisplayHelper.BuildListDisplayAsync(
+ _dbContext.SqlSugarClient,
+ entity?.AvailabilityType,
+ regionIds,
+ locationIds,
+ regions,
+ locationNames,
+ partnerContext);
+
result[catId] = new CategoryScopeData
{
- Region = regions.Count > 0
- ? string.Join(", ", regions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
- : EmptyDisplay,
- Location = locationNames.Count > 0
- ? string.Join(", ", locationNames.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
- : EmptyDisplay,
+ Region = regionDisplay,
+ Location = locationDisplay,
RegionIds = regionIds,
LocationIds = locationIds
};
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
index 9f2e38e..67aa994 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
@@ -43,7 +43,7 @@ public class LabelMultipleOptionAppService : ApplicationService, ILabelMultipleO
query = await LabelEntityPartnerScopeHelper.ApplyMultipleOptionPartnerListFilterAsync(
_dbContext.SqlSugarClient, query, scopedPartnerIds);
- query = ApplyMultipleOptionScopeFilter(query, scopedLocationIds);
+ query = LabelEntityListScopeHelper.ApplyMultipleOptionLocationAvailabilityFilter(query, scopedLocationIds);
if (!string.IsNullOrWhiteSpace(input.Sorting))
{
@@ -395,27 +395,6 @@ public class LabelMultipleOptionAppService : ApplicationService, ILabelMultipleO
};
}
- private static ISugarQueryable ApplyMultipleOptionScopeFilter(
- ISugarQueryable query,
- List? scopedLocationIds)
- {
- if (scopedLocationIds is null)
- {
- return query;
- }
-
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(o => o.AvailabilityType == "ALL");
- }
-
- return query.Where(o =>
- o.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(ol => ol.MultipleOptionId == o.Id && scopedLocationIds.Contains(ol.LocationId))
- .Any());
- }
-
private async Task> BuildMultipleOptionScopeMapAsync(
List entities)
{
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
index 1e96ce0..2a21745 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
@@ -43,7 +43,7 @@ public class LabelTypeAppService : ApplicationService, ILabelTypeAppService
query = await LabelEntityPartnerScopeHelper.ApplyTypePartnerListFilterAsync(
_dbContext.SqlSugarClient, query, scopedPartnerIds);
- query = ApplyLabelTypeScopeFilter(query, scopedLocationIds);
+ query = LabelEntityListScopeHelper.ApplyTypeLocationAvailabilityFilter(query, scopedLocationIds);
if (!string.IsNullOrWhiteSpace(input.Sorting))
{
@@ -346,27 +346,6 @@ public class LabelTypeAppService : ApplicationService, ILabelTypeAppService
return merged.OrderBy(x => x, StringComparer.Ordinal).ToList();
}
- private static ISugarQueryable ApplyLabelTypeScopeFilter(
- ISugarQueryable query,
- List? scopedLocationIds)
- {
- if (scopedLocationIds is null)
- {
- return query;
- }
-
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(t => t.AvailabilityType == "ALL");
- }
-
- return query.Where(t =>
- t.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(tl => tl.LabelTypeId == t.Id && scopedLocationIds.Contains(tl.LocationId))
- .Any());
- }
-
private async Task SaveTypeLocationsAsync(
string labelTypeId,
string availabilityType,
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
index fe4aed5..0522fcb 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
@@ -170,7 +170,7 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
}
var list = await LoadBoundLocationsAsync(CurrentUser.Id.Value);
- if (ReportsRoleHelper.IsAdminRole(CurrentUser))
+ if (await UsAppAuthScopeHelper.CanUseAdminScopeApisAsync(_dbContext.SqlSugarClient, CurrentUser))
{
var cached = await UsAppAuthScopeHelper.GetAdminScopeCacheAsync(
_distributedCache,
@@ -189,39 +189,40 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
///
[Authorize]
+ [HttpGet("us-app-auth/admin-scope-companies")]
public virtual async Task> GetAdminScopeCompaniesAsync()
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListCompaniesAsync(_dbContext.SqlSugarClient);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetCompaniesAsync(CurrentUser, _dbContext);
}
///
[Authorize]
- public virtual async Task> GetAdminScopeRegionsAsync(string partnerId)
+ [HttpGet("us-app-auth/admin-scope-regions")]
+ public virtual async Task> GetAdminScopeRegionsAsync([FromQuery] string partnerId)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListRegionsAsync(_dbContext.SqlSugarClient, partnerId);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetRegionsAsync(CurrentUser, _dbContext, partnerId);
}
///
[Authorize]
+ [HttpGet("us-app-auth/admin-scope-locations")]
public virtual async Task> GetAdminScopeLocationsAsync(
- string partnerId,
- string groupId)
+ [FromQuery] string partnerId,
+ [FromQuery] string groupId)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListLocationsAsync(
- _dbContext.SqlSugarClient,
- partnerId,
- groupId);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetLocationsAsync(CurrentUser, _dbContext, partnerId, groupId);
}
///
[Authorize]
+ [HttpPost("us-app-auth/select-admin-scope-location")]
public virtual async Task SelectAdminScopeLocationAsync(
AuthScopeSelectLocationInputVo input)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
if (!CurrentUser.Id.HasValue)
{
throw new UserFriendlyException("用户未登录");
@@ -230,6 +231,7 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
return await UsAppAuthScopeHelper.SelectLocationAsync(
_dbContext.SqlSugarClient,
_distributedCache,
+ CurrentUser,
CurrentUser.Id.Value,
new UsAppSelectAdminScopeLocationInputVo
{
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
index 273af31..2227bcf 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
@@ -364,11 +364,13 @@ public class UsAppLabelingAppService : ApplicationService, IUsAppLabelingAppServ
}
var labelRow = await _dbContext.SqlSugarClient
- .Queryable(
- (l, c, t, tpl) => l.LabelCategoryId == c.Id && l.LabelTypeId == t.Id && l.TemplateId == tpl.Id)
+ .Queryable()
+ .InnerJoin((l, c) => l.LabelCategoryId == c.Id)
+ .LeftJoin((l, c, t) => l.LabelTypeId == t.Id)
+ .InnerJoin((l, c, t, tpl) => l.TemplateId == tpl.Id)
.Where((l, c, t, tpl) => !l.IsDeleted && l.State)
.Where((l, c, t, tpl) => !c.IsDeleted && c.State)
- .Where((l, c, t, tpl) => !t.IsDeleted && t.State)
+ .Where((l, c, t, tpl) => t.Id == null || (!t.IsDeleted && t.State))
.Where((l, c, t, tpl) => !tpl.IsDeleted)
.Where((l, c, t, tpl) => l.LabelCode == labelCode)
.Select((l, c, t, tpl) => new
@@ -551,10 +553,11 @@ public class UsAppLabelingAppService : ApplicationService, IUsAppLabelingAppServ
// 校验 label + location,并补齐一些顶部字段用于任务表落库
var labelRow = await _dbContext.SqlSugarClient
- .Queryable(
- (l, t, tpl) => l.LabelTypeId == t.Id && l.TemplateId == tpl.Id)
+ .Queryable()
+ .LeftJoin((l, t) => l.LabelTypeId == t.Id)
+ .InnerJoin((l, t, tpl) => l.TemplateId == tpl.Id)
.Where((l, t, tpl) => !l.IsDeleted && l.State)
- .Where((l, t, tpl) => !t.IsDeleted && t.State)
+ .Where((l, t, tpl) => t.Id == null || (!t.IsDeleted && t.State))
.Where((l, t, tpl) => !tpl.IsDeleted)
.Where((l, t, tpl) => l.LabelCode == labelCode)
.Select((l, t, tpl) => new
diff --git a/美国版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts b/美国版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
index 1bfa47c..d8f34db 100644
--- a/美国版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
+++ b/美国版/Food Labeling Management App UniApp/src/utils/appAdminRole.ts
@@ -1,6 +1,16 @@
import type { UsAppMyProfileOutputDto } from '../services/usAppAuth'
-/** 与后端 ReportsRoleHelper.IsAdminRole 对齐(App 管理员级联选店) */
+function isCompanyAdminProfile(profile: UsAppMyProfileOutputDto): boolean {
+ const code = (profile.primaryRoleCode ?? '').trim().toLowerCase()
+ if (code === 'companyadmin' || code.includes('partner')) return true
+ const display = (profile.roleDisplay ?? '').trim().toLowerCase()
+ if (!display) return false
+ if (display === 'company admin') return true
+ if (display.includes('partner admin')) return true
+ return false
+}
+
+/** 平台管理员或 Company Admin(App 级联选店) */
export function isAppAdminUser(profile: UsAppMyProfileOutputDto | null | undefined): boolean {
if (!profile) return false
const code = (profile.primaryRoleCode ?? '').trim().toLowerCase()
@@ -8,9 +18,9 @@ export function isAppAdminUser(profile: UsAppMyProfileOutputDto | null | undefin
if (code === 'admin') return true
if (compactCode === 'companyadmin') return true
const display = (profile.roleDisplay ?? '').trim().toLowerCase()
- if (!display) return false
+ if (!display) return isCompanyAdminProfile(profile)
if (display.includes('administrator')) return true
if (display.includes('super admin')) return true
if (display.includes('company admin')) return true
- return false
+ return isCompanyAdminProfile(profile)
}
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
index 4f08361..be7c640 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/AuthScopeQueryHelper.cs
@@ -277,14 +277,10 @@ public static class AuthScopeQueryHelper
return;
}
- var lid = locationId.Trim();
- var userIdStr = currentUser.Id!.Value.ToString();
- var bound = await dbContext.SqlSugarClient.Queryable()
- .AnyAsync(x => !x.IsDeleted && x.UserId == userIdStr && x.LocationId == lid);
- if (!bound)
- {
- throw new UserFriendlyException("当前账号未绑定该门店,无法选择");
- }
+ await UsAppPrintLogScopeHelper.EnsureUserCanAccessLocationAsync(
+ currentUser,
+ dbContext.SqlSugarClient,
+ locationId);
}
private static async Task ResolveAndValidateSelectionAsync(
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
new file mode 100644
index 0000000..c53fee6
--- /dev/null
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/EntityLocationScopeDisplayHelper.cs
@@ -0,0 +1,67 @@
+using FoodLabeling.Domain.Shared;
+using SqlSugar;
+
+namespace FoodLabeling.Application.Helpers;
+
+///
+/// 标签类型/分类/多选项等:列表 Region/Location 列展示(适用全部时分别为 All Region / All Location)。
+///
+public static class EntityLocationScopeDisplayHelper
+{
+ ///
+ /// 根据可用范围类型与已解析的 Region/Location Id、名称,生成列表展示文案。
+ ///
+ public static async Task<(string Region, string Location)> BuildListDisplayAsync(
+ ISqlSugarClient db,
+ string? availabilityType,
+ IReadOnlyList regionIds,
+ IReadOnlyList locationIds,
+ IEnumerable regionNames,
+ IEnumerable locationNames,
+ IReadOnlyList? partnerIdsForContext)
+ {
+ if (AllScopeBindingHelper.IsDeclaredAll(availabilityType))
+ {
+ return (AllScopeBindingHelper.AllRegionsDisplay, AllScopeBindingHelper.AllLocationsDisplay);
+ }
+
+ var normRegionIds = LocationScopeBindingHelper.NormalizeIds(regionIds);
+ var normLocationIds = LocationScopeBindingHelper.NormalizeIds(locationIds);
+ var partnerContext = partnerIdsForContext is { Count: > 0 } ? partnerIdsForContext : null;
+
+ var allRegionIds = await AllScopeBindingHelper.ResolveAllRegionIdsAsync(db, partnerContext);
+ var regionIsAll = normRegionIds.Count > 0
+ && allRegionIds.Count > 0
+ && AllScopeBindingHelper.IsFullIdSelection(normRegionIds, allRegionIds);
+
+ var regionContextForLocations = regionIsAll ? null : normRegionIds.Count > 0 ? normRegionIds : null;
+ var allLocationIds = await AllScopeBindingHelper.ResolveAllLocationIdsAsync(
+ db,
+ partnerContext,
+ regionContextForLocations);
+ var locationIsAll = normLocationIds.Count > 0
+ && allLocationIds.Count > 0
+ && AllScopeBindingHelper.IsFullIdSelection(normLocationIds, allLocationIds);
+
+ var regionDisplay = regionIsAll
+ ? AllScopeBindingHelper.AllRegionsDisplay
+ : JoinDistinctNames(regionNames);
+
+ var locationDisplay = locationIsAll
+ ? AllScopeBindingHelper.AllLocationsDisplay
+ : JoinDistinctNames(locationNames);
+
+ return (regionDisplay, locationDisplay);
+ }
+
+ private static string JoinDistinctNames(IEnumerable names)
+ {
+ var ordered = names
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Select(x => x.Trim())
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ return ordered.Count > 0 ? string.Join(", ", ordered) : FoodLabelingDisplayConsts.NotAvailable;
+ }
+}
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
new file mode 100644
index 0000000..d8c8296
--- /dev/null
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityListScopeHelper.cs
@@ -0,0 +1,88 @@
+using FoodLabeling.Application.Services.DbModels;
+using SqlSugar;
+
+namespace FoodLabeling.Application.Helpers;
+
+///
+/// 标签类型/分类/多选项列表:非平台管理员仅可见其绑定 Company 范围内数据。
+///
+public static class LabelEntityListScopeHelper
+{
+ ///
+ /// 标签类型列表:按 Company + Region/Location 范围过滤(Company Admin 不可见 All Companies 数据)。
+ ///
+ public static ISugarQueryable ApplyTypeLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(t =>
+ (t.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && t.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (t.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(tl => tl.LabelTypeId == t.Id && scopedLocationIds.Contains(tl.LocationId))
+ .Any()));
+ }
+
+ ///
+ /// 标签分类列表:按 Company + Region/Location 范围过滤。
+ ///
+ public static ISugarQueryable ApplyCategoryLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(c =>
+ (c.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && c.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (c.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(cl => cl.CategoryId == c.Id && scopedLocationIds.Contains(cl.LocationId))
+ .Any()));
+ }
+
+ ///
+ /// 标签多选项列表:按 Company + Region/Location 范围过滤。
+ ///
+ public static ISugarQueryable ApplyMultipleOptionLocationAvailabilityFilter(
+ ISugarQueryable query,
+ List? scopedLocationIds)
+ {
+ if (scopedLocationIds is null)
+ {
+ return query;
+ }
+
+ if (scopedLocationIds.Count == 0)
+ {
+ return query.Where(_ => false);
+ }
+
+ return query.Where(o =>
+ (o.AvailabilityType == AllScopeBindingHelper.ScopeAll
+ && o.AppliedPartnerType == LabelEntityPartnerScopeHelper.ScopeSpecified)
+ || (o.AvailabilityType == AllScopeBindingHelper.ScopeSpecified
+ && SqlFunc.Subqueryable()
+ .Where(ol => ol.MultipleOptionId == o.Id && scopedLocationIds.Contains(ol.LocationId))
+ .Any()));
+ }
+}
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
index 57e580c..1bdbc25 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelEntityPartnerScopeHelper.cs
@@ -348,17 +348,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(t =>
- !SqlFunc.Subqueryable()
- .Where(p => p.LabelTypeId == t.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(t =>
- !SqlFunc.Subqueryable()
- .Where(p => p.LabelTypeId == t.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ t.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.LabelTypeId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
@@ -384,17 +379,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(c =>
- !SqlFunc.Subqueryable()
- .Where(p => p.CategoryId == c.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(c =>
- !SqlFunc.Subqueryable()
- .Where(p => p.CategoryId == c.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ c.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.CategoryId == c.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
@@ -420,17 +410,12 @@ public static class LabelEntityPartnerScopeHelper
if (scopedPartnerIds.Count == 0)
{
- return query.Where(o =>
- !SqlFunc.Subqueryable()
- .Where(p => p.MultipleOptionId == o.Id)
- .Any());
+ return query.Where(_ => false);
}
return query.Where(o =>
- !SqlFunc.Subqueryable()
- .Where(p => p.MultipleOptionId == o.Id)
- .Any()
- || SqlFunc.Subqueryable()
+ o.AppliedPartnerType == ScopeSpecified
+ && SqlFunc.Subqueryable()
.Where(p => p.MultipleOptionId == o.Id && scopedPartnerIds.Contains(p.PartnerId))
.Any());
}
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
index f7ae0ea..674a63b 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LabelTemplateScopeHelper.cs
@@ -437,23 +437,7 @@ public static class LabelTemplateScopeHelper
if (scopedLocationIds.Count == 0)
{
- return hasExtendedScope
- ? query.Where(t =>
- t.AppliedLocationType == ScopeAll
- && !SqlFunc.Subqueryable()
- .Where(l => l.TemplateId == t.Id)
- .Any()
- && !SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id)
- .Any()
- && !SqlFunc.Subqueryable()
- .Where(r => r.TemplateId == t.Id)
- .Any())
- : query.Where(t =>
- t.AppliedLocationType == ScopeAll
- && !SqlFunc.Subqueryable()
- .Where(l => l.TemplateId == t.Id)
- .Any());
+ return query.Where(_ => false);
}
if (!hasExtendedScope)
@@ -470,12 +454,9 @@ public static class LabelTemplateScopeHelper
db, scopedLocationIds);
return query.Where(t =>
- (!SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id)
- .Any()
- || SqlFunc.Subqueryable()
- .Where(p => p.TemplateId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
- .Any())
+ SqlFunc.Subqueryable()
+ .Where(p => p.TemplateId == t.Id && scopedPartnerIds.Contains(p.PartnerId))
+ .Any()
&& (!SqlFunc.Subqueryable()
.Where(r => r.TemplateId == t.Id)
.Any()
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
index e9d0616..b0942ee 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/LocationRegionScopeHelper.cs
@@ -25,6 +25,7 @@ public static class LocationRegionScopeHelper
///
/// 解析当前用户可查询的 Region(公司 + 组织名)集合。
+ /// Company Admin 展开为绑定 Company 下全部 Region(与 一致)。
///
public static async Task ResolveLocationListScopeAsync(
ICurrentUser currentUser,
@@ -40,8 +41,15 @@ public static class LocationRegionScopeHelper
return new LocationListScopeFilter();
}
+ var db = dbContext.SqlSugarClient;
+
+ if (await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser))
+ {
+ return await ResolveCompanyAdminLocationListScopeAsync(db, currentUser.Id.Value);
+ }
+
var userId = currentUser.Id.Value.ToString();
- var rows = await dbContext.SqlSugarClient.Queryable()
+ var rows = await db.Queryable()
.InnerJoin((ul, loc) =>
!loc.IsDeleted && ul.LocationId == loc.Id.ToString())
.Where(ul => !ul.IsDeleted && ul.UserId == userId)
@@ -57,6 +65,59 @@ public static class LocationRegionScopeHelper
return new LocationListScopeFilter { RegionKeys = keys };
}
+ private static async Task ResolveCompanyAdminLocationListScopeAsync(
+ ISqlSugarClient db,
+ Guid userId)
+ {
+ var locationIds = await LocationScopeBindingHelper.ResolveBoundLocationIdsForUserAsync(db, userId);
+ if (locationIds.Count == 0)
+ {
+ return new LocationListScopeFilter();
+ }
+
+ var partnerIds = await LocationScopeBindingHelper.ResolvePartnerIdsFromLocationIdsAsync(db, locationIds);
+ if (partnerIds.Count == 0)
+ {
+ return new LocationListScopeFilter();
+ }
+
+ var partners = await db.Queryable()
+ .Where(p => !p.IsDeleted && partnerIds.Contains(p.Id))
+ .Select(p => new { p.Id, p.PartnerName })
+ .ToListAsync();
+
+ var groups = await db.Queryable()
+ .Where(g => !g.IsDeleted && partnerIds.Contains(g.PartnerId))
+ .Select(g => new { g.PartnerId, g.GroupName })
+ .ToListAsync();
+
+ var keys = new HashSet<(string Partner, string GroupName)>();
+ foreach (var group in groups)
+ {
+ var groupName = group.GroupName?.Trim();
+ if (string.IsNullOrEmpty(groupName))
+ {
+ continue;
+ }
+
+ var partner = partners.FirstOrDefault(p =>
+ string.Equals(p.Id, group.PartnerId, StringComparison.OrdinalIgnoreCase));
+ var partnerName = partner?.PartnerName?.Trim();
+ if (!string.IsNullOrEmpty(partnerName))
+ {
+ keys.Add((partnerName, groupName));
+ }
+
+ var partnerId = group.PartnerId?.Trim();
+ if (!string.IsNullOrEmpty(partnerId))
+ {
+ keys.Add((partnerId, groupName));
+ }
+ }
+
+ return new LocationListScopeFilter { RegionKeys = keys.ToList() };
+ }
+
///
/// 将 Region 范围应用到 location 查询(须在其它 Where 之前或之后均可,建议在 IsDeleted 之后)。
///
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
index 59661b7..f9f4c8c 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Helpers/UsAppAuthScopeHelper.cs
@@ -19,7 +19,7 @@ public static class UsAppAuthScopeHelper
{
private const string CacheKeyPrefix = "FoodLabeling:UsAppAdminScope:";
- public static void EnsureAdminAppToken(ICurrentUser currentUser)
+ public static async Task EnsureAppScopeCallerAsync(ISqlSugarClient db, ICurrentUser currentUser)
{
if (currentUser.Id is null)
{
@@ -32,12 +32,30 @@ public static class UsAppAuthScopeHelper
throw new UserFriendlyException("请使用 App 登录令牌调用该接口");
}
- if (!ReportsRoleHelper.IsAdminRole(currentUser))
+ if (!await CanUseAdminScopeApisAsync(db, currentUser))
{
- throw new UserFriendlyException("仅管理员可使用公司/区域/门店筛选接口");
+ throw new UserFriendlyException("仅管理员或 Company Admin 可使用公司/区域/门店筛选接口");
}
}
+ ///
+ /// 平台管理员或 Company Admin 可使用 App 级联选店接口。
+ ///
+ public static async Task CanUseAdminScopeApisAsync(ISqlSugarClient db, ICurrentUser currentUser)
+ {
+ if (currentUser.Id is null)
+ {
+ return false;
+ }
+
+ if (ReportsRoleHelper.IsAdminRole(currentUser))
+ {
+ return true;
+ }
+
+ return await TeamMemberRoleHelper.IsCompanyAdminUserAsync(db, currentUser);
+ }
+
public static async Task> ListCompaniesAsync(ISqlSugarClient db)
{
return await db.Queryable()
@@ -119,6 +137,7 @@ public static class UsAppAuthScopeHelper
public static async Task SelectLocationAsync(
ISqlSugarClient db,
IDistributedCache cache,
+ ICurrentUser currentUser,
Guid userId,
UsAppSelectAdminScopeLocationInputVo input)
{
@@ -130,6 +149,11 @@ public static class UsAppAuthScopeHelper
throw new UserFriendlyException("请选择公司、区域和门店");
}
+ if (!ReportsRoleHelper.IsAdminRole(currentUser))
+ {
+ await UsAppPrintLogScopeHelper.EnsureUserCanAccessLocationAsync(currentUser, db, locationId);
+ }
+
var scopedIds = await LocationScopeBindingHelper.ResolveFilteredLocationIdsForListAsync(
db,
partnerId,
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
index cd4a368..d3adc88 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
@@ -62,38 +62,28 @@ public class LabelAppService : ApplicationService, ILabelAppService
var db = _dbContext.SqlSugarClient;
var regionSchema = await LabelRegionSchemaHelper.GetStatusAsync(db);
- var scopedLocationIds = await LocationScopeBindingHelper.ResolveScopedLocationIdsAsync(
- db, groupId, locationId);
+ var scopedLocationIds = await TeamMemberListScopeHelper.ResolveListLocationIdsAsync(
+ CurrentUser,
+ _dbContext,
+ partnerId,
+ groupId,
+ locationId);
var filterGroupId = groupId?.Trim();
- if (!string.IsNullOrWhiteSpace(filterGroupId))
+ if (scopedLocationIds is not null)
{
- labelIdsQuery = scopedLocationIds is { Count: 0 }
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelRegionListFilter(
+ if (scopedLocationIds.Count == 0)
+ {
+ labelIdsQuery = labelIdsQuery.Where(_ => false);
+ }
+ else if (!string.IsNullOrWhiteSpace(filterGroupId))
+ {
+ labelIdsQuery = LabelRegionScopeHelper.ApplyLabelRegionListFilter(
db, labelIdsQuery, filterGroupId, scopedLocationIds, regionSchema);
- }
- else if (scopedLocationIds is not null)
- {
- labelIdsQuery = scopedLocationIds.Count == 0
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelLocationListFilter(
- db, labelIdsQuery, scopedLocationIds, regionSchema);
- }
- else if (!string.IsNullOrWhiteSpace(groupId))
- {
- labelIdsQuery = LabelRegionScopeHelper.ApplyGroupIdListFilter(
- db, labelIdsQuery, groupId, regionSchema);
- }
- else if (!string.IsNullOrWhiteSpace(partnerId))
- {
- var partnerLocationIds = await LocationScopeBindingHelper.ResolveFilteredLocationIdsForListAsync(
- db, partnerId, null, null);
- if (partnerLocationIds is not null)
+ }
+ else
{
- labelIdsQuery = partnerLocationIds.Count == 0
- ? labelIdsQuery.Where(_ => false)
- : LabelRegionScopeHelper.ApplyLabelLocationListFilter(
- db, labelIdsQuery, partnerLocationIds, regionSchema);
+ labelIdsQuery = LabelRegionScopeHelper.ApplyLabelLocationListFilter(
+ db, labelIdsQuery, scopedLocationIds, regionSchema);
}
}
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
index 9c9c71b..dd918a9 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
@@ -71,11 +71,11 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
var ids = entities.Select(x => x.Id).ToList();
var labelStatsMap = await BuildCategoryLabelStatsMapAsync(ids);
- var scopeMap = await BuildCategoryScopeMapAsync(entities);
var partnerScopeMap = await LabelEntityPartnerScopeHelper.BuildPartnerScopeDisplayMapAsync(
_dbContext.SqlSugarClient,
LabelEntityPartnerScopeHelper.LabelEntityPartnerKind.Category,
ids);
+ var scopeMap = await BuildCategoryScopeMapAsync(entities, partnerScopeMap);
var items = entities.Select(x =>
{
@@ -370,16 +370,7 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
return query;
}
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(c => c.AvailabilityType == "ALL");
- }
-
- return query.Where(c =>
- c.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(cl => cl.CategoryId == c.Id && scopedLocationIds.Contains(cl.LocationId))
- .Any());
+ return LabelEntityListScopeHelper.ApplyCategoryLocationAvailabilityFilter(query, scopedLocationIds);
}
private async Task SaveCategoryPartnerScopeAsync(
@@ -420,7 +411,8 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
private const string EmptyDisplay = FoodLabelingDisplayConsts.NotAvailable;
private async Task> BuildCategoryScopeMapAsync(
- List entities)
+ List entities,
+ Dictionary partnerScopeMap)
{
var result = new Dictionary(StringComparer.Ordinal);
if (entities.Count == 0)
@@ -428,8 +420,9 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
return result;
}
- foreach (var e in entities.Where(x =>
- !string.Equals(x.AvailabilityType, "SPECIFIED", StringComparison.OrdinalIgnoreCase)))
+ var entityById = entities.ToDictionary(x => x.Id, StringComparer.Ordinal);
+
+ foreach (var e in entities.Where(x => AllScopeBindingHelper.IsDeclaredAll(x.AvailabilityType)))
{
result[e.Id] = new CategoryScopeData
{
@@ -525,14 +518,29 @@ public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppServ
var regionIds = await LocationScopeBindingHelper.ResolveGroupIdsFromLocationIdsAsync(
_dbContext.SqlSugarClient, locationIds);
+ entityById.TryGetValue(catId, out var entity);
+ partnerScopeMap.TryGetValue(catId, out var partnerScope);
+ var partnerContext = entity is not null
+ && string.Equals(
+ entity.AppliedPartnerType,
+ LabelEntityPartnerScopeHelper.ScopeSpecified,
+ StringComparison.OrdinalIgnoreCase)
+ ? partnerScope?.PartnerIds
+ : null;
+
+ var (regionDisplay, locationDisplay) = await EntityLocationScopeDisplayHelper.BuildListDisplayAsync(
+ _dbContext.SqlSugarClient,
+ entity?.AvailabilityType,
+ regionIds,
+ locationIds,
+ regions,
+ locationNames,
+ partnerContext);
+
result[catId] = new CategoryScopeData
{
- Region = regions.Count > 0
- ? string.Join(", ", regions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
- : EmptyDisplay,
- Location = locationNames.Count > 0
- ? string.Join(", ", locationNames.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
- : EmptyDisplay,
+ Region = regionDisplay,
+ Location = locationDisplay,
RegionIds = regionIds,
LocationIds = locationIds
};
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
index 9f2e38e..67aa994 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
@@ -43,7 +43,7 @@ public class LabelMultipleOptionAppService : ApplicationService, ILabelMultipleO
query = await LabelEntityPartnerScopeHelper.ApplyMultipleOptionPartnerListFilterAsync(
_dbContext.SqlSugarClient, query, scopedPartnerIds);
- query = ApplyMultipleOptionScopeFilter(query, scopedLocationIds);
+ query = LabelEntityListScopeHelper.ApplyMultipleOptionLocationAvailabilityFilter(query, scopedLocationIds);
if (!string.IsNullOrWhiteSpace(input.Sorting))
{
@@ -395,27 +395,6 @@ public class LabelMultipleOptionAppService : ApplicationService, ILabelMultipleO
};
}
- private static ISugarQueryable ApplyMultipleOptionScopeFilter(
- ISugarQueryable query,
- List? scopedLocationIds)
- {
- if (scopedLocationIds is null)
- {
- return query;
- }
-
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(o => o.AvailabilityType == "ALL");
- }
-
- return query.Where(o =>
- o.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(ol => ol.MultipleOptionId == o.Id && scopedLocationIds.Contains(ol.LocationId))
- .Any());
- }
-
private async Task> BuildMultipleOptionScopeMapAsync(
List entities)
{
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
index 1e96ce0..2a21745 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
@@ -43,7 +43,7 @@ public class LabelTypeAppService : ApplicationService, ILabelTypeAppService
query = await LabelEntityPartnerScopeHelper.ApplyTypePartnerListFilterAsync(
_dbContext.SqlSugarClient, query, scopedPartnerIds);
- query = ApplyLabelTypeScopeFilter(query, scopedLocationIds);
+ query = LabelEntityListScopeHelper.ApplyTypeLocationAvailabilityFilter(query, scopedLocationIds);
if (!string.IsNullOrWhiteSpace(input.Sorting))
{
@@ -346,27 +346,6 @@ public class LabelTypeAppService : ApplicationService, ILabelTypeAppService
return merged.OrderBy(x => x, StringComparer.Ordinal).ToList();
}
- private static ISugarQueryable ApplyLabelTypeScopeFilter(
- ISugarQueryable query,
- List? scopedLocationIds)
- {
- if (scopedLocationIds is null)
- {
- return query;
- }
-
- if (scopedLocationIds.Count == 0)
- {
- return query.Where(t => t.AvailabilityType == "ALL");
- }
-
- return query.Where(t =>
- t.AvailabilityType == "ALL" ||
- SqlFunc.Subqueryable()
- .Where(tl => tl.LabelTypeId == t.Id && scopedLocationIds.Contains(tl.LocationId))
- .Any());
- }
-
private async Task SaveTypeLocationsAsync(
string labelTypeId,
string availabilityType,
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
index b7e76ab..08d3c64 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppAuthAppService.cs
@@ -161,7 +161,7 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
}
var list = await LoadBoundLocationsAsync(CurrentUser.Id.Value);
- if (ReportsRoleHelper.IsAdminRole(CurrentUser))
+ if (await UsAppAuthScopeHelper.CanUseAdminScopeApisAsync(_dbContext.SqlSugarClient, CurrentUser))
{
var cached = await UsAppAuthScopeHelper.GetAdminScopeCacheAsync(
_distributedCache,
@@ -180,39 +180,40 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
///
[Authorize]
+ [HttpGet("us-app-auth/admin-scope-companies")]
public virtual async Task> GetAdminScopeCompaniesAsync()
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListCompaniesAsync(_dbContext.SqlSugarClient);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetCompaniesAsync(CurrentUser, _dbContext);
}
///
[Authorize]
- public virtual async Task> GetAdminScopeRegionsAsync(string partnerId)
+ [HttpGet("us-app-auth/admin-scope-regions")]
+ public virtual async Task> GetAdminScopeRegionsAsync([FromQuery] string partnerId)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListRegionsAsync(_dbContext.SqlSugarClient, partnerId);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetRegionsAsync(CurrentUser, _dbContext, partnerId);
}
///
[Authorize]
+ [HttpGet("us-app-auth/admin-scope-locations")]
public virtual async Task> GetAdminScopeLocationsAsync(
- string partnerId,
- string groupId)
+ [FromQuery] string partnerId,
+ [FromQuery] string groupId)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
- return await UsAppAuthScopeHelper.ListLocationsAsync(
- _dbContext.SqlSugarClient,
- partnerId,
- groupId);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
+ return await AuthScopeQueryHelper.GetLocationsAsync(CurrentUser, _dbContext, partnerId, groupId);
}
///
[Authorize]
+ [HttpPost("us-app-auth/select-admin-scope-location")]
public virtual async Task SelectAdminScopeLocationAsync(
AuthScopeSelectLocationInputVo input)
{
- UsAppAuthScopeHelper.EnsureAdminAppToken(CurrentUser);
+ await UsAppAuthScopeHelper.EnsureAppScopeCallerAsync(_dbContext.SqlSugarClient, CurrentUser);
if (!CurrentUser.Id.HasValue)
{
throw new UserFriendlyException("用户未登录");
@@ -221,6 +222,7 @@ public class UsAppAuthAppService : ApplicationService, IUsAppAuthAppService
return await UsAppAuthScopeHelper.SelectLocationAsync(
_dbContext.SqlSugarClient,
_distributedCache,
+ CurrentUser,
CurrentUser.Id.Value,
new UsAppSelectAdminScopeLocationInputVo
{
diff --git a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
index 273af31..2227bcf 100644
--- a/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
+++ b/美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/UsAppLabelingAppService.cs
@@ -364,11 +364,13 @@ public class UsAppLabelingAppService : ApplicationService, IUsAppLabelingAppServ
}
var labelRow = await _dbContext.SqlSugarClient
- .Queryable(
- (l, c, t, tpl) => l.LabelCategoryId == c.Id && l.LabelTypeId == t.Id && l.TemplateId == tpl.Id)
+ .Queryable()
+ .InnerJoin((l, c) => l.LabelCategoryId == c.Id)
+ .LeftJoin((l, c, t) => l.LabelTypeId == t.Id)
+ .InnerJoin((l, c, t, tpl) => l.TemplateId == tpl.Id)
.Where((l, c, t, tpl) => !l.IsDeleted && l.State)
.Where((l, c, t, tpl) => !c.IsDeleted && c.State)
- .Where((l, c, t, tpl) => !t.IsDeleted && t.State)
+ .Where((l, c, t, tpl) => t.Id == null || (!t.IsDeleted && t.State))
.Where((l, c, t, tpl) => !tpl.IsDeleted)
.Where((l, c, t, tpl) => l.LabelCode == labelCode)
.Select((l, c, t, tpl) => new
@@ -551,10 +553,11 @@ public class UsAppLabelingAppService : ApplicationService, IUsAppLabelingAppServ
// 校验 label + location,并补齐一些顶部字段用于任务表落库
var labelRow = await _dbContext.SqlSugarClient
- .Queryable(
- (l, t, tpl) => l.LabelTypeId == t.Id && l.TemplateId == tpl.Id)
+ .Queryable()
+ .LeftJoin((l, t) => l.LabelTypeId == t.Id)
+ .InnerJoin((l, t, tpl) => l.TemplateId == tpl.Id)
.Where((l, t, tpl) => !l.IsDeleted && l.State)
- .Where((l, t, tpl) => !t.IsDeleted && t.State)
+ .Where((l, t, tpl) => t.Id == null || (!t.IsDeleted && t.State))
.Where((l, t, tpl) => !tpl.IsDeleted)
.Where((l, t, tpl) => l.LabelCode == labelCode)
.Select((l, t, tpl) => new
diff --git a/美国版/Food Labeling Management Platform/src/services/labelCategoryService.ts b/美国版/Food Labeling Management Platform/src/services/labelCategoryService.ts
index 64149d2..c5c5abc 100644
--- a/美国版/Food Labeling Management Platform/src/services/labelCategoryService.ts
+++ b/美国版/Food Labeling Management Platform/src/services/labelCategoryService.ts
@@ -49,6 +49,8 @@ function normalizeLabelCategoryDto(raw: unknown): LabelCategoryDto {
? Number(orderRaw)
: null;
const companyRaw = r.company ?? r.Company;
+ const regionRaw = r.region ?? r.Region;
+ const locationRaw = r.location ?? r.Location;
return {
...(r as object),
id: String(r.id ?? r.Id ?? ""),
@@ -60,6 +62,8 @@ function normalizeLabelCategoryDto(raw: unknown): LabelCategoryDto {
regionIds: groupIds,
locationIds,
company: typeof companyRaw === "string" ? companyRaw : null,
+ region: typeof regionRaw === "string" ? regionRaw : null,
+ location: typeof locationRaw === "string" ? locationRaw : null,
noOfLabels,
orderNum,
} as LabelCategoryDto;
--
libgit2 0.21.4