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/公司租户库登录。 ///