系统管理/部门管理角色管理用户管理

This commit is contained in:
Teo
2025-07-11 19:16:57 +08:00
parent 4a0962b117
commit 748464b44a
13 changed files with 243 additions and 81 deletions

View File

@ -11,6 +11,13 @@ export const listDept = (query?: DeptQuery) => {
});
};
export const getDeptList = () => {
return request({
url: '/project/project/listNoDept',
method: 'get'
});
};
/**
* 通过deptIds查询部门
* @param deptIds

View File

@ -5,6 +5,8 @@ export interface DeptQuery extends PageQuery {
deptName?: string;
deptCategory?: string;
status?: number;
isSubset?: string;
isShow?: string;
}
/**
@ -16,6 +18,7 @@ export interface DeptVO extends BaseEntity {
parentId: number | string;
children: DeptVO[];
deptId: number | string;
projectList: any[];
deptName: string;
deptCategory: string;
orderNum: number;
@ -48,10 +51,13 @@ export interface DeptForm {
parentId?: number | string;
children?: DeptForm[];
deptId?: number | string;
projectId?: number | string;
deptName?: string;
deptCategory?: string;
orderNum?: number;
leader?: string;
isSubset?: string;
isShow?: string;
phone?: string;
email?: string;
status?: string;

View File

@ -56,3 +56,14 @@ export function delPost(postId: string | number | (string | number)[]) {
method: 'delete'
});
}
// 获取岗位选择框列表
export function getRoleList(deptId?: number | string): AxiosPromise<any[]> {
return request({
url: '/system/role/listNoPage',
method: 'get',
params: {
deptId
}
});
}

View File

@ -6,7 +6,8 @@ export interface DeptTreeOption {
label: string;
parentId: string;
weight: number;
children?: DeptTreeOption[];
children: DeptTreeOption[];
disabled: boolean;
}
export interface RoleDeptTree {
@ -34,6 +35,7 @@ export interface RoleVO extends BaseEntity {
export interface RoleQuery extends PageQuery {
roleName: string;
roleKey: string;
deptId: string;
status: string;
}
@ -46,7 +48,9 @@ export interface RoleForm {
deptCheckStrictly: boolean;
remark: string;
dataScope?: string;
isSpecial: string;
roleId: string | undefined;
menuIds: Array<string | number>;
deptIds: Array<string | number>;
deptId?: string;
}

View File

@ -202,10 +202,11 @@ export const listUserByDeptId = (deptId: string | number): AxiosPromise<UserVO[]
/**
* 查询部门下拉树结构
*/
export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
export const deptTreeSelect = (data?: { isShow: string }): AxiosPromise<DeptTreeVO[]> => {
return request({
url: '/system/user/deptTree',
method: 'get'
method: 'get',
params: data
});
};

View File

@ -3,6 +3,7 @@ export interface FlowDefinitionQuery extends PageQuery {
flowName?: string;
category: string | number;
isPublish?: number;
projectId: string | number;
}
export interface FlowDefinitionVo {
@ -23,6 +24,7 @@ export interface FlowDefinitionForm {
flowCode: string;
category: string;
formPath: string;
projectId: string;
}
export interface definitionXmlVO {

View File

@ -2,9 +2,11 @@ import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
export default {
routerJump(routerJumpVo: RouterJumpVo, proxy) {
console.log(routerJumpVo.formPath);
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: routerJumpVo.formPath,
path: routerJumpVo.formPath ? '/' + routerJumpVo.formPath : routerJumpVo.formPath,
query: {
id: routerJumpVo.businessId,
type: routerJumpVo.type,

View File

@ -63,7 +63,7 @@
<el-tooltip content="修改" placement="top">
<el-button v-hasPermi="['system:dept:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
</el-tooltip>
<el-tooltip content="新增" placement="top">
<el-tooltip content="新增" placement="top" v-if="scope.row.isSubset != '0'">
<el-button v-hasPermi="['system:dept:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
@ -75,7 +75,7 @@
</el-card>
<el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-body width="600px">
<el-form ref="deptFormRef" :model="form" :rules="rules" label-width="80px">
<el-form ref="deptFormRef" :model="form" :rules="rules" label-width="110px">
<el-row>
<el-col v-if="form.parentId !== 0" :span="24">
<el-form-item label="上级部门" prop="parentId">
@ -128,6 +128,21 @@
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否拥有子级">
<el-radio-group v-model="form.isSubset" @change="handleChangeisSubset">
<el-radio value="1"></el-radio>
<el-radio value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.isSubset == '0'">
<el-form-item label="所属项目" prop="projectId">
<el-select v-model="form.projectId" placeholder="请选择所属项目">
<el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
@ -141,7 +156,7 @@
</template>
<script setup name="Dept" lang="ts">
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from '@/api/system/dept';
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild, getDeptList } from '@/api/system/dept';
import { DeptForm, DeptQuery, DeptVO } from '@/api/system/dept/types';
import { UserVO } from '@/api/system/user/types';
import { listUserByDeptId } from '@/api/system/user';
@ -166,7 +181,7 @@ const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const projectList = ref([]);
const deptTableRef = ref<ElTableInstance>();
const queryFormRef = ref<ElFormInstance>();
const deptFormRef = ref<ElFormInstance>();
@ -180,6 +195,9 @@ const initFormData: DeptForm = {
leader: undefined,
phone: undefined,
email: undefined,
isShow: undefined,
isSubset: undefined,
projectId: undefined,
status: '0'
};
const initData: PageData<DeptForm, DeptQuery> = {
@ -190,7 +208,8 @@ const initData: PageData<DeptForm, DeptQuery> = {
deptName: undefined,
deptCategory: undefined,
status: undefined,
isShow:1
isShow: undefined,
isSubset: undefined
},
rules: {
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
@ -231,6 +250,7 @@ const cancel = () => {
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectList.value = [];
deptFormRef.value?.resetFields();
};
@ -241,9 +261,17 @@ const handleQuery = () => {
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
projectList.value = [];
handleQuery();
};
const handleChangeisSubset = async (value: string) => {
if (value == '0' && (!projectList.value || !projectList.value.length)) {
const res = await getDeptList();
projectList.value = res.data;
}
};
/** 展开/折叠操作 */
const handleToggleExpandAll = () => {
isExpandAll.value = !isExpandAll.value;
@ -279,6 +307,7 @@ const handleUpdate = async (row: DeptVO) => {
getDeptAllUser(row.deptId);
const res = await getDept(row.deptId);
form.value = res.data;
projectList.value = res.data.projectList;
const response = await listDeptExcludeChild(row.deptId);
const data = proxy?.handleTree<DeptOptionsType>(response.data, 'deptId');
if (data) {

View File

@ -35,7 +35,26 @@
</el-card>
</div>
</transition>
<el-row :gutter="20">
<!-- 部门树 -->
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
<el-card shadow="hover">
<template #header>
<el-row :gutter="10">
@ -43,10 +62,14 @@
<el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">修改</el-button>
<el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()">删除</el-button>
<el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
@ -98,9 +121,24 @@
@pagination="getList"
/>
</el-card>
</el-col>
</el-row>
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
<el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px">
<el-form ref="roleFormRef" :model="form" :rules="rules" label-width="110px">
<el-form-item label="所属部门" prop="deptId">
<el-cascader
:options="deptOptions"
v-model="form.deptId"
placeholder="请选择所属部门"
clearable
filterable
:show-all-levels="false"
:props="{ value: 'id', emitPath: false, checkStrictly: true }"
@change=""
>
</el-cascader>
</el-form-item>
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
</el-form-item>
@ -124,7 +162,7 @@
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand(Boolean($event), 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
@ -138,6 +176,9 @@
:props="{ label: 'label', children: 'children' }"
></el-tree>
</el-form-item>
<el-form-item label="是否为特殊角色">
<el-switch v-model="form.isSpecial" active-value="1" inactive-value="0" active-text="是" inactive-text="否"> </el-switch>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item>
@ -165,7 +206,7 @@
</el-select>
</el-form-item>
<el-form-item v-show="form.dataScope === '2'" label="数据权限">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand(Boolean($event), 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree
@ -196,6 +237,8 @@ import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updat
import { roleMenuTreeselect, treeselect as menuTreeselect } from '@/api/system/menu/index';
import { RoleVO, RoleForm, RoleQuery, DeptTreeOption } from '@/api/system/role/types';
import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types';
import api, { uploadCertList } from '@/api/system/user';
import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
const router = useRouter();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -214,8 +257,11 @@ const menuExpand = ref(false);
const menuNodeAll = ref(false);
const deptExpand = ref(true);
const deptNodeAll = ref(false);
const deptOptions = ref<DeptTreeOption[]>([]);
const deptOptions = ref<DeptTreeVO[]>([]);
const enabledDeptOptions = ref<DeptTreeVO[]>([]);
const openDataScope = ref(false);
const deptName = ref('');
/** 数据范围选项*/
const dataScopeOptions = ref([
@ -232,6 +278,7 @@ const roleFormRef = ref<ElFormInstance>();
const dataScopeRef = ref<ElFormInstance>();
const menuRef = ref<ElTreeInstance>();
const deptRef = ref<ElTreeInstance>();
const deptTreeRef = ref<ElTreeInstance>();
const initForm: RoleForm = {
roleId: undefined,
@ -244,6 +291,8 @@ const initForm: RoleForm = {
remark: '',
dataScope: '1',
menuIds: [],
deptId: '',
isSpecial: null,
deptIds: []
};
@ -254,6 +303,7 @@ const data = reactive<PageData<RoleForm, RoleQuery>>({
pageSize: 10,
roleName: '',
roleKey: '',
deptId: '',
status: ''
},
rules: {
@ -269,6 +319,18 @@ const dialog = reactive<DialogOption>({
title: ''
});
/** 通过条件过滤节点 */
const filterNode = (value: string, data: any) => {
if (!value) return true;
return data.label.indexOf(value) !== -1;
};
/** 节点单击事件 */
const handleNodeClick = (data: DeptVO) => {
queryParams.value.deptId = data.id as string;
handleQuery();
};
/**
* 查询角色列表
*/
@ -293,6 +355,9 @@ const handleQuery = () => {
const resetQuery = () => {
dateRange.value = ['', ''];
queryFormRef.value?.resetFields();
queryParams.value.pageNum = 1;
queryParams.value.deptId = undefined;
deptTreeRef.value?.setCurrentKey(undefined);
handleQuery();
};
/**删除按钮操作 */
@ -496,8 +561,28 @@ const cancelDataScope = () => {
form.value = { ...initForm };
openDataScope.value = false;
};
/** 查询部门下拉树结构 */
const getDeptTree = async () => {
const res = await api.deptTreeSelect({ isShow: '1' });
deptOptions.value = res.data;
enabledDeptOptions.value = filterDisabledDept(res.data);
};
/** 过滤禁用的部门 */
const filterDisabledDept = (deptList: DeptTreeVO[]) => {
return deptList.filter((dept) => {
if (dept.disabled) {
return false;
}
if (dept.children && dept.children.length) {
dept.children = filterDisabledDept(dept.children);
}
return true;
});
};
onMounted(() => {
getDeptTree(); // 初始化部门数据
getList();
});
</script>

View File

@ -4,7 +4,7 @@
<!-- 部门树 -->
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称1" prefix-icon="Search" clearable />
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
@ -317,7 +317,7 @@ import { RoleVO } from '@/api/system/role/types';
import { PostVO } from '@/api/system/post/types';
import { globalHeaders } from '@/utils/request';
import { to } from 'await-to-js';
import { optionselect } from '@/api/system/post';
import { getRoleList, optionselect } from '@/api/system/post';
import ShuttleFrame from '../../project/projectRelevancy/component/ShuttleFrame.vue';
const router = useRouter();
@ -469,7 +469,7 @@ const getList = async () => {
/** 查询部门下拉树结构 */
const getDeptTree = async () => {
const res = await api.deptTreeSelect();
const res = await api.deptTreeSelect({ isShow: '1' });
deptOptions.value = res.data;
enabledDeptOptions.value = filterDisabledDept(res.data);
};
@ -623,7 +623,6 @@ const handleAdd = async () => {
dialog.visible = true;
dialog.title = '新增用户';
postOptions.value = data.posts;
roleOptions.value = data.roles;
form.value.password = initPassword.value.toString();
};
@ -638,7 +637,7 @@ const handleUpdate = async (row?: UserForm) => {
postOptions.value = data.posts;
roleOptions.value = data.roles;
form.value.postIds = data.postIds;
form.value.roleIds = data.roleIds;
form.value.roleIds = data.user.roleIds;
form.value.password = '';
};
@ -682,8 +681,11 @@ onMounted(() => {
async function handleDeptChange(value: number | string) {
const response = await optionselect(value);
const roleList = await getRoleList(value);
roleOptions.value = roleList.data;
postOptions.value = response.data;
form.value.postIds = [];
form.value.roleIds = [];
}
const shuttleVisible = ref(false);

View File

@ -59,7 +59,7 @@
<el-tree-select
v-model="form.parentId"
:data="categoryOptions"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' } as any"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
value-key="categoryId"
placeholder="请选择上级分类"
check-strictly

View File

@ -529,4 +529,17 @@ const handleCopyDef = async (row: FlowDefinitionVo) => {
const handleExportDef = () => {
proxy?.download(`/workflow/definition/exportDef/${ids.value[0]}`, {}, `${flowCodeList.value[0]}.json`);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
</script>

View File

@ -10,7 +10,7 @@
class="mt-2"
node-key="id"
:data="categoryOptions"
:props="{ label: 'label', children: 'children' } as any"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current