Browse Source

fix(post): hide stale deleted user ids in post view dialog

Omit redundant field labels and exclude soft-deleted users from post bindings.

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 3 months ago
parent
commit
19c6d06fa0

+ 31 - 9
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,

+ 1 - 1
web-admin/src/components/business/system-view-dialog/index.vue

@@ -112,7 +112,7 @@
                 class="view-kv"
                 :class="{ 'view-kv-span-2': field.span }"
               >
-                <dt>{{ field.label }}</dt>
+                <dt v-if="field.label">{{ field.label }}</dt>
                 <dd>
                   <el-tag v-if="field.tagType" :type="field.tagType" size="small">{{
                     formatViewValue(field.value)

+ 10 - 6
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)
     }