diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/seed_host_platform_menus.sql b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/seed_host_platform_menus.sql
new file mode 100644
index 0000000..8645253
--- /dev/null
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/scripts/seed_host_platform_menus.sql
@@ -0,0 +1,103 @@
+-- 泰额版平台级菜单:清空 antis-foodlabeling-host.menu 后按前端路由表重录
+-- 使用稳定 Id(f001*),保证 rolemenu 等引用不失效
+-- MenuSource=0(Ruoyi),平台目录 MenuType=0,页面 MenuType=1
+
+SET NAMES utf8mb4;
+START TRANSACTION;
+
+DELETE FROM menu;
+
+INSERT INTO menu (
+ Id, IsDeleted, CreationTime, CreatorId, LastModifierId, LastModificationTime,
+ OrderNum, State, MenuName, RouterName, MenuType, PermissionCode, ParentId,
+ MenuIcon, Router, IsLink, IsCache, IsShow, Remark, Component, MenuSource, Query, ConcurrencyStamp
+) VALUES
+-- 首页概览
+('f0010001-0001-4000-8000-000000000001', 0, NOW(), NULL, NULL, NULL,
+ -1, 1, '首页概览', 'FoodLabelingDashboard', 1, 'menu.dashboard.analytics', '0',
+ 'lucide:layout-dashboard', '/analytics', 0, 0, 1, NULL, '/food-labeling/dashboard/index', 0, NULL, ''),
+
+-- 平台管理
+('f0010002-0001-4000-8000-000000000002', 0, NOW(), NULL, NULL, NULL,
+ 5, 1, '平台管理', 'FoodLabelingPlatform', 0, 'menu.platform', '0',
+ 'lucide:cloud-cog', '/platform', 0, 0, 1, NULL, NULL, 0, NULL, ''),
+('f0010003-0001-4000-8000-000000000003', 0, NOW(), NULL, NULL, NULL,
+ 6, 1, 'SAAS 公司', 'FoodLabelingPlatformTenants', 1, 'menu.platform.tenants', 'f0010002-0001-4000-8000-000000000002',
+ 'lucide:building', '/platform/tenants', 0, 0, 1, NULL, '/food-labeling/platform/tenants/index', 0, NULL, ''),
+
+-- 标签管理
+('f0010010-0001-4000-8000-000000000010', 0, NOW(), NULL, NULL, NULL,
+ 10, 1, '标签管理', 'FoodLabelingLabeling', 0, 'menu.labeling', '0',
+ 'lucide:tags', '/labeling', 0, 0, 1, NULL, NULL, 0, NULL, ''),
+('f0010011-0001-4000-8000-000000000011', 0, NOW(), NULL, NULL, NULL,
+ 11, 1, '标签', 'FoodLabelingLabels', 1, 'menu.labeling.labels', 'f0010010-0001-4000-8000-000000000010',
+ 'lucide:tag', '/labels', 0, 0, 1, NULL, '/food-labeling/labeling/labels/index', 0, NULL, ''),
+('f0010012-0001-4000-8000-000000000012', 0, NOW(), NULL, NULL, NULL,
+ 12, 1, '标签分类', 'FoodLabelingLabelCategories', 1, 'menu.labeling.categories', 'f0010010-0001-4000-8000-000000000010',
+ 'lucide:folder-tree', '/label-categories', 0, 0, 1, NULL, '/food-labeling/labeling/label-categories/index', 0, NULL, ''),
+('f0010013-0001-4000-8000-000000000013', 0, NOW(), NULL, NULL, NULL,
+ 13, 1, '标签类型', 'FoodLabelingLabelTypes', 1, 'menu.labeling.types', 'f0010010-0001-4000-8000-000000000010',
+ 'lucide:layers', '/label-types', 0, 0, 1, NULL, '/food-labeling/labeling/label-types/index', 0, NULL, ''),
+('f0010014-0001-4000-8000-000000000014', 0, NOW(), NULL, NULL, NULL,
+ 14, 1, '标签模板', 'FoodLabelingLabelTemplates', 1, 'menu.labeling.templates', 'f0010010-0001-4000-8000-000000000010',
+ 'lucide:layout-template', '/label-templates', 0, 0, 1, NULL, '/food-labeling/labeling/label-templates/index', 0, NULL, ''),
+('f0010015-0001-4000-8000-000000000015', 0, NOW(), NULL, NULL, NULL,
+ 15, 1, '多选选项集', 'FoodLabelingMultipleOptions', 1, 'menu.labeling.multiple-options', 'f0010010-0001-4000-8000-000000000010',
+ 'lucide:list-checks', '/multiple-options', 0, 0, 1, NULL, '/food-labeling/labeling/multiple-options/index', 0, NULL, ''),
+
+-- 业务模块
+('f0010020-0001-4000-8000-000000000020', 0, NOW(), NULL, NULL, NULL,
+ 15, 1, '业务模块', 'FoodLabelingModules', 0, 'menu.modules', '0',
+ 'lucide:boxes', '/modules', 0, 0, 1, NULL, NULL, 0, NULL, ''),
+('f0010021-0001-4000-8000-000000000021', 0, NOW(), NULL, NULL, NULL,
+ 16, 1, '培训', 'FoodLabelingTraining', 1, 'menu.modules.training', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:graduation-cap', '/training', 0, 0, 1, NULL, '/food-labeling/modules/training/index', 0, NULL, ''),
+('f0010022-0001-4000-8000-000000000022', 0, NOW(), NULL, NULL, NULL,
+ 17, 1, '告警', 'FoodLabelingAlerts', 1, 'menu.modules.alerts', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:bell', '/alerts', 0, 0, 1, NULL, '/food-labeling/modules/alerts/index', 0, NULL, ''),
+('f0010023-0001-4000-8000-000000000023', 0, NOW(), NULL, NULL, NULL,
+ 18, 1, '任务', 'FoodLabelingTasks', 1, 'menu.modules.tasks', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:list-todo', '/tasks', 0, 0, 1, NULL, '/food-labeling/modules/tasks/index', 0, NULL, ''),
+('f0010024-0001-4000-8000-000000000024', 0, NOW(), NULL, NULL, NULL,
+ 19, 1, '传感器', 'FoodLabelingSensors', 1, 'menu.modules.sensors', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:activity', '/sensors', 0, 0, 1, NULL, '/food-labeling/modules/sensors/index', 0, NULL, ''),
+('f0010025-0001-4000-8000-000000000025', 0, NOW(), NULL, NULL, NULL,
+ 20, 1, '食物浪费', 'FoodLabelingFoodWaste', 1, 'menu.modules.food-waste', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:apple', '/food-waste', 0, 0, 1, NULL, '/food-labeling/modules/food-waste/index', 0, NULL, ''),
+('f0010026-0001-4000-8000-000000000026', 0, NOW(), NULL, NULL, NULL,
+ 21, 1, '电子标签', 'FoodLabelingELabelModule', 1, 'menu.modules.e-label', 'f0010020-0001-4000-8000-000000000020',
+ 'lucide:file-digit', '/e-label-module', 0, 0, 1, NULL, '/food-labeling/modules/e-label/index', 0, NULL, ''),
+
+-- 管理
+('f0010030-0001-4000-8000-000000000030', 0, NOW(), NULL, NULL, NULL,
+ 20, 1, '管理', 'FoodLabelingManagement', 0, 'menu.management', '0',
+ 'lucide:building-2', '/management', 0, 0, 1, NULL, NULL, 0, NULL, ''),
+('f0010031-0001-4000-8000-000000000031', 0, NOW(), NULL, NULL, NULL,
+ 21, 1, '账户管理', 'FoodLabelingAccountManagement', 1, 'menu.management.account', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:users', '/account-management', 0, 0, 1, NULL, '/food-labeling/management/account-management/index', 0, NULL, ''),
+('f0010032-0001-4000-8000-000000000032', 0, NOW(), NULL, NULL, NULL,
+ 22, 1, '系统菜单', 'FoodLabelingSystemMenu', 1, 'menu.management.system-menu', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:menu-square', '/system-menu', 0, 0, 1, NULL, '/food-labeling/management/system-menu/index', 0, NULL, ''),
+('f0010033-0001-4000-8000-000000000033', 0, NOW(), NULL, NULL, NULL,
+ 23, 1, '菜单管理', 'FoodLabelingMenuManagement', 1, 'menu.management.menu', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:utensils', '/menu-management', 0, 0, 1, NULL, '/food-labeling/management/menu-management/index', 0, NULL, ''),
+('f0010034-0001-4000-8000-000000000034', 0, NOW(), NULL, NULL, NULL,
+ 24, 1, '设备', 'FoodLabelingDevices', 1, 'menu.management.devices', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:smartphone', '/devices', 0, 0, 1, NULL, '/food-labeling/modules/devices/index', 0, NULL, ''),
+('f0010035-0001-4000-8000-000000000035', 0, NOW(), NULL, NULL, NULL,
+ 25, 1, '报表', 'FoodLabelingReports', 1, 'menu.management.reports', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:file-bar-chart', '/reports', 0, 0, 1, NULL, '/food-labeling/management/reports/index', 0, NULL, ''),
+('f0010036-0001-4000-8000-000000000036', 0, NOW(), NULL, NULL, NULL,
+ 26, 1, '发票', 'FoodLabelingInvoices', 1, 'menu.management.invoices', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:receipt', '/invoices', 0, 0, 1, NULL, '/food-labeling/modules/invoices/index', 0, NULL, ''),
+('f0010037-0001-4000-8000-000000000037', 0, NOW(), NULL, NULL, NULL,
+ 27, 1, '二维码', 'FoodLabelingQrCodes', 1, 'menu.management.qr-codes', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:qr-code', '/qr-codes', 0, 0, 1, NULL, '/food-labeling/modules/qr-codes/index', 0, NULL, ''),
+('f0010038-0001-4000-8000-000000000038', 0, NOW(), NULL, NULL, NULL,
+ 28, 1, '支持', 'FoodLabelingSupport', 1, 'menu.management.support', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:life-buoy', '/support', 0, 0, 1, NULL, '/food-labeling/management/support/index', 0, NULL, ''),
+('f0010039-0001-4000-8000-000000000039', 0, NOW(), NULL, NULL, NULL,
+ 29, 1, 'API', 'FoodLabelingApi', 1, 'menu.management.api', 'f0010030-0001-4000-8000-000000000030',
+ 'lucide:code-2', '/api-settings', 0, 0, 1, NULL, '/food-labeling/modules/api/index', 0, NULL, '');
+
+COMMIT;
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/MultiTenancy/ThWebPlatformLoginHelper.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/MultiTenancy/ThWebPlatformLoginHelper.cs
index 8bd922a..eaccce7 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/MultiTenancy/ThWebPlatformLoginHelper.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/MultiTenancy/ThWebPlatformLoginHelper.cs
@@ -14,6 +14,16 @@ public static class ThWebPlatformLoginHelper
/// 平台登录成功时 th-web-auth 返回的 tenantName(无 TenantId Claim)
public const string PlatformTenantDisplayName = "Platform";
+ /// 平台账号误选业务租户时的登录拒绝提示
+ public const string PlatformAccountMustUseDefaultMessage =
+ "登录失败:平台管理员账号请选择 Default 选项登录,不能使用业务租户登录";
+
+ ///
+ /// 是否为业务租户登录(选了具体公司,而非 Default / 空 tenantId)
+ ///
+ public static bool IsBusinessTenantLogin(Guid? tenantId, string? tenantName)
+ => !ShouldTryPlatformLogin(tenantId, tenantName);
+
///
/// 是否应优先尝试主库平台登录(与前端选 Default / 空 tenantId 一致)
///
diff --git a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/Services/ThWebAuthAppService.cs b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/Services/ThWebAuthAppService.cs
index 4b9ef60..afc01a1 100644
--- a/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/Services/ThWebAuthAppService.cs
+++ b/泰额版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling/FoodLabeling.Th.Application/Services/ThWebAuthAppService.cs
@@ -49,7 +49,8 @@ public class ThWebAuthAppService : ApplicationService, IThWebAuthAppService
/// 校验租户后在租户独立库验证账号,签发含 TenantId 与 RBAC 权限的 JWT。
///
/// 泰额 H5 与公司 Web 共用此接口。选 **Default** 或 tenantId 为空时,若邮箱账号存在于主库则走**平台登录**(JWT 无 TenantId);
- /// 选具体公司 tenantId 时在该公司业务库校验。Default 业务库(如 US)仅在主库无该邮箱时作为回落。
+ /// 选具体公司 tenantId 时在该公司业务库校验;若账号已存在于主库(平台管理员),则拒绝登录并提示改用 Default。
+ /// Default 业务库(如 US)仅在主库无该邮箱时作为回落。
///
/// 示例请求(平台,选 Default):
/// ```json
@@ -97,6 +98,10 @@ public class ThWebAuthAppService : ApplicationService, IThWebAuthAppService
input.TenantId = ThWebPlatformLoginHelper.DefaultTenantId;
}
}
+ else
+ {
+ await EnsureNotHostPlatformAccountAsync(input.UserName);
+ }
TenantConfiguration tenantConfig;
try
@@ -157,6 +162,26 @@ public class ThWebAuthAppService : ApplicationService, IThWebAuthAppService
}
///
+ /// 业务租户登录前校验:主库已存在的账号(平台管理员)不得落入公司业务库。
+ ///
+ private async Task EnsureNotHostPlatformAccountAsync(string userName)
+ {
+ if (string.IsNullOrWhiteSpace(userName))
+ {
+ return;
+ }
+
+ using (CurrentTenant.Change(null))
+ {
+ var hostUser = await FindActiveUserByEmailAsync(userName.Trim());
+ if (hostUser != null)
+ {
+ throw new UserFriendlyException(ThWebPlatformLoginHelper.PlatformAccountMustUseDefaultMessage);
+ }
+ }
+ }
+
+ ///
/// 主库平台登录:CurrentTenant 为空签发无 TenantId 的 JWT,供 Vue3Router/vben5 使用。
/// 主库无对应邮箱用户时返回 null,由调用方回落 Default/公司租户库登录。
///