feat: 角色管理添加按钮级权限管理

This commit is contained in:
2025-02-22 16:24:12 +08:00
parent b32c2c5713
commit b1a2605ce1
6 changed files with 141 additions and 17 deletions

View File

@@ -178,3 +178,8 @@ user:buttons:roleDataList: User Role Data List
user:buttons:permisssionList: User Permisssion List user:buttons:permisssionList: User Permisssion List
user:buttons:uploadAvatar: Upload Avatar user:buttons:uploadAvatar: Upload Avatar
user:buttons:resetPassword: Reset Password user:buttons:resetPassword: Reset Password
role:buttons:addPermission: Add Role Permission
role:buttons:deletePermission: Delete Role Permission
role:buttons:updatePermission: Update Role Permission
role:buttons:permissiomInfo: Role Permissiom Info
role:buttons:permissionDataList: Rolr Permission Data List

View File

@@ -178,3 +178,8 @@ user:buttons:roleDataList: 用户角色列表
user:buttons:permisssionList: 用户权限列表 user:buttons:permisssionList: 用户权限列表
user:buttons:uploadAvatar: 上传头像 user:buttons:uploadAvatar: 上传头像
user:buttons:resetPassword: 重置密码 user:buttons:resetPassword: 重置密码
role:buttons:addPermission: 添加角色权限
role:buttons:deletePermission: 删除角色权限
role:buttons:updatePermission: 更新角色权限
role:buttons:permissiomInfo: 角色权限详情
role:buttons:permissionDataList: 角色权限列表

View File

@@ -318,6 +318,15 @@ export const deleteRoleAPI = (id: string) => {
return http.request<null>("post", `/api/role/delete/${id}`); return http.request<null>("post", `/api/role/delete/${id}`);
}; };
/**批量删除角色 */
export const deleteRoleListAPI = (ids: string[]) => {
return http.request<null>("post", `/api/role/deleteList`, {
data: {
ids
}
});
};
// --------------------------用户相关-------------------------------------- // --------------------------用户相关--------------------------------------
/**添加用户参数 */ /**添加用户参数 */

View File

@@ -4,6 +4,7 @@ import type { FormRules } from "element-plus";
import { getDepartmentListAPI } from "@/api/system"; import { getDepartmentListAPI } from "@/api/system";
import type { DepartmentInfo } from "types/system"; import type { DepartmentInfo } from "types/system";
import { usePublicHooks } from "../../hooks"; import { usePublicHooks } from "../../hooks";
import { handleTree } from "@pureadmin/utils";
defineOptions({ defineOptions({
name: "SystemRoleForm" name: "SystemRoleForm"
@@ -53,7 +54,9 @@ function getRef() {
const getDepartments = async () => { const getDepartments = async () => {
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 }); const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
if (res.success) { if (res.success) {
departments.value = formatHigherOptions(res.data.result); departments.value = formatHigherOptions(
handleTree(res.data.result, "id", "parent_id")
);
} else { } else {
departments.value = []; departments.value = [];
} }

View File

@@ -19,6 +19,7 @@ import Close from "@iconify-icons/ep/close";
import Check from "@iconify-icons/ep/check"; import Check from "@iconify-icons/ep/check";
import { onBeforeRouteUpdate } from "vue-router"; import { onBeforeRouteUpdate } from "vue-router";
const { t } = useI18n(); const { t } = useI18n();
import { hasAuth } from "@/utils/auth";
defineOptions({ defineOptions({
name: "SystemRole" name: "SystemRole"
}); });
@@ -51,8 +52,8 @@ const {
curRow, curRow,
loading, loading,
columns, columns,
rowStyle,
dataList, dataList,
selectedNum,
treeData, treeData,
treeProps, treeProps,
isLinkage, isLinkage,
@@ -61,8 +62,11 @@ const {
isSelectAll, isSelectAll,
treeSearchValue, treeSearchValue,
departments, departments,
rowStyle,
onSearch, onSearch,
resetForm, resetForm,
onSelectionCancel,
onbatchDel,
openDialog, openDialog,
handleMenu, handleMenu,
handleSave, handleSave,
@@ -71,8 +75,9 @@ const {
transformI18n, transformI18n,
onQueryChanged, onQueryChanged,
handleSizeChange, handleSizeChange,
handleCurrentChange handleCurrentChange,
} = useRole(treeRef); handleSelectionChange
} = useRole(treeRef, tableRef);
onMounted(() => { onMounted(() => {
useResizeObserver(contentRef, async () => { useResizeObserver(contentRef, async () => {
await nextTick(); await nextTick();
@@ -180,6 +185,7 @@ onBeforeRouteUpdate((to, from, next) => {
> >
<template #buttons> <template #buttons>
<el-button <el-button
v-if="hasAuth('role:btn:add')"
type="primary" type="primary"
:icon="useRenderIcon(AddFill)" :icon="useRenderIcon(AddFill)"
@click="openDialog()" @click="openDialog()"
@@ -188,8 +194,42 @@ onBeforeRouteUpdate((to, from, next) => {
</el-button> </el-button>
</template> </template>
<template v-slot="{ size, dynamicColumns }"> <template v-slot="{ size, dynamicColumns }">
<div
v-if="selectedNum > 0"
v-motion-fade
class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center"
>
<div class="flex-auto">
<span
style="font-size: var(--el-font-size-base)"
class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]"
>
已选 {{ selectedNum }}
</span>
<el-button type="primary" text @click="onSelectionCancel">
{{ t("buttons:Deselect") }}
</el-button>
</div>
<el-popconfirm
v-if="hasAuth('role:btn:delete')"
title="是否确认删除?"
@confirm="onbatchDel"
>
<template #reference>
<el-button
type="danger"
text
class="mr-1"
:disabled="selectedNum < 0 || hasAuth('role:btn:delete')"
>
{{ t("buttons:DeleteInBatches") }}
</el-button>
</template>
</el-popconfirm>
</div>
<pure-table <pure-table
ref="tableRef" ref="tableRef"
row-key="id"
align-whole="center" align-whole="center"
showOverflowTooltip showOverflowTooltip
table-layout="auto" table-layout="auto"
@@ -208,6 +248,7 @@ onBeforeRouteUpdate((to, from, next) => {
background: 'var(--el-fill-color-light)', background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)' color: 'var(--el-text-color-primary)'
}" }"
@selection-change="handleSelectionChange"
@page-size-change="handleSizeChange" @page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange" @page-current-change="handleCurrentChange"
> >
@@ -217,6 +258,7 @@ onBeforeRouteUpdate((to, from, next) => {
link link
type="primary" type="primary"
:size="size" :size="size"
:disabled="!hasAuth('role:btn:update')"
:icon="useRenderIcon(EditPen)" :icon="useRenderIcon(EditPen)"
@click="openDialog('修改', row)" @click="openDialog('修改', row)"
> >
@@ -232,6 +274,7 @@ onBeforeRouteUpdate((to, from, next) => {
link link
type="danger" type="danger"
:size="size" :size="size"
:disabled="!hasAuth('role:btn:delete')"
:icon="useRenderIcon(Delete)" :icon="useRenderIcon(Delete)"
> >
{{ t("buttons:Delete") }} {{ t("buttons:Delete") }}
@@ -243,6 +286,7 @@ onBeforeRouteUpdate((to, from, next) => {
link link
type="primary" type="primary"
:size="size" :size="size"
:disabled="!hasAuth('role:btn:permissionInfo')"
:icon="useRenderIcon(Menu)" :icon="useRenderIcon(Menu)"
@click="handleMenu(row)" @click="handleMenu(row)"
> >

View File

@@ -4,6 +4,7 @@ import { message } from "@/utils/message";
import { import {
deleteRoleAPI, deleteRoleAPI,
deleteRoleListAPI,
getPermissionListAPI, getPermissionListAPI,
getRoleListAPI, getRoleListAPI,
postAddRoleAPI, postAddRoleAPI,
@@ -26,7 +27,7 @@ import type {
RolePermissionInfo RolePermissionInfo
} from "types/system"; } from "types/system";
export const useRole = (treeRef: Ref) => { export const useRole = (treeRef: Ref, tableRef: Ref) => {
/**查询表单 */ /**查询表单 */
const form = reactive({ const form = reactive({
name: "", name: "",
@@ -47,6 +48,10 @@ export const useRole = (treeRef: Ref) => {
* 加载状态 * 加载状态
*/ */
const loading = ref(true); const loading = ref(true);
/**
* 已选数量
*/
const selectedNum = ref<number>(0);
/** /**
* 标签样式 * 标签样式
*/ */
@@ -87,6 +92,12 @@ export const useRole = (treeRef: Ref) => {
/**是否全选 */ /**是否全选 */
const isSelectAll = ref<boolean>(false); const isSelectAll = ref<boolean>(false);
const columns: TableColumnList = [ const columns: TableColumnList = [
{
label: "勾选列", // 如果需要表格多选此处label必须设置
type: "selection",
fixed: "left",
reserveSelection: true // 数据刷新后保留选项
},
{ {
label: "角色名称", label: "角色名称",
prop: "name", prop: "name",
@@ -150,7 +161,10 @@ export const useRole = (treeRef: Ref) => {
dataList.value = data.data.result; dataList.value = data.data.result;
pagination.total = data.data.total; pagination.total = data.data.total;
pagination.currentPage = data.data.page; pagination.currentPage = data.data.page;
pagination.pageSize = data.data.pageSize;
message(data.msg, {
type: data.success ? "success" : "error"
});
setTimeout(() => { setTimeout(() => {
loading.value = false; loading.value = false;
}, 500); }, 500);
@@ -171,22 +185,61 @@ export const useRole = (treeRef: Ref) => {
dataList.value = data.result; dataList.value = data.result;
pagination.total = data.total; pagination.total = data.total;
pagination.currentPage = data.page; pagination.currentPage = data.page;
pagination.pageSize = res.data.pageSize;
} }
}; };
/**处理每页数量变化 */ /**
* 处理页码变化
* @param val
*/
const handleCurrentChange = async (val: number) => { const handleCurrentChange = async (val: number) => {
loading.value = true;
const res = await getRoleListAPI({ const res = await getRoleListAPI({
page: val, page: val,
pageSize: pagination.pageSize pageSize: pagination.pageSize,
...toRaw(form)
}); });
if (res.success) { if (res.success) {
const data = res.data; dataList.value = res.data.result;
dataList.value = data.result; pagination.total = res.data.total;
pagination.total = data.total; pagination.currentPage = res.data.page;
pagination.currentPage = data.page; pagination.pageSize = res.data.pageSize;
} }
message(res.msg, {
type: res.success ? "success" : "error"
});
loading.value = false;
};
/** 当CheckBox选择项发生变化时会触发该事件 */
const handleSelectionChange = async (val: any) => {
selectedNum.value = val.length;
// 重置表格高度
tableRef.value.setAdaptive();
}; };
/** 取消选择 */
const onSelectionCancel = async () => {
selectedNum.value = 0;
// 用于多选表格,清空用户的选择
tableRef.value.getTableRef().clearSelection();
};
/**
* 批量删除
*/
const onbatchDel = async () => {
// 返回当前选中的行
const curSelected = tableRef.value.getTableRef().getSelectionRows();
const res = await deleteRoleListAPI(getKeyList(curSelected, "id"));
if (res.success) {
message(res.msg, {
type: "success"
});
tableRef.value.getTableRef().clearSelection();
onSearch();
} else {
message(res.msg, { type: "error", duration: 5000 });
}
};
const handleDelete = async (row: RoleInfo) => { const handleDelete = async (row: RoleInfo) => {
const res = await deleteRoleAPI(row.id); const res = await deleteRoleAPI(row.id);
if (res.success) { if (res.success) {
@@ -237,7 +290,6 @@ export const useRole = (treeRef: Ref) => {
} }
FormRef.validate(async (valid: any) => { FormRef.validate(async (valid: any) => {
if (valid) { if (valid) {
console.log("curData", curData);
// 表单规则校验通过 // 表单规则校验通过
if (title === "新增") { if (title === "新增") {
// 实际开发先调用新增接口,再进行下面操作 // 实际开发先调用新增接口,再进行下面操作
@@ -335,13 +387,15 @@ export const useRole = (treeRef: Ref) => {
const getDepartments = async () => { const getDepartments = async () => {
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 }); const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
if (res.success) { if (res.success) {
departments.value = formatHigherOptions(res.data.result); departments.value = formatHigherOptions(
handleTree(res.data.result, "id", "parent_id")
);
} else { } else {
departments.value = []; departments.value = [];
} }
}; };
const formatHigherOptions = treeList => { const formatHigherOptions = (treeList: any) => {
// 根据返回数据的status字段值判断追加是否禁用disabled字段返回处理后的树结构用于上级部门级联选择器的展示 // 根据返回数据的status字段值判断追加是否禁用disabled字段返回处理后的树结构用于上级部门级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理)
if (!treeList || !treeList.length) return; if (!treeList || !treeList.length) return;
const newTreeList = []; const newTreeList = [];
for (let i = 0; i < treeList.length; i++) { for (let i = 0; i < treeList.length; i++) {
@@ -379,6 +433,7 @@ export const useRole = (treeRef: Ref) => {
loading, loading,
columns, columns,
dataList, dataList,
selectedNum,
treeData, treeData,
treeProps, treeProps,
isLinkage, isLinkage,
@@ -390,6 +445,8 @@ export const useRole = (treeRef: Ref) => {
rowStyle, rowStyle,
onSearch, onSearch,
resetForm, resetForm,
onSelectionCancel,
onbatchDel,
openDialog, openDialog,
handleMenu, handleMenu,
handleSave, handleSave,
@@ -398,6 +455,7 @@ export const useRole = (treeRef: Ref) => {
transformI18n, transformI18n,
onQueryChanged, onQueryChanged,
handleSizeChange, handleSizeChange,
handleCurrentChange handleCurrentChange,
handleSelectionChange
}; };
}; };