feat: 员工角色

fix/0524_ch
向文可 2 years ago
parent 716eb4bb63
commit 403adddce4

@ -26,7 +26,7 @@ export function getUserInfo() {
// 获取权限列表
export function getPermission(params) {
return request({
url: '/u-admin/uc/ucPermission/listUserMenu',
url: '/uc/menu',
method: 'get',
params,
});

@ -12,6 +12,19 @@ export const detail = (id) => {
method: 'get',
});
};
export const searchPermission = (id) => {
return request({
url: '/uc/employee/role/' + id,
method: 'get',
});
};
export const savePermission = (id, data) => {
return request({
url: '/uc/employee/role/' + id,
method: 'put',
data,
});
};
export const create = (data) => {
return request({
url: '/uc/employee',

@ -1,5 +1,6 @@
import * as deptAPI from '@/api/permission/dept.js';
import * as api from '@/api/permission/employee.js';
import * as systemAPI from '@/api/permission/system.js';
import { ElMessage, ElMessageBox } from '@/plugins/element-plus';
const state = () => ({
code: 'EmployeeManagement',
@ -8,6 +9,7 @@ const state = () => ({
total: 0,
opts: {
init: false,
system: [],
dept: [],
},
});
@ -36,6 +38,7 @@ const actions = {
...state.opts,
init: true,
dept: await deptAPI.search({ hiddenDisable: true }),
system: await systemAPI.search(),
});
},
detail: async (context, id) => {
@ -45,12 +48,27 @@ const actions = {
}
return res;
},
permission: async (context, id) => {
let res = await api.searchPermission(id);
if (!res) {
ElMessage.error('加载权限列表失败');
}
return res;
},
save: async ({ dispatch }, data) => {
let save = data.id ? api.update : api.create;
let res = await save(data);
if (res) {
ElMessage.success('保存成功');
dispatch('search');
if (!data.id) {
data.id = res;
}
res = await api.savePermission(data.id, { roleIds: data.roleIds });
if (res) {
ElMessage.success('保存成功');
dispatch('search');
} else {
ElMessage.error('保存角色失败');
}
} else {
ElMessage.error('保存失败');
}

@ -43,6 +43,49 @@
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" />
</el-form-item>
<el-form-item label="账号角色" prop="roleIds">
<div class="role-list">
<div v-for="(item, index) in opts.system" :key="index" class="system">
<h3 class="system-header">
{{ item.systemName }}
</h3>
<div class="flex">
<el-tag
v-for="(role, j) in handleSystemRole(item.id)"
:key="index + '' + j"
closable
size="large"
@close="handleDelRole(role.id)"
>
{{ role.roleName }}
</el-tag>
<el-button @click="handleAddRole(item.id)"></el-button>
</div>
</div>
</div>
<el-dialog v-model="roleVisible" title="添加角色">
<el-form v-loading="loading2">
<el-form-item>
<el-select
v-model="checkedRole"
:config="{
label: 'roleName',
value: 'id',
disabled: (item) =>
handleSystemRole(currentSystemId).findIndex((role) => role.id === item.id) !==
-1,
}"
multiple
:opts="systemRoleList"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="roleVisible = false">取消</el-button>
<el-button :loading="loading2" type="primary" @click="handleSaveRole"></el-button>
</template>
</el-dialog>
</el-form-item>
</el-form>
<div class="form-footer">
<el-button @click="handleCancel"></el-button>
@ -71,13 +114,17 @@
phone: '',
remark: '',
userName: '',
roleIds: [],
});
const permissionList = reactive([]);
const handleSystemRole = (systemId) => permissionList.filter((item) => item.systemId === systemId);
const rules = reactive({
departmentId: [{ required: unref(computed(() => !form.id)), message: '所在组织不能为空' }],
userName: [{ required: true, message: '用户名不能为空' }],
phone: [{ required: true, message: '手机号码不能为空' }],
email: [{ required: true, message: '邮箱地址不能为空' }],
employeeName: [{ required: true, message: '员工姓名不能为空' }],
roleIds: [{ required: true, message: '账号角色不能为空' }],
});
const opts = computed(() => store.state.employee.opts);
if (!unref(opts).init) {
@ -91,6 +138,9 @@
let res = await store.dispatch('employee/detail', id);
Object.assign(form, res);
}
permissionList.splice(0);
permissionList.push(...(await store.dispatch('employee/permission', id)));
form.roleIds = permissionList.map((item) => item.id);
}
};
onActivated(handleLoad);
@ -125,6 +175,50 @@
const handleClose = () => {
router.push({ name: 'EmployeeManagement' });
};
const loading2 = ref(false);
const roleVisible = ref(false);
const currentSystemId = ref(null);
const checkedRole = ref([]);
const systemRoleList = ref([]);
const handleAddRole = async (id) => {
loading2.value = true;
currentSystemId.value = id;
checkedRole.value = [];
roleVisible.value = true;
systemRoleList.value = await store.dispatch('deptRole/role', id);
loading2.value = false;
};
const handleDelRole = (id) => {
form.roleIds.splice(form.roleIds.findIndex(id), 1);
permissionList.splice(
permissionList.findIndex((item) => item.id === id),
1
);
};
const handleSaveRole = async () => {
form.roleIds.push(...unref(checkedRole));
permissionList.push(...unref(systemRoleList).filter((item) => unref(checkedRole).indexOf(item.id) !== -1));
roleVisible.value = false;
};
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.role-list {
.system {
& + .system {
margin-top: @layout-space;
}
.system-header {
margin-bottom: @layout-space;
}
.flex {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.el-tag {
margin: @layout-space-small @layout-space @layout-space-small 0;
}
}
}
</style>

@ -23,7 +23,7 @@
</div>
</div>
</template>
<div v-loading="loading" class="card-body">
<el-scrollbar v-loading="loading" class="card-body">
<el-tree
:data="list"
default-expand-all
@ -56,7 +56,7 @@
</div>
</template>
</el-tree>
</div>
</el-scrollbar>
</el-card>
<el-card class="feature">
<template #header>
@ -67,7 +67,7 @@
</div>
</div>
</template>
<div v-loading="loading2" class="card-body">
<el-scrollbar v-loading="loading2" class="card-body">
<el-tree
:data="featureList"
default-expand-all
@ -95,7 +95,7 @@
</div>
</template>
</el-tree>
</div>
</el-scrollbar>
</el-card>
<el-card v-show="menuState.formVisible" class="form">
<template #header>
@ -104,59 +104,61 @@
<div class="action"></div>
</div>
</template>
<el-form
ref="refsMenuForm"
v-loading="menuState.submitting"
label-width="100px"
:model="menuState.form"
:rules="menuState.rules"
>
<el-form-item label="所属系统" prop="systemId">
<el-select
v-model="menuState.form.systemId"
:config="{ label: 'systemName', value: 'id' }"
:opts="opts.system"
/>
</el-form-item>
<el-form-item label="上级菜单" prop="parentId">
<el-cascader
v-model="menuState.form.parentId"
:options="list"
:props="{
label: 'title',
value: 'id',
children: 'menuChild',
checkStrictly: true,
expandTrigger: 'hover',
emitPath: false,
}"
/>
</el-form-item>
<el-form-item label="菜单类型" prop="type">
<el-radio-group v-model="menuState.form.type" :opts="opts.type" />
</el-form-item>
<el-form-item label="菜单名称" prop="title">
<el-input v-model="menuState.form.title" />
</el-form-item>
<el-form-item label="权限标识" prop="permission">
<el-input v-model="menuState.form.permission" />
</el-form-item>
<el-form-item label="路由路径" prop="path">
<el-input v-model="menuState.form.path" />
</el-form-item>
<el-form-item label="前端页面" prop="page">
<el-input v-model="menuState.form.page" />
</el-form-item>
<el-form-item label="菜单图标" prop="icon">
<el-input v-model="menuState.form.icon" />
</el-form-item>
<el-form-item label="菜单排序" prop="sort">
<el-input-number v-model="menuState.form.sort" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSaveMenu"></el-button>
</el-form-item>
</el-form>
<el-scrollbar v-loading="loading2" class="card-body">
<el-form
ref="refsMenuForm"
v-loading="menuState.submitting"
label-width="100px"
:model="menuState.form"
:rules="menuState.rules"
>
<el-form-item label="所属系统" prop="systemId">
<el-select
v-model="menuState.form.systemId"
:config="{ label: 'systemName', value: 'id' }"
:opts="opts.system"
/>
</el-form-item>
<el-form-item label="上级菜单" prop="parentId">
<el-cascader
v-model="menuState.form.parentId"
:options="list"
:props="{
label: 'title',
value: 'id',
children: 'menuChild',
checkStrictly: true,
expandTrigger: 'hover',
emitPath: false,
}"
/>
</el-form-item>
<el-form-item label="菜单类型" prop="type">
<el-radio-group v-model="menuState.form.type" :opts="opts.type" />
</el-form-item>
<el-form-item label="菜单名称" prop="title">
<el-input v-model="menuState.form.title" />
</el-form-item>
<el-form-item label="权限标识" prop="permission">
<el-input v-model="menuState.form.permission" />
</el-form-item>
<el-form-item label="路由路径" prop="path">
<el-input v-model="menuState.form.path" />
</el-form-item>
<el-form-item label="前端页面" prop="page">
<el-input v-model="menuState.form.page" />
</el-form-item>
<el-form-item label="菜单图标" prop="icon">
<el-input v-model="menuState.form.icon" />
</el-form-item>
<el-form-item label="菜单排序" prop="sort">
<el-input-number v-model="menuState.form.sort" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSaveMenu"></el-button>
</el-form-item>
</el-form>
</el-scrollbar>
</el-card>
<el-card v-show="featureState.formVisible" class="form">
<template #header>
@ -165,51 +167,53 @@
<div class="action"></div>
</div>
</template>
<el-form
ref="refsFeatureForm"
v-loading="featureState.submitting"
label-width="100px"
:model="featureState.form"
:rules="featureState.rules"
>
<el-form-item label="所属系统" prop="systemId">
<el-select
v-model="featureState.form.systemId"
:config="{ label: 'systemName', value: 'id' }"
:opts="opts.system"
@change="state.condition.systemId = $event"
/>
</el-form-item>
<el-form-item label="所属菜单" prop="menuId">
<el-cascader
v-model="featureState.form.menuId"
:options="list"
:props="{
label: 'title',
value: 'id',
children: 'menuChild',
checkStrictly: true,
expandTrigger: 'hover',
emitPath: false,
}"
/>
</el-form-item>
<el-form-item label="功能名称" prop="name">
<el-input v-model="featureState.form.name" />
</el-form-item>
<el-form-item label="请求方式" prop="method">
<el-select v-model="featureState.form.method" :opts="opts.method" />
</el-form-item>
<el-form-item label="接口路径" prop="uri">
<el-input v-model="featureState.form.uri" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-switch v-model="featureState.form.isEnable" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSaveFeature"></el-button>
</el-form-item>
</el-form>
<el-scrollbar v-loading="loading2" class="card-body">
<el-form
ref="refsFeatureForm"
v-loading="featureState.submitting"
label-width="100px"
:model="featureState.form"
:rules="featureState.rules"
>
<el-form-item label="所属系统" prop="systemId">
<el-select
v-model="featureState.form.systemId"
:config="{ label: 'systemName', value: 'id' }"
:opts="opts.system"
@change="state.condition.systemId = $event"
/>
</el-form-item>
<el-form-item label="所属菜单" prop="menuId">
<el-cascader
v-model="featureState.form.menuId"
:options="list"
:props="{
label: 'title',
value: 'id',
children: 'menuChild',
checkStrictly: true,
expandTrigger: 'hover',
emitPath: false,
}"
/>
</el-form-item>
<el-form-item label="功能名称" prop="name">
<el-input v-model="featureState.form.name" />
</el-form-item>
<el-form-item label="请求方式" prop="method">
<el-select v-model="featureState.form.method" :opts="opts.method" />
</el-form-item>
<el-form-item label="接口路径" prop="uri">
<el-input v-model="featureState.form.uri" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-switch v-model="featureState.form.isEnable" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSaveFeature"></el-button>
</el-form-item>
</el-form>
</el-scrollbar>
</el-card>
</div>
</div>
@ -396,6 +400,7 @@
flex-direction: column;
.body {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: row;
> * {
@ -404,6 +409,17 @@
margin-left: @layout-space;
}
}
.el-card {
display: flex;
flex-direction: column;
:deep(.el-card__body) {
flex: 1;
overflow: hidden;
.card-body {
padding-right: @layout-space;
}
}
}
:deep(.el-tree) {
.flex {
width: 100%;

@ -203,7 +203,7 @@
const menuList = ref([]);
const permissionList = ref([]);
const formState = reactive({
currentTab: '1',
currentTab: '0',
formVisible: false,
submitting: false,
form: {
@ -230,31 +230,6 @@
departmentList: [{ required: true, trigger: 'change', message: '绑定组织不能为空' }],
},
});
watch(
() => formState.currentTab,
async (value) => {
let res = await store.dispatch('role/detail', formState.form.id);
res.menuIds = [];
res.permissionIds = [];
const deep = (arr) => {
(arr || []).forEach((item) => {
if (item.isHave) {
res.menuIds.push(item.id);
}
res.permissionIds.push(
...(item.permissionChild || []).filter((item) => item.isHave).map((item) => item.id)
);
deep(item.menuChild);
});
};
deep(res.roleMenuTree);
delete res.roleMenuTree;
Object.assign(formState.form, res);
if (value === '2') {
menuList.value = await store.dispatch('role/loadMenu', formState.form.systemId);
}
}
);
const refsTree = ref(null);
const checkAll = ref(false);
watch(checkAll, (value) => {
@ -301,8 +276,34 @@
}
});
};
const handleDetail = async () => {
formState.submitting = true;
if (formState.currentTab === '1') {
let res = await store.dispatch('role/detail', formState.form.id);
res.role.menuIds = [];
res.role.permissionIds = [];
const deep = (arr) => {
(arr || []).forEach((item) => {
if (item.isHave) {
res.role.menuIds.push(item.id);
}
res.role.permissionIds.push(
...(item.permissionChild || []).filter((item) => item.isHave).map((item) => item.id)
);
deep(item.menuChild);
});
};
deep(res.roleMenuTree);
Object.assign(formState.form, res.role);
} else if (formState.currentTab === '2') {
menuList.value = await store.dispatch('role/loadMenu', formState.form.systemId);
}
formState.submitting = false;
};
watch(() => formState.currentTab, handleDetail);
const handleCreate = (row) => {
formState.formVisible = true;
formState.currentTab = '1';
Object.assign(
formState.form,
_.cloneDeep(
@ -330,7 +331,7 @@
);
if (formState.currentTab === '3') {
formState.formVisible = false;
formState.currentTab = '1';
formState.currentTab = '0';
handleSearch();
} else {
let data = _.cloneDeep(formState.form);
@ -342,7 +343,7 @@
: 'role/updateDept',
data
);
if (res && formState.currentTab === '1') {
if (res && formState.currentTab === '1' && !formState.form.id) {
formState.form.id = res.id;
}
formState.currentTab = +formState.currentTab + 1 + '';

Loading…
Cancel
Save