diff --git a/backend/app/crud/user.py b/backend/app/crud/user.py index b728dd02..d57d5050 100644 --- a/backend/app/crud/user.py +++ b/backend/app/crud/user.py @@ -167,6 +167,13 @@ def set_user_post_ids_only( def list_user_ids_bound_to_post(db: Session, post_id: str, tenant_no: str) -> List[str]: rows = ( db.query(SysUserPost.user_id) + .join( + SysUser, + and_( + SysUser.id == SysUserPost.user_id, + SysUser.del_flag == 0, + ), + ) .filter( and_( SysUserPost.post_id == post_id, @@ -250,6 +257,12 @@ def sync_post_user_bindings( def get_user_with_relations(db: Session, user_id: str) -> Optional[Dict[str, Any]]: + from app.services.web_auth_roles import ( + get_effective_role_ids, + get_post_inherited_role_ids, + get_role_names_by_ids, + ) + u = get_user(db, user_id) if not u: return None @@ -269,8 +282,13 @@ def get_user_with_relations(db: Session, user_id: str) -> Optional[Dict[str, Any .all() ] post_ids = list_post_ids_for_user(db, user_id) + effective_role_ids = get_effective_role_ids(db, user_id) + post_inherited_role_ids = get_post_inherited_role_ids(db, user_id) d["roleIds"] = role_ids d["postIds"] = post_ids + d["postInheritedRoleIds"] = post_inherited_role_ids + d["effectiveRoleIds"] = effective_role_ids + d["effectiveRoleNames"] = get_role_names_by_ids(db, effective_role_ids) return d @@ -291,16 +309,15 @@ def _replace_associations( role_ids: Optional[List[str]] = None, post_ids: Optional[List[str]] = None, ) -> None: + """全量替换关联。仅当对应参数不为 None 时才替换该侧(避免只改职位时清空直接角色)。""" now = datetime.now() - db.query(SysUserRole).filter( - and_(SysUserRole.user_id == user_id, SysUserRole.del_flag == 0) - ).update({"del_flag": 1, "update_time": now}) - db.query(SysUserPost).filter( - and_(SysUserPost.user_id == user_id, SysUserPost.del_flag == 0) - ).update({"del_flag": 1, "update_time": now}) - - if role_ids: + if role_ids is not None: + db.query(SysUserRole).filter( + and_(SysUserRole.user_id == user_id, SysUserRole.del_flag == 0) + ).update({"del_flag": 1, "update_time": now}) for rid in role_ids: + if not rid: + continue db.add(SysUserRole( id=generate_uuid(), user_id=user_id, @@ -316,8 +333,13 @@ def _replace_associations( del_flag=0, )) - if post_ids: + if post_ids is not None: + db.query(SysUserPost).filter( + and_(SysUserPost.user_id == user_id, SysUserPost.del_flag == 0) + ).update({"del_flag": 1, "update_time": now}) for pid in post_ids: + if not pid: + continue db.add(SysUserPost( id=generate_uuid(), user_id=user_id, diff --git a/web-admin/src/components/business/system-view-dialog/index.vue b/web-admin/src/components/business/system-view-dialog/index.vue index fe8a798d..d892d510 100644 --- a/web-admin/src/components/business/system-view-dialog/index.vue +++ b/web-admin/src/components/business/system-view-dialog/index.vue @@ -112,7 +112,7 @@ class="view-kv" :class="{ 'view-kv-span-2': field.span }" > -
{{ field.label }}
+
{{ field.label }}
{{ formatViewValue(field.value) diff --git a/web-admin/src/views/system/post/index.vue b/web-admin/src/views/system/post/index.vue index 71a0dde3..a30f1146 100644 --- a/web-admin/src/views/system/post/index.vue +++ b/web-admin/src/views/system/post/index.vue @@ -493,13 +493,13 @@ if (viewBoundRoleNames.value.length > 0) { sections.push({ title: '关联角色', - fields: [{ label: '已关联角色', value: viewBoundRoleNames.value.join('、'), span: true }] + fields: [{ label: '', value: viewBoundRoleNames.value.join('、'), span: true }] }) } if (viewBoundUserNames.value.length > 0) { sections.push({ title: '关联用户', - fields: [{ label: '已关联用户', value: viewBoundUserNames.value.join('、'), span: true }] + fields: [{ label: '', value: viewBoundUserNames.value.join('、'), span: true }] }) } return sections @@ -518,15 +518,19 @@ if (roleIds.length > 0) { const roleListRes = await fetchRoleList({ page: 1, pageSize: 100 }) const idToName = new Map( - (roleListRes?.list || []).map((r: any) => [r.id, r.roleName || r.id]) + (roleListRes?.list || []).map((r: any) => [r.id, r.roleName || '']) ) - viewBoundRoleNames.value = roleIds.map((id: string) => idToName.get(id) || id) + viewBoundRoleNames.value = roleIds + .map((id: string) => idToName.get(id) || '') + .filter((name: string) => Boolean(name)) } const boundIds = boundRes?.userIds || [] if (boundIds.length === 0) return const users = await fetchAllUsersForPostBind() - const idToName = new Map(users.map((u) => [u.id, u.nickName || u.userNo || u.id])) - viewBoundUserNames.value = boundIds.map((id: string) => idToName.get(id) || id) + const idToName = new Map(users.map((u) => [u.id, u.nickName || u.userNo || ''])) + viewBoundUserNames.value = boundIds + .map((id: string) => idToName.get(id) || '') + .filter((name: string) => Boolean(name)) } catch (e) { console.error('加载职位关联信息失败:', e) }