123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- <template>
- <div class="table-box">
- <ProTable ref="proTable" :columns="columns" row-key="roleId" :request-api="listRoleApi">
- <!-- 表格 header 按钮 -->
- <template #tableHeader="scope">
- <el-button type="primary" v-auth="['system:role:add']" :icon="CirclePlus" @click="openDialog(1, '角色信息新增')"> 新增 </el-button>
- <el-button type="primary" v-auth="['system:role:import']" :icon="Upload" plain @click="batchAdd"> 导入 </el-button>
- <el-button type="primary" v-auth="['system:role:export']" :icon="Download" plain @click="downloadFile"> 导出 </el-button>
- <el-button
- type="danger"
- v-auth="['system:user:remove']"
- :icon="Delete"
- plain
- :disabled="!scope.isSelected"
- @click="batchDelete(scope.selectedListIds)"
- >
- 批量删除
- </el-button>
- </template>
- <!-- 表格操作 -->
- <template #operation="scope">
- <el-button
- type="primary"
- v-if="scope.row.roleId !== 1"
- link
- :icon="EditPen"
- v-auth="['system:role:edit']"
- @click="openDialog(2, '角色编辑', scope.row)"
- >
- 编辑
- </el-button>
- <el-button type="primary" v-if="scope.row.roleId !== 1" link :icon="Delete" v-auth="['system:role:remove']" @click="deleteRole(scope.row)">
- 删除
- </el-button>
- <el-button
- type="primary"
- v-if="scope.row.roleId !== 1"
- link
- :icon="CircleCheck"
- v-auth="['system:role:edit']"
- @click="openDataDialog(3, '数据权限', scope.row)"
- >
- 数据权限
- </el-button>
- <el-button type="primary" v-if="scope.row.roleId !== 1" link :icon="User" v-auth="['system:role:edit']" @click="handleAuthUser(scope.row)">
- 分配用户
- </el-button>
- </template>
- </ProTable>
- <FormDialog ref="formDialogRef">
- <template #default="{ parameter }">
- <ProFrom ref="proFormRef" :items-options="itemsOptions" :disabled="!parameter.isEdit" :form-options="_options" :model="parameter.model">
- <template #menuCheckStrictly="{ formModel }">
- <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
- <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
- <el-checkbox v-model="formModel.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')"> 父子联动 </el-checkbox>
- <el-tree
- class="tree-border"
- :data="menuOptions"
- show-checkbox
- ref="menuRef"
- node-key="id"
- :check-strictly="!formModel.menuCheckStrictly"
- empty-text="加载中,请稍后"
- :props="{ label: 'label', children: 'children' }"
- />
- </template>
- </ProFrom>
- </template>
- <template #footer="{ parameter }">
- <el-button type="primary" :loading="butLoading" @click="handleSubmit(proFormRef, parameter, formDialogRef, '1')">确认</el-button>
- <el-button @click="handleCancel(formDialogRef)">取消</el-button>
- </template>
- </FormDialog>
- <FormDialog ref="formDataRef">
- <template #default="{ parameter }">
- <ProFrom ref="proFormDateRef" :items-options="itemsOptions" :form-options="_options" :model="parameter.model">
- <template #deptCheckStrictly="{ formModel }">
- <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
- <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
- <el-checkbox v-model="formModel.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')"> 父子联动 </el-checkbox>
- <el-tree
- class="tree-border"
- :data="deptOptions"
- show-checkbox
- ref="deptRef"
- default-expand-all
- node-key="id"
- :check-strictly="!formModel.deptCheckStrictly"
- empty-text="加载中,请稍后"
- :props="{ label: 'label', children: 'children' }"
- />
- </template>
- </ProFrom>
- </template>
- <template #footer="{ parameter }">
- <el-button type="primary" :loading="butLoading" @click="handleSubmit(proFormDateRef, parameter, formDataRef)">确认</el-button>
- <el-button @click="handleCancel(formDataRef)">取消</el-button>
- </template>
- </FormDialog>
- <ImportExcel ref="dialogRef" />
- </div>
- </template>
- <script setup lang="tsx" name="RoleManage">
- import { ref, reactive, nextTick } from 'vue'
- import { useHandleData } from '@/hooks/useHandleData'
- import { useDownload } from '@/hooks/useDownload'
- import { ElMessageBox, ElMessage } from 'element-plus'
- import ProTable from '@/components/ProTable/index.vue'
- import ImportExcel from '@/components/ImportExcel/index.vue'
- import FormDialog from '@/components/CustomDialog/index.vue'
- import ProFrom from '@/components/ProForm/index.vue'
- import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
- import { Delete, EditPen, Download, Upload, CircleCheck, User, CirclePlus } from '@element-plus/icons-vue'
- import {
- listRoleApi,
- delRoleApi,
- addRoleApi,
- updateRoleApi,
- importTemplateApi,
- importDataApi,
- exportApi,
- changeStatusApi,
- deptTreeSelectApi,
- dataScopeApi,
- roleMenuTreeSelectApi
- } from '@/api/modules/system/role'
- import { treeSelectApi } from '@/api/modules/system/menu'
- import { getDictsApi } from '@/api/modules/system/dictData'
- import { useRouter } from 'vue-router'
- const router = useRouter()
- // 菜单列表
- const menuOptions = ref<any>()
- const menuExpand = ref(false)
- const menuNodeAll = ref(false)
- const deptExpand = ref(true)
- const deptNodeAll = ref(false)
- const menuRef = ref<any>(null)
- const proFormRef = ref<any>(null)
- const proFormDateRef = ref<any>(null)
- const deptOptions = ref<any[]>([])
- const deptRef = ref<any>(null)
- const butLoading = ref(false)
- // 数据范围选项
- const dataScopeOptions = ref([
- { value: '1', label: '全部数据权限' },
- { value: '2', label: '自定数据权限' },
- { value: '3', label: '本部门数据权限' },
- { value: '4', label: '本部门及以下数据权限' },
- { value: '5', label: '仅本人数据权限' }
- ])
- // 获取菜单
- const getMenuTreeSelect = () => {
- treeSelectApi().then((response: any) => {
- if (response.code === 200) {
- menuOptions.value = response.data
- }
- })
- }
- getMenuTreeSelect()
- // 根据角色ID查询菜单树结构
- const getRoleMenuTreeSelect = (roleId: any) => {
- return roleMenuTreeSelectApi(roleId).then((res: any) => {
- menuOptions.value = res.menus
- return res
- })
- }
- // 根据角色ID查询部门树结构
- const getDeptTree = (roleId: string) => {
- return deptTreeSelectApi(roleId).then((res: any) => {
- if (res.code === 200) {
- deptOptions.value = res.depts
- return res
- }
- })
- }
- // ProTable 实例
- const proTable = ref<ProTableInstance>()
- // 删除角色信息信息
- const deleteRole = async (params: any) => {
- await useHandleData(delRoleApi, params.roleId, `删除【${params.roleName}】角色信息`)
- proTable.value?.getTableList()
- }
- // 批量删除角色信息信息
- const batchDelete = async (ids: string[]) => {
- await useHandleData(delRoleApi, ids, '删除所选角色信息信息')
- proTable.value?.clearSelection()
- proTable.value?.getTableList()
- }
- // 导出角色信息列表
- const downloadFile = async () => {
- ElMessageBox.confirm('确认导出角色信息数据?', '温馨提示', { type: 'warning' }).then(() =>
- useDownload(exportApi, '角色信息列表', proTable.value?.searchParam)
- )
- }
- // 批量添加角色信息
- const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
- const batchAdd = () => {
- const params = {
- title: '角色信息',
- tempApi: importTemplateApi,
- importApi: importDataApi,
- getTableList: proTable.value?.getTableList
- }
- dialogRef.value?.acceptParams(params)
- }
- const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
- // 打开弹框的功能
- const openDialog = async (type: number, title: string, row?: any) => {
- reset()
- // 重置表单
- setItemsOptions()
- const params = {
- title,
- width: 720,
- isEdit: true,
- itemsOptions: itemsOptions,
- model: type == 1 ? {} : row,
- api: type == 1 ? addRoleApi : updateRoleApi,
- getTableList: proTable.value?.getTableList
- }
- formDialogRef.value?.openDialog(params)
- if (row?.roleId) {
- getRoleMenuTreeSelect(row?.roleId).then(res => {
- let checkedKeys = res.checkedKeys
- checkedKeys.forEach((v: any) => {
- nextTick(() => {
- menuRef.value.setChecked(v, true, false)
- })
- })
- })
- }
- }
- const formDataRef = ref<InstanceType<typeof FormDialog> | null>(null)
- // 打开弹框的功能
- const openDataDialog = async (type: number, title: string, row?: any) => {
- reset()
- // 重置表单
- setPerDataItemsOptions()
- const params = {
- title,
- width: 720,
- isEdit: true,
- itemsOptions: itemsOptions,
- model: type == 1 ? {} : row,
- api: dataScopeApi,
- getTableList: proTable.value?.getTableList
- }
- formDataRef.value?.openDialog(params)
- if (row?.roleId) {
- nextTick(() => {
- getDeptTree(row?.roleId).then(res => {
- nextTick(() => {
- if (deptRef.value) {
- deptRef.value.setCheckedKeys(res.checkedKeys)
- }
- })
- })
- })
- }
- }
- // 树权限(展开/折叠
- const handleCheckedTreeExpand = (value: any, type: string) => {
- if (type === 'menu') {
- const nodes = menuRef.value.store._getAllNodes()
- nodes.forEach(item => {
- item.expanded = value
- })
- } else if (type === 'dept') {
- const nodes = deptRef.value.store._getAllNodes()
- nodes.forEach(item => {
- item.expanded = value
- })
- }
- }
- // 树权限(全选/全不选)
- const handleCheckedTreeNodeAll = (value: any, type: string) => {
- if (type === 'menu') {
- menuRef.value.setCheckedNodes(value ? menuOptions.value : [])
- } else if (type === 'dept') {
- deptRef.value.setCheckedNodes(value ? deptOptions.value : [])
- }
- }
- // 树权限(父子联动)
- const handleCheckedTreeConnect = (value: any, type: string) => {
- if (type === 'menu') {
- proFormRef.value.formModel.menuCheckStrictly = value ? true : false
- } else if (type === 'dept') {
- proFormDateRef.value.formModel.deptCheckStrictly = value ? true : false
- }
- }
- // 分配用户
- function handleAuthUser(row: any) {
- router.push('/system/role-auth/user/' + row.roleId)
- }
- // 切换绝俗状态
- const changeStatus = async (row: any) => {
- await useHandleData(changeStatusApi, { roleId: row.roleId, status: row.status == '1' ? 0 : 1 }, `切换【${row.roleName}】角色状态`)
- proTable.value?.getTableList()
- }
- // 所有部门节点数据
- const getDeptAllCheckedKeys = () => {
- // 目前被选中的部门节点
- let checkedKeys = deptRef.value.getCheckedKeys()
- // 半选中的部门节点
- let halfCheckedKeys = deptRef.value.getHalfCheckedKeys()
- checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
- return checkedKeys
- }
- // 所有菜单节点数据
- const getMenuAllCheckedKeys = () => {
- // 目前被选中的菜单节点
- let checkedKeys = menuRef.value.getCheckedKeys()
- // 半选中的菜单节点
- let halfCheckedKeys = menuRef.value.getHalfCheckedKeys()
- checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
- return checkedKeys
- }
- // 提交
- const handleSubmit = (proFormRef: any, parameter: any, closeRefVal: any, type?: string) => {
- const formEl = proFormRef.proFormRef
- butLoading.value = true
- if (!formEl) return
- formEl.validate(valid => {
- if (valid) {
- if (type === '1') {
- parameter.model.menuIds = getMenuAllCheckedKeys()
- } else {
- parameter.model.deptIds = getDeptAllCheckedKeys()
- }
- parameter.api!(parameter.model).then(res => {
- if (res.code == 200) {
- proFormRef?.resetForm(formEl)
- ElMessage.success('操作成功')
- handleCancel(closeRefVal)
- proTable.value?.getTableList()
- } else {
- console.log('message', res.message)
- }
- })
- butLoading.value = false
- }
- butLoading.value = false
- })
- }
- // 取消按钮,重置表单,关闭弹框
- const handleCancel = (closeRefVal: any) => {
- closeRefVal.handleCancel()
- }
- const reset = () => {
- if (menuRef.value) {
- menuRef.value.setCheckedKeys([])
- }
- menuExpand.value = false
- menuNodeAll.value = false
- deptExpand.value = true
- deptNodeAll.value = false
- }
- // 表格配置项
- const columns = reactive<ColumnProps<any>[]>([
- { type: 'selection', fixed: 'left', width: 70 },
- { prop: 'roleId', label: '角色编号' },
- {
- prop: 'roleName',
- label: '角色名称'
- },
- {
- prop: 'roleKey',
- label: '角色权限字符串'
- },
- {
- prop: 'roleSort',
- label: '显示顺序'
- },
- {
- prop: 'status',
- label: '角色状态',
- enum: () => getDictsApi('sys_normal_disable'),
- search: { el: 'tree-select' },
- fieldNames: { label: 'dictLabel', value: 'dictValue' },
- render: scope => {
- return (
- <el-switch
- model-value={scope.row.status}
- active-text={scope.row.status === '1' ? '禁用' : '启用'}
- active-value={'0'}
- inactive-value={'1'}
- onClick={() => changeStatus(scope.row)}
- />
- )
- }
- },
- {
- prop: 'createTime',
- label: '创建时间',
- search: {
- el: 'date-picker',
- props: { type: 'datetimerange', valueFormat: 'YYYY-MM-DD HH:mm:ss' }
- }
- },
- { prop: 'operation', label: '操作', width: 350, fixed: 'right' }
- ])
- let _options = ref<ProForm.FormOptions>({
- labelWidth: 120,
- hasFooter: false,
- disabled: false
- })
- // 表单配置项
- let itemsOptions: ProForm.ItemsOptions[] = []
- const setItemsOptions = () => {
- itemsOptions = [
- {
- label: '角色名称',
- prop: 'roleName',
- rules: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
- compOptions: {
- placeholder: '请输入角色名称'
- }
- },
- {
- label: '角色权限',
- prop: 'roleKey',
- rules: [{ required: true, message: '角色权限字符串不能为空', trigger: 'blur' }],
- tooltip: '@PreAuthorize("@ss.hasPermi(`admin`)")',
- compOptions: {
- placeholder: '请输入角色权限字符串'
- }
- },
- {
- label: '显示顺序',
- prop: 'roleSort',
- rules: [{ required: true, message: '显示顺序不能为空', trigger: 'blur' }],
- compOptions: {
- placeholder: '请输入显示顺序'
- }
- },
- {
- label: '角色状态',
- prop: 'status',
- rules: [{ required: true, message: '角色状态不能为空', trigger: 'blur' }],
- compOptions: {
- placeholder: '请输入角色状态'
- }
- },
- {
- label: '菜单权限',
- prop: 'menuCheckStrictly',
- hideLabelSuffix: true,
- compOptions: {
- elTagName: 'slot',
- placeholder: '请输入菜单树选择项是否关联显示'
- }
- },
- {
- label: '备注',
- prop: 'remark',
- compOptions: {
- type: 'textarea',
- placeholder: '请输入内容'
- }
- }
- ]
- }
- const setPerDataItemsOptions = () => {
- itemsOptions = [
- {
- label: '角色名称',
- prop: 'roleName',
- compOptions: {
- disabled: true
- }
- },
- {
- label: '权限字符',
- prop: 'roleKey',
- compOptions: {
- disabled: true
- }
- },
- {
- label: '权限范围',
- prop: 'dataScope',
- compOptions: {
- elTagName: 'select',
- enum: dataScopeOptions.value,
- onChange: (val: string) => {
- if (val !== '2') {
- deptRef.value.setCheckedKeys([])
- }
- }
- }
- },
- {
- label: '数据权限',
- prop: 'deptCheckStrictly',
- hideLabelSuffix: true,
- compOptions: {
- elTagName: 'slot'
- }
- }
- ]
- }
- </script>
- <style scoped lang="scss">
- @import './index.scss';
- </style>
|