feat: 添加角色管理
This commit is contained in:
141
src/views/system/role/components/form.vue
Normal file
141
src/views/system/role/components/form.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive } from "vue";
|
||||
import type { FormRules } from "element-plus";
|
||||
import { getDepartmentListAPI } from "@/api/system";
|
||||
import type { DepartmentInfo } from "types/system";
|
||||
import { usePublicHooks } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "SystemRoleForm"
|
||||
});
|
||||
|
||||
/** 自定义表单规则校验 */
|
||||
const formRules = reactive<FormRules>({
|
||||
name: [{ required: true, message: "角色名称为必填项", trigger: "blur" }],
|
||||
code: [{ required: true, message: "角色标识为必填项", trigger: "blur" }]
|
||||
});
|
||||
interface FormItemProps {
|
||||
/**角色ID */
|
||||
id: string;
|
||||
/** 角色名称 */
|
||||
name: string;
|
||||
/** 角色编号 */
|
||||
code: string;
|
||||
/**角色状态 */
|
||||
status: number;
|
||||
/** 角色描述 */
|
||||
description: string;
|
||||
/** 角色部门ID */
|
||||
department_id: string;
|
||||
}
|
||||
interface FormProps {
|
||||
formInline: FormItemProps;
|
||||
}
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
formInline: () => ({
|
||||
id: "",
|
||||
name: "",
|
||||
code: "",
|
||||
description: "",
|
||||
status: 1,
|
||||
department_id: ""
|
||||
})
|
||||
});
|
||||
|
||||
const ruleFormRef = ref();
|
||||
const newFormInline = ref(props.formInline);
|
||||
const departments = ref<DepartmentInfo[]>([]);
|
||||
const { switchStyle } = usePublicHooks();
|
||||
function getRef() {
|
||||
return ruleFormRef.value;
|
||||
}
|
||||
/**获取部门列表 */
|
||||
const getDepartments = async () => {
|
||||
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
|
||||
if (res.code === 200) {
|
||||
departments.value = formatHigherOptions(res.data.result);
|
||||
} else {
|
||||
departments.value = [];
|
||||
}
|
||||
};
|
||||
const formatHigherOptions = treeList => {
|
||||
// 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示
|
||||
if (!treeList || !treeList.length) return;
|
||||
const newTreeList = [];
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
treeList[i].disabled = treeList[i].status === 0 ? true : false;
|
||||
formatHigherOptions(treeList[i].children);
|
||||
newTreeList.push(treeList[i]);
|
||||
}
|
||||
return newTreeList;
|
||||
};
|
||||
defineExpose({ getRef });
|
||||
/**组件挂载执行 */
|
||||
onMounted(async () => {
|
||||
await getDepartments();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
:model="newFormInline"
|
||||
:rules="formRules"
|
||||
label-width="82px"
|
||||
>
|
||||
<el-form-item label="角色名称" prop="name">
|
||||
<el-input
|
||||
v-model="newFormInline.name"
|
||||
clearable
|
||||
placeholder="请输入角色名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="角色标识" prop="code">
|
||||
<el-input
|
||||
v-model="newFormInline.code"
|
||||
clearable
|
||||
placeholder="请输入角色标识"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="角色描述">
|
||||
<el-input
|
||||
v-model="newFormInline.description"
|
||||
placeholder="请输入角色描述信息"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="department_id">
|
||||
<el-cascader
|
||||
v-model="newFormInline.department_id"
|
||||
class="w-full"
|
||||
:options="departments"
|
||||
:props="{
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
emitPath: false,
|
||||
checkStrictly: true
|
||||
}"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择所属部门~"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span>{{ data.name }}</span>
|
||||
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
|
||||
</template>
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色状态" prop="status">
|
||||
<el-switch
|
||||
v-model="newFormInline.status"
|
||||
inline-prompt
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="启用"
|
||||
inactive-text="停用"
|
||||
:style="switchStyle"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
340
src/views/system/role/index.vue
Normal file
340
src/views/system/role/index.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, nextTick, onMounted } from "vue";
|
||||
import { useRole } from "./utils/hook";
|
||||
import { PureTableBar } from "@/components/RePureTableBar";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import {
|
||||
delay,
|
||||
subBefore,
|
||||
deviceDetection,
|
||||
useResizeObserver
|
||||
} from "@pureadmin/utils";
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import Refresh from "@iconify-icons/ep/refresh";
|
||||
import Menu from "@iconify-icons/ep/menu";
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
import Close from "@iconify-icons/ep/close";
|
||||
import Check from "@iconify-icons/ep/check";
|
||||
import { onBeforeRouteUpdate } from "vue-router";
|
||||
const { t } = useI18n();
|
||||
defineOptions({
|
||||
name: "SystemRole"
|
||||
});
|
||||
|
||||
const iconClass = computed(() => {
|
||||
return [
|
||||
"w-[22px]",
|
||||
"h-[22px]",
|
||||
"flex",
|
||||
"justify-center",
|
||||
"items-center",
|
||||
"outline-none",
|
||||
"rounded-[4px]",
|
||||
"cursor-pointer",
|
||||
"transition-colors",
|
||||
"hover:bg-[#0000000f]",
|
||||
"dark:hover:bg-[#ffffff1f]",
|
||||
"dark:hover:text-[#ffffffd9]"
|
||||
];
|
||||
});
|
||||
const treeRef = ref();
|
||||
|
||||
const formRef = ref();
|
||||
const tableRef = ref();
|
||||
const contentRef = ref();
|
||||
const treeHeight = ref();
|
||||
const {
|
||||
form,
|
||||
isShow,
|
||||
curRow,
|
||||
loading,
|
||||
columns,
|
||||
rowStyle,
|
||||
dataList,
|
||||
treeData,
|
||||
treeProps,
|
||||
isLinkage,
|
||||
pagination,
|
||||
isExpandAll,
|
||||
isSelectAll,
|
||||
treeSearchValue,
|
||||
departments,
|
||||
onSearch,
|
||||
resetForm,
|
||||
openDialog,
|
||||
handleMenu,
|
||||
handleSave,
|
||||
handleDelete,
|
||||
filterMethod,
|
||||
transformI18n,
|
||||
onQueryChanged,
|
||||
handleSizeChange,
|
||||
handleCurrentChange
|
||||
} = useRole(treeRef);
|
||||
onMounted(() => {
|
||||
useResizeObserver(contentRef, async () => {
|
||||
await nextTick();
|
||||
delay(60).then(() => {
|
||||
treeHeight.value = parseFloat(
|
||||
subBefore(tableRef.value.getTableDoms().tableWrapper.style.height, "px")
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
onBeforeRouteUpdate((to, from, next) => {
|
||||
onSearch();
|
||||
next();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:inline="true"
|
||||
:model="form"
|
||||
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto"
|
||||
>
|
||||
<el-form-item label="角色名称:" prop="name">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
placeholder="请输入角色名称"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色标识:" prop="code">
|
||||
<el-input
|
||||
v-model="form.code"
|
||||
placeholder="请输入角色标识"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色描述:" prop="description">
|
||||
<el-input
|
||||
v-model="form.description"
|
||||
placeholder="请输入角色描述"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门:" prop="department_id">
|
||||
<el-cascader
|
||||
v-model="form.department_id"
|
||||
class="w-full"
|
||||
:options="departments"
|
||||
:props="{
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
emitPath: false,
|
||||
checkStrictly: true
|
||||
}"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择所属部门~"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span>{{ data.name }}</span>
|
||||
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
|
||||
</template>
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态:" prop="status">
|
||||
<el-select
|
||||
v-model="form.status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
>
|
||||
<el-option label="已启用" value="1" />
|
||||
<el-option label="已停用" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon('ri:search-line')"
|
||||
:loading="loading"
|
||||
@click="onSearch"
|
||||
>
|
||||
{{ t("buttons:Search") }}
|
||||
</el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
|
||||
{{ t("buttons:Reset") }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div
|
||||
ref="contentRef"
|
||||
:class="['flex', deviceDetection() ? 'flex-wrap' : '']"
|
||||
>
|
||||
<PureTableBar
|
||||
:class="[isShow && !deviceDetection() ? '!w-[60vw]' : 'w-full']"
|
||||
style="transition: width 220ms cubic-bezier(0.4, 0, 0.2, 1)"
|
||||
title="角色管理"
|
||||
:columns="columns"
|
||||
@refresh="onSearch"
|
||||
>
|
||||
<template #buttons>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon(AddFill)"
|
||||
@click="openDialog()"
|
||||
>
|
||||
{{ t("buttons:Add") }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-slot="{ size, dynamicColumns }">
|
||||
<pure-table
|
||||
ref="tableRef"
|
||||
align-whole="center"
|
||||
showOverflowTooltip
|
||||
table-layout="auto"
|
||||
:loading="loading"
|
||||
:size="size"
|
||||
adaptive
|
||||
border
|
||||
stripe
|
||||
:row-style="rowStyle"
|
||||
:adaptiveConfig="{ offsetBottom: 108 }"
|
||||
:data="dataList"
|
||||
:columns="dynamicColumns"
|
||||
:pagination="pagination"
|
||||
:paginationSmall="size === 'small' ? true : false"
|
||||
:header-cell-style="{
|
||||
background: 'var(--el-fill-color-light)',
|
||||
color: 'var(--el-text-color-primary)'
|
||||
}"
|
||||
@page-size-change="handleSizeChange"
|
||||
@page-current-change="handleCurrentChange"
|
||||
>
|
||||
<template #operation="{ row }">
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(EditPen)"
|
||||
@click="openDialog('修改', row)"
|
||||
>
|
||||
{{ t("buttons:Update") }}
|
||||
</el-button>
|
||||
<el-popconfirm
|
||||
:title="`是否确认删除角色名称为${row.name}的这条数据`"
|
||||
@confirm="handleDelete(row)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="danger"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
>
|
||||
{{ t("buttons:Delete") }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(Menu)"
|
||||
@click="handleMenu(row)"
|
||||
>
|
||||
{{ t("buttons:Permission") }}
|
||||
</el-button>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
<div
|
||||
v-if="isShow"
|
||||
class="!min-w-[calc(100vw-60vw-268px)] w-full mt-2 px-2 pb-2 bg-bg_color ml-2 overflow-auto"
|
||||
>
|
||||
<div class="flex justify-between w-full px-3 pt-5 pb-4">
|
||||
<div class="flex">
|
||||
<span :class="iconClass">
|
||||
<IconifyIconOffline
|
||||
v-tippy="{
|
||||
content: t('buttons:Close')
|
||||
}"
|
||||
class="dark:text-white"
|
||||
width="18px"
|
||||
height="18px"
|
||||
:icon="Close"
|
||||
@click="handleMenu"
|
||||
/>
|
||||
</span>
|
||||
<span :class="[iconClass, 'ml-2']">
|
||||
<IconifyIconOffline
|
||||
v-tippy="{
|
||||
content: t('buttons:Save')
|
||||
}"
|
||||
class="dark:text-white"
|
||||
width="18px"
|
||||
height="18px"
|
||||
:icon="Check"
|
||||
@click="handleSave"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<p class="font-bold truncate">
|
||||
{{ `${curRow?.name ? `${curRow.name}` : ""}` }}-权限列表
|
||||
</p>
|
||||
</div>
|
||||
<el-input
|
||||
v-model="treeSearchValue"
|
||||
placeholder="请输入权限进行搜索"
|
||||
class="mb-1"
|
||||
clearable
|
||||
@input="onQueryChanged"
|
||||
/>
|
||||
<div class="flex flex-wrap">
|
||||
<el-checkbox
|
||||
v-model="isExpandAll"
|
||||
:label="t('buttons:ExpandOrCollapse')"
|
||||
/>
|
||||
<el-checkbox
|
||||
v-model="isSelectAll"
|
||||
:label="t('buttons:CheckAllOrCheckOutAll')"
|
||||
/>
|
||||
<el-checkbox v-model="isLinkage" :label="t('buttons:Linked')" />
|
||||
</div>
|
||||
<el-tree-v2
|
||||
ref="treeRef"
|
||||
show-checkbox
|
||||
:data="treeData"
|
||||
:props="treeProps"
|
||||
:height="treeHeight"
|
||||
:check-strictly="!isLinkage"
|
||||
:filter-method="filterMethod"
|
||||
>
|
||||
<template #default="{ node }">
|
||||
<span>{{ transformI18n(node.label) }}</span>
|
||||
</template>
|
||||
</el-tree-v2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dropdown-menu__item i) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin: 24px 24px 0 !important;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
402
src/views/system/role/utils/hook.tsx
Normal file
402
src/views/system/role/utils/hook.tsx
Normal file
@@ -0,0 +1,402 @@
|
||||
import dayjs from "dayjs";
|
||||
import editForm from "../components/form.vue";
|
||||
import { message } from "@/utils/message";
|
||||
|
||||
import {
|
||||
deleteRoleAPI,
|
||||
getPermissionListAPI,
|
||||
getRoleListAPI,
|
||||
postAddRoleAPI,
|
||||
putUpdateRoleAPI,
|
||||
getRolePermissionsAPI,
|
||||
putUpdateRolePermissionsAPI,
|
||||
getDepartmentListAPI
|
||||
} from "@/api/system";
|
||||
|
||||
import { handleTree } from "@/utils/tree";
|
||||
import { usePublicHooks } from "../../hooks";
|
||||
import { getKeyList } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
import type { PaginationProps } from "@pureadmin/table";
|
||||
import { type Ref, reactive, ref, onMounted, h, watch, toRaw } from "vue";
|
||||
import type {
|
||||
DepartmentInfo,
|
||||
RoleInfo,
|
||||
RolePermissionInfo
|
||||
} from "types/system";
|
||||
|
||||
export const useRole = (treeRef: Ref) => {
|
||||
/**查询表单 */
|
||||
const form = reactive({
|
||||
name: "",
|
||||
code: "",
|
||||
status: "",
|
||||
department_id: "",
|
||||
description: ""
|
||||
});
|
||||
/**
|
||||
* 表单Ref
|
||||
*/
|
||||
const formRef = ref();
|
||||
/**
|
||||
* 数据列表
|
||||
*/
|
||||
const dataList = ref<RoleInfo[]>([]);
|
||||
/**
|
||||
* 加载状态
|
||||
*/
|
||||
const loading = ref(true);
|
||||
/**
|
||||
* 标签样式
|
||||
*/
|
||||
const { tagStyle } = usePublicHooks();
|
||||
/**树形列表id列表 */
|
||||
const treeIds = ref<string[]>([]);
|
||||
/**
|
||||
* 树形列表
|
||||
*/
|
||||
const treeProps = {
|
||||
value: "id",
|
||||
label: "title",
|
||||
children: "children"
|
||||
};
|
||||
/**
|
||||
* 分页参数
|
||||
*/
|
||||
const pagination = reactive<PaginationProps>({
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
background: true
|
||||
});
|
||||
const curRow = ref();
|
||||
/**
|
||||
* 树形列表数据
|
||||
*/
|
||||
const treeData = ref([]);
|
||||
/**是否显示 */
|
||||
const isShow = ref<boolean>(false);
|
||||
/**是否关联 */
|
||||
const isLinkage = ref<boolean>(false);
|
||||
/**查询值 */
|
||||
const treeSearchValue = ref<string>("");
|
||||
/**是否展开 */
|
||||
const isExpandAll = ref<boolean>(false);
|
||||
/**是否全选 */
|
||||
const isSelectAll = ref<boolean>(false);
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "角色名称",
|
||||
prop: "name",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
label: "角色标识",
|
||||
prop: "code",
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
minWidth: 130,
|
||||
cellRenderer: ({ row, props }) => (
|
||||
<el-tag size={props.size} style={tagStyle.value(row.status)}>
|
||||
{row.status === 1 ? "启用" : "停用"}
|
||||
</el-tag>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: "角色描述",
|
||||
prop: "description",
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
label: "所属部门",
|
||||
prop: "department_name",
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
label: "创建时间",
|
||||
minWidth: 180,
|
||||
prop: "create_time",
|
||||
formatter: ({ create_time }) =>
|
||||
dayjs(create_time).format("YYYY-MM-DD HH:mm:ss")
|
||||
},
|
||||
{
|
||||
label: "更新时间",
|
||||
minWidth: 180,
|
||||
prop: "update_time",
|
||||
formatter: ({ update_time }) =>
|
||||
dayjs(update_time).format("YYYY-MM-DD HH:mm:ss")
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
fixed: "right",
|
||||
width: 300,
|
||||
slot: "operation"
|
||||
}
|
||||
];
|
||||
/**
|
||||
* 初次查询
|
||||
*/
|
||||
const onSearch = async () => {
|
||||
loading.value = true;
|
||||
const data = await getRoleListAPI({
|
||||
page: pagination.currentPage,
|
||||
pageSize: pagination.pageSize,
|
||||
...toRaw(form)
|
||||
});
|
||||
dataList.value = data.data.result;
|
||||
pagination.total = data.data.total;
|
||||
pagination.currentPage = data.data.page;
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
}, 500);
|
||||
};
|
||||
const resetForm = formEl => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
onSearch();
|
||||
};
|
||||
/**处理页码变化 */
|
||||
const handleSizeChange = async (val: number) => {
|
||||
const res = await getRoleListAPI({
|
||||
page: pagination.currentPage,
|
||||
pageSize: val
|
||||
});
|
||||
if (res.code === 200) {
|
||||
const data = res.data;
|
||||
dataList.value = data.result;
|
||||
pagination.total = data.total;
|
||||
pagination.currentPage = data.page;
|
||||
}
|
||||
};
|
||||
/**处理每页数量变化 */
|
||||
const handleCurrentChange = async (val: number) => {
|
||||
const res = await getRoleListAPI({
|
||||
page: val,
|
||||
pageSize: pagination.pageSize
|
||||
});
|
||||
if (res.code === 200) {
|
||||
const data = res.data;
|
||||
dataList.value = data.result;
|
||||
pagination.total = data.total;
|
||||
pagination.currentPage = data.page;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async (row: RoleInfo) => {
|
||||
const res = await deleteRoleAPI(row.id);
|
||||
if (res.code === 200) {
|
||||
message(`您删除了角色名称为${row.name}的这条数据`, { type: "success" });
|
||||
onSearch();
|
||||
} else {
|
||||
message(`删除失败!`, { type: "error" });
|
||||
}
|
||||
};
|
||||
const openDialog = (title = "新增", row?: RoleInfo) => {
|
||||
addDialog({
|
||||
title: `${title}角色`,
|
||||
props: {
|
||||
formInline: {
|
||||
id: row?.id ?? "",
|
||||
name: row?.name ?? "",
|
||||
code: row?.code ?? "",
|
||||
description: row?.description ?? "",
|
||||
status: row?.status ?? 1,
|
||||
department_id: row?.department_id ?? ""
|
||||
}
|
||||
},
|
||||
width: "40%",
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () =>
|
||||
h(editForm, {
|
||||
ref: formRef,
|
||||
formInline: {
|
||||
id: row?.id ?? "",
|
||||
name: row?.name ?? "",
|
||||
code: row?.code ?? "",
|
||||
description: row?.description ?? "",
|
||||
status: row?.status ?? 1,
|
||||
department_id: row?.department_id ?? ""
|
||||
}
|
||||
}),
|
||||
beforeSure: (done, { options }) => {
|
||||
const FormRef = formRef.value.getRef();
|
||||
let curData = options.props.formInline as RoleInfo;
|
||||
function chores() {
|
||||
message(`您${title}了角色名称为${curData.name}的这条数据`, {
|
||||
type: "success"
|
||||
});
|
||||
done(); // 关闭弹框
|
||||
onSearch(); // 刷新表格数据
|
||||
}
|
||||
FormRef.validate(async (valid: any) => {
|
||||
if (valid) {
|
||||
console.log("curData", curData);
|
||||
// 表单规则校验通过
|
||||
if (title === "新增") {
|
||||
// 实际开发先调用新增接口,再进行下面操作
|
||||
const res = await postAddRoleAPI(curData);
|
||||
if (res.code === 200) {
|
||||
chores();
|
||||
} else {
|
||||
message(`添加失败!`, {
|
||||
type: "error"
|
||||
});
|
||||
done();
|
||||
}
|
||||
} else {
|
||||
// 实际开发先调用修改接口,再进行下面操作
|
||||
const res = await putUpdateRoleAPI(curData, row.id);
|
||||
if (res.code === 200) {
|
||||
chores();
|
||||
} else {
|
||||
message(`修改失败!`, {
|
||||
type: "error"
|
||||
});
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 角色权限
|
||||
*/
|
||||
const handleMenu = async (row?: RolePermissionInfo) => {
|
||||
const { id } = row;
|
||||
if (id) {
|
||||
curRow.value = row;
|
||||
isShow.value = true;
|
||||
const res = await getRolePermissionsAPI(id);
|
||||
if (res.success) {
|
||||
treeRef.value.setCheckedKeys(
|
||||
getKeyList(res.data.result, "permission_id")
|
||||
);
|
||||
isExpandAll.value = true;
|
||||
} else {
|
||||
treeRef.value.setCheckedKeys([]);
|
||||
isExpandAll.value = true;
|
||||
}
|
||||
} else {
|
||||
curRow.value = null;
|
||||
isShow.value = false;
|
||||
isExpandAll.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 高亮当前权限选中行 */
|
||||
const rowStyle = ({ row: { id } }) => {
|
||||
return {
|
||||
cursor: "pointer",
|
||||
background: id === curRow.value?.id ? "var(--el-fill-color-light)" : ""
|
||||
};
|
||||
};
|
||||
/**保存角色权限 */
|
||||
const handleSave = async () => {
|
||||
const { id, name } = curRow.value;
|
||||
// 根据用户 id 调用实际项目中菜单权限修改接口
|
||||
let permissions = treeRef.value.getCheckedKeys();
|
||||
let halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
|
||||
permissions = [...new Set(permissions.concat(halfCheckedKeys))];
|
||||
const res = await putUpdateRolePermissionsAPI(id, {
|
||||
permission_ids: permissions
|
||||
});
|
||||
if (res.code === 200) {
|
||||
message(`角色名称为${name}的权限修改成功~`, {
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
message(`角色名称为${name}的权限修改失败!`, {
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
/**查询权限变化 */
|
||||
const onQueryChanged = (query: string) => {
|
||||
treeRef.value!.filter(query);
|
||||
};
|
||||
|
||||
/**过滤方法 */
|
||||
const filterMethod = (query: string, node) => {
|
||||
return transformI18n(node.title)!.includes(query);
|
||||
};
|
||||
/**部门列表 */
|
||||
const departments = ref<DepartmentInfo[]>([]);
|
||||
/**获取部门列表 */
|
||||
const getDepartments = async () => {
|
||||
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
|
||||
if (res.code === 200) {
|
||||
departments.value = formatHigherOptions(res.data.result);
|
||||
} else {
|
||||
departments.value = [];
|
||||
}
|
||||
};
|
||||
const formatHigherOptions = treeList => {
|
||||
// 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示
|
||||
if (!treeList || !treeList.length) return;
|
||||
const newTreeList = [];
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
treeList[i].disabled = treeList[i].status === 0 ? true : false;
|
||||
formatHigherOptions(treeList[i].children);
|
||||
newTreeList.push(treeList[i]);
|
||||
}
|
||||
return newTreeList;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
onSearch();
|
||||
const res = await getPermissionListAPI({ page: 1, pageSize: 99999 });
|
||||
const data = res.data.result;
|
||||
treeIds.value = getKeyList(data, "id");
|
||||
treeData.value = handleTree(data, "id", "parent_id");
|
||||
await getDepartments();
|
||||
});
|
||||
watch(isExpandAll, val => {
|
||||
val
|
||||
? treeRef.value.setExpandedKeys(treeIds.value)
|
||||
: treeRef.value.setExpandedKeys([]);
|
||||
});
|
||||
|
||||
watch(isSelectAll, val => {
|
||||
val
|
||||
? treeRef.value.setCheckedKeys(treeIds.value)
|
||||
: treeRef.value.setCheckedKeys([]);
|
||||
});
|
||||
|
||||
return {
|
||||
form,
|
||||
isShow,
|
||||
curRow,
|
||||
loading,
|
||||
columns,
|
||||
dataList,
|
||||
treeData,
|
||||
treeProps,
|
||||
isLinkage,
|
||||
pagination,
|
||||
isExpandAll,
|
||||
isSelectAll,
|
||||
treeSearchValue,
|
||||
departments,
|
||||
rowStyle,
|
||||
onSearch,
|
||||
resetForm,
|
||||
openDialog,
|
||||
handleMenu,
|
||||
handleSave,
|
||||
handleDelete,
|
||||
filterMethod,
|
||||
transformI18n,
|
||||
onQueryChanged,
|
||||
handleSizeChange,
|
||||
handleCurrentChange
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user