Przeglądaj źródła

fix(system): 修复编辑用户时租户角色/职位被过滤为空的问题

- RoleOutput.tenantId 改为 TenantId(long?) 以正确映射 SqlSugar 租户字段,避免默认 0 被前端租户过滤误删
- editUser.vue 角色/职位从全量列表按 tenantId 重滤,避免多次打开弹窗渐进滤空
- chore: bump version Web 2.4.243 / server 1.0.241
skygu 2 tygodni temu
rodzic
commit
088d5da341

+ 1 - 1
Web/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "admin.net",
   "name": "admin.net",
   "type": "module",
   "type": "module",
-  "version": "2.4.253",
+  "version": "2.4.254",
   "packageManager": "pnpm@10.32.1",
   "packageManager": "pnpm@10.32.1",
   "lastBuildTime": "2026.03.15",
   "lastBuildTime": "2026.03.15",
   "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
   "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",

+ 15 - 7
Web/src/views/system/user/component/editUser.vue

@@ -250,19 +250,26 @@ const state = reactive({
 	selectedTabName: '0', // 选中的 tab 页
 	selectedTabName: '0', // 选中的 tab 页
 	orgTreeData: [] as Array<OrgTreeOutput>,
 	orgTreeData: [] as Array<OrgTreeOutput>,
 	ruleForm: {} as UpdateUserInput,
 	ruleForm: {} as UpdateUserInput,
-	posData: [] as Array<SysPos>, // 职位数据
-	roleData: [] as Array<RoleOutput>, // 角色数据
+	posData: [] as Array<SysPos>, // 职位数据(当前弹窗过滤后)
+	allPosData: [] as Array<SysPos>, // 全量职位(避免多次打开弹窗把列表滤空)
+	roleData: [] as Array<RoleOutput>, // 角色数据(当前弹窗过滤后)
+	allRoleData: [] as Array<RoleOutput>, // 全量角色
 	languages: [] as any[], // 语言数据
 	languages: [] as any[], // 语言数据
 });
 });
 // 级联选择器配置选项
 // 级联选择器配置选项
 const cascaderProps = { checkStrictly: true, emitPath: false, value: 'id', label: 'name', expandTrigger: 'hover' };
 const cascaderProps = { checkStrictly: true, emitPath: false, value: 'id', label: 'name', expandTrigger: 'hover' };
 
 
+/** 雪花 Id 可能是 number/string,严格 === 会导致租户过滤后列表为空 */
+const sameTenantId = (a: any, b: any) => a != null && b != null && String(a) === String(b);
+
 onMounted(async () => {
 onMounted(async () => {
 	state.loading = true;
 	state.loading = true;
 	var res = await getAPI(SysPosApi).apiSysPosListGet();
 	var res = await getAPI(SysPosApi).apiSysPosListGet();
-	state.posData = res.data.result ?? [];
+	state.allPosData = res.data.result ?? [];
+	state.posData = state.allPosData;
 	var res1 = await getAPI(SysRoleApi).apiSysRoleListGet();
 	var res1 = await getAPI(SysRoleApi).apiSysRoleListGet();
-	state.roleData = res1.data.result ?? [];
+	state.allRoleData = res1.data.result ?? [];
+	state.roleData = state.allRoleData;
 	if (langStore.languages.length === 0) {
 	if (langStore.languages.length === 0) {
         await langStore.loadLanguages();
         await langStore.loadLanguages();
     }
     }
@@ -272,9 +279,10 @@ onMounted(async () => {
 
 
 // 打开弹窗
 // 打开弹窗
 const openDialog = async (row: any) => {
 const openDialog = async (row: any) => {
-	state.orgTreeData = (row.tenantId ? props.orgTreeData?.filter((e) => e.tenantId === row.tenantId) : props.orgTreeData) ?? [];
-	state.posData = (row.tenantId ? state.posData?.filter((e) => e.tenantId === row.tenantId) : state.posData) ?? [];
-	state.roleData = (row.tenantId ? state.roleData?.filter((e) => e.tenantId === row.tenantId) : state.roleData) ?? [];
+	// 每次从全量重滤,避免上次按其他租户过滤后残留空列表
+	state.orgTreeData = (row.tenantId ? props.orgTreeData?.filter((e) => sameTenantId(e.tenantId, row.tenantId)) : props.orgTreeData) ?? [];
+	state.posData = (row.tenantId ? state.allPosData?.filter((e) => sameTenantId(e.tenantId, row.tenantId)) : state.allPosData) ?? [];
+	state.roleData = (row.tenantId ? state.allRoleData?.filter((e) => sameTenantId(e.tenantId, row.tenantId)) : state.allRoleData) ?? [];
 	ruleFormRef.value?.resetFields();
 	ruleFormRef.value?.resetFields();
 	state.selectedTabName = '0'; // 重置为第一个 tab 页
 	state.selectedTabName = '0'; // 重置为第一个 tab 页
 	state.ruleForm = JSON.parse(JSON.stringify(row));
 	state.ruleForm = JSON.parse(JSON.stringify(row));

+ 3 - 3
server/Admin.NET.Core/Service/Role/Dto/RoleOutput.cs

@@ -1,4 +1,4 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
 //
 //
 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
 //
 //
@@ -27,7 +27,7 @@ public class RoleOutput
     public string Code { get; set; }
     public string Code { get; set; }
 
 
     /// <summary>
     /// <summary>
-    /// 租户Id
+    /// 租户Id(须与实体 TenantId 同名,否则 Select&lt;RoleOutput&gt; 映射为 0,账号编辑按租户过滤后角色列表为空)
     /// </summary>
     /// </summary>
-    public long tenantId { get; set; }
+    public long? TenantId { get; set; }
 }
 }

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET ͨ��Ȩ�޿���ƽ̨</Description>
     <Description>Admin.NET ͨ��Ȩ�޿���ƽ̨</Description>
-    <AssemblyVersion>1.0.251</AssemblyVersion>
-    <FileVersion>1.0.251</FileVersion>
-    <Version>1.0.251</Version>
+    <AssemblyVersion>1.0.252</AssemblyVersion>
+    <FileVersion>1.0.252</FileVersion>
+    <Version>1.0.252</Version>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>