You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将后端权限数据按分组渲染,实现单标题下多选框聚合展示

权限分组渲染解决方案

问题场景

从后端拿到的权限数据包含group字段(部分数据可能没有),当前循环渲染时每个权限项都会重复显示分组名称,需要实现每个分组只显示一次标题,下方聚合展示该组所有权限复选框的效果。

后端返回数据示例

[
  {
    id: 54,
    name: "agent_read_all",
    description: null,
    displayName: "Read all",
    group: "Admin - Agent",
  },
  {
    id: 55,
    name: "agent_read",
    description: "Fetch single record",
    displayName: "Read",
  },
  {
    id: 56,
    name: "agent_create",
    description: null,
    displayName: "Create",
    group: "Admin - Agent",
  },
  {
    id: 57,
    name: "agent_update",
    description: null,
    displayName: "Update",
    group: "Admin - Agent",
  },
  {
    id: 62,
    name: "candidate_upload_batch_read_all",
    description: null,
    displayName: "Read all",
  },
];

当前问题代码

<b>Permissions Section</b>;
{
  Object.keys(permissions).map((item, index) => (
    <>
      <List style={{ display: "flex" }}>
        <p>{permissions[item].group}</p>
        <FormGroup>
          <FormControlLabel
            control={
              <Checkbox
                checked={uroleData.permissions[index] ? true : false}
                value={roleData.permissionId}
                onChange={(e) => {
                  if (e.target.checked) {
                    checkedp.push(permissions[item].id);
                    setRoleData({ ...roleData, permissionId: checkedp });
                  } else {
                    roleData.permissionId.splice(
                      checkedp.indexOf(e.target.value),
                      1
                    );
                  }
                  // console.log(roleData);
                }}
              />
            }
            label={permissions[item].displayName}
          />
        </FormGroup>
      </List>
    </>
  ));
}

解决步骤

1. 先对权限数据按分组聚合

用Array.reduce()把原始数据转换成以分组名为键,对应权限数组为值的对象,没有group字段的项统一归到「未分组权限」组:

// 处理权限数据,按group分组
const groupedPermissions = permissions.reduce((acc, permission) => {
  // 给无group的项分配默认分组名
  const groupName = permission.group || "未分组权限";
  if (!acc[groupName]) {
    acc[groupName] = [];
  }
  acc[groupName].push(permission);
  return acc;
}, {});

2. 修改渲染逻辑

循环分组后的对象,每个分组先渲染标题,再循环该组内的权限项渲染复选框。同时修正选中状态判断和勾选逻辑(原来的index判断不可靠,改成按权限ID匹配):

<b>Permissions Section</b>
{/* 循环分组后的权限数据 */}
{Object.entries(groupedPermissions).map(([groupName, permissionsInGroup]) => (
  <div key={groupName}>
    {/* 渲染分组标题 */}
    <h4>{groupName}</h4>
    {/* 渲染当前分组下的所有权限复选框 */}
    {permissionsInGroup.map((permission) => {
      // 判断当前权限是否被选中
      const isChecked = roleData.permissionId.includes(permission.id);
      return (
        <List style={{ display: "flex" }} key={permission.id}>
          <FormGroup>
            <FormControlLabel
              control={
                <Checkbox
                  checked={isChecked}
                  value={permission.id}
                  onChange={(e) => {
                    let updatedPermissions;
                    if (e.target.checked) {
                      // 勾选时添加权限ID
                      updatedPermissions = [...roleData.permissionId, permission.id];
                    } else {
                      // 取消勾选时移除权限ID
                      updatedPermissions = roleData.permissionId.filter(id => id !== permission.id);
                    }
                    setRoleData({ ...roleData, permissionId: updatedPermissions });
                  }}
                />
              }
              label={permission.displayName}
            />
          </FormGroup>
        </List>
      );
    })}
  </div>
))}

关键优化点

  • 用reduce聚合数据,避免重复渲染分组标题
  • 选中状态改为通过权限ID判断,不再依赖数组索引,避免数据排序变化导致的错误
  • 勾选逻辑采用不可变更新方式(扩展运算符、filter),避免直接修改state数组引发的问题

内容的提问来源于stack exchange,提问作者Navnath kumbhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:01:07