Skip to content

Latest commit

 

History

History
613 lines (581 loc) · 40 KB

File metadata and controls

613 lines (581 loc) · 40 KB

角色管理页 roleManagement

本文档是 KE04-example-permission--auth-and-rbac.md 的拆分文件

- **示例代码来源**:下文示例代码均从官方示例中抽取。 - **复用原则**:生成角色管理页面时若有疑问,应优先直接复用本示例中的写法(变量命名、API 调用顺序、组件配置等),避免自行发挥。

角色管理页 roleManagement

前端视图:角色 CRUD + 角色成员管理 + 角色权限管理

生成要点:布局为左侧角色列表 + 右侧详情 Tab;必须使用下方示例中的 Logic(见下表),禁止用 FROM/PAGINATE 替代;$Viewauthtrue

**必须确保删除、编辑、创建角色功能完整可用,权限关联和人员管理功能稳定**:生成角色管理页面时,必须严格按照以下关键流程实现,禁止遗漏关键步骤。

布局与实现约束(必须遵守)

- **布局**:必须与下方示例一致——**左侧约 20% 角色列表**(无表头 ElTable + 创建角色按钮 + 行内修改/删除 Popover),**右侧约 80% 角色详情**(标题区 + ElTabs:人员管理 | 功能权限)。**禁止**改为「顶部查询区 + 单表 + 下方详情卡」的布局。 - **Logic**:必须使用下方示例中的 Logic,**禁止**用 `FROM`/`PAGINATE` 等替代。对应关系见下表。 - **$View**:`auth` 必须为 `true`;`authDescription` 建议与 title 一致。
场景 Logic
角色名列表(唯一性校验) app.logics.LcapGetRoleNameList()
角色表格数据 app.logics.LcapLoadRoleManagementTableView
用户角色表格 app.logics.LcapLoadUserRoleMappingTableView
可添加用户列表 app.logics.LcapLoadAddRoleUserTableView
角色已有权限 app.logics.LcapGetPermissionByRoleId
可添加权限列表 app.logics.LcapLoadAddRolePermissionTableView
移除角色权限 app.logics.LcapGetMappingDeleteByRoleIdAndPermissionId

CRUD 关键流程

操作 关键步骤 代码要点
删除角色 克隆数据 → 打开确认对话框 → 删除实体 → 删除用户角色映射 → 删除角色权限映射 → 重新选择角色 → 刷新所有表格 → 关闭对话框 → 提示成功 deleteRoleBody = nasl.util.Clone(...); LcapRoleEntity.delete(...); LcapUserRoleMappingEntity.deleteBy(...); LcapRolePerMappingEntity.deleteBy(...); selectRole = ...; $refs.el_table_1.reload(); reloadUserTable();
编辑角色 设置 isUpdateRole=true → 重置表单 → 克隆数据 → 保存当前角色名 → 获取角色名列表 → 打开对话框 → 验证表单 → 更新实体 → 更新 selectRole 和 selectRoleId → 刷新表格 → 提示成功 isUpdateRole = true; $refs.el_form_2.resetForm(); inputRole = nasl.util.Clone(...); updateRoleName = ...; getRoleNameList(); LcapRoleEntity.update(...); selectRole = nasl.util.Clone(inputRole); $refs.el_table_1.reload();
创建角色 设置 isUpdateRole=false → 重置表单 → 清空输入 → 获取角色名列表 → 打开对话框 → 验证表单 → 创建实体 → 更新 selectRole 和 selectRoleId → 刷新表格 → 提示成功 isUpdateRole = false; nasl.util.Clear(inputRole, 'shallow'); getRoleNameList(); inputRole = LcapRoleEntity.create(...); selectRole = nasl.util.Clone(inputRole); selectRoleId = inputRole.id;
添加用户 清空待添加列表 → 打开对话框 → 获取可选用户列表 → 选择用户 → 获取用户信息 → 批量创建映射(包含 userName 和 source)→ 刷新用户表格 → 清空待添加列表 → 关闭对话框 → 提示成功 nasl.util.Clear(waitAddRoleUserIdList, 'shallow'); getRoleAddUser(); userList = LcapGetUserByUserIds(...); batchCreate(包含 userName 和 source); reloadUserTable();
移除用户 克隆数据 → 打开确认对话框 → 删除映射 → 清空对象 → 刷新用户表格 → 关闭对话框 → 提示成功 deleteUserRole = nasl.util.Clone(...); LcapUserRoleMappingEntity.delete(...); nasl.util.Clear(deleteUserRole, 'shallow'); reloadUserTable();
添加权限 清空已选列表 → 打开对话框 → 获取可选权限列表 → 选择权限 → 批量创建映射 → 刷新权限表格 → 清空已选列表 → 关闭对话框 → 提示成功 nasl.util.Clear(alreadySelectedPermissionIdList, 'shallow'); getRoleAddPermission(...); batchCreate(LcapRolePerMapping); $refs.el_table_3.reload();
移除权限 克隆数据 → 打开确认对话框 → 调用逻辑删除映射 → 清空对象 → 刷新权限表格 → 关闭对话框 → 提示成功 removePermission = nasl.util.Clone(...); LcapGetMappingDeleteByRoleIdAndPermissionId(...); nasl.util.Clear(removePermission, 'shallow'); $refs.el_table_3.reload();

关键细节

- **角色名称唯一性校验**:创建和编辑时都必须调用 `getRoleNameList()`;编辑时排除当前角色名:`if (isUpdateRole) nasl.util.Remove(roleNameList, updateRoleName);`,表单验证使用 `nasl.validation.unique(roleNameList)` - **删除角色必须删除关联数据**:删除角色前必须先删除用户角色映射和角色权限映射,最后删除角色实体 - **删除角色后重新选择角色**:删除角色后必须重新从角色列表中选择一个角色(或创建空角色),更新 `selectRole` 和 `selectRoleId` - **添加用户必须包含完整信息**:批量创建用户角色映射时,必须包含 `userId`、`roleId`、`userName`、`source` 字段 - **添加用户前获取用户列表**:打开添加用户对话框前必须调用 `getRoleAddUser()` 获取可选用户列表,排除已添加的用户 - **添加权限前获取权限列表**:打开添加权限对话框前必须调用 `getRoleAddPermission()` 获取可选权限列表,排除已添加的权限 - **权限表格数据源**:功能权限表格使用 `loadPermissionByRoleId(1, 999999999)` 加载数据,需要传入分页参数 - **用户表格刷新**:添加/移除用户后必须调用 `reloadUserTable()` 刷新用户表格,该函数会更新 `alreadyAddRoleUserIdList` - **权限表格刷新**:添加/移除权限后必须调用 `$refs.el_table_3.reload()` 刷新权限表格 - **数据克隆**:操作前必须使用 `nasl.util.Clone()` 克隆数据,避免直接修改原始对象 - **清空对象时机**:删除/移除操作成功后必须清空对应的对象(`deleteRoleBody`、`deleteUserRole`、`removePermission`) - **编辑角色后更新选中角色**:编辑成功后必须更新 `selectRole = nasl.util.Clone(inputRole)`,确保右侧详情显示最新数据 - **ElFormTreeSelect**:建议加上 `virtualize={false}`。 - **ElDialog 的 slot 与按钮**:`slotHeader`、`slotFooter` 必须使用 **`(current) =>`** 形式(即带参数的箭头函数),勿使用 `() =>`。弹窗内「确定」「取消」等按钮的 `onClick` 必须使用 **`function click() { ... return; }`** 形式,取消按钮需显式写 **`type=""`**。否则在部分运行时下可能导致取消按钮点击无反应或 `$refs` 未正确绑定。 - **`LcapRole.editable` 的配置位置与仅允许的绑定**:`editable` 定义在实体 `LcapRole` 上,由角色创建来源在数据层维护(标识该角色是否允许修改角色定义),**不在本页表单或属性面板中单独配置**。本页**仅允许**以下用法: - (1)左侧角色列表行内:用 `$if={current.item.lcapRole.editable}` 控制是否展示带「修改 / 删除」的 Popover 入口; - (2)右侧详情区当前选中角色:仅用于功能权限区域,控制「新增功能权限」按钮与「移除该权限」链路的 `disabled={!selectRole.editable}`。 - **明确要求**:人员管理区域(「添加用户」「移除」)**不使用** `editable` 做禁用控制,系统内置角色也必须允许成员增删。 - **禁止**在本页其它位置或任何其它视图用 `editable` 控制禁用/显隐。 $View({ title: '角色管理', description: '角色的创建、编辑、删除及权限分配管理', crumb: '角色管理', auth: true, authDescription: '角色管理', isIndex: false, }) export function roleManagement() { let filterRole: app.dataSources.defaultDS.entities.LcapRole; let inputRole: app.dataSources.defaultDS.entities.LcapRole; let deleteRoleBody: app.dataSources.defaultDS.entities.LcapRole; let updateRoleName: String; let isUpdateRole: Boolean; let selectRole: app.dataSources.defaultDS.entities.LcapRole; let filterUser: app.dataSources.defaultDS.entities.LcapUserRoleMapping; let alreadyAddRoleUserIdList: List; let deleteUserRole: { lcapUserRoleMapping: app.dataSources.defaultDS.entities.LcapUserRoleMapping, lcapRole: app.dataSources.defaultDS.entities.LcapRole }; let waitAddRoleUserIdList: List; let alreadyAddPermissionIdList: List; let removePermission: app.dataSources.defaultDS.entities.LcapPermission; let alreadySelectedPermissionIdList: List; let selectRoleId: Integer; let roleNameList: List; let toastInfo: String; let selectUserList: List<{ lcapUser: app.dataSources.defaultDS.entities.LcapUser }>; let selectPerList: { list: List<{ lcapPermission: app.dataSources.defaultDS.entities.LcapPermission }>, total: Integer }; let userTableData: { list: List<{ lcapUserRoleMapping: app.dataSources.defaultDS.entities.LcapUserRoleMapping, lcapRole: app.dataSources.defaultDS.entities.LcapRole }>, total: Integer };
onCreated(function created() {
    let search = app.logics.LcapLoadRoleManagementTableView(1, 10, 'id', 'asc', filterRole).list;
    if (nasl.util.HasValue(search)) {
        selectRole = nasl.util.ListHead(nasl.util.ListTransform(search, (item) => item.lcapRole));
    } else {
        selectRole = nasl.util.New<app.dataSources.defaultDS.entities.LcapRole>();
    }
    selectRoleId = selectRole.id;
    reloadUserTable();
    $refs.el_table_3.reload();
})

/* 判断角色名称是否重复 */
function getRoleNameList() {
    roleNameList = app.logics.LcapGetRoleNameList();
    if (isUpdateRole) {
        nasl.util.Remove(roleNameList, updateRoleName);
    }
    return;
}

/* 获取已添加的用户角色关联数据 */
function loadUserRoleByUserId(page: Integer = 1, size: Integer = 20, sort: String, order: String): { list: List<{ lcapUserRoleMapping: app.dataSources.defaultDS.entities.LcapUserRoleMapping, lcapRole: app.dataSources.defaultDS.entities.LcapRole }>, total: Integer } {
    filterUser.roleId = selectRole.id;
    let result = app.logics.LcapLoadUserRoleMappingTableView(page, size, sort, order, filterUser);
    alreadyAddRoleUserIdList = nasl.util.ListTransform(result.list, (item) => item.lcapUserRoleMapping.userId);
    return result;
}

/* 刷新角色成员表格 */
function reloadUserTable() {
    userTableData = loadUserRoleByUserId($refs.el_table_2.currentPage, $refs.el_table_2.pageSize, $refs.el_table_2.sort, $refs.el_table_2.order);
}

/* 获取角色添加成员弹窗选择器数据 */
function getRoleAddUser() {
    selectUserList = app.logics.LcapLoadAddRoleUserTableView(alreadyAddRoleUserIdList, selectRole.id);
    nasl.util.ListDistinct(waitAddRoleUserIdList);
}

/* 获取角色对应的权限数据 */
function loadPermissionByRoleId(page: Integer, size: Integer) {
    let result = app.logics.LcapGetPermissionByRoleId(selectRole.id, page, size);
    if (nasl.util.HasValue(result.list)) {
        alreadyAddPermissionIdList = nasl.util.ListTransform(result.list, (item) => item.id);
    } else {
        alreadyAddPermissionIdList = nasl.util.New<List<Integer>>();
    }
    return result;
}

/* 获取新增功能权限弹窗数据 */
function getRoleAddPermission(page: Integer, size: Integer, order: String, sort: String): { list: List<{ lcapPermission: app.dataSources.defaultDS.entities.LcapPermission }>, total: Integer } {
    selectPerList = app.logics.LcapLoadAddRolePermissionTableView(page, size, sort, order, alreadyAddPermissionIdList, selectRole.id);
    return selectPerList;
}


return <>
    <ElFlex direction="horizontal" mode="flex" justify="start" alignment="start" wrap={false} gutter={0}
        style="background-color:#FFF;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:6px;border-bottom-right-radius:6px;margin-bottom:60px;width:100%; box-shadow: 0px 2px 12px rgba(0, 0, 0, .06);">
        {/* 左侧角色列表 */}
        <ElFlex widthStretch="false" mode="flex" wrap={false} direction="vertical" justify="start" gutter={0} alignment="center"
            style="width:20%;border-top-left-radius:6px;border-bottom-left-radius:6px;border-top-right-radius:0px;border-bottom-right-radius:0px;border-right-color:#e5e5e5;border-right-width:1px;border-style:solid;border-top-width:0px;border-left-width:0px;border-bottom-width:0px;height:auto; align-self: stretch;">
            <ElFlex direction="horizontal" widthStretch="false" mode="flex" justify="start" alignment="start" wrap={false}
                style="width:100%;padding-top:14px;padding-left:24px;padding-right:24px;">
                <ElText text="角色列表" />
            </ElFlex>
            <ElButton text="创建角色" type="primary" widthStretch="false" icon="Plus"
                onClick={function click() {
                    $refs.el_form_2.resetForm();
                    isUpdateRole = false;
                    nasl.util.Clear(inputRole, 'shallow');
                    getRoleNameList();
                    $refs.el_dialog_3.open();
                    return;
                }}
                style="margin-top:15px;margin-bottom:12px;width:90%;" />
            <ElFlex direction="horizontal" mode="block" widthStretch="false" gutter={0}
                style="width:100%;padding-bottom:14px; min-height: calc(100vh - 210px);">
                <ElTable ref="el_table_1" dataSourceWatch={[]}
                    dataSource={app.logics.LcapLoadRoleManagementTableView($self.currentPage, $self.pageSize, $self.sort, $self.order, filterRole)}
                    widthStretch="false"
                    showHeader={false}
                    defaultOrder="ascending"
                    border={true}
                    stripe={false}
                    pagination={false}
                    defaultPageSize={999999}
                    onCurrentChange={function currentchange(event) {
                        selectRole = app.dataSources.defaultDS.entities.LcapRoleEntity.get(selectRoleId);
                        reloadUserTable();
                        $refs.el_table_3.reload();
                        return;
                    }}
                    style="min-width:100px;width:100%; --el-table-td-padding-vertical: 0px; --el-table-td-padding-horizontal: 0px;">
                    <ElTableColumn
                        slotDefault={(current) =>
                            <ElFlex direction="horizontal" mode="flex" alignment="center" wrap={false} justify="space-between"
                                onClick={function click() {
                                    if (current.item.lcapRole.id == selectRoleId) {
                                    } else {
                                        selectRoleId = current.item.lcapRole.id;
                                        selectRole = app.dataSources.defaultDS.entities.LcapRoleEntity.get(selectRoleId);
                                        reloadUserTable();
                                        $refs.el_table_3.reload();
                                    }
                                    return;
                                }}
                                style="width:100%;padding-top:12px;padding-bottom:12px;padding-left:16px;padding-right:16px; cursor: pointer;"
                                $dynamicStyle={{
                                    backgroundColor: (current.item.lcapRole.id == selectRoleId) ? '#e8f7ff' : '#fff',
                                }}>
                                <ElFlex direction="horizontal" mode="flex" justify="start" alignment="center" wrap={false} gutter={12}>
                                    <ElIcon name="https://lcap-static-saas.nos-eastchina1.126.net/user/wangfeng/1760094494192_f03b904ff2594dcc8abab382d60de46f.svg"
                                        style="font-size:16px;"
                                        $dynamicStyle={{
                                            color: (current.item.lcapRole.id == selectRole.id) ? '#409eff' : '#333',
                                        }} />
                                    <ElText text={current.item.lcapRole.name} overflow="break"
                                        $dynamicStyle={{
                                            color: (current.item.lcapRole.id == selectRole.id) ? '#409eff' : '#333',
                                        }} />
                                </ElFlex>
                                <ElPopover ref="el_popover_1" $if={current.item.lcapRole.editable} trigger="click"
                                    slotReference={() =>
                                        <ElIcon name="https://lcap-static-saas.nos-eastchina1.126.net/user/wangfeng/1760094494194_0eea142c35334f3c90ebf62c5908f632.svg" />}>
                                    <ElFlex direction="vertical" gutter={12} mode="flex" justify="start" alignment="start" wrap={false}>
                                        <ElLink text="修改" type="primary"
                                            onClick={function click() {
                                                $refs.el_form_2.resetForm();
                                                isUpdateRole = true;
                                                inputRole = nasl.util.Clone(current.item.lcapRole);
                                                updateRoleName = current.item.lcapRole.name;
                                                getRoleNameList();
                                                $refs.el_popover_1.hide();
                                                $refs.el_dialog_3.open();
                                                return;
                                            }}
                                            style="width:100%;text-align:left; display: block;" />
                                        <ElLink text="删除" type="danger"
                                            onClick={function click() {
                                                deleteRoleBody = nasl.util.Clone(current.item.lcapRole);
                                                $refs.el_popover_1.hide();
                                                $refs.el_message_box_3.open();
                                                return;
                                            }}
                                            style="width:100%;text-align:left; display: block;" />
                                    </ElFlex>
                                </ElPopover>
                            </ElFlex>
                        } />
                </ElTable>
            </ElFlex>
        </ElFlex>

        {/* 右侧角色详情 */}
        <ElFlex mode="flex" direction="vertical" justify="start" alignment="start" wrap={false} gutter={0} widthStretch="false" heightStretch="false"
            style="width:80%;background-color:#FFFFFF;padding-top:14px;padding-bottom:18px;padding-left:24px;padding-right:24px;border-top-right-radius:6px;border-bottom-right-radius:6px;border-top-left-radius:0px;border-bottom-left-radius:0px;position:static;height:auto;">
            <ElFlex direction="horizontal" widthStretch="false" mode="flex" justify="start" wrap={false} alignment="center" gutter={16}
                style="width:100%;padding-top:10px;padding-bottom:16px;">
                <ElFlex direction="horizontal" widthStretch="false" heightStretch="false" mode="flex" alignment="center" justify="center" wrap={false} gutter={0}
                    style="width:45px;height:45px;background-color:#EBF2FF;border-top-left-radius:8px;border-bottom-left-radius:8px;border-top-right-radius:8px;border-bottom-right-radius:8px;">
                    <ElIcon name="https://lcap-static-saas.nos-eastchina1.126.net/user/wangfeng/1760094493712_c4da70baaef94d7aa4d246c5e1fd2e4d.svg"
                        style="color:#337EFF;font-size:24px;" />
                </ElFlex>
                <ElFlex mode="flex" direction="vertical" alignment="start" wrap={false} justify="center" gutter={2}>
                    <ElText text={selectRole.name} />
                    <ElText text={selectRole.description}
                        style="font-size:14px;color:#999;" />
                </ElFlex>
            </ElFlex>
            <ElTabs widthStretch="false" style="width:100%; flex: 1;">
                {/* 角色成员 Tab */}
                <ElTabPane style="width:100%;"
                    slotLabel={(current) => <ElText text="人员管理" />}>
                    <ElFlex gutter={16} direction="vertical" mode="flex" justify="start" alignment="start">
                        <ElButton text="添加用户" type="primary" icon="Plus"
                            onClick={function click() {
                                nasl.util.Clear(waitAddRoleUserIdList, 'shallow');
                                $refs.el_dialog_1.open();
                                return;
                            }} />
                        <ElTable ref="el_table_2" widthStretch="false"
                            dataSourceWatch={[]}
                            dataSource={userTableData.list}
                            border={true}
                            pagination={true}
                            columnConfig={false}
                            stripe={true}
                            showTotal={true}
                            showJumper={true}
                            defaultPageSize={20}
                            defaultOrder="descending"
                            rowKey="lcapUserRoleMapping.userId"
                            defaultField="lcapUserRoleMapping.createdTime"
                            style="width:100%;">
                            <ElTableColumn prop="lcapUserRoleMapping.id" type="index" style="width: 60px;"
                                slotDefault={(current) => <ElText text={current.index + 1} />}
                                slotHeader={(current) => <ElText text="序号" />} />
                            <ElTableColumn
                                slotDefault={(current) => <ElText text={current.item.lcapUserRoleMapping.userName} />}
                                slotHeader={(current) => <ElText text="用户名" />} />
                            <ElTableColumn style="width: 120px;"
                                slotDefault={(current) =>
                                    <ElFlex direction="horizontal" mode="block" gutter={12}>
                                        <ElLink text="移除" type="danger"
                                            onClick={function click() {
                                                deleteUserRole = nasl.util.Clone(current.item);
                                                $refs.el_message_box_1.open();
                                                return;
                                            }} />
                                    </ElFlex>
                                }
                                slotHeader={(current) => <ElText text="操作" />} />
                        </ElTable>
                    </ElFlex>
                </ElTabPane>

                {/* 功能权限 Tab */}
                <ElTabPane style="width:100%;"
                    slotLabel={(current) => <ElText text="功能权限" />}>
                    <ElFlex direction="vertical" gutter={16} mode="flex" justify="start" alignment="start">
                        <ElButton text="新增功能权限" type="primary" icon="Plus"
                            disabled={!selectRole.editable}
                            onClick={function click() {
                                nasl.util.Clear(alreadySelectedPermissionIdList, 'shallow');
                                $refs.el_dialog_2.open();
                                return;
                            }} />
                        <ElTable ref="el_table_3" widthStretch="false"
                            dataSourceWatch={[]}
                            dataSource={loadPermissionByRoleId(1, 999999999)}
                            border={true}
                            pagination={true}
                            columnConfig={false}
                            stripe={true}
                            showTotal={true}
                            showJumper={true}
                            defaultPageSize={20}
                            defaultOrder="descending"
                            defaultField="createdTime"
                            rowKey="id"
                            style="width:100%;">
                            <ElTableColumn prop="id" type="index" style="width: 60px;"
                                slotDefault={(current) => <ElText text={current.index + 1} />}
                                slotHeader={(current) => <ElText text="序号" />} />
                            <ElTableColumn
                                slotDefault={(current) => <ElText text={current.item.name} />}
                                slotHeader={(current) => <ElText text="权限名称" />} />
                            <ElTableColumn
                                slotDefault={(current) => <ElText text={current.item.description} />}
                                slotHeader={(current) => <ElText text="权限描述" />} />
                            <ElTableColumn style="width: 120px;"
                                slotDefault={(current) =>
                                    <ElFlex direction="horizontal" mode="block" gutter={12}>
                                        <ElLink text="移除该权限" type="danger"
                                            disabled={!selectRole.editable}
                                            onClick={function click() {
                                                removePermission = nasl.util.Clone(current.item);
                                                $refs.el_message_box_2.open();
                                                return;
                                            }} />
                                    </ElFlex>
                                }
                                slotHeader={(current) => <ElText text="操作" />} />
                        </ElTable>
                    </ElFlex>
                </ElTabPane>
            </ElTabs>
        </ElFlex>
    </ElFlex>

    {/* 新增/编辑角色弹窗 */}
    <ElDialog ref="el_dialog_3"
        closeOnClickModal={false}
        width="30%"
        style="padding-left:24px;padding-right:24px;padding-top:24px;padding-bottom:24px;"
        slotHeader={(current) => <ElText text={isUpdateRole ? "编辑角色" : "新增角色"} />}
        slotFooter={(current) => <ElFlex direction="horizontal" mode="flex" alignment="start" justify="center" wrap={false} gutter={16}>
            <ElButton text="确定" type="primary"
                onClick={function click() {
                    getRoleNameList();
                    if (!$refs.el_form_2.validated().valid) return;
                    if (isUpdateRole) {
                        app.dataSources.defaultDS.entities.LcapRoleEntity.update(inputRole);
                        selectRole = nasl.util.Clone(inputRole);
                        selectRoleId = inputRole.id;
                        toastInfo = '修改成功';
                    } else {
                        inputRole = app.dataSources.defaultDS.entities.LcapRoleEntity.create(inputRole);
                        selectRole = nasl.util.Clone(inputRole);
                        selectRoleId = inputRole.id;
                        toastInfo = '新增成功';
                    }
                    $refs.el_table_1.reload();
                    reloadUserTable();
                    $refs.el_table_3.reload();
                    $refs.el_dialog_3.close();
                    nasl.ui.showMessage(`${toastInfo}`);
                }} />
            <ElButton text="取消" type="" onClick={function click() { $refs.el_dialog_3.close(); return; }} />
        </ElFlex>}>
        <ElForm ref="el_form_2" labelPosition="top">
            <ElFormInput modelValue={$sync(inputRole.name)}
                rules={[nasl.validation.filled(), nasl.validation.unique(roleNameList), nasl.validation.maxLength(50)]}
                isRequired={true}
                clearable={true}
                placeholder="请输入角色名称"
                maxlength={50}
                slotLabel={(current) => <ElText text="角色名称" />} />
            <ElFormInput modelValue={$sync(inputRole.description)}
                rules={[nasl.validation.maxLength(150)]}
                maxlength={150}
                placeholder="请输入角色描述"
                slotLabel={(current) => <ElText text="角色描述" />} />
        </ElForm>
    </ElDialog>

    {/* 添加角色成员弹窗 */}
    <ElDialog ref="el_dialog_1"
        closeOnClickModal={false}
        width="30%"
        style="padding-left:24px;padding-right:24px;padding-top:24px;padding-bottom:24px;"
        slotHeader={(current) => <ElText text="请添加用户" />}
        slotFooter={(current) => <ElFlex direction="horizontal" mode="flex" alignment="start" justify="center" wrap={false} gutter={16}>
            <ElButton text="添加" type="primary"
                onClick={function click() {
                    let userList: List<app.dataSources.defaultDS.entities.LcapUser>;
                    let createUserAndRoleList: List<app.dataSources.defaultDS.entities.LcapUserRoleMapping>;
                    if (nasl.util.HasValue(waitAddRoleUserIdList)) {
                        userList = app.logics.LcapGetUserByUserIds(waitAddRoleUserIdList);
                        createUserAndRoleList = nasl.util.ListTransform(waitAddRoleUserIdList, (item) =>
                            new app.dataSources.defaultDS.entities.LcapUserRoleMapping({
                                userId: item,
                                roleId: selectRole.id,
                                userName: nasl.util.ListFind(userList, (item1) => item1.userId == item).userName,
                                source: nasl.util.ToString(nasl.util.ListFind(userList, (item1) => item1.userId == item).source)
                            })
                        );
                        app.dataSources.defaultDS.entities.LcapUserRoleMappingEntity.batchCreate(createUserAndRoleList);
                        toastInfo = '添加成功';
                    } else {
                        toastInfo = '未选择用户';
                    }
                    reloadUserTable();
                    $refs.el_dialog_1.close();
                    nasl.ui.showMessage(`${toastInfo}`);
                    nasl.util.Clear(waitAddRoleUserIdList, 'shallow');
                }} />
            <ElButton text="取消" type="" onClick={function click() { $refs.el_dialog_1.close(); return; }} />
        </ElFlex>}
        onOpen={function open() {
            nasl.util.Clear(waitAddRoleUserIdList, 'shallow');
            getRoleAddUser();
        }}>
        <ElForm showMessage={false}>
            <ElFormSelect modelValue={$sync(waitAddRoleUserIdList)}
                dataSourceWatch={[]}
                dataSource={selectUserList}
                textField="lcapUser.userName"
                valueField="lcapUser.userId"
                placeholder="请选择用户"
                clearable={true}
                filterable={true}
                virtualize={true}
                multiple={true}
                noDataText="No data"
                style="width:100%;"
                slotLabel={(current) => <ElText text="用户名" />} />
        </ElForm>
    </ElDialog>

    {/* 新增功能权限弹窗 */}
    <ElDialog ref="el_dialog_2"
        closeOnClickModal={false}
        width="50%"
        destroyOnClose={true}
        style="padding-left:24px;padding-right:24px;padding-top:24px;padding-bottom:24px;"
        slotHeader={(current) => <ElText text="请勾选需要关联的权限" />}
        slotFooter={(current) => <ElFlex direction="horizontal" mode="flex" alignment="start" justify="center" wrap={false} gutter={16}>
            <ElButton text="确定" type="primary"
                onClick={function click() {
                    let mappingList: List<app.dataSources.defaultDS.entities.LcapRolePerMapping>;
                    if (nasl.util.HasValue(alreadySelectedPermissionIdList)) {
                        mappingList = nasl.util.ListTransform(alreadySelectedPermissionIdList, (item) =>
                            new app.dataSources.defaultDS.entities.LcapRolePerMapping({
                                roleId: selectRole.id,
                                permissionId: item
                            })
                        );
                        app.dataSources.defaultDS.entities.LcapRolePerMappingEntity.batchCreate(mappingList);
                        toastInfo = '权限添加成功';
                    } else {
                        toastInfo = '未选择权限';
                    }
                    $refs.el_table_3.reload();
                    $refs.el_dialog_2.close();
                    nasl.ui.showMessage(`${toastInfo}`);
                    nasl.util.Clear(alreadySelectedPermissionIdList, 'shallow');
                }} />
            <ElButton text="取消" type="" onClick={function click() { $refs.el_dialog_2.close(); return; }} />
        </ElFlex>}
        onOpen={function open() {
            nasl.util.Clear(alreadySelectedPermissionIdList, 'shallow');
        }}>
        <ElTable ref="el_table_4"
            dataSourceWatch={[]}
            dataSource={getRoleAddPermission(1, 999, null, null)}
            border={true}
            pagination={true}
            defaultPageSize={20}
            stripe={true}
            showTotal={true}
            showJumper={true}
            defaultField="lcapPermission.createdTime"
            defaultOrder="descending"
            rowKey="lcapPermission.id"
            selectedValues={$sync(alreadySelectedPermissionIdList)}
            highlightCurrentRow={false}
            onSelect={function select(event) {
                alreadySelectedPermissionIdList = event.newSelection;
            }}>
            <ElTableColumn prop="lcapPermission.id" type="selection"
                slotHeader={(current) => <ElText text="表格列" />} />
            <ElTableColumn
                slotDefault={(current) => <ElText text={current.item.lcapPermission.name} />}
                slotHeader={(current) => <ElText text="权限名称" />} />
            <ElTableColumn
                slotDefault={(current) => <ElText text={current.item.lcapPermission.description} />}
                slotHeader={(current) => <ElText text="权限描述" />} />
        </ElTable>
    </ElDialog>

    {/* 删除角色确认 */}
    <ElMessageBox ref="el_message_box_3"
        type="confirm"
        iconType="warning"
        title="删除角色"
        showCancelButton={true}
        closeOnClickModal={false}
        onConfirm={function confirm() {
            let search: List<{ lcapRole: app.dataSources.defaultDS.entities.LcapRole }>;
            // 删除角色实体
            app.dataSources.defaultDS.entities.LcapRoleEntity.delete(deleteRoleBody.id);
            // 删除用户角色映射
            app.dataSources.defaultDS.entities.LcapUserRoleMappingEntity.deleteBy((_) => _.roleId == deleteRoleBody.id);
            // 删除角色权限映射
            app.dataSources.defaultDS.entities.LcapRolePerMappingEntity.deleteBy((_) => _.roleId == deleteRoleBody.id);
            // 重新选择角色
            search = app.logics.LcapLoadRoleManagementTableView(1, 10, 'id', 'asc', filterRole).list;
            if (nasl.util.HasValue(search)) {
                selectRole = nasl.util.ListHead(nasl.util.ListTransform(search, (item) => item.lcapRole));
            } else {
                selectRole = nasl.util.New<app.dataSources.defaultDS.entities.LcapRole>();
            }
            selectRoleId = selectRole.id;
            // 刷新所有表格
            $refs.el_table_1.reload();
            reloadUserTable();
            $refs.el_table_3.reload();
            $refs.el_message_box_3.close();
            nasl.ui.showMessage('删除成功');
        }}
        onCancel={() => $refs.el_message_box_3.close()}>
        <ElText text={`删除后,该角色对应的成员、权限、资源关联关系都会被删除!

确定删除角色:${deleteRoleBody.name}?`} />

    {/* 移除成员确认 */}
    <ElMessageBox ref="el_message_box_1"
        type="confirm"
        iconType="warning"
        title="移除成员"
        showCancelButton={true}
        closeOnClickModal={false}
        onConfirm={function confirm() {
            app.dataSources.defaultDS.entities.LcapUserRoleMappingEntity.delete(deleteUserRole.lcapUserRoleMapping.id);
            nasl.util.Clear(deleteUserRole, 'shallow');
            reloadUserTable();
            $refs.el_message_box_1.close();
            nasl.ui.showMessage('移除成功');
        }}
        onCancel={() => $refs.el_message_box_1.close()}>
        <ElText text={`移除后,该用户将失去${selectRole.name}对应的权限、资源关联关系!

确定移除成员:${deleteUserRole.lcapUserRoleMapping.userName}?`} />

    {/* 移除权限确认 */}
    <ElMessageBox ref="el_message_box_2"
        type="confirm"
        iconType="warning"
        title="确定移除下面权限?"
        showCancelButton={true}
        closeOnClickModal={false}
        onConfirm={function confirm() {
            app.logics.LcapGetMappingDeleteByRoleIdAndPermissionId(selectRole.id, removePermission.id);
            nasl.util.Clear(removePermission, 'shallow');
            $refs.el_table_3.reload();
            $refs.el_message_box_2.close();
            nasl.ui.showMessage('移除成功');
        }}
        onCancel={() => $refs.el_message_box_2.close()}>
        <ElText text={removePermission.name} />
    </ElMessageBox>
</>

}